摘要

  • RFC 3461 允许 SMTP 客户端按收件人请求成功、失败或延迟报告,并让事务标识与原始收件人标识穿过中继;RFC 3464 则把回复组织成按收件人区分的机器可读记录。
  • 这套词汇刻意没有许诺绝对确定性:delivered 不代表已读,relayed 表示成功交付证据在此后可能中断,而 DSN 自身也可能被伪造、丢失或因保密而停止传播。

早期退信是一封承担过多任务的普通邮件。它既要让人知道邮件失败,又要帮助管理员诊断路径,还得让软件猜出通知对应哪次提交。正文格式各异,常常只附一段错误说明和原信片段。对大型邮件列表而言,成批退信抵达后,运营者仍可能分不清失败发生在哪台主机、影响哪个收件人,也无法稳定地把通知归回原事务。

SMTP 的责任转移使这种含混不能只算界面问题。服务器对 RCPT 返回肯定响应,通常意味着它承担把邮件交付给该收件人、或在失败后通知发送方的责任。但“以后通知”包含许多不同判断:发送方是否需要成功通知?多久才算异常延迟?转发改写地址后,报告应指向旧地址还是新地址?一次提交里多个收件人的结果不同,又该怎样表达?

2003 年 1 月同时发布的 RFC 3461、3463 与 3464 把这些问题拆开。3461 规定请求怎样进入 SMTP 信封;3464 规定状态通知的结构;3463 规定与具体传输无关的增强状态码。它们取代 189x 系列标准,真正的进步不是让“退信”更好看,而是把证据请求、身份延续、执行动作和失败原因放进不同字段。

四个参数没有把愿望写成命令

服务器在 EHLO 响应中公布 DSN 能力。扩展没有增加新命令,而是在原有 MAIL 与 RCPT 上增加四个可选参数。

NOTIFY 针对单个收件人。客户端可以组合请求 SUCCESS、FAILURE、DELAY,也可以单独使用 NEVER。缺省时,服务器可以维持只报失败的传统行为,也可以加上延迟通知。这里的控制权很精确:发送方选择愿意接收哪类证据,却不能预定实际结果。

DELAY 最能说明这条边界。它不由发送方设置计时器。持有邮件的 MTA 判断等待是否异常漫长,而发出延迟报告时,最终成功或失败仍然未知。同一个 4.x.x 临时状态,可能先伴随 delayed,表示继续尝试;几天后队列放弃,才伴随 failed。

RET 面向整次事务。失败报告可以按 FULL 返回完整原信,也可以按 HDRS 只返回首部;若报告里没有失败收件人,标准只让首部返回。这既是诊断选择,也是披露选择。完整正文能帮助复现问题,却会让原内容沿另一条邮件路径复制和留存。

其余两个参数负责保存身份,而且各自回答不同问题。

内容标识、事务标识与收件人标识不能混用

ENVID 随 MAIL 命令进入信封,之后可作为 Original-Envelope-Id 出现在 DSN 中。邮件系统不解释这个值;只有创建它的发送方或用户代理知道其含义。

它也不是邮件首部里的 Message-Id。后者标识内容,前者标识一次提交事务。同一内容可以在不同时间提交两次,一次事务也可以包含结果分叉的多个收件人。若把二者当成同一个身份,自动系统会把重试、重发和多收件人结果混在一起。

ORCPT 保存发送方最初指定的收件人。首次提交时,它必须与 RCPT TO 相同;邮件被转发后,当前操作地址可以改变,原始值仍随路径传递。当前地址说明这一跳正把邮件送往哪里,ORCPT 说明这份证据对应发送方名单里的谁。即使邮件经过使用不同地址体系的网关,这一区分仍应尽量保留。

两个标识合在一起,软件才有机会先把报告归到某次事务,再把每组结果归到原始收件人。但它们只是关联把手,不是身份认证。ORCPT 不证明地址属于某个人,ENVID 也不是密码学凭据;整条链必须诚实保存它们,关联才有价值。

Action 说明采取了什么动作,Status 说明遇到什么条件

RFC 3464 把 DSN 定义为 multipart/report。第一部分供人阅读,第二部分是 message/delivery-status:先列整封邮件的字段,再为每个被报告的收件人列一组字段;第三部分可选,放回原信或首部。

每个收件人必须有一个 Action:failed、delayed、delivered、relayed 或 expanded。同时,Status 使用 RFC 3463 的三段数字:2.x.x 表示成功,4.x.x 表示持续的暂时失败,5.x.x 表示永久失败,后两段再描述对象与细节。

动作与状态并不重复。DNS 查询超时可能一直是 4.x.x,但队列仍在重试时动作是 delayed;达到重试上限后,条件类别未必改变,动作却成为 failed。前者描述环境,后者描述报告方已经作出的运行决定。

五种动作也拆掉了“已投递”的单一想象。failed 是终态,意味着不再尝试;delayed 不是终态。delivered 对该收件人是终态,却可能只是交给邮件列表分发器,绝不代表人已经阅读。expanded 表示多收件人别名接受后又展开到更多地址,因此后续仍可能出现延迟或失败。

最诚实的是 relayed。它表示邮件已进入一个不承担成功 DSN 责任的环境。报告方能证明自己完成了交接,无法证明最后邮箱的结果。协议没有在网关处编造确定性,而是给“证据到此为止”起了名字。

为了不让失败自我繁殖,通知必须允许沉默

DSN 本身也是邮件,也会投递失败。如果失败的 DSN 再生成 DSN,两套不可达系统就可能不断制造“通知失败的通知”。标准因此要求经 SMTP 发送的 DSN 使用空反向路径 MAIL FROM:<>,并禁止它的失败再触发网络 DSN。

这是一项主动选择:为了稳定,系统放弃递归可见性。发送方可能永远不知道通知本身丢失,但这好过无限反馈环。所谓可靠,是在明示的边界内保持一致语义,不是保证观察到每一层失败。

中继和异构网关形成另一道边界。兼容 DSN 的 SMTP 节点应继续传递请求和标识;进入其他邮件环境时,网关只能尽力映射。有些系统不能承担成功通知,有些地址与诊断形式完全不同。此时 relayed 比虚构最终成功更有信息。

隐私还可能要求有意截断证据。收件人把邮件转发到保密地址时,RFC 3464 允许省略敏感远端字段、停止向下游请求正面通知,或在边界返回 relayed。完整遥测与隐藏转发目的地并不总能兼得。

机器可读不是可信认证

RFC 3464 明确指出,DSN 和普通互联网邮件一样容易伪造。虚假成功会让流程过早停止,虚假失败可能触发重试、移除名单成员或制造客服事件;伪造的最终收件人和远端 MTA 还会把调查引向错误对象。

ENVID 无法把报告变成可信凭证。它由发送方选择,邮件系统不赋予语义,知道一个看似正确的值只构成关联线索。自动化系统还需要消息认证背景、预期收件人状态、重放控制以及可逆的处置方式。

RET=FULL 带来另一类风险:失败报告复制整封原信,可能经过不同路由,进入新的日志和邮箱。即使只返回首部,也会暴露通信双方、主题和路由。参数让发送方表达取舍,却不能约束每个中间系统怎样保存副本。

回执最终成为一张“有限权力地图”

DSN 的历史意义,在于它准确分配了谁能声明什么。发送方控制请求与关联标识;各 MTA 控制接收、重试与自己报告的动作;网关控制翻译忠实度;保密转发器可以停止披露;收件人是否阅读则完全在 SMTP 之外。

这张地图写在词汇里:NOTIFY 是偏好,不是命令;ENVID 与 ORCPT 保存身份但不裁定身份;Action 记录决定,Status 记录条件;relayed 承认证据缺口;空反向路径则让某类失败故意保持沉默,以换取系统稳定。

IANA 的 SMTP 注册表至今仍把 DSN 指向 RFC 3461。这项能力最持久的价值,是要求报告对知识范围保持克制:它可以说清事务、原始收件人、报告节点、采取的动作和诊断条件,也必须让终态、非终态与空白显示确定性在哪里结束。

它能帮助队列对账、邮件列表清理、客服诊断和自动化运维,却不能承诺进入收件箱、被人看见,或跨过不负责报告的环境仍保有真相。正因为拒绝这些夸大的承诺,SMTP DSN 才比自由格式退信更有用,也比“万能回执”更诚实。

来源