摘要
某台运行 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 能力不匹配触发最终退信
这是一个非常典型、也非常具有教学价值的实战案例。