使用 EWS API 将邮件保存到 msg 文件

Posted

技术标签:

【中文标题】使用 EWS API 将邮件保存到 msg 文件【英文标题】:Save mail to msg file using EWS API 【发布时间】:2011-09-11 16:42:46 【问题描述】:

我正在使用 Exchange Web Services Managed API 1.1 连接到 Exchange server 2010,然后查找收到的新电子邮件。现在我想将 .msg 文件的副本保存到磁盘上的文件夹中。

我不想使用任何付费第三方进行集成。

任何帮助将不胜感激。

【问题讨论】:

您是否尝试保存到 .eml.msg 文件?跨度> 【参考方案1】:

如果您愿意改为保存为.eml 格式,则只需使用 EWS 即可轻松完成,无需第三方库。 .eml 文件将包含所有相同的信息,并且可以由 Outlook 以与 .msg 相同的方式打开(也可以由其他程序打开)。

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();

清理代码:

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);

【讨论】:

我知道这早已不复存在,但感谢您的回答。为我节省了很多时间。 同意。这很有帮助!我只是稍微改变了它以使用 using 语句: using (FileStream fileStream = File.Open(@"C:\message.eml", FileMode.Create, FileAccess.Write)) message.Load(new PropertySet(ItemSchema.哑剧内容)); MimeContent mc = message.MimeContent; fileStream.Write(mc.Content, 0, mc.Content.Length); 我通过包含 using 语句清理了代码,并更正了字符串文字 (@"C:\Test.eml") 的错误。 我要补充一点,这仅适用于交换中存在的电子邮件。它不能用于您从头开始撰写的电子邮件。 这对我不起作用。如果我尝试使用 Outlook 打开文件,它会打开一封带有榆树附件的新邮件。打开附件会打开另一条以榆树为附件的新消息(ala Escher)。【参考方案2】:

没有对使用 EWS 的 MSG 文件的本机支持。它严格来说是一种 Outlook 格式。

味精规范发布在http://msdn.microsoft.com/en-us/library/cc463912%28EXCHG.80%29.aspx。理解起来有点复杂,但是可行。您需要下拉消息的所有属性,然后将其序列化为 OLE 结构化文件格式。这不是一件容易的事。

最后,您最好还是使用 3rd 方库,否则这可能是一项艰巨的任务。

【讨论】:

【参考方案3】:

您可以通过message.MimeContent 轻松访问邮件的 MIME 内容并将邮件保存为 EML 文件。最新(2013 和 2016)版本的 Outlook 将能够直接打开 EML 文件。

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();

如果您仍需要转换为 MSG 格式,您有几个选择:

    MSG 文件格式已记录 - 它是一个 OLE 存储 (IStorage) 文件。见https://msdn.microsoft.com/en-us/library/cc463912(v=exchg.80).aspx

    使用第三方 MSG 文件包装器,例如来自 Independentsoft 的包装器:http://www.independentsoft.de/msg/index.html。设置 Outlook 期望的所有属性可能具有挑战性。

    使用Redemption直接将EML文件转换为MSG:

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

    请记住,MIME 不会保留所有 MAPI 特定属性。您可以使用ExportItems EWS operation 使用的快速传输流 (FTS) 格式(与 MSG 格式一样,它保留了大多数 MAPI 属性)。然后可以使用 Redemption (RDOSession.CreateMessageFromMsgFile / RDOMail.Import(..., olFTS) / RDOMail.Save) 将 FTS 数据转换(不损失任何保真度)为 MSG 格式

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

【讨论】:

保存到 .eml 很简单,但是保存到 .msg 需要 第三方(非免费 您仍然可以在二进制级别上直接使用 MSG 文件,但问题是这样做是否会节省您的时间或金钱 - 可​​能不会。【参考方案4】:

这条建议是@mack 作为评论发布的,但我认为它应该有自己的位置作为答案,如果除了答案与 cmets 的格式和可读性之外没有其他原因。

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); 

【讨论】:

【参考方案5】:

如果 eml 格式是一个选项并且 php 是语言,则在保存文件之前对 Mimencontent 使用 base64_decode。

如果使用https://github.com/Heartspring/Exchange-Web-Services-for-PHP或https://github.com/hatsuseno/Exchange-Web-Services-for-PHP需要添加

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

在第 245 或 247 行。

【讨论】:

【参考方案6】:

这就是我解决问题的方法,即通过 vbs 代码从 EWS 下载 .eml 格式的电子邮件

' 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

【讨论】:

【参考方案7】:

如果您要通过 VSTO(十六进制)从 Outlook 的 EntryID 转到 EwsID,则需要查看此处:http://bernhardelbl.wordpress.com/2013/04/15/converting-entryid-to-ewsid-using-exchange-web-services-ews/

救了我。我不断收到“数据已损坏”。消息。

【讨论】:

【参考方案8】:

您可以使用 EWS API 和 C# 下载所有附件。下面是给出的例子:

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++;
            
        
    

以上代码将所有附件转换为字节。一旦有了字节,就可以将字节转换为所需的格式。 要将字节转换为文件并保存在磁盘中,请点击以下链接: Write bytes to file http://www.digitalcoding.com/Code-Snippets/C-Sharp/C-Code-Snippet-Save-byte-array-to-file.html

【讨论】:

以上是关于使用 EWS API 将邮件保存到 msg 文件的主要内容,如果未能解决你的问题,请参考以下文章

C# Managed EWS 通过 ID 从共享邮箱获取电子邮件

Powershell 访问Exchange EWS API

如果地址是别名,如何使用 ews-java-api 识别收件人电子邮件?

Exchange Web 服务 (EWS) - 如何识别会议参与者是邮件组还是个人参与者

使用 EWS API 发送电子邮件时控制消息编码

使用Ews API去删除邮件内容中包含特定关键字的邮件