标题：简单邮件传输协议
介绍
简单邮件传输协议（SMTP）的目标是可靠高效地传送邮件，它独立于传送子系统而且仅要求一条可以保证传送数据单元顺序的通道。附录A，B，C和D描述了不同传送服务下SMTP的使用。在名词表中还定义了本文档中使用的术语。
SMTP的一个重要特点是它能够在传送中接力传送邮件，传送服务提供了进程间通信环境（IPCE），此环境可以包括一个网络，几个网络或一个网络的子网。理解到传送系统（或IPCE）不是一对一的是很重要的。进程可能直接和其它进程通过已知的IPCE通信。邮件是一个应用程序或进程间通信。邮件可以通过连接在不同IPCE上的进程跨网络进行邮件传送。更特别的是，邮件可以通过不同网络上的主机接力式传送。
是因特网电子邮件系统首要的应用 层协议。它使用由TCP提供的可靠的数据传输服务把邮件消息从发信人的邮件服务器传送到收信人的邮件服务器。跟大多数应用层协议一样，SMTP也存在两个 端：在发信人的邮件服务器上执行的客户端和在收信人的邮件服务器上执行的服务器端。SMTP的客户端和服务器端同时运行在每个邮件服务器上。当一个邮件服 务器在向其他邮件服务器发送邮件消息时，它是作为SMTP客户在运行。当一个邮件服务器从其他邮件服务器接收邮件消息时，它是作为SMTP服务器在运行。
SMTP协议与人们用于面对面交互的礼仪之间有许多相似之处。首先，运行在发送端邮件服务器主机上的SMTP客户，发起建立一个到运行在接收端邮件服务 器主机上的SMTP服务器端口号25之间的TCP连接。如果接收邮件服务器当前不在工作，SMTP客户就等待一段时间后再尝试建立该连接。这个连接建立之 后，SMTP客户和服务器先执行一些应用层握手操作。就像人们在转手东西之前往往先自我介绍那样，SMTP客户和服务器也在传送信息之前先自我介绍一下。 在这个SMTP握手阶段，SMTP客户向服务器分别指出发信人和收信人的电子邮件地址。彼此自我介绍完毕之后，客户发出邮件消息。SMTP可以指望由 TCP提供的可靠数据传输服务把该消息无错地传送到服务器。如果客户还有其他邮件消息需发送到同一个服务器，它就在同一个TCP连接上重复上述过程;否 则，它就指示TCP关闭该连接。[1]
SMTP模型
SMTP设计基于以下通信模型：针对用户的邮件请求，发送SMTP建立与接收SMTP之间建立一个双向传送通道。接收SMTP可以是最终接收者也可以是中间传送者。SMTP命令由发送SMTP发出，由接收SMTP接收，而应答则反方面传送。
一旦传送通道建立，SMTP发送者发送MAIL命令指明邮件发送者。如果
SMTP接收者可以接收邮件则返回OK应答。SMTP发送者再发出RCPT命令确认邮件是否接收到。如果SMTP接收者接收，则返回OK应答；如果不能接收到，则发出拒绝接收应答（但不中止整个邮件操作），双方将如此重复多次。当接收者收到全部邮件后会接收到特别的序列，如果接收者成功处理了邮件，则返回OK应答。　
SMTP提供传送邮件的机制，如果接收方与发送方连接在同一个传送服务下时，邮件可以直接由发送方主机传送到接收方主机；或者，当两者不在同一个传送服务下时，通过中继SMTP服务器传送。为了能够对SMTP服务器提供中继能力，它必须拥有最终目的主机地址和邮箱名称。
MAIL命令参数是回复路径，它指定邮件从何处来；而RCPT命令的参数是转发路径的，它指定邮件向何处去。向前路径是源路径，而回复路径是返回路径（它用于发生错误时返回邮件）。
当同一个消息要发往不同的接收者时，SMTP遇到了向不同接收者发送同一份数据的复制品的问题，邮件命令和应答有一个比较奇怪的语法，应答也有一个数字代码。在下面，例子中可以看到哪些使用实际的命令和应答。完整的命令和应答在第四节。
命令与应答对大小写不敏感，也就是说，命令和应答可以是大写，小写或两者的混合，但这一点对用户邮件名称却不一定是对的，因为有的主机对用户名大小写是敏感的。这样SMTP实现中就将用户邮箱名称保留成初始时的样子，主机名称对大小写不敏感。
命令与应答由ASCⅡ字母表组成，当传送服务提供8位字节传送通道，每7位字符正确传送，而最高位被填充为0。当指定一般的命令或应答格式后，参数会由一些类似于语言的字符串表示出来，如"<string>"或"<reverse-path>"，这里尖括号表示这是一种类似于语言的变量。
SMTP过程
本节提供了SMTP中的一些过程。头一个说明的是基本发送过程（定义为发送操作）。下来描述向前传送邮件，确认邮箱名称和扩展邮件列表，发送到终端和打开关闭交换。在本节的最后是对中断，邮件域的说明。本节的例子只是一部分命令和应答的序列，完整的例子见附录F。3.1. MAIL在SMTP发送操作中有三步，操作由MAIL命令开始给出发送者标识。一系列或更多的RCPT命令紧跟其后，给出了接收者信息，然后是DATA命令列出发送的邮件内容，最后邮件内容指示符确认操作。
过程中的第一步是MAIL命令，<reverse-path >；包括源邮箱。
MAIL <SP> FROM:<reverse-path><CRLF> 
此命令告诉接收者新的发送操作已经开始，请复位所有状态表和缓冲区。它给出反向路径以进行错误信息返回。如果请求被接收，接收方返回一个250 OK应答。<reverse-path>；中不止包括了邮箱，它包括了主机和源邮箱的反向路由，其中的第一个主机就是发送此命令的主机。
过程中的第二步是发送RCPT命令。
RCPT <SP> TO:<forward-path> <CRLF> 
此命令给出向前路径标识接收者，如果命令被接收，接收方返回一个
250 OK应答，并存储向前路径。如果接收者未知，接收方会返回一个550 Failure应答。此过程可能会重复若干次。
<forward-path>；不仅包括邮件，它是主机和目的邮箱的路由表，在其中的第一个主机就是接收命令的主机。过程中的第三步是发送DATA命令。
DATA <CRLF> 
如果命令被接收，接收方返回一个354 Intermediate应答，并认定以下的各行都是信件内容。当信件结尾收到并存储后，接收者发送一个250 OK应答。因为邮件是在传送通道上发送，因此必须指明邮件内容结尾，以便应答对话可以重新开始。SMTP通过在最后一行仅发送一个句号来表示邮件内容的结束，在接收方，一个对用户透明的过程将此符号过滤掉，以不影响正常的数据。
注意：邮件内容包括如下提示：Date,Subject,To,Cc,From。
邮件内容指示符确认邮件操作并告知接收者可以存储和再发送数据了。如果此命令被接收，接收方返回一个250 OK应答。DATA命令仅在邮件操作未完成或源无效的情况下失败。
上面所述的过程是一个发送操作。这些命令只能以上面的顺序使用。下例表示了在一个发送操作中这些命令的使用。
SMTP过程例子 此例是在Alpha..ARPA主机的Smith发送邮件给Beta..ARPA主机的Jones，Green和Brown的，这里假定主机Alpha与主机Beta直接相连。
S: MAIL FROM:<Smith@Alpha..ARPA> 
R: 250 OK 
S: RCPT TO:<Jones@Beta..ARPA> 
R: 250 OK 
S: RCPT TO:<Green@Beta..ARPA> 
R: 550 No such user here 
S: RCPT TO:<Brown@Beta..ARPA> 
R: 250 OK 
S: DATA 
R: 354 Start mail input; end with<CRLF>.<CRLF> 
S: Blah blah blah... 
S: ...等等
S: <CRLF>.<CRLF> 
R: 250 OK 
此信被前两个人接收，而第三个人在此主机上没有邮箱。3.2. 转发下面是一些<forward-path>；中目的地址不正确的，但接收者知道正确的目的地址的例子。在这些例子中，下列应答之一（251,551）应该允许发送方与获得正确地址。
251：用户不在本地；将向前发送到<forward-path>；。
这个应答意味着，接收方SMTP知道用户的邮箱在另外的主机上，而且意味着将在未来使用正确的转向路径。请注意，主机或者用户，或者它们两者是不同的。接收方负责传送消息。
551 ：用户非本地，请尝试<forward-path>
这个应答意味着接收SMTP知道用户的邮箱在另外的主机上，并意味着使用了正确的转发路径。注意请注意，主机或者用户，或者它们两者是不同的。接收方拒绝接收此用户的信件，发送者必须根据提供的信息重新发送或者向原发送者返回错误信息。下例显示了这些响应的应用。
转发的例子
S: RCPT TO:<Postel@USC-ISI..ARPA> 
R: 251 User not local; will forward to<Postel@USC-ISIF..ARPA> 
或者
S: RCPT TO:<Paul@USC-ISIB..ARPA> 
R: 551 User not local; please try<Mockapetris@USC-ISIF..ARPA> 3.3. 确认和扩展SMTP提供了另外的确认用户名和扩展邮件列表的功能。这些功能由VREF和EXPN命令完成，它们都以字符串为参数。对于VREF命令，字符串参数指的是用户名，对此命令的响应要包括用户的命名和用户的邮箱。对于EXPN命令，字符串参数指的是邮件列表，对此命令的响应多于一个，它们要包括所有列表中用户的命名和他们的邮箱。
“用户名”是一个多余的项目，它是故意被加上的。如果主机采用VREF命令和EXPN命令，最后本地邮箱必须提供用户名使它被主机确认。如果主机选择由另外的字符串作为用户名，也是允许的。
在一些主机中，邮箱列表和一个邮箱的代名有一点不清楚，因为一般的数据结构可能包括两种类型的入口。如果要发出对邮件列表的确认，应该给出确定响应。在接收到这个消息后，主机将把邮件传送到列表上所有的地址上去，如果没有接收到确定响应，就会报告错误。例如，
"550 That is a mail list,not a user name"。如果请求用于扩展一个用户名，可能通过返回包括一个名字的列表来形成确定响应，如果没有接收到确定响应，就会报告错误。（例如，"550 That is a user name,not a mailing list"）。
在多个响应的情况下（通常是对于EXPN而言的），每个应答指定一个邮箱。在模糊请求的情况下，例如"VRFY Smith"，这里两个Smith的响应必须是"553 User ambiguous"。
确认用户名的情况如下例所示：例3：
确认用户名
S: VRFY Smith 
R: 250 Fred Smith<Smith@USC-ISIF..ARPA> 
或者
S: VRFY Smith 
R: 251 User not local; will forward to<Smith@USC-ISIQ..ARPA> 
或者
S: VRFY Jones 
R: 550 String does not match anything. 
或者
S: VRFY Jones 
R: 551 User not local; please try<Jones@USC-ISIQ.,ARPA> 
或者
S: VRFY Gourzenkyinplatz 
R: 553 User ambiguous. 
邮箱列表要求多个响应的情况如下例所示：
S: EXPN Example-People 
R: 250-Jon Postel <Postel@USC-ISIF..ARPA> 
R: 250-Fred Fonebone <Fonebone@USC-ISIQ..ARPA> 
R: 250-Sam Q. Smith <SQSmith@USC-ISIQ.,ARPA> 
R: 250-Quincy Smith<@USC-ISIF..ARPA:Q-Smith@ISI-VAXA..ARPA> 
R: 250-<joe@foo-unix..ARPA> 
R: 250 <xyz@bar-unix..ARPA> 
或者
S: EXPN Executive-Washroom-List 
R: 550 Access Denied to You. 
VERF和EXPN命令的字符串命令参数因为具体实现的不同而不能再加以限制了。在一些系统上，EXPN命令的参数可能是一个包含邮件列表的文件名，但是在Internet上有许多不同的文件结构。
VRFY和EXPN命令在最小实现中并不包括，当它们实现时，它们也不要求被在传送间实现。
3.4. 发送信件和获得信件
SMTP的主要目的是将邮件发送到用户的邮箱中。由一些主机提供的类似的功能是把邮件送至用户的终端（如果用户正打开终端）。将邮件送到用户的邮箱中称为发送信件（mailing）；而送至用户终端则称之为获得信件
（sending）。因为在一些主机上，这两者的实现十分类似，所以它们同时
被放入了SMTP中。然而，获得信件命令在SMTP的最小实现中是没有的。用户应该具有控制向终端上写信息的能力。大部分主机允许用户接受或者拒绝类似的信息。
下面三个命令被定义来支持获得信件。它们被用于邮件命令而不是MAIL 
命令，指示接收SMTP这种操作的特殊意义：
SEND <SP> FROM:<reverse-path><CRLF> 
SEND命令要求邮件内容直接传送到用户终端。如果用户未打开终端（或
者未接收终端信息），450响应将返回一个RCPT命令。如果信息被成功发送，此操作成功。　
SOML <SP> FROM:<reverse-path><CRLF>；　
Send或者MaiL命令要求将邮件内容直接发送到用户的终端上（如果用户在终端上）。如果用户不在终端上，邮件内容直接进入邮箱。如果邮件被发送到用户终端或者用户信箱，发送操作成功。　
SAML <SP> FROM:<reverse-path><CRLF> 
Send和MaiL命令要求邮件内容直接发送到用户终端上（如果用户在终端上）。不管怎么样，信件都会进入信箱。如果信件进入信箱，发送操作成功。
用于MAIL命令的响应和这些命令的响应相同。
3.5. 打开和关闭
当打开传送通道时，要交换一些信息以确定双方的身份。以下的命令是
用于打开和关闭的：
HELO <SP> <domain> <CRLF> 
QUIT <CRLF> 
在HELLO命令中，主机自己发送命令，此命令可以被解释为：“你好，
我是XX”。
打开联结的例子
R: 220 BBN-UNⅨ..ARPA Simple Mail Transfer ServiceReady 
S: HELO USC-ISIF..ARPA 
R: 250 BBN-UNⅨ..ARPA 
关闭联结的例子
S: QUIT 
R: 221 BBN-UNⅨ..ARPA Service closing transmissionchannel
3.6. 转发
转发路径可能是如下格式："@ONE,@TWO:JOE@THREE"，在这里，ONE，TWO 
和THREE是主机。这种格式用于强调地址和路径的区别。邮箱是绝对地址，路径是关于如何到达的信息。这两个概念不应该被混淆。
概念上，转发路径的元素被移动到回复路径作为从一个SMTP服务器到另一个SMTP服务器的信息。回复路径是一个反向数据源路径，例如从当前信息的位置到发起者的位置。当一个SMTP服务器从转发路径中删除自己的标记并将它插入到回复路径中时，它必须使用它发送环境能够理解的名称来进行，以防它的名称在不同的环境中被理解为不同的名字。
如果当SMTP接收到信息的转发路径的第一个元素不是此SMTP的标记时，此元素不从转发路径中删除，而被用来决定下一个应该发送到的SMTP服务器。在任何情况下，SMTP都将自己的标记加入反向路径中。
使用源路径时，接收SMTP接收转发的邮件并发送到另一接收SMTP服务器上。接收服务器可以接受或拒绝转发本地用户的邮件。接收SMTP通过将它自己的标记从转发路径移至回复路径的开始处来改变命令参数。这时，接收SMTP变成了发送SMTP，也就建立了到下一个转发路径中SMTP的通道，然后，它向这个SMTP发送邮件。
在回复路径上的头一个主机应是发送SMTP命令的主机，在转发路径上第一个主机应是接收SMTP命令的主机。
注意：转发路径和回复路径出现在SMTP命令和应答中，但不一定要出现在信
息中。也就是说，没有必须要这样的路径特别这种格式出现在信息头的"To:"，"From:"和"CC:"等域中。
如果SMTP服务器接受了转发任务，但后来它发现因为转发路径不正确或者其它原理无法发送邮件，它必须建立一"undeliverable mail"信号，将此信号送到此信的发主者那里。
此信号必须是从此主机的SMTP服务上发出的，当然了，此服务器不应该再报告出错信息的错误。一种阻止这种出错报告循环的情况是在信号的邮件命令的回复路径上置空。在传送此信息时，允许将回复路径也置为空。一个MAIL命令后的回复路径为空表现为如下形式：
MAIL FROM:<> 
下例中显示了不可传送的邮件信息。此信息是对从HOSTW上的JOE发出的邮件经过在HOSTX需要经过HOSTZ到达HOSTY时出错的回应。我们看到的例子是在HOSTX和HOSTY之间发生的。
不可传送邮件信息的例子
S: MAIL FROM:<> 
R: 250 ok 
S: RCPT TO:<@HOSTX..ARPA:JOE@HOSTW..ARPA> 
R: 250 ok 
S: DATA 
R: 354 send the mail data,end with . 
S: Date: 23 Oct 81 11:22:33 
S: From: SMTP@HOSTY..ARPA 
S: To: JOE@HOSTW,.ARPA 
S: Subject: Mail System Problem 
S: Sorry JOE,your message to SAM@HOSTZ..ARPA lost. 
S: HOSTZ..ARPA said this: 
S: "550 No Such User" 
S: . 
R: 250 ok
常见问题
⒈ SMTP是什么?有什么作用?答： SMTP是Simple Mail Transfer Protocol的缩写，即简单邮件传输协议，是一种提供有效可靠传送电子邮件的协议，用于在两台邮件服务器间交换邮件.
⒉ 邮件服务器间邮件传输使用了TCP协议，为何邮件有时还会丢失?
答： 邮件服务器之间的SMTP协议使用TCP连接，可以保证邮件准确无误地在邮件服务器之间传输. 但由于邮件服务器本身的故障，例如邮件空间不足等，会导致邮件无法完成传输而导致丢失.
⒊ 发件人用户代理为何不直接将邮件发送给收件人的用户代理，而是通过邮件服务器来传输?
答： 因为用户电脑性能的限制，无法运行收发邮件的程序，并且无法不间断地运行并连接到互联网上. 因此只能将信件暂时存放在邮件服务器中，用户需要时就可以去下载信件.