C#使用MimeMessage.WriteTo生成Outlook .msg文件无法打开问题求助
问题根源
你误用了MimeMessage.WriteTo方法的输出格式:MimeKit提供的WriteTo方法生成的是标准EML(符合RFC822规范)格式的邮件内容,并非微软专属的Outlook MSG二进制复合文件格式。你只是把生成的EML文件后缀修改为了.msg,本质还是EML文件,Outlook识别到格式不匹配就会抛出异常,这和权限、文件占用没有任何关系,也是两种方案生成的文件大小差距巨大的根本原因。
免费实现方案
如果不想采购IndependentSoft的商业授权,可以根据你的部署场景选择以下两种免费方案:
- 方案1:依赖Outlook环境的Interop方案(适合客户端场景,不推荐服务端使用)
前提是运行环境已安装Outlook,示例代码如下:using System.IO; using System.Runtime.InteropServices; using MimeKit; using Microsoft.Office.Interop.Outlook; public static byte[] ConvertMimeToMSG(MimeMessage mm) { if (mm == null) return null; // 生成临时EML文件 string tempEmlPath = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid()}.eml"); mm.WriteTo(tempEmlPath); // 用Outlook打开EML另存为MSG Application outlookApp = new Application(); MailItem mailItem = (MailItem)outlookApp.Session.OpenSharedItem(tempEmlPath); string tempMsgPath = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid()}.msg"); mailItem.SaveAs(tempMsgPath, OlSaveAsType.olMSG); // 读取MSG字节流 byte[] msgBytes = File.ReadAllBytes(tempMsgPath); // 清理临时文件和COM对象 File.Delete(tempEmlPath); File.Delete(tempMsgPath); Marshal.ReleaseComObject(mailItem); Marshal.ReleaseComObject(outlookApp); return msgBytes; } - 方案2:使用开源MsgKit库实现纯代码转换(服务端、客户端均适用,MIT协议可免费商用)
首先通过NuGet安装MsgKit包,示例代码如下:using System.IO; using System.Linq; using MimeKit; using MsgKit; using MsgKit.Enums; public static byte[] ConvertMimeToMSG(MimeMessage mm) { if (mm == null) return null; using var ms = new MemoryStream(); // 提取发件人信息 var from = mm.From.OfType<MailboxAddress>().FirstOrDefault(); if (from == null) return null; // 构造MSG对象 using var msg = new Message( new Sender(from.Address, from.Name), mm.To.Select(t => new Recipient(RecipientType.To, ((MailboxAddress)t).Address, ((MailboxAddress)t).Name)).ToList(), mm.Subject); // 填充正文 msg.BodyText = mm.TextBody; msg.BodyHtml = mm.HtmlBody; msg.Date = mm.Date.DateTime; // 填充附件 foreach (var attachment in mm.Attachments.OfType<MimePart>()) { using var attachStream = new MemoryStream(); attachment.Content.DecodeTo(attachStream); msg.Attachments.Add(attachment.FileName, attachStream.ToArray()); } // 可按需补充抄送、密送、优先级等其他属性 msg.Save(ms); return ms.ToArray(); }
内容的提问来源于stack exchange,提问作者vazun
相关产品推荐
相关产品推荐

