4. Data Formats (数据格式)
IMAP4rev1 使用文本命令和响应. IMAP4rev1 中的数据可以采用几种形式之一: 原子 (Atom), 数字 (Number), 字符串 (String), 括号列表 (Parenthesized List) 或 NIL. 请注意, 特定数据项可能采用多种形式, 例如, 定义为使用 "astring" 语法的数据项可以是原子或字符串.
4.1. Atom (原子)
原子由一个或多个非特殊字符组成.
示例:
OK
INBOX
CAPABILITY
4.2. Number (数字)
数字由一个或多个数字字符组成, 表示数值.
示例:
1
42
1234
4.3. String (字符串)
字符串有两种形式之一: 字面量 (Literal) 或引号字符串 (Quoted String). 字面量形式是字符串的一般形式. 引号字符串形式是一种替代方案, 它避免了处理字面量的开销, 代价是限制了可以使用的字符.
字面量 (Literal)
字面量是零个或多个八位字节 (包括 CR 和 LF) 的序列, 前缀引用八位字节计数, 形式为左大括号 ({), 八位字节数, 右大括号 (}), 和 CRLF.
- 服务器到客户端: CRLF 后紧跟八位字节数据
- 客户端到服务器: 客户端必须 (MUST) 等待接收命令继续请求 (Command Continuation Request, 本文档后面描述) 后再发送八位字节数据 (和命令的其余部分)
示例:
{12}
Hello World!
{0}
(空字面量)
引号字符串 (Quoted String)
引号字符串是零个或多个 7 位字符的序列, 不包括 CR 和 LF, 每端都有双引号 (") 字符.
示例:
"Hello"
"INBOX"
"[email protected]"
空字符串
空字符串表示为:
""(双引号之间没有字符的引号字符串){0}后跟 CRLF (八位字节计数为 0 的字面量)
注意: 即使八位字节计数为 0, 传输字面量的客户端也必须 (MUST) 等待接收命令继续请求.
4.3.1. 8-bit and Binary Strings (8位和二进制字符串)
通过使用 [MIME-IMB] 内容传输编码支持 8 位文本和二进制邮件. IMAP4rev1 实现可以 (MAY) 在字面量中传输 8 位或多八位字节字符, 但应该 (SHOULD) 仅在识别 [CHARSET] 时才这样做.
虽然定义了 BINARY 正文编码, 但不允许未编码的二进制字符串. "二进制字符串" 是任何带有 NUL 字符的字符串. 实现必须 (MUST) 在传输数据之前将二进制数据编码为文本形式, 例如 BASE64. 具有过多 CTL 字符的字符串也可以 (MAY) 被视为二进制.
4.4. Parenthesized List (括号列表)
数据结构表示为 "括号列表", 一系列由空格分隔的数据项, 并在每端由括号括起来. 括号列表可以包含其他括号列表, 使用多级括号表示嵌套.
示例:
(FLAGS (\Seen \Answered))
(1 2 3 4 5)
(BODY ("TEXT" "PLAIN" ("CHARSET" "US-ASCII") NIL NIL "7BIT" 1152 23))
空列表表示为 () - 没有成员的括号列表.
4.5. NIL
特殊形式 "NIL" 表示特定数据项 (表示为字符串或括号列表) 的不存在, 与空字符串 "" 或空括号列表 () 不同.
注意: NIL 从不用于采用原子形式的任何数据项. 例如, 邮箱名称 "NIL" 是名为 NIL 的邮箱, 而不是不存在的邮箱名称. 这是因为邮箱使用 "astring" 语法, 它是原子或字符串. 相反, addr-name 为 NIL 是不存在的个人姓名, 因为 addr-name 使用 "nstring" 语法, 它是 NIL 或字符串, 但从不是原子.
数据格式对比表
| 格式 | 定义 | 示例 | 用途 |
|---|---|---|---|
| Atom (原子) | 非特殊字符序列 | INBOX, OK, FLAGS | 命令名, 关键字, 简单标识符 |
| Number (数字) | 数字字符序列 | 1, 42, 1234 | 消息序列号, 计数, UID |
| Quoted String (引号字符串) | 双引号包围的字符 | "Hello", "[email protected]" | 简单文本, 邮箱名称 |
| Literal (字面量) | {n}CRLF + n个八位字节 | {12}CRLF + Hello World! | 包含特殊字符的文本, 二进制数据 |
| Parenthesized List (括号列表) | 括号包围的项列表 | (1 2 3), (FLAGS (\Seen)) | 复杂数据结构, 嵌套信息 |
| NIL | 特殊值表示不存在 | NIL | 表示缺少的可选字段 |
字符串格式选择指南
使用引号字符串的情况:
- ✅ 简单 ASCII 文本
- ✅ 不包含双引号, CR, LF 的字符串
- ✅ 短字符串 (性能考虑)
使用字面量的情况:
- ✅ 包含双引号, CR, LF 的字符串
- ✅ 8位或多字节字符
- ✅ 二进制数据 (BASE64 编码后)
- ✅ 大量文本
实际示例
示例 1: FETCH 响应中的数据格式
* 1 FETCH (
FLAGS (\Seen) # 括号列表
UID 4827313 # 数字
INTERNALDATE "17-Jul-1996 02:44:25 -0700" # 引号字符串
RFC822.SIZE 4286 # 数字
BODY[HEADER.FIELDS (FROM)] {21} # 字面量
From: [email protected] # 字面量内容
)
示例 2: LIST 响应
* LIST (\Noselect) "/" ~/Mail/foo # 原子: \Noselect, 引号字符串: "/"
* LIST () NIL INBOX # 空列表: (), NIL, 原子: INBOX
示例 3: SEARCH 响应
* SEARCH 1 2 3 4 5 # 所有都是数字
* SEARCH # 没有匹配 (空结果)
术语表 (本章重点术语):
- Atom (原子): 不包含特殊字符的简单字符序列
- Number (数字): 数值的文本表示
- String (字符串): 文本数据, 可以是引号字符串或字面量
- Literal (字面量): 带前缀长度的字符串, 支持任意八位字节
- Quoted String (引号字符串): 双引号包围的 7 位字符串
- Parenthesized List (括号列表): 括号包围的数据项列表
- NIL: 表示数据项不存在的特殊值
- astring: 可以是原子或字符串的语法类型
- nstring: 可以是 NIL 或字符串的语法类型