将MailMessage转换为原始文本

有没有简单的方法将System.Net.Mail.MailMessage对象转换为原始邮件消息文本,就像在记事本中打开eml文件一样。

这是相同的解决方案,但作为MailMessage的扩展方法。

通过在静态上下文中抓取ConstructorInfoMethodInfo成员一次,可以最大限度地减少一些reflection开销。

 ///  /// Uses reflection to get the raw content out of a MailMessage. ///  public static class MailMessageExtensions { private static readonly BindingFlags Flags = BindingFlags.Instance | BindingFlags.NonPublic; private static readonly Type MailWriter = typeof(SmtpClient).Assembly.GetType("System.Net.Mail.MailWriter"); private static readonly ConstructorInfo MailWriterConstructor = MailWriter.GetConstructor(Flags, null, new[] { typeof(Stream) }, null); private static readonly MethodInfo CloseMethod = MailWriter.GetMethod("Close", Flags); private static readonly MethodInfo SendMethod = typeof(MailMessage).GetMethod("Send", Flags); ///  /// A little hack to determine the number of parameters that we /// need to pass to the SaveMethod. ///  private static readonly bool IsRunningInDotNetFourPointFive = SendMethod.GetParameters().Length == 3; ///  /// The raw contents of this MailMessage as a MemoryStream. ///  /// The caller. /// A MemoryStream with the raw contents of this MailMessage. public static MemoryStream RawMessage(this MailMessage self) { var result = new MemoryStream(); var mailWriter = MailWriterConstructor.Invoke(new object[] { result }); SendMethod.Invoke(self, Flags, null, IsRunningInDotNetFourPointFive ? new[] { mailWriter, true, true } : new[] { mailWriter, true }, null); result = new MemoryStream(result.ToArray()); CloseMethod.Invoke(mailWriter, Flags, null, new object[] { }, null); return result; } } 

要获取底层的MemoryStream

 var email = new MailMessage(); using (var m = email.RawMessage()) { // do something with the raw message } 

我在MimeKit中实现了逻辑,允许您将System.Net.Mail.MailMessage 强制转换为MimeKit.MimeMessage 。 完成后,您只需将消息写入流:

 var message = (MimeMessage) CreateSystemNetMailMessage (); using (var stream = File.Create ("C:\\message.eml")) message.WriteTo (stream); 

这不需要反映到内部方法中,这意味着它不依赖于运行时,使其比目前为止给出的其他答案更具可移植性。

我见过这样做的代码依赖于reflection。 我调整了在线发现的样本来创建这个方法:

  private static MemoryStream ConvertMailMessageToMemoryStream(MailMessage message) { BindingFlags flags = BindingFlags.Instance | BindingFlags.NonPublic; Assembly assembly = typeof(SmtpClient).Assembly; MemoryStream stream = new MemoryStream(); Type mailWriterType = assembly.GetType("System.Net.Mail.MailWriter"); ConstructorInfo mailWriterContructor = mailWriterType.GetConstructor(flags, null, new[] { typeof(Stream) }, null); object mailWriter = mailWriterContructor.Invoke(new object[] { stream }); MethodInfo sendMethod = typeof(MailMessage).GetMethod("Send", flags); sendMethod.Invoke(message, flags, null, new[] { mailWriter, true }, null); MethodInfo closeMethod = mailWriter.GetType().GetMethod("Close", flags); closeMethod.Invoke(mailWriter, flags, null, new object[] { }, null); return stream; } 

然后,您可以将MemoryStream转换为字符串或您需要的任何内容。

更新:.NET 4.5中的方法签名已更改,这破坏了上述内容: 在.NET 4.5 beta中将System.Net.Mail.MailMessage作为MemoryStream