我正在尝试使用下面的代码来发送消息System.Net.Mail
,有时会得到像'=?utf-8?B?W3AxM25dIEZpbGV...'
(修剪过)这样的主题.这是被称为的代码:
MailMessage message = new MailMessage() { From = new MailAddress("someone@somewhere.com", "Service"), BodyEncoding = Encoding.UTF8, Body = body, IsBodyHtml = true, ReplyTo = new MailAddress("do.not.reply@somewhere.com"), SubjectEncoding = Encoding.UTF8 }; foreach (string emailAddress in addresses) { message.To.Add(new MailAddress(emailAddress.Trim(), "Person")); } message.Subject = subject;
我想强调,这不会一直发生.
我究竟做错了什么?
当您的主题包含ASCII范围之外的字符时,邮件软件必须对它们进行编码(RFC2822邮件不允许标题中包含非ASCII字符).有两种方法可以做到这一点:
引用的可打印(主题以"=?utf-8?Q"
)开头
Base64(主题以"=?utf-8?B"
)开头
似乎框架已经确定Base64编码比引用的可打印编码更有效(=更短).当主题包含ASCII范围之外的相对多个字符时,这是有意义的.
回答你的问题:你没有做错任何事.这就是具有非ASCII字符的互联网邮件应该是这样的.当然,读取此类邮件的软件应检测并解码此类主题字段.
当我调试相同的问题时,我遇到了这个帖子,根据我的进一步调查,我可以为Andreas提供另一种解释:
问题可能是您的电子邮件客户端软件(在我的情况下,Outlook 2003)错误地解码主题行.换句话说,它是Outlook中的一个错误,而不是.NET或您的程序.
如果您使用这样的主题值(字母"c"重复256次),它在Outlook中显示正常:
subject = New String("c"c, 256)
同样,如果您使用这样的主题(字母"c"重复178次,附加了Unicode非破坏空格字符),它也会在Outlook中按预期显示:
subject = New String("c"c, 178) + System.Text.Encoding.UTF8.GetChars(New Byte() {194, 160})
但是,以下主题在Outlook中显示为"=?utf-8?B" - 预填垃圾:
subject = New String("c"c, 179) + System.Text.Encoding.UTF8.GetChars(New Byte() {194, 160})
不同之处在于,当UTF-8编码时,该第三主题行是256字节.我假设Outlook必须在显示它之前将主题行截断为255个字符...除了它通过将编码的字符串截断为255个字节(这会切断编码终结符("?="))这样做会很好,使它不可解码.
这是Outlook中的错误,而不是您的邮件提供商或.NET; 通过右键单击消息列表中的消息并从上下文菜单中选择"选项...",然后在"Internet标题"框中向下滚动,可以在Outlook中看到完整的,未截断的UTF-8编码主题行.你看到以"主题:"开头的行.
与Andreas建议的情况相反,问题不仅在有许多非ASCII字符时,而且在有一个或多个非ASCII字符且主题行很长的情况下表现出来.解决方法可能是使用较短的主题行或删除主题中的所有非ASCII字符.
(这个bug对我来说特别棘手,因为,如上所述,问题数据中没有明显的非ASCII字符 - 只有几个不间断的空格.当你打印出来时,这些显示与常规ASCII空格相同此外,如果在Visual Studio调试器中更改字符串变量的值,它会以静态方式将它们替换为常规空格.)