4.1.2. COMMAND语法格式
命令是由命令码和其后的参数域组成的。命令码是四个字母组成的,不区别
大小写。因为下面的命令的作用是相同的:
MAIL Mail mail MaIl mAIl
这对于引导任何参数值的标记也是适用的,如TO和to就是一样的。命令码和
参数由一个或多个空格分开。然而在回复路径和转发路径中的参数是区别大小写
的。特别是在一些主机上,"smith"和"Smith"就根本不是一个用户。
参数域由不定长的字符串组成,它由<CRLF>结束,接收方在完全接收到此序列前
不会采取任何行动。方括号代表可选的参数域。如果不选择的话,系统选择默认
的设置。
下面是SMTP命令:
HELO <SP> <domain> <CRLF> MAIL <SP> FROM:<reverse-path> <CRLF>
RCPT <SP> TO:<forward-path> <CRLF>
DATA <CRLF>
RSET <CRLF>
SEND <SP> FROM:<reverse-path> <CRLF>
SOML <SP> FROM:<reverse-path> <CRLF>
SAML <SP> FROM:<reverse-path> <CRLF>
VRFY <SP> <string> <CRLF>
EXPN <SP> <string> <CRLF>
HELP [<SP> <string>] <CRLF>
NOOP <CRLF>
QUIT <CRLF>
TURN <CRLF>
上面参数域的格式在下面给BNF的格式给出,其中的"..."代表对于一个
域的一次或多次的重复。
<reverse-path> ::= <path>
<forward-path> ::= <path>
<path> ::= "<" [ <a-d-l> ":" ] <mailbox> ">"
<a-d-l> ::= <at-domain> | <at-domain> "," <a-d-l>
<at-domain> ::= "@" <domain>
<domain> ::= <element> | <element> "." <domain>
<element> ::= <name> | "#" <number> | "[" <dotnum> "]"
<mailbox> ::= <local-part> "@" <domain>
<local-part> ::= <dot-string> | <quoted-string>
<name> ::= <a> <ldh-str> <let-dig>
<ldh-str> ::= <let-dig-hyp> | <let-dig-hyp> <ldh-str>
<let-dig> ::= <a> | <d>
<let-dig-hyp> ::= <a> | <d> | "-"
<dot-string> ::= <字符串> | <字符串> "." <dot-string>
<字符串> ::= <字符> | <字符> <字符串>
<quoted-string> ::= """ <qtext> """
<qtext> ::= "\" <x> | "\" <x> <qtext> | <q> | <q> <qtext>
<字符> ::= <c> | "\" <x>
<dotnum> ::= <snum> "." <snum> "." <snum> "." <snum>
<number> ::= <d> | <d> <number>
<CRLF> ::= <CR> <LF>
<CR> ::= 回车符(ASCII码13) <LF> ::= (ASCII码10)
<SP> ::= 空格(ASCII码32) <snum> ::=由一个,两个或三个数字组成的介
于0-255之间的数字
<a> ::= 所有A-Z的52个大小写英文字母
<c> ::= 128个ASCII字符,但不包括空格和特殊字符
<d> ::= 0-9数字
<q> ::=不包括<CR>,<LF>,"或\的128个ASCII字符
<x> ::=所有128个ASCII字符
<special> ::= "<" | ">" | "(" | ")" | "[" | "]" | "\" | "." | "," | ";" | ":" | "@" """
或控制字符
注意: "\"是一个转意字符,它表示在其后的字符代表另外的意义。
例如"Joe\,Smith"用于表示单独一个由逗号分隔的用户名。主机通常由转化为
地址的名称代表。注意:域的名称元素是正式的名称,不能够使用昵称或假名。
有时候名称的转变机制可能不知道主机,这就造成了通信的阻塞。为了解决这
个问题,可以采取两种方法:一种方法是:在"#"后加入一个十进制数表示主机地址;
另一种方法是在其后加入32位的IP地址,IP地址的形式是由句号分隔的四个介于
0-255之间的十进制数。时间戳行和返回路径行的格式通常由下面定义:
<return-path-line> ::= "Return-Path:" <SP><reverse-path><CRLF>
<time-stamp-line> ::= "Received:" <SP> <stamp> <CRLF>
<stamp> ::= <from-domain> <by-domain> <opt-info> ";" <daytime>
<from-domain> ::= "FROM" <SP> <域> <SP>
<by-domain> ::= "BY" <SP> <域> <SP>
<opt-info> ::= [<via>] [<with>] [<id>] [<for>]
<via> ::= "VIA" <SP> <连接> <SP>
<with> ::= "WITH" <SP> <协议> <SP>
<id> ::= "ID" <SP> <字符串> <SP>
<for> ::= "FOR" <SP> <路径> <SP>
<连接> ::= 在网络信息中心注册的连接的标准名称
<协议> ::= 在网络中心注册的协议的名称
<daytime> ::= <SP> <日> <SP> <时间>
<日期> ::= <日> <SP> <月> <SP> <年>
<时间> ::= <小时> ":" <分> ":" <秒> <SP> <时区>
<dd> ::= 由一个或两个数字组成的每月1-31日
<月> ::= "JAN" | "FEB" | "MAR" | "APR" | "MAY" | "JUN" | "JUL" | "AUG" | "SEP" | "OCT" | "NOV" | "DEC"
<年> ::= 由两位数字表示本世界的年代00-99
<小时> ::= 每天的24小时,由0到24
<分> ::= 每小时的分钟数0-59
<秒> ::= 每分钟的秒数0-59
<时区> ::= 全球标准时区
返回路径例子
Return-Path: <@CHARLIE.ARPA,@BAKER.ARPA:JOE@ABLE.ARPA>
时间戳行例子
Received: FROM ABC.ARPA BY XYZ.ARPA ; 22 OCT 81 09:23:59 PDT
Received: from ABC.ARPA by XYZ.ARPA via TELENET with X25
id M12345 for Smith@PDQ.ARPA ; 22 OCT 81 09:23:59 PDT
4.2. SMTP响应
对SMTP命令的响应是多样的,它确定了在邮件传输过程中请求和处理的
同步,也保证了发送SMTP知道接收SMTP的状态。每个命令必须有且只有一个
响应。
SMTP响应由三位数字组成,其后跟一些文本。数字帮助决定下一个应该
进入的状态,而文本对人是有意义的。三位的响应已经包括了足够的信息,
不用再阅读文本,文本可以直接抛弃或者传递给用户。特别的是,文本是与
接收和环境相关的,所以每次接收到的文本可能不同。在附录E中可以看到
全部的响应码。正规的情况下,响应由下面序列构成:三位的数字,<SP>,
一行文本和一个<CRLF>,或者也可以是一个多行响应。只有EXPN和HELP命令
可以导致多行应答,然而,对所有命令,多行响应都是允许的。
4.2.1. REPLY CODES BY FUNCTION GROUPS 500 格式错误,命令不可识别
(此错误也包括命令行过长)
501 参数格式错误
502 命令不可实现
503 错误的命令序列
504 命令参数不可实现
211 系统状态或系统帮助响应
214 帮助信息
220 <domain> 服务就绪
221 <domain> 服务关闭传输信道
421 <domain> 服务未就绪,关闭传输信道(当必须关闭时,此应答可以作
为对任何命令的响应)
250 要求的邮件操作完成
251 用户非本地,将转发向<forward-path>
450 要求的邮件操作未完成,邮箱不可用(例如,邮箱忙)
550 要求的邮件操作未完成,邮箱不可用(例如,邮箱未找到,或不可访问)
451 放弃要求的操作;处理过程中出错
551 用户非本地,请尝试<forward-path>
452 系统存储不足,要求的操作未执行
552 过量的存储分配,要求的操作未执行
553 邮箱名不可用,要求的操作未执行(例如邮箱格式错误)
354 开始邮件输入,以<CRLF>.<CRLF>结束
554 操作失败
4.3. 命令和应答序列
发送者和接收者之间的通信是一问一答的交替对话形式,由发送者控制。
这样,发送发出一条命令,接收者发出一个响应。接收者在发送下一条指令
前必须等应答。一个重要的应答是连接应答。在连接完成时,接收者通常会
发送220"服务就绪"。发送者在继续发送指令前会等待此应答。注意:每个连
接应答必须拥有服务主机的正式名称作为第一部分,其后跟响应码。例如:
220 <SP> USC-ISIF.ARPA <SP> Service ready <CRLF>
下面列出了成功和失败应答,这些应答必须遵守严格的次序,接收者可以
不理会应答中的文本,但是由数字指定的意义和操作和命令应答序列不能更改。
命令响应序列:
每个命令列出了它可能的应答。使用在可能应答前的前缀"P"表示预备的
(未用在SMTP中),"I"表示中间的,"S"表示成功,"F"表示失败,"E"表示错
误。如果STMP接收者必须关闭信道,可以对任何命令作出421(服务不可用,
关闭传输信道)响应。此表基于下面要讲述的状态图:
CONNECTION ESTABLISHMENT(建立连接)
S: 220
F: 421
HELO
S: 250
E: 500, 501, 504, 421
MAIL
S: 250
F: 552, 451, 452
E: 500, 501, 421
RCPT S: 250, 251 F: 550, 551, 552, 553, 450, 451, 452 E: 500, 501, 503, 421
DATA
I: 354 -> data -> S: 250
F: 552, 554, 451, 452
F: 451, 554
E: 500, 501, 503, 421
RSET
S: 250
E: 500, 501, 504, 421
SEND
S: 250
F: 552, 451, 452
E: 500, 501, 502, 421
SOML
S: 250
F: 552, 451, 452
E: 500, 501, 502, 421
SAML
S: 250
F: 552, 451, 452
E: 500, 501, 502, 421
VRFY
S: 250, 251
F: 550, 551, 553
E: 500, 501, 502, 504, 421
EXPN
S: 250
F: 550
E: 500, 501, 502, 504, 421
HELP
S: 211, 214
E: 500, 501, 502, 504, 421
NOOP
S: 250
E: 500, 421
QUIT
S: 221
E: 500
TURN
S: 250
F: 502
E: 500, 503
4.4. 状态图
下面状态图是一个简单的SMTP实现,每一组命令都有一个状态图。在图中,
只使用了响应码的第一位数字作为响应的代表。命令组是对每个命令建立模式然
后以结构模式将命令集中起来的。对于每个命令有三种可能的应答:成功(S),
失败(F)和错误(E)。在状态中,我们使用B代表开始,使用W代表等待应答。
此状态图使用了如下命令:HELO, MAIL, RCPT, RSET, SEND, SOML,
SAML, VRFY, EXPN, HELP, NOOP, QUIT, TURN.
下面是对于DATA命令的更复杂的状态图:
注意:这里的邮件内容是多行的,接收者只能收到最后一行时才发出应答。
4.5. 详细内容
4.5.1. 最小实现
为使SMTP能够工作,对于接收者来说,这是最少应该实现的命令:
COMMANDS - HELO
MAIL
RCPT
DATA
RSET
NOOP
QUIT
4.5.2. 透明性
没有对数据透明性的保证,在发送类似"<CRLF>.<CRLF>"结束邮件内容时会
发生错误。通常,用户不关心这个"非法"序列。若要所有用户能够透明地使用
必须使用以下措施:
1. 在发送邮件之间,发送SMTP必须检查邮件的每一行,如果是一个句号,就
在行首再加一个句号。
2. 当邮件被接收时,接收SMTP必须检查邮件的每一行,如果发现一行仅有一
个句号,邮件就此结束,如果一行中有两个句号,那么这一行中就只应该有一
个句号,而将第一个句号删除。
发送的邮件内容可以包括所有128个ASCII字符。所有字符发送到收信者的
邮箱,包括格式符号和其它控制字符。如果传输信道提供一个8位数据流,7位
的ASCII码就可以在其中传送,而将最高位置为0。一些系统在接收和存储时需
要对数据进行格式转换。对于使用不同于ASCII字符集的主机或不能以串的形
式而只能以记录形式存储的主机更是如此,如果必须进行转换,必须能够再次
转换回来,对于用于存储转发的主机更是如此。
4.5.3. 大小
一些对象需要最大和最小大小。也就是说,每个实现必须能够接收大于最
小大小的对象,不能发送大于最大大小的对象。对于可能的最大大小,实现技
术上并没有限制。
用户 用户名的最大长度是64个字节。
域 域的最大长度是64个字符
路径 回复路径和转发路径的最大长度是256个字符
命令行 命令行的最大长度,包括回车符为512个字符
应答行 应答行的最大长度,包括回车符为512个字符
文本行 文本行的最大长度,包括回车符和为透明性增加的字符不得超过1000
个字符
接收缓冲区 接收缓冲区最多可以容纳100个接收者
如果出错,应答如下:
500 行过长
501 路径过多
552 接收者过多
552 邮件内容过多
附录 A TCP传输服务
传输控制协议(TCP)在ARPA Internet中使用,并遵守网络协议的US DoD标
准。SMTP传输信道连接建立在发送进程的端口U和接收进程的端口L上。一个单一
的全双工信道用于传输。被指定用于此协议的服务端口为25,也就是说L=25。
TCP连接支持传输8位字节,而SMTP只需要传输7位;这样,每个8位字符的最高
位被置为0。
附录 B NCP传输服务
ARPANET主机-主机协议(由网络控制程序实现)也可以用于ARPANET。
SMTP传输信道连接建立在发送进程的端口U和接收进程的端口L上;其后,根据
初始连接协议(ICP)建立一对简单连接。这一对简单连接被用作传输信道。
此协议被指定为连接套接字25,也就是说L=25。NCP连接支持传输8位字节,而
SMTP只需要传输7位;这样,每个8位字符的最高位被置为0。
附录 C NITS
也可以使用网络独立转输服务。通过在NITS在发送进程和接收进程之间建
立传输信道。发送进程执行CONNECT原语,然后等待接收ACCEPT原语。NITS连接
支持传输8位字节,而SMTP只需要传输7位;这样,每个8位字符的最高位被置
为0。
附录 D X.25传输服务
可以直接使用公共数据网络接收的X.25服务,然而,推荐在其上使用可靠
的端到端的协议如TCP。
附录 E 应答码构成方法
三位的应答码每一位都有特定的意义。每一位应答表示是否是成功的,失败
的或未完成的。通过这一位,不复杂的SMTP发送就可以决定下一步的操作,如果
发送方希望大概了解究竟出了什么问题,它可以检测第二位,而第三位则保存了
最后更完整的信息。也就是说,从第一位到第三位,接收方可以一步比一步精
确地确定接收方的状态。对于第一位有五种可能的表示代表不同的意义:
1yz 部分完成应答
命令被接受,但是要求的操作被中止,原因在应答码中。发送方应该再次
发送另一命令指明是否继续操作,或者放弃操作。
2yz 全部完成应答
要求的操作已经完成,可以开始另一个新的请求。
3yz 需要近一步信息的部分完成应答
命令被接受,但是要求的操作被中止,需要接收进一步的信息。发送方应
该发送另一条命令指明进一步的信息。
4yz 暂时未完成应答
命令未被接受,要求的操作也未执行,但是发生错误的状态是暂时的,可
以再一次请求操作。发送者应该返回命令序列的开始命令(如果有的话)。很
难解释这个暂时的意义,特别对于两个不同的站点来说。区别应答是属于些类
还是下一类的方法是:如果能够不加任何改变地重复的再一次发送命令,就是
本类的,如果不是,就是下一类(5yz)的。
5yz 永久未完成应答
命令未被接受,要求的操作未完成。发送对命令的重复不起作用。即使一
些出错条件已经改变,但是用户已经不希望重试,而希望在未来的某个时间再
进行操作。
应答的第二位的意义有以下几类:
x0z 语法:此类型的应答是针对以下情况的:语法错误;符合语法但命令不存
在功能;未完成或冗余的命令。
x1z 信息:此类型的应答是用于请求信息的,如状态或帮助信息。
x2z 连接:此类型的应答是关于传输信道的。
x3z 未使用。
x4z 未使用。
x5z 邮件系统:此类型的应答指明接收方邮件系统关于请求传送或其它操作
的状态的。
第三位给出了更详细的说明。列出的应答表说明了这一点。文本应答是
推荐使用的,而不是必须使用的,它的内容是可以根据不同情况而变化的。
另一方面,应答码必须严格遵守本节的说明。接收方不应该因为稍稍的不同
情况而自己创建新的代码而不使用已经定义的代码。例如,如NOOP命令的情
况,如果成功执行它后,不用返回任何新的信息,只用返回250应答。当发送
的命令要求一个未实现的站点指定操作时,应答应该是502。 应答文本可能
多于一行;在此情况下,文本必须被标记,接收文本的一方才不致于少读入
一行数据。这要求特定的格式说明多行应答。此格式是:每一行,除了最后
一行外,都以应答码加一个"-"开始。而最后一行以应答码加空格<SP>开始。
如下例:
123-First line
123-Second line
123-234 text beginning with numbers
123 The last line
通常情况下,接收的一方只用寻找应答码加空格的那一行就可以,而忽
略前面行的内容。在特殊的情况下,发送方必须知道响应文本的内容,这时
接收应答的一方可以通过当时的情况正确地决定是否需要知道文本的内容。
附录 F 一些例子
本节提供了一些SMTP会话的完整例子。
典型的SMTP操作
此类显示邮件如何由在USC-ISIF和机上的Smith发送到BBN-UNIX主机上
Jones,Green和Brown的。这里,我们假设USC-ISIF主机直接和BBN-UNIX主机联系。
Jones和Brown接收邮件,而Green在BBN-UNIX上没有邮箱。
R: 220 BBN-UNIX.ARPA Simple Mail Transfer Service Ready
S: HELO USC-ISIF.ARPA
R: 250 BBN-UNIX.ARPA
S: MAIL FROM:<Smith@USC-ISIF.ARPA>
R: 250 OK
S: RCPT TO:<Jones@BBN-UNIX.ARPA>
R: 250 OK
S: RCPT TO:<Green@BBN-UNIX.ARPA>
R: 550 No such user here
S: RCPT TO:<Brown@BBN-UNIX.ARPA>
R: 250 OK
S: DATA
R: 354 Start mail input; end with <CRLF>.<CRLF>
S: Blah blah blah...
S: ...etc. etc. etc.
S: .
R: 250 OK
S: QUIT
R: 221 BBN-UNIX.ARPA Service closing transmission channel
放弃SMTP操作
R: 220 MIT-Multics.ARPA Simple Mail Transfer Service Ready
S: HELO ISI-VAXA.ARPA R: 250 MIT-Multics.ARPA
S: MAIL FROM:<Smith@ISI-VAXA.ARPA>
R: 250 OK
S: RCPT TO:<Jones@MIT-Multics.ARPA>
R: 250 OK
S: RCPT TO:<Green@MIT-Multics.ARPA>
R: 550 No such user here
S: RSET
R: 250 OK
S: QUIT
R: 221 MIT-Multics.ARPA Service closing transmission channel
转发邮件
第一步:源主机到转发主机
R: 220 USC-ISIE.ARPA Simple Mail Transfer Service Ready
S: HELO MIT-AI.ARPA
R: 250 USC-ISIE.ARPA
S: MAIL FROM:<JQP@MIT-AI.ARPA>
R: 250 OK
S: RCPT TO:<@USC-ISIE.ARPA:Jones@BBN-VAX.ARPA>
R: 250 OK
S: DATA
R: 354 Start mail input; end with <CRLF>.<CRLF>
S: Date: 2 Nov 81 22:33:44
S: From: John Q. Public <JQP@MIT-AI.ARPA>
S: Subject: The Next Meeting of the Board
S: To: Jones@BBN-Vax.ARPA
S:
S: Bill:
S: The next meeting of the board of directors will be
S: on Tuesday.
S: John.
S: .
R: 250 OK
S: QUIT
R: 221 USC-ISIE.ARPA Service closing transmission channel ,