邮件地址过长、行过长、收件人过多被拒,协议规定的上限到底是多少?
RFC 5321 §4.5.3.1 在给出具体数字前先立了一条原则,这条原则决定了如何正确解读后面的每一个值:每一个实现都必须能够接收至少这些尺寸的对象;超过这些尺寸的对象在可能的情况下应当避免。规范同时指出,某些互联网邮件构造往往需要更大的对象,客户端可以尝试传输,但必须准备好被服务端拒绝。
换句话说,这些数字定义的是「你至少要能收下多少」,而不是「你最多只能收多少」。规范明确建议:在最大可能的范围内,应当采用对这些对象长度不施加限制的实现技术。
规范还特别说明,由于 SMTP 扩展可能引入占用多个八位组的字符,本节的长度以八位组(octet)为单位,而非字符数。这一点在处理国际化邮件时尤为关键:一个中文字符在 UTF-8 下占三个八位组,按字符数估算会严重低估实际长度。
RFC 5321 §4.5.3.1 给出的各项如下:
- 本地部分(Local-part):最大总长 64 octets。即地址中 @ 之前的部分。
- 域(Domain):最大总长 255 octets。域名或数字地址。
- 路径(Path):最大总长 256 octets。反向路径或正向路径的总长,包含标点与元素分隔符在内。注意这一项不等于本地部分与域简单相加,尖括号等标点也计入其中。
- 命令行:最大总长 512 octets,包含命令字与结尾的 CRLF。SMTP 扩展可用于提高此限制。
- 回复行:最大总长 512 octets,包含回复码与结尾的 CRLF。需要传达更多信息时应使用多行回复。
- 文本行:最大总长 1000 octets,包含结尾的 CRLF,不计入为透明性而重复的前导句点。此值可通过 SMTP 服务扩展提高。
- 报文内容:必须至少支持 64K octets,包含信头部分与正文。规范指出自多媒体邮件标准出现以来报文长度显著增长,应尽可能避免报文尺寸限制;确需限制的服务端应当实现 RFC 1870 的 SIZE 服务扩展,需要发送大报文的客户端应当尽可能利用它。
- 收件人缓冲:必须至少缓冲 100 个收件人。以少于 100 条 RCPT 命令为由拒绝报文(理由为收件人过多)违反本规范。
收件人这一项值得单独展开,因为它是实践中最常被违反、也最常被误读的一条。
RFC 5321 的要求包含几个层次。其一,少于 100 个收件人时不得以数量为由拒绝,这是硬性的。其二,规范提到一条一般原则——中继 SMTP 服务端不得、投递 SMTP 服务端不应对报文信头字段执行校验测试;这条原则意味着不应当依据信头字段中显示的收件人总数来拒绝报文。信封收件人与信头收件人是两回事,前者才是投递依据。
其三,施加了收件人数量限制的服务端必须以有序的方式行事:应当拒绝超出其限制的后续地址,而不是静默丢弃此前已经接受的地址。这一条是整节里最重要的安全性要求——静默丢弃会造成「发送方以为全部送达、部分收件人实际从未收到」的静默失败,且双方日志都不会显示异常。
其四,需要投递超过 100 条 RCPT 命令的客户端应当准备好分成每批 100 个收件人来传输,以应对服务端不接受更多收件人的情况。这是发送侧应当实现的兼容逻辑。
RFC 5321 §4.5.3.1.9 说明超出这些限制的错误可以用回复码报告,并给出了「500 Line too long.」这样的示例。实践中的排错可按以下顺序进行:
- 先量八位组,不要数字符。用
wc -c或hexdump确认实际字节数。含非 ASCII 的显示名、主题、文件名极易在字符数看起来很短时已经超出八位组限制。 - 区分是地址超限还是路径超限。本地部分与域各自合规,不代表路径合规——路径限制是 256 octets 且包含标点。带有超长参数的 RCPT 命令还要同时受命令行 512 octets 的约束。
- 正文被拒时先看有没有超长行。典型触发场景是:正文中嵌入了未折行的长 URL、base64 未按规定折行、或从其他系统导出的单行数据。文本行的 1000 octets 上限是含 CRLF 的,而 RFC 5322 §2.1.1 进一步规定每行不得超过 998 字符(不含 CRLF)、且应当不超过 78 字符,两者需要一起满足。
- 大附件被拒时确认对端是否通告 SIZE。若对端通告了 SIZE 及其数值,应在 MAIL 命令上声明报文大小,让拒绝发生在传输之前而不是传完之后。传完再被拒既浪费带宽,也会让重试策略反复踩同一个坑。
- 八位组内容需确认 8BITMIME。若报文正文含八位组数据,需确认对端通告了 RFC 6152 定义的 8BITMIME 扩展;否则应先做内容传输编码转换,而不是直接发送。
- 接收侧的限制值不要低于规范下限。把收件人上限设成低于 100、把行长上限设成低于 1000 octets,都会与合规发送方产生不可预期的互操作失败,且故障现象往往归因到别处。
- 拒绝必须是显式且可读的。无论拒绝哪一项,回复文本都应说明是哪个对象超限、限制值是多少。「500 Syntax error」这类回复会让对方运维完全无从下手。
- 严禁静默截断。无论是截断地址、截断收件人列表还是截断正文,都会把一个可见的失败变成不可见的错误。宁可拒绝整封邮件。
- 发送侧在生成阶段就做校验。在报文进入 SMTP 之前校验地址长度、行长与收件人数量,比在投递失败后回溯要高效得多。批量发送系统尤其应当内置分批逻辑,不要依赖对端恰好接受超大收件人列表。
- 把边界值纳入回归测试。构造恰好等于与恰好超过各项限制的测试报文,在 MTA 升级或网关策略变更后自动跑一遍,可以在上线前发现绝大多数尺寸类互操作问题。
参考:RFC 5321《Simple Mail Transfer Protocol》§4.5.3.1 Size Limits and Minimums、§4.5.3.1.9,J. Klensin,2008 年 10 月,Standards Track,DOI 10.17487/RFC5321,https://www.rfc-editor.org/rfc/rfc5321.html ;RFC 5322《Internet Message Format》§2.1.1 Line Length Limits,P. Resnick 编,2008 年 10 月,https://www.rfc-editor.org/rfc/rfc5322.html ;RFC 1870《SMTP Service Extension for Message Size Declaration》,J. Klensin、N. Freed、K. Moore,1995 年 11 月,STD 10,https://www.rfc-editor.org/rfc/rfc1870.html ;RFC 2045《Multipurpose Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies》,N. Freed、N. Borenstein,1996 年 11 月,https://www.rfc-editor.org/rfc/rfc2045.html ;RFC 6152《SMTP Service Extension for 8-bit MIME Transport》,J. Klensin 等,2011 年 3 月,STD 71,https://www.rfc-editor.org/rfc/rfc6152.html
