SmtpClient(.NET)不对符合RFC 2047的邮件头进行编码

Pie*_*aud 5 .net encoding smtpclient

我正在使用.NET SmtpClient发送电子邮件,其中主题可能包含ASCII范围之外的字符.在RFC 2047定义了如何当它含有特殊字符的电子邮件正文应进行编码.以下是电子邮件标题中主题的示例:

Subject: Votre enregistrement numéro 123

在编码为ISO-8859-1之后,这应该成为:

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

所有特殊字符,包括?,=(和其他人)和白色空间,使用编码的=xx转义序列.

但是,当我查看SmtpClient产生的内容时,我发现它不会逃避空白区域,这意味着邮件客户端会收到此标头:

Subject: =?iso-8859-1?Q?Votre enregistrement num=E9ro 123?=

这意味着编码在(我的阅读)RFC 2047中被打破.一些电子邮件客户端对这种不正确的编码(其中大多数,实际上包括Outlook和gmail)非常满意,但是一个(wanadoo.fr)以原始格式显示标题.这不是用户应该看到的:-(

这个问题有没有已知的解决方法?

注意: .NET 4.0实现SmtpClient按预期编码主题,产生此输出,这是正确的:

Subject: =?Windows-1252?Q?Votre_enregistrement_num=E9ro_123?=

Gab*_*abe 3

问题在于 SMTP 发送方使用通用的引用打印编码器,该编码器不知道有关标头的特殊模式的任何信息,因此我怀疑不会有简单的解决方法。

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

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

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