在SmtpClient /主题MAILMESSAGE编码(Subject encoding on S

2019-08-31 07:35发布

我试图发送包含使用非ASCII字符的电子邮件SmtpClientMailMessage类。

我使用的是外部邮件服务( MailChimp )和我的一些电子邮件通过它们的SMTP服务器都被拒绝。 我曾接触过他们,这是他们说什么:

它出现的主题行被Base64编码,然后引用打印编码,这通常要细,但其中一个字符被横跨两行破碎。 所以,当你的主题行的时间长一点,才能被正确处理,它的分解到两行。 当使用UTF-8引述主题行打印,不应该字符串线之间被打破。 取而代之的是线应短,这样完整的字符串仍然在一起。 在这种情况下,没有发生,所以字符表示单个字符被跨多个线断裂,因此该字符串不是有效UTF-8引用可打印的编码。

有问题的主题如下:

Subject: XXXXXXX - 5 personnes vous ont nommé guide

这是在UTF-8 / Base64编码:

Subject: WFhYWFhYWCAtIDUgcGVyc29ubmVzIHZvdXMgb250IG5vbW3DqSBndWlkZQ==

因为该标头将超过特定的最大长度(我不能确定它是否是引用打印编码和其每行76个字符,或者SMTP头限制限制),编码和分割后,报头将成为:

Subject: =?utf-8?B?WFhYWFhYWCAtIDUgcGVyc29ubmVzIHZvdXMgb250IG5vbW3D?=
 =?utf-8?B?qSBndWlkZQ==?=

显然,这使得解码时(因为第一线不能被解码为有效的字符串)的问题。 我不知道我完全理解这个问题,我有以下问题:

  • 为什么?UTF-8?B' 部分重复? 如果不是QP编码分割线,因此它的头不应该重复以前发生的呢?
  • QP-解码之后,我们不应该结束了一个有效的1行Base64编码字符串?
  • 有一个在第二行开始的空白,这是QP编码外,可这是什么问题?
  • 是编码器坏了,或者是解码器?

还要注意的是一些其他SMTP服务器将接受此消息,不过,这并不意味着它是有效的。

作为一种变通方法,我试图禁用Base64编码,这显然是不必要的,然而,类MAILMESSAGE具有BodyTransferEncoding控制该编码,但只适用于消息的主体部分属性。 无属性似乎能控制主题的“转移”的编码。

Answer 1:

这被确认为在MSDN论坛中的错误:
http://social.msdn.microsoft.com/Forums/vstudio/en-US/4d1c1752-70ba-420a-9510-8fb4aa6da046/subject-encoding-on-smtpclientmailmessage

而一个bug提交于Microsoft连接: https://connect.microsoft.com/VisualStudio/feedback/details/785710/mailmessage-subject-incorrectly-encoded-in-utf-8-base64

一种解决办法是给MAILMESSAGE的SubjectEncoding设定为其他编码,如ISO-8859-1。 在这种情况下,受试者将在其避免了问题引用Printable(未Base64编码)进行编码。



Answer 2:

一个更好的解决方案是使用Encoding.Unicode而不是Encoding.UTF8SubjectEncoding

看来,作为微软执行只是忽略UTF-16能够在两个多字节编码字符(如看到的现实为什么C#使用UTF-16字符串? ),稳定的字符大小可以帮助。

我已经看到了这个上使用https://gist.github.com/dbykadorov/9047455 。



Answer 3:

我对这个问题的解决方案是某种绝招!

我用在邮件主题波斯语和我向使用SmtpClient我的邮箱:在.NET框架4.5.2。 所接收的消息受试者显示在某些位置的一些垃圾话,例如第18和第38字在字符串对象。 不论主题是。

然后我试图插入在这些位置,并重新发送邮件,结果是非常好的后一些空格(字符32)。 unicode的受试者示出如预期。

所以我写了一个函数在我需要的位置(避免插入单词的空格内),这样插入6位:

private static string InsertSpacesBetweenWords(this string subject , int where)
    {
        int l;
        int i=1;
        string[] s = subject.Split(new string[] { " " },  StringSplitOptions.RemoveEmptyEntries);
        string output = "";

        if (s.Length > 0) output += s[0] + " ";
        l = output.Length;
        bool done = false;

        while (i < s.Length)
        {
            if (!done)
            {
                if ((s[i] + output).Length > where)
                {
                    for (int j = output.Length; j < where + 6; j++)
                        output += " ";
                    done = true;
                }
            }
            output += s[i] + " ";
            i++;
        }
        return output;
    }

然后我用这个函数转换邮件主题:

mail.Subject = mySubject.InsertSpacesBetweenWords(38).InsertSpacesBetweenWords(18);

有趣的一点是,Gmail和雅虎邮箱(可能还有其他基于Web的邮件系统)忽略额外的空间和展示主题预期。



文章来源: Subject encoding on SmtpClient/MailMessage