I need help with converting EML to MSG, using the Exchange web service (EWS) in a Outlook Web Add-In. When i create an EML file from the MimeContent (EmailMessage.MimeContent.Content), the file output looks bad, some tags are not convert currently.
The files open good just from Windows mail app, but from Ooutlook(2016) looks bad.
I tried to find some solution from Microsoft and found this Independentsoft, a third party solution, and it is work great. the file looks good while the format is MSG. but it is to expansive licence solution for the customer (used 30 days demo).
This is what i used and work well, and try to found something like this:
//1.This code use the EWS mimeContent(the message on bytes - eml format)
//2.Create Independentsoft message object
//Independentsoft.Msg.Message constractor do the convert by
// making an msg object from an eml object.
//3. save the msg file.
Independentsoft.Email.Mime.Message mimeMessage = new Independentsoft.Email.Mime.Message(emailMessage.MimeContent.Content);
Independentsoft.Msg.Message msgMessage = Independentsoft.Msg.Message(mimeMessage);
using (MemoryStream memStream = new MemoryStream(emailMessage.MimeContent.Content.Length))
{
Directory.CreateDirectory(TempMsgDirectory);
msgMessage.Save(TempMsgDirectory + "mail.msg", true);
}
I am not aware of any Outlook problems with displaying EML files. It uses the same EML parser used to parse incoming POP3/IMAP4 messages. Please post a specific EML file that Outlook does not display correctly.
As for converting EML files to MSG, you can also use Redemption (I am its author) and its RDOSession.CreateMessageFromMsgFIle and RDOMail.Import methods. Just keep in mind that it requires the MAPI system to be present to function properly, which means Outlook must be installed locally.
Off the top of my head:
RDOSession session = new RDOSession();
RDOMail msg = session.CreateMessageFromMsgFile(TempMsgDirectory + "mail.msg");
msg.Import(TempMsgDirectory + "YouEmlFile.eml", rdoSaveAsType.olRFC822);
msg.Save();
Also keep in mind that retrieving MIME content from Exchange might not be the best idea - you will lose all MAPI specific properties and will end up with a corrupted message if the original was in the RTF format (with or without embedded OLE objects). In that case, you can use ExportItems EWS operation. Its format is not documented, but it is very close to the MSG format, and you can convert it to MSG using code similar to that above, but specifying olFTS format instead of olRFC822.
Related
I'm trying to do a conversion from .msg files into .txt. I have two questions.
1)I've been investigating and found the Microsoft.Interop Outlook package and there is a way where I can extract the bodyHTML, To, Sent Date, and a few other properties but I feel as if this is a very manual process because I have to trim out all the html tags such as < br>,  , a href etc...
Here is my current code...
MailItem mailItem = outlookApp.Session.OpenSharedItem(item) as MailItem;
TextFile textFile = new TextFile(); //collection of properties I am interested in
textFile.To = mailItem.To;
textFile.Subject = mailItem.Subject;
textFile.Sent = mailItem.SentOn.ToString();
textFile.Name = Path.GetFileNameWithoutExtension(item);
var atttach = mailItem.Attachments; //Really just want the names
textFile.Body = RemoveStuff(mailItem.HTMLBody); //manually removing all html tags
textFiles.Add(textFile);
Marshal.ReleaseComObject(mailItem);
Does anyone know if there is a more effective way to do this in C# or a way using Interop that I am not aware of?
2)If I go the interop route, is there a way I can bypass the popup in Outlook asking if I can allow access to Outlook? Seems inefficient if my goal is to create a converter.
Any help is greatly appreciated.
Thanks!
Firstly, why are you using HTMLBody property instead of the plain text Body?
Secondly, you can use MailItem.SaveAs(..., olTxt) to save the message as a text file. Or do you mean something else by txt file?
The security prompt is raised by Outlook if your antivirus app is not up to date. If you cannot control the environment where your code runs, Extended MAPI (C++ or Delphi only) or a wrapper like Redemption (any language - I am its author) are pretty much your only option. See http://www.outlookcode.com/article.aspx?id=52 for more details.
In Redemption, you can have something like the following:
using Redemption;
...
RDOSession session = new RDOSession();
RDOMail msg = session.GetMessageFromMsgFile(TheFileName);
msg.SaveAs(TxtFileName, rdoSaveAsType.olTXT);
We are using MailKit in our application to send e-mails to users. These e-mails often have attachments with Unicode or long file names. Some e-mail clients, such as Outlook (when using POP or IMAP) or Outlook Express, cannot handle RFC 2231, and the result is that the attachments have names 'Untitled Attachment'.
Is there a way to send mails (using MailKit) supporting RFC 2047 (encoded-words) for attachments file names? A possible solution would be to keep RFC 2231 in filename in content-disposition, but use as a fall-back an encoded-word encoded name parameter in content-type. Is something like this supported?
I've just added support for using rfc2047 encoding to MimeKit.
There are now 2 ways of controlling the encoding method used for parameter values.
The first way is to set the encoding method on each individual Parameter:
param.EncodingMethod = ParameterEncodingMethod.Rfc2047;
The second way is to set the default parameter encoding method on the FormatOptions used for writing out the message and/or MIME part(s):
var options = FormatOptions.Default.Clone ();
options.ParameterEncodingMethod = ParameterEncodingMethod.Rfc2047;
message.WriteTo (options, stream);
I'll try to release a new MimeKit 1.3.0-beta3 to nuget soon with this feature.
Fair warning: I'm a little bit of a rookie to C# and to Outlook, so bear with me on this.
I've been experimenting with emails in Outlook for a quick and dirty addin I'm building, but the addin requires me to send attached files to a different system.
Long story short; in order to do this I need to convert an Outlook item's mail attachment into a byte array.
What I have thus far (and the complete code is obviously miles longer than this, but I'm sure we all have better things to do than to sit and read page up and page down of code):
Outlook.Selection sel = control.Context as Outlook.Selection;
Outlook.MailItem mail = sel[1];
Outlook.Attachment a = mail.Attachments[0];
Problem is, that I have no idea how to convert a to a byte array.
PS: I know there are about a billion answers as to how to convert a byte array to a mail, but none to explain how to get it running the other way around.
EDIT 1: I would rather not have to save the file.
The second method proposed by Dmitry (open attachment as binary stream) is also achievable in managed code. It uses the PropertyAccessor interface, which is available for Attachment objects in C#. Here is some sample code I've used successfully in my own project:
const string PR_ATTACH_DATA_BIN = "http://schemas.microsoft.com/mapi/proptag/0x37010102";
Outlook.Attachment attachment = mail.Attachments[0];
// Retrieve the attachment as a byte array
var attachmentData =
attachment.PropertyAccessor.GetProperty(PR_ATTACH_DATA_BIN);
My example code is based on the How to: Modify an Attachment of an Outlook Email Message topic provided by Ken Getz, MCW Technologies, LLC as part of the MSDN documentation.
You can either
Save the attachment (Attachment.SaveAsFile) to a file, then open the file as a byte stream.
If you were using C++ or Delphi, you could use IAttach::OpenProperty(PR_ATTACH_DATA_BIN, IID_IStream, ..) to open the attachment as IStream COM object.
If using Redemption is an option (I am its author), it exposes the AsArray property on the Attachment and RDOAttachment objects.
I have a the following setup to send emails from my c# Application :
SmtpClient (under System.Net.Mail namespace) to do the actual sending once everything is in place and set the 'IsBodyHtml' property of the Message object to True
Using the dll from Sautinsoft I convert a simple rtf file which contains the formatting of the email and convert it to a HTML string which I then use as the body of the mail.
It works great just as it is and I have sent a few test emails to myself and all the appropriate formatting is retained. However i am having a problem with images - The dll converts images to a img tag and uses the base 64 format of the image as the data source, this works fine if you view it as a html page, but sending it as the body of you email produces problems. Email clients such as Yahoo don't mind embedded images but Gmail does not play nice with this methodology. The only image that should appear in the emails I'm sending is the signature image located at the bottom of each email. Using signatures in the native Gmail client in your browser poses no problems since the image has a link to a actual file on a server somewhere, but sending emails with signatures via a C# Application seems to be a different story. Any suggestions?
Thank you for your time.
You may consider automating Outlook from a C# application. See How to automate Outlook and Word by using Visual C# .NET to create a pre-populated e-mail message that can be edited. Also you can find a sample code - C# app automates Outlook (CSAutomateOutlook).
If you are talking about RTF2HTML, you may add any images in a separate folder (no include in body of HTML):
string inpFile = #"..\..\..\..\example.docx";
string outFile = Path.GetFullPath(#"Result2.html");
string imgDir = Path.GetDirectoryName(outFile);
RtfToHtml r = new RtfToHtml();
// Set images directory
HtmlFixedSaveOptions opt = new HtmlFixedSaveOptions()
{
ImagesDirectoryPath = Path.Combine(imgDir, "Result_images"),
ImagesDirectorySrcPath = "Result_images",
// Change to store images as physical files on local drive.
EmbedImages = false
};
try
{
r.Convert(inpFile, outFile, opt);
}
catch (Exception ex)
{
Console.WriteLine($"Conversion failed! {ex.Message}");
}
As the result you will see HTML file with linked images in folder.
I have a number of Outlook MSGs that I need to save to alternate formats, such as MHT. The MSGs each have thousands of recipients, and I am aware that the MSG structure is not robust enough to handle large numbers of recipients. I believe that my first step is to import the MSGs into a PST, which can handle large numbers of recipients.
I am using Outlook 2010 and Redemption 5.4 (full). I am prepared to use either the Outlook object model or Redemption to accomplish my goals. Platform: Windows 7 SP1, 64-bit.
I have tried these methods:
//Establish Session
RDOSession rdoSession = new RDOSession();
rdoSession.Logon(null, null, false, true, null, true);
//Create empty mail item in PST.
RDOMail rdoMail = rdoSession.GetDefaultFolder(rdoDefaultFolders.olFolderInbox).Items.Add(null);
//Merge MSG into new, empty mail
//fi.FullName = C:\<subdirectories>\009.msg
rdoMail.Import(fi.FullName, rdoSaveAsType.olMSGUnicode);
rdoMail.Save();
//Save as MHT
rdoMail.SaveAs(diMht.FullName + #"\" + strNormalizedSubject + ".mht", Redemption.rdoSaveAsType.olMHTML);
This code fails to import the MSG into the PST. I receive this exception:
{"Error importing: 0x8004011B"}
I have also tried this method, which does not rely on a PST.
RDOMail rdoMail = rdoSession.GetMessageFromMsgFile(fi.FullName, false);
string strNormalizedSubject = NormalizeSubject(rdoMail.Subject);
rdoMail.SaveAs(diMht.FullName + #"\" + strNormalizedSubject + ".mht", Redemption.rdoSaveAsType.olMHTML);
This code results in this exception: Error in OpenIMsgOnIStg: MAPI_E_CORRUPT_DATA.
I believe that Transend Migrator can convert MSGs with large numbers or recipients. However, that is not an option due to high licensing costs.
How can I save the MSG to another format?
0x8004011B is MAPI_E_CORRUPT_DATA. Looks like you have a corrupt PST store. Did you try to repair it using scanpst.exe?
Dmitry suggested that I treat MSG files as OLE storage files. That idea led me to this site: Reading an Outlook MSG File in C# CodeProject.
I have confirmed that the project is able to open MSGs with large numbers of recipients. I tested it with an MSG having 2,499 recipients.
That project may make it possible to extract the data required to build an MHT file.