8

我正在使用 Amazon SES SendRawEmail API,因此我需要一个 MailMessage 作为内存流。

我在 stackoverflow 上找到了关于 MailMessage to MemoryStream 问题的几个答案。

解决方案 1:使用使用私有方法的方法会导致电子邮件部分编码错误: https ://stackoverflow.com/a/8826833

解决方案 2:使用此解决方案没有编码问题,您将其发送到拾取目录,然后将其读回: https ://stackoverflow.com/a/14350088

我非常不喜欢我需要写入一个临时文件才能使其正常工作的事实。有谁知道纯 MemoryStream 解决方案如何弄乱一些编码。

我正在测试的邮件是这样的:

var mailMessage = new MailMessage();
mailMessage.Subject = "HEADER WITH SPECIAL ÆØÅ";
mailMessage.Body = "TEST";

Attachment att = new Attachment(@"C:\AttachmentWithSpecial ÆØÅ.pdf");
mailMessage.Attachments.Add(att);
mailMessage.From = new MailAddress("test@test.com", "NameÆØÅ");
mailMessage.To.Add(new MailAddress("test@test.com", "NameÆØÅ"));

总结一下:

  • 如果我使用标准 SMTP 发送此消息,它看起来不错。
  • 如果我使用 SendRawEmail 发送它,如果我使用解决方案 2 生成内存流看起来不错
  • 如果我使用 SendRawEmail 发送它,如果我使用解决方案 1 生成内存流,则会出现编码问题。

对于编码问题,我的意思是“ø”显示为

在此处输入图像描述

4

3 回答 3

2

不幸的是 MailMessage 对象是错误的并且界面很差。

好消息是 .NET 4.5 在 Send() 中使用 allowUnicode 标志部分修复了它(不幸的是,Send 方法仍然是私有的)

下面是修改后的“解决方案1”。它以与“解决方案 2”相同的方式对主题进行编码。仅限 .NET Framework 4.5。

private static MemoryStream ConvertMailMessageToMemoryStream(MailMessage message)
{
    Assembly systemAssembly = typeof(SmtpClient).Assembly;
    Type mailWriterType = systemAssembly.GetType("System.Net.Mail.MailWriter");
    const BindingFlags nonPublicInstance = BindingFlags.Instance | BindingFlags.NonPublic;
    ConstructorInfo mailWriterContructor = mailWriterType.GetConstructor(nonPublicInstance, null, new[]  typeof(Stream) }, null);

    MethodInfo sendMethod = typeof(MailMessage).GetMethod("Send", nonPublicInstance);
    MethodInfo closeMethod = mailWriterType.GetMethod("Close", nonPublicInstance);
    using (MemoryStream memoryStream = new MemoryStream())
    {
        object mailWriter = mailWriterContructor.Invoke(new object[] { memoryStream });
        //AssertHelper.IsTrue(sendMethod.GetParameters().Length > 2, ".NET framework must be 4.5 or higher in order to properly encode email subject.");
        sendMethod.Invoke(message, nonPublicInstance, null,
            new[] { mailWriter, true, false },
            null);
        closeMethod.Invoke(mailWriter, nonPublicInstance, null, new object[] { }, null);
        return memoryStream;
    }
}
于 2014-11-24T17:53:53.357 回答
1

您是否尝试明确指定主题/正文和邮件地址的编码?

我猜想当 .NET 将邮件写入文件夹时,它可以以某种方式定义正确的编码(或者文件阅读器可能以某种方式找到正确的编码来转换数据)。在内存中,所有内容都采用默认编码,这对您不起作用。

于 2013-04-05T16:45:52.260 回答
0
message.BodyEncoding = message.SubjectEncoding = message.HeadersEncoding = Encoding.UTF8;
于 2013-04-17T15:32:00.253 回答