关于 email-mcp
通过 IMAP 和 SMTP 管理邮件的 MCP 服务,适用于需要处理多个账户邮件的 AI 助手。除邮件操作外,还提供定时发送、分析、实时 IMAP IDLE 监控和分类处理。
主要功能
- 01读取、搜索、发送和管理邮件
- 02支持多个 IMAP 与 SMTP 账户
- 03定时邮件与日历提取
- 04实时 IMAP IDLE 监控
- 05邮件分析与 AI 分类处理
适用场景
- 01跨账户搜索和整理邮件
- 02安排邮件在之后发送
- 03监控新邮件并捕获验证码
- 04分析邮件活动并提取日历数据
MCP 相关
向 MCP 客户端提供 52 个工具、7 个提示词和 6 个资源。支持本地 stdio 连接及通过 Streamable HTTP 的网络访问。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
Email MCP 服务
一个通过 IMAP 和 SMTP 提供全面电子邮件功能的 MCP(Model Context Protocol)服务。
支持 AI 助手跨多个账户读取、搜索、发送、管理、安排和分析电子邮件。通过 MCP 协议提供 52 个工具、7 个提示词和 6 个资源,并支持 OAuth2 (实验性)、电子邮件定时发送、日历提取、分析、基于服务提供商的标签管理、由 AI 驱动分类的实时 IMAP IDLE 监视器、即时验证码捕获并复制到剪贴板、可自定义预设和静态规则,以及引导式设置向导。
基于 MCP TypeScript SDK v2(规范修订版 2026-07-28)构建,可通过 stdio 为本地客户端提供服务,或通过 Streamable HTTP 实现网络访问——现有 stdio 配置无需更改即可继续使用。
亮点
| 功能 | email-mcp | 典型的 MCP 电子邮件工具 |
|---|---|---|
| 多账户 | ✅ | ❌ |
| 发送 / 回复 / 转发 | ✅ | ✅ |
| 草稿和模板 | ✅ | ❌ |
| 标签和批量操作 | ✅ 基于服务提供商 | ❌ |
| 定时发送邮件 | ✅ | ❌ |
| 实时 IMAP IDLE 监视器 | ✅ | ❌ |
| 验证码 → 剪贴板 | ✅ 隐藏 + 自动清除 | ❌ |
| 使用预设进行 AI 分类 | ✅ | ❌ |
| 桌面和 Webhook 提醒 | ✅ | ❌ |
| 日历(ICS)提取 | ✅ | ❌ |
| 电子邮件分析 | ✅ | ❌ |
| OAuth2(Gmail / M365) | ✅ 实验性 | ❌ |
| 引导式设置向导 | ✅ 自动检测 | ❌ |
| Streamable HTTP 传输 | ✅ | ❌ |
目录
安全
- 所有连接都使用 TLS/STARTTLS 加密
- 密码绝不会被记录;审计跟踪会记录操作,但不包含凭据
- 令牌桶速率限制器可防止滥用(每个账户使用一个桶,共享全局
rate_limit) - Gmail 和 Microsoft 365 支持 OAuth2 XOAUTH2 身份验证 (实验性)
- 附件下载上限为 5 MB,并采用 base64 编码
背景
大多数 MCP 电子邮件实现只提供基本的读取和发送功能。此服务旨在成为面向 AI 助手的全功能电子邮件客户端,涵盖电子邮件的整个生命周期:读取、撰写、管理、定时发送和分析——所有操作都通过一个 MCP 服务完成。
主要设计决策:
- 符合 XDG 规范的配置 — TOML 文件位于
~/.config/email-mcp/config.toml - 多账户 — 可同时在多个 IMAP/SMTP 账户上操作
- 分层服务 — 业务逻辑与 MCP 连接层解耦,便于测试
- 自动检测服务提供商 — Gmail、Outlook、Yahoo、iCloud、Fastmail、ProtonMail、Zoho、GMX
安装
需要 Node.js ≥ 24。
# Run directly (no install needed)
npx @codefuturist/email-mcp setup
# or
pnpm dlx @codefuturist/email-mcp setup
# Or install globally
npm install -g @codefuturist/email-mcp
# or
pnpm add -g @codefuturist/email-mcp
当 npm 的全局前缀是由 root 所有的目录(系统级 Node 安装中很常见)时,npm install -g 会因 EACCES 失败;上面的 npx/pnpm dlx 形式完全避免了这个问题,因为无需全局安装任何内容。如果你确实需要永久全局安装,请修复 npm 的前缀,而不是使用 sudo(npm config set prefix ~/.npm-global 并将其添加到 PATH,或使用 nvm/fnm/volta 等 Node 版本管理器)。以 root 身份运行 npm install -g 经常会在由用户拥有的 node_modules 目录树中混入由 root 拥有的文件,导致下一次全局安装时出现更难诊断的权限错误。
Homebrew(原生二进制文件)
来自 codefuturist tap 的预构建、无依赖二进制文件——运行时无需 Node.js:
brew install codefuturist/tap/email-mcp
每次稳定版发布时都会作为 cask 发布;适用于 macOS(arm64 + x64)和 Linuxbrew ≥ 4.3(仅二进制 cask)。
原生二进制文件(Bun)
可以使用 Bun 编译出无依赖的单一二进制文件(已压缩并预编译为字节码,冷启动约 32 ms,运行时无需 Node.js):
bun run build:binary # native binary → build/email-mcp
cp build/email-mcp ~/.local/bin/
bun run build:binaries # release matrix: darwin-arm64/x64, linux-x64/arm64,
# windows-x64 → build/release/*.{tar.gz,zip} + sha256 checksums
CI 会使用 GoReleaser Pro(.goreleaser.yaml)为所有常见平台构建每个版本的预构建二进制文件——Linux glibc + musl、macOS 和 Windows;在 Bun 支持的范围内,每个平台均提供 x64 + arm64 版本。二进制文件均附带来源证明(使用 gh attestation verify <asset> --repo codefuturist/email-mcp 验证),并随 GitHub releases 一同发布——可通过 mise 安装:mise use -g ubi:codefuturist/email-mcp。
也可以从已发布的 npm 包在本地构建相同的二进制文件(无需检出代码;需使用 ≥ 0.5.1 版本,该版本在运行时包含 imapflow TLS 修复;较早版本则需要仓库中的 pnpm 补丁)。请注意,直接使用 bun add -g 安装的 shim 会根据其 shebang 在 node 下执行 dist/main.js,因此编译步骤才是实现约 11 ms 冷启动的关键:
bun add -g @codefuturist/email-mcp
bun build --compile --minify --bytecode \
"${BUN_INSTALL:-$HOME/.bun}/install/global/node_modules/@codefuturist/email-mcp/dist/main.js" \
--outfile ~/.local/bin/email-mcp
安装后的二进制文件可自行更新:email-mcp update 会检查最新版本,并在确认后、根据发布版本的校验和文件检查 sha256,以及(存在 gh CLI 时)检查来源证明后,原子替换自身。--check 仅报告状态(退出码 1 = 有可用更新);--yes 可供脚本使用并跳过提示。系统会识别由 npm 和 mise 管理的安装,并改为提示使用 npm install -g …@latest / mise upgrade,而不会覆盖它们。
二进制文件中的 server install 会将启动项指向该二进制文件。需要包含 imapflow 补丁(patches/)——对于 IP 主机,imapflow 会向 tls.connect 传入 servername: false,而 Bun 更严格的 node:tls 会拒绝此设置。
Docker
无需 Node.js——只需 Docker。
# Latest stable release
docker pull ghcr.io/codefuturist/email-mcp:latest
# Pin to an exact version (immutable)
docker pull ghcr.io/codefuturist/email-mcp:0.2.3
# Auto-update patches within a minor version
docker pull ghcr.io/codefuturist/email-mcp:0.2
# Track a major version (won't cross breaking-change boundary)
docker pull ghcr.io/codefuturist/email-mcp:0
# Pin to an exact git commit (immutable, CI traceability)
docker pull ghcr.io/codefuturist/email-mcp:sha-abc1234
# Or build from source
docker build -t ghcr.io/codefuturist/email-mcp .
标签约定: 标签使用不带
v前缀的纯 semver,符合 Docker 生态系统标准(例如node:24、nginx:1.25)。latest标签仅在稳定版发布时更新,预发布版本不会更新。
注意: 默认情况下,服务使用 stdio 传输。必须先在主机上创建配置 (通过
npx @codefuturist/email-mcp setup或手动创建),再挂载到容器中。
用法
设置
# Add an email account interactively (recommended)
# On macOS and Linux this offers to store the password in the OS keychain,
# so config.toml only carries a `keychain:<account>` reference.
email-mcp account add
# Or use the legacy alias
email-mcp setup
# Or create a template config manually
email-mcp config init
设置向导会自动检测服务设置、测试连接、保存配置,并输出 MCP 客户端配置片段。
测试连接
email-mcp test # all accounts
email-mcp test personal # specific account
配置 MCP 客户端
下面的代码片段使用默认的 stdio 传输方式,最适合本地桌面客户端。如需通过 Streamable HTTP 进行联网或远程访问,请参阅下方的 Streamable HTTP(联网)。
推荐 — 使用引导式安装程序(可自动检测 Claude Desktop、Cursor、Windsurf;VS Code 请使用下方的手动配置片段):
email-mcp install
或者使用下面的代码片段手动添加。
Claude Desktop
编辑 ~/Library/Application Support/Claude/claude_desktop_config.json(macOS)或 %APPDATA%\Claude\claude_desktop_config.json(Windows):
{
"mcpServers": {
"email": {
"command": "npx",
"args": ["-y", "@codefuturist/email-mcp", "stdio"]
}
}
}
VS Code(GitHub Copilot)
选项 1 — 扩展市场(最简单):
- 打开扩展视图(⇧⌘X / Ctrl+Shift+X)
- 搜索
@mcp email-mcp - 点击 安装(适用于所有用户),或右键点击 → 在工作区中安装
选项 2 — 工作区配置(.vscode/mcp.json,提交到源代码管理):
{
"servers": {
"email": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@codefuturist/email-mcp", "stdio"]
}
}
}
选项 3 — 用户配置(settings.json,适用于所有工作区):
打开命令面板 → 首选项:打开用户设置(JSON),然后添加:
{
"mcp": {
"servers": {
"email": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@codefuturist/email-mcp", "stdio"]
}
}
}
}
Cursor
编辑 ~/.cursor/mcp.json:
{
"mcpServers": {
"email": {
"command": "npx",
"args": ["-y", "@codefuturist/email-mcp", "stdio"]
}
}
}
Windsurf
编辑 ~/.codeium/windsurf/mcp_config.json:
{
"mcpServers": {
"email": {
"command": "npx",
"args": ["-y", "@codefuturist/email-mcp", "stdio"]
}
}
}
Zed
编辑 ~/.config/zed/settings.json:
{
"context_servers": {
"email": {
"command": {
"path": "npx",
"args": ["-y", "@codefuturist/email-mcp", "stdio"]
}
}
}
}
Mistral Vibe
添加到 ~/.vibe/config.toml:
[[mcp_servers]]
name = "email-mcp"
transport = "stdio"
command = "npx"
args = ["-y", "@codefuturist/email-mcp", "stdio"]
若要直接传递凭据而不使用配置文件,请使用 env 字段:
[[mcp_servers]]
name = "email-mcp"
transport = "stdio"
command = "npx"
args = ["-y", "@codefuturist/email-mcp", "stdio"]
env = { "EMAIL_ACCOUNTS" = "<your-accounts-json>" }
MCP 工具会以 email-mcp_<tool_name> 的形式提供(例如 email-mcp_list_emails)。编辑配置后,请重启 Vibe。
Docker(任意 MCP 客户端)
在容器中运行服务 — 以只读方式挂载配置目录:
docker run --rm -i \
-v ~/.config/email-mcp:/home/node/.config/email-mcp:ro \
-v email-mcp-state:/home/node/.local/state/email-mcp \
-v email-mcp-cache:/home/node/.cache/email-mcp \
ghcr.io/codefuturist/email-mcp
配置挂载可以保持只读,但状态和缓存必须持久化。
该镜像将两者声明为卷,因此如果省略这些标志,Docker 会将它们保存在匿名卷中 — 像上面那样为卷命名,才能确保它们在执行 docker run --rm 后仍然保留。状态中保存着定时邮件队列:如果没有状态,重启后所有已安排但尚未发送的邮件都会丢失。缓存保存着本地镜像,可重新生成,因此丢失缓存只会导致需要重新同步。
MCP 客户端配置示例(如 Claude Desktop):
{
"mcpServers": {
"email": {
"command": "docker",
"args": [
"run", "--rm", "-i",
"-v", "~/.config/email-mcp:/home/node/.config/email-mcp:ro",
"-v", "email-mcp-state:/home/node/.local/state/email-mcp",
"-v", "email-mcp-cache:/home/node/.cache/email-mcp",
"ghcr.io/codefuturist/email-mcp"
]
}
}
}
通过环境变量配置单个账户(无需配置文件)
{
"mcpServers": {
"email": {
"command": "npx",
"args": ["-y", "@codefuturist/email-mcp", "stdio"],
"env": {
"MCP_EMAIL_ADDRESS": "[email protected]",
"MCP_EMAIL_PASSWORD": "your-app-password",
"MCP_EMAIL_IMAP_HOST": "imap.gmail.com",
"MCP_EMAIL_SMTP_HOST": "smtp.gmail.com"
}
}
}
}
stdio 传输仅在 MCP 客户端保持连接时运行——这也意味着 IMAP 监视器(以及验证捕获)会随之停止。email-mcp server 会像 iMCP 一样,将 Streamable HTTP 服务作为后台服务运行:
email-mcp server start # detached on http://127.0.0.1:8080/mcp
email-mcp server start --port 3199 # any http flags pass through (--host, --token, …)
email-mcp server start --attach # foreground instead (Ctrl-C stops)
email-mcp server status # pid, address, /healthz, uptime
email-mcp server logs -n 50 # tail the daemon log
email-mcp server restart # reuses the previous flags
email-mcp server stop # graceful SIGTERM (add --force for SIGKILL)
绑定地址保存在配置文件中,因此直接运行 server start 的结果始终确定:
[settings.server]
host = "127.0.0.1"
port = 8080
path = "/mcp"
token = "" # bearer token; empty = no auth (loopback only)
allowed_hosts = [] # Host-header allowlist for reverse proxies
优先级:CLI 标志 → EMAIL_MCP_HTTP_* 环境变量 → [settings.server] → 默认值——适用于 email-mcp http、server start 和 launchd 登录项。使用 config edit server 交互式编辑(令牌会以遮罩形式显示)。--insecure 特意设为仅能通过标志指定,不能持久保存。
登录时启动(macOS): email-mcp server install 会创建一个 launchd 登录项(com.email-mcp.server,RunAtLoad + KeepAlive),不带任何标志运行 email-mcp http——配置文件是重启或崩溃后唯一的配置来源。server status 可识别 launchd 模式;server uninstall 会移除该登录项。
状态保存在 $XDG_STATE_HOME/email-mcp/daemon.json,日志保存在其旁边的 server.log(达到 5 MB 时轮转)。stop 只会向命令行经验证确属此服务的进程发送信号(可安全应对 PID 重用)。让支持 HTTP 的 MCP 客户端连接到 http://127.0.0.1:8080/mcp;绑定非回环主机仍需要令牌。
Streamable HTTP(联网)
默认情况下,服务通过 stdio 提供 MCP,适合本地桌面客户端(参见上方示例)。如需联网或远程访问,请改为将其作为 Streamable HTTP 服务运行:
email-mcp http --port 8080
MCP 服务地址为 http://127.0.0.1:8080/mcp,健康探测地址为 GET /healthz。
标志和环境变量
| 标志 | 环境变量 | 默认值 | 描述 |
|---|---|---|---|
--host <addr> | EMAIL_MCP_HTTP_HOST | 127.0.0.1 | 要绑定的地址 |
--port <n> | EMAIL_MCP_HTTP_PORT | 8080 | 监听端口 |
--path <path> | EMAIL_MCP_HTTP_PATH | /mcp | 提供 MCP 服务的 HTTP 路径 |
--token <secret> | EMAIL_MCP_HTTP_TOKEN | — | 要求每个请求都携带 Authorization: Bearer <secret> |
--allowed-hosts a,b,c | EMAIL_MCP_HTTP_ALLOWED_HOSTS | 回环名称 + 绑定主机 | 以逗号分隔的 Host 标头允许列表(防止 DNS 重绑定);* 可禁用此检查 |
--insecure | — | false | 允许在没有令牌的情况下绑定非回环主机 |
安全性
- 令牌身份验证 — 设置令牌后,每个请求都必须发送
Authorization: Bearer <token>。 - 非回环绑定保护 — 绑定非回环主机(例如
0.0.0.0)时,如果未设置令牌,除非传入--insecure,否则会被拒绝。仅在上游反向代理负责终止 TLS 并进行身份验证时使用--insecure。 - DNS 重绑定防护 — 会根据允许列表验证
Host标头(默认包含回环名称和绑定主机)。将EMAIL_MCP_HTTP_ALLOWED_HOSTS设为公共域名;如果代理已实施保护,也可设为*以禁用此检查。
客户端配置
适用于支持 Streamable HTTP 传输的客户端:
{
"mcpServers": {
"email": {
"type": "streamable-http",
"url": "http://127.0.0.1:8080/mcp"
}
}
}
配置令牌后,如果客户端支持自定义标头,请添加 Authorization: Bearer <token> 标头。
Docker
docker compose --profile http up
必须设置 EMAIL_MCP_HTTP_TOKEN;镜像通过 EXPOSE 声明端口 8080。
CLI 命令
email-mcp [command]
Commands:
stdio Run as MCP server over stdio (default)
http Run as MCP server over Streamable HTTP (networked)
server start [--attach] Start an always-on HTTP server (detached by default)
server stop [--force] Stop the detached server
server status Show pid, address, health, uptime (exit 1 if stopped)
server restart Stop and start again (reuses previous flags)
server logs [-n N] Show the last N daemon log lines
server install Install as macOS login item (launchd, survives reboots)
server uninstall Remove the login item and stop the server
account list List all configured accounts
account add Add a new email account interactively
account edit [name] Edit an existing account
account delete [name] Remove an account
setup Alias for 'account add'
test Test connections for all or a specific account
open <id> [--print] Open an email in the native mail client via its message: link
(macOS; --print or other platforms print the URL instead)
install Register email-mcp with MCP clients interactively
install status Show registration status for detected clients
install remove Unregister email-mcp from MCP clients
config show Show config (passwords masked)
config edit [section] Interactive settings editor (general, server, send, attachments,
scheduler, watcher, verification, cache, hooks, alerts)
config validate Check syntax, schema, typo'd keys, and cross-setting consistency
completion zsh|bash|fish Print shell completion script (accounts and sections complete dynamically)
config path Print config file path
config init Create template config
scheduler check Process pending scheduled emails
scheduler list Show all scheduled emails
scheduler install Install OS-level scheduler (launchd/crontab)
scheduler uninstall Remove OS-level scheduler
scheduler status Show scheduler installation status
cache status [--json] Show cache size, contents, coverage and freshness
cache clear [--account N] Delete cached mail/attachments and free the disk space
(--json supported by status, clear and verify)
cache verify Check the cache for corruption and reclaim orphaned files
update [--check|--yes] Self-update the binary to the latest GitHub release
help Show help
Shell 补全
# zsh (one line in ~/.zshrc)
source <(email-mcp completion zsh)
# bash
source <(email-mcp completion bash)
# fish
email-mcp completion fish > ~/.config/fish/completions/email-mcp.fish
补全涵盖每个命令、子命令和标志——还会动态补全配置中的账户名称(email-mcp test <TAB>、account edit <TAB>)和设置区段(config edit <TAB>)。
查看日志
后台守护进程将日志写入 $XDG_STATE_HOME/email-mcp/server.log。使用 tail/follow/filter 查看器查看日志,无需查找文件:
email-mcp logs # last 40 lines (colored by level)
email-mcp logs -n 200 # more lines
email-mcp logs -f # live follow (Ctrl-C to stop)
email-mcp logs --level warn # only WARN and ERROR (continuation lines kept)
email-mcp logs --grep imap # only lines matching a substring
email-mcp logs -f --level error # watch for errors as they happen
email-mcp server logs 是具有相同选项的别名。通过管道输出或设置 NO_COLOR 时会自动禁用颜色;在 systemd 主机上,也可以使用 journalctl --user -u email-mcp。
从命令行读取和发送邮件
除了作为 MCP 服务运行,email-mcp 本身也是一个可用的邮件客户端——无需 MCP 客户端,也无需编写代码。命令默认使用你配置的第一个账户(传入 --account <name> 可选择其他账户),会输出整洁的彩色表格(通过管道传输或设置 NO_COLOR 时会自动禁用颜色),并支持 Tab 补全(参见Shell 补全)。
email-mcp list # recent INBOX messages (● unread, ★ flagged, 📎 attachment)
email-mcp list --unread --limit 50 # filters
email-mcp list --mailbox Archive --search invoice
email-mcp read 42 # full message (headers, body, attachment names + sizes)
email-mcp read 42 --mark-read
email-mcp search "from bank" # IMAP search
email-mcp mailboxes # folders with unread/total counts
email-mcp flag 42 # flag / --off to unflag
email-mcp attach 42 report.pdf ~/Downloads # save an attachment
email-mcp delete 42 --yes # delete (asks to confirm without --yes)
email-mcp reply 42 --body "on it" --all
email-mcp send --to [email protected],[email protected] --subject "Hi" --body "..." --attach ./file.pdf
每个命令都接受 --help;读取命令(list、read、search、mailboxes)接受 --json,以输出可供机器读取的内容,你可以将其传递给 jq:
email-mcp list --json | jq '.items[] | {id, subject, from: .from.address}'
email-mcp read 42 --json | jq .attachments
发送或回复时,附件大小会在任何内容离开你的设备之前根据配置的限制进行检查(有关如何避免以明文存储凭据,请参见存储账户密钥)。
配置
配置文件位于 $XDG_CONFIG_HOME/email-mcp/config.toml(默认:~/.config/email-mcp/config.toml)。使用 email-mcp config validate 验证配置(检查 TOML 语法、架构、拼写错误的键并提供类似建议的键,以及设置间的一致性;出错时退出码为 1,适合用于 CI),并使用 email-mcp config edit [section] 交互式编辑——每次保存前都会先验证,并将之前的文件备份为 config.toml.bak。注意:以编程方式保存会重写文件,并移除 TOML 注释(备份文件会保留注释)。
[settings]
rate_limit = 10 # max emails per minute per account
[settings.send]
max_attachment_mb = 25 # global cap on the base64-encoded attachment total
save_to_sent = false # file a copy of each sent message in the IMAP Sent folder
[settings.attachments]
auto_download = true # save attachments locally when calendar events are created from emails
[settings.attachment_download]
# dir = "/data/attachments" # unset (default) disables download_attachment's saveToDownloadDir
allowed_extensions = ["pdf", "png", "jpg", "jpeg", "webp", "tiff", "txt", "md", "doc", "docx", "odt", "xls", "xlsx", "csv"]
max_bytes = 26214400 # 25 MB
[[accounts]]
name = "personal"
email = "[email protected]"
full_name = "Your Name"
password = "keychain:personal" # or "env:VAR", or a plaintext app password
# max_attachment_mb = 25 # optional per-account override (beats global + provider limits)
# sent_mailbox = "INBOX.Sent Messages" # optional, see "Sent-folder copies" below
# save_to_sent = true # optional per-account override of the Gmail-skip guess
[accounts.imap]
host = "imap.gmail.com"
port = 993
tls = true
[accounts.smtp]
host = "smtp.gmail.com"
port = 465
tls = true
starttls = false
verify_ssl = true
[accounts.smtp.pool]
enabled = true
max_connections = 1
max_messages = 100
存储账户密钥
password 字段(以及 OAuth2 的 client_secret / refresh_token)支持间接引用,因此凭据无需以明文形式存放在文件中:
| 值 | 解析来源 |
|---|---|
keychain:<account> | 操作系统密钥链——macOS Keychain(security)或 Linux libsecret(secret-tool),服务为 email-mcp,账户为 <account> |
keychain:<service>/<account> | macOS Keychain,使用显式指定的服务名称 |
env:<VAR> | 环境变量 <VAR>(可用于 Linux,或使用由 age/SOPS 提供的环境变量) |
| 任何其他字符串 | 按原样使用(明文,向后兼容) |
配置文件本身始终以 0600(仅所有者可访问)权限写入,其 .bak 文件也一样。
**macOS Keychain(多账户):**为每个账户的密钥各存储一次——
email-mcp account set-secret personal # store a NEW secret (prompts; nothing echoed or in argv)
email-mcp account migrate-secret personal # move an EXISTING plaintext password into the keychain
set-secret 会提示输入值并将其存储;migrate-secret 会从 config.toml 读取该账户当前的明文密码,将其存储在密钥链中,验证后再将对应行改写为 password = "keychain:personal"。无论哪种方式,最终都会得到 password = "keychain:personal"。每个账户都是共享 email-mcp 服务下的独立 Keychain 项目,因此多个账户可以共存。启动时通过 security CLI 读取密钥;传递给命令的参数始终只有服务名和账户名,密钥只通过标准输出传递。
静态存储时,密钥保存在你的登录密钥链中,由 macOS 登录凭据(登录级别的 Touch ID)加密并解锁。正在运行的 email-mcp 守护进程会在启动时读取一次密钥;每次 IMAP 重新连接时都不会提示使用 Touch ID——有意不在无人值守的后台服务中使用每次访问都要求生物识别验证的方式。(真正实现每次访问都要求 Touch ID,需要使用数据保护密钥链和原生辅助程序。)
OAuth2 (实验性)
**注意:**OAuth2 支持为实验性功能。在你的环境中,令牌刷新和特定提供商的流程可能需要额外测试。
[[accounts]]
name = "work"
email = "[email protected]"
full_name = "Your Name"
[accounts.oauth2]
provider = "google" # or "microsoft"
client_id = "your-client-id"
client_secret = "your-client-secret"
refresh_token = "your-refresh-token"
[accounts.imap]
host = "imap.gmail.com"
port = 993
tls = true
[accounts.smtp]
host = "smtp.gmail.com"
port = 465
tls = true
[accounts.smtp.pool]
enabled = true
max_connections = 1
max_messages = 100
环境变量
适用于单账户配置(会覆盖配置文件):
| 变量 | 默认值 | 说明 |
|---|---|---|
MCP_EMAIL_ADDRESS | required | 电子邮件地址 |
MCP_EMAIL_PASSWORD | required | 密码或应用专用密码 |
MCP_EMAIL_IMAP_HOST | required | IMAP 服务器主机名 |
MCP_EMAIL_SMTP_HOST | required | SMTP 服务器主机名 |
MCP_EMAIL_ACCOUNT_NAME | default | 账户名称 |
MCP_EMAIL_FULL_NAME | — | 显示名称 |
MCP_EMAIL_USERNAME | 登录用户名 | |
MCP_EMAIL_IMAP_PORT | 993 | IMAP 端口 |
MCP_EMAIL_IMAP_TLS | true | IMAP TLS |
MCP_EMAIL_SMTP_PORT | 465 | SMTP 端口 |
MCP_EMAIL_SMTP_TLS | true | SMTP TLS |
MCP_EMAIL_SMTP_STARTTLS | false | SMTP STARTTLS |
MCP_EMAIL_SMTP_VERIFY_SSL | true | 验证 SSL 证书 |
MCP_EMAIL_SMTP_POOL_ENABLED | true | 启用 SMTP 传输连接池 |
MCP_EMAIL_SMTP_POOL_MAX_CONNECTIONS | 1 | SMTP 连接池中的最大连接数 |
MCP_EMAIL_SMTP_POOL_MAX_MESSAGES | 100 | 每个池化连接的最大邮件数 |
MCP_EMAIL_RATE_LIMIT | 10 | 每分钟最大发送数 |
MCP_EMAIL_SEND_SAVE_TO_SENT | false | true 会将每封已发送邮件的副本追加到 IMAP 已发送文件夹 |
MCP_EMAIL_READ_ONLY | false | true 会注销邮箱写入工具(发送、移动、删除、标签、批量操作)。日历/提醒写入、剪贴板复制和配置写入工具仍可用——这是邮箱防护,不是全局防护。 |
MCP_EMAIL_SCHEDULER_SENT_RETENTION_DAYS | 90 | 保留已发送邮件历史记录的天数;0 表示全部保留 |
MCP_EMAIL_ATTACHMENT_DOWNLOAD_DIR | — | download_attachment 的 saveToDownloadDir 写入的目录;未设置则禁用此选项 |
MCP_EMAIL_ATTACHMENT_DOWNLOAD_ALLOWED_EXTENSIONS | (内置列表 — 见下文) | 保存附件的逗号分隔扩展名允许列表 |
MCP_EMAIL_ATTACHMENT_DOWNLOAD_MAX_BYTES | 26214400(25 MB) | saveToDownloadDir 可写入的最大附件大小 |
本地缓存
读取操作由本地 SQLite 邮件镜像(以及用于附件的内容寻址存储)提供,位于
${XDG_CACHE_HOME:-~/.cache}/email-mcp/ 下。它能加快邮件列表、搜索和
重新读取速度,并在邮件服务器无法访问时让邮件仍可读取。此功能默认启用。
缓存绝非权威数据源。 每一行都可以从 IMAP 重新获取,因此删除缓存只会导致重新同步, 不会丢失邮件——按照 XDG 缓存约定,你可以随时删除该目录。
查看和回收缓存占用空间
email-mcp cache status # size vs budget, per-mailbox coverage, last sync
email-mcp cache status --json # same, for scripts
email-mcp cache clear # free the space (asks first; mail is re-fetched)
email-mcp cache clear --account work --yes
email-mcp cache verify # integrity check + reclaim orphaned files
cache status 会分别报告索引大小和附件字节数、已缓存完整文本的邮件数量,以及每个邮箱上次协调同步距今的时间。
check_health 会向 AI 客户端提供相同数据,外加读取命中率。
如何判断数据是否最新
正确性优先:对“有新邮件吗?”给出过时答案就是错误答案。
从缓存提供邮箱数据之前,服务会选择信任最近 10 秒内的一次协调同步,或花费一次 STATUS 往返,将服务器的 UIDVALIDITY/UIDNEXT/HIGHESTMODSEQ/MESSAGES 与镜像记录进行比较——这相当于 IMAP 中的条件请求。如果有任何变化,服务会在回答前重新同步(有上限;超过上限时,你会收到标记为 stale 的缓存答案)。如果服务器无法访问,你会收到标记为 offline 的缓存答案。
对于给定的 UIDVALIDITY/UID,邮件正文和附件不可变,因此存储后无需重新验证即可提供。通过此服务进行的写入(标记、移动、删除)会立即重新同步受影响的邮箱;这对不支持 CONDSTORE 的服务器尤为重要,因为否则标记更改将无法被察觉。
设置
| 设置项 | 默认值 | 功能说明 |
|---|---|---|
enabled | true | false 表示每次都从 IMAP 实时读取 |
mailboxes | ["INBOX"] | 在后台同步。其他邮箱仅在读取时按需镜像 |
window_days | 0(全部) | 邮箱首次同步时向前追溯的天数 |
body_messages | 500 | 每个邮箱保留的邮件正文数量。0 表示缓存仅保留元数据 |
max_size_mb | 500 | 索引和附件合计的容量上限 |
sync_interval | 300 | 后台协调之间的间隔秒数 |
超出容量上限时,将按重建成本从低到高清理:附件文件(优先清理最近最少读取的文件),然后是邮件正文,最后是早于 window_days 的邮件信封。邮件信封会尽可能保留,因为列表和搜索都需要它们。
覆盖范围,而不只是新鲜度。 只有当缓存包含服务器报告的该邮箱全部邮件时,才能用缓存响应列表查询。将 window_days 设为非 0 值后,镜像就会变成一个切片——此时无法如实报告 total,也无法判断是否还有更多页面,因此在缓存追上之前,读取会回退到实时路径。这也是为什么清除邮件信封时会同时清除该邮箱的同步水位:下一次同步会重新建立覆盖范围,而不是留下永久且不可见的缺口。
静态数据
缓存的邮件(包括正文和附件内容)以未加密形式存储在仅当前用户可读取的目录和文件中(0700/0600)。这与桌面邮件客户端的做法一致;建议使用全盘加密(FileVault、LUKS)来保护数据。如果不希望正文和附件存储在磁盘上,请将 body_messages = 0,这样缓存就只保留元数据。
Gmail 注意事项:不要将 [Gmail]/All Mail 添加到 mailboxes。Gmail 会在每个标签文件夹中显示同一封邮件,因此在镜像 INBOX 的同时镜像 All Mail 会导致同一封邮件被存储两次。
邮件定时发送
定时发送功能采用分层架构,实现未来时间的邮件投递:
- MCP 自动检查 — 在服务启动时处理队列,并在 MCP 服务运行期间每隔 60 秒处理一次
- CLI — 使用
email-mcp scheduler check手动处理,或通过 cron 处理 - 操作系统级守护进程 —
email-mcp scheduler install会设置 launchd(macOS)或 crontab(Linux),每分钟运行一次,独立于 MCP 服务
重要 — 必须安装守护进程,才能确保可靠投递。 如果未安装,定时邮件只会在 AI 客户端主动连接时发送。 到达预定时间时,机器也必须处于运行状态;如果机器处于休眠或关机状态,守护进程会在下次唤醒或启动时处理逾期邮件。发送失败最多重试 3 次,之后会标记为
failed。
设置守护进程
# Install (macOS launchd / Linux crontab — runs every minute)
email-mcp scheduler install
# Verify it's running
email-mcp scheduler status
# View pending / sent / failed scheduled emails
email-mcp scheduler list
# Trigger a manual check immediately
email-mcp scheduler check
# Remove the daemon
email-mcp scheduler uninstall
定时邮件以 JSON 文件形式存储在 ~/.local/state/email-mcp/scheduled/ 中,并通过状态进行锁定。每个条目都会记录尝试次数(最多 3 次)和上次错误,因此可以使用 scheduler list 检查失败情况。
实时监视器与 AI 钩子
IMAP IDLE 监视器通过持久 IDLE 连接(与工具连接分开)实时监控已配置的邮箱。收到新邮件时:
- 静态规则 — 根据发件人、收件人或主题进行模式匹配 → 立即应用标签、标记邮件或设为已读(无需 AI)
- AI 分类 — 通过 MCP 采样和可自定义的预设提示词分析其余邮件
- 通知模式 — 如果禁用了 AI 分类,则改为记录日志
在 config.toml 中配置:
[settings.watcher]
enabled = true
folders = ["INBOX"]
idle_timeout = 1740 # 29 minutes (IMAP spec max is 30)
[settings.hooks]
on_new_email = "triage" # "triage" | "notify" | "none"
preset = "inbox-zero" # "inbox-zero" | "gtd" | "priority-focus" | "notification-only" | "custom"
auto_label = true # apply AI-suggested labels
auto_flag = true # flag urgent emails
batch_delay = 5 # seconds to batch before triage
# User context — appended to preset's AI prompt
custom_instructions = """
I'm a software engineer. Emails from @mycompany.com are always high priority.
Newsletters I read: TL;DR, Hacker Newsletter.
"""
# Static rules — run BEFORE AI, skip AI if matched
[[settings.hooks.rules]]
name = "GitHub Notifications"
match = { from = "*@github.com" }
actions = { labels = ["Dev"], mark_read = true }
[[settings.hooks.rules]]
name = "Newsletter Archive"
match = { from = "*@substack.com|*@buttondown.email" }
actions = { labels = ["Newsletter"] }
[[settings.hooks.rules]]
name = "VIP Contacts"
match = { from = "[email protected]|[email protected]" }
actions = { flag = true, labels = ["VIP"] }
预设
| 预设 | 重点 | 建议标签 |
|---|---|---|
inbox-zero | 积极分类和归档 | Newsletter、Notification、Updates、Finance、Social、Promo |
gtd | Getting Things Done 上下文 | @Action、@Waiting、@Reference、@Someday、@Delegated |
priority-focus | 简单的优先级分类(默认) | (无——仅设置优先级和标记) |
notification-only | 不进行 AI 分类,仅记录日志 | (无) |
custom | 用户定义完整的系统提示词 | 用户自定义 |
静态规则
静态规则使用 glob 风格的模式(*@github.com),并以 | 作为 OR 分隔符(*@github.com|*@gitlab.com)。匹配项中的所有条件都必须同时满足。按顺序应用规则,首条匹配的规则优先。
可用操作:labels(字符串数组)、flag(布尔值)、mark_read(布尔值)、alert(布尔值——强制发送桌面通知)。
警报
基于紧急程度的多渠道通知路由——即使你没有查看聊天,也能让你注意到重要邮件。所有渠道均为选择加入,默认禁用。
| 优先级 | 桌面 | 声音 | MCP 日志级别 | Webhook |
|---|---|---|---|---|
urgent | ✅ 横幅 | 🔊 提醒音 | alert | ✅ |
high | ✅ 横幅 | 🔇 静音 | warning | ✅ |
normal | ❌ | ❌ | info | ❌ |
low | ❌ | ❌ | debug | ❌ |
[settings.hooks.alerts]
desktop = true # OS-level notifications (macOS/Linux/Windows)
sound = true # play sound for urgent emails
urgency_threshold = "high" # minimum priority to trigger desktop alert
webhook_url = "https://ntfy.sh/my-email-alerts" # optional: Slack, Discord, ntfy.sh, etc.
webhook_events = ["urgent", "high"]
**支持的平台:**macOS(通过 osascript 使用通知中心)、Linux(notify-send)、Windows(PowerShell Toast 通知)。无需 npm 依赖——使用操作系统原生命令。
各平台的通知设置:
macOS
桌面通知使用 osascript(内置)。运行 MCP 服务的终端应用需要获得通知权限:
- 打开系统设置 → 通知与专注模式
- 找到你的终端应用(Terminal、iTerm2、VS Code、Cursor 等)
- 启用允许通知,并选择横幅或提醒
- 确保专注模式/“请勿打扰”没有拦截通知
使用 check_notification_setup 进行诊断,并使用 test_notification 进行验证。
Linux
需要安装来自 libnotify 的 notify-send。如需声音提醒,还需要 paplay:
# Ubuntu / Debian
sudo apt install libnotify-bin pulseaudio-utils
# Fedora
sudo dnf install libnotify pulseaudio-utils
# Arch
sudo pacman -S libnotify
桌面通知需要正在运行的显示服务器(X11/Wayland)——在无头/SSH 会话中无法使用。
Windows
使用 PowerShell Toast 通知(内置):
- 打开设置 → 系统 → 通知
- 确保已开启通知
- 设置专注助手以允许通知
- 如果使用 Windows Terminal,请确保已启用其通知
**可由 AI 配置:**AI 可以在运行时检查、测试和配置通知:
check_notification_setup— 诊断平台支持情况并显示设置说明test_notification— 发送测试通知以验证一切正常configure_alerts— 启用/禁用桌面通知、声音、阈值和 webhook(可选择保存到配置文件)
Webhook 载荷:
{
"event": "email.urgent",
"account": "work",
"sender": { "name": "John CEO", "address": "[email protected]" },
"subject": "Q4 Review Due Today",
"priority": "urgent",
"labels": ["VIP"],
"rule": "VIP Contacts",
"timestamp": "2026-02-18T11:30:00Z"
}
无论紧急程度阈值如何,静态规则都可以通过 alert = true 强制发送桌面通知:
[[settings.hooks.rules]]
name = "VIP Contacts"
match = { from = "[email protected]" }
actions = { flag = true, alert = true, labels = ["VIP"] }
功能:
- 自动重连 — 连接失败时采用指数退避策略(1 秒 → 60 秒)
- 批处理 — 将可配置延迟时间内收到的邮件归为一组,以减少 AI 调用
- 速率限制 — 每分钟最多 10 次采样调用
- 优雅降级 — 如果客户端不支持采样,则回退到通知模式
- 资源订阅 — 推送
notifications/resources/updated,更新未读计数
验证码(即时捕获 OTP)
收到包含验证码(OTP/2FA)或登录魔法链接的邮件时,email-mcp 会在约 1–2 秒内将其复制到剪贴板并显示通知 — “✅ 来自 GitHub 的代码 482913 — 已复制到剪贴板,将在 60 秒后清除”。按 ⌘V / Ctrl+V 即可。
检测采用评分机制(支持英语和德语),而非简单的数字正则表达式:根据关键词邻近程度
(verification、Bestätigungscode、expires 等)加分,根据负面上下文(订单号、
发票、物流追踪、Zoom 密码、电话号码、价格、日期)扣分。没捕获到也好过把错误代码放进剪贴板。
[settings.watcher]
enabled = true # REQUIRED for ambient catching (IMAP IDLE push)
[settings.verification]
enabled = true # on by default
auto_copy = true # copy caught codes/links to the clipboard
confirm_copy = false # ask (native dialog) before touching the clipboard
notify = true # desktop notification on catch
copy_links = true # also catch magic links (only when no code found)
link_action = "open" # "open" = offer to open links in the browser, "copy" = clipboard
clear_after_seconds = 60 # conditional auto-clear (0 = never)
max_age_minutes = 10 # ignore stale messages (IDLE replays)
accounts = [] # limit to specific accounts (empty = all)
sender_allowlist = [] # e.g. ["*@github.com", "*@google.com"]
sender_denylist = []
先询问模式: 设置 confirm_copy = true 后,原生 macOS 对话框(“来自
GitHub 的代码 482913 — 要复制到剪贴板吗?”)会在任何内容写入剪贴板前出现。登录
链接默认使用三按钮对话框(link_action = "open"):打开会在默认浏览器中打开链接,复制会将链接放入剪贴板,取消则不执行任何操作 — 打开操作始终需要确认,因为从邮件内容自动启动浏览器会带来钓鱼风险。设置 link_action = "copy" 可使用静默复制到剪贴板的行为。对话框仅适用于 macOS;在其他系统上,这些模式会退化为仅显示通知。
剪贴板安全:(macOS)验证码通过 JXA osascript 写入,并使用
org.nspasteboard.ConcealedType 标记 — 这是 1Password/Bitwarden 使用的相同惯例 — 因此
行为良好的剪贴板管理器(Maccy、Paste 等)不会记录验证码。自动清除是有条件的:仅当剪贴板中仍是捕获到的值时才会清除,因此不会覆盖你在此期间复制的内容。Linux 使用
wl-copy/xclip,Windows 使用
PowerShell Set-Clipboard(那里没有对应的隐藏标记惯例)。不依赖任何 npm 包。
供 Agent 使用: get_verification_code 会按需获取最新验证码 — 在自动注册过程中,调用时设置
wait_seconds = 30,邮件到达后几秒内即可返回验证码(配合监听器时由事件触发,不配合时每 5 秒轮询)。如果在限定时间内没有收到邮件,它会返回 found: false 和提示 — 再次调用即可。
安全说明: 剪贴板是共享的操作系统状态 — 验证码存在期间,任何应用都可以读取它(该时间段由
clear_after_seconds 限定)。验证码本身不会写入服务器日志或审计日志;但会出现在
get_verification_code 的结果中,这正是该工具的用途。紧急关闭开关:enabled = false(关闭功能)或
auto_copy = false(仅显示通知)。环境变量覆盖项:MCP_EMAIL_VERIFICATION_*
(_ENABLED、_AUTO_COPY、_CONFIRM_COPY、_NOTIFY、_COPY_LINKS、_LINK_ACTION、
_CLEAR_AFTER_SECONDS、_MAX_AGE_MINUTES、_ACCOUNTS、_SENDER_ALLOWLIST、
_SENDER_DENYLIST)。
使用 check_clipboard_setup 诊断处理流程(添加 test_write = true 可执行无害的复制 → 读回 → 清除往返测试)。
API
工具(52)
结构化输出:
list_emails、search_emails、get_email_status、list_mailboxes和get_verification_code除了返回人类可读文本外,还会返回机器可读结果(outputSchema+structuredContent),供使用类型化工具输出的客户端使用。
邮件正文:HTML 和其他格式
几乎所有真实邮件都是 HTML 格式 — 在抽样的某个邮箱中,169 封邮件有 165 封是
单部分 text/html — 因此,读取工具会转换邮件内容,而不是直接返回标记语言。
get_email、get_emails 和 get_thread 接受 format:
format | 返回的正文 |
|---|---|
text (默认) | 将 HTML 转换为易读文本:链接转换为 [label](url),表格保留单元格边界,列表转换为编号或项目符号,引用行首加上 > ,图像转换为 [image: alt] |
stripped | 与 text 相同,但去掉引用的回复链和签名 |
full | 原始正文部分,包含 HTML |
正文默认有长度上限:get_email 为 10 000 个字符,get_emails 和 get_thread 中每封邮件为 5 000 个字符;提示会说明省略了多少内容。传入 maxLength: 0 可取消上限。正文的两种形式(纯文本、HTML)各自最多读取 512 KB,且由其各个部分共享此上限。 |
其他格式的处理方式如下:
multipart/alternative— 会获取两个部分,因此bodyText和bodyHtml都可用。如果纯文本部分太短,无法容纳与其 HTML 同级部分相同的内容,就会将其视为“请在 HTML 阅读器中查看”的占位内容并跳过。- 包含多个文本部分的
multipart/mixed— 按顺序拼接,因此,无论是被内嵌图片隔开的备注(Apple Mail),还是每封邮件各自的摘要部分,都不会因为只读取第一部分而被截断。 text/plain; format=flowed(RFC 3676)— 会还原软换行,因此段落会按段落显示,而不是每 72 列硬换行;同时遵循DelSp和空格填充规则。- 内嵌(
cid:)图片 — 会作为附件列出,并包含partId、contentId和inline,可通过download_attachment的partId下载。发送邮件时,如需嵌入图片,请在attachments中传入{path, cid, contentType},并通过<img src="cid:…">引用。 - 退信(
multipart/report)— 可供机器读取的message/delivery-status部分会单独呈现,与正文分开。 - 日历邀请 — 由
extract_calendar/add_to_calendar处理,并遵循该部分声明的字符集。 - 加密邮件(S/MIME、PGP/MIME)— 不会解密;正文会明确说明这一点,而不会显示为空。
- 附加的邮件(
message/rfc822)— 绝不会误当作正文;但如果邮件没有其他文本(作为附件转发、摘要),则会用它作为正文。
附件下载目录。 download_attachment 通常会返回经过 Base64 编码的文件(≤5 MB)。将 [settings.attachment_download] dir(或
MCP_EMAIL_ATTACHMENT_DOWNLOAD_DIR)设置为某个目录,并传入
saveToDownloadDir: true,即可将文件写入该目录并获取其路径,而不是返回 Base64 编码内容——这适用于较大的文件,或调用方只希望将附件保存到磁盘,而不是内嵌到对话中的情况。设置 dir 前无法使用此选项(调用会失败),因为没有默认位置。只会写入 allowed_extensions 中的文件(默认值:常见文档和图片类型;参见上方的配置示例);max_bytes 会限制文件大小,且不受 5 MB 的 Base64 上限影响。传入 saveAs 可指定写入的文件名(只能是纯文件名,不能包含路径分隔符);否则会清理附件自身的文件名后使用。在 Docker 中运行时,请将 dir 指向一个挂载卷,并确保需要读取文件的程序也能访问该卷,例如在 docker-compose.yml 中:
services:
email-mcp:
environment:
MCP_EMAIL_ATTACHMENT_DOWNLOAD_DIR: /data/attachments
volumes:
- attachments:/data/attachments
other-service:
volumes:
- attachments:/data/attachments:ro
volumes:
attachments:
已发送文件夹中的副本。 SMTP 负责投递邮件,但不会将其存档。[settings.send] save_to_sent 默认值为 false;如果 IMAP 主机不会自行保存已发送邮件,请启用此选项。Gmail 会在服务器端保存已发送邮件,因此如果某个账户的 IMAP 服务器声明了 X-GM-EXT-1 功能,即使启用了此设置,也会自动跳过保存——否则再存一份会导致所有邮件重复。设置账户自身的 save_to_sent 可强制决定是否保存(true 表示仍然保存,false 表示永不保存,无论全局设置或对 Gmail 的判断如何)。
副本会携带服务器接受的相同 Message-ID,标记为
\Seen,并存入服务器标记为 \Sent 的文件夹(如果不存在,则存入新建的 Sent 文件夹)。如果邮箱中有多个看起来像已发送邮件的文件夹——例如实际使用的文件夹旁还留有一个 Sent 文件夹——自动判断可能会选中空文件夹;请将账户的 sent_mailbox 设置为完整路径(list_mailboxes 报告的路径)以明确指定。副本不包含 Bcc,因为 MIME 组装器会无条件移除该字段。
归档失败不会导致发送失败——邮件已经发出,若报告发送失败,可能会引发重复发送——但在这种情况下,send_draft 会保留草稿,而不是删除这封邮件唯一剩下的副本。send_email、reply_email、forward_email 和 send_draft 都会在结果的 sentCopy 字段中报告处理结果:{kind: "filed", path}、{kind: "skipped"}(设置已关闭,或由 Gmail 自行捕获),或 {kind: "failed", error}。
外发 HTML(html: true)会以 multipart/alternative 格式发送,并附带生成的纯文本替代内容。转发时会以转换后的文本引用原邮件;向 forward_email 传入 html: true,还会一并转发原邮件的 HTML。
读取(14)
| 工具 | 说明 |
|---|---|
list_accounts | 列出所有已配置的电子邮件帐户 |
list_mailboxes | 列出文件夹及其未读邮件数和特殊用途标记 |
list_emails | 分页列出邮件,可按日期、发件人、主题和标记筛选;标记批量邮件;可选预览正文 |
get_email | 读取完整邮件内容,包含附件元数据和批量邮件分类(默认将 HTML 转换为易读文本) |
get_emails | 一次调用获取多封邮件的完整内容(最多 20 封);包含相同的批量邮件标记 |
get_email_status | 获取邮件的已读、标记和标签状态,而不获取正文 |
search_emails | 按关键字搜索主题、发件人和正文;包含与 list_emails 相同的批量邮件标记和可选预览 |
download_attachment | 按文件名或 MIME 部分 ID 下载邮件附件;以 base64 编码,或(如已配置)保存到服务器的附件下载目录 |
find_email_folder | 查找邮件实际所在的文件夹(解析虚拟文件夹) |
extract_contacts | 从近期邮件标头中提取不重复的联系人 |
get_thread | 通过 References/In-Reply-To 重建对话线程;包含相同的批量邮件标记 |
list_templates | 列出可用的电子邮件模板 |
get_email_stats | 电子邮件分析——邮件量、主要发件人和每日趋势 |
check_health | 检查连接状态、延迟、配额和 IMAP 功能 |
批量邮件分类
list_emails、search_emails、get_email、get_emails 和 get_thread 会标记邮件列表和机器生成的邮件,因此无需阅读正文也能对收件箱进行分拣:
| 标记 | 含义 | 判定依据 |
|---|---|---|
📰 newsletter | 邮件列表或订阅邮件 | List-Unsubscribe(RFC 2369)、List-Id(RFC 2919)、Precedence: list |
🤖 automated | 机器生成的通知 | Auto-Submitted(RFC 3834)、Precedence: bulk/junk |
| (无) | 普通的人际邮件 | 不包含批量邮件标头 |
如果发件人提供了退订 URI,新闻邮件也会报告该 URI;如果支持 RFC 8058 一键退订,还会标记 1-click。这些标头会在获取邮件列表时一并请求,因此分类整页邮件无需额外往返。
分类依据标头,因此结果是确定性的——不会调用模型,也不会对主题文本使用启发式判断。若发件人省略这些标头,邮件会被报告为个人邮件,而不会进行猜测。这些标头由发件人声明,并未经过验证——应将标记视为参考信号,而非可盲目信赖的事实。
正文预览
list_emails 和 search_emails 接受 preview: true,以包含每封邮件正文中约 200 个字符的预览。默认关闭:每封邮件会额外获取 1500 字节,并增加工具输出长度;调用方应自行决定是否承担这项开销,而不是默认继承。
预览从一个正文部分解码,而非从邮件源解码——IMAP 部分 1;如果部分 1 本身是多部分结构,则使用 1.1。由于获取操作按字节数而非编码边界停止,解码时会容忍输入在流中途截断:base64 会截至完整分组,未写完的 quoted-printable 转义序列会被丢弃,截断 UTF-8 序列留下的替换字符也会被去除。也支持 UTF-8 以外的字符集——实际邮件仍会使用 iso-8859-1。
无论发件人是否声明了标记语言,都会剥除标记,因为群发邮件发送方经常会在标记为 text/plain 的部分中放入 HTML 和样式表。实体字符和零宽预标题填充也会解码;如果预览内容只剩下标记残留,就会省略:没有预览也好过误导性的预览。
写入(9)
| 工具 | 描述 |
|---|---|
send_email | 发送新邮件(纯文本或 HTML,支持 CC/BCC) |
reply_email | 按正确的线程信息回复(In-Reply-To、References) |
forward_email | 转发邮件并引用原始内容 |
save_draft | 将邮件草稿保存到 Drafts 文件夹 |
send_draft | 发送现有草稿并从 Drafts 中移除 |
apply_template | 应用模板并替换变量 |
schedule_email | 预定邮件以供日后发送 |
list_scheduled | 按状态列出已预定的邮件 |
cancel_scheduled | 取消待发送的预定邮件 |
管理(7)
| 工具 | 描述 |
|---|---|
move_email | 在文件夹之间移动邮件 |
delete_email | 将邮件移至 Trash 或永久删除 |
mark_email | 将邮件标记为已读/未读、加旗标/取消旗标 |
bulk_action | 对最多 100 封邮件执行批量操作 |
create_mailbox | 创建新的邮箱文件夹 |
rename_mailbox | 重命名现有邮箱文件夹 |
delete_mailbox | 永久删除邮箱及其内容 |
标签(5)
| 工具 | 描述 |
|---|---|
list_labels | 查找可用标签(自动检测服务商策略) |
add_label | 为邮件添加标签(ProtonMail 文件夹、Gmail X-GM-LABELS 或 IMAP 关键字) |
remove_label | 从邮件中移除标签 |
create_label | 创建新标签 |
delete_label | 删除标签 |
监视器与提醒(6)
| 工具 | 描述 |
|---|---|
get_watcher_status | 显示 IMAP IDLE 连接、正在监视的文件夹以及最近查看的 UID |
list_presets | 列出可用的 AI 分流预设及其描述和建议标签 |
get_hooks_config | 显示当前 hooks 配置——预设、规则和自定义说明 |
configure_alerts | 在运行时更新提醒/通知设置 |
check_notification_setup | 诊断桌面通知支持情况并提供设置说明 |
test_notification | 发送测试通知,以验证操作系统权限是否已配置 |
验证(3)
| 工具 | 描述 |
|---|---|
get_verification_code | 查找最新的 OTP/2FA 验证码或登录魔法链接(或等待最多 45 秒),可选复制到剪贴板 |
check_clipboard_setup | 诊断剪贴板集成情况(平台工具、隐蔽写入支持),可选执行往返测试 |
configure_verification | 在运行时更新验证捕获设置(包括启动/停止捕获器),可选保存到配置文件 |
日历与提醒(8)
| 工具 | 描述 |
|---|---|
extract_calendar | 从电子邮件中提取 ICS/iCalendar 事件 |
analyze_email_for_scheduling | 分析电子邮件,检测事件及值得设置提醒的内容 |
add_to_calendar | 将电子邮件中的事件添加到本地日历(macOS Calendar.app;在 Linux 上会通过 xdg-open 打开 .ics 文件);事件备注会链接回源电子邮件 |
create_reminder | 根据电子邮件在 macOS Reminders.app 中创建提醒;提醒备注会链接回源电子邮件 |
list_calendars | 列出所有可用的本地日历(macOS Calendar.app;其他平台显示单个占位项) |
check_calendar_permissions | 检查是否可以访问本地日历(macOS 会实际探测;其他平台始终报告可访问) |
list_events | 按日期范围列出本地日历中的事件(仅限 macOS;其他平台返回空结果) |
list_reminders | 列出 Reminders.app 中的提醒(仅限 macOS) |
提示词(7)
| 提示词 | 描述 |
|---|---|
triage_inbox | 对未读电子邮件进行分类和优先级排序,并提供建议操作 |
summarize_thread | 总结电子邮件对话线程 |
compose_reply | 起草结合上下文的电子邮件回复 |
draft_from_context | 根据提供的上下文和指示撰写新邮件 |
extract_action_items | 从电子邮件线程中提取可执行任务 |
summarize_meetings | 总结电子邮件中的即将举行的日历事件 |
cleanup_inbox | 建议归档、删除或取消订阅哪些电子邮件 |
资源(6)
| 资源 | URI | 描述 |
|---|---|---|
| Accounts | email://accounts | 已配置账户列表 |
| Mailboxes | email://{account}/mailboxes | 账户的文件夹树 |
| Unread | email://{account}/unread | 未读电子邮件摘要 |
| Templates | email://templates/{name} | 按名称指定的一封电子邮件模板;该资源会列出可用名称 |
| Stats | email://{account}/stats | 电子邮件统计快照 |
| Scheduled | email://scheduled | 待发送的定时邮件 |
提供商自动检测
| 提供商 | 域名 |
|---|---|
| Gmail | gmail.com、googlemail.com |
| Outlook / Hotmail | outlook.com、hotmail.com、live.com、outlook.de、outlook.co.uk |
| Yahoo Mail | yahoo.com、yahoo.co.uk、yahoo.de、ymail.com |
| iCloud | icloud.com、me.com、mac.com |
| Fastmail | fastmail.com、fastmail.fm |
| ProtonMail Bridge | proton.me、protonmail.com、protonmail.ch、pm.me |
| Zoho Mail | zoho.com、zohomail.com |
| GMX | gmx.com、gmx.de、gmx.net、gmx.at、gmx.ch |
架构
src/
├── main.ts — Entry point and subcommand routing
├── server.ts — MCP server factory
├── logging.ts — MCP protocol logging bridge
├── cli/ — Interactive CLI commands
│ ├── account-commands.ts — Account CRUD (list, add, edit, delete)
│ ├── setup.ts — Legacy setup alias → account add
│ ├── test.ts — Connection tester
│ ├── config-commands.ts — Config management (show, edit, path, init)
│ ├── install-commands.ts — MCP client registration (install, status, remove)
│ ├── cache-commands.ts — Local-mirror CLI (status, clear, verify)
│ └── scheduler.ts — Scheduler CLI
├── config/ — Configuration layer
│ ├── xdg.ts — XDG Base Directory paths
│ ├── schema.ts — Zod validation schemas
│ ├── providers.ts — Provider auto-detection + OAuth2 endpoints (experimental)
│ └── loader.ts — Config loader (TOML + env vars)
├── cache/ — Local SQLite mirror
│ ├── schema.ts — Mirror schema + migrations
│ ├── store.ts — Read/write API over the mirror
│ └── sync-engine.ts — Background reconcile + body backfill
├── connections/
│ └── manager.ts — Lazy persistent IMAP/SMTP with OAuth2 (experimental)
├── services/ — Business logic
│ ├── imap.service.ts — IMAP operations
│ ├── label-strategy.ts — Provider-aware label strategy (ProtonMail/Gmail/IMAP keywords)
│ ├── smtp.service.ts — SMTP operations
│ ├── template.service.ts — Email template engine
│ ├── oauth.service.ts — OAuth2 token management (experimental)
│ ├── calendar.service.ts — ICS/iCalendar parsing
│ ├── scheduler.service.ts — Email scheduling queue
│ ├── watcher.service.ts — IMAP IDLE real-time watcher with auto-reconnect
│ ├── hooks.service.ts — AI triage via MCP sampling + static rules + auto-labeling/flagging
│ ├── notifier.service.ts — Multi-channel notification dispatcher (desktop/sound/webhook)
│ ├── clipboard.service.ts — Concealed clipboard writes for caught codes (zero deps)
│ ├── dialog.service.ts — Native confirm dialogs + browser hand-off (macOS)
│ ├── verification-catcher.service.ts — Instant OTP/magic-link catch on new mail
│ ├── presets.ts — Built-in hook presets (inbox-zero, gtd, priority-focus, etc.)
│ └── event-bus.ts — Typed EventEmitter for internal email events
├── tools/ — MCP tool definitions (52)
├── prompts/ — MCP prompt definitions (7)
├── resources/ — MCP resource definitions (6)
├── safety/ — Audit trail and rate limiter
└── types/ — Shared TypeScript types
路线图
这里记录了已提出但有意暂不实现的想法,以免遗失或被悄悄重新提议:
- 将 AgentMail 作为替代提供商。 AgentMail
提供仅需 API 密钥的程序化
@agentmail.to收件箱,无需设置 IMAP/SMTP 主机、端口、TLS 或凭据,适合快速创建临时的 Agent 自有地址。这会作为补充方案 (与实际的 IMAP/SMTP 账户并存,而非取而代之),但这是产品/架构决策——会引入新的 供应商依赖和工具范围——而非错误修复或功能补缺,因此暂列于此,而不自动构建。 如果确实有人需要由 Agent 配置的收件箱,而不是访问现有邮箱,可以重新考虑。
维护者
发布前提
release.yml 会在发布任何内容前检查这些项目,因此缺少其中任何一项都会快速失败,而不是发布一半后才失败:
| 密钥 | 用途 |
|---|---|
GORELEASER_KEY | GoReleaser Pro 许可证 — .goreleaser.yaml 使用仅限 Pro 的键(includes、variables),OSS 会拒绝整个配置 |
HOMEBREW_TAP_TOKEN | 在 codefuturist/homebrew-tap 上具有 contents:write 权限的 PAT;默认的 GITHUB_TOKEN 无法推送到其他仓库 |
NPM_TOKEN | 发布到 npm |
DOCKERHUB_USERNAME / DOCKERHUB_TOKEN | 推送到 Docker Hub(GHCR 使用 GITHUB_TOKEN) |
Homebrew cask 会分发未签名的 Bun 二进制文件,因此其 postflight 会清除 macOS 隔离标记 — 仅限 macOS,因为 Linux 没有 xattr(1),而 cask DSL 的 system_command 会在退出码非零时引发错误。brew uninstall --zap 会删除配置、状态、缓存和数据目录,以及两个启动代理。
贡献
欢迎提交 PR。编辑此 README 时,请遵循 standard-readme 规范。
# Development workflow
pnpm install
pnpm typecheck # type check
pnpm check # lint and format
pnpm build # build
pnpm start # run
测试
pnpm test # unit tests
pnpm test:integration # against a throwaway GreenMail server (Docker required)
pnpm smoke # most MCP tools against a real configured account (see caveats below)
集成测试套件会针对临时启动的 GreenMail 服务(通过 Testcontainers 启动)运行每个工具。附件测试(email-attachments.integration.test.ts)会驱动真实的 MCP 工具层,并锁定大小感知契约:每次发送都会报告每个文件的大小以及原始大小≈Base64 总大小;上限按编码后的总大小(即实际传输的数据量)执行;超过上限的发送会安全失败(不会投递任何内容);转发会携带原始附件,除非设置 includeAttachments: false。有效上限按账户解析:如果明确设置了账户级 max_attachment_mb,则优先使用该值;否则采用全局 [settings.send] 上限与提供商公布上限中较严格的值(Gmail、Yahoo 和 Proton 为 25 MB;Outlook.com、iCloud 和 GMX 为 20 MB;Fastmail 为 50 MB)。
pnpm smoke 会像客户端一样通过 stdio 驱动所有工具,从而覆盖 GreenMail 无法涵盖的内容:提供商特有行为、真实世界的 MIME,以及 macOS Calendar 桥接。它需要可用的账户,因此不属于 CI。写入操作仅限于临时文件夹和它自行创建的草稿;不会触碰 Calendar、Reminders、通知或 reply_email,后者会向真实联系人发送邮件。传入 E2E_ACCOUNT=<name> 可选择账户,否则使用配置的第一个账户。
许可证
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。