摘要

某台运行 Postfix 的 Linux 服务器在连续多天内无法向自建 Mailcow 邮件服务器发送系统告警邮件,邮件队列持续增长。表面错误为 DNS 解析失败(4.4.3 Host not found),在 DNS 修复后仍存在投递异常。最终发现是 SMTPUTF8 协议能力不匹配导致部分邮件被永久拒绝(5.6.7)。

本文完整记录该事故的诊断路径与修复策略。


1. 事故现象

Postfix 日志中持续出现:

dsn=4.4.3
status=deferred
Host or domain name not found. Name service error for name=mail.example.net type=A

邮件队列中积压多封系统邮件(root → admin),时间跨度超过 5 天。


2. 第一层问题:DNS 故障导致长期队列堆积

检查发现系统的 /etc/resolv.conf 曾指向错误的网关地址(例如 192.168.0.1 而不是实际使用的 192.168.1.1),导致 Postfix 在那段时间无法解析 mail.example.net

DNS 修复后:

getent ahosts mail.example.net
dig +short A mail.example.net @1.1.1.1

均返回正确 IPv4 地址,说明系统 DNS 已恢复。

但邮件仍不断失败,是因为 Postfix 会对 4.x.x 错误进行指数退避式重试,旧邮件会在之后被不断重新投递。


3. 强制重投递后发现新的真实错误

执行:

postqueue -f

后,大量历史邮件一次性成功发送。

但新发送的测试邮件仍然失败,并在 /var/log/mail.log 中出现:

dsn=5.6.7
status=bounced
SMTPUTF8 is required, but was not offered by host

这意味着:
DNS 和网络已经恢复,但 SMTP 协议层存在不兼容。


4. 根本原因:SMTPUTF8 协议能力不匹配

SMTPUTF8 是 RFC 6531 定义的扩展,用于支持 UTF-8 邮件地址和头部(EAI)。

发送端(Postfix)在某些邮件上判定“必须使用 SMTPUTF8”,但接收端(Mailcow 的 Postfix)在 EHLO 中并未声明支持:

250-PIPELINING
250-SIZE
250-AUTH
250-8BITMIME
250-DSN
(没有 SMTPUTF8)

于是发送端拒绝投递并直接 bounce。


5. 最稳妥的修复方案:关闭发送端 SMTPUTF8

在这种架构下,该 Postfix 仅用于发送系统通知(ASCII 地址),不需要 EAI 能力,因此可以安全关闭 SMTPUTF8 要求。

执行:

postconf -e 'smtputf8_enable = no'
systemctl restart postfix

之后再次发送包含 UTF-8 标题的测试邮件,投递成功。


6. 清理历史队列

DNS 错误时期积压的邮件可直接清空:

postsuper -d ALL

或删除单个残留队列项。


7. 经验总结

本次事故体现了两个容易被忽略的层面:

(1)DNS 错误的“滞后效应”

Postfix 对 4.x.x 错误会长期重试,即使 DNS 已恢复,也会不断重放历史失败邮件,制造“系统仍然故障”的错觉。

(2)SMTPUTF8 是隐藏的协议炸弹

即使 SMTP 连接成功,如果 EAI 能力不匹配,也会在 DATA 阶段被永久拒绝(5.x.x),与 DNS、TLS 无关。


8. 最终稳定状态

系统最终达成:

  • DNS 解析正常
  • Postfix → Mailcow SMTP over TLS 连接正常
  • SMTPUTF8 在发送端关闭
  • 邮件队列清空
  • 系统告警邮件稳定投递

结语

在复杂邮件系统中,DNS、队列机制与 SMTP 扩展协议会叠加出非常迷惑的故障表现。
只有逐层剥离(解析 → 连接 → 协议能力 → 队列行为),才能准确定位真实故障点。

这次事件的根因不是单点失败,而是:

DNS 错误触发堆积 + SMTPUTF8 能力不匹配触发最终退信

这是一个非常典型、也非常具有教学价值的实战案例。

Leave a Reply

Your email address will not be published. Required fields are marked *