2026/07/22

邮箱错误码全景:SMTP 三位数、增强状态码和 DSN 的统一读法

把 SMTP 3-digit reply、RFC 3463 enhanced status code 和 RFC 3464 DSN 放进同一套诊断模型,系统化理解退信、重试和认证策略。

邮箱SMTPDSN退信邮件投递

邮箱错误码最容易被误读的一点,是把“SMTP 三位数回复”当成完整结论。实际上,3-digit reply 只告诉你传输层的大类;真正可操作的诊断通常来自 enhanced status code(X.Y.Z)、DSN 字段,以及接收方返回的 Diagnostic-Code。没有这三层上下文,单看一个 550 或 451,几乎必然会误判。

RFC 5321 定义了 SMTP 回复码的基本语义:2xx 表示 positive completion,4xx 表示 transient / temporary failure,5xx 表示 permanent failure。RFC 3463 进一步把诊断拆成 class.subject.detail,例如 5.1.1 user unknown、4.2.2 mailbox full、5.7.1 delivery not authorized、5.7.8 authentication credentials invalid。RFC 3464 的 DSN 则把这类结果装进 Final-Recipient、Action、Status、Diagnostic-Code、Remote-MTA、Reporting-MTA 等字段里,便于程序化处理。

先建立一个不会误判的心智模型

看邮件失败时,顺序应当是:先确认 SMTP 三位数,再读取 enhanced status code,再看 DSN 和对方文本。如果收件方提供了可读说明,优先级通常是:接收方原文 > Diagnostic-Code > enhanced status code > 3-digit reply。原因很简单:标准码提供通用语义,但各家邮箱、网关和反垃圾系统会在相同标准码下加上不同策略。

LayerExampleWhat it tells youAction
SMTP 3-digit reply550Transport-level class and coarse outcomeCheck recipient policy, syntax, or local server state
Enhanced status code5.1.1Standardized diagnostic class / subject / detailUse as the primary machine-readable clue
DSN fieldsStatus + Diagnostic-Code + Remote-MTADelivery report payload and correlation keysParse the full DSN, not just the first line

常见代码怎么分层理解

SMTP reply常见 enhanced code典型含义处理方向
220服务就绪,连接成功继续会话
2502.0.0 / 2.1.x命令接受、投递成功或中间步骤成功记录成功链路
354开始输入邮件内容准备 DATA
4214.3.0 / 4.4.1服务不可用、连接关闭、临时中断退避重试
4504.2.0 / 4.2.2邮箱忙、暂时不可用、容量类问题延后重试,检查队列
4514.3.0 / 4.4.0本地处理错误重试并排查系统依赖
4524.3.1系统存储不足清理队列、扩容、重试
5505.1.1 / 5.7.1用户不存在、策略拒绝、认证失败等通常不应自动重试
5525.2.2超出配额或存储告知用户清理或升配
5545.7.1 / 5.6.0事务失败、内容或策略拒绝先修正原因,再重新发送

为什么 550 不等于“邮箱坏了”

550 只是永久失败的大类里最常见的外壳。它可能对应 user unknown、mailbox unavailable、policy rejection、relay denied、syntax error,甚至 SPF / DKIM / DMARC 相关的安全策略拒绝。比如:

  • 550 5.1.1:收件人不存在,或者系统认为地址无效。
  • 550 5.7.1:没有投递授权,常见于反垃圾、未认证发信、relay denied、域名策略不匹配。
  • 554 5.7.1:更偏向事务级拒绝,网关或策略系统直接终止。

这也是为什么不能只写“SMTP 550”就结束分析。你要看完整回包、对端系统、发信路径、认证方式、发件域名、以及邮件内容是否触发策略。

DSN 字段怎么读

DSN 是运维和程序处理里最有用的部分。下面这几个字段尤其关键:

  • Final-Recipient:最终收件人,帮助你确认是不是别名、转发或规则导致的目标变化。
  • Action:failed、delayed、delivered、relayed,说明投递结果类型。
  • Status:enhanced status code,通常是最重要的标准化诊断。
  • Diagnostic-Code:对端返回的更详细原文,往往比状态码更接近真相。
  • Remote-MTA:出问题的对端 MTA,方便定位是接收方还是中继。
  • Reporting-MTA:发出 DSN 的系统,便于追踪你自己的投递链路。
Final-Recipient: rfc822; [email protected]
Action: failed
Status: 5.1.1
Diagnostic-Code: smtp; 550 5.1.1 user unknown
Remote-MTA: dns; mx.example.net
Reporting-MTA: dns; mail.example.org

如果只把 DSN 当作“退信文本”,你会丢掉最重要的关联信息。Final-Recipient 和 Remote-MTA 一起看,才能判断是地址、路由、别名展开还是策略拦截。

重试策略要按 4xx / 5xx 分开

4xx 是 transient failure,适合指数退避、随机抖动和队列保持。5xx 通常是 permanent failure,不应盲目重试。一个健康的重试规则可以是:

  1. 4.2.x / 4.3.x:5 分钟后重试,随后按 15 分钟、1 小时、4 小时递增。
  2. 4.4.x:先检查网络连通性、TLS、DNS、MX 解析,再决定是否重试。
  3. 5.1.x / 5.2.x / 5.7.x:默认不自动重试,只在修复地址、认证或策略后重新投递。
  4. 5.6.x:内容格式、字符集或 MIME 错误,修复消息后再重发。

不要把所有失败都塞进同一个 retry queue。那样只会让队列膨胀、延迟变长、误报更多,而且会在反垃圾系统里留下糟糕的重试痕迹。

SPF / DKIM / DMARC 的常见误区

认证失败并不总是直接等于退信,但它会显著影响策略评分和最终可达性。注意这几个坑:

  • SPF 只验证发送 IP / 发送域名授权,不等于内容可信。
  • DKIM 关注签名完整性,但转发、列表或正文改写会破坏签名。
  • DMARC 看对齐关系,单独通过 SPF 或 DKIM 不代表一定能通过 DMARC。
  • 转发场景里最容易出问题:SPF 可能失效,DKIM 可能被修改,DMARC 也可能因此失败。
  • 一些接收方不会直说“DMARC failed”,而是用 550 5.7.1554 5.7.1 或自定义文本表达。

因此,做排查时要把认证日志、退信文本、接收方政策和头部信息一起看,而不是只盯着一个 SPF pass/fail。

排障流程

  1. 读取原始退信,提取 SMTP reply、enhanced status code、Diagnostic-Code。
  2. 判断是临时失败还是永久失败。
  3. 检查收件地址、别名、转发、域名拼写和目标 MX。
  4. 检查发信认证:SPF、DKIM、DMARC、SMTP AUTH、IP allowlist。
  5. 检查邮件内容:URL、附件、编码、HTML 结构、黑名单关键词。
  6. 根据码值决定重试、修复或人工介入。

如果需要自动化,可以把解析结果存成结构化日志:

{
  "smtpReply": 550,
  "enhancedStatus": "5.7.1",
  "action": "failed",
  "finalRecipient": "[email protected]",
  "remoteMta": "mx.example.net",
  "category": "policy-rejection"
}

官方参考

真正稳定的邮件系统,不是记住更多错误码,而是把错误码分层使用:3-digit reply 用于粗分类,enhanced code 用于标准化诊断,DSN 用于关联与自动化,原文和策略文本用于最终判断。