将MailMessage转换为原始文本

时间:2011-09-22 13:24:17

标签: c# .net

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

4 个答案:

答案 0 :(得分:19)

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

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

/// <summary>
/// Uses reflection to get the raw content out of a MailMessage.
/// </summary>
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);

    /// <summary>
    /// A little hack to determine the number of parameters that we
    /// need to pass to the SaveMethod.
    /// </summary>
    private static readonly bool IsRunningInDotNetFourPointFive = SendMethod.GetParameters().Length == 3;

    /// <summary>
    /// The raw contents of this MailMessage as a MemoryStream.
    /// </summary>
    /// <param name="self">The caller.</param>
    /// <returns>A MemoryStream with the raw contents of this MailMessage.</returns>
    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
}

答案 1 :(得分:8)

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

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

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

答案 2 :(得分:2)

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

    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中的方法签名已更改,这违反了上述内容: Getting System.Net.Mail.MailMessage as a MemoryStream in .NET 4.5 beta

答案 3 :(得分:0)

byte[] allBytes = new byte[attachment.ContentStream.Length];
int bytesRead = attachment.ContentStream.Read(allBytes, 0, (int)attachment.ContentStream.Length);
Encoding encoding = Encoding.UTF8;
String contenidoCorreo = encoding.GetString(allBytes);