2019/01/21

[筆記] .Net SmtpClient 發出的信,特定中文寄件人在特定收信軟體上亂碼問題

某天 PM 開了一張問題單,附了這張圖,說寄件人顯示名稱出現亂碼



可是我的電腦都不會啊

經 PM 說明,才知道公司的 web mail 跟 gmail 信箱才會這樣,用郵件軟體等似乎不會有問題

說是郵件軟體,其實也只測試了 thunderbird

實際進去看郵件的原始碼,發現 SmtpClient 發出來的信原始碼如下:



而使用郵件軟體(thunderbird)發出來的郵件原始碼長這樣:



後者的寄件人是正常的,前者的寄件人會在特定情況下造成亂碼

查 email 的規格時看到在 RFC2047 第二點 Syntax of encoded-words 中提到

編碼後的格式為:

"=?{charset}?{encoding}?{encoded_text}?="

stackoverflow 這篇文章中提到,RFC2822 規格中當文字在 ASCII 編碼的範圍內時,會採取兩種作法:

  • Quoted Printable (subject starts with "=?utf-8?Q")
  • Base64 (subject starts with "=?utf-8?B")

但詳細規範應該是列在 RFC2047 的第四章中,以下節錄:
4.1. The "B" encoding

   The "B" encoding is identical to the "BASE64" encoding defined by RFC
   2045.

4.2. The "Q" encoding

   The "Q" encoding is similar to the "Quoted-Printable" content-
   transfer-encoding defined in RFC 2045.  It is designed to allow text
   containing mostly ASCII characters to be decipherable on an ASCII
   terminal without decoding.
所以說 SmtpClient 對寄件者名稱是用了 Quoted Printable 編碼方式來進行處理,然後轉碼後的文字在 web mail 中轉回來轉壞了變成了 PM 看到的亂碼
順道紀錄一下 ,Quoted Printable的線上解碼工具https://www.webatic.com/quoted-printable-convertor

但是 .Net 的 MailAddress 並不能指定要使用 Quoted Printable 或是 Base64

不過注意,只要給定的寄件者名稱為 ascii 範圍內的文字,就不會被 .Net 自動包 Quoted Printable

所以解法很簡單,先自己將寄件者轉成 base64 字串然後串上編碼後的格式就好了:

 
string senderMail = ""; //計件人地址
string senderName = ""; //寄件人顯示名稱
string senderNameb64Enc = Convert.ToBase64String(Encoding.UTF8.GetBytes(senderName));
new MailMessage() {
    From = new MailAddress(senderMail, $"=?UTF-8?B?{senderNameb64Enc}?=")
};




沒有留言:

張貼留言