Suggestions please?

I have an email message in a MailMessage object. and I want to be able to represent it as an XPS file. This particular email has a small body (15 lines of text or so) and several much larger pdf attachments.

In order to be create the XPS file you suggested I follow these steps:

  1. Construct a MemoryStream object
  2. Save the MailMessage content in MHTML format to the MemoryStream
  3. Use the MemoryStream to construct an Aspose.Words.Document
  4. Use the Document Save method to create the XPS file.

A problem I have is that MemoryStream intermittently throws an exception when it tries to resize its internal buffer. Here's a stack dump. My SaveAsXps method has just made a call to save the MailMessage as MHTML format:

System.OutOfMemoryException: Exception of type 'System.OutOfMemoryException' was thrown.
at System.IO.MemoryStream.set_Capacity(Int32 value)
at System.IO.MemoryStream.EnsureCapacity(Int32 value)
at System.IO.MemoryStream.Write(Byte[] buffer, Int32 offset, Int32 count)
at  .Write(Byte[]  , Int32 , Int32  )
at  .Write(Byte[]  , Int32 , Int32  )
at System.IO.StreamWriter.Flush(Boolean flushStream, Boolean flushEncoder)
at System.IO.StreamWriter.Write(String value)
at   .Write(Byte[]  , Int32 , Int32  )
at   .     (     , Boolean )
at   .     (     , Boolean )
at   .      (     )
at Aspose.Email.Mail.MailMessage.(     )
at Aspose.Email.Mail.MailMessage.Save(Stream stream, SaveOptions options)
at Aspose.Email.Mail.MailMessage.Save(Stream stream)
at Aspose.Email.Mail.MailMessage.Save(Stream stream, SaveOptions options)
at Kutana.Kappris.Manipulation.MsgHandler.SaveAsXps(CT_FileNode parent)
at Kutana.Kappris.Manipulation.PrintFu.SaveAsXps(CT_FileNode parent)

I don't have a way of reproducing this error at will - it is intermittent and seems to depend somewhat on system load and allocations made by other code in my app. It is not dependent on msg content.

Q1 - Have you seen this exception? How can I avoid it?

Q2 - the saved MemoryStream contains everything that's in the MailMessage - all the attachments, and all the message headers and content. But in order to create an XPS file of the email body text, the MemoryStream doesn't need all the attachments - it only really needs the inline attachments. Is there any way of filling a MemoryStream with MHTML content so that the non-inline attachments are omitted? Then the MemoryStream would not need to have such a large internal buffer and wouldn't need to be resized so often. In particular, the msg I am trying to save as xps is about 4MB because of all its attachments, but its body content is only about 10KB - a big difference!

Hi Brian,

Thank you for writing to Aspose Support team.

For the exception you are facing while saving the message to memory stream, we’ll be in need of your sample message file to report the issue to our Product team for further investigation.

Q1. The exception you have faced seems to be specific to your message file. However, you may try converting it to TIFF using Aspose.Email API using the API’s printing features.

Q2. Please try using the MhtFormatOptions to avoid writing the Outline attachments to the mhtml as shown in the following code sample. Please try it at your end and let us know your feedback.

Sample Code:

<!–[if gte mso 9]>
<w:WordDocument>
<w:View>Normal</w:View>
<w:Zoom>0</w:Zoom>
<w:TrackMoves/>
<w:TrackFormatting/>
<w:PunctuationKerning/>
<w:ValidateAgainstSchemas/>
<w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid>
<w:IgnoreMixedContent>false</w:IgnoreMixedContent>
<w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText>
<w:DoNotPromoteQF/>
<w:LidThemeOther>EN-US</w:LidThemeOther>
<w:LidThemeAsian>X-NONE</w:LidThemeAsian>
<w:LidThemeComplexScript>X-NONE</w:LidThemeComplexScript>
<w:Compatibility>
<w:BreakWrappedTables/>
<w:SnapToGridInCell/>
<w:WrapTextWithPunct/>
<w:UseAsianBreakRules/>
<w:DontGrowAutofit/>
<w:SplitPgBreakAndParaMark/>
<w:EnableOpenTypeKerning/>
<w:DontFlipMirrorIndents/>
<w:OverrideTableStyleHps/>
</w:Compatibility>
<m:mathPr>
<m:mathFont m:val=“Cambria Math”/>
<m:brkBin m:val=“before”/>
<m:brkBinSub m:val=“–”/>
<m:smallFrac m:val=“off”/>
<m:dispDef/>
<m:lMargin m:val=“0”/>
<m:rMargin m:val=“0”/>
<m:defJc m:val=“centerGroup”/>
<m:wrapIndent m:val=“1440”/>
<m:intLim m:val=“subSup”/>
<m:naryLim m:val=“undOvr”/>
</m:mathPr></w:WordDocument>
<![endif]–><!–[if gte mso 10]>

/* Style Definitions */ table.MsoNormalTable {mso-style-name:"Table Normal"; mso-tstyle-rowband-size:0; mso-tstyle-colband-size:0; mso-style-noshow:yes; mso-style-priority:99; mso-style-parent:""; mso-padding-alt:0in 5.4pt 0in 5.4pt; mso-para-margin-top:0in; mso-para-margin-right:0in; mso-para-margin-bottom:8.0pt; mso-para-margin-left:0in; line-height:107%; mso-pagination:widow-orphan; font-size:11.0pt; font-family:"Calibri",sans-serif; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin;}

<![endif]–>

MailMessage msg = MailMessage.Load("Untitled.msg", new MsgLoadOptions());

MemoryStream ms = new MemoryStream();

msg.Save(ms); //default eml

ms.Position = 0;

byte[] byArr = ms.ToArray();

Console.WriteLine("eml size in bytes including outline attachments: " + byArr.Length);

ms.Position = 0;

ms.SetLength(0);// = 0;

// Save as mht with header

MhtSaveOptions mhtSaveOptions = new MhtSaveOptions

{

MhtFormatOptions = MhtFormatOptions.None, //you can use other combinations here

MailMessageSaveType = MailMessageSaveType.MHtmlFormat,

};

msg.Save(ms, mhtSaveOptions);

ms.Position = 0;

byArr = ms.ToArray();

Console.WriteLine("mhtml size in bytes after excluding outline attachments: " + byArr.Length);

ms.Position = 0;

MailMessage reloaded = MailMessage.Load(ms, new MhtmlLoadOptions());

Console.WriteLine(reloaded.Attachments.Count);

Console.WriteLine(reloaded.LinkedResources.Count);

Very many thanks for these suggestions Kashif. I will try the Q2 suggestion you made. I cannot use the Q1 suggestion because I have to save as XPS, and cannot use TIFF format images.

Also, the error is intermittent, and not depending on a particular msg - the problem seems to be that the user will work for a while and then start getting the memory exception. So it's not a problem with any aspose code - from what I've read the MemoryStream has to resize itself and will throw the exception if it can't find a large enough free block of the appropriate size. If the MemoryStream has had to resize itself a lot then it will have chopped up the free space so that no sufficiently large block exists.

For that reason, I think your Q2 suggestion will be useful, as the MHTML content I put in the MemoryStream only needs the document body and the inline attachments. If I can omit the Outline attachments then the MemoryStream won't need to be resized lots of times and the probability of suffering a memory exception will be much lower.

Hi Brian,

Thank you for sharing your feedback.

You can use the Aspose.Email API to convert directly to XPS format that is actually listed in the article we shared with you in our earlier post.

Sample Code:

//Declare message as an MailMessage instance
MailMessage message = new MailMessage();

//Sender’s address
message.From = "user1@domain.com";

//Recipient’s address
message.To = "user2@domain.com";

//Subject of the email
message.Subject = “My First Mail”;

//Set message date to current date and time
message.Date = DateTime.Now;

//Body of the email nessage
message.TextBody = “Text is the Mail Message”;

//Instantiate an instance of MailPrinter
var printer = new Aspose.Email.Printing.MailPrinter();

//Set the MessageFormattingFlags to none to display only the message body
printer.FormattingFlags = Aspose.Email.Printing.MessageFormattingFlags.None;

//Print the email to an XPS file
printer.Print(message, “test.xps”, Aspose.Email.Printing.PrintFormat.XPS);


If you don’t want to use Aspose.Email API for direct conversion to XPS, then you can use the Q2 suggestion for reducing the size of the mhtml. Please feel free to write to us if you have any further query in this regard.