Save mail to msg file using EWS API
Asked Answered
B

8

30

I'm using Exchange Web Services Managed API 1.1 to connect to Exchange server 2010 and then find out new emails received. Now I want to save a copy of the .msg file to a folder on the disk.

I do not want to use any paid third party to integrate.

Any help will be appreciated.

Bracing answered 9/6, 2011 at 12:58 Comment(1)
did you tried save to .eml or .msg file?Overtake
R
61

If you are happy to save into the .eml format instead, it can be done very easily just using EWS and no third party libraries. The .eml file will contain all the same information and can be opened by Outlook in the same way as .msg (and also by other programs).

message.Load(new PropertySet(ItemSchema.MimeContent));

MimeContent mc = message.MimeContent;
FileStream fs = new FileStream("c:\test.eml", FileMode.Create);

fs.Write(mc.Content, 0, mc.Content.Length);
fs.Close();

Cleaned up code:

message.Load(new PropertySet(ItemSchema.MimeContent));
var mimeContent = message.MimeContent;

using (var fileStream = new FileStream(@"C:\Test.eml", FileMode.Create))
{
    fileStream.Write(mimeContent.Content, 0, mimeContent.Content.Length);
}
Ruler answered 7/7, 2011 at 12:38 Comment(5)
I know this is long gone, but thanks for your answer. Saved me a lot of time.Statfarad
Agreed. This was very helpful! I just changed it a little to use a using statement: using (FileStream fileStream = File.Open(@"C:\message.eml", FileMode.Create, FileAccess.Write)) { message.Load(new PropertySet(ItemSchema.MimeContent)); MimeContent mc = message.MimeContent; fileStream.Write(mc.Content, 0, mc.Content.Length); }Turgescent
I cleaned up the code by including the using statements, and also corrected a mistake with the string literal (@"C:\Test.eml").Vespertine
I would add that this only works for emails that exist in exchange. It cannot be used on an email you are composing from scratch.Maccaboy
This did not work for me. If I attempt to open the file with Outlook, it opens a new message with the elm as an attachment. Opening the attachment opens another new message with the elm as an attachment ala Escher.Mccurdy
B
7

There is no native support for MSG files using EWS. It's strictly an Outlook format.

The MSG spec is published at http://msdn.microsoft.com/en-us/library/cc463912%28EXCHG.80%29.aspx. It's a little complicated to understand, but do-able. You would need to pull down all of the properties for the message and then serialize it into an OLE structured file format. It's not an easy task.

In the end, you are probably better off going with a 3rd party library otherwise it might be a big task to accomplish.

Borlow answered 15/6, 2011 at 0:10 Comment(0)
R
3

You can easily access the MIME contents of the message through message.MimeContent and save the message as an EML file. The latest (2013 and 2016) versions of Outlook will be able to open EML files directly.

message.Load(new PropertySet(ItemSchema.MimeContent));
MimeContent mimcon = message.MimeContent;
FileStream fStream = new FileStream("c:\test.eml", FileMode.Create);
fStream.Write(mimcon.Content, 0, mimcon.Content.Length);
fStream.Close();

If you still need to convert to the MSG format, you have a few options:

  1. MSG file format is documented - it is an OLE store (IStorage) file. See https://msdn.microsoft.com/en-us/library/cc463912(v=exchg.80).aspx

  2. Use a third party MSG file wrapper, such as the one from Independentsoft: http://www.independentsoft.de/msg/index.html. Setting all properties that Outlook expects can be challenging.

  3. Convert EML file to MSG directly using Redemption (I am its author):

    set Session = CreateObject("Redemption.RDOSession") set Msg = Session.CreateMessageFromMsgFile("c:\test.msg") Msg.Import("c:\test.eml", 1024) Msg.Save

  4. Keep in mind that MIME won't preserve all MAPI specific properties. You can use the Fast Transfer Stream (FTS) format used by the ExportItems EWS operation (which, just like the MSG format, preserves most MAPI properties). The FTS data can then be converted (without any loss of fidelity) to the MSG format using Redemption (I am its author) - RDOSession.CreateMessageFromMsgFile / RDOMail.Import(..., olFTS) / RDOMail.Save

    RDOSession session = new RDOSession(); RDOMail msg = session.CreateMessageFromMsgFile(@"c:\temp\test.msg"); msg.Import(@"c:\temp\test.fts", rdoSaveAsType.olFTS); msg.Save();

Rosin answered 17/3, 2016 at 20:11 Comment(2)
Save to .eml is easy, but save to .msg requires third party (NOT free)Overtake
You can still work directly with the MSG file on the binary level, but the question is whether doing so will save you any time or money - probably not.Rosin
W
2

This suggestion was posted as a comment by @mack, but I think it deserves its own place as an answer, if for no other reason than formatting and readability of answers vs. comments.

using (FileStream fileStream = 
    File.Open(@"C:\message.eml", FileMode.Create, FileAccess.Write)) 
{ 
    message.Load(new PropertySet(ItemSchema.MimeContent)); 
    MimeContent mc = message.MimeContent; 
    fileStream.Write(mc.Content, 0, mc.Content.Length); 
}
Weedy answered 11/9, 2013 at 13:39 Comment(0)
C
1

If eml format is an option and php is the language use base64_decode on the Mimencontent before save on file.

If using https://github.com/Heartspring/Exchange-Web-Services-for-PHP or https://github.com/hatsuseno/Exchange-Web-Services-for-PHP need to add

 $newmessage->mc = $messageobj->MimeContent->_;

on line 245 or 247.

Chokeberry answered 10/10, 2012 at 10:31 Comment(0)
H
0

This is how I solved the problem to download from EWS the email message in .eml format via vbs code

' This is the function that retrieves the message:
function CreaMailMsg(ItemId,ChangeKey)
Dim MailMsg
Dim GetItemSOAP,GetItemResponse,Content

    LogFile.WriteLine (Now() & "-" & ":CreaMailMsg:ID:" & ItemId)
    GetItemSOAP=ReadTemplate("GetItemMsg.xml")
    GetItemSOAP=Replace(GetItemSOAP, "<!--ITEMID-->", ItemId)   
    GetItemSOAP=Replace(GetItemSOAP, "<!--ITEMCHANGEKEY-->", ChangeKey)
    LogFile.WriteLine (Now() & ":GetItemSOAP:" & GetItemSOAP) 

    set GetItemResponse=SendSOAP(GetItemSOAP,TARGETURL,"",USERNAME,PASSWORD)
    ' Check we got a Success response
    if not IsResponseSuccess(GetItemResponse, "m:GetItemResponseMessage","ResponseClass") then
        LogFile.WriteLine (Now() & "-" & ":ERRORE:Fallita GetItemMsg:" & GetItemResponse.xml)
        Chiusura 1
    end if

'   LogFile.WriteLine (Now() & "-" & ":DEBUG:riuscita GetItemMsg:" & GetItemResponse.xml)
    Content = GetItemResponse.documentElement.getElementsByTagName("t:MimeContent").Item(0).Text
'   LogFile.WriteLine (Now() & ":Contenuto MIME" & Content)

    CreaMailMsg = WriteAttach2File(Content,"OriginaryMsg.eml")

'   MailMsg.close
    CreaMailMsg = true
end function
'###########################################################################
' These are the functions the save the message in .eml format
'###########################################################################
function WriteAttach2File(Content,nomeAttach)
Dim oNode,oXML,Base64Decode
    ' Read the contents Base64 encoded and Write a file  
    set oXML=CreateObject("MSXML2.DOMDocument")
    set oNode=oXML.CreateElement("base64")
    oNode.DataType="bin.base64"
    oNode.Text = Content
    Base64Decode = Stream_Binary2String(oNode.nodeTypedValue,nomeAttach)
    Set oNode = Nothing
    Set oXML = Nothing
end function
'###########################################################################
function Stream_Binary2String(binary,nomeAttach)
    Const adTypeText = 2
    Const adTypeBinary = 1
    Dim BinaryStream

    Set BinaryStream=CreateObject("ADODB.Stream")
    BinaryStream.Type=adTypeBinary' Binary
    BinaryStream.Open
    BinaryStream.Write binary   
    BinaryStream.Position=0
    BinaryStream.Type=adTypeText
    BinaryStream.CharSet = "us-ascii"
    Stream_Binary2String=BinaryStream.ReadText
    'msgbox Stream_Binary2String
    BinaryStream.SaveToFile ShareName & "\" & nomeAttach,2

    Set BinaryStream=Nothing
end function
Hochheimer answered 5/4, 2014 at 16:31 Comment(0)
D
0

If you are going from Outlook's EntryID via VSTO (Hex) to EwsID, you need to look here: http://bernhardelbl.wordpress.com/2013/04/15/converting-entryid-to-ewsid-using-exchange-web-services-ews/

Saved me. I kept getting a "Data is corrupt." message.

Defalcate answered 28/4, 2014 at 19:49 Comment(0)
B
-1

You can download all the attachments using EWS API and C# . Below is the example given:

byte[][] btAttachments = new byte[3][]; //To store  3 attachment 

if (item.HasAttachments) {
    EmailMessage message = EmailMessage.Bind(objService, new ItemId(item.Id.UniqueId.ToString()), new PropertySet(BasePropertySet.IdOnly, ItemSchema.Attachments));

    noOfAttachment = message.Attachments.Count;

    // Iterate through the attachments collection and load each attachment.
    foreach(Attachment attachment in message.Attachments)
    {
        if (attachment is FileAttachment)
        {
            FileAttachment fileAttachment = attachment as FileAttachment;
            // Load the file attachment into memory and print out its file name.
            fileAttachment.Load();
            //Get the Attachment as bytes
            if (i < 3) {
                btAttachments[i] = fileAttachment.Content;
                i++;
            }
        }
        // Attachment is an item attachment.
                    else
        {
            // Load attachment into memory and write out the subject.
            ItemAttachment itemAttachment = attachment as ItemAttachment;
            itemAttachment.Load(new PropertySet(EmailMessageSchema.MimeContent));
            MimeContent mc = itemAttachment.Item.MimeContent;
            if (i < 3) {

                btAttachments[i] = mc.Content;
                i++;
            }
        }
    }
}

Above code converts all the attachment into bytes. Once you have bytes, you can convert bytes into your required format. To Convert bytes into files and save in the disk follow the below links: Write bytes to file http://www.digitalcoding.com/Code-Snippets/C-Sharp/C-Code-Snippet-Save-byte-array-to-file.html

Brann answered 11/12, 2012 at 5:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.