非官方中文译本声明:本页为 IETF RFC 5321《Simple Mail Transfer Protocol (SMTP)》 的中文译本,由 ztpop.net 整理翻译,仅供学习参考。RFC 文档由 IETF 发布,受 BCP 78 与 IETF 信托法律条款约束;本译本保留原文编号与结构,权威性以英文原文为准。英文原文见 rfc-editor.org/rfc/rfc5321。
RFC 5321:简单邮件传输协议(SMTP)
本备忘录的状态
本文档规定了面向互联网社群的互联网标准跟踪(Standards Track)协议,并征询改进意见与建议。有关本协议的标准化状态与现状,请参阅当前版本的《互联网官方协议标准》(STD 1)。本备忘录的分发不受限制。
摘要
本文档是 Internet 电子邮件传输基础协议的规范。它整合、更新并澄清了先前的若干文档,使其中大部分或全部内容被废弃。它涵盖了当代互联网中的 SMTP 扩展机制与最佳实践,但不提供关于特定扩展的细节。尽管 SMTP 被设计为邮件传输与投递协议,本规范也包含了对其用作"邮件提交"(mail submission)协议(供"分离式 UA"用户代理邮件阅读系统与移动环境使用)而言十分重要的信息。
版权声明
Copyright (c) 2008 IETF 信托及被列为文档作者的个人。保留所有权利。
本文档受 BCP 78 以及 IETF 信托的《IETF 文档相关法律规定》(http://trustee.ietf.org/license-info)约束,以本文档发布之日生效的版本为准。请仔细审阅这些文档,因为它们描述了您就本文档所享有的权利与限制。
目录
- 1. 引言
- 2. SMTP 模型
- 3. SMTP 过程:概述
- 4. SMTP 规范
- 5. 地址解析与邮件处理
- 6. 问题检测与处理
- 7. 安全考量
- 8. IANA 考量
- 9. 致谢
- 10. 参考文献
- 附录 A. TCP 传输服务
- 附录 B. 由 RFC 822 头字段生成 SMTP 命令
- 附录 C. 源路由
- 附录 D. 场景
- 附录 E. 其他网关问题
- 附录 F. RFC 821 的弃用特性
1. 引言
简单邮件传输协议(SMTP)的目标,是可靠且高效地传输邮件。
SMTP 独立于特定的传输子系统,仅要求一条可靠的、有序的数据流信道。尽管本文档专门讨论基于 TCP 的传输,但其他传输方式也是可能的。RFC 821 [1] 的附录描述了一些替代传输方式。
SMTP 的一个重要特性,是它能够跨多个网络传输邮件,通常称为"SMTP 邮件中继"(见第 3.6 节)。一个网络可以是公共 Internet 上彼此通过 TCP 互访的主机、防火墙隔离的 TCP/IP 内联网上彼此通过 TCP 互访的主机,或是利用非 TCP 传输层协议的某种其他 LAN 或 WAN 环境。借助 SMTP,一个进程可以把邮件传送给同一网络上的另一个进程,或通过两个网络均可访问的中继或网关进程,传送到其他网络。
如此,一封邮件在从发送方到最终收件人的路径上,可能经过若干中间中继或网关主机。域名系统(DNS)的邮件交换(Mail eXchanger)机制(RFC 1035 [2]、RFC 974 [12] 以及本文档第 5 节)用于确定被传输邮件的恰当下一跳目的地。
1.1. 电子邮件的传输
(本节标题译注:上段已就"电子邮件的传输"给出核心描述:SMTP 的目标是可靠高效地传邮,且可跨网络中继。)
1.2. 本文档的历史与背景
本文档是 Internet 电子邮件传输基础协议的规范。它整合、更新并澄清了以下文档,但不增加新的、也不改变其现有功能:
- RFC 821 [1] 中的原始 SMTP(简单邮件传输协议)规范;
- 来自 RFC 1035 [2] 与 RFC 974 [12] 的、与邮件传输相关的域名系统要求与含义;
- RFC 1123 [3] 中的澄清与适用性声明;
- 以及来自 RFC 1869 [13] 中 SMTP 扩展机制的材料。
它废弃了 RFC 821、RFC 974、RFC 1869 和 RFC 2821,并更新了 RFC 1123(取代 RFC 1123 中的邮件传输材料)。然而,RFC 821 规定了一些在 1990 年代中期已不再被 Internet 广泛使用、并在(附录中)给出一些额外传输模型的功能。出于清晰与简洁的目的,这些章节在此被略去;需要它们的读者应参阅 RFC 821。
它还纳入了 RFC 1123 中需要扩充的一些材料。这些材料通过多种方式被标识出来,主要是追踪各类邮件列表与新闻组中的争论,以及随着 SMTP 扩展的部署而出现的、对罕见解读所产生的种种问题。凡本规范超出整合范围并实际区别于早期文档之处,它在技术上与文字上都取代它们。
尽管 SMTP 被设计为邮件传输与投递协议,本规范也包含了对其用作"邮件提交"协议十分重要的信息——正如为邮政协议(POP,RFC 937 [15]、RFC 1939 [16])和 IMAP(RFC 3501 [17])所推荐的那样。一般而言,RFC 4409 [18] 中规定的独立邮件提交协议现在更受青睐,优于直接使用 SMTP;关于该主题的更多讨论见该文档。
第 2.3 节提供了本文档专用术语的定义。除非为清晰起见必须使用历史术语,本文档使用当前的"客户端(client)"与"服务器(server)"术语,分别指称发送与接收的 SMTP 进程。
配套文档 RFC 5322 [4] 讨论了报文头部分与主体,并为其规定了格式与结构。
1.3. 文档约定
本文档中的关键词"MUST(必须)"、"MUST NOT(不得)"、"REQUIRED(要求)"、"SHALL(应)"、"SHALL NOT(不应)"、"SHOULD(应该)"、"SHOULD NOT(不应该)"、"RECOMMENDED(推荐)"、"MAY(可以)"和"OPTIONAL(可选)"应依照 RFC 2119 [5] 中的描述进行解释。由于这些术语都是经过刻意而审慎地选取、用以提升电子邮件的互操作性,因此每次使用这些术语都应被视为一项一致性(conformance)要求。
由于本文档历史悠久,且为了避免各种错误、并避免混淆那些指向本文档的读者与其他文档,大多数示例及其所含的域名都沿用了 RFC 2821 的内容。提醒读者:这些只是示例,不应在实际的代码或配置文件中使用。
2. SMTP 模型
2.1. 基本结构
SMTP 的设计可以用下图表示:
+----------+ +----------+
+------+ | | | |
| User |<-->| | SMTP | |
+------+ | Client- |Commands/Replies| Server- |
+------+ | SMTP |<-------------->| SMTP | +------+
| File |<-->| | and Mail | |<-->| File |
|System| | | | | |System|
+------+ +----------+ +----------+ +------+
SMTP client SMTP server
当 SMTP 客户端有消息要传输时,它建立一条到 SMTP 服务器的双向传输信道。SMTP 客户端的职责是将邮件消息传送给一个或多个 SMTP 服务器,或报告其传送失败。
邮件消息如何被呈现给 SMTP 客户端,以及该客户端如何确定邮件消息要被传送到的域("名称")标识符,属于本地事务,不在本文档讨论范围之内。在某些情况下,指定的域(或 SMTP 客户端所确定的域)会标识邮件消息的最终目的地。在另一些情况下——对于与 POP(RFC 937 [15]、RFC 1939 [16])或 IMAP(RFC 3501 [17])协议实现相关联的 SMTP 客户端,或当 SMTP 客户端处于隔离的传输服务环境中时——所确定的域会标识一个中间目的地,所有邮件消息都要经由它进行中继。那些不论目标域如何都传输全部流量、或不维护用于重试初始无法完成的消息传输的队列的 SMTP 客户端,虽也可能符合本规范,但被视为不具备完整能力。期望具备完整能力的 SMTP 实现(包括这些能力较弱者所使用的中继及其目的地)支持本规范中讨论的全部排队、重试与备用地址功能。在许多情境与配置下,上述能力较弱的客户端应当使用邮件提交协议(RFC 4409 [18])而非 SMTP。
一旦 SMTP 客户端确定了目标域,它如何确定要将消息副本传送到的 SMTP 服务器的身份、并随后执行该传送,属于本文档的覆盖范围。为向某个 SMTP 服务器传送邮件,SMTP 客户端建立一条到该服务器的双向传输信道。SMTP 客户端通过将目标域名解析为某个中间邮件交换主机或最终目标主机,来确定运行 SMTP 服务器的恰当主机的地址。
SMTP 服务器可以是最终目的地,也可以是中间"中继"(即:在收到消息后可以担当 SMTP 客户端的角色),或"网关"(即:它可以使用 SMTP 以外的某种协议进一步传输消息)。SMTP 命令由 SMTP 客户端生成并发送给 SMTP 服务器。SMTP 应答由 SMTP 服务器发送给 SMTP 客户端,以响应这些命令。
换言之,消息传输可以发生在原始 SMTP 发送方与最终 SMTP 接收方之间的单一连接中,也可以经由中间系统的一系列跳数发生。无论哪种情况,一旦服务器在邮件数据末尾发出成功应答,就发生了一次正式的责任移交:协议要求服务器必须承担投递消息或妥善报告投递失败的责任(见下文第 6.1、6.2 和 7.8 节)。
一旦传输信道建立且初始握手完成,SMTP 客户端通常会启动一个邮件事务。这样的一个事务由一系列命令组成,用以指定邮件的发起者与目的地,并传输消息内容本身(包括头部分中的任何行或其他结构)。当同一消息发送给多个收件人时,本协议鼓励只为目标(或中间中继)主机上的所有收件人传输一份数据副本。
服务器以应答响应每条命令;应答可以表示命令已被接受、期望更多命令,或存在临时或永久错误状况。指定发送方或收件人的命令可以包含服务器所允许的 SMTP 服务扩展请求,如第 2.2 节所讨论。这种对话(dialog)刻意地采用锁步(lock-step)、逐条进行的方式,尽管这可以通过双方约定的扩展请求(如命令流水线化,RFC 2920 [19])来改变。
一旦某封邮件消息被传输完毕,客户端可以请求关闭连接,也可以启动其他邮件事务。此外,SMTP 客户端可以利用到 SMTP 服务器的连接来使用辅助服务,例如验证电子邮件地址或获取邮件列表订户地址。
如上所述,本协议提供了邮件传输的机制。历史上,当两个主机连接到同一传输服务时,这种传输通常直接从发送用户的主机发生到接收用户的主机。当它们未连接到同一传输服务时,传输经由一个或多个中继 SMTP 服务器发生。当今 Internet 上一种非常常见的情况是:将原始消息提交给一个中间的"邮件提交"服务器,它类似于中继但具有一些附加属性;此类服务器在第 2.3.10 节以及 RFC 4409 [18] 中有相当篇幅的讨论。作为 SMTP 中继或通向其他传输环境的网关的中间主机,通常通过域名服务(DNS)的邮件交换机制来选定。
通常,中间主机由 DNS 的 MX 记录确定,而非通过显式的"源"路由(见第 5 节以及附录 C 与附录 F.2)。
2.2. 扩展模型
2.2.1. 背景
在始于 1990 年、即 RFC 821 完成约十年后的一项工作中,该协议被一个"服务扩展"模型所改造,该模型允许客户端与服务器约定利用超出原始 SMTP 要求之外的共享功能。SMTP 扩展机制定义了一种方式,使扩展的 SMTP 客户端与服务器能够彼此识别,并且服务器可以告知客户端它所支持的服务扩展。
当代的 SMTP 实现必须支持基本的扩展机制。例如,服务器必须支持 EHLO 命令,即便它们未实现任何具体扩展;客户端应当优先使用 EHLO 而非 HELO。(然而,为了与较早的一致实现兼容,SMTP 客户端与服务器必须支持原始的 HELO 机制作为回退。)除非出于互操作性目的必须标识 HELO 的不同特性,本文档只讨论 EHLO。
SMTP 被广泛部署,高质量的实现已被证明非常健壮。然而,Internet 社群现在认为某些服务十分重要,而它们在协议最初设计时并未被预期到。如果要添加对这些服务的支持,必须以一种允许较早实现继续可接受地工作的方式来进行。扩展框架由以下部分组成:
- SMTP 命令 EHLO,取代较早的 HELO;
- 一个 SMTP 服务扩展的注册表;
- SMTP 的 MAIL 与 RCPT 命令的附加参数;
- 对本协议中定义命令的可选替换,例如用于非 ASCII 传输的 DATA 替换(RFC 3030 [20])。
SMTP 的优势主要来自其简洁性。许多协议的实践经验表明:选项少的协议趋向于普及,而选项多的协议趋向于湮没无闻。
每一项扩展,无论其收益如何,都必须就其实现、部署与互操作性成本被仔细审视。在许多情况下,扩展 SMTP 服务的成本很可能超过其收益。
2.2.2. 扩展的定义与注册
IANA 维护着一个 SMTP 服务扩展的注册表。每个扩展都关联一个相应的 EHLO 关键字值。每个在 IANA 注册的 SMTP 服务扩展,必须在一个正式的 Standards-Track 或 IESG 批准的实验性协议文档中定义。该定义必须包含:
- SMTP 服务扩展的文本名称;
- 与该扩展关联的 EHLO 关键字值;
- 与 EHLO 关键字值关联的参数之语法与可能取值;
- 该扩展关联的任何附加 SMTP 动词(附加动词通常、但不要求是,与 EHLO 关键字值相同);
- 该扩展与 MAIL 或 RCPT 动词关联的任何新参数;
- 关于对该扩展的支持如何影响服务器与客户端 SMTP 行为的描述;
- 以及该扩展使命令 MAIL 和/或 RCPT 的最大长度相对于本标准所规定者增加的增量。
此外,任何以大写或小写"X"开头的 EHLO 关键字值,都指代仅通过双边协议使用的本地 SMTP 服务扩展。以"X"开头的关键字不得用于已注册的扩展。反之,EHLO 应答中给出的、不以"X"开头的关键字值,必须对应于已在 IANA 注册的、标准的、Standards-Track 的、或 IESG 批准的实验性 SMTP 服务扩展。一致的服务器不得提供未在某项已注册扩展中描述的、非"X"前缀的关键字值。
附加动词与参数名受与 EHLO 关键字相同的规则约束;具体而言,以"X"开头的动词是本地扩展,不得被注册或标准化。反之,不以"X"开头的动词必须始终被注册。
2.2.3. 扩展的特殊问题
允许改变 SMTP 相当基本属性的扩展。理解本文档其他章节的文字时必须置于这一背景之下。特别是,扩展可以改变第 4.5.3 节中规定的最小限制,可以改变上文提到的 ASCII 字符集要求,或可以引入某些可选的消息处理模式。
特别地,如果某个扩展意味着投递路径通常会支持该扩展的特殊特性,而某个中间 SMTP 系统发现下一跳并不支持所需扩展,则它可以根据具体扩展与情形,选择将消息重新排队并稍后重试和/或尝试另一个 MX 主机。如果采用此策略,在回退到非扩展格式(若可用)之前的超时,应当小于将邮件作为不可投递而退信的常规超时(例如,若常规超时为三天,则在尝试不带该扩展发送邮件之前的重排超时可能是一天)。
2.3. SMTP 术语
2.3.1. 邮件对象
SMTP 传输一个邮件对象。一个邮件对象包含一个信封(envelope)与内容(content)。
SMTP 信封作为一系列 SMTP 协议单元(在第 3 节中描述)发送。它由发起者地址(错误报告应当发往该地址)、一个或多个收件人地址,以及可选的协议扩展材料组成。历史上,反向路径(发起者)地址指定命令(MAIL)的变体曾被用来指定替代投递模式,例如立即显示;这些变体现已被废弃(见附录 F 与附录 F.6)。
SMTP 内容在 SMTP 的 DATA 协议单元中发送,并由两部分组成:头部分与主体。如果内容符合其他当代标准,头部分由一组头字段组成,每个头字段由头名、冒号与数据构成,其结构如报文格式规范(RFC 5322 [4])所示;主体若结构化,则按 MIME(RFC 2045 [21])定义。内容本质上是文本性的,使用 US-ASCII 字符集 [6] 表达。尽管 SMTP 扩展(如"8BITMIME",RFC 1652 [22])可以放宽对内容主体的这一限制,内容头字段始终使用 US-ASCII 字符集编码。两个 MIME 扩展(RFC 2047 [23] 与 RFC 2231 [24])定义了一种算法,用于在仍使用 US-ASCII 字符集编码的同时,表示 US-ASCII 字符集之外的头值。
2.3.2. 发送方与接收方
在 RFC 821 中,参与 SMTP 事务的两台主机被称为"SMTP-sender"与"SMTP-receiver"。本文档已改为反映当前的行业术语,因此分别称它们为"SMTP 客户端"(client,或有时仅称"客户端")与"SMTP 服务器"(server,或仅称"服务器")。由于给定主机在 relay 情形下可能同时充当服务器与客户端,在需要清晰之处仍使用"接收方"与"发送方"术语。
2.3.3. 邮件代理与报文存储
RFC 821 发布之后,一些额外的邮件系统术语变得常见,并且在方便之处被用于本规范。特别是,SMTP 服务器与客户端提供邮件传输服务,因此充当"邮件传输代理"(MTA,Mail Transfer Agents)。"邮件用户代理"(MUA 或 UA,Mail User Agents)通常被视为邮件的来源与目标。在源头,一个 MUA 可能收集要传输的用户邮件并将其交给一个 MTA;最终的("投递")MTA 被视为将邮件交给一个 MUA(或至少将责任移交给它,例如,通过将消息存入一个"报文存储"(message store))。然而,尽管这些术语在其他环境中以至少表面上极高的精度被使用,MUA 与 MTA 之间所暗示的边界往往并不准确对应 Internet 邮件中常见且一致的做法。因此,读者在推断这些术语若在别处使用所可能暗示的强关系与责任时应当谨慎。
2.3.4. 主机
就本规范而言,主机是连接到 Internet(或某些情况下连接到私有 TCP/IP 网络)并支持 SMTP 协议的计算机系统。主机以名称(见下一节)为人所知;它们不应以数字地址标识,即不应以第 4.1.2 节所述的地址字面量(address literals)标识。
2.3.5. 域名
域名(或常简称为"域")由一个或多个部分组成,若不止一个部分则以点分隔。在电子邮件地址中单独使用顶级域的情况下,使用不含任何点的单一字符串。这使得下文更详细描述的、要求只有完全限定域名(FQDN)出现在公共 Internet 上的 SMTP 事务中的要求,在涉及顶级域时显得尤为重要。这些部分(DNS 术语中的"标签",RFC 1035 [2])为 SMTP 之目的被限制为:由取自 ASCII 字符集 [6] 的字母、数字与连字符组成的序列。域名被用作主机名以及域层次结构中其他实体的名称。例如,一个域可以指代一个别名(CNAME 资源记录的标签),或指代用于投递邮件而非代表主机名的邮件交换记录的标签。参见 RFC 1035 [2] 以及本规范第 5 节。
如本文档与 RFC 1035 [2] 所描述的,域名是完整的、完全限定的名称(常称为"FQDN")。非 FQDN 形式的域名不过是一个本地别名。本地别名不得出现在任何 SMTP 事务中。
当域名被用于 SMTP 时,只允许可解析的、完全限定的域名(FQDN)。换言之,可被解析为 MX 资源记录或地址(即 A 或 AAAA)资源记录(如第 5 节所讨论)的名称是允许的,同样,其目标又可被解析为 MX 或地址资源记录的 CNAME 资源记录也是允许的。本地的昵称或非限定名称不得使用。要求使用 FQDN 的规则有两个例外:
- EHLO 命令中给出的域名必须是一个主主机名(解析到地址资源记录的域名),或者,若该主机没有名称,则为一个地址字面量,如第 4.1.3 节所述,并在第 4.1.4 节的 EHLO 讨论中有进一步讨论。
- 保留的邮箱名"postmaster"可以在 RCPT 命令中不带域限定地使用(见第 4.1.1.3 节),并且若如此使用则必须被接受。
2.3.6. 缓冲区与状态表
SMTP 会话是有状态的,双方都仔细维护对当前状态的共同视图。在本文档中,我们将此状态建模为服务器上的一个虚拟"缓冲区"与一个"状态表",客户端可利用它们,例如"清空缓冲区"或"重置状态表",使缓冲区中的信息被丢弃、状态回到某个先前的状态。
2.3.7. 命令与应答
SMTP 命令,以及(除非被服务扩展改变)邮件数据,由发送方经传输信道以"行"的方式传送给接收方。
SMTP 应答是由接收方经传输信道以"行"的方式、作为对命令的响应而发送的一个确认(肯定或否定)。应答的一般形式是一个数字完成码(指示失败或成功),其后通常跟随一个文本字符串。这些代码供程序使用,而文本通常面向人类用户。RFC 3463 [25] 对应答字符串规定了进一步的结构化,包括使用补充的、更具体的完成码(另见 RFC 5248 [26])。
2.3.8. 行
行由零个或多个数据字符组成,并以 ASCII 字符"CR"(十六进制值 0D)紧接 ASCII 字符"LF"(十六进制值 0A)的序列终止。该终止序列在本文档中记为 <CRLF>。一致的实现不得识别或生成任何其他字符或字符序列作为行终止符。服务器可以对行长度施加限制(见第 4 节)。
此外,"裸露的"CR 或 LF 字符出现在文本中(即二者缺一)长期来在邮件实现以及将邮件系统作为工具使用的应用程序中引发问题。SMTP 客户端实现不得传输这些字符,除非它们意在作为行终止符,并且此时必须如上所述、只以 <CRLF> 序列传输它们。
2.3.9. 报文内容与邮件数据
术语"报文内容"(message content)与"邮件数据"(mail data)在本文档中可互换使用,用以描述在 DATA 命令被接受之后、并在数据结束指示被传输之前所传输的材料。报文内容包含报文头部分以及可能结构化的报文主体。MIME 规范(RFC 2045 [21])提供了结构化报文主体的标准机制。
2.3.10. 发起、投递、中继与网关系统
本规范根据四类 SMTP 系统在传输电子邮件中所扮演的角色进行区分。一个"发起"(originating)系统(有时称为 SMTP 发起者)将邮件引入 Internet,或更一般地说,引入一个传输服务环境。一个"投递"(delivery)SMTP 系统从传输服务环境接收邮件,并将其传递给一个邮件用户代理,或将其存入一个邮件用户代理预期随后访问的报文存储。一个"中继"(relay)SMTP 系统(通常简称为"中继")从一个 SMTP 客户端接收邮件,并在不修改消息数据(添加跟踪信息除外)的情况下,将其传输给另一个 SMTP 服务器以进一步中继或投递。
一个"网关"(gateway)SMTP 系统(通常简称为"网关")从一个传输环境中的客户端系统接收邮件,并将其传输给另一个传输环境中的服务器系统。网关两侧的传输环境之间在协议或消息语义上的差异,可能要求网关系统对消息执行 SMTP 中继系统所不允许的变换。就本规范而言,重写地址的防火墙应被视为网关,即便其两侧都使用 SMTP(见 RFC 2979 [27])。
2.3.11. 邮箱与地址
如本规范中所用,"地址"(address)是一个标识向其发送邮件的用户、或邮件将被存入其中的位置的字符串。"邮箱"(mailbox)指该存放处。这两个术语通常可互换使用,除非存放邮件的位置(邮箱)与对其的引用(地址)之间的区别很重要。一个地址通常由用户与域的规格组成。标准邮箱命名约定被定义为"local-part@domain";当代用法允许比简单"用户名"广泛得多的应用集合。因此,并且由于中间主机试图通过修改它们来优化传输的长期历史问题,local-part 必须只由地址的域部分所指定的主机来解释并赋予语义。
2.4. 通用语法原则与事务模型
SMTP 命令与应答具有严格的语法。所有命令以一个命令动词开头。所有应答以一个三位数字代码开头。在某些命令与应答中,动词或应答代码之后需要参数。有些命令不接受参数(在动词之后),有些应答代码之后有时可选地跟随自由格式文本。两种情况下,文本出现时,都以一个空格字符与动词或应答代码分隔。命令与应答的完整定义见第 4 节。
动词与参数值(例如,RCPT 命令中的"TO:"或"to:",以及扩展名关键字)不区分大小写,本规范中唯一的例外是邮箱的 local-part(SMTP 扩展可以显式指定区分大小写的元素)。也就是说,命令动词、除邮箱 local-part 之外的参数值,以及自由格式文本,可以用大写、小写或大小写任意混合来编码,对其含义没有影响。邮箱的 local-part 必须被视为区分大小写。因此,SMTP 实现必须注意保留邮箱 local-part 的大小写。特别是,对于某些主机,用户"smith"不同于用户"Smith"。然而,利用邮箱 local-part 的大小写敏感性会妨碍互操作性,因此不被鼓励。邮箱域遵循正常的 DNS 规则,因而不区分大小写。
少数 SMTP 服务器(违反了本规范与 RFC 821)要求客户端以大写编码命令动词。实现可以但愿采用这种编码以兼容那些服务器。
参数子句由一个可变长度的字符串组成,以行尾(即字符序列 <CRLF>)结束。在收到该序列之前,接收方不采取任何动作。
每条命令的语法在该命令的讨论中给出。公共元素与参数在第 4.1.2 节给出。
命令与应答由 ASCII 字符集 [6] 中的字符组成。当传输服务提供 8 位字节(八位组)传输信道时,每个 7 位字符以右对齐方式在一个八位组中传输,高位置零。更具体地说,未扩展的 SMTP 服务只提供 7 位传输。
一个未与特定服务器成功协商适当扩展的发起 SMTP 客户端(见下一段),不得传输八位组高位含信息的消息。如果违反此规则传输了此类消息,接收 SMTP 服务器可以清除高位或将消息作为无效而拒绝。一般而言,中继 SMTP 应当假定它所收到的消息内容是有效的,并且在信封允许的情况下,不经检查该内容就对其进行中继。当然,如果内容被错误标记且数据路径无法接受实际内容,这可能导致最终投递给收件人的是严重乱码的消息。投递 SMTP 系统可以拒绝此类消息,或将其作为不可投递退回,而非投递它们。在服务器未提供显式允许此事的扩展的情况下,发送 SMTP 系统不得用 US-ASCII 之外的任何字符集发送信封命令。接收系统应当拒绝此类命令,通常使用"500 语法错误 - 无效字符"应答。
客户端可以使用扩展 SMTP 设施(特别是"8BITMIME"扩展,RFC 1652 [22])向服务器请求 8 位消息内容传输。SMTP 服务器应当支持 8BITMIME。然而,它不得被解释为授权传输不受限制的 8 位材料,8BITMIME 也不授权以非 ASCII 传输任何信封材料。对于高位置位、且未采用带有适当内容传输编码的 MIME 格式的材料,发送方不得请求 8BITMIME;服务器可以拒绝此类消息。
本文档所使用的元语言记号对应于其他 Internet 邮件系统文档中使用的"扩充 BNF"。不熟悉该语法的读者应查阅 RFC 5234 [7] 中的 ABNF 规范。正文中的元语言术语为清晰起见用尖括号括起(例如 <CRLF>)。提醒读者:元语言所表达的文法并非全面的。文本中的许多规定约束或以其他方式修改了文法所暗示的语法或语义。
3. SMTP 过程:概述
本节包含对 SMTP 中所用过程的描述:会话启动、邮件事务、邮件转发、验证邮箱名与展开邮件列表,以及打开与关闭交换。关于中继的评论、关于邮件域的说明,以及关于角色变化的讨论包含在本节末尾。几个完整的场景在附录 D 中给出。
3.1. 会话启动
当客户端打开到服务器的连接、且服务器以一个开场消息响应时,一个 SMTP 会话便启动了。
SMTP 服务器实现可以在 220 代码之后的连接问候应答中包括其软件与版本信息的标识,这一做法有助于更高效地隔离与修复任何问题。实现可以为 SMTP 服务器提供关闭软件与版本宣告的选项,当它会引发安全顾虑时。尽管某些系统也标识其邮件问题的联系点,但这并不能替代维护所需的"postmaster"地址(见第 4 节)。
SMTP 协议允许服务器在仍允许初始连接的情况下正式拒绝邮件会话,方式如下:可以在初始连接开场消息中给出 554 应答,而非 220。采取这种方式的服务器仍必须等待客户端发送 QUIT(见第 4.1.1.10 节)后再关闭连接,并且应当用"503 命令顺序错误"响应任何中间的命令。由于试图向此类系统建立 SMTP 连接可能是错误的,在连接开场时返回 554 应答的服务器应当在应答文本中提供足够信息,以方便调试发送系统。
3.2. 客户端启动
一旦服务器发送了问候(welcoming)消息且客户端已收到它,客户端通常向服务器发送 EHLO 命令,表明客户端的身份。除开启会话外,使用 EHLO 还表明客户端能够处理服务扩展,并请求服务器提供它所支持的扩展列表。无法支持服务扩展的较早 SMTP 系统,以及不要求邮件会话中有服务扩展的当代客户端,可以使用 HELO 代替 EHLO。服务器不得向 HELO 命令返回扩展的 EHLO 风格应答。对于特定的连接尝试,如果服务器对 EHLO 返回"命令无法识别"应答,客户端应当能够回退并发送 HELO。
在 EHLO 命令中,发送命令的主机标识自身;该命令可被解释为"你好,我是 <domain>"(并且在 EHLO 的情况下,"并且我支持服务扩展请求")。
3.3. 邮件事务
SMTP 邮件事务有三个步骤。事务以一条给出发送方标识的 MAIL 命令开始。(一般而言,MAIL 命令只能在没有邮件事务进行时才可发送;见第 4.1.4 节。)随后是一系列一条或多条 RCPT 命令,给出接收方信息。然后,一条 DATA 命令启动邮件数据的传输,并由"邮件结束"数据指示符终止,该指示符同时确认事务。
该过程的第一步是 MAIL 命令。
MAIL FROM:<reverse-path> [SP <mail-parameters> ] <CRLF>
该命令告诉 SMTP 接收方一个新的邮件事务正在开始,并重置其所有状态表与缓冲区,包括任何收件人或邮件数据。第一个或唯一参数的 <reverse-path> 部分包含源邮箱(位于"<"与">"括号之间),可用于报告错误(关于错误报告的讨论见第 4.2 节)。如果被接受,SMTP 服务器返回"250 OK"应答。如果邮箱规格因某种原因不可接受,服务器必须返回一个应答,指明该失败是永久的(即,若客户端尝试再次发送同一地址会再次发生)还是临时的(即,若客户端稍后重试该地址可能被接受)。尽管此要求看似范围广泛,仍存在某些情形,其中反向路径的可接受性要等到一个或多个正向路径(在 RCPT 命令中)被检查后才能确定。在这些情况下,服务器可以合理地接受反向路径(以 250 应答),然后在正向路径被收到并检查后报告问题。通常,失败产生 550 或 553 应答。
历史上,<reverse-path> 曾被允许包含不止一个邮箱;然而,当代系统不应使用源路由(见附录 C)。
可选的 <mail-parameters> 与协商好的 SMTP 服务扩展相关联(见第 2.2 节)。
该过程的第二步是 RCPT 命令。这一步可以重复任意次数。
RCPT TO:<forward-path> [ SP <rcpt-parameters> ] <CRLF>
该命令的第一个或唯一参数包含一个正向路径(通常是一个邮箱与域,总是被"<"与">"括号包围),标识一个收件人。如果被接受,SMTP 服务器返回"250 OK"应答并存储该正向路径。如果收件人已知不是一个可投递地址,SMTP 服务器返回 550 应答,通常带有如"no such user - "以及邮箱名的字符串(其他情形与应答码是可能的)。
<forward-path> 可以包含不止一个邮箱。历史上,<forward-path> 曾被允许包含一个源路由主机列表与目的邮箱;然而,当代 SMTP 客户端不应使用源路由(见附录 C)。服务器必须准备好遇到正向路径中的源路由列表,但它们应当忽略这些路由,或可以拒绝支持它们所意味的中继。类似地,服务器可以拒绝接受发往其他主机或系统的邮件。这些限制使服务器对于不支持完整 SMTP 功能的客户端而言无法作为中继使用。因此,受限能力的客户端不得假设 Internet 上任何 SMTP 服务器都能被用作它们的邮件处理(中继)站点。如果一条 RCPT 命令出现在前一条 MAIL 命令之前,服务器必须返回 503"命令顺序错误"应答。可选的 <rcpt-parameters> 与协商好的 SMTP 服务扩展相关联(见第 2.2 节)。
由于这曾是一个常见的错误来源,值得指出:在 MAIL 命令中 FROM 之后的冒号两侧、或 RCPT 命令中 TO 之后的冒号两侧,都不允许有空格。语法恰如上文所给出。
该过程的第三步是 DATA 命令(或某项服务扩展中规定的某种替代)。
DATA <CRLF>
如果被接受,SMTP 服务器返回一个 354 中间应答,并将其后直到(但不包括)邮件数据结束指示符的所有后续行视为消息文本。当文本成功收到并存储时,SMTP 接收方发送一个"250 OK"应答。
由于邮件数据在传输信道上发送,必须指示邮件数据的结束,以便命令与应答对话可以恢复。SMTP 通过发送一个只包含"."(句点或句号)的行来指示邮件数据的结束。使用一种透明化(transparency)过程来防止这干扰用户的文本(见第 4.5.2 节)。
邮件数据结束指示符同时确认邮件事务,并通知 SMTP 服务器现在处理所存储的收件人与邮件数据。如果被接受,SMTP 服务器返回一个"250 OK"应答。DATA 命令只能在协议交换的两个点上失败:
如果没有 MAIL,或没有 RCPT,命令,或所有此类命令都被拒绝,服务器可以在响应 DATA 命令时返回"命令超出顺序"(503)或"无有效收件人"(554)应答。如果收到这些应答(或任何其他 5yz 应答)之一,客户端不得发送消息数据;更一般地说,除非收到 354 应答,否则不得发送消息数据。
如果动词最初被接受且发出了 354 应答,DATA 命令应当只在邮件事务不完整(例如,无收件人)、资源不可用(当然包括服务器意外变得不可用),或服务器基于策略或其他原因决定拒绝该消息时失败。
然而,在实践中,某些服务器直到消息文本被收到之后才执行收件人验证。这些服务器应当将一个或多个收件人的失败视为"后续失败",并返回如第 6 节、特别是第 6.1 节所讨论的邮件消息。在数据被接受之后使用"550 邮箱未找到"(或等同)应答码,会使客户端难以或无法断定哪些收件人失败。
当使用 RFC 822 格式([28]、[4])时,邮件数据包含诸如 Date、Subject、To、Cc 与 From 等头字段。服务器 SMTP 系统不应基于 RFC 822 或 MIME(RFC 2045 [21])报文头部分或报文主体中察觉到的缺陷而拒绝消息。特别地,它们不得拒绝那些 Resent- 头字段数量不匹配、或 Resent-to 出现却没有 Resent-from 和/或 Resent-date 的消息。
邮件事务命令必须按上述顺序使用。
3.4. 用于地址更正或更新的转发
对转发支持的需求,最常见的是为了在企业内部或相对于某企业整合与简化地址,较少情况下是为了建立地址以将一个人的先前地址与当前地址联系起来。出于安全或不披露目的、对消息进行静默转发(不向发送方通知服务器),在当代 Internet 中很常见。
在企业与"新地址"两种情况下,信息隐藏(有时是安全)的考量都反对通过 SMTP 协议将"最终"地址作为转发活动的副作用暴露出来。当最终地址甚至发送方都无法到达时,这一点可能特别重要。因此,RFC 821 第 3.2 节描述的"转发"机制,特别是 RCPT 的 251(已更正目的地)与 551 应答码,必须由实现者仔细评估,并且在它们可用时,由那些配置系统的人仔细评估(另见第 7.4 节)。
特别地:
- 当服务器知悉地址变更时,可以转发消息。当它们这样做时,可以用 251 码提供地址更新信息,或者可以"静默"转发并返回 250 码。然而,如果使用 251 码,它们不得假设客户端会实际更新地址信息,甚至会将那信息返回给用户。
或者:
- 当消息无法按寻址精确投递时,服务器可以将其拒绝或作为不可投递退回。当它们这样做时,可以用 551 码提供地址更新信息,或者用 550 码且无任何地址特定信息将消息作为不可投递拒绝。然而,如果使用 551 码,它们不得假设客户端会实际更新地址信息,甚至会将那信息返回给用户。
支持 251 和/或 551 应答码的 SMTP 服务器实现应当提供配置机制,以便那些认为会不当地披露信息的站点可以禁用或限制其使用。
3.5. 用于调试地址的命令
3.5.1. 概述
SMTP 提供命令以验证用户名或获取邮件列表的内容。这通过带有字符串参数的 VRFY 与 EXPN 命令完成。实现应当支持 VRFY 与 EXPN(然而,见第 3.5.2 节与第 7.3 节)。
对于 VRFY 命令,字符串是一个用户名或用户名加域(见下)。如果返回正常(即 250)应答,应答可以包括用户的全名,并且必须包括用户的邮箱。它必须采用以下两种形式之一:
User Name <local-part@domain> local-part@domain
当一个作为 VRFY 参数的名字可能标识多个邮箱时,服务器可以指出歧义或标识出各个候选项。换言之,以下任何一项都是对 VRFY 的合法应答:
553 User ambiguous or 553- Ambiguous; Possibilities are 553-Joe Smith <jsmith@foo.com> 553-Harry Smith <hsmith@foo.com> 553 Melvin Smith <dweep@foo.com> or 553-Ambiguous; Possibilities 553- <jsmith@foo.com> 553- <hsmith@foo.com> 553 <dweep@foo.com>
在正常情况下,收到 553 应答的客户端预期会将结果暴露给用户。使用所给出的确切形式,以及"user ambiguous"或"ambiguous"关键字,可能辅以扩展应答码(如 RFC 3463 [25] 所述),将有助于按需自动翻译成其他语言。当然,一个高度自动化的客户端,或运行于非英语环境的客户端,可以选择尝试翻译该应答,以向用户返回不同于应答原文的其他指示,或采取某些自动化动作(例如在向用户报告之前查阅目录服务以获取额外信息)。
对于 EXPN 命令,字符串标识一个邮件列表,成功的(即 250)多行应答可以包括用户的全名,并且必须给出邮件列表上的邮箱。
在某些主机上,邮件列表与单个邮箱的别名之间的区别有些模糊,因为一种常见的数据结构可以容纳两类条目,并且可能存在只含一个邮箱的邮件列表。如果请求对邮件列表应用 VRFY,若如此寻址的消息会被投递给列表上的每个人,则可以给出肯定应答,否则应当报告错误(例如"550 那是一个邮件列表,不是用户"或"252 无法验证邮件列表的成员")。如果请求展开一个用户名,服务器可以返回
550 That is a mailing list, not a user
也可以返回由包含单个名字的列表组成的肯定应答,或者报告错误(例如"550 那是一个用户名,不是邮件列表")。
在成功多行应答(EXPN 的正常情况)的情况下,应答的每一行正好指定一个邮箱。歧义请求的情况见上文讨论。
"用户名"是一个模糊的术语,被有意使用。VRFY 或 EXPN 命令的实现必须至少包含对本地邮箱作为"用户名"的识别。然而,由于当代 Internet 实践常常导致单个主机为多个域处理邮件,主机——尤其是提供此功能的主机——应当接受"local-part@domain"形式作为"用户名";主机也可以自行选择将其他字符串识别为"用户名"。
展开邮箱列表的情况需要多行应答,例如:
C: EXPN Example-People S: 250-Jon Postel <Postel@isi.edu> S: 250-Fred Fonebone <Fonebone@physics.foo-u.edu> S: 250 Sam Q. Smith <SQSmith@specific.generic.com> or C: EXPN Executive-Washroom-List S: 550 Access Denied to You.
VRFY 与 EXPN 命令的字符串参数由于用户名与邮箱列表概念实现的多样性而无法进一步限制。在某些系统上,EXPN 命令的参数是一个包含邮件列表的文件名或许是恰当的,但 Internet 上同样存在各种各样的文件命名约定。类似地,这些命令返回内容的历代差异使得该应答应当非常谨慎地解释(若有的话),并且通常只应用于诊断目的。
3.5.2. VRFY 的正常应答
当从 VRFY 或 EXPN 请求返回正常(2yz 或 551)应答时,应答必须包含使用"<local-part@domain>"构造的 <Mailbox> 名,其中"domain"是一个完全限定域名。在特殊到足以证明违反本规范意图的情形下,可以返回自由格式文本。为了便于计算机与人都易于解析,地址应当出现在尖括号中。当返回的是地址而非自由格式调试信息时,EXPN 与 VRFY 必须只返回可在 SMTP 的 RCPT 命令中使用的有效域地址。因此,如果某个地址意味着投递给某个程序或其他系统,则必须给出用于到达该目标的邮箱名。路径(显式源路由)不得由 VRFY 或 EXPN 返回。
服务器实现应当同时支持 VRFY 与 EXPN。出于安全原因,实现可以通过配置选项或等价物,为本地安装提供禁用这两个命令之一或两者的方式(见第 7.3 节)。当支持这些命令时,在支持中继的情况下,它们不要求跨中继工作。由于它们在 RFC 821 中都是可选的,但 VRFY 在 RFC 1123 [3] 中被设为强制,如果支持 EXPN,它必须作为服务扩展列在 EHLO 应答中。VRFY 可以列为方便起见,但由于对其的支持是要求的,SMTP 客户端在使用它之前不需要检查扩展列表上是否存在它。
3.5.3. VRFY 或 EXPN 成功应答的含义
服务器不得在尚未实际验证地址的情况下,就针对 VRFY 或 EXPN 命令返回 250 码。特别地,如果服务器所做的全部只是验证所给语法有效,则不得返回 250。在这种情况下,应当返回 502(命令未实现)或 500(语法错误,命令无法识别)。如别处所述,对 VRFY 与 EXPN 的实现(即实际验证地址并返回信息的意义)是强烈推荐的。因此,为 VRFY 返回 500 或 502 的实现并未完全符合本规范。
可能存在这样的情形:一个地址看似有效,但无法合理地实时验证,特别是当服务器充当另一个服务器或域的邮件交换器时。"表观有效性"在这种情况下通常至少涉及语法检查,并可能涉及验证任何指定域都是主机预期能够向其中继邮件的域。在这些情况下,应当返回应答码 252。这些情形与第 2.1 节中 RCPT 验证的讨论类似。类似地,第 3.4 节的讨论适用于将应答码 251 与 551 用于 VRFY(及 EXPN),以指示那些被识别、但若收到发给它们的邮件会被转发或拒绝的地址。一般而言,实现在 VRFY 情况下应当比在 RCPT 情况下更积极地进行地址验证,即便这样做会多花一点时间。
3.5.4. EXPN 的语义与应用
EXPN 在调试与理解邮件列表及多目标地址别名的问题时常常非常有用。某些系统曾试图使用邮件列表的源展开作为消除重复的手段。随着邮件在 Internet 上通过主机(通常借助 MX 与 CNAME 的 DNS 记录)、通过邮箱(各类本地主机别名)以及在各种代理安排中进行别名化系统的传播,已使这些策略几乎不可能一致地工作,邮件系统不应尝试它们。
3.6. 中继与邮件路由
3.6.1. 源路由与中继
一般而言,域名系统中邮件交换记录(RFC 1035 [2]、RFC 974 [12])的存在,使得在 Internet 邮件系统中使用显式源路由成为不必要。许多关于显式源路由解释的历史问题已使它们的使用不受欢迎。SMTP 客户端不应生成显式源路由,除非在异常情形下。SMTP 服务器可以拒绝充当邮件中继,或拒绝接受指定了源路由的地址。当遇到路由信息时,SMTP 服务器可以忽略路由信息,而简单地发送到路由中最后一个元素指定的最终目的地,并且应当这样做。存在一种无效的做法,即使用不出现在 DNS 中的名称作为目的地名称,发送方指望源路由中指定的中间主机解决任何问题。如果源路由被剥离,这种做法将导致失败。这是 SMTP 客户端不得生成无效源路由或依赖名称串行解析的若干原因之一。
当不使用源路由时,RFC 821 中从正向路径构造反向路径的过程不再适用,投递时的反向路径将仅仅是出现在 MAIL 命令中的地址。
3.6.2. 邮件交换记录与中继
中继 SMTP 服务器通常是将其指定为目标的 DNS MX 记录的对象,而非最终投递系统。中继服务器可以如同它接受或拒绝本地用户的邮件一样,接受或拒绝中继该邮件的任务。如果它接受该任务,它便成为 SMTP 客户端,根据第 5 节的规则建立到 DNS 中指定的下一个 SMTP 服务器的传输信道,并将邮件发送给它。如果它出于策略原因拒绝中继到某个特定地址,应当返回 550 应答。
本规范不处理用于投递通知的返回路径验证。近期的工作,如关于 SPF [29] 与 DKIM [30] [31] 的工作,已被用来提供确认某个地址有效或属于实际发送消息的人的方法。服务器可以在将其地址用于投递通知之前尝试验证返回路径,但这样做的方法此处未定义,目前也不推荐任何特定方法。
3.6.3. 作为中继的邮件提交服务器
存在许多发信客户端,尤其是与通过 POP3 或 IMAP 接收邮件的设施配合使用的那些,它们支持本规范某些要求(例如为后续投递尝试排队消息的能力)的能力有限。对于这些客户端,常见的做法是私下约定将所有消息发送到一个单一服务器进行处理与后续分发。如此规定的 SMTP 并非理想地适合这一角色。一个标准化的邮件提交协议已被开发出来,正逐渐取代基于 SMTP 的做法(见 RFC 4409 [18])。无论如何,由于这些安排是私下的且在本规范范围之外,此处不予描述。
需要指出,MX 记录可以指向充当进入其他环境的网关的 SMTP 服务器,而不仅仅是 SMTP 中继与最终投递系统;见第 3.7 节与第 5 节。
如果某个 SMTP 服务器已接受中继邮件的任务,而后发现目的地不正确或因其他原因无法投递,则它必须构造一个"不可投递邮件"通知消息,并发送给该不可投递邮件的发起者(如反向路径所示)。如果可能,应当使用其他标准规定的不可投递报告格式(例如见 RFC 3461 [32] 与 RFC 3464 [33])。
该通知消息必须来自中继主机上的 SMTP 服务器,或最先确定无法完成投递的主机。当然,SMTP 服务器不得发送关于传输通知消息所遇问题的通知消息。防止错误报告中循环的一种方法是:在通知消息的 MAIL 命令中指定一个空反向路径。当传输此类消息时,反向路径必须被设为空(进一步讨论见第 4.5.5 节)。带有空反向路径的 MAIL 命令如下所示:
MAIL FROM:<>
如第 6.4 节所讨论,中继 SMTP 无需检查或处理消息数据的头部分或主体,并且除添加其自身的"Received:"头字段(第 4.4 节)以及(可选地)尝试检测邮件系统中的循环(见第 6.3 节)之外,不得这样做。当然,此禁令也适用于对这些头字段或文本的任何修改(另见第 7.9 节)。
3.7. 邮件网关
尽管上文讨论的中继功能在互联网 SMTP 传输服务环境内运作,MX 记录或各种形式的显式路由可能要求某个中间 SMTP 服务器在两个传输服务之间执行翻译功能。如第 2.3.10 节所讨论,当这样的系统处于两个传输服务环境的边界时,我们称其为"网关"或"网关 SMTP"。
在不同邮件环境(例如不同的邮件格式与协议)之间网关转发邮件是复杂的,不易标准化。然而,可以就 Internet 与另一个邮件环境之间的网关给出一些一般性要求。
3.7.1. 网关中的头字段
当消息跨邮件环境边界进行网关转发时,头字段可以在必要时被重写。这可能涉及检查消息主体或解释目的地址的 local-part,尽管有第 6.4 节的禁令。
网关到 Internet 的其他邮件系统常常使用 RFC 822 头部分的一个子集,或以不同语法提供类似功能,但其中一些邮件系统没有等价于 SMTP 信封的东西。因此,当消息离开 Internet 环境时,可能有必要将 SMTP 信封信息折叠进消息头部分。一种可能的解决方案是创建新的头字段来承载信封信息(例如"X-SMTP-MAIL:"与"X-SMTP-RCPT:");然而,这将要求对外部环境中的邮件程序作出改动,并可能冒披露私密信息的风险(见第 7.2 节)。
3.7.2. 网关中的 Received 行
当将消息转发进或转发出 Internet 环境时,网关必须前置一个 Received: 行,但不得以任何方式更改头部分中已有的 Received: 行。
源自其他环境的消息的"Received:"头字段可能并不完全符合本规范。然而,Received: 行最重要的用途是调试邮件故障,而这一调试可能被试图"修复"Received: 行的善意的网关严重妨碍。作为源自非 SMTP 环境的跟踪头字段的另一后果,接收系统不得基于跟踪头字段的格式拒绝邮件,并且面对这些头字段中意外的信息或格式时应当极为健壮。
网关应当在其提供的 Received 头字段的"via"子句中指示环境与协议。
3.7.3. 网关中的地址
从 Internet 一侧,网关应当接受 SMTP 命令与 RFC 822 头部分中的所有有效地址格式,以及所有有效的 RFC 822 消息。网关生成的地址与头字段必须符合适用标准(包括本规范与 RFC 5322 [4])。网关当然要遵守第 3.3 节中为其他 SMTP 系统描述的、处理源路由的相同规则。
3.7.4. 网关中的其他头字段
网关必须确保它所转发进 Internet 邮件环境的消息的所有头字段满足 Internet 邮件的要求。特别地,"From:"、"To:"、"Cc:"等头字段中的所有地址必须被变换(若必要)以满足 RFC 5322 [4] 的标准头语法,必须只引用完全限定域名,并且必须有效且可用于发送回复。将从 Internet 协议转换到另一环境协议的翻译算法,应当确保来自外部邮件环境的错误消息被投递到 SMTP 信封的反向路径,而非消息的"From:"、"Sender:"或类似头字段中的地址。
3.7.5. 网关中的信封
类似地,当从另一环境将消息转发进 Internet 时,网关应当根据错误消息返回地址(若由外部环境提供)设置信封返回路径。如果外部环境没有等价概念,网关必须选择并使用一个最佳近似,以消息发起者的地址作为最后手段的默认。
3.8. 终止会话与连接
当客户端发送 QUIT 命令时,SMTP 连接终止。服务器以一个肯定应答码响应,之后关闭连接。
在正常操作情形下,SMTP 服务器不得故意关闭连接(见第 7.8 节),除非:
- 在收到 QUIT 命令并以 221 应答响应之后。
- 在检测到需要关闭 SMTP 服务并返回 421 应答码之后。该应答码可以在服务器收到任何命令之后发出,或在必要时与命令接收异步发出(假设客户端会在下发下一条命令后收到它)。
- 在等待客户端发送命令或数据时,发生了第 4.5.3.2 节规定的超时之后。
特别地,以关闭连接来响应无法理解的命令的服务器违反了本规范。服务器应当对未知命令保持容忍,发出 500 应答并等待客户端的进一步指令。
被外部手段强行关闭的 SMTP 服务器应当在退出前尝试向 SMTP 客户端发送一行包含 421 应答码的内容。SMTP 客户端通常会在发送其下一条命令后读到该 421 应答码。
由于非其所能控制的情形(违反本规范意图但有时不可避免)而经历连接关闭、重置或其他通信失败的 SMTP 客户端,为维护邮件系统的健壮性,应当将该邮件事务视为收到了 451 应答并据此行动。
3.9. 邮件列表与别名
具备 SMTP 能力的主机应当同时支持别名与列表这两种用于多投递的地址展开模型。当消息被投递或转发到展开列表形式的每个地址时,信封中的返回地址("MAIL FROM:")必须被改为管理该列表的人或其他实体的地址。然而,在这种情况下,消息头部分(RFC 5322 [4])必须保持不变;特别地,头部分的"From"字段不受影响。
一个重要的邮件设施是单消息多目的地投递的机制,它通过将(或"展开"或"炸开")一个伪邮箱地址变换为一个目的邮箱地址列表来实现。当消息被发送到此伪邮箱(有时称为"exploder")时,副本被转发或再分发给展开列表中的每个邮箱。服务器应当直接利用列表上的地址;强烈反对应用启发式或其他匹配规则来消除某些地址(例如发起者的地址)。我们根据展开规则将此类伪邮箱分类为"别名"或"列表"。
3.9.1. 别名
要展开一个别名,收件邮件程序只需用每个展开地址依次替换信封中的伪邮箱地址;其余信封与消息主体保持不变。然后消息被投递或转发到每个展开地址。
3.9.2. 列表
邮件列表可以说是通过"再分发"(redistribution)而非"转发"(forwarding)来运作。要展开一个列表,收件邮件程序用每个展开地址依次替换信封中的伪邮箱地址。信封中的返回(向后指向的)地址被改变,使得由最终投递所产生的所有错误消息都返回给列表管理员,而非消息发起者——发起者通常无法控制列表内容,并通常会觉得错误消息烦人。注意,处理别名(第 3.9.1 节)与转发(本节)的关键区别在于:后者改动了向后指向的地址。当列表将其处理限制在此处描述的非常有限的修改与动作集合时,它是在试图模拟一个 MTA;这样的列表可被视为电子邮件传输中的一个延续。
存在执行额外的、有时是广泛的、对消息及其信封的修改的邮件列表。此类邮件列表需要被视为完整的 MUA,它们接受一个投递并发布一条新消息。
4. SMTP 规范
4.1. SMTP 命令
4.1.1. 命令语义与语法
SMTP 命令定义了用户所请求的邮件传输或邮件系统功能。SMTP 命令是以 <CRLF> 终止的字符字符串。命令本身是字母字符,若后跟参数则以 <SP> 终止,否则以 <CRLF> 终止。(为改进互操作性,SMTP 接收方应当容忍终止 <CRLF> 之前的尾随空白。)邮箱 local-part 的语法必须符合接收方站点的约定以及第 4.1.2 节规定的语法。下文讨论 SMTP 命令,SMTP 应答在第 4.2 节讨论。
一封邮件事务涉及若干作为不同命令参数被传送的数据对象。反向路径是 MAIL 命令的参数,正向路径是 RCPT 命令的参数,邮件数据是 DATA 命令的参数。这些参数或数据对象必须被传输并暂存,等待由终止事务的邮件数据结束指示所传达的确认。其模型是:提供不同的缓冲区来保存各类数据对象;即,存在一个反向路径缓冲区、一个正向路径缓冲区与一个邮件数据缓冲区。特定的命令导致信息被追加到特定的缓冲区,或导致一个或多个缓冲区被清空。
若干命令(RSET、DATA、QUIT)被规定为不允许带参数。在服务器未提供且客户端未接受特定扩展的情况下,客户端不得发送此类参数,服务器应当将以无效语法拒绝包含它们的命令。
4.1.1.1. 扩展 HELLO(EHLO)或 HELLO(HELO)
这些命令用于向 SMTP 服务器标识 SMTP 客户端。参数子句包含 SMTP 客户端的完全限定域名(若可用)。在 SMTP 客户端系统没有有意义的域名(例如,其地址是动态分配且没有反向映射记录可用)的情况下,客户端应当发送一个地址字面量(见第 4.1.3 节)。
RFC 2821 以及某些较早的非正式做法,曾鼓励在字面量之后跟随有助于标识客户端系统的信息。该约定未被广泛支持,且许多 SMTP 服务器将其视为错误。为互操作性起见,服务器最好准备好接受该字符串出现,但 SMTP 客户端不应发送它。
SMTP 服务器在连接问候应答中以及对该命令的应答中,向 SMTP 客户端标识自身。
客户端 SMTP 应当通过发出 EHLO 命令来启动 SMTP 会话。如果 SMTP 服务器支持 SMTP 服务扩展,它会给出成功应答、失败应答或错误应答。如果 SMTP 服务器违反了本规范而不支持任何 SMTP 服务扩展,它会生成一个错误应答。较早的客户端 SMTP 系统可以如上所述使用 HELO(如 RFC 821 所规定)代替 EHLO,并且服务器必须支持 HELO 命令并恰当地应答它。无论如何,客户端必须在启动邮件事务之前发出 HELO 或 EHLO。
这些命令,以及对其中之一的"250 OK"应答,确认 SMTP 客户端与 SMTP 服务器都处于初始状态,即没有正在进行的事务,且所有状态表与缓冲区都被清空。
语法:
ehlo = "EHLO" SP ( Domain / address-literal ) CRLF helo = "HELO" SP Domain CRLF
通常,对 EHLO 的应答会是一个多行应答。应答的每一行包含一个关键字,以及可选的一个或多个参数。遵循多行应答的正常语法,这些关键字在所有非末行跟随代码(250)与连字符,末行跟随代码与空格。使用 RFC 5234 [7] 的 ABNF 记号与终结符,肯定应答的语法为:
ehlo-ok-rsp = ( "250" SP Domain [ SP ehlo-greet ] CRLF )
/ ( "250-" Domain [ SP ehlo-greet ] CRLF
*( "250-" ehlo-line CRLF )
"250" SP ehlo-line CRLF )
ehlo-greet = 1*(%d0-9 / %d11-12 / %d14-127)
; string of any characters other than CR or LF
ehlo-line = ehlo-keyword *( SP ehlo-param )
ehlo-keyword = (ALPHA / DIGIT) *(ALPHA / DIGIT / "-")
; additional syntax of ehlo-params depends on
; ehlo-keyword
ehlo-param = 1*(%d33-126)
; any CHAR excluding <SP> and all
; control characters (US-ASCII 0-31 and 127
; inclusive)
尽管 EHLO 关键字可以用大写、小写或混合大小写指定,它们必须始终以不区分大小写的方式被识别与处理。这仅仅是 RFC 821 与第 2.4 节所规定做法的扩展。
EHLO 应答必须包含第 4.5.1 节中未列为"必需"的所有命令的关键字(及所需的关联参数),只有第 4.1.5 节描述的私用命令除外。私用命令可以列出。
4.1.1.2. MAIL(MAIL)
此命令用于启动一个邮件事务,其中邮件数据被投递给一个 SMTP 服务器,该服务器可以转而将其投递到一个或多个邮箱,或将其传递给另一个系统(可能使用 SMTP)。参数子句包含一条反向路径,并可以包含可选参数。一般而言,MAIL 命令只能在没有邮件事务进行时才可发送,见第 4.1.4 节。
反向路径由发送方邮箱组成。历史上,该邮箱之前可选地可以有一个主机列表,但该行为现已被废弃(见附录 C)。在某些类型的、回复可能引起邮件循环的报告消息中(例如,邮件投递与未投递通知),反向路径可以为空(见第 3.6 节)。
此命令清空反向路径缓冲区、正向路径缓冲区与邮件数据缓冲区,并将来自其参数子句的反向路径信息插入反向路径缓冲区。
如果已协商服务扩展,MAIL 命令也可以携带与特定服务扩展关联的参数。
语法:
mail = "MAIL FROM:" Reverse-path
[SP Mail-parameters] CRLF
4.1.1.3. RECIPIENT(RCPT)
此命令用于标识邮件数据的单个收件人;多个收件人通过多次使用此命令来指定。参数子句包含一条正向路径,并可以包含可选参数。
正向路径通常由所需的目邮箱组成。发送系统不应生成称为源路由的可选主机列表。接收系统必须识别源路由语法,但应当剥离源路由规格,并如同未提供源路由一样,使用与邮箱关联的域名。类似地,中继主机应当剥离或忽略源路由,并且名称不得被复制到反向路径中。当邮件到达其最终目的地(正向路径只包含一个目的邮箱)时,SMTP 服务器按照其主机邮件约定将其插入目的邮箱。
此命令将其正向路径参数追加到正向路径缓冲区;它不改变反向路径缓冲区,也不改变邮件数据缓冲区。
例如,在 xyz.com 中继主机收到的、帯有信封命令
MAIL FROM:<userx@y.foo.org> RCPT TO:<@hosta.int,@jkl.org:userc@d.bar.org>
的邮件,通常会以信封命令
MAIL FROM:<userx@y.foo.org> RCPT TO:<userc@d.bar.org>
直接发往主机 d.bar.org。如附录 C 所允许,xyz.com 也可以选择使用信封命令
MAIL FROM:<userx@y.foo.org> RCPT TO:<@hosta.int,@jkl.org:userc@d.bar.org>
将消息中继给 hosta.int,或使用信封命令
MAIL FROM:<userx@y.foo.org> RCPT TO:<@jkl.org:userc@d.bar.org>
中继给 jkl.org。以这种方式尝试使用中继现在被强烈反对。由于主机根本不要求中继邮件,xyz.com 也可以在收到 RCPT 命令时,使用 550 码完全拒绝该消息(因为这是"策略原因")。
如果已协商服务扩展,RCPT 命令也可以携带与服务器提供的特定服务扩展关联的参数。客户端不得传输除服务器在其 EHLO 应答中提供的、与服务扩展关联的参数之外的任何其他参数。
语法:
rcpt = "RCPT TO:" ( "<Postmaster@" Domain ">" / "<Postmaster>" /
Forward-path ) [SP Rcpt-parameters] CRLF
Note that, in a departure from the usual rules for
local-parts, the "Postmaster" string shown above is
treated as case-insensitive.
4.1.1.4. DATA(DATA)
接收方通常对 DATA 发送一个 354 应答,然后将跟随该命令之后的行(以 <CRLF> 序列结尾的字符串,如第 2.3.7 节所述)视为来自发送方的邮件数据。此命令导致邮件数据被追加到邮件数据缓冲区。邮件数据可以包含 128 个 ASCII 字符码中的任何一个,尽管经验表明,使用除 SP、HT、CR 与 LF 之外的控制字符可能引起问题,应当尽可能避免。
邮件数据以只包含句点、即字符序列"<CRLF>.<CRLF>"的行终止,其中第一个 <CRLF> 实际上是前一行(见第 4.5.2 节)的终止符。这就是邮件数据结束指示。该终止序列的第一个 <CRLF> 同时也是结束数据(消息文本)最后一行的 <CRLF>,或者,如果没有邮件数据,则结束 DATA 命令本身("无邮件数据"的情况不符合本规范,因为它要求既不传输本规范要求的跟踪头字段、也不传输 RFC 5322 [4] 要求的报文头部分)。不得添加额外的 <CRLF>,因为那会导致向消息添加一个空行。此规则的唯一例外出现在:消息主体以一个不以 <CRLF> 结尾的最终"行"传递给发起 SMTP 发送方时;在这种情况下,发起 SMTP 系统必须要么将消息作为无效拒绝,要么添加 <CRLF>,以使接收 SMTP 服务器能够识别"数据结束"条件。
接受只以 <LF> 结尾的行、作为对某些 UNIX 系统不符合规范行为的让步,已被证明引起的互操作性问题多于它解决的,SMTP 服务器系统不得这样做,即便打着改进健壮性的旗号。特别地,序列"<LF>.<LF>"(裸换行,无回车)不得被当作等价于 <CRLF>.<CRLF> 的邮件数据结束指示。
收到邮件数据结束指示要求服务器处理所存储的邮件事务信息。此处理消耗反向路径缓冲区、正向路径缓冲区与邮件数据缓冲区中的信息,并且在此命令完成时这些缓冲区被清空。如果处理成功,接收方必须发送一个 OK 应答。如果处理失败,接收方必须发送一个失败应答。SMTP 模型在此刻不允许部分失败:要么消息被服务器接受以进行投递并返回肯定应答,要么不被接受并返回失败应答。在针对数据结束指示发送肯定的"250 OK"完成应答时,接收方承担消息的全部责任(见第 6.1 节)。随后诊断出的错误必须以邮件消息的形式报告,如第 4.4 节所讨论。
当 SMTP 服务器接受一条消息用于中继或最终投递时,它在邮件数据的顶部插入一条跟踪记录(也可互换地称为"时间戳行"或"Received"行)。该跟踪记录指示发送消息的主机的身份、接收消息的主机(正在插入此时间戳)的身份,以及收到消息的日期与时间。被中继的消息将有多条时间戳行。这些行的形成细节(包括其语法)在第 4.4 节规定。
关于 DATA 命令操作的进一步讨论见第 3.3 节。
语法:
data = "DATA" CRLF
4.1.1.5. RESET(RSET)
此命令指定当前邮件事务将被中止。任何已存储的发送方、收件人与邮件数据必须被丢弃,所有缓冲区与状态表被清空。接收方必须对一个不带参数的 RSET 命令发送"250 OK"应答。客户端可以在任何时刻发出重置命令。如果它在 EHLO 之后立即发出、在会话中发出 EHLO 之前发出、在发送并确认了数据结束指示之后发出,或在 QUIT 之前立即发出,它实际上等价于一个 NOOP(即,它没有效果)。SMTP 服务器不得因收到 RSET 而关闭连接;该动作保留给 QUIT(见第 4.1.1.10 节)。
由于 EHLO 意味着服务器的某些额外处理与应答,RSET 通常比重新发出该命令更高效,即便形式语义相同。
存在某些情形,与本文档意图相反,SMTP 服务器可能收到底层 TCP 连接已被关闭或重置的指示。为维护邮件系统的健壮性,SMTP 服务器应当为此条件做好准备,并应当将其视为在连接消失之前收到了 QUIT。
语法:
rset = "RSET" CRLF
4.1.1.6. VERIFY(VRFY)
此命令请求接收方确认参数标识了一个用户或邮箱。如果它是一个用户名,则如第 3.5 节所规定返回信息。
此命令对反向路径缓冲区、正向路径缓冲区或邮件数据缓冲区都没有影响。
语法:
vrfy = "VRFY" SP String CRLF
4.1.1.7. EXPAND(EXPN)
此命令请求接收方确认参数标识了一个邮件列表,若是,则返回该列表的成员。如果命令成功,返回一个包含第 3.5 节所描述信息的应答。除单行列表的平凡情况外,该应答会有多行。
此命令对反向路径缓冲区、正向路径缓冲区或邮件数据缓冲区都没有影响,并且可以在任何时刻发出。
语法:
expn = "EXPN" SP String CRLF
4.1.1.8. HELP(HELP)
此命令使服务器向客户端发送有用的信息。该命令可以带一个参数(例如,任何命令名)并返回更具体的信息作为应答。
此命令对反向路径缓冲区、正向路径缓冲区或邮件数据缓冲区都没有影响,并且可以在任何时刻发出。
SMTP 服务器应当支持不带参数的 HELP,并可以支持带参数的 HELP。
语法:
help = "HELP" [ SP String ] CRLF
4.1.1.9. NOOP(NOOP)
此命令不影响任何参数或先前输入的命令。除要求接收方发送一个"250 OK"应答外,它不指定任何动作。
此命令对反向路径缓冲区、正向路径缓冲区或邮件数据缓冲区都没有影响,并且可以在任何时刻发出。如果指定了参数字符串,服务器应当忽略它。
语法:
noop = "NOOP" [ SP String ] CRLF
4.1.1.10. QUIT(QUIT)
此命令指定接收方必须发送一个"221 OK"应答,然后关闭传输信道。
接收方在收到并应答一个 QUIT 命令之前,不得故意关闭传输信道(即便出现了错误)。在发送 QUIT 命令之前,发送方不得故意关闭传输信道,并且它应当等待收到应答(即便对前一条命令有错误应答)。如果由于违反上述规定或系统/网络故障而导致连接被过早关闭,服务器必须取消任何待处理的事务,但不撤销任何先前已完成的事务,并且通常必须像进行中命令或事务收到了临时错误(即 4yz 应答)一样行动。
QUIT 命令可以在任何时刻发出。任何当前未完成的邮件事务都将被中止。
语法:
quit = "QUIT" CRLF
4.1.1.11. Mail-Parameter 与 Rcpt-Parameter 错误应答
如果服务器 SMTP 无法识别或无法实现与特定 MAIL FROM 或 RCPT TO 命令关联的一个或多个参数,它将返回码 555。
如果出于某种原因,服务器暂时无法容纳与 MAIL FROM 或 RCPT TO 命令关联的一个或多个参数,并且如果该特定参数的定义不强制使用另一代码,它应当返回码 455。
特定于特定参数及其值的错误将在该参数的定义 RFC 中指定。
4.1.2. 命令参数语法
上述命令的参数子句的语法(在适用处使用 RFC 5234 [7] 规定的语法)如下给出。下面给出的某些产生式只与附录 C 所述的源路由结合使用。本文档未定义的终结符,如 ALPHA、DIGIT、SP、CR、LF、CRLF,按 RFC 5234 [7] 第 6 节的"核心"语法或 RFC 5322 [4] 的报文格式语法定义。
Reverse-path = Path / "<>"
Forward-path = Path
Path = "<" [ A-d-l ":" ] Mailbox ">"
A-d-l = At-domain *( "," At-domain )
; Note that this form, the so-called "source
; route", MUST BE accepted, SHOULD NOT be
; generated, and SHOULD be ignored.
At-domain = "@" Domain
Mail-parameters = esmtp-param *(SP esmtp-param)
Rcpt-parameters = esmtp-param *(SP esmtp-param)
esmtp-param = esmtp-keyword [ "=" esmtp-value ]
esmtp-keyword = (ALPHA / DIGIT) *(ALPHA / DIGIT / "-" )
esmtp-value = 1*(%d33-60 / %d62-126)
; any CHAR excluding "=", SP, and control
; characters. If this string is an email address,
; i.e., a Mailbox, then the "xtext" syntax [32]
; SHOULD be used.
Keyword = Ldh-str
Argument = Atom
Domain = sub-domain *( "." sub-domain )
sub-domain = Let-dig [Ldh-str ]
Let-dig = ALPHA / DIGIT
Ldh-str = *( ALPHA / DIGIT / "-" ) Let-dig
address-literal = "[" ( IPv4-address-literal /
IPv6-address-literal /
General-address-literal ) "]"
; See Section 4.1.3
Mailbox = Local-part "@" ( Domain / address-literal )
Local-part = Dot-string / Quoted-string
; MAY be case-sensitive
Dot-string = Atom *( "." Atom )
Atom = 1*atext
Quoted-string = DQUOTE *QcontentSMTP DQUOTE
QcontentSMTP = qtextSMTP / quoted-pairSMTP
quoted-pairSMTP = %d92 %d32-126
; i.e., backslash followed by any ASCII
; graphic (including itself) or SPace
qtextSMTP = %d32-33 / %d35-91 / %d93-126
; i.e., within a quoted string, any
; ASCII graphic or space is permitted
; without blackslash-quoting except
; double-quote and the backslash itself.
String = Atom / Quoted-string
尽管上述 Local-part 的定义相对宽松,但为最大互操作性,期望接收邮件的主机应当避免定义要求(或使用)Quoted-string 形式、或要求 Local-part 区分大小写的邮箱。对于任何需要生成或比较 Local-part 的用途(例如,针对特定邮箱名),所有引用形式必须被视为等价,并且发送系统应当传输使用最少引用可能的形式。
系统不得以要求 SMTP 中使用非 ASCII 字符(高位被置一的八位组)或 ASCII"控制字符"(十进制值 0-31 与 127)的方式来定义邮箱。这些字符不得用于 MAIL 或 RCPT 命令、或其他要求邮箱名的命令中。
注意,反斜杠"\"是一个引用字符,用于表示下一个字符应按字面使用(而非其正常解释)。例如,"Joe\,Smith"表示一个九个字符的用户名字符串,逗号是该字符串的第四个字符。
为促进互操作性,并与关于在命名与应用中保守使用 DNS 的长期指导一致(例如,见基础 DNS 文档 RFC 1035 [2] 的第 2.3.1 节),字母字符、数字与连字符之外的字符不得出现在 SMTP 客户端或服务器的域名标签中。特别是,下划线字符不被允许。收到使用了无效字符码、且无其他拒绝理由的命令的 SMTP 服务器,必须以 501 应答拒绝该命令(此规则如同其他规则,可能被适当的 SMTP 扩展覆盖)。
4.1.3. 地址字面量
有时,一个主机不为域名系统所知,并且通信(特别是用于报告与修复错误的通信)被阻断。为绕过此障碍,允许一种特殊的字面地址形式作为域名的替代。对于 IPv4 地址,该形式使用四个由点分隔的小十进制整数,并括在方括号内,如 [123.255.37.2],它表示以八位组序列形式的一个(IPv4)Internet 地址。对于 IPv6 以及最终可能被标准化的其他寻址形式,该形式由一个标识地址语法的标准化"标签"、一个冒号,以及地址本身组成,其格式作为相关标准(即 RFC 4291 [8] 针对 IPv6)的一部分被规定。
具体而言:
IPv4-address-literal = Snum 3( "." Snum )
IPv6-address-literal = "IPv6:" IPv6-addr
General-address-literal = Standardized-tag ":" 1*dcontent
Standardized-tag = Ldh-str
; Standardized-tag MUST be specified in a
; Standards-Track RFC and registered with IANA
dcontent = %d33-90 / ; Printable US-ASCII
%d94-126 ; excl. "[", "\", "]"
Snum = 1*3DIGIT
; representing a decimal integer
; value in the range 0 through 255
IPv6-addr = IPv6-full / IPv6-comp / IPv6v4-full / IPv6v4-comp
IPv6-hex = 1*4HEXDIG
IPv6-full = IPv6-hex 7( ":" IPv6-hex )
IPv6-comp = [IPv6-hex *5( ":" IPv6-hex )] "::"
[IPv6-hex *5( ":" IPv6-hex )]
; The "::" represents at least 2 16-bit groups of
; zeros. No more than 6 groups in addition to the
; "::" may be present.
IPv6v4-full = IPv6-hex 5( ":" IPv6-hex ) ":" IPv4-address-literal
IPv6v4-comp = [IPv6-hex *3( ":" IPv6-hex )] "::"
[IPv6-hex *3( ":" IPv6-hex ) ":"]
IPv4-address-literal
; The "::" represents at least 2 16-bit groups of
; zeros. No more than 4 groups in addition to the
; "::" and IPv4-address-literal may be present.
4.1.4. 命令的顺序
对这些命令的使用顺序存在限制。
一个将包含邮件事务的会话,必须首先通过使用 EHLO 命令来初始化。SMTP 服务器应当接受非邮件事务的命令(例如 VRFY 或 EXPN)而无需此初始化。
客户端可以在会话稍后发出 EHLO 命令。如果它在会话开始后发出、且该 EHLO 命令可被 SMTP 服务器接受,SMTP 服务器必须清空所有缓冲区并重置状态,恰如发出了 RSET 命令。换言之,紧接着 RSET 后发出 EHLO 的序列是冗余的,但除了执行不必要命令的性能代价外并无害处。
如果 EHLO 命令不被 SMTP 服务器接受,必须酌情返回 501、500、502 或 550 失败应答。SMTP 服务器在传输这些应答之后,必须保持在收到 EHLO 之前所处的同一状态。
SMTP 客户端必须(若可能)确保 EHLO 命令的域参数是第 2.3.5 节为此命令规定的主主机名。如果这不可能(例如,当客户端的地址是动态分配且客户端没有明显的名称时),应当用地址字面量替代域名。
SMTP 服务器可以验证 EHLO 命令中的域名参数是否确实对应于客户端的 IP 地址。然而,如果验证失败,服务器不得据此拒绝接受消息。验证尝试中捕获的信息用于日志与跟踪目的。注意,此禁令只适用于参数与其 IP 地址的匹配;关于拒绝传入连接或邮件消息的更广泛讨论见第 7.9 节。
NOOP、HELP、EXPN、VRFY 与 RSET 命令可以在会话期间的任何时刻使用,或无需先初始化会话。SMTP 服务器应当正常处理这些(即,不返回 503 码),即便尚未收到 EHLO 命令;客户端应当在发送这些命令之前以 EHLO 打开会话。
如果遵循这些规则,RFC 821 中显示针对 EXPN 命令"550 access denied to you"的示例就是不正确的,除非 EXPN 之前有 EHLO 命令,或拒绝访问是基于客户端的 IP 地址或其他认证或授权判定机制。
MAIL 命令(或已废弃的 SEND、SOML 或 SAML 命令)开始一个邮件事务。一旦开始,一个邮件事务由一个事务起始命令、一条或多条 RCPT 命令,以及一个 DATA 命令按顺序组成。邮件事务可以由 RSET、一个新的 EHLO 或 QUIT 命令中止。一个会话中可以有零个或多个事务。如果邮件事务已经打开,则不得发送 MAIL(或 SEND、SOML 或 SAML);即,只有会话中尚未开始任何邮件事务、或前一个已以成功的 DATA 命令成功结束、或前一个已被中止(例如,用 RSET 或新 EHLO)时,才应发送它。
如果事务起始命令的参数不可接受,必须返回 501 失败应答,且 SMTP 服务器必须保持同一状态。如果事务中的命令顺序错乱到服务器无法处理的程度,必须返回 503 失败应答,且 SMTP 服务器必须保持同一状态。
会话中的最后一条命令必须是 QUIT 命令。即便未发送并接受任何会话开始命令,客户端 SMTP 也应当使用 QUIT 命令来请求关闭连接。
4.1.5. 私用命令
如第 2.2.2 节所规定,以"X"开头的命令可以由客户端(发送方)与服务器(接收方)SMTP 代理之间的双边协议使用。预期不识别此类命令的 SMTP 服务器以"500 Command not recognized"应答。扩展的 SMTP 服务器可以在对 EHLO 命令的应答中列出与这些私用命令关联的特性名。
由不以"X"开头的 SMTP 系统发送或接受的命令,必须符合第 2.2.2 节的要求。
4.2. SMTP 应答
对 SMTP 命令的应答用于确保邮件传输过程中请求与动作的同步,并保证 SMTP 客户端始终知道 SMTP 服务器的状态。每条命令必须恰好生成一个应答。
命令-应答序列的细节在第 4.3 节描述。
SMTP 应答由一个三位数字(作为三个数字字符传输)后跟一些文本组成,除非本文档另有规定。该数字供自动机用来确定要进入的下一个状态;文本是给人类用户的。这三位数字包含足够的编码信息,使得 SMTP 客户端无需检查文本,并可以适当地丢弃它或将其传递给用户。例外情况如本文档他处所述。特别地,220、221、251、421 与 551 应答码关联着必须被机器解析与解释的报文文本。一般情况下,文本可能是接收方相关与上下文相关的,因此每个应答码可能有不同的文本。关于应答码理论的讨论见第 4.2.1 节。形式上,一个应答被定义为序列:一个三位代码、<SP>、一行文本,以及 <CRLF>,或一个多行应答(在同节定义)。由于违反了本文档规定,文本有时不被发送,未收到它的客户端应当准备好仅处理代码(带或不带尾随空格字符)。只有 EHLO、EXPN 与 HELP 命令在正常情形下预期会产生多行应答;然而,多行应答允许用于任何命令。
在 ABNF 中,服务器应答为:
Greeting = ( "220 " (Domain / address-literal)
[ SP textstring ] CRLF ) /
( "220-" (Domain / address-literal)
[ SP textstring ] CRLF
*( "220-" [ textstring ] CRLF )
"220" [ SP textstring ] CRLF )
textstring = 1*(%d09 / %d32-126) ; HT, SP, Printable US-ASCII
Reply-line = *( Reply-code "-" [ textstring ] CRLF )
Reply-code [ SP textstring ] CRLF
Reply-code = %x32-35 %x30-35 %x30-39
where "Greeting" appears only in the 220 response that announces that
the server is opening its part of the connection. (Other possible
server responses upon connection follow the syntax of Reply-line.)
SMTP 服务器应当只发送本文档所列的应答码。SMTP 服务器应当在适当时使用示例中所示的文本。
SMTP 客户端必须只根据应答码(而非文本,但"地址变更"的 251 与 551,以及必要时 220、221 与 421 应答除外)来确定其动作;一般情况下,任何文本(包括完全没有文本,尽管发送方不应发送裸代码)都必须可被接受。应答码之后的空格(空白)被视为文本的一部分。只要可能,接收方 SMTP 应当测试应答码的第一位(严重性指示)。
下面出现的代码列表不得被解释为永久性的。尽管新代码的添加应当是一个罕见且重要的活动,并且优先使用应答文本部分的补充信息,新代码仍可能因新的标准或 Standards-Track 规范而添加。因此,发送方 SMTP 必须准备好处理本文档未规定的代码,并且必须只通过解释第一位来这样做。
在没有与客户端协商的扩展的情况下,SMTP 服务器不得发送第一位不是 2、3、4 或 5 的应答码。收到此类超出范围代码的客户端通常应当将其视为致命错误并终止邮件事务。
4.2.1. 应答码严重性与理论
应答的三位数字各有特殊意义。第一位表示响应是良好、糟糕还是未完成。一个不成熟或收到意外代码的 SMTP 客户端,将能够通过检查第一位来确定其下一个动作(按计划继续、重做、退避等)。一个想要大致知道发生了哪类错误(例如,邮件系统错误、命令语法错误)的 SMTP 客户端可以检查第二位。第三位以及可能存在的任何补充信息保留用于最精细的信息分级。
应答码第一位有四种取值:
2yz 肯定完成应答:所请求的动作已成功完成。可以发起一个新请求。
3yz 肯定中间应答:命令已被接受,但所请求的动作被搁置,等待收到进一步信息。SMTP 客户端应当发送另一条命令来指定该信息。此应答用于命令序列组(即,在 DATA 中)。
4yz 临时否定完成应答:命令未被接受,所请求的动作未发生。然而,错误状况是临时的,可以再次请求该动作。发送方应当回到命令序列的起点(若有)。当两个不同站点(接收方与发送方 SMTP 代理)必须对解释达成一致时,很难赋予"临时"以含义。此类别中的每个应答可能有不同的时间值,但 SMTP 客户端应当重试。判断一个应答属于 4yz 还是 5yz 类别(见下)的经验法则是:如果重复时命令形式或发送方/接收方属性无需任何改变即可成功,则应答是 4yz(即,命令被完全相同地重复,且接收方不启用新的实现)。
5yz 永久否定完成应答:命令未被接受,所请求的动作未发生。SMTP 客户端不应重复完全相同的请求(在同一序列中)。即使某些"永久"错误状况也可以被纠正,因此人类用户可能希望在将来的某个时刻通过直接动作重新发起命令序列(例如,在拼写被更改、或用户已更改账户状态之后)。
值得指出,文件传输协议(FTP)[34] 使用非常相似的代码架构,并且 SMTP 代码基于 FTP 模型。然而,SMTP 使用一命令一应答模型(而 FTP 是异步的),且 FTP 的 1yz 代码不是 SMTP 模型的一部分。
第二位对特定类别中的应答进行编码:
x0z 语法:这些应答涉及语法错误、不适合任何功能类别的语法正确的命令,以及未实现或多余的命令。
x1z 信息:这些是对信息请求的应答,例如状态或帮助。
x2z 连接:这些是指传输信道的应答。
x3z 未指定。
x4z 未指定。
x5z 邮件系统:这些应答指示接收方邮件系统相对于所请求的传输或其他邮件系统动作的状态。
第三位在第二位规定的每个类别中给出更精细的含义分级。应答列表说明了这一点。每条应答文本是推荐而非强制的,并且甚至可以根据其关联的命令而改变。另一方面,应答码必须严格遵循本节的规定。接收方实现不应为与此处描述的略为不同的情况发明新代码,而应改编已定义的代码。
例如,像 NOOP 这样、成功执行不会向 SMTP 客户端提供任何新信息的命令,将返回 250 应答。当命令请求一个未实现的、非站点特定的动作时,应答是 502。对此的细化是 504 应答,针对已实现、但请求了未实现参数的命令。
应答文本可能长于一行;在这些情况下,必须标记完整文本,以便 SMTP 客户端知道何时可以停止读取应答。这需要一个特殊格式来指示多行应答。
多行应答的格式要求:除最后一行外,每一行以应答码开头,紧跟一个连字符"-"(也称减号),后跟文本。最后一行以应答码开头,紧跟 <SP>,可选地带一些文本,以及 <CRLF>。如上所述,如果后续文本未被发送,服务器应当发送 <SP>,但客户端必须准备好它被省略。
例如:
250-First line 250-Second line 250-234 Text beginning with numbers 250 The last line
在多行应答中,每一行上的应答码必须相同。客户端依赖这一点是合理的,因此它可以根据任意一行中的代码做出处理决定,假设所有其他行都将相同。在少数情况下,应答"文本"中含有对客户端的重数据。客户端将能够从当前上下文识别这些情况。
4.2.2. 按功能分组的应答码
- 500 语法错误,命令无法识别(这可能包括命令行过长等错误)
- 501 参数或参数中的语法错误
- 502 命令未实现(见第 4.2.4 节)
- 503 命令顺序错误
- 504 命令参数未实现
- 211 系统状态,或系统帮助应答
- 214 帮助消息(关于如何使用接收方或某特定非标准命令的含义;此应答仅对人类用户有用)
- 220 <domain> 服务就绪
- 221 <domain> 服务正在关闭传输信道
- 421 <domain> 服务不可用,正在关闭传输信道(如果服务知道它必须关闭,这可能是对任何命令的应答)
- 250 所请求的邮件动作正常,已完成
- 251 用户非本地;将转发到 <forward-path>(见第 3.4 节)
- 252 无法 VRFY 用户,但将接受消息并尝试投递(见第 3.5.3 节)
- 455 服务器无法容纳参数
- 555 MAIL FROM/RCPT TO 参数无法识别或未实现
- 450 所请求的邮件动作未采取:邮箱不可用(例如,邮箱忙或由于策略原因被临时屏蔽)
- 550 所请求的动作未采取:邮箱不可用(例如,未找到邮箱、无访问权,或由于策略原因命令被拒绝)
- 451 所请求的动作中止:处理中出错
- 551 用户非本地;请尝试 <forward-path>(见第 3.4 节)
- 452 所请求的动作未采取:系统存储不足
- 552 所请求的邮件动作中止:超出存储配额
- 553 所请求的动作未采取:不允许的邮箱名(例如,邮箱语法不正确)
- 354 开始邮件输入;以 <CRLF>.<CRLF> 结束
- 554 事务失败(或者,在作为连接开场应答的情况下,"此处无 SMTP 服务")
4.2.3. 按数字顺序排列的应答码
- 211 系统状态,或系统帮助应答
- 214 帮助消息
- 220 <domain> 服务就绪
- 221 <domain> 服务正在关闭传输信道
- 250 所请求的邮件动作正常,已完成
- 251 用户非本地;将转发到 <forward-path>(见第 3.4 节)
- 252 无法 VRFY 用户,但将接受消息并尝试投递(见第 3.5.3 节)
- 354 开始邮件输入;以 <CRLF>.<CRLF> 结束
- 421 <domain> 服务不可用,正在关闭传输信道
- 450 所请求的邮件动作未采取:邮箱不可用
- 451 所请求的动作中止:处理中本地错误
- 452 所请求的动作未采取:系统存储不足
- 455 服务器无法容纳参数
- 500 语法错误,命令无法识别
- 501 参数或参数中的语法错误
- 502 命令未实现(见第 4.2.4 节)
- 503 命令顺序错误
- 504 命令参数未实现
- 550 所请求的动作未采取:邮箱不可用
- 551 用户非本地;请尝试 <forward-path>(见第 3.4 节)
- 552 所请求的邮件动作中止:超出存储配额
- 553 所请求的动作未采取:不允许的邮箱名
- 554 事务失败(或在连接开场应答情况下,"此处无 SMTP 服务")
- 555 MAIL FROM/RCPT TO 参数无法识别或未实现
4.2.4. 应答码 502
关于何时应优先返回应答码 502(命令未实现)而非其他代码,已有疑问被提出。当命令实际被 SMTP 服务器识别、但未实现时,应当使用 502。如果命令不被识别,应当返回 500 码。扩展的 SMTP 系统不得为它们将返回 502(或 500)应答的能力在 EHLO 应答中列出。
4.2.5. DATA 之后及随后的 <CRLF>.<CRLF> 的应答码
当 SMTP 服务器在 DATA 命令以 <CRLF>.<CRLF> 完成后返回肯定完成状态(2yz 码)时,它承担以下责任:
- 投递消息(如果收件人邮箱存在);或
- 如果由于临时状况导致投递消息的尝试失败,按照第 4.5.4 节规定的间隔重试投递合理次数;或
- 如果由于永久状况导致投递消息的尝试失败,或由于临时状况重复尝试投递消息失败,则向原始消息的发送方(使用 SMTP MAIL 命令中的地址)返回适当的通知。
当 SMTP 服务器在 DATA 命令以 <CRLF>.<CRLF> 完成后返回临时错误状态(4yz)码时,它不得随后尝试投递该消息。SMTP 客户端保留该消息的投递责任,并可以将其返回给用户,或将其重新排队以进行后续尝试(见第 4.5.4.1 节)。
发起消息的用户应当能够将返回临时失败状态(通过邮件消息或其他方式)解释为非投递指示,正如永久失败会被解释的那样。如果客户端 SMTP 成功处理这些情况,用户将不会收到此类应答。
当 SMTP 服务器在 DATA 命令以 <CRLF>.<CRLF> 完成后返回永久错误状态(5yz)码时,它不得对该消息进行任何后续投递尝试。与临时错误状态码一样,SMTP 客户端保留消息的责任,但在没有用户审查消息与应答并适当干预的情况下,不应再次尝试向同一服务器投递。
4.3. 命令与应答的排序
4.3.1. 排序概述
发送方与接收方之间的通信是一场由发送方控制的交替对话。因此,发送方发出一条命令,接收方以应答响应。除非通过服务扩展协商了其他安排,发送方必须在发送进一步命令之前等待此应答。一个重要应答是连接问候。通常,接收方将在连接完成时发送 220"服务就绪"应答。发送方应当在发送任何命令之前等待此问候消息。
注意:所有问候类型的应答,在应答码之后的第一个词都是服务器的正式名称(完全限定主域名)。有时主机没有有意义的名称。这些情况下的替代方案讨论见第 4.1.3 节。
例如:
220 ISIF.USC.EDU Service ready or 220 mail.example.com SuperSMTP v 6.1.2 Service ready or 220 [10.0.0.1] Clueless host service ready
下表列出每个命令的替代成功与失败应答。这些应当被严格遵循。接收方可以在应答中替换文本,但代码数字以及特定命令-应答序列所暗示的含义与动作必须被保留。
4.3.2. 命令-应答序列
每条命令都与其通常可能的应答一起列出。可能应答前使用的前缀:"I"表示中间,"S"表示成功,"E"表示错误。由于某些服务器在特殊情形下可能生成其他应答,并为未来扩展留有余地,SMTP 客户端应当(在可能时)只解释应答的第一位,并且必须准备好通过只解释第一位来处理无法识别的应答码。除非使用第 2.2 节描述的机制进行扩展,SMTP 服务器不得向 SMTP 客户端传输不是三位数字、或不以 2 至 5(含)之间数字开头的应答码。
这些排序规则,并且原则上这些代码本身,可以被服务器提供、客户端接受(请求)的 SMTP 扩展扩展或修改。然而,如果目标是代码中更精细的粒度,而非用于全新目的的完全新代码,应当优先使用 RFC 3463 [25] 中描述的系统,而非发明新代码。
除下列代码外,任何 SMTP 命令在遇到相应的异常情形时都可以返回以下任何代码:
500 用于"命令行过长"情况,或命令名未被识别。注意,针对这些命令的必需子集产生"命令无法识别"错误违反了本文档。类似地,对短于 512 字符的命令行产生"命令过长"消息将违反第 4.5.3.1.4 节的规定。
501 命令或参数中的语法错误。为提供未来扩展,本文档规定不接受参数的命令(DATA、RSET、QUIT)若在没有 EHLO 通告的扩展的情况下提供了参数,应当返回 501 消息。
421 服务正在关闭并关闭传输信道。
具体序列如下:
CONNECTION ESTABLISHMENT
S: 220
E: 554
EHLO or HELO
S: 250
E: 504 (a conforming implementation could return this code only
in fairly obscure cases), 550, 502 (permitted only with an old-
style server that does not support EHLO)
MAIL
S: 250
E: 552, 451, 452, 550, 553, 503, 455, 555
RCPT
S: 250, 251 (but see Section 3.4 for discussion of 251 and 551)
E: 550, 551, 552, 553, 450, 451, 452, 503, 455, 555
DATA
I: 354 -> data -> S: 250
E: 552, 554, 451, 452
E: 450, 550 (rejections for policy reasons)
E: 503, 554
RSET
S: 250
VRFY
S: 250, 251, 252
E: 550, 551, 553, 502, 504
EXPN
S: 250, 252
E: 550, 500, 502, 504
HELP
S: 211, 214
E: 502, 504
NOOP
S: 250
QUIT
S: 221
4.4. 跟踪信息
当 SMTP 服务器收到一条消息用于投递或进一步处理时,它必须在消息内容的开头插入跟踪("时间戳"或"Received")信息,如第 4.1.1.4 节所讨论。
此行必须结构化如下:
- FROM 子句,在 SMTP 环境中必须提供,应当同时包含(1)EHLO 命令中给出的源主机名,以及(2)从 TCP 连接确定的、包含源 IP 地址的地址字面量。
- ID 子句可以包含如 RFC 822 所建议的"@",但这不是必需的。
- 如果 FOR 子句出现,它必须恰好包含一个 <path> 条目,即使已给出了多条 RCPT 命令。多个 <path> 会引发一些安全问题,且已被废弃,见第 7.2 节。
Internet 邮件程序不得更改或删除先前已添加到消息头部分的 Received: 行。SMTP 服务器必须向消息前置 Received 行;它们不得更改现有行的顺序,也不得在其他任何位置插入 Received 行。
随着 Internet 的发展,Received 头字段的可比性对于检测问题(特别是缓慢的中继)很重要。创建 Received 头字段的 SMTP 服务器应当在日期中使用显式偏移(例如 -0800),而非任何类型的时区名。只要可行,应当使用本地时间(带偏移)而非 UT。此表述允许指定关于本地环境的稍多信息。如果需要 UT,接收方只需做一些简单算术来转换这些值。使用 UT 会丢失关于服务器时区位置的信息。如果希望提供时区名,应当将其包含在注释中。
当投递 SMTP 服务器对一条消息进行"最终投递"时,它在邮件数据的开头插入一个 return-path 行。此 return-path 的使用是要求的;邮件系统必须支持它。return-path 行保留了来自 MAIL 命令的 <reverse-path> 中的信息。这里,最终投递意味着消息已离开 SMTP 环境。通常,这将意味着它已被投递给目标用户或关联的邮件投放点,但在某些情况下它可能被进一步处理并由另一个邮件系统传输。
返回路径中的邮箱可能不同于实际发送方的邮箱,例如,如果错误应答要被投递到一个特殊的错误处理邮箱,而非消息发送方。当涉及邮件列表时,这种安排很常见也很有用,作为一种将错误指向列表维护者而非消息发起者的手段。
上述文本暗示最终邮件数据将以一个 return-path 行开始,后跟一个或多个时间戳行。这些行之后是邮件数据的其余部分:先是邮件头部分的其余部分,然后是主体(RFC 5322 [4])。
有时 SMTP 服务器很难确定它是否在进行最终投递,因为在消息被接受用于投递之后可能发生转发或其他操作。因此,任何进一步的(转发、网关或中继)系统可以移除返回路径,并按需重建 MAIL 命令,以确保被投递的消息中恰好出现这样一行。
发起消息的 SMTP 系统不应发送已经包含 Return-path 头字段的消息。执行中继功能的 SMTP 服务器不得检查消息数据,尤其不应检查到确定是否存在 Return-path 头字段所需的程度。进行最终投递的 SMTP 服务器可以在添加它们自己的之前移除 Return-path 头字段。
Return-path 的主要目的是指定应当将指示未投递或其他邮件系统失败的消息发送到的地址。为使这无歧义,当消息被投递时应当恰好存在一个返回路径。使用带有非 SMTP 传输的 RFC 822 语法的系统应当指定一个明确的、与传输信封关联的地址,错误报告(例如,未投递消息)应当被发送到该地址。
历史注记:RFC 822 中看似与将 Return-path 头字段(或来自 MAIL 命令的信封反向路径地址)用作错误消息目的地相矛盾的文本,在 Internet 上不适用。反向路径地址(如复制到 Return-path 中)必须被用作任何包含投递错误消息的邮件的目标。
特别地:
- 从 SMTP 到其他环境的网关应当插入一个 return-path 头字段,除非已知该"其他"传输也使用 Internet 域名地址,并单独维护信封发送方地址。
- 从其他环境到 SMTP 的网关应当删除消息中存在的任何 return-path 头字段,并将该信息复制到 SMTP 信封,或将其与该其他传输系统的信封中的信息合并,以构造 SMTP 信封中 MAIL 命令的反向路径参数。
服务器必须特殊处理邮件数据结束指示之后的处理仅部分成功的情况。这可能发生在:在接受了若干收件人与邮件数据之后,SMTP 服务器发现邮件数据可以成功投递给部分而非全部收件人。在这种情况下,对 DATA 命令的应答必须是 OK 应答。然而,SMTP 服务器必须组成并向消息发起者发送一个"不可投递邮件"通知消息。
必须发送一个列出所有失败收件人的单一通知,或为每个失败收件人发送单独的通知消息。为发送方处理的经济性,应当尽可能使用前者。注意,处理别名(第 3.9.1 节)与转发(本节)的关键区别在于:后者改动了向后指向的地址。所有关于不可投递邮件的通知消息都必须使用 MAIL 命令发送(即使它们源于处理已废弃的 SEND、SOML 或 SAML 命令),并且必须使用第 3.6 节讨论的空返回路径。
时间戳行与返回路径行被正式定义如下("FWS"与"CFWS"的定义见 RFC 5322 [4]):
Return-path-line = "Return-Path:" FWS Reverse-path <CRLF>
Time-stamp-line = "Received:" FWS Stamp <CRLF>
Stamp = From-domain By-domain Opt-info [CFWS] ";"
FWS date-time
; where "date-time" is as defined in RFC 5322 [4]
; but the "obs-" forms, especially two-digit
; years, are prohibited in SMTP and MUST NOT be used.
From-domain = "FROM" FWS Extended-Domain
By-domain = CFWS "BY" FWS Extended-Domain
Extended-Domain = Domain /
( Domain FWS "(" TCP-info ")" ) /
( address-literal FWS "(" TCP-info ")" )
TCP-info = address-literal / ( Domain FWS address-literal )
; Information derived by server from TCP connection
; not client EHLO.
Opt-info = [Via] [With] [ID] [For]
[Additional-Registered-Clauses]
Via = CFWS "VIA" FWS Link
With = CFWS "WITH" FWS Protocol
ID = CFWS "ID" FWS ( Atom / msg-id )
; msg-id is defined in RFC 5322 [4]
For = CFWS "FOR" FWS ( Path / Mailbox )
Additional-Registered-Clauses = CFWS Atom FWS String
; Additional standard clauses may be
; added in this location by future
; standards and registration with
; IANA. SMTP servers SHOULD NOT use
; unregistered names. See Section 8.
Link = "TCP" / Addtl-Link
Addtl-Link = Atom
; Additional standard names for links are
; registered with the Internet Assigned Numbers
; Authority (IANA). "Via" is primarily of value
; with non-Internet transports. SMTP servers
; SHOULD NOT use unregistered names.
Protocol = "ESMTP" / "SMTP" / Attdl-Protocol
Attdl-Protocol = Atom
; Additional standard names for protocols are
; registered with the Internet Assigned Numbers
; Authority (IANA) in the "mail parameters"
; registry [9]. SMTP servers SHOULD NOT
; use unregistered names.
4.5. 其他实现问题
4.5.1. 最小实现
为使 SMTP 可用,所有接收方必须提供以下最小实现。为符合本规范,必须支持以下命令:
EHLO HELO MAIL RCPT DATA RSET NOOP QUIT VRFY
任何包含支持邮件中继或投递的 SMTP 服务器的系统,必须支持保留邮箱"postmaster"作为不区分大小写的本地名。如果服务器总是在连接开场时返回 554(如第 3.1 节所述),此 postmaster 地址并非严格必要。接受发往 postmaster 的邮件的要求意味着:针对 SMTP 服务器提供邮件服务的任何域中 postmaster 的邮箱的 RCPT 命令,以及"RCPT TO:<Postmaster>"(无域规格)的特殊情况,都必须被支持。
期望 SMTP 系统尽一切合理努力接受来自 Internet 上任何其他系统的、发往 Postmaster 的邮件。在极端情况下——例如为了遏制拒绝服务攻击或其他安全破坏——SMTP 服务器可以阻断发往 Postmaster 的邮件。然而,此类安排应当被狭义地裁剪,以避免阻断不属于此类攻击的消息。
4.5.2. 透明性
如果没有某种数据透明性规定,字符序列"<CRLF>.<CRLF>"会结束邮件文本,并且不能被用户发送。一般而言,用户并不知道此类"被禁止"的序列。为允许所有用户编写的文本被透明传输,使用以下过程:
- 在发送一行邮件文本之前,SMTP 客户端检查该行的第一个字符。如果它是句点,则在行首再插入一个句点。
- 当 SMTP 服务器收到一行邮件文本时,它检查该行。如果该行由一个单独句点组成,它被视为邮件结束指示符。如果第一个字符是句点且行上还有其他字符,则删除第一个字符。
邮件数据可以包含 128 个 ASCII 字符中的任何一个。所有字符都要被投递到收件人的邮箱,包括空格、垂直与水平制表符,以及其他控制字符。如果传输信道提供 8 位字节(八位组)数据流,7 位 ASCII 码以右对齐方式在八位组中传输,高位清零。关于这些条件在充当中继功能的 SMTP 系统中的特殊处理,见第 3.6 节。
在某些系统中,可能需要在接收与存储时变换数据。这对于使用不同于 ASCII 的本地字符集、以记录而非字符串存储数据、或在邮箱内部使用特殊字符序列作为分隔符的主机可能是必要的。如果此类变换是必要的,它们必须是可逆的,特别是当它们被应用于正在中继的邮件时。
4.5.3. 大小与超时
4.5.3.1. 大小限制与最小值
有若干对象有要求的/最小值/最大值大小。每个实现必须能够接收至少这些大小的对象。应当尽可能避免大于这些大小的对象。然而,某些 Internet 邮件构造(例如编码的 X.400 地址,RFC 2156 [35])常常需要更大的对象。客户端可以尝试传输这些,但必须准备好在服务器无法处理时被其拒绝。在最大程度上,应当使用对这些对象长度不加限制的实作技术。
对 SMTP 的扩展可能涉及使用占据多于一个八位组的字符。因此,本节在意图为绝对长度而非字符计数之处,以八位组规定长度。
4.5.3.1.1. Local-part
用户名或其他 local-part 的最大总长度为 64 个八位组。
4.5.3.1.2. 域
域名或数字的最大总长度为 255 个八位组。
4.5.3.1.3. 路径
反向路径或正向路径的最大总长度为 256 个八位组(包括标点与元素分隔符)。
4.5.3.1.4. 命令行
包括命令字与 <CRLF> 的命令行的最大总长度为 512 个八位组。可以使用 SMTP 扩展来增加此限制。
4.5.3.1.5. 应答行
包括应答码与 <CRLF> 的应答行的最大总长度为 512 个八位组。可以通过多行应答传达更多信息。
4.5.3.1.6. 文本行
包括 <CRLF> 的文本行的最大总长度为 1000 个八位组(不计入为透明性而复制的前导句点)。此数字可以通过使用 SMTP 服务扩展来增加。
4.5.3.1.7. 消息内容
消息内容(包括任何报文头部分以及消息主体)的最大总长度必须至少为 64K 八位组。自从 Internet 多媒体邮件标准(RFC 2045 [21])引入以来,Internet 上的消息长度急剧增长,应当尽可能避免消息大小限制。必须施加限制的 SMTP 服务器系统应当实现 RFC 1870 [10] 的"SIZE"服务扩展,并且将发送大消息的 SMTP 客户端系统应当尽可能利用它。
4.5.3.1.8. 收件人缓冲区
必须被缓冲的收件人的最小总数为 100 个收件人。以少于 100 条 RCPT 命令而拒绝消息(因收件人过多)违反了本文档。中继 SMTP 服务器不得、投递 SMTP 服务器不应基于头字段中显示的总收件人数对消息进行验证测试的原则表明:消息不应基于头字段中显示的总收件人数而被拒绝。对收件人数施加限制的服务器必须以有序方式行动,例如拒绝其限制之外的额外地址,而非静默丢弃先前已接受的地址。需要投递包含超过 100 条 RCPT 命令的消息的客户端,应当准备好在服务器拒绝在单条消息中接受超过 100 个收件人时,以 100 个收件人的"块"传输。
4.5.3.1.9. 超出限制时的处理
因超出这些限制而产生的错误可以使用应答码报告。一些应答码示例:
500 Line too long. or 501 Path too long or 452 Too many recipients (see below) or 552 Too much mail data.
4.5.3.1.10. 收件人过多代码
RFC 821 [1] 错误地将 SMTP 服务器用尽其关于 RCPT 命令数的实现限制("收件人过多")的错误列为应答码 552。此状况的正确应答码是 452。客户端在这种情况下应当将 552 码视为临时而非永久失败,以便下面的逻辑有效。
当一致的 SMTP 服务器遇到此状况时,其收件人缓冲区中至少有 100 条成功的 RCPT 命令。如果服务器能够接受该消息,则至少这 100 个地址将从 SMTP 客户端的队列中移除。当客户端尝试重传那些收到 452 应答的地址时,至少其中 100 个将能放入 SMTP 服务器的收件人缓冲区。每个能够投递任何内容的重传尝试都将能够处理至少 100 个此类收件人。
如果 SMTP 服务器对 RCPT 命令数有实现限制且此限制被用尽,它必须使用 452 应答码(但客户端也应当如上文所述准备好接受 552)。如果服务器对 RCPT 命令数有配置的站点策略限制,它可以改为使用 5yz 应答码。特别地,如果意图是禁止具有多于站点规定收件人数的消息,而非仅仅限制给定邮件事务中的收件人数,则对 452(或 552)码之后收到的任何 DATA 命令返回 503 应答,或在 DATA 之后不返回任何先前的否定应答而直接返回 503,是合理的。
4.5.3.2. 超时
SMTP 客户端必须提供超时机制。它必须使用每命令超时,而非试图以某种方式对整个邮件事务计时。超时应当易于重新配置,最好无需重新编译 SMTP 代码。为实现这点,为每个 SMTP 命令以及数据传送的每个缓冲区设置一个定时器。后者意味着总体超时本质上与消息大小成比例。
基于与繁忙邮件中继主机的广泛经验,每命令超时的最小值应当如下:
4.5.3.2.1. 初始 220 消息:5 分钟
SMTP 客户端进程需要区分失败的 TCP 连接与接收初始 220 问候消息的延迟。许多 SMTP 服务器接受 TCP 连接但延迟发送 220 消息,直到其系统负载允许处理更多邮件。
4.5.3.2.2. MAIL 命令:5 分钟
4.5.3.2.3. RCPT 命令:5 分钟
如果对邮件列表与别名的处理未被推迟到消息被接受之后,则需要更长的超时。
4.5.3.2.4. DATA 启动:2 分钟
这是在等待 DATA 命令的"354 开始输入"应答期间。
4.5.3.2.5. 数据块:3 分钟
这是在等待传输一块数据的每个 TCP SEND 调用完成期间。
4.5.3.2.6. DATA 终止:10 分钟
这是在等待"250 OK"应答期间。当接收方得到终止消息数据的最后一个句点时,它通常执行处理以将消息投递到用户邮箱。此处的虚假超时将非常浪费,并且通常会导致消息的多个副本被投递,因为它已被成功发送且服务器已承担投递责任。进一步讨论见第 6.1 节。
4.5.3.2.7. 服务器超时:5 分钟
SMTP 服务器在等待发送方的下一条命令时,应当具有至少 5 分钟的超时。
4.5.4. 重试策略
主机 SMTP 实现的常见结构包括用户邮箱、一个或多个用于排队传输中消息的区域,以及一个或多个用于发送与接收邮件的守护进程。确切结构将随主机上用户的需求以及主机支持的邮件列表的数量与大小而变化。我们描述几种已被证明有用、特别是对支持高流量邮件程序的优化。
任何排队策略必须在每命令基础上包含所有活动的超时。排队策略在任何情况下都不得针对错误消息发送错误消息。
4.5.4.1. 发送策略
SMTP 客户端的通用模型是一个或多个周期性尝试传输外发邮件的进程。在典型系统中,编写消息的程序有某种方法来请求对新外发邮件的即时关注,而无法立即传输的邮件必须被排队并由发送方定期重试。邮件队列条目将不仅包含消息本身,还包含信封信息。
在一次尝试失败后,发送方必须延迟重试特定目的地。一般而言,重试间隔应当至少为 30 分钟;然而,当 SMTP 客户端能够确定非投递原因时,更复杂且可变的策略将是有益的。
重试持续进行,直到消息被传输或发送方放弃;放弃时间通常需要至少为 4-5 天。对于未投递通知与等同错误消息,相对于标准消息,设定较短的最大重试次数可能是恰当的。重试算法的参数必须可配置。
客户端应当保留它无法到达的主机列表,以及相应的连接超时,而非仅仅重试排队的邮件项。
经验表明,失败通常是临时的(目标系统或其连接已崩溃),这支持一种策略:在消息进入队列的第一小时内尝试两次连接,然后退避到每两或三小时一次。
SMTP 客户端可以与 SMTP 服务器合作来缩短排队延迟。例如,如果从特定地址收到邮件,则很可能为该主机排队的邮件现在可以被发送。在许多情况下,应用此原则可以消除对显式"立即发送队列"功能(如 ETRN,RFC 1985 [36])的需求。
该策略可以由于每主机的多个地址(见下)而进一步修改,以优化投递时间与资源使用。
SMTP 客户端可能为每个不可达的目标主机有大量的消息队列。如果所有这些消息在每次重试周期都被重试,将产生过度的 Internet 开销,并且发送系统将被阻塞很长时间。注意,SMTP 客户端通常只能在几分钟超时之后才能确定投递尝试失败,并且即使每次连接一分钟的超时,如果对同一主机的数十甚至数百个排队消息重复重试,也会导致非常大的延迟。
同时,SMTP 客户端在缓存服务器的否定应答时应当极为谨慎。在极端情况下,如果在同一 SMTP 连接期间多次发出 EHLO,服务器可能返回不同的答案。更重要的是,不得缓存对 MAIL 命令的 5yz 应答。
当一条邮件消息要投递给多个收件人,并且要向其发送消息副本的 SMTP 服务器对多个收件人是相同的,则只应传输消息的一份副本。即,SMTP 客户端应当使用命令序列:MAIL、RCPT、RCPT、...、RCPT、DATA,而非序列:MAIL、RCPT、DATA、...、MAIL、RCPT、DATA。然而,如果地址非常多,可以对每条 MAIL 命令的 RCPT 命令数施加限制。应当实现此效率特性。
类似地,为实现及时投递,SMTP 客户端可以支持多个并发的外发邮件事务。然而,可以施加某种限制,以保护主机不将其所有资源用于邮件。
4.5.4.2. 接收策略
SMTP 服务器应当尝试始终在 SMTP 端口(由 IANA 指定为端口 25)上保持一个待处理的监听。这需要支持多个传入的 SMTP TCP 连接。可以施加某种限制,但不能一次处理多于一个 SMTP 事务的服务器不符合本文档的意图。
如上所述,当 SMTP 服务器从特定主机地址收到邮件时,它可以激活自身的 SMTP 排队机制,以重试该主机地址待处理的任何邮件。
4.5.5. 具有空反向路径的消息
现有与提议的标准要求以空反向路径发送的若干类通知消息,即第 3.7 节讨论的未投递通知、其他类型的投递状态通知(DSN,RFC 3461 [32]),以及消息处置通知(MDN,RFC 3798 [37])。所有这些种类的消息都是关于先前消息的通知,它们被发送到先前邮件消息的反向路径。(如果此类通知消息的投递失败,通常表明该通知消息所寻址的主机的邮件系统有问题。因此,在某些主机上,MTA 被设置为将此类失败的通知消息转发给能够修复邮件系统问题的人,例如通过 postmaster 别名。)
所有其他类型的消息(即,任何不被 Standards-Track RFC 要求具有空反向路径的消息)应当以有效的、非空的返回路径发送。
自动化邮件处理程序的实现者应当小心确保正确处理各类具有空反向路径的消息。特别地,此类系统不应回复具有空反向路径的消息,并且它们不应在转发时向此类消息添加非空的返回路径,或将空返回路径改为非空返回路径。
5. 地址解析与邮件处理
5.1. 定位目标主机
一旦 SMTP 客户端在词法上标识了一个要投递以进行处理(如第 2.3.5 节与第 3.6 节所述)的域,就必须执行 DNS 查找来解析该域名(RFC 1035 [2])。这些名称预期是完全限定域名(FQDN):从部分名称或本地别名推断 FQDN 的机制不在本规范范围内。由于历史上的问题,用于消息初始提交的 SMTP 服务器不应做此类推断(邮件提交服务器 [18] 有稍多一些灵活性),而中间(中继)SMTP 服务器不得做此类推断。
查找首先尝试定位与该名称关联的 MX 记录。如果找到 CNAME 记录,所得名称被当作初始名称一样处理。如果返回不存在域错误,此情形必须作为错误报告。如果返回临时错误,消息必须被排队并稍后重试(见第 4.5.4.1 节)。如果返回空的 MX 列表,该地址被当作与指向该主机的、偏好为 0 的隐式 MX 资源记录关联一样处理。如果存在 MX 记录,但其中无一是可用的,或隐式 MX 不可用,此情形必须作为错误报告。
如果为一个给定名称找到了一个或多个 MX 资源记录,SMTP 系统不得利用与该名称关联的任何地址资源记录,除非它们是通过 MX 资源记录定位的;上述"隐式 MX"规则仅在没有 MX 记录存在时适用。如果 MX 记录存在,但其中无一是可用的,此情形必须作为错误报告。
当查找与 MX 资源记录关联的域名、并获得了关联数据字段时,该响应的数据字段必须包含一个域名。该域名在被查询时,必须返回至少一个给出消息应被定向到的 SMTP 服务器的 IP 地址的地址记录(例如 A 或 AAAA 资源记录)。任何其他的响应,特别是包含被查询时将返回 CNAME 记录的值,都超出本标准的范围。关于解析为 CNAME 的数据中标签的禁令在 RFC 2181 第 10.3 节 [38] 中有更详细的讨论。
当查找成功时,由于多个 MX 记录、多宿主(multihoming)或两者兼有,映射可以产生一个替代投递地址列表,而非单个地址。为提供可靠的邮件传输,SMTP 客户端必须能够按顺序尝试(并重试)此列表中的每个相关地址,直到一次投递尝试成功。然而,也可以对可尝试的替代地址数施加可配置的限值。无论如何,SMTP 客户端应当至少尝试两个地址。
两类信息用于为主机地址排序:多个 MX 记录,以及多宿主主机。
MX 记录包含一个偏好指示,当存在多于一个此类记录时必须用于排序(见下)。数字越小越受偏好。如果存在多个具有相同偏好的目的地,且没有明显的理由偏好某一个(例如,通过识别一个容易到达的地址),则发送方 SMTP 必须将它们在本地随机化,以将负载分散到
特定组织可以有多个邮件交换器。
目标主机(或许取自偏好的 MX 记录)可能是多宿主的,在这种情况下域名解析器将返回一列替代的 IP 地址。域名解析器接口有责任在必要时按递减偏好对此列表排序,且 SMTP 发送方必须按呈现的顺序尝试它们。
尽管尝试多个替代地址的能力是要求的,特定安装可能想限制或禁用替代地址的使用。发送方是否应当尝试使用多宿主主机的不同地址进行重试一直有争议。使用多个地址的主要论点是它最大化了及时投递的概率,并且有时是任何投递的概率;反面论点是它可能导致不必要的资源使用。注意,资源使用也强烈由第 4.5.4.1 节讨论的发送策略决定。
如果 SMTP 服务器收到一条以它为指定邮件交换器的目的地的消息,它可以中继该消息(可能在重写 MAIL FROM 和/或 RCPT TO 地址之后)、对该消息进行最终投递,或使用 SMTP 提供的传输环境之外的某种机制将其交出。当然,后两者都不要求进一步检查 MX 记录列表。
如果它确定应当在不重写地址的情况下中继该消息,它必须对 MX 记录排序以确定投递的候选项。这些记录首先按偏好排序,编号最低的纪录最受偏好。中继主机随后必须检查该列表中是否有它可能在邮件事务中以其闻名的任何名称或地址。如果找到匹配记录,该偏好级别及更高编号的所有记录必须从考虑中丢弃。如果此时没有记录剩下,则为错误状况,且消息必须作为不可投递退回。如果仍有记录剩下,它们应当如上所述、按最佳偏好优先被尝试。
5.2. IPv6 与 MX 记录
在当代 Internet 中,SMTP 客户端与服务器可能托管于 IPv4 系统、IPv6 系统,或兼容任一 Internet 协议版本的双重栈系统。因此,MX 记录指向的主机域可以包含"A RR"(IPv4)、"AAAA RR"(IPv6),或它们的任意组合。尽管 RFC 3974 [39] 讨论了混合环境中的一些运营经验,但它不够全面,不足以证明标准化,并且其某些建议似乎与本规范不一致。要采取的恰当动作要么取决于本地环境(例如相关网络的性能以及可能需要的任何转换),要么是显然的(例如,仅 IPv6 的客户端无需尝试查找 A 资源记录或尝试到达仅 IPv4 的服务器)。可能在 IPv6 或双重栈环境中运行的 SMTP 实现的开发者应当研究上述过程,特别是关于多宿主主机的评论,并且最好在考虑本地环境的同时,提供机制以促进 IPv4 与 IPv6 系统之间的运营调优与邮件互操作性。
6. 问题检测与处理
6.1. 可靠投递与通过电子邮件的应答
当接收方 SMTP 接受一段邮件(通过针对 DATA 发送"250 OK"消息)时,它是在承担投递或中继该消息的责任。它必须严肃对待此责任。它不得因轻率原因(例如因为主机随后崩溃,或因为可预见的资源短缺)而丢失消息。下一节与第 7.8 节讨论了某些不被认为是轻率的原因。
如果在消息被接受之后出现投递失败,接收方 SMTP 必须组成并邮寄一个通知消息。此通知必须使用该信封中的空("<>")反向路径发送。此通知的收件人必须是来自信封返回路径(或 Return-Path: 行)的地址。然而,如果该地址为空("<>"),接收方 SMTP 不得发送通知。显然,本节中没有任何内容能够或应当禁止本地决定(即,作为接收方 SMTP 的同一系统环境的一部分)在需要时本地记录或以其他方式传输关于空地址事件的信息。如果该地址是显式源路由,它必须被剥离到其最后一跳。
例如,假设必须为一条以下列方式到达的消息发送错误通知:
MAIL FROM:<@a,@b:user@d>
通知消息必须使用以下方式发送:
RCPT TO:<user@d>
消息被 SMTP 接受之后的一些投递失败是不可避免的。例如,由于"软"域名系统错误,接收 SMTP 服务器可能无法验证 RCPT 命令中的所有投递地址,因为目标是邮件列表(见前文对 RCPT 的讨论),或因为服务器充当中继且无法立即访问投递系统。
为避免由于超时而收到重复消息,接收方 SMTP 必须设法最小化响应最终 <CRLF>.<CRLF> 数据结束指示所需的时间。关于此问题的讨论见 RFC 1047 [40]。
6.2. 不需要的、主动提供的与"攻击"消息
Internet 邮件系统的效用与可预测性要求:可以投递的消息应当被投递,无论这些消息关联有任何语法或其他缺陷,也无论其内容如何。如果它们不能被投递,且在 SMTP 事务期间不能被 SMTP 服务器拒绝,则应当如上所述被"退回"(用未投递通知消息退回)。在当今世界,许多 SMTP 服务器运营者发现不需要的批量电子邮件的数量远远超过所需邮件的数量,并且接受一条消息可能通过提供地址验证而触发额外的不需要流量,这些原则可能不实用。
如第 7.8 节与第 7.9 节所讨论,在实践中允许在不通知发送方的情况下丢弃邮件。然而,这极其危险,并且违反了邮件要么被投递要么被退回的长期传统与社群期望。如果静默丢弃消息被滥用,它可能轻易破坏对 Internet 邮件系统可靠性的信心。因此,静默丢弃消息应当只在极有把握消息是严重欺诈或以其他方式不恰当时才考虑。
为了尽可能进一步延伸"尽可能投递"的原则,将没有无效返回地址的邮件不投递可能是一个理性的策略,尽管网络的历史是:用户通常通过投递任何可以投递的消息而得到更好的服务。可靠地确定返回地址无效可能是一个困难且耗时的过程,特别是如果假定的发送系统不可直接访问或不完全准确地支持 VRFY,并且即使采用了"丢弃具有无效返回地址的消息"策略,它也只应在几乎确定返回地址事实上无效时应用。
反之,如果一条消息因被发现含有恶意内容而被拒绝(此决定超出本文档所定义 SMTP 服务器的范围),则不应发送拒绝("退回")消息,除非接收站点确信那些消息将被有用投递。在这些情况下,偏好与默认是:当传入消息被确定含有恶意内容时,避免发送未投递消息。
6.3. 循环检测
简单地计算消息中"Received:"头字段的数量,已被证明是一种有效的(尽管很少是最优的)检测邮件系统中循环的方法。使用此技术的 SMTP 服务器应当使用较大的拒绝阈值,通常至少为 100 个 Received 条目。无论使用何种机制,服务器必须包含检测并停止平凡循环的规定。
6.4. 对不规则性的补偿
不幸的是,Internet 邮件协议的变体、创造性解释与公然违反确实会发生;有人会认为它们发生得相当频繁。关于行为良好的 SMTP 接收方或中继应当拒绝格式错误的消息、尝试原样传递、还是尝试修复它以增加成功投递(或后续应答)的几率的争论,几乎与结构化网络邮件的诞生同时开始,并且没有减缓的迹象。拒绝的倡导者声称,尝试的修复很少完全充分,且拒绝坏消息是让侵权软件被修复的唯一途径。修复或"无论如何都要投递"的倡导者辩称,用户偏好邮件尽可能通过,并且在这方面存在显著的市场压力。在实践中,无论实际开发者的偏好如何,这些市场压力对特定供应商可能比严格遵守标准更重要。
与格式不良消息相关的问题因分离式 UA 邮件阅读协议(邮政协议(POP)第 2 版 [15]、邮政协议(POP)第 3 版 [16]、IMAP 第 2 版 [41] 与 PCMAIL [42])的引入而加剧。这些协议鼓励将 SMTP 用作发布(消息提交)协议,以及将 SMTP 服务器用作这些客户端主机(通常只是间歇地连接到 Internet)的中继系统。历史上,许多此类客户端机器缺乏 SMTP(事实上,还有邮件格式协议 RFC 822 [28])所假设的某些机制与信息。一些不能充分跟踪时间;另一些没有时区概念;还有一些不能标识它们自己的名称或地址;当然,没有哪个能满足支撑 RFC 822 认证地址概念的假设。
为响应这些弱 SMTP 客户端,许多 SMTP 系统现在补全以不完整或不正确形式投递给它们的消息。当服务器能够识别或认证客户端、且它们之间先前有协议时,此策略通常被认为是恰当的。相比之下,对于对用户的客户端机器知之甚少或一无所知的中继或投递 SMTP 服务器所应用的修复,至多存在极大的担忧。许多此类问题通过使用单独的协议(例如 RFC 4409 [18] 定义的协议)进行消息提交、而非为此目的使用发起 SMTP 服务器来解决。
当必要时,以下对正在处理的消息的更改可以由发起 SMTP 服务器、或用作 SMTP 初始发布(消息提交)协议目标的服务器应用:
- 当没有出现 message-id 字段时,添加它;
- 当没有出现日期、时间或时区时,添加它们;
- 将地址纠正为恰当的 FQDN 格式。
服务器关于客户端的信息越少,这些更改正确的可能性越小,并且在考虑是否执行修复以及如何执行时,应当应用越多的谨慎与保守。提供中间中继功能的 SMTP 服务器不得应用这些更改。
在所有情况下,提供正确信息的、正常运作的客户端优于 SMTP 服务器的更正。在所有情况下,服务器所执行动作应当记录在跟踪头字段和/或头字段注释中。
7. 安全考量
7.1. 邮件安全与伪造
SMTP 邮件本质上是不可靠安全的:即便是相当普通的用户,也有可能直接与接收方和中继 SMTP 服务器协商,并构造出能让天真(缺乏经验)的收件人误以为邮件来自别处的消息。要构造出连专家都无法侦测的“伪造(spoofed)”邮件,难度会稍大一些,但对于有决心且具备相关知识的人来说,这点难度仍不足以构成威慑。因此,随着人们对互联网邮件认识的加深,大家也越来越清楚:SMTP 邮件在传输层面本质上无法被认证,也无法提供完整性校验。真正的邮件安全只能依赖于端到端的、作用于消息体的机制,例如使用数字签名的方案(参见 RFC 1847 [43],以及例如 RFC 4880 [44] 中的 Pretty Good Privacy(PGP),或 RFC 3851 [45] 中的 Secure/Multipurpose Internet Mail Extensions(S/MIME))。
各种在传输层面提供认证(例如从 SMTP 客户端到 SMTP 服务器)的协议扩展与配置选项,对上述传统处境有一定改善。然而一般而言,它们只认证一台服务器到另一台服务器,而不是一整条中继与服务器链,更谈不上认证用户或用户机器。因此,除非它们配合在精心设计的信任环境中对责任进行审慎交接,否则它们本质上仍弱于那些使用数字签名消息、而非依赖传输系统完整性的端到端机制。
试图让用户更难把信封返回路径(reverse path)和“From”头字段设置为指向自己以外的有效地址,在很大程度上是误入歧途的:这会妨碍一些合法应用,例如某用户代表另一用户发送邮件、错误(或正常)回复应当发往某个特定地址、或者单条消息要发往不同主机上的多个收件人。(那些为用户提供便捷方式、按每条消息修改这些头字段的系统,应当尽量为用户建立一个主要且永久的邮箱地址,以便消息数据中能够合理地生成 Sender 头字段。)
除倡导“不应为了防范试图伪造邮件的用户而禁用有用功能”之外,本规范不进一步讨论与 SMTP 相关的认证问题。
7.2. “盲抄送”(Blind Copies)
出于若干原因,未出现在消息头部分的地址可能会出现在发给 SMTP 服务器的 RCPT 命令中。最常见的两种情况是:将一个邮件地址用作“列表展开器(list exploder)”(一个会解析为多个地址的单一地址),以及出现“盲抄送(blind copies)”。尤其是在存在多个 RCPT 命令的情况下,为了避免削弱这些机制的部分初衷,SMTP 客户端与服务器不应该把全部 RCPT 命令参数复制到头部分中,无论是作为跟踪头字段的一部分,还是作为信息性或私有扩展头字段。由于这条规则在实践中经常被违反,且无法被强制实施,那些意识到“bcc”用法的发送 SMTP 系统,可能会发现将每一份盲抄送作为只含单个 RCPT 命令的独立消息事务来发送会有所帮助。
在 SMTP 事务(“信封”)中,“反向”(来自 MAIL、SAML 等命令)或“正向”(RCPT)地址与头部分中的地址之间,并不存在固有的对应关系。接收系统不应该试图推断这种对应关系,并用它来修改待投递消息的头部分。流行的“Apparently-to”头字段既违反了这一原则,又是无意信息泄露的常见来源,不应该被使用。
7.3. VRFY、EXPN 与安全
如第 3.5 节所讨论,各站点可能出于安全原因(见下文)禁用 VRFY 或 EXPN 中的任意一个或全部。作为上述内容的推论,允许禁用的实现必须不表现出已验证了实际上并未被验证的地址。如果某站点出于安全原因禁用了这些命令,SMTP 服务器必须返回 252 应答,而不是可能与其他“验证成功”或“验证失败”代码相混淆的代码。
在仅做了语法检查后就返回 250 应答码并列出 VRFY 命令中的地址,违反了这条规则。当然,一个“支持”VRFY 的实现,若无论地址是否有效都总是返回 550,同样不符合规范。
在公共互联网上,邮件列表的内容已经成为所谓“垃圾邮件发送者(spammers)”获取地址信息的流行来源。随着列表管理员对列表本身的不当使用安装防护措施,利用 EXPN 来“收割(harvest)”地址的做法也日益增多。然而,VRFY 和 EXPN 对于经过认证的用户以及在一个管理域内部仍然是有用的。例如,VRFY 和 EXPN 可用于执行内部审计,检查邮件如何被路由,以确保没有人将敏感邮件自动转发到组织之外。实现了 SMTP 认证的站点,可以选择仅向经过认证的请求者提供 VRFY 和 EXPN。实现仍然应该提供对 EXPN 的支持,但站点应该仔细权衡利弊。
禁用 VRFY 是否带来任何真正的边际安全性,取决于一系列其他条件。在许多情况下,RCPT 命令可被用来获取关于地址有效性的相同信息。另一方面,特别是在对 RCPT 命令的地址有效性判定被推迟到收到 DATA 命令之后的情况下,RCPT 可能根本不返回任何信息,而 VRFY 则被期望在生成应答码之前认真尝试判定有效性(见上文讨论)。
7.4. 基于 251 与 551 应答码的邮件重定向
在客户端使用来自 RCPT 命令的 251 或 551 应答码来自动更新其未来行为(例如更新用户的地址簿)之前,它应当确认服务器的真实性。否则,它可能会遭受中间人(man in the middle)攻击。
7.5. 公告中的信息披露
关于在问候应答或 HELP 命令的应答中公布服务器类型与版本(有时甚至包括服务器域名)所带来的调试便利,与暴露可能在潜在敌对攻击中有用的信息这一弊端之间的权衡,一直存在持续争论。调试信息的价值毋庸置疑。主张公开这些信息的人指出,真正保护好 SMTP 服务器,远比希望通过隐藏服务器的确切身份来掩盖已知漏洞以获得更多保护要好得多。鼓励站点带着这一考量来评估其中的权衡;实现至少应该提供某种方式,将类型与版本信息提供给其他网络主机。
7.6. 跟踪字段中的信息披露
在某些情况下,例如当邮件源自并非直接位于公共互联网上的局域网(LAN)而其主机位于其中时,符合本规范生成的跟踪(“Received”)头字段可能会泄露通常不可用的主机名及类似信息。这通常不构成问题,但那些对名称泄露有特别顾虑的站点应当意识到这一点。此外,当涉及多个收件人时,可选的 FOR 子句应当谨慎提供,或者根本不提供,以免无意中将“盲抄送”收件人的身份泄露给他人。
7.7. 消息转发中的信息披露
如第 3.4 节所讨论,使用 251 或 551 应答码来标识与某邮箱关联的替换地址,可能会无意中泄露敏感信息。关注这些问题的站点应当确保它们选择并适当地配置服务器。
7.8. 抵抗攻击
近年来,针对 SMTP 服务器的攻击有所增加,其目的或是试图发现用于发送不请自来消息的地址,或是单纯要使服务器对其他用户不可达(即作为应用层的拒绝服务攻击)。虽然实现此类攻击的手段超出了本标准的范围,但理性的运维行为要求允许服务器检测此类攻击并采取自我保护行动。例如,如果服务器判定作为攻击一部分的大量 RCPT TO 命令正在被发送,且其中大部分或全部具有无效地址,那么服务器在生成适当数量的 5yz(通常为 550)应答后关闭连接,是合理的。
7.9. SMTP 服务器的操作范围
一条由来已久的原则是:SMTP 服务器可以基于对其提供服务的站点而言合理的任何运维或技术原因,拒绝接收邮件。然而,站点与设施之间的合作才使互联网成为可能。如果站点过度利用拒绝流量之权,电子邮件可用性的普遍性(互联网的优势之一)将受到威胁;如果一个站点决定对其将接受并处理的流量有所选择,则应当格外谨慎并保持平衡。
近年来,经由任意站点的中继功能被用来作为敌对行动的一部分,以隐藏邮件的真实来源。一些站点已决定将该中继功能的使用限制在已知或可识别的来源,实现应该提供执行此类过滤的能力。当邮件因这些或其他策略原因被拒绝时,应当针对 EHLO(或 HELO)、MAIL 或 RCPT 酌情使用 550 代码作为应答。
8. IANA 考量
IANA 为支持本规范维护着三个注册表,它们均是为 RFC 2821 或更早的文档创建的。本文档按下述方式扩展了第三个注册表。所列注册表引用以发布时为准;IANA 不保证与这些 URL 相关联的位置长期有效。这些注册表如下:
- 第一个注册表是“Simple Mail Transfer Protocol (SMTP) Service Extensions”[46],由 SMTP 服务扩展及其关联关键字,以及(如需要)参数与动词组成。如第 2.2.2 节所规定,任何以“X”开头的条目都不得进入该注册表。只有在 Standards-Track 或经 IESG 专门为此目的批准的 Experimental RFC 中定义的服务扩展(及关联的关键字、参数或动词)才能登记入册。
- 第二个注册表是“Address Literal Tags”[47],由“标签(tags)”组成,用于标识除 IPv4 地址(由 RFC 821 及本文档规定)之外的域字面量形式。该注册表的初始条目用于 IPv6 地址(由本文档规定)。额外的字面量类型在使用前需要标准化;目前不预期会有此类类型。
- 第三个注册表是“Mail Transmission Types”[46],由 RFC 821 建立、并由本规范续用,是一个链路与协议标识符的注册表,用于第 4.4 节所述时间戳(“Received:”头字段)的“via”和“with”子句中。除本文档规定的之外,链路与协议标识符只能通过标准化,或通过 RFC 文档化、且经 IESG 批准的 Experimental 协议扩展来登记。该命名空间用于标识,且大小不受限制:鼓励 IESG 基于清晰的文档说明以及明确的区分方法来批准,而非基于对方法本身特性的偏好。
已在本注册表的“VIA link types”与“WITH protocol types”子节中增加了一个附加子节,用于包含如上所述的“Additional-registered-clauses”登记项。该注册表将包含子句名称、描述、关联 String 的语法摘要,以及引用。随着新子句被定义,原则上它们可以规定创建自己的注册表——如果那些 String 由保留字或关键字而非受限较少的字符串组成的话。与链路和协议标识符一样,附加子句只能经由标准化,或通过 RFC 文档化、且经 IESG 批准的 Experimental 协议扩展来登记。附加子句命名空间用于标识,且大小不受限制:鼓励 IESG 基于清晰的文档、实际的使用或该子句将被使用的强烈迹象,以及明确的需求来批准,而非基于对子句本身特性的偏好。
此外,如果将来创建了任何附加的跟踪头字段(即除 Return-path 与 Received 之外),那些跟踪头字段必须被加入由 BCP 90(RFC 3864)[11]为配合 RFC 5322 [4]使用而建立的 IANA 注册表中。
9. 致谢
许多人参与了 RFC 2821 的制定。应当查阅该文档以获取那些致谢。就本文档而言,编辑与社区感谢 Dawn Mann 和 Tony Hansen,他们协助完成了将文档内部格式从一套系统编辑并转换为另一套系统这一非常痛苦的过程。
无论是本文档还是 RFC 2821,若没有已故的 Jon Postel 的诸多贡献与洞见,都不可能完成。这些贡献当然包括 RFC 821 中 SMTP 的原始规范。RFC 821 中相当数量的文本仍出现在本文档中,Jon 的几个原始示例也仅作了必要的更新以反映规范中的其他变更。
许多人在邮件列表上或给作者的便笺中提出了意见或建议。若干人提出了重要的修正或澄清,其中包括 Matti Aarnio、Glenn Anderson、Derek J. Balling、Alex van den Bogaerdt、Stephane Bortzmeyer、Vint Cerf、Jutta Degener、Steve Dorner、Lisa Dusseault、Frank Ellerman、Ned Freed、Randy Gellens、Sabahattin Gucukoglu、Philip Guenther、Arnt Gulbrandsen、Eric Hall、Richard O. Hammer、Tony Hansen、Peter J. Holzer、Kari Hurtta、Bryon Roche Kain、Valdis Kletnieks、Mathias Koerber、John Leslie、Bruce Lilly、Jeff Macdonald、Mark E. Mallett、Mark Martinec、S. Moonesamy、Lyndon Nerenberg、Chris Newman、Douglas Otis、Pete Resnick、Robert A. Rosenberg、Vince Sabio、Hector Santos、David F. Skoll、Paul Smith 与 Brett Watson。
区域主任 Lisa Dusseault、Ted Hardie 与 Chris Newman 为重启并推动此项工作所做的努力,以及一个出于相同目的的特设委员会,均在此致以谢意。该委员会成员(按字母顺序)为 Dave Crocker、Cyrus Daboo、Tony Finch、Ned Freed、Randall Gellens、Tony Hansen、本文件作者,以及 Alexey Melnikov。Tony Hansen 还担任了审阅本文档的邮件列表特设主席;没有他的努力、平衡感与公正性,以及耐心,这项工作显然不可能完成。
10. 参考文献
10.1. 规范性参考文献
- Postel, J., "Simple Mail Transfer Protocol", STD 10, RFC 821, August 1982.
- Mockapetris, P., "Domain names - implementation and specification", STD 13, RFC 1035, November 1987.
- Braden, R., "Requirements for Internet Hosts - Application and Support", STD 3, RFC 1123, October 1989.
- Resnick, P., "Internet Message Format", RFC 5322, October 2008.
- Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, March 1997.
- American National Standards Institute (formerly United States of America Standards Institute), "USA Code for Information Interchange", ANSI X3.4-1968, 1968. ANSI X3.4-1968 has been replaced by newer versions with slight modifications, but the 1968 version remains definitive for the Internet.
- Crocker, D. and P. Overell, "Augmented BNF for Syntax Specifications: ABNF", STD 68, RFC 5234, January 2008.
- Hinden, R. and S. Deering, "IP Version 6 Addressing Architecture", RFC 4291, February 2006.
- Newman, C., "ESMTP and LMTP Transmission Types Registration", RFC 3848, July 2004.
- Klensin, J., Freed, N., and K. Moore, "SMTP Service Extension for Message Size Declaration", STD 10, RFC 1870, November 1995.
- Klyne, G., Nottingham, M., and J. Mogul, "Registration Procedures for Message Header Fields", BCP 90, RFC 3864, September 2004.
10.2. 资料性参考文献
- Partridge, C., "Mail routing and the domain system", RFC 974, January 1986.
- Klensin, J., Freed, N., Rose, M., Stefferud, E., and D. Crocker, "SMTP Service Extensions", STD 10, RFC 1869, November 1995.
- Klensin, J., "Simple Mail Transfer Protocol", RFC 2821, April 2001.
- Butler, M., Postel, J., Chase, D., Goldberger, J., and J. Reynolds, "Post Office Protocol: Version 2", RFC 937, February 1985.
- Myers, J. and M. Rose, "Post Office Protocol - Version 3", STD 53, RFC 1939, May 1996.
- Crispin, M., "INTERNET MESSAGE ACCESS PROTOCOL - VERSION 4rev1", RFC 3501, March 2003.
- Gellens, R. and J. Klensin, "Message Submission for Mail", RFC 4409, April 2006.
- Freed, N., "SMTP Service Extension for Command Pipelining", STD 60, RFC 2920, September 2000.
- Vaudreuil, G., "SMTP Service Extensions for Transmission of Large and Binary MIME Messages", RFC 3030, December 2000.
- Freed, N. and N. Borenstein, "Multipurpose Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies", RFC 2045, November 1996.
- Klensin, J., Freed, N., Rose, M., Stefferud, E., and D. Crocker, "SMTP Service Extension for 8bit-MIMEtransport", RFC 1652, July 1994.
- Moore, K., "MIME (Multipurpose Internet Mail Extensions) Part Three: Message Header Extensions for Non-ASCII Text", RFC 2047, November 1996.
- Freed, N. and K. Moore, "MIME Parameter Value and Encoded Word Extensions: Character Sets, Languages, and Continuations", RFC 2231, November 1997.
- Vaudreuil, G., "Enhanced Mail System Status Codes", RFC 3463, January 2003.
- Hansen, T. and J. Klensin, "A Registry for SMTP Enhanced Mail System Status Codes", BCP 138, RFC 5248, June 2008.
- Freed, N., "Behavior of and Requirements for Internet Firewalls", RFC 2979, October 2000.
- Crocker, D., "Standard for the format of ARPA Internet text messages", STD 11, RFC 822, August 1982.
- Wong, M. and W. Schlitt, "Sender Policy Framework (SPF) for Authorizing Use of Domains in E-Mail, Version 1", RFC 4408, April 2006.
- Fenton, J., "Analysis of Threats Motivating DomainKeys Identified Mail (DKIM)", RFC 4686, September 2006.
- Allman, E., Callas, J., Delany, M., Libbey, M., Fenton, J., and M. Thomas, "DomainKeys Identified Mail (DKIM) Signatures", RFC 4871, May 2007.
- Moore, K., "Simple Mail Transfer Protocol (SMTP) Service Extension for Delivery Status Notifications (DSNs)", RFC 3461, January 2003.
- Moore, K. and G. Vaudreuil, "An Extensible Message Format for Delivery Status Notifications", RFC 3464, January 2003.
- Postel, J. and J. Reynolds, "File Transfer Protocol", STD 9, RFC 959, October 1985.
- Kille, S., "MIXER (Mime Internet X.400 Enhanced Relay): Mapping between X.400 and RFC 822/MIME", RFC 2156, January 1998.
- De Winter, J., "SMTP Service Extension for Remote Message Queue Starting", RFC 1985, August 1996.
- Hansen, T. and G. Vaudreuil, "Message Disposition Notification", RFC 3798, May 2004.
- Elz, R. and R. Bush, "Clarifications to the DNS Specification", RFC 2181, July 1997.
- Nakamura, M. and J. Hagino, "SMTP Operational Experience in Mixed IPv4/v6 Environments", RFC 3974, January 2005.
- Partridge, C., "Duplicate messages and SMTP", RFC 1047, February 1988.
- Crispin, M., "Interactive Mail Access Protocol: Version 2", RFC 1176, August 1990.
- Lambert, M., "PCMAIL: A distributed mail system for personal computers", RFC 1056, June 1988.
- Galvin, J., Murphy, S., Crocker, S., and N. Freed, "Security Multiparts for MIME: Multipart/Signed and Multipart/Encrypted", RFC 1847, October 1995.
- Callas, J., Donnerhacke, L., Finney, H., Shaw, D., and R. Thayer, "OpenPGP Message Format", RFC 4880, November 2007.
- Ramsdell, B., "Secure/Multipurpose Internet Mail Extensions (S/MIME) Version 3.1 Message Specification", RFC 3851, July 2004.
- Internet Assigned Number Authority (IANA), "IANA Mail Parameters", 2007, <http://www.iana.org/assignments/mail-parameters>.
- Internet Assigned Number Authority (IANA), "Address Literal Tags", 2007, <http://www.iana.org/assignments/address-literal-tags>.
附录 A. TCP 传输服务
TCP 连接支持 8 位字节的传输。SMTP 数据是 7 位 ASCII 字符。每个字符作为一个高位置零的 8 位字节传输。服务扩展可修改此规则,以允许在消息体部分传输完整的 8 位数据字节,或者,如果是专门为此设计的,在 SMTP 命令或应答中传输。
附录 B. 由 RFC 822 头字段生成 SMTP 命令
某些系统在邮件提交协议中使用(仅)RFC 822 头部分,或者在消息从用户代理(UA)交给邮件传输代理(MTA)时,由 RFC 822 头字段生成 SMTP 命令。虽然 MTA–UA 协议是私有事务,不受任何互联网标准覆盖,但这种方法存在问题。例如,当概念上属于邮件信封的信息在处理的早期阶段未从头字段信息中分离出来(并保持分离)时,对“bcc”副本与再分发列表的正确处理就反复出现问题。
建议 UA 为其初始(“提交客户端”)MTA 提供一个独立于消息本身的信封。然而,如果未提供信封,SMTP 命令应该按下述方式生成:
- 每个来自 TO、CC 或 BCC 头字段的收件人地址应该被复制到一条 RCPT 命令中(如果排队或投递需要,则生成多个消息副本)。这包括 RFC 822“group”中列出的任何地址。随后,任何 BCC 头字段应该从头部分中被移除。一旦该过程完成,应该检查剩余头字段,以确认至少仍保留了一个 TO、CC 或 BCC 头字段。如果没有,则应该按 [4] 的规定插入一个不含额外信息的 BCC 头字段。
- MAIL 命令中的返回地址应该(若可能)取自提交(本地)用户的系统身份,否则取自“From:”头字段。如果存在系统身份,且它与 From 头字段中的地址不同,则它也应该被复制到 Sender 头字段。(任何已经存在的 Sender 头字段应该被移除。)系统可以提供让提交者覆盖信封返回地址的方式,但可能希望将其使用限制为特权用户。这不能防止邮件伪造,但可能减少其发生频率;参见第 7.1 节。
当 MTA 以这种方式被使用时,它负有确保所传输消息有效的责任。检查该有效性的机制,以及处理(或退回)在到达时无效的消息的机制,属于 MUA–MTA 接口的一部分,不受本规范覆盖。
仅基于标准 RFC 822 信息之上的提交协议,必须不被用于从外来(非 SMTP)邮件系统向 SMTP 环境网关转发消息。构造信封所需的额外信息必须来自另一环境中的某个来源,无论是补充头字段还是外来系统的信封。
仅使用消息的“To”和“Cc”头字段来网关转发消息的尝试,已反复造成邮件环路及其他不利于互联网邮件环境正常运作的行为。当消息源自某个互联网邮件列表、并使用信封信息分发到外来环境时,这些问题尤其常见。当这些消息随后被一个仅基于头部分的转发器处理时,几乎不可避免地会 loop 回互联网环境(及该邮件列表)。
附录 C. 源路由
历史上,<reverse-path> 是一个由主机与源邮箱组成的反向源路由列表。<reverse-path> 中的第一台主机历史上就是发送 MAIL 命令的主机;如今,源路由不应该出现在 reverse-path 中。类似地,<forward-path> 可以是一个由主机与目的邮箱组成的源路由列表。然而一般而言,<forward-path> 应该只包含邮箱与域名,在需要路由信息时依赖域名系统来提供。源路由的使用已被废弃(见附录 F.2);尽管服务器必须按照第 3.3 节与附录 F.2 的讨论做好准备接收并处理它们,客户端不应该发送它们,且本节被纳入当前规范仅为提供背景。它相对 RFC 821 中的材料已作了一些修改,以防止可能混淆那些不期望完整源路由实现的客户端或后续服务器的服务器行为。
出于中继目的,forward-path 可以是形如“@ONE,@TWO:JOE@THREE”的源路由,其中 ONE、TWO 与 THREE 必须是完整的合格域名。这种形式用于强调地址与路由之间的区别。邮箱(此处为 JOE@THREE)是绝对地址,而路由是关于如何到达那里信息。这两个概念不应混淆。
如果使用了源路由,应当查阅 RFC 821 及下文,以了解构造与更新 forward-path 的机制。一个经由源路由到达的服务器(例如,其域名出现在 forward-path 列表的首位)必须在转发消息之前,从任何包含该域名的 forward-path 中移除其域名,并可以移除所有其他源路由信息。符合本规范的服务器不应该更新 reverse-path。
注意,forward-path 与 reverse-path 出现在 SMTP 命令与应答中,但不一定出现在消息中。也就是说,没有必要让这些路径、尤其是这种语法,出现在消息头部分的“To:”、“From:”、“CC:”等字段中。反之,SMTP 服务器必须不从消息头字段推导最终消息路由信息。
尽管有上述建议,当主机列表存在时,它是一个“反向”源路由,表明邮件经由列表中的每台主机被中继(列表中的第一台主机是最近的中继)。该列表被用作源路由,以将未投递通知返回给发件人。如果(与上述建议相反)某中继主机将自己加入列表开头,它必须使用它欲中继到的传输环境中已知的名字,而非它从中继出邮件的传输环境的名字(若二者不同)。注意,很容易出现一种情况:某些中继主机将自己的名字加入反向源路由,而其他主机没有,从而在路由列表中产生不连续。这也是为什么需要返回消息的服务器应该完全忽略源路由、而只使用邮箱中所规定的域名的另一个原因。
附录 D. 场景
本节给出若干类型 SMTP 会话的完整场景。在示例中,“C:”表示 SMTP 客户端所说的内容,“S:”表示 SMTP 服务器所说的内容。
D.1. 一个典型的 SMTP 事务场景
这个 SMTP 示例展示了由主机 bar.com 上的 Smith 发送,发往主机 foo.com 上的 Jones、Green 与 Brown 的邮件。此处我们假设主机 bar.com 直接联系主机 foo.com。邮件被 Jones 与 Brown 接受。Green 在主机 foo.com 上没有邮箱。
S: 220 foo.com Simple Mail Transfer Service Ready C: EHLO bar.com S: 250-foo.com greets bar.com S: 250-8BITMIME S: 250-SIZE S: 250-DSN S: 250 HELP C: MAIL FROM:<Smith@bar.com> S: 250 OK C: RCPT TO:<Jones@foo.com> S: 250 OK C: RCPT TO:<Green@foo.com> S: 550 No such user here C: RCPT TO:<Brown@foo.com> S: 250 OK C: DATA S: 354 Start mail input; end with <CRLF>.<CRLF> C: Blah blah blah... C: ...etc. etc. etc. C: . S: 250 OK C: QUIT S: 221 foo.com Service closing transmission channel
D.2. 中止的 SMTP 事务场景
S: 220 foo.com Simple Mail Transfer Service Ready C: EHLO bar.com S: 250-foo.com greets bar.com S: 250-8BITMIME S: 250-SIZE S: 250-DSN S: 250 HELP C: MAIL FROM:<Smith@bar.com> S: 250 OK C: RCPT TO:<Jones@foo.com> S: 250 OK C: RCPT TO:<Green@foo.com> S: 550 No such user here C: RSET S: 250 OK C: QUIT S: 221 foo.com Service closing transmission channel
D.3. 中继邮件场景
第 1 步——源主机到中继主机
源主机对 XYZ.COM(目的地址)进行 DNS 查询,找到 DNS MX 记录,指定 xyz.com 为最佳优先级、foo.com 为较低优先级。它尝试打开到 xyz.com 的连接但失败。于是它打开到 foo.com 的连接,对话如下:
S: 220 foo.com Simple Mail Transfer Service Ready C: EHLO bar.com S: 250-foo.com greets bar.com S: 250-8BITMIME S: 250-SIZE S: 250-DSN S: 250 HELP C: MAIL FROM:<JQP@bar.com> S: 250 OK C: RCPT TO:<Jones@XYZ.COM> S: 250 OK C: DATA S: 354 Start mail input; end with <CRLF>.<CRLF> C: Date: Thu, 21 May 1998 05:33:29 -0700 C: From: John Q. Public <JQP@bar.com> C: Subject: The Next Meeting of the Board C: To: Jones@xyz.com C: C: Bill: C: The next meeting of the board of directors will be C: on Tuesday. C: John. C: . S: 250 OK C: QUIT S: 221 foo.com Service closing transmission channel
第 2 步——中继主机到目的主机
foo.com 在收到消息后,对 xyz.com 进行 DNS 查询。它找到同一组 MX 记录,但无法使用指向自身(或任何其他主机、作为更差优先级)的那条。它尝试打开到 xyz.com 本身的连接并成功。于是我们有:
S: 220 xyz.com Simple Mail Transfer Service Ready C: EHLO foo.com S: 250 xyz.com is on the air C: MAIL FROM:<JQP@bar.com> S: 250 OK C: RCPT TO:<Jones@XYZ.COM> S: 250 OK C: DATA S: 354 Start mail input; end with <CRLF>.<CRLF> C: Received: from bar.com by foo.com ; Thu, 21 May 1998 C: 05:33:29 -0700 C: Date: Thu, 21 May 1998 05:33:22 -0700 C: From: John Q. Public <JQP@bar.com> C: Subject: The Next Meeting of the Board C: To: Jones@xyz.com C: C: Bill: C: The next meeting of the board of directors will be C: on Tuesday. C: John. C: . S: 250 OK C: QUIT S: 221 foo.com Service closing transmission channel
D.4. 验证与发送场景
S: 220 foo.com Simple Mail Transfer Service Ready C: EHLO bar.com S: 250-foo.com greets bar.com S: 250-8BITMIME S: 250-SIZE S: 250-DSN S: 250-VRFY S: 250 HELP C: VRFY Crispin S: 250 Mark Crispin <Admin.MRC@foo.com> C: MAIL FROM:<EAK@bar.com> S: 250 OK C: RCPT TO:<Admin.MRC@foo.com> S: 250 OK C: DATA S: 354 Start mail input; end with <CRLF>.<CRLF> C: Blah blah blah... C: ...etc. etc. etc. C: . S: 250 OK C: QUIT S: 221 foo.com Service closing transmission channel
附录 E. 其他网关问题
一般而言,互联网与其他邮件系统之间的网关应该尝试在所涉及的两个邮件系统之间的边界上保留任何分层语义。那些试图通过映射走捷径的网关转换方法(例如将一个系统的信封信息映射到另一系统的消息头部分或正文)已被普遍证明在重要方面是不充分的。在那些不能同时满足既有信封又有头部分的系统与互联网邮件之间进行转换时,编写系统必须有这样的认识:某些信息丢失几乎是不可避免的。
附录 F. RFC 821 的弃用特性
RFC 821 的少数特性已被证明存在问题,不应该在互连网邮件中使用。
F.1. TURN
RFC 821 中描述的这个命令引发了重要的安全问题,因为在缺乏对请求切换客户端与服务器角色的主机进行强认证的情况下,它很容易被用来将邮件从其正确目的地转移开。它的使用已被弃用;SMTP 系统不应该使用它,除非服务器能够认证客户端。
F.2. 源路由
RFC 821 利用显式源路由的概念,经由一系列中继将邮件从一台主机传送到另一台主机。在域名系统的“MX”记录引入后,常规邮件流量中使用源路由的要求被消除了;而随着 RFC 1123 引入“@”之后的地址必须全部为完整合格域名这一明确要求,使用它们的最后一个重大理由也不复存在。因此,使用源路由仅存的理由是支持非常老的 SMTP 客户端或 MUA,以及用于邮件系统调试。不过,在后者情形下以及为了绕过严重的(但暂时的)问题(例如相关 DNS 记录的问题)而路由邮件时,它们仍然有用。
SMTP 服务器必须继续按照本文件正文与 RFC 1123 的规定接受源路由语法。如有必要,它们可以忽略这些路由,而只使用地址中的目标域。如果它们确实使用了源路由,消息必须被发往地址中显示的第一个域。特别地,服务器必须不在源路由内部猜测捷径。
客户端不应该使用显式源路由,除非在异常情形下,例如调试,或可能绕过防火墙或邮件系统配置错误进行中继。
F.3. HELO
如第 3.1 节与第 4.1.1 节所讨论,当服务器将接受 EHLO 时,应该使用 EHLO 而非 HELO。为了支持较老的客户端,服务器必须继续接受并处理 HELO。
F.4. # 字面量
RFC 821 规定可以将互联网地址指定为一个以井号“#”为前缀的十进制整数主机号。在实践中,那种形式自 TCP/IP 引入以来就已过时。它已被弃用,且必须不被使用。
F.5. 日期与年份
当 SMTP 客户端或服务器将日期插入消息时(例如插入跟踪头字段),必须使用四位数年份。两位数年份已被弃用;三位数年份在互联网邮件系统中从未被允许。
F.6. 发送(Sending)与邮寄(Mailing)之别
除规定向用户邮箱投递消息的机制外,RFC 821 还提供了额外的、可选的命令,用于直接将消息投递到用户的终端屏幕。这些命令(SEND、SAML、SOML)很少被实现,而且工作站技术的变更以及其他协议的引入,即便在实现了它们的地方,也可能已使其过时。
客户端不应该将 SEND、SAML 或 SOML 作为服务提供。服务器可以实现它们。如果服务器实现了它们,必须使用 RFC 821 中规定的实现模型,且命令名必须在 EHLO 命令的应答中公布。
作者地址
John C. Klensin
1770 Massachusetts Ave, Suite 322
Cambridge, MA 02140
USA
EMail: john+smtp@jck.com
完整版权声明
Copyright (C) The IETF Trust (2008).
本文件受 BCP 78 所含权利、许可与限制约束,除其中所规定者外,作者保留其全部权利。
本文件及其中所包含的信息按“AS IS(现状)”基础提供,且贡献者、其所代表或赞助的组织(如有)、互联网协会、IETF 信托与互联网工程任务组,否认所有明示或暗示的担保,包括但不限于任何关于使用 herein 信息不会侵犯任何权利的担保,以及任何关于适销性或特定用途适用性的暗示担保。
知识产权
IETF 不就任何可能声称与本文档所描述技术的实现或使用相关、或其范围如何的知识产权或其他权利的有效性或范围采取立场,也不表示它已作出任何独立努力来识别任何此类权利。关于 RFC 文件中权利相关程序的更多信息,见于 BCP 78 与 BCP 79。
向 IETF 秘书处做出的知识产权(IPR)披露副本、任何关于将可提供许可的保证,或为实施者或用户获取使用此类专有权利的通用许可或授权之尝试结果,可从 IETF 在线 IPR 仓库获取:http://www.ietf.org/ipr。
IETF 邀请任何利害关系方,将其注意到的、可能涵盖实施本标准所需技术的任何版权、专利或专利申请,或其他专有权利,提请 IETF 注意。请将相关信息寄至 ietf-ipr@ietf.org。
