RFC 1870《SMTP 服务扩展:消息尺寸声明》中文导读
非官方中文导读声明:本页为 IETF RFC 1870《SMTP Service Extension for Message Size Declaration》 的非官方中文技术导读,按原文章节顺序梳理规范要点,并非逐字全文翻译;任何规范性判断均以英文原文为准。英文原文见 rfc-editor.org/rfc/rfc1870.txt。
1. 为什么需要预先声明尺寸
在互联网邮件早期,SMTP 没有机制让发送方在上传整封邮件之前知道对方能否收下。结果是一封远超接收方磁盘或策略限额的大邮件,要等到被完整传输、甚至被接收方开始落盘之后,才以某种错误被拒——白白占用带宽与 I/O。
RFC 1870 给 SMTP 增加 SIZE 扩展,让双方在传输正文之前交换尺寸信息:服务端说“我最多能收多大”,客户端说“我这封有多大”,超限则立刻停下。它被收录进 STD 10,是邮件尺寸协商的规范基础。
2. EHLO 中的 SIZE 关键字
服务端在 EHLO 响应中以带可选参数的 SIZE 关键字通告能力。参数是一个十进制数字,表示本服务端愿意接收的单封消息最大八位组(octet)数;若省略参数,则只表示“我支持 SIZE 参数”,不承诺具体上限。
S: 250-mx.example.net Hello S: 250-SIZE 35882577 S: 250 HELP
值为 0 表示服务端未声明上限(仍支持 SIZE 参数,但不限制大小)。当服务端不支持该扩展时,EHLO 响应中不会出现 SIZE 行,客户端也就不得发送 SIZE 参数。
3. MAIL FROM 的 SIZE 参数
客户端在 MAIL FROM 命令中携带 SIZE= 参数,给出本封邮件的八位组总数。这个计数的口径必须一致:包含每行的 CRLF,但不包含 DATA 阶段用于终止邮件的那个“单独一行的点”。
C: MAIL FROM:SIZE=1000000 S: 250 OK
如果服务端已通告具体上限,而客户端的 SIZE 超过了该上限,服务端可以在收到 MAIL FROM 时直接回绝,而不必等到 DATA 之后。规范使用的回绝码是 552(请求的动作被中止:超出了存储分配)。
4. 服务端如何处置超限与不足
- 超出上限(永久失败):消息尺寸超过服务端公布的 SIZE,服务端应回
552 5.x.x,且必须丢弃后续被传输的邮件内容,不得将其投递。 - 临时存储不足:消息尺寸本身在范围内,但服务端此刻没有足够空间落盘,应回
452(请求的动作未执行:系统存储不足),并丢弃后续内容,客户端稍后可重试。 - 正常:在范围内且有空间,继续正常事务。
关键在于:一旦判定无法接收,服务端必须丢弃后续正文,而不是边收边报错——否则会留下半截邮件与浪费的带宽。
5. 与转发和加密的交互
当一封邮件经多个中继转发时,SIZE 限制是逐跳生效的:每一跳都按本跳通告的上限判断。若某中间 MTA 本身支持 SIZE 但上游传来的尺寸超过了它下一跳能接收的限度,它需要在自己这一跳就拒收,而不是转发后才失败。
对于使用 STARTTLS 或 AUTH 的场景,SIZE 参数仍然挂在 MAIL FROM 上,不受加密/认证影响;加密只保护传输,不改尺寸语义。
6. 部署提示
实际运维中,SIZE 是防大附件压垮服务器的第一道闸门。把它与 8BITMIME、PIPELINING 等扩展一起通告是常见做法。需要注意的是:客户端申报的 SIZE 应是最终落盘字节数,若经过编码(如 base64 会膨胀约 33%),申报值应当反映编码后的实际传输量,否则可能出现“申报未超、实际超”的边界误判。
参考:https://www.rfc-editor.org/rfc/rfc1870.txt
