关于 mail-mcp
mail-mcp 是用 Rust 编写的邮件 MCP 服务,面向需要让 AI Agent 读取、搜索和处理邮件的用户。它支持 IMAP、SMTP、EWS 和 Microsoft Graph,并提供 OAuth2 与多账户配置。
主要功能
- 01读取、搜索、发送和转发邮件
- 02支持 IMAP、SMTP、EWS 和 Graph
- 03支持 OAuth2 与多账户
- 04创建、修改和发送草稿
- 05提供跨邮箱与邮件线程搜索
适用场景
- 01搜索邮件并获取完整对话
- 02草拟邮件供人工审核后发送
- 03通过不同邮件后端管理多个账户
MCP 相关
该 MCP 服务向 AI Agent 提供邮件读取、搜索、发送及草稿管理工具。默认使用 stdio,也可选择无状态的 Streamable HTTP 传输。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
我们还没有获取到这个服务的安装包或远程地址,请按项目 README 中的说明安装。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
mail-mcp
面向 AI Agent 的生产就绪型邮件 MCP 服务
IMAP + SMTP + EWS + Microsoft Graph API — 使用 Rust 构建
大多数邮件 MCP 服务只能通过 IMAP 读取邮件。这个服务则能处理所有操作:读取、搜索、发送、回复、转发、批量操作、Microsoft Graph API 和 Exchange Web Services,并支持真正的 OAuth2、多账户和多服务提供商。使用 Rust 编写,快速且安全。
v0.6.1 版新增内容
RUST_LOG=info时,邮件内容不会写入日志。 在该 日志级别下,rmcp 库会完整记录每个 JSON-RPC 响应;使用 HTTP 传输时, 邮件主题和正文会写入服务端日志(对于 systemd 服务,即写入 journal)。当RUST_LOG设置为全局级别info或更详细时,rmcp 现在会被限制在warn,除非RUST_LOG明确指定了它(例如,调试时设置RUST_LOG=info,rmcp=info)。stdio 传输不会记录响应;如果未设置RUST_LOG,则行为不变。如果你通过 HTTP 运行 v0.6.0 或更早版本,请设置RUST_LOG=info,rmcp=warn。- 修正 EWS 设置的作用域。 Microsoft 现在会因
AADSTS70011(invalid_scope)错误拒绝https://outlook.office365.com/EWS.AccessAsUser.All。快速入门现改用https://outlook.office.com/EWS.AccessAsUser.All。现有 EWS 令牌仍可 使用;只有获取新令牌时才会受到影响。
v0.6.0 版新增内容
除非选择启用,否则现有安装不会发生变化。
- 为 Shell 和 PowerShell 安装方式提供自更新功能。 安装程序现在还会
安装
mail-mcp-update;运行它即可原地更新到最新发行版。Homebrew 安装仍通过brew upgrade更新。 - 使用轮换后的 OAuth2 刷新令牌,并可将其持久化。 Microsoft
每次刷新时都会返回新的刷新令牌;此前服务会丢弃该令牌,并一直使用配置的
令牌进行刷新,直到配置的令牌过期。现在服务会使用最新的令牌进行刷新。将
MAIL_OAUTH2_TOKEN_STORE设置为文件路径,即可在重启后保留该令牌 (文件权限设为0600;即使无法写入也不会导致操作失败)。配置中更改的 刷新令牌始终优先于已存储的令牌。 - 工具和字段描述中加入发送规则。 预览并确认规则以及“
body_text和body_html是独立字段”规则,现在也会显示在发送工具和正文 字段的描述中,供不会转发服务指令的 MCP 网关使用。有关 mail-mcp 位于网关 后方时还会发生哪些变化,请参阅 在 MCP 网关后方运行。
v0.5.0 版本新增内容
- 新增:草稿工具(
draft_create、draft_update、draft_send、draft_delete、draft_list),解决了 #3 和 #17。Agent 可以 将邮件保存到账号自己的“草稿”文件夹中,修改后再发送,让用户可以先在邮件客户端中 审阅。所有后端均支持这五种工具:IMAP + SMTP、Exchange Web Services 和 Microsoft Graph;每个账号会按顺序选择后端(EWS 配置、否则 Graph 配置、否则 IMAP)。list_all_accounts会通过drafts_with报告后端。 - 独立开关:
MAIL_DRAFTS_ENABLED(默认值为false)。它与MAIL_IMAP_WRITE_ENABLED相互独立:对已有draft_id执行任何操作前,都会先 检查目标确实是草稿(IMAP“草稿”文件夹、EWSIsDraft、GraphisDraft),因此 启用草稿功能不会授予对其他邮件的移动或删除权限。draft_send还需要MAIL_SMTP_WRITE_ENABLED。 - Graph 账号需要
Mail.ReadWrite范围才能操作草稿;请参阅 账号设置。EWS 附件流程(先使用SaveOnly执行CreateItem,再执行CreateAttachment)采用了 @verdelyi 在 #14 中提出的方法。 - 修复:SMTP 邮件现在会携带发件人域名下的 Message-ID (#7)。此前,lettre 不会自行生成 Message-ID,因此发送工具返回的 ID 为空,已发送邮件副本也没有 Message-ID。
- 已在 IMAP(Zoho)和 Microsoft Graph 上进行实时验证;EWS 草稿流程由单元测试覆盖。
v0.4.17 版本新增内容
- 新增:
imap_search_all_mailboxes,由 @tdabasinskas 在 #35 中贡献。它会在账号中 所有可选邮箱内执行一次搜索,并返回最新的匹配项,每项都标注其邮箱。此工具适用于 没有“All Mail”文件夹的服务提供商(如 iCloud);这类服务中,同一会话会分散在 INBOX、Sent Messages 和项目文件夹中。搜索任务会分配给MAIL_IMAP_SEARCH_CONCURRENCY个连接(默认值为4,限制在1..=8);某个邮箱 搜索失败时会报告错误,但不会中止搜索。可通过include_mailboxes/exclude_mailboxes限定范围。 - 按 Message-ID 搜索会话,由
@tdabasinskas 在
#34 中贡献。
imap_search_messages新增了thread_message_id条件,可匹配指定邮件,以及In-Reply-To或References中包含该 ID 的所有邮件,让 Agent 能通过一次搜索 获取整个会话。
v0.4.16 版本新增内容
imap_list_mailboxes的上限现在可配置且会在结果中显示,由 @tdabasinskas 在 #33 中贡献。此前,该工具会 静默省略超过 200 个的邮箱;对于文件夹较多的账号(例如 iCloud 上有 217 个文件夹),Sent Messages等文件夹就不会显示。现在可通过MAIL_IMAP_MAX_MAILBOXES设置 上限(默认值为200,限制在1..=10000),响应还会增加total和truncated两个字段,让客户端始终能判断列表是否被截断。除非设置该变量,否则行为 不变。
v0.4.15 新功能
- 新增:可选的流式 HTTP 传输,由
@tdabasinskas 在
#32 中贡献。设置
MAIL_MCP_TRANSPORT=http,即可使用 MCP 流式 HTTP(无状态)而非 stdio 提供服务;适合在另一台机器上通过 MCP 网关运行服务。默认绑定到127.0.0.1:8000的/mcp路径,可通过MAIL_MCP_HTTP_HOST/MAIL_MCP_HTTP_PORT/MAIL_MCP_HTTP_PATH配置,并在收到 SIGINT/SIGTERM 时优雅关闭。此端点没有内置身份验证——请将其限制在回环地址上,或置于经过身份验证的网关后;请参阅docs/advanced-configuration.md#remote-http-transport。stdio 仍为默认方式:除非设置此变量,否则不会有任何变化。
v0.4.14 新功能
社区版本——这两项改动均来自外部贡献者。感谢大家!
- 新增:
MAIL_ATTACHMENT_UPLOAD_DIR——限制外发附件的file_path范围,由 @mjones-PL 在 #31 中贡献,解决了 #11 的问题。如果不加限制,发送工具会读取服务进程可访问的任意文件——受到提示词注入的模型可能会将 SSH 密钥或.env文件作为附件外传。将此变量设为某个目录后,每个file_path都会被规范化(解析..和符号链接),且必须指向该目录范围内;对于不存在的文件和超出范围的文件,都会返回相同错误,因此无法通过此检查探测文件是否存在。此功能为可选:未设置时,行为不变。请参阅docs/security.md#outbound-attachment-scope。 - 修复:
FROM_EMAIL验证不再拒绝不含点的内部主机名,由 @arwack 在 #30 中贡献。解决了升级到 v0.4.13 时的注意事项:企业内部中继上的noreply@localhost/alerts@intranet等地址现在重新获准使用,同时仍会检查真正的拼写错误(包含多个@、空白字符、本地部分为空)。如果你因此暂缓升级到 v0.4.13,现在可以放心升级到 v0.4.14。
v0.4.13 新功能
effective_from()辅助函数 +FROM_EMAIL启动验证,由 @arwack 在 #29 中贡献——这是对其 #19 的后续改进。from_email→user回退逻辑现在集中在一处(SmtpAccountConfig::effective_from()),并会在服务启动时验证MAIL_SMTP_<ID>_FROM_EMAIL,而不是等到首次发送时才失败。- 行为变更——升级前请阅读:格式错误的
FROM_EMAIL(包含多个@、空白字符、本地部分为空或域名不含点)现在会阻止服务启动,适用于所有账户。请注意,目前不含点的域名(例如user@localhost或alerts@intranet)也会被拒绝;如果你使用此类内部中继地址,请暂缓升级——目前正在 #29 中讨论后续放宽点号规则的改动。 - 由 @tordable 在 #28 中加强了 APPEND 线格式测试:现在每项 append 测试都会断言邮箱引用格式、声明的字面量长度以及逐字节一致的负载。
v0.4.12 版本更新
社区发布版本 — 两项更改均由社区贡献者提交。感谢大家!
- 支持 iCloud 邮箱别名,读取邮件不再将其标记为已读,由
@felipefdl 在
#16 中提交。现在,短邮箱名会在搜索、复制和移动操作中解析为各服务提供商的真实文件夹(iCloud 上的
Sent→Sent Messages,Gmail 上的Sent→[Gmail]/Sent Mail,Trash→Deleted Messages,以及其他文件夹,支持多语言)。现在,原始邮件提取使用BODY.PEEK[],因此通过 MCP 读取邮件不会再产生设置\Seen标记的副作用 — 若服务端拒绝PEEK,则回退到BODY[](已弃用并在 #23 中移除的RFC822项目不会使用)。作者已在真实 iCloud 邮箱上验证,并新增了别名解析测试和 iCloud 设置文档。 - 优化多阶段 Dockerfile + docker-compose,由
@monssefbaakka 在
#5 中提交。采用 cargo-chef 层缓存、支持 TARGETARCH 的 musl 交叉构建(amd64/arm64),以及
scratch运行时镜像 — 体积为 16.9 MB,低于原来的 25.5 MB — 已验证可通过 stdio 响应 MCP initialize/tools-list。工具链版本固定值已更新为 Rust 1.90(代码库中的 let-chains 要求版本 >= 1.88)。
v0.4.11 版本更新
社区错误修复版本 — 两项修复均由社区贡献者提交。感谢大家!
- 已修复:在严格的 IMAP 服务端(iCloud 等)上,保存到 Sent 会静默失败,由 @dominikknafelj 在
#26 中修复,问题由
#25 报告。v0.4.10 中引入的
\Seen标记未采用 RFC 3501 要求的带括号标记列表语法(发送的是APPEND "Sent" \Seen …,而不是APPEND "Sent" (\Seen) …),因为async-imap会原样插入标记参数。严格的服务端会拒绝 APPEND,导致已发送邮件副本丢失 — 但工具仍会返回status: ok。现在会在发送前规范化标记;smtp_send_message/smtp_reply_message/smtp_forward_message的响应中新增saved_to_sent字段(值为true/false,若禁用保存则为null),以便调用方检测归档失败。 @tordable 同时诊断并修复了相同根本原因,见 #24。 - 已修复:在 iCloud 上读取邮件会返回空内容,由
@tdabasinskas 在
#23 中修复。原始邮件提取使用了已弃用的
RFC822项目,iCloud 虽然接受该项目,却不会填充内容。现在提取使用 IMAP4rev1 的BODY[]项目 —\Seen语义不变,且适用于所有服务端 — 并新增模拟服务端回归测试,以固定线路格式。
v0.4.10 新功能
社区发布版——这三项更改均由外部贡献者提供。感谢大家!
- 兼容网易 IMAP(126.com / 163.com / yeah.net),由
@pep-27 在
#21 中贡献。网易服务
器会拒绝未表明身份的客户端访问邮箱。现在,mail-mcp 会在身份验证后,
只要服务端声明支持
ID功能,就发送 RFC 2971ID命令。包含模拟服务 器回归测试,以及docs/account-setup.md中的网易设置文档。 MAIL_SMTP_<ID>_FROM_EMAIL——覆盖发件人地址,由 @arwack 在 #19 中贡献。适用于共享或群组 邮箱:SMTP 使用个人账户进行身份验证,但 From 地址应为群组地址。此设置适用于发送、 回复(包括“全部回复”时的自身地址检测)和转发;未设置时回退到_USER。- 发件箱副本现在会标记为
\Seen,由 @ray-of-darkness 在 #9 中贡献。SMTP 发送后 MCP 应用追加到“已发送”文件夹的副本不再显示为未读。
v0.4.9 新功能
- 新增工具
imap_get_attachment——将单个附件下载到磁盘。 此前,获取附件字节数据只有两种方式:imap_get_message(返回附件元数据,以及可选提取的 PDF 文本,但不返回二进制数据)和imap_get_message_raw(上限为 1 MB,并以 Base64 编码后放入响应中)。带有 X 光图像的 7 MB 邮件无法获取——它超过了上限,而且将其全部写入响应也会耗尽大模型的 上下文。 - 工作原理:调用
imap_get_attachment,并提供message_id以及一个选择器—— 可以是part_id(imap_get_message为每个附件返回的值),也可以是filename。服务端会获取完整邮件(服务端不设大小上限),只提取并解码指定部分,然后写入磁盘,返回{ file_path, filename, content_type, part_id, size_bytes }。 二进制数据不会进入响应,因此上下文占用很小。保存的路径可直接传给本地读取器(例如图像描述工具或 PDF 阅读器)。 - **文件保存位置:**若提供
output_dir参数,则使用该目录;否则使用MAIL_ATTACHMENT_DOWNLOAD_DIR环境变量指定的目录;再否则使用系统临时目录。 文件名会经过净化处理(仅保留基本文件名,并移除控制字符),以防止路径遍历; 文件名前还会添加邮件 UID 和部分 ID,以避免冲突。 - **可选的内联 Base64:**设置
include_base64: true也可在响应中获取字节数据,但附件大小必须不超过max_inline_bytes(默认 256 KiB)。默认关闭。
v0.4.8 更新内容
SAVE_SENT现在按账户设置,并采用感知提供商的默认值。 以前,通过 IMAP APPEND 将外发邮件副本保存到“已发送”文件夹,由一个全局标志MAIL_SMTP_SAVE_SENT控制。问题在于:已经在服务器端保存已发送邮件的提供商(Gmail、 Zoho)会在“已发送”文件夹中留下两份相同副本;而通用 SMTP 服务器或 Office 365(不会在 SMTP 提交时自动保存邮件)则会在标志为false时完全丢失副本。- 感知提供商的默认值(未配置任何值时):
- Gmail(
smtp.gmail.com):在服务器端保存,并按 Message-ID 去重 → MCP 不会追加(false)。 - Zoho(
smtp.zoho.com):在服务器端保存,但不 去重 → MCP 不会追加(false),以避免重复。 - Office 365 / 通用 SMTP:不会在 SMTP 提交时自动保存 →
MCP 会追加(
true),否则已发送邮件副本会丢失。
- Gmail(
- 按账户覆盖:
MAIL_SMTP_<ID>_SAVE_SENT=true|false的 优先级最高。全局设置MAIL_SMTP_SAVE_SENT仍然有效,可作为 粗粒度覆盖值(优先级高于提供商默认值,低于按账户设置)。 - 优先级:按账户 → 全局 → 感知提供商的默认值。
| 提供商 | 在服务器端自动保存 | MCP 默认值 |
|---|---|---|
| Gmail | 是(会去重) | false |
| Zoho | 是(不去重) | false |
| Office 365(SMTP) | 否 | true |
| 通用 SMTP / 中继 | 否 | true |
v0.4.7 更新内容
- 严重问题修复 —
graph_send_message在带线程的回复中会静默丢弃附件。 使用in_reply_to+attachments调用时,createReply → PATCH → send流程会在针对/me/messages/{id}的 PATCH 请求中包含附件。Microsoft Graph 将Message.attachments视为导航属性,并会在 PATCH 请求中静默丢弃该字段(返回 2xx 响应且不报错),因此发出的邮件会变成没有附件的单部分text/html。MCP 返回status: ok,调用方误以为操作成功。数据就这样无声丢失。 - **修复方法:**在
send_via_reply()中,现在会在 PATCH 和发送之间,逐个将附件上传到POST /me/messages/{draft_id}/attachments。小于 3 MB 的文件会以内嵌方式发送(使用 base64 编码的contentBytes的 JSON);大于或等于 3 MB 的文件则使用createUploadSession,通过分块 PUT 上传,每块 4 MB。从PatchDraftRequest结构体中移除了attachments字段,避免通过类型检查无误的编辑再次引入该回归问题。 - 已正常工作的流程不变。
send_via_sendmail(不带in_reply_to的新邮件)使用POST /me/sendMail,在 JSON 中内嵌attachments— Graph 确实接受此端点上的该字段,也从未丢弃它。该路径未作改动。 - **新增回归测试:**如果有人将该字段重新添加到结构体中,
patch_draft_request_never_serializes_attachments就会失败。 - **参考:**仓库根目录下的
BUG_GRAPH_ATTACHMENTS.md记录了完整的复现步骤、根本原因,以及支撑此修复的实证依据。
v0.4.6 版本更新
- 在服务端强制执行硬性规则 #1。 连续三个版本仅通过提示词进行强化(v0.4.3 → v0.4.4 → v0.4.5),仍无法完全避免大模型偶尔将字面量
</body_text><parameter name="body_html">标记泄漏到收件人的收件箱中。v0.4.6 新增了真正的验证器:如果body_text或body_html包含工具调用包装语法,它会在尝试 SMTP / Graph / EWS 之前拒绝该工具调用。此检查已接入全部 5 个发送路径(smtp_send_message、smtp_reply_message、smtp_forward_message、graph_send_message、ews_send_message)。 - 禁止标记不区分大小写,且范围严格限定为在人类通信中没有正当用途的伪标签:
<body_text>、</body_text>、<body_html>、</body_html>、<function_calls>、</function_calls>、<invoke name=、</invoke>和<parameter name="body_*">。如果一般技术内容恰好在 XML 架构中提及<parameter>,或在代码示例中提及<invoke>,仍会通过检查。 - 更新了硬性规则 #1 的措辞,明确说明服务端会拒绝违规内容,让大模型知道这是必须遵守的硬性约束,而非可以忽略的建议。
- 不会破坏遵循规范的调用方:格式正确的消息发送方式与之前完全相同。
v0.4.5 版本更新
serverInfo现在会报告name="mail-mcp"和 crate 的version(此前框架返回的是自身的rmcp 0.16.0,这个值不会随版本发布而变化)。这有助于通过/mcp验证当前使用的版本,也能让任何按(服务端、版本)建立索引的客户端缓存随每次版本升级而失效。- 重新整理了 MCP 指令:3 条关键的防串接规则(在 v0.4.3 和 v0.4.4 中位于区块末尾,可能因截断或注意力减弱而丢失)现在作为硬性规则 #1、#2、#3 放在最前面,紧接标题之后。内容整合为 3 个简短段落(之前是 3 个较长部分,合计约 1500 个字符)。
- 服务端功能没有变化。 SMTP/IMAP/EWS/Graph、工具集和行为均保持不变。只有向客户端公开的文本发生了变化。
这些规则生效的重要说明
使用 claude --continue(或 /resume)恢复会话的客户端不会刷新 MCP system_prompt,而是继续使用该会话首次握手时获取的内容。如果你的会话早于 v0.4.5,即使磁盘上的二进制文件已更新,这些规则也不会进入当前上下文。如需获取这些规则,请在项目中启动一个新会话(不要使用 --continue)。
v0.4.4 版本更新
-
MCP
instructions中新增了预览规范规则:大模型向用户展示待发送的邮件预览时,应呈现一份整洁的正文版本(使用类似 Markdown 的项目符号、粗体,并将链接显示为文本 + URL),同时说明邮件将以 multipart 格式发送;但不得在预览中倾倒原始 HTML 源码(<p>、<strong>、<a href>……)。原因有两个:- 人类审核者想读的是邮件内容,而不是检查标记;展示 HTML 只会造成干扰。
- 在预览中并排展示纯文本字符串和 HTML 字符串,正是过去导致大模型在最终工具调用中将两者串接起来的上下文(v0.4.3 记录了这个 bug)。在预览中隐藏 HTML 源码,就能避免这种诱因。
这是对 v0.4.3 中引入的预览不等于工具调用规则的补充。
v0.4.3 新增内容
- 服务端指导,防止格式错误的工具调用。 MCP
instructions块现在明确告知调用方大模型:body_text和body_html是两个独立的 JSON 字段,绝不能拼接。 先前的措辞(“同时发送body_text和body_html”)含义不明确,一些大模型将其理解为“在单个body_text字符串中用<body_text>...</body_html>伪标签拼接 两者”。发生这种情况时,收件人看到的内容会混乱且重复;而且之后任何通过此 MCP 打开已保存副本的 Claude 会话都会触发使用政策拦截(泄露的<invoke>...</invoke>在安全过滤器看来像是提示注入尝试)。新指令提供了正确与错误示例,并禁止在邮件字段中使用伪标签/工具调用包装语法。
v0.4.2 新增内容
- 修复发布流水线:已禁用 CI 发布工作流中的
publish-npm作业。该作业继承自上游分支,并尝试发布到@bradsjm/mail-imap-mcp-rs,这是本组织不拥有的作用域,因此每次发布都会在该步骤返回 404。完整说明以及如何在需要时重新启用 npm 发布,请参阅下方的“发布”。 - 推送标签时自动触发发布:
.github/workflows/release.yml现在会在push: tags: ['v*']时运行,因此只需为vX.Y.Z创建标签并推送,即可发布新版本。仍保留workflow_dispatch,作为手动备用方式。 - 清理:移除了无效的
init-npm-placeholder.yml工作流(该工作流也引用了分支的 npm 作用域)。 - 文档:README 新增“发布”部分,说明新的发布流程和 npm 发布决策。
v0.4.1 新增内容
- 修复:
save_to_sent_folder现在会归档实际发送的 RFC822 字节(通过lettre.formatted()获取),而不是手工拼出的纯文本占位内容。已发送文件夹中的副本会保留 HTML 正文、多部分/替代结构以及 RFC 2047 编码的主题——不再把原本的重音字符显示为???,也不会再悄悄丢弃 HTML。 - 改进:本地化的已发送文件夹检测——
Enviado[s]、Elementos enviados、Enviadas、Itens enviados、Envoyés、Éléments envoyés、Gesendet、Posta inviata、Verzonden、Wysłane,以及嵌套变体。 之前只识别英文名称,因此 Zoho/本地化 IMAP 账户会回退到不存在的"Sent"文件夹。 - 改进:
smtp_forward_message现在接受body_html(此前被硬编码为仅支持纯文本)。 - 改进:EWS 发送功能新增
bcc、in_reply_to、references(通过<t:InternetMessageHeaders>),并加入完整的收件人及主题长度验证——现在与 SMTP 和 Graph 发送路径一致。 - 改进:Graph API 线程关联回退现在会记录日志。消息查询 HTTP 调用失败(速率限制、5xx、权限问题)时记录
WARN,让运维人员知道线程关联因实际错误而降级;原始消息确实不存在时记录DEBUG。 - 重构:EWS XML 解析已从子串匹配迁移到
quick-xml。这修复了潜在的命名空间冲突错误(<soap:Body>与<t:Body>),能正确解码 XML 实体和 CDATA,并能处理包含=的属性值(EWS 项目 ID 等类 base64 字符串中常见)。 - 清理:
cargo build --release不再产生警告。 - 测试:64 项(之前为 47 项)。
为什么选择此项目
| mail-mcp | 典型邮件 MCP | |
|---|---|---|
| IMAP 读取/写入 | 18 个工具 | 3-5 个工具 |
| SMTP 发送/回复/转发 | 支持 | 不支持或无法正常工作 |
| Microsoft Graph API | 支持 | 不支持 |
| EWS(Exchange Web Services) | 支持 | 不支持 |
| OAuth2(XOAUTH2) | 原生支持 | 不支持 |
| 多账户 | 支持 | 单账户 |
| Microsoft 365 + Hotmail | 两者均可用 | 通常都不可用 |
| 语言 | Rust(快速、安全) | TypeScript/Python |
| 测试 | 64 项单元测试 + 集成测试 | 仅模拟测试 |
| 发布构建中的警告 | 0 | 不定 |
功能矩阵
| 提供方 | IMAP | SMTP | Graph API | EWS | OAuth2 | 多账户 |
|---|---|---|---|---|---|---|
| Microsoft 365(企业版) | 是 | 取决于管理员设置 | 是 | 是 | 是 | 是 |
| Hotmail / Outlook.com | 是 | 被 MS 屏蔽 | 是 | 是 | 是 | 是 |
| Gmail | 是 | 是 | — | — | 是 | 是 |
| Apple iCloud | 是 | 是 | — | — | — | 是 |
| Zoho | 是 | 是 | — | — | — | 是 |
| Fastmail | 是 | 是 | — | — | — | 是 |
| 任意 IMAP/SMTP 服务 | 是 | 是 | — | — | — | 是 |
EWS 是添加 Microsoft 账户最简单的方式——读取和发送共用一个 OAuth2 令牌。即使租户屏蔽了 Graph API 和 IMAP,也能正常使用。
快速入门 — 让 Claude Code 帮你完成
将此提示词复制并粘贴到 Claude Code 中,它会为你安装、编译并配置所有内容:
Install and configure the mail-mcp MCP server from https://github.com/tecnologicachile/mail-mcp
1. Clone the repo, build with cargo build --release
2. Add the MCP server to .claude.json with the binary path
3. For Microsoft accounts: use EWS (simplest) — run device code flow with
client_id d3590ed6-52b3-4102-aeff-aad2292ab01c and scope
https://outlook.office.com/EWS.AccessAsUser.All offline_access
Then configure MAIL_EWS_<ID>_USER and MAIL_EWS_<ID>_REFRESH_TOKEN
4. For Gmail: configure MAIL_IMAP + MAIL_SMTP with App Password from
https://myaccount.google.com/apppasswords
5. For Zoho: configure MAIL_IMAP + MAIL_SMTP with standard password
6. Enable write/send: MAIL_IMAP_WRITE_ENABLED=true, MAIL_SMTP_WRITE_ENABLED=true
My email accounts to configure:
- <[email protected]>
将最后一行替换为你的电子邮件地址。Claude Code 会引导你完成每个步骤,包括 Microsoft 账户的 OAuth2 设备代码流程。
手动设置(2 分钟)
安装预编译二进制文件:
# macOS and Linux (Homebrew)
brew install tecnologicachile/tap/mail-mcp
# macOS and Linux (shell installer)
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/tecnologicachile/mail-mcp/releases/latest/download/mail-mcp-installer.sh | sh
Shell 和 PowerShell 安装程序还会安装 mail-mcp-update,用于将现有安装更新到最新版本。使用 Homebrew 时,请运行 brew upgrade mail-mcp。
# Windows
powershell -ExecutionPolicy Bypass -c "irm https://github.com/tecnologicachile/mail-mcp/releases/latest/download/mail-mcp-installer.ps1 | iex"
或者从源代码构建:
git clone https://github.com/tecnologicachile/mail-mcp.git
cd mail-mcp
cargo build --release
将以下内容添加到 MCP 客户端配置中(Claude Code、Cursor 等)。使用预编译二进制文件时,请设置 "command": "mail-mcp":
{
"mcpServers": {
"mail": {
"command": "./target/release/mail-mcp",
"env": {
"MAIL_IMAP_DEFAULT_HOST": "imap.gmail.com",
"MAIL_IMAP_DEFAULT_USER": "[email protected]",
"MAIL_IMAP_DEFAULT_PASS": "your-app-password",
"MAIL_SMTP_DEFAULT_HOST": "smtp.gmail.com",
"MAIL_SMTP_DEFAULT_PORT": "587",
"MAIL_SMTP_DEFAULT_USER": "[email protected]",
"MAIL_SMTP_DEFAULT_PASS": "your-app-password",
"MAIL_SMTP_DEFAULT_SECURE": "starttls",
"MAIL_IMAP_WRITE_ENABLED": "true",
"MAIL_SMTP_WRITE_ENABLED": "true"
}
}
}
}
完成。你的 AI Agent 现在可以读取、搜索、发送和回复电子邮件,还能管理邮件。
Microsoft 账户?使用 Graph API
Microsoft 会屏蔽个人账户的 SMTP。请改用 Graph API:
{
"env": {
"MAIL_IMAP_DEFAULT_HOST": "outlook.office365.com",
"MAIL_IMAP_DEFAULT_USER": "[email protected]",
"MAIL_IMAP_DEFAULT_PASS": "your-app-password",
"MAIL_OAUTH2_DEFAULT_PROVIDER": "microsoft",
"MAIL_OAUTH2_DEFAULT_CLIENT_ID": "9e5f94bc-e8a4-4e73-b8be-63364c29d753",
"MAIL_OAUTH2_DEFAULT_CLIENT_SECRET": "none",
"MAIL_OAUTH2_DEFAULT_REFRESH_TOKEN": "<your-token>"
}
}
通过设备代码流程,1 分钟即可获取令牌。请参阅账户设置指南。
37 个 MCP 工具
读取(10 个工具)
| 工具 | 功能 |
|---|---|
list_all_accounts | 列出所有账户及其功能(IMAP、SMTP、Graph、EWS) |
imap_list_accounts | 列出 IMAP 账户 |
imap_verify_account | 测试连接和身份验证 |
imap_list_mailboxes | 列出文件夹 |
imap_mailbox_status | 邮件数量 |
imap_search_messages | 使用游标分页搜索;thread_message_id 可查找某条邮件及其回复 |
imap_search_all_mailboxes | 在每个邮箱中一次性按相同条件搜索(例如,查找分布在 INBOX、Sent 和项目文件夹中的完整对话),按时间从新到旧排序,并标注邮箱 |
imap_get_message | 已解析的邮件(文本、HTML、附件) |
imap_get_message_raw | RFC822 源内容 |
imap_get_attachment | 将单个附件下载到磁盘(不受原始大小上限限制) |
写入(11 个工具)
| 工具 | 功能 |
|---|---|
imap_update_message_flags | 添加或移除标记 |
imap_copy_message | 复制(支持跨账户) |
imap_move_message | 移动到文件夹 |
imap_delete_message | 确认后删除 |
imap_create_mailbox | 创建文件夹 |
imap_delete_mailbox | 删除文件夹 |
imap_rename_mailbox | 重命名文件夹 |
imap_append_message | 追加原始邮件 |
imap_bulk_move | 一次移动最多 500 封邮件 |
imap_bulk_delete | 一次删除最多 500 封邮件 |
imap_bulk_update_flags | 一次为最多 500 封邮件更新标记 |
发送(5 个工具)
| 工具 | 功能 |
|---|---|
smtp_send_message | 发送电子邮件(文本/HTML、抄送/密送) |
smtp_reply_message | 使用线程标头回复 |
smtp_forward_message | 转发邮件,并内联附上原始内容 |
smtp_verify_account | 测试 SMTP 连接 |
graph_send_message | 通过 Microsoft Graph API 发送邮件(支持回复线程) |
EWS — Exchange Web Services(3 个工具)
| 工具 | 功能 |
|---|---|
ews_search_messages | 通过 EWS 搜索电子邮件(收件箱、已发送、草稿等) |
ews_get_message | 通过 EWS 获取完整邮件内容 |
ews_send_message | 通过 EWS 发送电子邮件 |
草稿(5 个工具)
Agent 准备邮件,由用户在邮件客户端中审核(或要求 Agent 发送)。所有账户使用同一组工具:草稿会保存到 IMAP 草稿文件夹;如果账户已配置为使用 EWS 或 Microsoft Graph,则会通过它们保存(list_all_accounts 会显示 drafts_with)。
| 工具 | 功能 |
|---|---|
draft_create | 保存新草稿(抄送/密送、HTML、附件、邮件串) |
draft_update | 替换草稿内容;返回新的 draft_id |
draft_send | 发送草稿并将其从草稿文件夹中移除 |
draft_delete | 删除草稿(仅限草稿;需要 confirm: true) |
draft_list | 列出草稿,最新的排在最前 |
使用 MAIL_DRAFTS_ENABLED=true 启用。此设置独立于
MAIL_IMAP_WRITE_ENABLED:仅启用草稿时,Agent 可以撰写草稿,但无法移动、标记或删除其他邮件,而且每个草稿工具都会拒绝非草稿 ID。draft_send 还需要
MAIL_SMTP_WRITE_ENABLED=true。Graph 账户需要 Mail.ReadWrite 作用域。
附件
使用任意发送工具发送文件。支持两种模式:
// Large files — MCP reads from disk (recommended)
"attachments": [{"file_path": "/path/to/report.pdf"}]
// Small files — inline base64
"attachments": [{"filename": "note.txt", "content_type": "text/plain", "content_base64": "SGVsbG8="}]
系统会根据文件路径自动检测文件名和 MIME 类型。回复时设置 include_original_attachments: true,即可转发原始附件。
下载收到的邮件中的附件:使用 imap_get_attachment,并提供 message_id 和 part_id(来自 imap_get_message),或提供 filename。
该工具会将解码后的文件写入磁盘并返回路径——没有大小上限,且二进制内容不会出现在响应中。使用 MAIL_ATTACHMENT_DOWNLOAD_DIR 设置默认下载目录(默认使用系统临时目录),也可以在每次调用时传入 output_dir。
若要限制发送工具通过 file_path 可附加的本地文件,请设置 MAIL_ATTACHMENT_UPLOAD_DIR;该目录之外的路径(包括通过 .. 或符号链接访问的路径)都会被拒绝。请参阅 docs/security.md。
批量操作(2 个工具)
| 工具 | 功能 |
|---|---|
imap_search_and_move | 搜索并移动匹配项 |
imap_search_and_delete | 搜索并删除匹配项 |
设置助手(1 个工具)
| 工具 | 功能 |
|---|---|
get_setup_guide | 按服务提供商提供设置说明(Microsoft OAuth2、Gmail/iCloud App Passwords、Zoho 等) |
多账户
可根据需要配置任意数量的账户:
# Gmail
MAIL_IMAP_GMAIL_HOST=imap.gmail.com
[email protected]
MAIL_IMAP_GMAIL_PASS=app-password
# Apple iCloud (App-Specific Password from appleid.apple.com)
MAIL_IMAP_ICLOUD_HOST=imap.mail.me.com
[email protected]
MAIL_IMAP_ICLOUD_PASS=app-specific-password
MAIL_SMTP_ICLOUD_HOST=smtp.mail.me.com
[email protected]
MAIL_SMTP_ICLOUD_PASS=app-specific-password
MAIL_SMTP_ICLOUD_SECURE=starttls
# Microsoft 365
MAIL_IMAP_WORK_HOST=outlook.office365.com
[email protected]
MAIL_OAUTH2_WORK_PROVIDER=microsoft
MAIL_OAUTH2_WORK_CLIENT_ID=your-client-id
MAIL_OAUTH2_WORK_CLIENT_SECRET=none
MAIL_OAUTH2_WORK_REFRESH_TOKEN=your-token
# Zoho
MAIL_IMAP_DEFAULT_HOST=imap.zoho.com
[email protected]
MAIL_IMAP_DEFAULT_PASS=password
MAIL_SMTP_DEFAULT_HOST=smtp.zoho.com
[email protected]
MAIL_SMTP_DEFAULT_PASS=password
MAIL_SMTP_DEFAULT_SECURE=starttls
在工具调用中使用 account_id:"account_id": "gmail"、"account_id": "icloud"、"account_id": "work"、"account_id": "default"。
安全
- 强制使用 TLS:适用于所有连接(localhost 代理除外)
- 密码存储在 SecretString 中——绝不记录日志或在响应中返回
- 写操作受控——需要显式设置
MAIL_IMAP_WRITE_ENABLED=true - 发送操作受控——需要显式设置
MAIL_SMTP_WRITE_ENABLED=true - 草稿单独受控——
MAIL_DRAFTS_ENABLED=true允许撰写草稿,而无需开放任何其他写入权限 - 删除确认——需要
confirm: true - 使用 ammonia 清理 HTML(防止 XSS)
- 输出有上限——正文文本、HTML、附件会截断至可配置的限制
- 缓存 OAuth2 令牌,并预留 10 分钟的刷新缓冲时间
- 响应中不包含机密信息——凭据不会通过 MCP 工具泄露
- HTTP 传输为可选且未经身份验证——默认使用 stdio;
MAIL_MCP_TRANSPORT=http会绑定到回环地址,除非另有指定,并且应置于经过身份验证的网关之后
配置参考
完整的环境变量参考
IMAP(每个账户)
| 变量 | 必填 | 默认值 | 说明 |
|---|---|---|---|
MAIL_IMAP_<ID>_HOST | 是 | — | IMAP 服务 |
MAIL_IMAP_<ID>_PORT | 否 | 993 | IMAP 端口 |
MAIL_IMAP_<ID>_USER | 是 | — | 用户名 |
MAIL_IMAP_<ID>_PASS | 是* | — | 密码(*使用 OAuth2 时可选) |
MAIL_IMAP_<ID>_SECURE | 否 | true | 使用 TLS |
SMTP(每个账户)
| 变量 | 必需 | 默认值 | 描述 |
|---|---|---|---|
MAIL_SMTP_<ID>_HOST | 是 | — | SMTP 服务器 |
MAIL_SMTP_<ID>_PORT | 否 | 587 | SMTP 端口 |
MAIL_SMTP_<ID>_USER | 是 | — | 用户名 |
MAIL_SMTP_<ID>_PASS | 否 | — | 密码(使用 OAuth2 时可选) |
MAIL_SMTP_<ID>_SECURE | 否 | starttls | starttls、tls 或 plain |
MAIL_SMTP_<ID>_FROM_EMAIL | 否 | = _USER | 发件人地址与 SMTP 身份验证用户名不同时使用(例如共享/群组邮箱) |
OAuth2(每个账户)
| 变量 | 必需 | 默认值 | 描述 |
|---|---|---|---|
MAIL_OAUTH2_<ID>_PROVIDER | 是 | — | google 或 microsoft |
MAIL_OAUTH2_<ID>_CLIENT_ID | 是 | — | OAuth2 客户端 ID |
MAIL_OAUTH2_<ID>_CLIENT_SECRET | 是 | — | 客户端密钥(公共客户端使用 none) |
MAIL_OAUTH2_<ID>_REFRESH_TOKEN | 是 | — | 刷新令牌 |
Graph API OAuth2(每个账户)
| 变量 | 必需 | 默认值 | 描述 |
|---|---|---|---|
MAIL_GRAPH_<ID>_PROVIDER | 是 | — | microsoft |
MAIL_GRAPH_<ID>_CLIENT_ID | 是 | — | OAuth2 客户端 ID |
MAIL_GRAPH_<ID>_CLIENT_SECRET | 是 | — | 客户端密钥(公共客户端使用 none) |
MAIL_GRAPH_<ID>_REFRESH_TOKEN | 是 | — | 刷新令牌(Mail.Send 范围) |
EWS — Exchange Web Services(每个账户;Microsoft 的最简单选项)
| 变量 | 必需 | 默认值 | 描述 |
|---|---|---|---|
MAIL_EWS_<ID>_USER | 是 | — | 电子邮件地址 |
MAIL_EWS_<ID>_REFRESH_TOKEN | 是 | — | OAuth2 刷新令牌(EWS 范围) |
MAIL_EWS_<ID>_CLIENT_ID | 否 | d3590ed6...(Microsoft Office) | OAuth2 客户端 ID |
MAIL_EWS_<ID>_CLIENT_SECRET | 否 | none | 客户端密钥 |
提示: EWS 只需要 2 个变量(USER + REFRESH_TOKEN)。客户端 ID 默认为 Microsoft Office,其所有权限都已预先批准。
全局设置
| 变量 | 默认值 | 描述 |
|---|---|---|
MAIL_IMAP_WRITE_ENABLED | false | 启用 IMAP 写入操作 |
MAIL_SMTP_WRITE_ENABLED | false | 启用 SMTP/Graph 发送操作 |
MAIL_DRAFTS_ENABLED | false | 启用草稿工具(draft_send 还需要启用 MAIL_SMTP_WRITE_ENABLED) |
MAIL_SMTP_SAVE_SENT | false | 将已发送邮件保存到 IMAP Sent 文件夹(如果你的提供商发送邮件时不会自动保存,请启用此项——例如 Gmail 会自动保存,Zoho 则不一定) |
MAIL_SMTP_CONNECT_TIMEOUT_MS | 30000 | SMTP TCP/TLS/身份验证超时时间(连接阶段) |
MAIL_SMTP_SEND_TIMEOUT_MS | 300000 | SMTP DATA 传输超时时间(5 分钟,可容纳大型附件) |
MAIL_SMTP_TIMEOUT_MS | (已弃用) | 旧版单一超时时间。作为 MAIL_SMTP_SEND_TIMEOUT_MS 的备用值。建议改用上面的拆分变量。 |
MAIL_IMAP_CONNECT_TIMEOUT_MS | 30000 | TCP 连接超时时间 |
MAIL_IMAP_GREETING_TIMEOUT_MS | 15000 | TLS/问候超时时间 |
MAIL_IMAP_SOCKET_TIMEOUT_MS | 300000 | 套接字 I/O 超时时间 |
MAIL_IMAP_MAX_MAILBOXES | 200 | imap_list_mailboxes 返回的最大邮箱数(1–10000);响应会报告 total 和 truncated |
MAIL_IMAP_SEARCH_CONCURRENCY | 4 | imap_search_all_mailboxes 使用的并行 IMAP 连接数(1–8) |
MAIL_OAUTH2_TOKEN_STORE | (未设置) | 保存轮换后 OAuth2 刷新令牌的文件,以便在重启后保留令牌(参见 OAuth2 令牌存储) |
MAIL_MCP_TRANSPORT | stdio | stdio;或使用 http 提供 MCP 流式 HTTP 服务(参见 远程 HTTP 传输) |
MAIL_MCP_HTTP_HOST | 127.0.0.1 | HTTP 绑定地址(IP 字面值) |
MAIL_MCP_HTTP_PORT | 8000 | HTTP 绑定端口 |
MAIL_MCP_HTTP_PATH | /mcp | HTTP 端点路径 |
- IMAP 读取操作(搜索、获取、解析)
- IMAP 写入操作(复制、移动、删除、标记)
- IMAP 批量操作(每次最多 500 项)
- 基于游标的分页,带 TTL
- SMTP 发送、回复、转发
- Microsoft Graph API(sendMail)
- OAuth2 XOAUTH2(Google + Microsoft)
- 面向企业的独立 Graph API 令牌
- 通过环境变量支持多个账户
- 从附件中提取 PDF 文本
- HTML 清理(ammonia)
- 提供商设置文档,附直接链接
- 发送附件(SMTP/Graph)
- 回复时附上原始附件
- CDATA 清理(修复 Zoho 问题)
- 邮件确认协议(发送前预览)
- 令牌优化说明(减少 75%)
- 按需设置指南工具
- EWS(Exchange Web Services) — 在 Microsoft 上使用单个令牌进行读取和发送
- 支持使用 Microsoft Office Client ID 的 EWS(适用于受限租户)
- Graph API 会话串接 — 使用
createReply流程正确串接对话 - HTML 格式指南 — 对于发送给真人的邮件,大模型更倾向于使用 multipart(文本 + HTML)
- 已发送邮件文件夹归档保留完整 MIME — 与收件人收到的邮件逐字节一致(v0.4.1)
- 本地化的已发送邮件文件夹检测 — 西班牙语 / 葡萄牙语 / 法语 / 德语 / 意大利语 / 荷兰语 / 波兰语(v0.4.1)
- EWS 功能与 SMTP/Graph 对齐 — BCC、会话串接标头、收件人验证(v0.4.1)
- 通过
quick-xml实现 EWS XML 解析器 — 正确处理实体、CDATA 和命名空间(v0.4.1)
下一步 — 支持即时搜索的本地缓存
- SQLite + FTS5 本地邮件缓存 — 即时搜索(<10ms,而非 3-10s)
- 增量同步 — UIDVALIDITY + 最后一个 UID 增量同步
- 连接池 — 为每个账户维护持久的 IMAP 会话
- 跨账户搜索 — 一次搜索所有账户
- 邮件统计信息 — 数量、主要发件人、按日期统计的活动情况
未来
- Docker 镜像
- npm/npx 分发
- 草稿管理
- 联系人搜索
- IMAP IDLE(实时通知)
- 托管文档网站
文档
| 指南 | 说明 |
|---|---|
| 账户设置 | 各提供商的分步指南、OAuth2、应用专用密码、Azure Client ID |
| 工具契约 | 完整的工具定义和架构 |
| 消息 ID 格式 | 稳定的消息标识符格式 |
| 游标分页 | 分页行为和过期时间 |
| 安全性 | 安全功能和最佳实践 |
| 高级配置 | 超时和性能调优 |
开发
cargo test # 64 unit + integration tests
cargo fmt -- --check # formatting
cargo clippy --all-targets -- -D warnings # linting
贡献者指南请参阅 AGENTS.md。
发布
发布通过 cargo-dist 自动完成。要发布新版本:
- 在
Cargo.toml中更新version = "X.Y.Z"(发布工作流会确保该版本与推送的标签一致)。 - 将此更新和任何发布说明提交到
main。 - 创建标签并推送:
git tag vX.Y.Z git push origin main --tags .github/workflows/release.yml中的push: tags: ['v*']触发器会为 Linux / macOS(Intel + Apple Silicon)/ Windows 编译二进制文件,生成安装脚本(.sh、.ps1),创建 GitHub Release,并附上所有带 SHA256 校验和的构件。- 如果发生故障,可以在 Actions 标签页中手动重新运行工作流(保留了
workflow_dispatch触发器作为应急方案)。
有意禁用了 npm 发布。 上游分支被配置为以 @bradsjm/mail-imap-mcp-rs 发布,而本组织并不拥有此作用域,因此每次发布时 npm publish 都会返回 404。npm tarball 仍会生成并附加到每个 GitHub Release,供用户手动通过 npm install ./mail-mcp-npm-package.tar.gz 安装。若要为此分支启用 npm 注册表发布:创建一个 npm 组织(例如 @tecnologicachile),在 npmjs.com 上配置指向此仓库的 Trusted Publishing,在 dist-workspace.toml 中设置 publish-jobs = ["npm"],然后运行 dist generate --allow-dirty,以恢复 release.yml 中的 publish-npm 作业。
贡献
欢迎贡献!请查看 issues,寻找适合新手的议题。
如果 mail-mcp 对你有用,请给仓库点个 ⭐,帮助其他人发现它。
许可证
MIT 许可证——详情请参阅 LICENSE。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。