Skip to main content

4. 数据格式 (Data Formats)

IMAP4rev2 使用文本命令和响应. IMAP4rev2 中的数据可以采用以下几种形式之一:原子 (Atom)、数字 (Number)、字符串 (String)、括号列表 (Parenthesized List) 或 NIL. 请注意,特定数据项可能采用多种形式,例如,定义为使用 "astring" 语法的数据项可以是原子或字符串.

4.1 原子 (Atom)

原子 (Atom) 由一个或多个非特殊字符组成.

4.1.1 序列集和 UID 集 (Sequence Set and UID Set)

可以通过包含消息序列号或唯一标识符的序列集 (Sequence Set) 来引用一组消息. 详细信息请参见第 9 节. 序列集可以包含序列号范围 (例如 "5:50")、特定序列号的枚举,或上述的组合. 序列集可以使用特殊符号 "*" 来表示邮箱中的最大序列号. 序列集从不包含唯一标识符.

"UID 集" (UID Set) 与序列集类似,但使用唯一标识符而不是消息序列号,并且不允许包含特殊符号 "*".

4.2 数字 (Number)

数字 (Number) 由一个或多个数字字符组成,表示一个数值.

4.3 字符串 (String)

字符串 (String) 有三种形式之一:同步字面量 (Synchronizing Literal)、非同步字面量 (Non-synchronizing Literal) 或引用字符串 (Quoted String). 同步字面量形式是字符串的通用形式,对字符串可以包含的字符没有限制. 非同步字面量形式也是通用形式,但它有长度限制. 引用字符串形式是一种替代方案,避免了处理字面量的开销,但对可以使用的字符有限制.

当同步字面量和非同步字面量之间的区别不重要时,本文档仅使用术语 "字面量" (Literal).

同步字面量 (Synchronizing Literal) 是零个或多个八位字节的序列 (包括 CR 和 LF),以八位字节计数作为前缀引用,形式为左大括号 (")、八位字节数、右大括号 (") 和 CRLF. 对于从服务器传输到客户端的同步字面量,CRLF 后立即跟随八位字节数据. 对于从客户端传输到服务器的同步字面量,客户端必须 (MUST) 等待接收命令继续请求 (Command Continuation Request) (本文档稍后描述) 后再发送八位字节数据 (和命令的其余部分).

非同步字面量 (Non-synchronizing Literal) 是同步字面量的替代形式,可以在客户端到服务器的任何允许同步字面量的地方使用. 非同步字面量形式不得 (MUST NOT) 从服务器发送到客户端. 非同步字面量与同步字面量的区别在于在八位字节计数和右大括号 ("}") 之间有一个加号 ("+"). 服务器不会响应非同步字面量生成命令继续请求,并且客户端不需要在发送非同步字面量的八位字节之前等待. 除非在 IMAP 扩展中另有说明,否则非同步字面量不得 (MUST NOT) 大于 4096 个八位字节. 任何大于 4096 字节的字面量必须 (MUST) 作为同步字面量发送. (本文档中定义的非同步字面量与 [RFC7888] 中 LITERAL- 扩展定义的非同步字面量相同. 有关如何处理长于 4096 个八位字节的无效非同步字面量以及与其他 IMAP 扩展的交互,请参见该文档.)

引用字符串 (Quoted String) 是零个或多个 Unicode 字符的序列,不包括 CR 和 LF,以 UTF-8 编码,每端都有双引号 (<">) 字符.

空字符串表示为 "" (双引号之间有零个字符的引用字符串)、{0} 后跟 CRLF (八位字节计数为 0 的同步字面量),或 {0+} 后跟 CRLF (八位字节计数为 0 的非同步字面量).

注意:即使八位字节计数为 0,传输同步字面量的客户端也必须 (MUST) 等待接收命令继续请求.

4.3.1 8 位和二进制字符串 (8-Bit and Binary Strings)

通过使用 [MIME-IMB] 内容传输编码来支持 8 位文本和二进制邮件. IMAP4rev2 实现可以 (MAY) 在字面量中传输 8 位或多八位字节字符,但应该 (SHOULD) 仅在标识 [CHARSET] 时才这样做.

IMAP4rev2 与 [I18N-HDRS] 兼容. 因此,具有 8 位内容的标头字段值的标识字符集是 UTF-8 [UTF-8]. IMAP4rev2 实现必须 (MUST) 接受并可以 (MAY) 在引用字符串中传输 [UTF-8] 文本,只要字符串不包含 NUL、CR 或 LF. 这与 IMAP4rev1 实现不同.

虽然定义了 BINARY 内容传输编码,但不允许未编码的二进制字符串,除非在响应 BINARY.PEEK[<section-binary>]<partial>BINARY[<section-binary>]<partial> FETCH 数据项时在 <literal8> 中返回. "二进制字符串" (Binary String) 是任何包含 NUL 字符的字符串. 具有过多 CTL 字符的字符串也可以 (MAY) 被视为二进制. 除非在响应 BINARY.PEEK[...]/BINARY[...] FETCH 时返回,否则客户端和服务器实现必须 (MUST) 在传输数据之前将二进制数据编码为文本形式,例如 base64.

4.4 括号列表 (Parenthesized List)

数据结构表示为"括号列表" (Parenthesized List),即由空格分隔并在每端由括号界定的数据项序列. 括号列表可以包含其他括号列表,使用多级括号来表示嵌套.

空列表表示为 () -- 一个没有成员的括号列表.

4.5 NIL

特殊形式 "NIL" 表示表示为字符串或括号列表的特定数据项的不存在,与空字符串 "" 或空括号列表 () 不同.

注意:NIL 从不用于任何采用原子形式的数据项. 例如,邮箱名称 "NIL" 是名为 NIL 的邮箱,而不是不存在的邮箱名称. 这是因为邮箱使用 "astring" 语法,它是原子或字符串. 相反,NIL 的 addr-name 是不存在的个人姓名,因为 addr-name 使用 "nstring" 语法,它是 NIL 或字符串,但从不是原子.

示例

以下 LIST 响应:

* LIST () "/" NIL

等同于:

* LIST () "/" "NIL"

因为 LIST 响应 ABNF 对邮箱名称使用 "astring".

但是,以下响应:

* FETCH 1 (BODY[1] NIL)

不等同于:

* FETCH 1 (BODY[1] "NIL")

前者表示不存在正文部分,而后者表示它包含一个包含三个字符 "NIL" 的字符串.