namesapce
NAMESPACE
命令的作用是在 IMAP 会话中让客户端查询服务器上可用的邮箱命名空间(namespace),并获取每个命名空间对应的名称前缀(prefix)和层级分隔符(hierarchy delimiter)。具体来说,它告诉客户端:
个人命名空间(Personal Namespace) 客户自己的邮箱都放在哪个前缀下,以及如何把层级结构(比如
INBOX/子文件夹
)拆分和拼接。例如常见的"" "/"
就表示根前缀为空,层级分隔符是斜杠。其他用户命名空间(Other Users’ Namespace) 如果服务器支持访问别人的邮箱,就会在这里列出诸如
"#user/" "/"
这样的前缀,客户端就知道要在该前缀下查找其他用户邮箱。共享命名空间(Shared Namespace) 用于展示 server-wide 的共享邮箱或者公共邮箱集合,前缀和分隔符同样由这里提供。
客户端在收到这些信息后,就能正确地:
- 枚举所有邮件箱(LIST/LSUB)
- 构造或解析带层级的邮箱名
- 支持 “切换到别人的邮箱” 或 “访问共享文件夹” 等功能
如果服务器不实现 NAMESPACE
,客户端往往只能假设一套规则(比如把所有东西都当在根目录),会导致对一些自定义或多用户场景下的命名空间支持不完整,甚至像 Gmail 那样直接崩溃。
我的imap返回这个,gmail 崩溃了,怎么办 2025-07-01 08:16:49.312 [t-io-2] INFO c.t.m.w.h.ImapServerAioHandler.handler:59 - <<< 1 CAPABILITY 2025-07-01 08:16:49.313 [t-io-2] INFO c.t.m.w.h.ImapServerAioHandler.handler:158 - * CAPABILITY IMAP4rev1 AUTH=LOGIN AUTH=PLAIN IDLE UIDPLUS ID LITERAL+ MOVE 1 OK CAPABILITY
Gmail 在建立 IMAP 连接时,会立刻发起一次 NAMESPACE
请求来探测服务器支持的命名空间,如果服务器既不宣告也不实现这个命令,客户端就会直接崩溃。
解决方案
在 CAPABILITY 中加入
NAMESPACE
* CAPABILITY IMAP4rev1 AUTH=LOGIN AUTH=PLAIN IDLE UIDPLUS ID LITERAL+ MOVE NAMESPACE 1 OK CAPABILITY
实现对
NAMESPACE
命令的响应 在你的ImapServerAioHandler
(或相应的命令分发部分)里,增加:if ("NAMESPACE".equalsIgnoreCase(command)) { // 返回一个“空前缀、‘/’分隔符”的默认命名空间 ctx.write("* NAMESPACE ((\"\" \"/\")) NIL NIL\r\n"); ctx.write(tag + " OK NAMESPACE completed\r\n"); return; }
这样,当 Gmail 发送:
a001 NAMESPACE
你的服务器就会正确返回:
* NAMESPACE (("" "/")) NIL NIL a001 OK NAMESPACE completed
完成以上两步后,Gmail 客户端就不会因为收不到 NAMESPACE
而崩溃了。
Tip: 如果你还想让 Gmail 能识别 “所有邮件”/“已删除邮件” 等特殊文件夹,可以再实现 SPECIAL-USE 扩展(比如返回
\All
,\Trash
等),或实现它的旧版XLIST
扩展,但这不是崩溃的根本原因。