跳到主要内容

4. 过时语法

本规范的早期版本允许不同于 (通常更宽松于) 本版本所允许的语法. 此外, 互联网上的消息中还使用过一些其解释从未被记录的语法元素. 尽管按照第 3 节的文法不得生成这些语法形式, 但符合规范的接收者仍必须接受并解析它们. 本节记录其中许多语法元素. 把第 3 节的文法与本节给出的定义相加, 就得到用于解释消息的文法.

注意: 本节指明任何实现都必须合理解释的语法形式. 然而, 确实存在甚至不符合本节所给出附加语法的互联网消息. 某种特定形式未出现在本文档任何一节中, 并不构成计算机程序崩溃, 或任何实现不可挽回地丢失畸形数据的理由. 如何稳健地处理消息由实现自行决定.

过时 (解释用) 语法与当前 (生成用) 语法之间的一个重要区别是: 在结构化头部字段主体中 (即任何结构化头部字段的冒号与 CRLF 之间), 空白字符 (包括折叠空白) 和注释可以自由插入任意语法记号之间. 这允许了许多复杂形式, 而这些形式已被证明难以被某些实现解析.

过时语法与当前语法之间的另一个关键区别是: 第 3.2.2 节关于注释和折叠空白中完全由空白组成的行的规则不再适用. 见下文第 4.2 节对折叠空白的讨论.

最后, 本节还包含某些以往允许出现在消息中的字符. NUL 字符 (ASCII 值 0) 曾经被允许, 但出于兼容性原因不再允许. 类似地, 除 CR、LF、SP 和 HTAB 之外的 US-ASCII 控制字符 (ASCII 值 1 到 8、11、12、14 到 31 以及 127) 曾被允许出现在头部字段主体中. CR 和 LF 曾被允许以 CRLF 之外的形式出现在消息中; 这种用法也在此处展示.

语法和语义的其他差异在以下各节中说明.

4.1. 其他过时记号​

这些语法元素用于过时语法或主语法中的其他位置. 裸 CR、裸 LF 和 NUL 被加入 obs-qp、obs-body 和 obs-unstruct. US-ASCII 控制字符被加入 obs-qp、obs-unstruct、obs-ctext 和 obs-qtext. 句点字符被加入 obs-phrase. obs-phrase-list 提供 (可能为空的) 逗号分隔短语列表, 其中可以包含"空"元素. 也就是说, 这样的列表中可以出现两个或更多逗号而其间没有任何内容, 或者逗号出现在列表的开头或结尾.

注意: obs-phrase 中的 "period" (或 "full stop") 字符 (".") 并不是本规范或任何其他规范的早期版本所允许的形式. 由于句点 (以及 specials 中的任何其他字符) 会带来区分短语与 addr-spec 部分的解析困难 (见第 4.4 节), 因此它当时不允许出现在 phrase 中. 它出现在此处, 是因为句点字符目前被用于许多消息地址的 display-name 部分, 特别是姓名中的首字母缩写, 因此必须被正确解释.

obs-NO-WS-CTL   =   %d1-8 /            ; US-ASCII control
%d11 / ; characters that do not
%d12 / ; include the carriage
%d14-31 / ; return, line feed, and
%d127 ; white space characters

obs-ctext = obs-NO-WS-CTL

obs-qtext = obs-NO-WS-CTL

obs-utext = %d0 / obs-NO-WS-CTL / VCHAR

obs-qp = "\" (%d0 / obs-NO-WS-CTL / LF / CR)

obs-body = *((*LF *CR *((%d0 / text) *LF *CR)) / CRLF)

obs-unstruct = *((*LF *CR *(obs-utext *LF *CR)) / FWS)

obs-phrase = word *(word / "." / CFWS)

obs-phrase-list = [phrase / CFWS] *("," [phrase / CFWS])

裸 CR 和裸 LF 在消息中出现时有两种不同的含义. 在许多情况下, 裸 CR 或裸 LF 被不正确地用来代替 CRLF 表示行分隔符. 在其他情况下, 裸 CR 和裸 LF 只是作为具有其传统 ASCII 含义的 US-ASCII 控制字符使用.

4.2. 过时的折叠空白​

在过时语法中, 凡允许 obs-FWS 规则的位置都可以插入任意数量的折叠空白. 这会产生在一行中出现两个连续"折叠"的可能性, 因而也可能使构成折叠头部字段的某一行完全由空白组成.

obs-FWS         =   1*WSP *(CRLF 1*WSP)

4.3. 过时的日期与时间​

过时日期格式的语法允许在 date 字段中使用两位数的年份, 并允许使用早期版本本规范中使用过的字母时区说明符列表. 它还允许在许多记号之间出现注释和折叠空白.

obs-day-of-week =   [CFWS] day-name [CFWS]

obs-day = [CFWS] 1*2DIGIT [CFWS]

obs-year = [CFWS] 2*DIGIT [CFWS]

obs-hour = [CFWS] 2DIGIT [CFWS]

obs-minute = [CFWS] 2DIGIT [CFWS]

obs-second = [CFWS] 2DIGIT [CFWS]

obs-zone = "UT" / "GMT" / ; Universal Time
; North American UT
; offsets
"EST" / "EDT" / ; Eastern: - 5/ - 4
"CST" / "CDT" / ; Central: - 6/ - 5
"MST" / "MDT" / ; Mountain: - 7/ - 6
"PST" / "PDT" / ; Pacific: - 8/ - 7
;
%d65-73 / ; Military zones - "A"
%d75-90 / ; through "I" and "K"
%d97-105 / ; through "Z", both
%d107-122 ; upper and lower case

当日期中出现两位或三位年份时, 年份按如下方式解释: 如果遇到的两位数年份取值在 00 到 49 之间, 则该年份加上 2000 来解释, 得到 2000 到 2049 之间的值. 如果遇到的两位数年份取值在 50 到 99 之间, 或者遇到任何三位数年份, 则该年份加上 1900 来解释.

在过时时区中, "UT" 和 "GMT" 分别表示 "Universal Time" 和 "Greenwich Mean Time", 二者在语义上都等同于 "+0000".

其余三字符时区是美国时区. 第一个字母 "E"、"C"、"M" 或 "P" 分别代表 "Eastern"、"Central"、"Mountain" 和 "Pacific". 第二个字母是 "S", 表示 "Standard" (标准) 时间, 或 "D", 表示 "Daylight Savings" (夏令) 时间. 它们的解释如下:

EDT 在语义上等价于 -0400 EST 在语义上等价于 -0500 CDT 在语义上等价于 -0500 CST 在语义上等价于 -0600 MDT 在语义上等价于 -0600 MST 在语义上等价于 -0700 PDT 在语义上等价于 -0700 PST 在语义上等价于 -0800

单字符军事时区在 [RFC0822] 中以非标准方式定义, 因此其含义不可预测. 军事时区 "A" 到 "I" 的原始定义分别等价于 "+0100" 到 "+0900"; "K"、"L" 和 "M" 分别等价于 "+1000"、"+"1100" 和 "+1200"; "N" 到 "Y" 分别等价于 "-0100" 到 "-1200"; 而 "Z" 等价于 "+0000". 然而, 由于 [RFC0822] 中的错误, 除非有带外信息确认其含义, 否则它们都应当被视为等价于 "-0000".

其他多字符 (通常在 3 到 5 个字符之间) 字母时区曾在互联网消息中使用. 任何此类含义未知的时区, 除非有带外信息确认其含义, 否则都应当被视为等价于 "-0000".

4.4. 过时的寻址​

寻址有四个主要差异. 第一, 当邮箱地址括在 "<" 和 ">" 中时, 允许在 addr-spec 之前有一个 route 部分. route 只是由域名组成的逗号分隔列表, 每个域名前面加 "@", 列表以冒号结尾. 第二, 允许在 local-part 和 domain 的句点分隔元素之间出现 CFWS (即不使用 dot-atom). 此外, local-part 除了允许 atom 之外还允许包含 quoted-string. 第三, mailbox-list 和 address-list 允许有"空"成员. 也就是说, 这样的列表中可以出现两个或更多逗号而其间没有任何内容, 或者逗号出现在列表的开头或结尾. 最后, domain literal 中曾允许 US-ASCII 控制字符和 quoted-pair, 此处把它们加入.

obs-angle-addr  =   [CFWS] "<" obs-route addr-spec ">" [CFWS]

obs-route = obs-domain-list ":"

obs-domain-list = *(CFWS / ",") "@" domain
*("," [CFWS] ["@" domain])

obs-mbox-list = *([CFWS] ",") mailbox *("," [mailbox / CFWS])

obs-addr-list = *([CFWS] ",") address *("," [address / CFWS])

obs-group-list = 1*([CFWS] ",") [CFWS]

obs-local-part = word *("." word)

obs-domain = atom *("." atom)

obs-dtext = obs-NO-WS-CTL / quoted-pair

解释地址时, 应当忽略 route 部分.

4.5. 过时的头部字段​

从句法上看, 过时字段语法的主要差异在于它允许任何字段出现多次, 且它们可以以任意顺序出现. 此外, 字段名末尾的 ":" 之前允许有任意数量的空白.

obs-fields      =   *(obs-return /
obs-received /
obs-orig-date /
obs-from /
obs-sender /
obs-reply-to /
obs-to /
obs-cc /
obs-bcc /
obs-message-id /
obs-in-reply-to /
obs-references /
obs-subject /
obs-comments /
obs-keywords /
obs-resent-date /
obs-resent-from /
obs-resent-send /
obs-resent-rply /
obs-resent-to /
obs-resent-cc /
obs-resent-bcc /
obs-resent-mid /
obs-optional)

除目标地址字段 (第 4.5.3 节所述) 之外, 字段多次出现时的解释没有规定. 此外, 未出现在前置到消息的块中的跟踪字段和重发字段, 其解释也没有规定. 除以下各节另有说明外, 其他字段的解释与第 3 节中其非过时对应字段的解释完全相同.

4.5.1. 过时的创建日期字段​

obs-orig-date   =   "Date" *WSP ":" date-time CRLF

4.5.2. 过时的发起者字段​

obs-from        =   "From" *WSP ":" mailbox-list CRLF

obs-sender = "Sender" *WSP ":" mailbox CRLF

obs-reply-to = "Reply-To" *WSP ":" address-list CRLF

4.5.3. 过时的目标地址字段​

obs-to          =   "To" *WSP ":" address-list CRLF

obs-cc = "Cc" *WSP ":" address-list CRLF

obs-bcc = "Bcc" *WSP ":"
(address-list / (*([CFWS] ",") [CFWS])) CRLF

当消息中出现多个目标地址字段时, 应当把它们视为: 第一个出现的字段中的地址列表与后续出现的字段的地址列表通过添加逗号并连接而合并.

4.5.4. 过时的标识字段​

过时的 "In-Reply-To:" 和 "References:" 字段与当前语法的差异在于它们允许出现 phrase (词或带引号字符串). 过时形式的 msg-id 左右两侧允许散布 CFWS, 使其在语法上分别与 local-part 和 domain 相同.

obs-message-id  =   "Message-ID" *WSP ":" msg-id CRLF

obs-in-reply-to = "In-Reply-To" *WSP ":" *(phrase / msg-id) CRLF

obs-references = "References" *WSP ":" *(phrase / msg-id) CRLF

obs-id-left = local-part

obs-id-right = domain

为解释起见, "In-Reply-To:" 和 "References:" 字段中的短语被忽略.

从语义上看, local-part 和 domain 中的可选 CFWS 都不属于 obs-id-left 和 obs-id-right.

4.5.5. 过时的信息性字段​

obs-subject     =   "Subject" *WSP ":" unstructured CRLF

obs-comments = "Comments" *WSP ":" unstructured CRLF

obs-keywords = "Keywords" *WSP ":" obs-phrase-list CRLF

4.5.6. 过时的重发字段​

过时语法增加了一个 "Resent-Reply-To:" 字段, 它由字段名、可选的注释和折叠空白、冒号以及逗号分隔的地址列表组成.

obs-resent-from =   "Resent-From" *WSP ":" mailbox-list CRLF

obs-resent-send = "Resent-Sender" *WSP ":" mailbox CRLF

obs-resent-date = "Resent-Date" *WSP ":" date-time CRLF

obs-resent-to = "Resent-To" *WSP ":" address-list CRLF

obs-resent-cc = "Resent-Cc" *WSP ":" address-list CRLF

obs-resent-bcc = "Resent-Bcc" *WSP ":"
(address-list / (*([CFWS] ",") [CFWS])) CRLF

obs-resent-mid = "Resent-Message-ID" *WSP ":" msg-id CRLF

obs-resent-rply = "Resent-Reply-To" *WSP ":" address-list CRLF

与其他重发字段一样, "Resent-Reply-To:" 字段只应被当作跟踪信息处理.

4.5.7. 过时的跟踪字段​

obs-return 和 obs-received 在此处同样作为模板定义给出, 正如第 3 节中的 return 和 received 一样. 它们的完整语法在 [RFC5321] 中给出.

obs-return      =   "Return-Path" *WSP ":" path CRLF

obs-received = "Received" *WSP ":" *received-token CRLF

4.5.8. 过时的可选字段​

obs-optional    =   field-name *WSP ":" unstructured CRLF