使用 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 从共享邮箱获取电子邮件
如果地址是别名,如何使用 ews-java-api 识别收件人电子邮件?