MIME 信件標題亂碼問題
某一天專案升級 Java 8 的過程中,我遇到寄出的 Email 標題變成亂碼。乍看像是編碼設定壞掉,但實際往下查才發現,問題不只是字串是不是 UTF-8,而是信件標頭本來就必須遵守 MIME 編碼格式。
這篇把這個問題整理成比較好理解的版本,之後如果又遇到中文標題、寄件者名稱亂碼,應該可以更快判斷原因。
為什麼主旨會亂碼
Email 並不是單純把一串 UTF-8 文字塞進去就結束。像 Subject、From 顯示名稱這些欄位,屬於信件 header,header 要符合 MIME 的 encoded-word 格式,例如:
|
|
這段格式可以拆成:
- UTF-8:使用的字元編碼。
- B:編碼方式,B 代表 Base64,Q 代表 Quoted-Printable。
- 後面那一段:實際被編碼過的內容。
也就是說,很多時候不是應用程式本身不知道 UTF-8,而是你把原始中文直接塞進 header,Mail Client 不一定會照你想的方式解讀。
PHP 的處理方式
如果是自己組 header,可以手動把標題包成 MIME encoded-word:
|
|
將上面一句加進去之後,中文標題通常就能正常顯示。
Java 的處理方式
如果是 JavaMail,建議不要自己手刻 MIME 格式,而是交給函式庫處理:
|
|
這樣做的好處是比較不容易在特殊字元、空白或多段字串時出錯。
哪些欄位常常一起中招
除了 Subject 之外,下面欄位也很常遇到相同問題:
- 寄件者名稱 From
- 收件者顯示名稱 To
- 副本 Cc
- 附件檔名
只要這些位置出現中文、日文、特殊符號,就要懷疑是不是 MIME header 編碼沒處理。
常見誤解
1. 內文正常,不代表主旨也正常
Email body 和 Email header 是兩件事。你可能內文 UTF-8 正常,但主旨還是亂碼,因為兩者處理規則不同。
2. 不是所有亂碼都是 SMTP 問題
有時候 SMTP Server 沒問題,真正有問題的是應用程式在組信件標頭時沒有正確 encode。
3. 手動 Base64 不是萬靈丹
若你使用成熟的 mail 函式庫,優先交給函式庫處理,會比自己硬湊格式更安全。
小結
信件標題亂碼的核心原因,通常不是 UTF-8 壞掉,而是 MIME header 沒有按照規則編碼。簡單記法就是:
- 主旨、寄件者名稱這類 header 要特別處理。
- PHP 可手動組 =?UTF-8?B?…?=。
- Java 盡量用 MimeUtility.encodeText() 之類的內建工具。
之後如果再遇到信件主旨亂碼,先檢查 MIME header,比直接懷疑資料庫或 SMTP 服務更有效率。