Кодировка темы в SmtpClient/MailMessage

Я пытаюсь отправить электронные письма, содержащие символы, отличные от ASCII, используя классы SmtpClient и MailMessage.

Я использую внешнюю почтовую службу (MailChimp), и некоторые из моих писем были отклонены их SMTP-сервером. Я связался с ними, и вот что они ответили:

Похоже, что строка темы кодируется Base64, а затем кодируется Quoted-Printable, что обычно должно быть хорошо, но один из символов разбит на две строки. Поэтому, когда ваши строки темы немного длиннее, для правильной обработки они разбиваются на две строки. При использовании UTF-8 в кавычках для печати в строке темы строки символов не должны разрываться между строками. Вместо этого строку следует закоротить так, чтобы вся строка символов оставалась вместе. В данном случае этого не происходит, поэтому строка символов, представляющая один символ, разбивается на несколько строк и, следовательно, не является допустимой кодировкой UTF-8 для печати в кавычках.

Проблемным предметом является следующее:

Subject: XXXXXXX - 5 personnes vous ont nommé guide

То есть в UTF-8/Base64:

Subject: WFhYWFhYWCAtIDUgcGVyc29ubmVzIHZvdXMgb250IG5vbW3DqSBndWlkZQ==

Поскольку этот заголовок превысит определенную максимальную длину (я не уверен, является ли это кодировкой Quoted-Printable и ее ограничением в 76 символов на строку или ограничением заголовка SMTP), после кодирования и разделения заголовок станет следующим:

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

По-видимому, это вызывает проблему при декодировании (поскольку первая строка не может быть декодирована в действительную строку). Я не уверен, что полностью понимаю проблему, и у меня есть следующие вопросы:

  • Почему ?utf-8?B? часть повторяется? Разве QP-кодирование не должно происходить перед разделением строки и, следовательно, его заголовок не должен повторяться?
  • Разве после QP-декодирования мы не должны получить действительную строку Base64 из одной строки?
  • В начале второй строки есть пробел, который находится за пределами кодировки QP, может ли это быть проблемой?
  • Сломался энкодер или декодер?

Также обратите внимание, что некоторые другие SMTP-серверы примут это сообщение, хотя это не означает, что оно действительно.

В качестве обходного пути я попытался отключить кодировку Base64, которая, по-видимому, не нужна, однако класс MailMessage имеет BodyTransferEncoding, которое управляет этой кодировкой, но только для основной части сообщения. Никакое свойство, по-видимому, не управляет "переносным" кодированием субъекта.


person Xavier Poinas    schedule 16.04.2013    source источник
comment
Здесь такая же проблема. Я могу воспроизвести это, когда заголовок темы письма кодируется с помощью Base64 или QuotedPrintable (EncodedWord RFC2047)   -  person Gonzalo Gallotti    schedule 05.02.2019


Ответы (4)


Это было подтверждено как ошибка на форумах MSDN:
http://social.msdn.microsoft.com/Forums/vstudio/en-US/4d1c1752-70ba-420a-9510-8fb4aa6da046/subject-encoding-on-smtpclientmailmessage

И в Microsoft Connect была зарегистрирована ошибка: https://connect.microsoft.com/VisualStudio/feedback/details/785710/mailmessage-subject-incorrectly-encoded-in-utf-8-base64

Одним из обходных путей является установка для SubjectEncoding MailMessage другой кодировки, например ISO-8859-1. В этом случае тема будет закодирована в Quoted Printable (не Base64), что позволяет избежать проблемы.

person Xavier Poinas    schedule 24.07.2013
comment
Обходной путь не работает для меня. Мои символы, отличные от ascii, по-прежнему отображаются как странные символы в теме. :( - person PussInBoots; 24.06.2015
comment
У вас может быть другая проблема. У меня были не странные символы, а электронные письма, которые отклонялись некоторыми SMTP-серверами. - person Xavier Poinas; 25.06.2015

Лучшее решение — использовать Encoding.Unicode вместо Encoding.UTF8 для SubjectEncoding.

Похоже, что, поскольку реализация Microsoft просто игнорирует реальность того, что UTF-16 может кодировать символы более чем двумя байтами (как показано на Почему C# использует кодировку UTF-16 для строк?), помогает стабильный размер символов.

Я видел, как это использовалось на https://gist.github.com/dbykadorov/9047455.

person Pablo Montilla    schedule 15.10.2016

Мое решение этой проблемы - это какой-то трюк!

Я использую персидский язык в теме письма и отправляю почту с помощью SmtpClient в .Net framework 4.5.2. тема полученного сообщения показывает некоторые слова-мусоры в определенных позициях, например, 18-й и 38-й символы в строке темы. каким бы ни был предмет.

Затем я попытался вставить пробелы (символ 32) в эти позиции, и после повторной отправки почты результат был очень хорошим. тема Юникода отображалась, как и ожидалось.

поэтому я написал функцию для вставки 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 и Yahoo (и, возможно, другие почтовые системы в Интернете) игнорируют лишние пробелы и отображают тему, как и ожидалось.

person Saeed Mousavi    schedule 26.02.2016

Добавление двух пробелов к теме помогло мне. Не спрашивайте, почему.

var mail = new MailMessage(from, to);
mail.Subject = subject + new string(new char[] { '\u2000', '\u2000' });
mail.SubjectEncoding = Encoding.UTF8;

введите здесь описание изображения

person Joel Wiklund    schedule 24.09.2020