摘要

  • RFC 5248 用三张登记表、公开规范、提交者和变更控制者,为 SMTP 增强状态码建立了可追溯的公共语义秩序。
  • 登记只能说明某个代码被赋予了什么含义,不能证明服务器诊断正确、客户端保留完整上下文、重试决策合理,更不能单独证明邮件已经送达或永久失败。

一个代码穿过了几层现实

增强状态码最初只是服务器在一次 SMTP 交互中作出的陈述。进入日志后,它可能变成“失败原因”;进入队列后,它可能变成“是否重试”的开关;进入客户界面后,它又可能变成“送达结果”。同一串数字在每次转手时都可能获得新的权威,但这些权威并不来自 IANA 登记表。

RFC 3463 设计了可扩展的增强状态码,却没有明确规定新增代码如何登记与跟踪。扩展发生后,冲突定义随之出现。RFC 5248 作为 BCP 138 的答案,不是再发明一套邮件投递机制,而是建立登记程序,并更新已经扩展过这套词汇的 RFC 4468、RFC 4954 等文档。

因此,RFC 5248 解决的是共享语言的治理问题。它让不同实现可以查询一个代码的公开含义、来源规范以及谁有权修改它。它没有观察生产服务器,也没有看到队列、下一跳或收件箱。把“已登记”写成“已证实”,等于让语义治理越权接管运行事实。

三张表不是一张真相表

代码采用“类别.主题.细节”结构。RFC 5248 把治理面拆成类别子代码、主题子代码和枚举状态码三张表。枚举项结合主题与细节,类别位置仍可保留通配,因为定义该条件的规范可能允许它与不止一种类别搭配。

每条记录保存代码、摘要或示例文本、描述、引用及其标准轨道状态、提交者和变更控制者。枚举项还会列出关联的三位基本 SMTP 状态码。这里记录的是语义谱系:谁提出,依据哪份公开文档,谁能维护,和哪类基本回复通常相关。

“关联”并不等于“唯一”。RFC 5248 明确说明,关联基本状态码是非排他的。表里列出某个三位码,不会自动禁止其他搭配;字段也可以写成 Any 或 Not given。如果验证程序把它强行改造成一对一矩阵,就会把登记表提供的参考信息误写成原规范并未授予的禁令。

X.0.0 也体现了这种克制。它是唯一的未定义代码,用于只能确定回复类别、不能确定更具体原因的情况。它保存“不知道”的边界,而不是用一个看似精确的编号替缺失证据补故事。

专家审查的是定义,不是事故

新值采用 Specification Required 政策。RFC 5248 要求非标准轨道规范也应当便于公开获得,并强调审查的主要目的在于避免混淆与碰撞,而不是设置不必要的门槛。今天的政策框架 RFC 8126 进一步说明,这类登记通常需要永久公开的规范和指定专家审查,专家关注清晰度、稳定性与技术质量。

这种审查对象是一个可复用的语义提案。专家不会登录某家运营商的生产队列,不会复现某个收件人的失败,也不会认证每个发送该代码的服务器,更不会批准企业自己的重试算法。因此,一个定义可以通过审查而被实现错误地使用;一项真实故障也可能被实现选择成过宽或过窄的代码。

变更权同样被明确划分。标准轨道登记通常只能通过更新标准来修改;非标准登记由记录中的变更控制者负责。日常更正一般调整简短描述或引用,而不是暗中更换代码和示例文本。IESG 在解决冲突时保留例外干预权。这些规则保护的是共享含义的连续性,不会自动修正过去每一行日志。

初始登记内容本身就提醒我们不要把来源想得过于整齐。RFC 5248 既纳入了已发布 RFC 中的值,也纳入了业界已经使用、当时没有公开规范的值;若干安全类代码由 IESG 控制。它还把“Trust Relationship Required”从过去对 X.7.8 的使用迁移到 X.7.14。登记机构能够修复语义地址,却不能证明所有部署何时完成迁移,也不能替历史数据选择正确解释。

“临时”和“永久”仍有条件

RFC 3463 把类别 2 定义为投递状态通知中的成功,把类别 4 定义为持续性临时失败——未来尝试可能成功,把类别 5 定义为通常需要改变邮件或目的地址的永久失败。它们为互操作提供了必要的行为信号,但不是关于未来的绝对预言。

RFC 5321 要求 SMTP 客户端根据回复代码而不是解释文本采取行动。4yz 表示在适当条件下可以稍后重试;5yz 表示不应原样重复同一请求。与此同时,规范也承认,看似永久的条件后来可能被纠正。

所以,4.x.x 没有承诺下一次一定成功,5.x.x 也没有证明现实永远不会改变。正确策略还需要消息标识、收件人、尝试次数、时间、发送服务器、当前配置和后续回复。代码可以成为决策输入,但不能把缺失的时间与上下文一并创造出来。

RFC 2034 规定增强状态码如何随 SMTP 回复传递,RFC 5248 管理它们的公共词汇。发出代码的判断逻辑、接收代码的解析器、保存响应的队列以及执行动作的自动化是另外几层控制面。再往后,下一跳接受、最终系统接收、邮箱处置和读者行为都需要各自的证据。

更详细的回复也可能更危险

RFC 5248 的安全讨论反对“越具体越好”的简单想象。增强状态码可能泄露邮件系统内部实现。在认证场景中,把“用户不存在”与“密码错误”区分给外部调用者,可能让攻击者获得枚举身份的预言机。因此,定义代码的规范应当告诉服务器软件何时限制对外细节。

这意味着公开回复和内部诊断可以合理地不一致。安全策略可能要求外部只看到较宽的类别,而内部日志保留更精确的条件。审计必须记录这种披露政策,而不是强迫两个表面完全相同。外部信息较少不一定代表内部诊断失败;外部信息很多也不代表它更加真实。

把名称、主张和印证分开保存

证据阶梯的第一步只是语法:代码能够被解析。第二步是登记事实:观察到的登记版本包含这个赋值。第三步仍然只是实现的主张:某台服务器声称登记条件已经发生。随后还要检查基本码与增强码是否符合适用规范,保存命令、响应、消息和收件人上下文,并用服务器日志、队列转换或独立观察印证原因。

更高层才是动作和结果:重试策略是否作用于正确消息,后续传输是否发生,目标是否接受,邮箱或应用如何处置,业务对象是否真正收到信息。低层凭据不能继承高层权威。一个格式正确且已经登记的代码,可以参与证据链,却不能独自走完整条链。

Lu Heng 关于运行代码优先和现实分层的纪律,在这里不是反对标准登记。登记表协调符号,运行实现产生行为,运营记录保存发生过的转换。三个层次互相连接,却不能互相冒充。真正可靠的邮件系统不会只存一个“规范化状态”,而会把定义版本、发出者、原始回复、策略动作和最终结果分别保留。

来源