摘要

  • RFC 772与RFC 780允许 MTP 接收方在 recipients-first 的 R 和 text-first 的 T 之间选择;MRSQ负责询问、选择与复位,MRCP在两种模式中承载不同阶段的收件人处理。
  • 两种顺序不是外观差异。R先缓存收件人表,再用一份正文批量完成;T先缓存正文,再逐个收件人交付。它们改变缓冲对象、失败何时变得明确,以及一次资源不足会影响谁。
  • RFC 788与RFC 821取消了这种线路级次序协商,固定为MAIL、一个或多个RCPT、DATA,但仍鼓励同一目的主机只传一份正文。标准化的是外部编舞,不是接收方内部实现。

一句询问也会清空状态

在RFC 780的模型里,MRSQ既是能力探测,也是状态操作。无参数的MRSQ在实现该设施时返回200,并选择“无方案”的默认状态。MRSQ ?要求接收方给出偏好,正常回答形如215 T或215 R。

但这不是只读查询。每次使用MRSQ都会复位方案状态:已经保存的收件人表或正文会按规则被冲掉。若监控系统只把问号理解成“看看设置”,就会漏掉它对正在进行状态的破坏性边界。

发送方可以提出MRSQ R。若接收方只能有效运行T,它可回答504拒绝该方案。规范明确说,发送方应准备使用任一方案,而接收方控制实际采用哪一种。理由很朴素:只有接收方知道自己的邮件器是一次接收完整批次,还是逐个交付更自然。

支持MRSQ的实现至少要支持R或T之一,并能回答偏好询问。协商的目标不是追求所有组合,而是让不同内部结构在同一线路上公开自己能安全承担的顺序。

R:先把名单装进表里

Recipients-first 模式先用多个MRCP TO:<path>提交收件人。接收端对每一个名字立即给出接受或拒绝,并把成功者保存在本地表中。一个错误名字不会撤销此前已保存的名字,也不应污染随后可接受的名字。

收件人收齐后,发送方发出不带TO参数的MAIL FROM:<sender-path>,然后传一份正文。正文的最终成功意味着所有被记住的收件人都成功;若正文阶段失败,规范要求把这组被记住的对象整体视作失败。事务结束后,收件人表被清空。

这个顺序适合把“完整收件人集合加一份正文”一次性交给中央 mailer 的系统。接收进程先形成工作包,再进行统一交接。它避免为同一主机上的每个人重复发送内容。

代价落在收件人表。若表满,MRCP可返回452,后续名字暂时装不下。RFC 780给出的办法是先把正文发给当前已保存的一组,再收下一组并重新传正文。一个50人消息,在只能保存10个名字的接收方上,可能变成五个批次、正文传五次。所谓“一份正文”受实际状态容量约束。

T:先保存正文,再一个人一个人试

Text-first 模式把次序翻转。发送方先用无收件人参数的MAIL FROM传入正文,接收方回答它已存下文本。随后每个MRCP都把那份已存正文应用到一个收件人,并返回像单独MAIL那样的成功或失败结果。

正文不会为每个MRCP重新过线。它留在接收端,直到下一次MAIL替换它,或MRSQ将它冲掉。因此T同样实现多收件人的传输经济性,只是缓存的是正文,不是名单。

这种顺序适合逐个直接递送的实现。邮箱配额、访问冲突等条件可以在每个收件人动作时得到具体响应,而不必让一次批量正文成功承担“所有人都已经处理”的含义。

它也有自己的边界。正文先被接受时,接收方还不知道之后会出现多少收件人,甚至不知道会不会出现有效收件人。若在正文尚未存入时先收到MRCP,相当于尝试发送空消息;规范允许实现接受或报错。状态顺序因此不是装饰,而是命令意义的前提。

同一个MRCP,在两个方案里承担不同证据

在R里,MRCP的成功主要表示“这个路径已经进入待处理收件人表”。最终正文结果还会作用于整组。在T里,MRCP发生在正文已经存在之后,它的成功更接近“这份已存正文已对这个收件人完成相应处理”。

相同的四个字母因状态机而改变证据位置。若日志只保存命令名与数字码,不保存已选方案,就不能可靠解释250究竟确认了名单存储,还是确认了某个收件人的实际发送。

复位规则更加重要。任何MRSQ都可能让原有收件人或正文失效,带非空TO的普通MAIL也会把方案状态拉回初始位置。调查一次“收件人莫名消失”或“正文被替换”的旧会话,必须按时间重放状态,不能逐行孤立阅读。

这正是可协商编舞的成本:协议不仅需要理解每个动词,还要理解同一动词在两个顺序、多个复位点和不同缓存对象下的意义。

为什么接收方握有选择权

RFC 780没有把R称为先进、T称为落后。它解释的是两种接收体系。集中式 mailer 希望一次获得更多相关信息,R的完整批次更高效;逐个直接投递的实现希望即时拿到每位收件人的资源结果,T更自然。

发送方看不到这些内部事实。它不知道对方收件人表能容纳多少名字,不知道正文缓存成本,也不知道本地交付是批处理还是增量处理。让发送方强行规定次序,会把缺乏证据的一端变成决策者。

所以发送方能表达偏好,接收方能拒绝。控制权与承担缓存和本地失败的一方绑定。这是一种很早的“实现能力先于远端愿望”。

然而,正确分配个别连接的权力,不代表把这种选择永久留在网络语法中没有代价。每个客户端都要准备两条路径,每个分析器都要跟踪两个状态机,每次恢复都要知道冲掉的是名单还是正文。局部最优可能扩大整体互操作空间。

1981年末:SMTP固定了三步

RFC 788改用一条明确流程。先以MAIL FROM声明发送方并复位事务状态;再用一个或多个RCPT TO逐个协商收件人;最后以DATA发送正文。文档说对话故意采用 lock-step,一次一项,并要求这些命令按规定顺序使用。

MRSQ与MTP意义的MRCP不在新命令表中。接收方不再能要求正文先于收件人。线路上只剩 recipients-first 的统一骨架,但它也不是把RFC 780的R原样改名。

SMTP把发送者身份、每个收件人和正文拆进清楚的命令。RCPT失败只拒绝该收件人,不必取消整个事务。所有收件人协商结束后,DATA结束标志才让接收方处理已存路径与正文并给出最终结果。

这条状态机降低了双方必须共同理解的排列数。内部可以先缓冲、后批处理,也可以逐步校验;线路不再协商内部架构。

简化没有丢掉一份正文的经济性

取消T并不意味着SMTP必须为每个收件人重复内容。RFC 788与RFC 821都鼓励:同一消息发给同一目的主机上的多名收件人时,只传一份数据。

做法成为后来最熟悉的序列:MAIL一次,RCPT多次,DATA一次。不合格的收件人可以在正文前被剔除,合格者共享正文传输。

RFC 1123进一步强烈建议这种效率:对同一主机的多人使用RCPT, RCPT, ... RCPT, DATA,而不是RCPT, DATA反复发送。SMTP保留了MTP要解决的带宽问题,只是删除了“正文也可以先到”的线路级替代方案。

因此,历史不是功能从二变一后失去一半效率。它是把共同目标——一次正文服务多个收件人——从两种协商语法收敛到一个确定顺序。

lock-step 与固定顺序不是同一件事

RFC 788称对话为lock-step,意味着发送命令、等待回复、再继续。后来的PIPELINING可以减少这些等待,但不会把DATA搬到RCPT之前。

这条边界避免与另一段SMTP历史混淆。性能扩展能让多个允许的命令提前排队发送,回复仍按顺序对应;它没有恢复MRSQ T,也没有让服务器选择正文先到。

交易顺序决定状态依赖:没有合格收件人就不能开始DATA;DATA的最终答复建立在此前收下的收件人集合上。等待策略决定同一顺序要花多少往返。二者都影响时间,却不是同一控制面。

现代SMTP保留的是固定外壳

RFC 5321仍以MAIL开启事务,以一个或多个RCPT建立收件人,以DATA交付内容。扩展能增加参数、能力与返回细节,但基本顺序没有重新交给接收方选择。

这不等于所有实现内部相同。某服务器可以把收件人和正文交给队列系统,另一台可以在RCPT时做昂贵校验,第三台可以在DATA后才发现内容相关限制。标准只固定双方共享的外部状态转换。

内部自由反而因外部统一而更容易保留。实现无需把自己的缓存偏好变成对所有客户端的语法要求;客户端也无需知道对方把什么先写入磁盘。接收方失去的是线路编舞权,不是本地工程权。

MRCP后来成了另一个缩写

本文的MRCP是MTP里的Mail Recipient命令。多年后出现的Media Resource Control Protocol也使用MRCP缩写,服务语音合成、识别等媒体资源。二者没有协议血缘。

生产搜索、文档检索和历史索引若只用MRCP,容易得到完全不同的现代协议。查重与证据采集必须同时限定MTP、邮件、MRSQ或RFC 772/780,否则同形缩写会制造虚假覆盖。

这也是协议历史中的普通风险:一个名字退出后,字母可能在另一领域重新出现。注册和上下文比字面相似更有证据价值。

来源与论证边界

本文依据RFC 772、RFC 780、RFC 788、RFC 821、RFC 1123与RFC 5321。它们能确定两种方案、控制权、状态与复位、SMTP固定顺序和一份正文的连续性。

它们不能证明某个具体实现采用率、删除发生于一次会议、或固定顺序带来统一的性能提升。RFC 788不说“MRSQ失败了”;最可靠的历史事实是它不再定义这些命令,并明确规定另一套唯一顺序。

R也不保证所有收件人原子成功,T也不是每人重传正文。二者解决的是缓存与处理次序,不能被简化成“批量可靠”对“逐个低效”。