2013-04-16 4 views
8

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

Я использую внешнюю почтовую службу (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-декодирования, не должно быть, мы получим допустимую строку Base64 с 1 строкой?
  • В начале второй строки есть пробел, который находится за пределами QP-кодировки, может быть проблема?
  • Является ли кодировщик сломанным, или это декодер?

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

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

ответ

5

Это было подтверждено как ошибка в форумах 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 (not Base64), который позволит избежать проблемы.

+0

Работа для меня не работает. Мои персонажи не-ascii по-прежнему отображаются как «странные-выглядящие символы» в теме. :( – PussInBoots

+0

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

+0

О, хорошо. – PussInBoots

0

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

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

0

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

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

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

Смежные вопросы