摘要

  • DELIVERBY 允许发送方在 MAIL FROM 中写入剩余秒数,并选择到期后停止尝试、退回失败,或只发延迟通知而让投递继续。
  • 支持该能力的中继必须扣除已经消耗的时间,再把更小的数值交给下一跳;任何节点都不能把原预算重新开始。它仍不承诺优先处理、按时送达或按时收到退信。

邮件队列面对的常见问题是“现在送不出去,之后是否再试”。发送方有时面对的却是另一类问题:“过了这个时刻,即使送到也不再正确。”两者看似都与时间有关,权力来源却不同。重试周期由持有队列的运营者制定;一封邮件为何在某个时刻失效,可能只有发送方知道。

RFC 2852 用一个很具体的场景说明这种错位:邮件会触发寻呼,但发送方不希望它在工作时间结束后打扰收件人。邮件系统若按普通规则晚些送达,技术上可能完成了任务,现实中却执行了错误动作。

2000 年 6 月发布的 Deliver By SMTP Service Extension 没有建立“加急邮件”。它建立的是一种可拒绝、可递减、能在中继边界上继承的时间条件。发送方可以说晚了以后应怎样处理;接收方仍然决定是否承接,也仍然掌握实际调度。

协议把失效时间与优先级拆开

服务器在 EHLO 响应里公布 DELIVERBY。它还可以给出一个固定最小值,表示 Return 模式下愿意接受的最短期限。客户端若使用该能力,只需在 MAIL FROM 后增加 BY 参数;没有新 SMTP 命令,也没有“立即排到队首”的语义。

这条限制是设计核心。宣布紧急不等于购买计算资源,声明期限也不等于取得另一家运营者的排程权。服务器可以完全不提高优先级,可以保留自己的公平、容量和重试策略。若期限不可信,它可以拒绝承担,而不是先答应、再靠隐藏降级化解压力。

因此,DELIVERBY 不是发送方对队列的统治工具。它更像一份有边界的接单条件:运营者可以说明自己能承接的最小时间,发送方可以决定这条路径是否还符合消息用途。

相对秒数比绝对钟表更适合跨机构

BY 值包含一个带正负号的十进制秒数、模式 R 或 N,以及可选的跟踪标志 T。规范给出的范围是正负 999,999,999 秒。

它使用相对时间,而不是要求双方认同一个绝对时间戳。接收节点收到参数后,把秒数加到自己的本地时间,得到本地 deliver-by-time。准备向下一跳发送时,它再计算距离该时刻还剩多少秒,并尽量贴近下一次 MAIL FROM 的发送瞬间。

这不能消灭时间误差。命令在网络中传输需要时间,RFC 2852 明确承认每一跳会让实际期限略微延长,多跳以后误差还会累积。协议解决的是“剩余义务怎样传递”,不是全球时钟怎样完全一致。

相对值也不是“到某时刻以后才发送”。它只表示必须在给定区间内送达。它不会延长本地通常的留存上限;若一个站点原本就会更早放弃无法投递的邮件,仍可在期限之前结束队列。

到期以后,R 与 N 指向相反动作

Return 模式 R 不接受零或负数。期限到达而邮件尚未送达或中继时,MTA 不得继续尝试;它必须为符合失败通知条件的收件人生成 5.4.7 “delivery time expired” 失败 DSN。这里改变的是保管权:时间一到,继续投递本身变成不被允许的动作。

Notify 模式 N 则保留继续尝试的权利。期限到达后,队列应按站点原有政策运行,同时为符合延迟通知条件的收件人生成 4.4.7 延迟 DSN。零和负数在该模式下合法,因为“已经晚了多少”仍然是可以传递的证据。

这一区分比一个笼统的“紧急”标签更精确。有些消息晚到会造成伤害,应该撤回;有些消息晚到仍有价值,只需要让发送方知道服务目标已经错过。前者要求终止,后者要求暴露状态。把两者合并,会让队列在最关键的时刻做错决定。

此外,永久失败无需等待期限。临时故障可以在期限前继续重试。本地留存政策也可以更早结束。DELIVERBY 没有重写 SMTP 整套失败模型,只新增了一个由发送方解释、由接收方承接的时间边界。

中继只能传递余额,不能复活原预算

当下一台服务器也支持 DELIVERBY,当前中继必须重新计算剩余秒数,保留原模式,再发出新的 BY 参数。第一跳花掉的时间不能在第二跳恢复。否则每个运营者都可以声称自己收到了一份完整期限,整条路径却永远不会真正到期。

R 模式要求最严格的连续性。它不能交给不支持 DELIVERBY 的下一跳,也不能交给一个最小可接受时间大于当前余额的服务器。当前节点可以尝试其他正当路由;若没有能够继承期限的路径,就必须把邮件视为不可投递,不能偷偷丢掉到期规则。

N 模式允许跨入不支持该扩展的环境,因为期限并不撤销继续尝试的权利。但中继必须为适用收件人生成 relayed DSN,明确告诉发送方原有时间语义在此失去连续性;若下游支持 DSN,还应在允许范围内保留延迟通知请求。

这是一种很薄的协调层。协议不替任何运营者运行队列,只规定跨边界必须保留的最小状态:余额、到期动作,以及语义无法继续时的证据。局部自主权仍在,已经接受的约束却不能被悄悄重置。

接受发生在分阶段获得知识的事务里

服务器可能先对 MAIL FROM 返回肯定响应,随后在 RCPT TO、DATA 或正文结束时才发现无法满足期限。收件人、内容与本地资源信息不是同时出现的,因此早期成功只说明该阶段的语法与初步条件可接受,并不证明每个收件人都能按时处理。

固定最小时间就是公开的准入边界。服务器可以诚实地说:“我支持 Return,但不会接受短于这个运行下限的承诺。”下一跳的下限大于余额,不是需要隐藏的兼容性小问题,而是该路径无法承继义务的直接证据。

通知记录决定,却不受同一时钟支配

DELIVERBY 借用 DSN 表达失败、延迟与中继,并为报告增加 Deliver-By-Date。可选的 T 会请求中继报告,即使没有显式请求成功通知也可能产生;这些报告不是终态,下游仍可发来其他结果。

这正是它与 DSN 历史的边界。DSN 规定一项动作如何成为结构化证据;DELIVERBY 决定期限到达时队列必须采取哪类动作。R 改变是否还能继续,N 改变必须报告什么。

报告还走另一条队列。即使原消息使用 BY=60;R,期限到达后生成的失败 DSN 也不保证在 60 秒内返回。正向期限约束原消息,返向证据有自己的路由、等待和失败。让一项义务有界,并不意味着协议突然控制了所有后果。

时间也会变成探测面

跟踪标志能显示中继交接。即使不用 T,攻击者也可能发送一系列期限逐渐变化的邮件,再比较拒绝、延迟和失败,从而粗略推断运输结构或排队时间。RFC 2852 把这种泄漏写入安全考虑。

这些信号不能被夸大。负的 N 值只能说明某节点计算出的期限已过去,不能确定哪一跳负责。5.4.7 说明 Return 义务无法继续,不证明拥塞或失职。relayed 说明一次交接,不等于最终送达。

IANA 的当前 SMTP 服务扩展注册表仍收录 DELIVERBY,指向 RFC 2852,并把要求级别列为 MAY。这证明能力仍有标准化登记,不证明今天有多少服务商实现它。

DELIVERBY 最值得保留的不是一个冷门参数,而是一条互联网设计纪律:跨越独立运营者的约束应当足够小,能被拒绝,能随消耗递减,并在无法延续时留下清楚边界。期限之所以能随邮件旅行,不是因为发送方获得了权力,而是因为中继被禁止把已经花掉的时间重新制造出来。

来源