RFC822(Standard for ARPA Internet Text Messages)基于RFC733(Standard for the Format of ARPA Network Text Messages)。
一、介绍
一封“消息(Message)”包括“信封(Envelope)”和“内容(Content)”,一般情况下,“信封(Envelope)”基于“内容(Content)”而生成。本文档只关注“内容(Content)”,而不涉及“信封(Envelope)”。
接下来如果未做特殊说明,“消息(Message)”就是指“内容(Content)”。
本文只约定“消息(Message)”在传输过程中的格式规范,而不对“消息的存储格式”,“消息处理系统特征”,“消息处理系统用户接口特征”等作出限定。
“消息(Message)”只包含纯文本内容,而不包含其他多媒体形式内容,如图片,音频,视频等。数据压缩,传输存储效率等细节都不作考虑和限定。
二、扩展的BNF
2.1、“或者”符号
1 | a/b |
hello/world
匹配“hello”或者“world”。
2.2、“整体”符号
1 | (a b) |
(hello world)
匹配“hello world”。
2.3、“重复”符号
1 | <l>*<m>a |
1*5a
匹配“1-5个a”,*a
匹配“0到无穷个a”,1*a
匹配“1到无穷个a”,*10
匹配“0到10个a”。
2.4、“可选”符号
1 | [a] |
[hello]
匹配“存在一个hello字符串”或者“不存在hello字符串”。
2.5、“重复特定次数”符号
1 | <n>a |
等价于<n>*<n>a
。1a
匹配“a”,2a
匹配“aa”。
2.6、“列表”符号
1 | <l>#<m>a |
1#5a
匹配“1-5个a,a之间至少以1个逗号隔开”,#a
匹配“0到无穷个a,a之间至少以1个逗号隔开”,1#a
匹配“1到无穷个a,a之间至少以1个逗号隔开”,#10a
匹配“0到10个a,a之间至少以1个逗号隔开”。
2.7、“注释”符号
1 | ;a |
;hello
表示“hello”是注释字符串。
三、消息(Message)的词法分析
3.1、一般描述
“消息(Message)”由“至少一个消息头字段(Header-Field)”和“可选的消息体(Body)”组成,中间以一个“空行”隔开。即:
Message=(1*(Header-Field))(CRLF)[Body]
3.2、消息头字段(Header-Field)
“消息头字段(Header-Field)”由“消息头字段名称(Field-Name)”和“可选的消息头字段体(Field-Body)”组成。即:
Header-Field=(Field-Name)”:”[Field-Body](CRLF)
Field-Name=1*< 由ASCII表中可打印字符组成(32-126),除了32(SPACE)和58(:) >
Field-Body=< text >
3.2.1、消息头字段(Header-Field)之分类
消息头字段(Header-Field)分为两类:“非结构化消息头字段”和“结构化消息头字段”。“结构化”类别跟“非结构化”类别相比,唯一的区别在于:前者的消息头字段体(Field-Body)可被解析为“specials,quoted-string,domain-literal,comment,atom”这5种组成成分。
3.2.2、消息头字段(Header-Field)之折叠和展开
1、折叠(Fold)
为了可读性,消息头字段(Header-Field)的消息头字段体(Field-Body)可被“折叠”,具体规则如下:
使用(CRLF)(1*(LWSP-char))替换linear-white-space,由“3.2、消息头字段(Header-Field)”中的“Field-Body”的定义可知,此时的“linear-white-space”事实上等价于“1*(LWSP-char)”。
2、展开(Unfold)
消息头字段(Header-Field)的消息头字段体(Field-Body)中“折叠”的逆过程为“展开”,具体规则如下:
使用1(LWSP-char)替换(CRLF)(1(LWSP-char))。
3.2.3、消息头字段(Header-Field)的消息头字段体(Field-Body)中的LWSP-char
消息头字段(Header-Field)的消息头字段体(Field-Body)中的LWSP-char没有任何意义,可被任意添加或者删减(除了CRLF后的LWSP-char不能被删除,因为这是“折叠”得到的)。
另外,有些地方规定只能有一个LWSP-char。
3.3、消息体(Body)
Body=< 由ASCII表中所有字符组成的字符串 >
3.4、词法分析记号
记号 | 表示含义 |
---|---|
CHAR | < ASCII表中任意字符,十进制范围0-127 > |
ALPHA | < ASCII表中任意拉丁字符,十进制范围65-90&97-122 > |
DIGIT | < ASCII表中任意数字字符,十进制范围48-57 > |
CTL | < ASCII表中控制字符和DEL字符,即“不可打印字符”,十进制范围0-31&127 > |
CR | < ASCII表中CR字符,十进制值为13 > |
LF | < ASCII表中LF字符,十进制值为10 > |
SPACE | < ASCII表中SPACE字符,十进制值为32 > |
HTAB | < ASCII表中TAB字符,十进制值为9 > |
<"> | < ASCII表中双引号字符,十进制值为34 > |
CRLF | (CR)(LF) |
LWSP-char | SPACE/HTAB |
linear-white-space | 1*([CRLF]LWSP-char) |
specials | “(“/“)”/“<”/“>”/“@”/“,”/“;”/“:”/“\“/<">/“.”/“[“/“]” |
delimiters | specials/linear-white-space/comment |
text | < 由任意ASCII表中字符(包括CR,LF)构成的字符串,除了CRLF > |
atom | < 1*(任意ASCII表中字符,除了specials,SPACE,CTL) > |
quoted-string | <">*(qtext/quoted-pair)<"> |
qtext | < 由任意ASCII表中字符(除了<">,”\“和CR)构成的字符串,包括linear-white-space > |
domain-literal | “[“*(dtext/quoted-pair)”]” |
dtext | < 由任意ASCII表中字符(除了”[“,”]”,”\“和CR)构成的字符串,包括linear-white-space > |
comment | “(“*(ctext/quoted-pair/comment)”)” |
ctext | < 由任意ASCII表中字符(除了”(“,”)”,”\“和CR)构成的字符串,包括linear-white-space > |
quoted-pair | “\“CHAR |
phrase | 1*(word) |
word | atom/quoted-string |
备注:
1、当消息被传递给一个不遵循本协议的消息处理系统时,comment被替换成一个SPACE
2、一般不区分大小写,除了以下这些词法单元:text,qtext,dtext,ctext,quoted-pair,local-part(其中的“Postmaster”作为特殊保留地址,不区分大小写)
四、消息(Message)的详细规范
4.1、详细规范
Message=(1*(Header-Field))(CRLF)[Body]或者说Message=(fields)(CRLF)[Body]
fields=(dates)(source)(1*destination)(*optional-field)
4.1.1、dates
dates=orig-date[resent-date]
orig-date=”Date””:”date-time(CRLF)
resent-date=”Resent-Date””:”date-time(CRLF)
4.1.2、source
source=[trace]originator[resent]
trace=(return)(1*received)
return=”Return-path””:”route-addr(CRLF)
received=”Received””:”[“from”domain][“by”domain][“via”atom](*(“with”atom))[“id”msg-id][“for”addr-spec]”;”date-time(CRLF)
msg-id=”<”addr-spec“>”
originator=authentic[“Reply-To””:”(1#address)(CRLF)]
authentic=”From””:”mailbox(CRLF)/(“Sender””:”mailbox(CRLF)”From””:”(1#mailbox)(CRLF))
resent=resent-authentic[“Resent-Reply-To””:”(1#address)(CRLF)]
resent-authentic=”Resent-From””:”mailbox(CRLF)/(“Resent-Sender””:”mailbox(CRLF)”Resent-From””:”(1#mailbox)(CRLF))
4.1.3、destination
destination=”To””:”(1#address)(CRLF)/“Resent-To””:”(1#address)(CRLF)/“cc””:”(1#address)(CRLF)/“Resent-cc””:”(1#address)(CRLF)/“bcc””:”(#address)(CRLF)/“Resent-bcc””:”(#address)(CRLF)
4.1.4、optional-field
optional-field=”Message-ID””:”msg-id(CRLF)/“Resent-Message-ID””:”msg-id(CRLF)/“In-Reply-To””:”(*(phrase/msg-id))(CRLF)/“References””:”(*(phrase/msg-id))(CRLF)/“Keywords””:”(#phrase)(CRLF)/“Subject””:”(*text)(CRLF)/“Comments””:”(*text)(CRLF)/“Encrypted””:”(1#2word)(CRLF)/extension-field/user-defined-field
4.1.4.1、extension-field
extension-field=< 扩展注册的标准消息头字段(Header-Field),规定消息头字段名称(Field-Name)不能以“X-/x-”字符串作为前缀 >
4.1.4.2、user-defined-field
user-defined-field=< 用户自定义完全私有的消息头字段(Header-Field),为了避免冲突,消息头字段名称(Field-Name)一般以“X-/x-”字符串作为前缀 >
4.2、转发
转发消息时会在不改变原有消息头字段(Header-Field)的基础上,增加一些以“Resent-”字符串作为前缀的消息头字段(Header-Field),这些消息头字段(Header-Field)的含义跟去掉“Resent-”字符串前缀对应的消息头字段(Header-Field)一致。
4.3、再细化
4.3.1、“Trace”族消息头字段
“Trace”族消息头字段主要由消息投递环节各个设备(除了发件人设备s)添加,用于记录路由信息。定义如下:
source=[trace]originator[resent]
trace=(return)(1*received)
return=”Return-path””:”route-addr(CRLF)
received=”Received””:”[“from”domain][“by”domain][“via”atom](*(“with”atom))[“id”msg-id][“for”addr-spec]”;”date-time(CRLF)
msg-id=”<”addr-spec“>”
4.3.1.1、“Return-Path”消息头字段
该消息头字段由消息投递环节最后一个设备(收件人设备e)添加,给出了确切地指向发件人的路由信息。类似的“Reply-To”消息头字段由发件人设备s添加,显式指定回复消息的接收者。
比如如下“Return-Path”字段值表示:消息反向依次经历“domain1,domain2,…,domainN”设备,消息发件人为“dslztx@domain.cn”。
1 | @domain1,@domain2,...,@domainN:dslztx@domain.cn |
4.3.1.2、“Received”消息头字段
该消息头字段由消息投递环节的各个设备添加(除了发件人设备s),用于记录消息在两个设备间的传递过程。
“from”:来源设备的IP地址、域名或主机名。
“by”:当前设备的IP地址、域名或主机名。
“via”:使用的物理传输路径,比如“Arpanet”、“Phonenet”等,具体值在“Network Information Center”中注册。
“with”:使用的传输协议,比如“SMTP”、“ESMTP”、“X.25”等,具体值在“Network Information Center”中注册。
“id”:消息在当前设备中的唯一序列号。
“for”:消息的收件人地址(“原始形式”,在消息投递环节中,消息的收件人地址有可能被各个设备转变成各种扩展形式,比如“缩写形式”)。
紧随其后的时间戳是当前设备接收该消息的时间。
4.3.2、“Originator”族消息头字段
“Originator”族消息头字段主要用于记录消息的发件人,也可用于显式指定回复消息的接收者。定义如下:
originator=authentic[“Reply-To””:”(1#address)(CRLF)]
authentic=”From””:”mailbox(CRLF)/(“Sender””:”mailbox(CRLF)”From””:”(1#mailbox)(CRLF))
4.3.2.1、“From/Resent-From”消息头字段
消息的作者。比如“张三(From)”写了一封消息,交给“李四(Sender)”去发送,但是希望由“王五(Reply-To)”接收回复消息。
4.3.2.2、“Sender/Resent-Sender”消息头字段
消息的发送者。比如“张三(From)”写了一封消息,交给“李四(Sender)”去发送,但是希望由“王五(Reply-To)”接收回复消息。
4.3.2.3、“Reply-To/Resent-Reply-To”消息头字段
回复消息的接收者。比如“张三(From)”写了一封消息,交给“李四(Sender)”去发送,但是希望由“王五(Reply-To)”接收回复消息。
4.3.3、“Destination”族消息头字段
“Destination”族消息头字段主要用于记录消息的收件人,可以指定多个。定义如下:
destination=”To””:”(1#address)(CRLF)/“Resent-To””:”(1#address)(CRLF)/“cc””:”(1#address)(CRLF)/“Resent-cc””:”(1#address)(CRLF)/“bcc””:”(#address)(CRLF)/“Resent-bcc””:”(#address)(CRLF)
4.3.3.1、“To/Resent-To”消息头字段
消息的收件人。
4.3.3.2、“Cc/Resent-Cc”消息头字段
消息的抄送收件人。
4.3.3.3、“Bcc/Resent-Bcc”消息头字段
消息的密送收件人。密送收件人信息不会被任何收件人(包括“收件人”,“抄送收件人”和“密送收件人”)看到。
4.3.4、“Optional”族消息头字段
“Optional”族消息头字段包括一些可选的消息头字段。
4.3.4.1、“Message-ID/Resent-Message-ID”消息头字段
用于记录在发件人设备s中该消息的唯一序列号。
4.3.4.2、“In-Reply-To”消息头字段
记录本消息(本消息是回复消息)所回复一系列消息的“Message-ID”值。
4.3.4.3、“References”消息头字段
记录本消息涉及到的一系列消息的“Message-ID”值。
4.3.4.4、“Keywords”消息头字段
由逗号隔开的消息的关键词。
4.3.4.5、“Subject”消息头字段
消息的主题。
4.3.4.6、“Comments”消息头字段
消息的注释。
4.3.4.7、“Encrypted”消息头字段
如果“消息体(Body)”是加密的,本字段记录解密需要用到的信息。该字段被废弃。
4.3.5、“Extension-Field”族消息头字段
扩展注册的标准消息头字段(Header-Field),规定消息头字段名称(Field-Name)不以“X-/x-”字符串作为前缀,具体消息头字段名在“Network Information Center”中注册。
4.3.6、“User-Defined-Field”族消息头字段
用户自定义完全私有的消息头字段(Header-Field),为了不与其他标准消息头字段(包括基本标准消息头字段和扩展标准消息头字段)冲突,消息头字段名称(Field-Name)一般以“X-/x-”字符串作为前缀,具体消息头字段名无需在“Network Information Center”中注册。
五、日期和时间规范
5.1、定义
date-time=[day“,”](date)(time)
day=”Mon”/“Tue”/“Wed”/“Thu”/“Fri”/“Sat”/“Sun”
date=(1*2DIGIT)(month)(2DIGIT)
month=”Jan”/“Feb”/“Mar”/“Apr”/“May”/“Jun”/“Jul”/“Aug”/“Sep”/“Oct”/“Nov”/“Dec”
time=(hour)(zone)
hour=2DIGIT“:”2DIGIT[“:”2DIGIT]
zone=”UT”/“GMT”/“EST”/“EDT”/“CST”/“CDT”/“MST”/“MDT”/“PST”/“PDT”/1ALPHA/((“+”/“-“)4DIGIT)
5.2、“zone”含义
“UT”:表示“Universal Time”或者“Greenwich Mean Time”。
“GMT”:表示“Greenwich Mean Time”。
“EST/EDT/CST/CDT/MST/MDT/PST/PDT”:表示北美时区标准。
“1ALPHA”:军事标准,“Z”表示“Universal Time”,“A”表示相对于“Universal Time”早1小时,“M”表示相对于“Universal Time”早12小时,“N”表示相对于“Universal Time”晚1小时,“Y”表示相对于“Universal Time”晚12小时等。
‘((“+”/“-“)4DIGIT)’:与“UT”的偏移值。
六、地址规范
6.1、定义
address=mailbox/group
mailbox=addr-spec/(phrase)(route-addr)
addr-spec=local-part“@”domain
local-part=word*(“.”word)
domain=sub-domain*(“.”sub-domain)
sub-domain=domain-ref/domain-literal
domain-ref=atom
route-addr=”<”[route]addr-spec“>”
route=1#(“@”domain)”:”
group=phrase“:”[#mailbox]”;”
6.2、含义
mailbox举例如:“George@gmail.com”,“George Jones<Group@Host>”等。
6.2.1、Domain-Literial
表示“ARPA Internet”地址,由4部分组成,每一部分都是一个8比特整型数值,形如:[10.0.3.19]。“Domain-Literial”的使用不再被鼓励。
6.2.2、Postmaster@Domain
作为特殊保留地址(表示相应域名下管理员的地址),不区分大小写。
七、字段添加过程
一封消息从“生成”到“到达”收件人需要经历一系列设备,示意图如图1所示。
图1
与上述过程相对应的是“字段添加过程”,分为两种情况描述“字段添加过程”:“非转发”和“转发”。
7.1、非转发
1、发件人设备s
生成消息的设备,添加以下字段:
- 添加“Date”字段(设备自动生成),表示消息生成时间
- 添加“From”字段或者添加“From和Sender”字段(人工填写),前者表示“消息的作者”和“消息的发送者”都为“From”字段的值;后者表示“消息的作者”是“From”字段的值,“消息的发送者”为“Sender”字段的值
- 可选添加“Reply-To”字段(人工填写),表示显式指定回复消息的接收者,否则回复消息的接收者为“From”字段值(无论是否有“Sender”字段值)
- 至少添加一个“To/cc/bcc”字段(人工填写),“To”字段值为“消息收件人列表”,“cc”字段值为“消息抄送收件人列表”,“bcc”字段值为“消息密送收件人列表”,“消息收件人”,“消息抄送收件人”和“消息密送收件人”都看得到“To”字段值和“cc”字段值,不能看到“bcc”字段值
- 可选添加“Message-ID”字段(设备自动生成),表示消息在发件人设备s中的唯一序列号
- 可选添加“In-Reply-To”字段(设备自动生成),本消息(本消息是回复消息)所回复一系列消息的“Message-ID”字段值
- 可选添加“References”字段(设备自动生成),字段值表示本消息涉及的一系列消息的“Message-ID”字段值
- 可选添加“Keywords”字段(人工填写),字段值表示消息的关键词组合,由逗号隔开
- 可选添加“Subject”字段(人工填写),表示消息主题
- 可选添加“Comments”字段(人工填写),字段值表示消息的注释
- 可选添加“Encrypted”字段(设备自动生成),字段值给出关于解密Body内容所需要的信息,该字段被废弃
2、中间设备mX
中间设备mX,添加以下字段:
- 添加“Received”字段,记录消息在两个设备间的传递过程
3、收件人设备e
收件人的设备,添加以下字段:
- 添加“Received”字段,记录消息在两个设备间的传递过程
- 添加“Return-Path”字段,记录确切地指向发件人的路由信息
7.2、转发
消息的原有字段不变,只是增加以“Resent-”字符串为前缀的字段。
八、其他
RFC822文档中有些内容前后不一致,甚至有些内容具有明显错误,本文内容跟其不完全一致。
**参考文献:** [1]http://www.rfc-editor.org/rfc/rfc822.txt [2]http://003317.blog.51cto.com/2005292/611104 [3]ASCII编码