IMAP 是有状态的邮件访问协议。RFC 9051 定义了 IMAP4rev2;它取代了 RFC 3501 中的 IMAP4rev1。客户端管理服务器上的邮箱和邮件状态,从而允许多个客户端查看同一个邮箱。
连接和命令 #
IMAP 是通过 TCP 传输的文本协议。端口 143 以明文开始,并可使用 STARTTLS 协商 TLS;
端口 993 从建立连接时起就使用 TLS。客户端必须获取能力,先于密码身份验证协商 TLS,
并要求验证证书和主机名。
协议状态限制了合法命令:
- 在未身份验证状态下,客户端协商能力、TLS 和身份验证。
- 在已身份验证状态下,客户端可以管理和列出邮箱。
- 在已选择状态下,客户端已选择一个邮箱,可以获取或更改邮件状态。
LOGOUT进入注销状态;服务器发送未标记的BYE和标记的完成响应后,会话关闭。
每个客户端命令都以客户端选择的标签开头。服务器响应可以是未标记响应(*)、继续请求(+)或标记的完成响应:
S: * OK IMAP4rev2 ready
C: A001 CAPABILITY
S: * CAPABILITY IMAP4rev2 STARTTLS SASL-IR
S: A001 OK completed
C: A002 STARTTLS
S: A002 OK begin TLS negotiation nowTLS 建立后,客户端再次发送 CAPABILITY,因为能力可能不同。当服务器和客户端支持
SASL 身份验证机制时,应使用它们,而不是使用 LOGIN。
邮箱和邮件 #
已身份验证的连接可以列出、创建、重命名、订阅和选择邮箱。SELECT 以读写方式打开邮箱;
EXAMINE 以只读方式打开。邮件具有会随邮箱变化的序列号,并在一个 UIDVALIDITY
周期内具有稳定的唯一标识符(UID)。持久化客户端必须使用 UID,记录 UIDVALIDITY,
并在其变化时重新同步。
邮箱名称是协议字符串,而不是操作系统路径。使用 LIST 发现层级分隔符和名称,保留
服务器提供的 UTF-8 名称,并在需要时将它们加引号或作为字面量发送。INBOX 不区分大小写;
其他名称是否区分大小写取决于服务器规则。
系统标志包括 \Seen、\Answered、\Flagged、\Deleted 和 \Draft。客户端使用
STORE 将邮件标记为已删除;EXPUNGE 会移除标记为 \Deleted 的邮件。对于可能接收
并发邮箱更新的工作流,应避免使用序列号。
FETCH 获取邮件属性或正文部分。SEARCH 返回匹配的邮件。IMAP 字面量承载不能安全地
出现在带引号字符串中的数据;服务器可以在客户端发送同步字面量前请求继续。诸如
{4096}\r\n 的字面量标记声明后续的确切八位字节数。解析器必须消耗该长度,而不能扫描
字面量内容来查找换行符。
空闲和同步 #
IDLE 允许客户端在保持连接的同时接收未经请求的邮箱变更。客户端必须先用 DONE
终止 IDLE,才能发送另一个命令。基于 UID 的同步、UID FETCH 和服务器能力检查可以
避免将邮箱快照视为永久稳定。
选择邮箱期间,未标记的 EXISTS、EXPUNGE、FETCH 和相关响应会报告变更。清除一封
邮件会重新编号后续序列号,因此客户端必须立即更新序列号映射,并继续使用 UID 标识持久
状态。存储最后已知的 UID、标志、UIDVALIDITY 和相关修改状态;当双方都公布支持时,
CONDSTORE 和 QRESYNC 等扩展可以减少传输,但回退方案必须执行正确的基于 UID 的重新扫描。
IMAP 传输邮件字节和元数据;MIME 定义邮件正文结构和传输编码。不要将 IMAP 的面向行的 命令编码与七位打包方案混淆:IMAP 命令行使用 ASCII 语法,而字面量传输八位字节。
评论
在 GitHub 上阅读或评论(发表评论需要登录)