SmtpClient(.NET)未按照RFC 2047对邮件头进行编码

SmtpClient(.NET)未按照RFC 2047对邮件头进行编码,.net,encoding,smtpclient,.net,Encoding,Smtpclient,我正在使用.NETSmtpClient发送主题可能包含ASCII范围以外字符的电子邮件。定义电子邮件文本包含特殊字符时应如何编码。以下是电子邮件标题中主题的示例: 主题:Votre Enregistrment numéro 123 编码至ISO-8859-1后,应为: 主题:=?iso-8859-1?Q?Votre=20enregistrement=20num=E9ro=20123?= 其中所有特殊字符,包括?、=(及其他)和空格,均使用=xx转义序列进行编码 但是,当我查看SmtpClient

我正在使用.NET
SmtpClient
发送主题可能包含ASCII范围以外字符的电子邮件。定义电子邮件文本包含特殊字符时应如何编码。以下是电子邮件标题中主题的示例:

主题:Votre Enregistrment numéro 123

编码至ISO-8859-1后,应为:

主题:=?iso-8859-1?Q?Votre=20enregistrement=20num=E9ro=20123?=

其中所有特殊字符,包括
=
(及其他)和空格,均使用
=xx
转义序列进行编码

但是,当我查看
SmtpClient
生成的内容时,我发现它没有逃逸空白,这意味着邮件客户端接收到以下标题:

主题:=?iso-8859-1?Q?Votre注册编号=E9ro 123?=

这意味着(我的阅读)RFC 2047的编码被破坏。一些电子邮件客户端对这种错误的编码非常满意(事实上,大多数都包括Outlook和gmail),但有一个(wanadoo.fr)以原始格式显示邮件头。这不是用户应该看到的:-(

是否有任何已知的解决此问题的方法

注意:SmtpClient的.NET 4.0实现按预期对主题进行编码,产生以下正确输出:

主题:=?Windows-1252?Q?Votre\u Enregistration\u num=E9ro\u 123?=


问题是SMTP发送者使用了一个通用的引用可打印编码器,它不知道任何关于头的特殊模式的信息,所以我怀疑没有简单的解决方法

我要做的是检查是否有任何非ASCII字符,这样主题就会被编码,如果有,用下划线替换任何空格(ASCII 95)。这应该可以工作,因为下划线字符应该由邮件阅读器解释为空格,但不应该由朴素编码器进行编码。也许此代码可以工作:

string FixSubject(string subject)
{
    foreach (char ch in subject)
        if (ch > '\x007f')
            return subject.Replace(" ", "_");
    return subject;
}

另一种可能是将电子邮件的编码设置为Unicode或UTF-8,因为这似乎会触发标题的Base64编码,而不是引用的可打印。使用不同的编码器应该可以完全避免此错误。

这在
SmtpClient
的NET 4.0实现中得到修复。它按预期对主题进行编码,从而产生此输出是正确的:

主题:=?Windows-1252?Q?Votre\u Enregistration\u num=E9ro\u 123?=


我没有为您提供解决方案,但我将证实您对RFC 2047的解释,特别是第4.2(3)节:“特别是,空格和制表符不能在编码单词中表示为它们自己。”(请注意,您也可以使用下划线代替=20)+1对于重大问题/提出的问题,并且您实际引用了相关的RFC,您已经完成了准备工作,仍然有一个问题需要解决您指定了消息编码还是让SmtpClient以默认方式工作?Joe、Curtik和Timoers:谢谢您的评论。Timores:不,我让.NET选择消息的编码方式。的确,将主题中的空格替换为下划线将生成正确的标题。在.NET 4.0中不再需要这种攻击。