實際案例:某客戶的架構是 PMG(Proxmox Mail Gateway)放在前端過濾垃圾郵件,再把信轉交給內部的 Zimbra。某天開始陸續有使用者反應,部分外部寄來的信收不到,寄件者那邊收到退信通知。
到 PMG 查郵件記錄,退信原因都是同一句:SMTPUTF8 is required, but was not offered by host。這篇整理這個錯誤的成因、為什麼只有部分信件會被退,以及在 PMG 上正確的處理方式。
錯誤訊息
在 PMG 的 /var/log/mail.log(或網頁介面的「追蹤中心」)可以看到類似這樣的記錄:
Mar 27 10:15:32 pmg postfix/smtp[12345]: 4ABCD1234567: to=<user@example.com>, relay=mail.example.com[192.168.1.20]:25, delay=0.35, delays=0.1/0/0.2/0, dsn=5.6.7, status=bounced (SMTPUTF8 is required, but was not offered by host mail.example.com[192.168.1.20])
relay= 後面是 PMG 要轉交的下一站,也就是內部的 Zimbra。意思是:這封信需要 SMTPUTF8,但 Zimbra 沒有宣告支援,所以 PMG 直接退信。
較新版的 Postfix 把這段訊息改寫成 message requires SMTPUTF8, but no server was found that supports SMTPUTF8,意思相同,狀態碼一樣是 5.6.7。
SMTPUTF8 是什麼
SMTPUTF8 是 RFC 6531 定義的 SMTP 擴充功能,屬於 EAI(Email Address Internationalization,郵件地址國際化)的一部分,讓郵件地址與表頭可以直接使用 UTF-8,例如中文的帳號或網域名稱。
運作方式是:
- 收件伺服器在
EHLO回應中列出SMTPUTF8,表示支援 - 寄件端在
MAIL FROM指令後面加上SMTPUTF8參數,表示這封信需要 UTF-8 處理
Postfix 3.0 起內建 SMTPUTF8 支援,smtputf8_enable 預設是 yes。PMG 底層就是 Postfix,所以 PMG 預設也是開啟的。
為什麼只有部分信件被退
依 Postfix 官方文件(SMTPUTF8_README),當 Postfix 收到一封帶有 SMTPUTF8 要求的信,要轉交給不支援 SMTPUTF8 的下一站時,只有在下列條件都成立時才會照常投遞:
- 所有表頭的值都沒有 UTF-8
- 信封寄件者地址沒有 UTF-8
- 這次投遞的信封收件者地址沒有 UTF-8
只要有一項不符合,就會把信退回。整個流程是:
- PMG 在
EHLO回應中宣告支援 SMTPUTF8 - 外部寄件伺服器(例如 Gmail)看到後,寄信時帶上
SMTPUTF8要求 - 這封信的表頭裡有未經編碼的 UTF-8 文字,例如中文的寄件者名稱或主旨
- PMG 過濾完要轉交給 Zimbra,但 Zimbra 的
EHLO回應沒有SMTPUTF8 - 依上面的規則,PMG 只能退信
所以同一個寄件者,有些信正常、有些被退,差別就在寄件端有沒有帶 SMTPUTF8 要求、表頭裡有沒有 UTF-8。這也是這個問題容易被忽略的原因:大部分信件都正常,只有零星的退信。
確認下一站是否支援 SMTPUTF8
從 PMG 連到 Zimbra 的 25 埠,送出 EHLO 看回應:
telnet 192.168.1.20 25
220 mail.example.com ESMTP Postfix
EHLO pmg.example.com
250-mail.example.com
250-PIPELINING
250-SIZE 52428800
250-ETRN
250-STARTTLS
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 DSN
清單裡沒有 SMTPUTF8,就是不支援。輸入 QUIT 離開。
Zimbra 的 MTA 雖然也是 Postfix,但並不支援 SMTPUTF8,在 Zimbra 端開啟也無法解決(Zimbra 論壇有使用者試過,改了設定仍無效)。Proxmox 開發團隊在讓這個選項可以調整的修補說明裡,也直接列出 Zimbra、OpenXchange、MS Exchange 是常見不支援 SMTPUTF8 的下游伺服器。
處理方式:在 PMG 停用 SMTPUTF8
既然下游不支援,就讓 PMG 也不要宣告支援。PMG 不宣告 SMTPUTF8 之後,寄件端就不會帶 SMTPUTF8 要求,會改用傳統方式寄送(表頭以 RFC 2047 編碼),PMG 轉給 Zimbra 時也就不會再被擋下。
PMG 7.3 以後:用 pmgsh 設定
PMG 7.3 起,SMTPUTF8 是 PMG 本身的設定項目(/etc/pmg/pmg.conf 的 mail 區段 smtputf8),可以用 pmgsh 修改:
# 查看目前設定
pmgsh get /config/mail
# 停用 SMTPUTF8
pmgsh set /config/mail -smtputf8 0
透過 API 修改設定時,PMG 會自動重新產生 Postfix 設定檔並重新啟動服務,不需要另外執行其他指令。這個選項目前網頁介面上沒有,要用指令設定。
叢集環境在主節點設定即可,設定會同步到其他節點。
確認 Postfix 已經套用:
postconf smtputf8_enable
輸出 smtputf8_enable = no 就完成了。
為什麼不直接用 postconf -e
網路上常見的做法是:
postconf -e 'smtputf8_enable=no'
systemctl restart postfix
這樣當下確實有效,但 PMG 的 Postfix 設定檔 /etc/postfix/main.cf 是由範本產生的。之後只要在網頁介面改任何設定、更新套件,或執行 pmgconfig sync,main.cf 就會依範本重新產生,手動加的這一行會消失,問題又會回來,而且通常是過了一段時間才發生,很難聯想到原因。
注意:PMG 上的 Postfix 設定請勿直接修改 main.cf,要用 PMG 的設定項目或自訂範本。
PMG 7.3 以前:使用自訂範本
舊版 PMG 沒有 smtputf8 這個設定項目,要改用自訂範本。依 PMG 管理手冊,預設範本在 /var/lib/pmg/templates/,請勿直接修改,要複製到 /etc/pmg/templates/ 再改:
cp /var/lib/pmg/templates/main.cf.in /etc/pmg/templates/main.cf.in
在 /etc/pmg/templates/main.cf.in 加入一行:
smtputf8_enable = no
重新產生設定檔並重新啟動服務:
pmgconfig sync --restart 1
自訂範本會跟著叢集同步到其他節點。之後升級到 7.3 以上,建議改用 pmgsh 的設定,並把自訂範本移除,以免日後 PMG 更新範本內容時,自訂範本沒有跟著更新。
停用後的影響
- 已經退回的信不會自動重送,要請寄件者重新寄一次
- PMG 不再接受非 ASCII 的郵件地址,例如帳號是中文的 EAI 地址。目前台灣的企業與一般使用者幾乎沒有在用這類地址,影響很小
- 中文主旨、中文寄件者名稱、中文附件檔名都不受影響,這些本來就可以用傳統的編碼方式傳送
結論
PMG 預設開啟 SMTPUTF8 本身沒有問題,問題在於前後兩站的能力不一致:前端宣告支援,下游卻不支援,中間的 PMG 只能退信。PMG 放在 Zimbra、Exchange 前面的架構,建議在 PMG 停用 SMTPUTF8,讓整條郵件路徑的能力一致。
修改時記得用 PMG 自己的設定方式,直接改 main.cf 遲早會被覆蓋。
參考資料
- Postfix SMTPUTF8 Support(SMTPUTF8_README)
https://www.postfix.org/SMTPUTF8_README.html - Proxmox Mail Gateway 管理手冊
https://pmg.proxmox.com/pmg-docs/pmg-admin-guide.html - pmg-devel:config: make smtputf8 configurable through the API
https://lists.proxmox.com/pipermail/pmg-devel/2023-March/002274.html - Zimbra 論壇:smtputf8_enable 相關討論
https://forums.zimbra.org/viewtopic.php?t=65075 - 開源郵件閘道伺服器 - Proxmox Mail Gateway
https://blog.jason.tools/2018/01/proxmox-mail-gateway.html



