如何在 C# 中使用 Outlook MAPI 打开 .eml 文件

本文关键字:MAPI Outlook 打开 eml 文件 | 更新日期: 2023-09-27 17:56:33

我有一个C#应用程序,可以读取.msg文件并提取正文和附件。但是当我尝试加载 .eml 文件时,应用程序崩溃了。我正在加载这样的文件:

MailItem mailItem = (MailItem)outlookApp.CreateItemFromTemplate(msgFileName);
mailItem.SaveAs(fullFilename, OlSaveAsType.olHTML); // save body in html format
for(int i = 0; i < mailItem.Attachments.Count; i++)
    mailItem.Attachments[i].SaveAsFile(filename); // save attachments

这适用于.msg文件,但不适用于 .eml 文件。我不明白为什么 .eml 文件不起作用,因为我可以在 Outlook 2010 中打开 .eml 文件。

如何使用 Outlook 主互操作程序集加载 .eml 文件?

如何在 C# 中使用 Outlook MAPI 打开 .eml 文件

尝试此示例代码 轻松从 检索电子邮件信息。电子移动单元文件

CreateItemFromTemplate仅适用于MSG/OFT文件。对于 EML 文件,您需要在代码中显式解析该文件或使用第三方库(例如 Redemption - 我是它的作者):

以下代码将创建一个 MSG 文件,并使用 Redemption(RDOSession 对象)将 EML 文件导入其中:

  set Session = CreateObject("Redemption.RDOSession")
  Session.MAPIOBJECT = outlookApp.Session.MAPIOBJECT
  set Msg = Session.CreateMessageFromMsgFile("C:'Temp'temp.msg")
  Msg.Import "C:'Temp'test.eml", 1024
  Msg.Save
  MsgBox Msg.Subject

然后,您可以使用消息 (RDOMail) 访问它的各种属性(主题、正文等)。

为了从.eml文件创建MailItem,您可以使用以下两个步骤:首先打开Outlook流程实例,然后使用Outlook API创建MailItem。

  string file = @"C:'TestEML'EmlMail.eml";
  System.Diagnostics.Process.Start(file);
  Outlook.Application POfficeApp = (Outlook.Application)Marshal.GetActiveObject("Outlook.Application");  // note that it returns an exception if Outlook is not running
  Outlook.MailItem POfficeItem = (Outlook.MailItem)POfficeApp.ActiveInspector().CurrentItem; // now pOfficeItem is the COM object that represents your .eml file

尽管Outlook可以打开EML文件,但仅使用VBA无法以编程方式执行此操作。所以我创建了这个VBA宏,它循环访问某个文件夹并使用SHELL EXEC打开每个EML文件。Outlook 打开 EML 文件可能需要几毫秒,因此 VBA 会等到在 ActiveInspector 中打开某些内容。最后,此电子邮件被复制到某个选定的文件夹中,并且(如果成功)原始EML文件将被删除。

在这里查看我的完整答案(和代码):https://stackoverflow.com/a/33761441/3606250

假设安装了 outlook...

仅对于消息文件,当 Outlook 正在运行/已打开时,您可以使用 OpenSharedItem

Microsoft.Office.Interop.Outlook.Application appOutlook = new Microsoft.Office.Interop.Outlook.Application();
var myMailItem = appOutlook.Session.OpenSharedItem(strPathToSavedEmailFile) as Microsoft.Office.Interop.Outlook.MailItem;

对于 eml 文件或 msg 文件(Outlook 将打开并弹出):

var strPathToSavedEmailFile=@"C:'temp'mail.eml";
//Microsoft.Win32 namespace to get path from registry
var strPathToOutlook=Registry.LocalMachine.OpenSubKey(@"Software'Microsoft'Windows'CurrentVersion'App Paths'outlook.exe").GetValue("").ToString();
//var strPathToOutlook=@"C:'Program Files'Microsoft Office'root'Office16'OUTLOOK.EXE";
string strOutlookArgs;
if(Path.GetExtension(strPathToSavedEmailFile)==".eml")
{
  strOutlookArgs =  @"/eml "+strPathToSavedEmailFile;  // eml is an undocumented outlook switch to open .eml files
}else
    {
     strOutlookArgs =   @"/f "+strPathToSavedEmailFile;
    }
Process p = new System.Diagnostics.Process();
p.StartInfo = new ProcessStartInfo()
{
    CreateNoWindow = false,
    FileName = strPathToOutlook, 
    Arguments = strOutlookArgs
};
p.Start();
//Wait for Outlook to open the file
Task.Delay(TimeSpan.FromSeconds(5)).GetAwaiter().GetResult();
Microsoft.Office.Interop.Outlook.Application appOutlook = new Microsoft.Office.Interop.Outlook.Application();
//Microsoft.Office.Interop.Outlook.MailItem myMailItem  = (Microsoft.Office.Interop.Outlook.MailItem)appOutlook.CreateItem(Microsoft.Office.Interop.Outlook.OlItemType.olMailItem);
var myMailItem = (Microsoft.Office.Interop.Outlook.MailItem)appOutlook.ActiveInspector().CurrentItem;
//Get the Email Address of the Sender from the Mailitem 
string strSenderEmail=string.Empty;
if(myMailItem.SenderEmailType == "EX"){
    strSenderEmail=myMailItem.Sender.GetExchangeUser().PrimarySmtpAddress;
}else{
    strSenderEmail=myMailItem.SenderEmailAddress;
}
//Get the Email Addresses of the To, CC, and BCC recipients from the Mailitem   
var strToAddresses = string.Empty;
var strCcAddresses= string.Empty;
var strBccAddresses = string.Empty;
foreach(Microsoft.Office.Interop.Outlook.Recipient recip in myMailItem.Recipients)
    {
    const string PR_SMTP_ADDRESS = @"http://schemas.microsoft.com/mapi/proptag/0x39FE001E";
    Microsoft.Office.Interop.Outlook.PropertyAccessor pa = recip.PropertyAccessor; 
    string eAddress = pa.GetProperty(PR_SMTP_ADDRESS).ToString(); 
    if(recip.Type ==1)
        {
        if(strToAddresses == string.Empty)
            {
            strToAddresses = eAddress;
            }else
                {
                strToAddresses = strToAddresses +","+eAddress;
                }
        };
    if(recip.Type ==2)
        {
        if(strCcAddresses == string.Empty)
            {
            strCcAddresses = eAddress;
            }else
                {
                strCcAddresses = strCcAddresses +","+eAddress;
                }       
        };
    if(recip.Type ==3)
        {
        if(strBccAddresses == string.Empty)
            {
            strBccAddresses = eAddress;
            }else
                {
                strBccAddresses = strBccAddresses +","+eAddress;
                }       
        };
    }
Console.WriteLine(strToAddresses);
Console.WriteLine(strCcAddresses);
Console.WriteLine(strBccAddresses);
foreach(Microsoft.Office.Interop.Outlook.Attachment mailAttachment in myMailItem.Attachments){
    Console.WriteLine(mailAttachment.FileName);
}
Console.WriteLine(myMailItem.Subject);
Console.WriteLine(myMailItem.Body);