mcp服务器电子邮件
    
快速开始
- 安装
go install github.com/boutquin/mcp-server-email/cmd/mcp-server-email@latest- 创建配置文件 (
~/.config/mcp-email/accounts.json)
对于知名提供商(Gmail、Outlook、Yahoo、iCloud、Fastmail、Zoho),主机和端口会从电子邮件域中自动检测到——只需提供凭据:
[
{
"id": "hello",
"email": "hello@gmail.com",
"username": "hello@gmail.com",
"password": "app-password-here"
}
]对于自定义邮件服务器,请明确指定主机和端口:
[
{
"id": "work",
"email": "hello@example.com",
"imap_host": "mail.example.com",
"imap_port": 993,
"smtp_host": "mail.example.com",
"smtp_port": 465,
"username": "hello@example.com",
"password": "app-password-here"
}
] chmod 600 ~/.config/mcp-email/accounts.json- 添加到克劳德代码 (
~/.claude.json)
{
"mcpServers": {
"email": {
"command": "mcp-server-email",
"env": {
"EMAIL_CONFIG_FILE": "~/.config/mcp-email/accounts.json"
}
}
}
}- 重新启动Claude代码 --the
email_*工具现在可用。
安装
Go安装(推荐给Go开发人员)
go install github.com/boutquin/mcp-server-email/cmd/mcp-server-email@latest自制(macOS/Linux)
brew install boutquin/tap/mcp-server-email二进制下载
从下载适用于您平台的预构建二进制文件 .
适用于:Linux(amd64、arm64)、macOS(amd64arm64)和Windows(amd64/arm64)。
码头工人
docker run --rm \
-e EMAIL_ACCOUNTS='[{"id":"main","email":"user@example.com","imap_host":"mail.example.com","imap_port":993,"smtp_host":"mail.example.com","smtp_port":465,"username":"user@example.com","password":"app-password"}]' \
ghcr.io/boutquin/mcp-server-email:latestMCP捆绑包(克劳德桌面版)
下载 .mcpb 文件来自 发布 并在Claude Desktop中打开。
从源代码构建
git clone https://github.com/boutquin/mcp-server-email.git
cd mcp-server-email
go build -o mcp-server-email ./cmd/mcp-server-email配置
帐户在启动时加载一次。更改需要重新启动服务器。
配置文件与环境变量
| 方法 | 最适合 |
|---|---|
EMAIL_CONFIG_FILE --JSON文件的路径 | 生产使用。文件可以被权限锁定(chmod 600) |
EMAIL_ACCOUNTS --env-var中的内联JSON | 测试、CI或容器化部署 |
如果两者都被设置, EMAIL_ACCOUNTS 优先。
帐户JSON模式
[
{
"id": "hello",
"email": "hello@example.com",
"imap_host": "mail.example.com",
"imap_port": 993,
"smtp_host": "mail.example.com",
"smtp_port": 465,
"username": "hello@example.com",
"password": "app-password-here"
}
]| 字段 | 必填 | 描述 |
|---|---|---|
id | 是 | 唯一帐户标识符 |
email | 是 | 电子邮件地址 |
imap_host | 否\* | IMAP服务器主机名 |
imap_port | 无\* | IMAP端口(993=隐式TLS,143=STARTTLS) |
smtp_host | 否\* | SMTP服务器主机名 |
smtp_port | 无\* | SMTP端口(465=隐式TLS,587=STARTTLS) |
username | 是 | 登录用户名 |
password | 是\*\* | 应用程序密码或帐户密码 |
use_starttls | 否 | 覆盖TLS自动检测(true/false) |
insecure_skip_verify | 否 | 跳过TLS证书验证(开发/测试) |
auth_method | 没有 | "password" (默认)或 "oauth2" |
oauth_client_id | 否 | OAuth2客户端ID(需要时 auth_method 是 "oauth2") |
oauth_client_secret | 否 | OAuth2客户端机密 |
oauth_token_file | 否 | 覆盖令牌文件路径 |
\*对于知名提供商,会自动检测主机和端口(见下文)。自定义服务器需要。 \*\*使用OAuth2身份验证时不需要。
提供商自动检测
当 imap_host/smtp_host 如果省略,服务器将检测电子邮件域中的设置:
| 提供商 | 域 | IMAP | SMTP |
|---|---|---|---|
| Gmail | gmail.com, googlemail.com | imap.gmail.com:993 | smtp.gmail.com:587 |
| 展望 | outlook.com, hotmail.com, live.com | outlook.office365.com:993 | smtp.office365.com:587 |
| 雅虎 | yahoo.com | imap.mail.yahoo.com:993 | smtp.mail.yahoo.com:587 |
| icloud | icloud.com, me.com, mac.com | imap.mail.me.com:993 | smtp.mail.me.com:587 |
| 快速邮件 | fastmail.com, fastmail.fm | imap.fastmail.com:993 | smtp.fastmail.com:587 |
| 佐霍 | zoho.com, zohomail.com | imap.zoho.com:993 | smtp.zoho.com:587 |
配置中的显式主机/端口始终优先于自动检测。
TLS模式
从端口自动检测TLS模式:
| 端口 | 协议 | 模式 |
|---|---|---|
| 993 | IMAP | 隐式TLS |
| 143 | IMAP | STARTTLS |
| 465 | SMTP | 隐式TLS |
| 587 | SMTP | STARTTLS |
覆盖 "use_starttls": true 或 "use_starttls": false 在account对象中。省略自动检测(推荐)。
OAuth2身份验证
对于支持它的提供商(Gmail、Outlook),您可以使用OAuth2而不是应用程序密码。这使用设备代码流(RFC 8628)——不需要浏览器重定向。
- 创建OAuth2凭据 在提供商的开发人员控制台(谷歌云控制台或Azure AD)中
- 配置帐户 随着
auth_method: "oauth2":
[
{
"id": "gmail",
"email": "user@gmail.com",
"username": "user@gmail.com",
"auth_method": "oauth2",
"oauth_client_id": "your-client-id.apps.googleusercontent.com",
"oauth_client_secret": "your-client-secret"
}
]- 首次连接时,服务器启动设备代码流——将验证URL和代码打印到stderr。访问URL并输入代码进行授权。
- 令牌被持久化 在
~/.config/mcp-email/tokens/并自动刷新。后续连接在没有重新授权的情况下重用存储的令牌。
支持的OAuth2提供程序: Gmail (gmail.com, googlemail.com)以及 展望 (outlook.com, hotmail.com, live.com).
环境变量
| 变量 | 必填 | 默认 | 描述 |
|---|---|---|---|
EMAIL_CONFIG_FILE | 是\* | -- | JSON配置文件的路径 |
EMAIL_ACCOUNTS | 是\* | -- | JSON帐户配置数组(内联) |
EMAIL_DEFAULT_ACCOUNT | 否 | 第一个帐户 | 默认帐户ID |
EMAIL_IMAP_TIMEOUT_MS | 没有 | 30000 | IMAP操作超时(毫秒) |
EMAIL_SMTP_TIMEOUT_MS | 没有 | 30000 | SMTP操作超时(毫秒) |
EMAIL_IMAP_RATE_LIMIT | 没有 | 60 | IMAP请求/分钟/帐户 |
EMAIL_SMTP_RATE_LIMIT | 没有 | 100 | SMTP发送/小时/帐户 |
MAX_ATTACHMENT_SIZE_MB | 没有 | 18 | 每个附件的最大大小(MB) |
MAX_TOTAL_ATTACHMENT_SIZE_MB | 没有 | 18 | 每封邮件的最大总附件大小(MB) |
MAX_DOWNLOAD_SIZE_MB | 没有 | 25 | 最大附件下载大小(MB) |
EMAIL_POOL_CLOSE_TIMEOUT_MS | 没有 | 5000 | 池关闭超时(ms) |
EMAIL_DEBUG | 没有 | false | 将日志记录调试到stderr |
LOG_LEVEL | 没有 | info | 日志级别: debug, info, warn, error |
LOG_FORMAT | 没有 | json | 日志格式: json 或 text |
\*其中之一 EMAIL_CONFIG_FILE 或 EMAIL_ACCOUNTS 是必需的。
配置文件权限
配置文件包含帐户密码。始终限制访问:
chmod 600 ~/.config/mcp-email/accounts.json工具(22)
帐户和文件夹工具
| 工具 | 描述 | 关键参数 |
|---|---|---|
email_accounts | 列出已配置的帐户及其连接状态 | -- |
email_folders | 列出所有未读/总计数的文件夹 | account? |
email_folder_create | 创建新文件夹 | name, account? |
邮件列表
| 工具 | 描述 | 关键参数 |
|---|---|---|
email_list | 列出文件夹中的邮件 | folder?, limit?, offset?, includeBody?, account? |
email_unread | 列出未读邮件 | folder?, limit?, includeBody?, account? |
email_search | 搜索主题和正文 | query, from?, to?, since?, before?, folder?, limit?, includeBody?, account? |
消息操作
| 工具 | 描述 | 关键参数 |
|---|---|---|
email_get | 按ID获取完整消息 | id |
email_read_body | 读取带有分页的电子邮件正文 | id, offset?, limit?, format? |
email_move | 将邮件移动到文件夹 | id, destination |
email_copy | 将邮件复制到文件夹 | id, destination |
email_delete | 删除邮件(垃圾或永久删除) | id, permanent? |
email_mark_read | 标记为已读/未读 | id, read |
email_flag | 标志/非标志信息 | id, flagged |
email_reply | 回复邮件(设置“回复对象”、“引用”、引用正文) | id, body, all?, cc?, bcc?, isHtml?, account? |
email_forward | 转发邮件(重新附加原始附件) | id, to, body?, cc?, bcc?, isHtml?, account? |
email_batch | 对多条消息进行批量操作 | action, ids, destination?, permanent?, read?, flagged? |
附件和螺纹
| 工具 | 描述 | 关键参数 |
|---|---|---|
email_attachment_list | 列出邮件中的附件 | id |
email_attachment_get | 按索引下载附件 | id, index, saveTo? |
email_thread | 获取对话线索(在收件箱、已发送、存档和所有邮件中搜索) | id |
发送草稿
| 工具 | 描述 | 关键参数 |
|---|---|---|
email_send | 通过SMTP发送,附带可选附件 | to, subject, body, cc?, bcc?, replyTo?, isHtml?, attachments?, account? |
email_draft_create | 保存带有可选附件的草稿 | to?, subject?, body?, cc?, bcc?, isHtml?, attachments?, account? |
email_draft_send | 发送现有草稿 | id |
全部可选 account params默认为配置的默认帐户。
搜索
email_search 搜索两者 主体与身体 使用IMAP SEARCH OR (SUBJECT "q") (BODY "q").
可选过滤器在身体扫描之前缩小服务器端的候选集:
| 筛选器 | 格式 | 示例 |
|---|---|---|
from | 电子邮件地址或姓名 | "alice@example.com" |
to | 电子邮件地址或姓名 | "bob@example.com" |
since | YYYY-MM-DD | "2026-01-01" |
before | YYYY-MM-DD | "2026-02-01" |
现有的操作超时(默认为30秒)阻止对大型邮箱进行挂起体搜索。
附件
email_send 和 email_draft_create 接受a attachments 参数——服务器主机上的文件引用数组:
{
"attachments": [
{"path": "/tmp/report.pdf"},
{"path": "/tmp/data.csv", "filename": "Q1-data.csv", "content_type": "text/csv"}
]
}| 参数 | 必填 | 说明 |
|---|---|---|
path | 是 | 服务器主机上的绝对文件路径 |
filename | 否 | 覆盖显示文件名(默认为basename path) |
content_type | 否 | MIME类型(如果省略,则从文件扩展名中自动检测) |
限制(默认值): 每个文件18 MB,总共18 MB(预base64编码;编码后保持在25 MB SMTP上限以下)。可通过以下方式配置 MAX_ATTACHMENT_SIZE_MB 和 MAX_TOTAL_ATTACHMENT_SIZE_MB 环境变量。
下载限制: 附件下载(email_attachment_get)默认情况下上限为25 MB,可通过以下方式配置 MAX_DOWNLOAD_SIZE_MB.
验证失败(丢失文件、非绝对路径、超出大小)返回 INVALID_ARGUMENT.
消息ID
邮件ID是编码帐户、邮箱和UID的复合字符串:
{account}:{mailbox}:{uid}例子: hello:INBOX:12345
所有CRUD工具(email_get, email_move, email_copy, email_delete, email_mark_read, email_flag, email_draft_send)从ID中提取帐户和文件夹——不需要单独的参数。
错误代码
所有错误均作为MCP工具错误返回,并带有结构化代码前缀:
| 代码 | 含义 |
|---|---|
AUTH_FAILED | IMAP/SMTP身份验证失败 |
CONNECTION_FAILED | 无法连接到服务器 |
ACCOUNT_NOT_FOUND | 未知帐户ID |
FOLDER_NOT_FOUND | 邮箱不存在 |
MESSAGE_NOT_FOUND | 在邮箱中找不到UID |
INVALID_ARGUMENT | 参数缺失/无效(包括附件验证) |
TIMEOUT | 操作超时 |
INTERNAL | 意外的服务器错误 |
资源
| URI | 描述 |
|---|---|
email://status | 服务器版本、帐户连接状态、速率限制配置 |
与苹果桥的比较
此服务器和 苹果桥 分享A Email 模型和参数语义(limit, includeBody, folder, query)因此LLM可以与两者互换使用。主要区别:
| 方面 | mcp服务器电子邮件 | apple bridge |
|---|---|---|
| 传输 | IMAP/SMTP(远程) | Mail.app(本地) |
| 工具前缀 | email_* | mail_* |
| 消息ID | {account}:{mailbox}:{uid} | RFC 5322消息ID |
| 文件夹创建 | 支持 | 不支持(Mail.app需要用户界面) |
| 复制邮件 | 支持 | 不支持 |
| 草稿发送 | 支持 | 不支持(Mail.app使用撰写UI) |
| 附件(发送) | 服务器主机上的文件路径 | 尚不支持 |
发展
先决条件
构建
go build ./...单元测试
make test
# or: go test -race -count=1 ./...单元测试使用模拟实现 imap.Operations 和 smtp.Operations 接口——不需要实时邮件服务器。
基准测试
go test -bench=. -benchmem ./...| 基准 | 包 | 它衡量什么 |
|---|---|---|
BenchmarkPoolGetRelease | imap | 连接池获取/释放周期 |
BenchmarkExtractAttachments | imap | MIME附件提取 |
BenchmarkHtmlToText | tools | HTML到纯文本转换 |
BenchmarkLimiterAllow | retry | 速率限制器(顺序) |
BenchmarkLimiterAllow_Parallel | retry | 速率限制器(并发) |
模糊测试
Fuzz使用种子语料库瞄准舰船 testdata/fuzz/ 目录。运行特定目标:
go test -fuzz=FuzzParseMessageID ./internal/models/ -fuzztime=30s| 目标 | 包 | 它模糊了什么 |
|---|---|---|
FuzzBuildSearchCriteria | imap | IMAP搜索查询生成器 |
FuzzExtractAttachmentByIndex | imap | 附件索引边界处理 |
FuzzExtractContentType | imap | MIME内容类型解析器 |
FuzzParseMessageID | models | 复合消息ID编解码器 |
FuzzHtmlToText | tools | HTML到文本清理程序 |
FuzzSplitAddresses | tools | 电子邮件地址列表拆分器 |
棉绒
make lint
# or: golangci-lint run ./...集成测试
集成测试针对真实的邮件服务器执行完整的IMAP/SMTP堆栈。他们被隔离在后面 integration 构建标签和 永远不要跑 在...期间 go test ./....
邮件服务器:Greenmail
测试使用 绿色邮件,一个打包为Docker镜像的轻量级Java邮件服务器。影响运行方式的关键细节:
| 设置 | 价值 | 为什么重要 |
|---|---|---|
| IMAPS端口 | 3993 | Greenmail的SSL IMAP端口(不是993)。代码会自动从端口号检测TLS,因此测试会显式设置 UseStartTLS=false 在此非标准端口上强制隐式TLS |
| SMTPS端口 | 3465 | Greenmail的SSL SMTP端口(不是465)。相同 UseStartTLS=false 以(权力)否决 |
| 绑定地址 | 0.0.0.0 | Greenmail默认为 127.0.0.1 *集装箱内*,这使得Docker端口映射无声地失败(连接得到EOF)。你 必须 通过 -Dgreenmail.hostname=0.0.0.0. |
| 用户名 | test | Greenmail使用 *仅本地部分* (之前 @)作为登录用户名,而不是完整的电子邮件地址。如果用户是 test@example.com,IMAP/SMTP用户名为 test. |
| TLS证书 | 自签名 | Greenmail生成自签名证书。测试集 InsecureSkipVerify: true 在帐户配置中接受它们。 |
快速启动(一个命令)
make test-integration这将启动一个Greenmail容器,运行所有集成测试,然后拆除容器——无论通过/失败。
手动分步
如果你需要在不每次重新启动容器的情况下迭代测试:
- 启动Greenmail
docker run -d --name greenmail \
-p 3465:3465 -p 3993:3993 \
-e "GREENMAIL_OPTS=-Dgreenmail.setup.test.all -Dgreenmail.users=test:password@example.com -Dgreenmail.hostname=0.0.0.0" \
greenmail/standalone:2.1.0等待约3秒,让JVM启动。
- 运行集成测试
TEST_IMAP_HOST=localhost TEST_IMAP_PORT=3993 \
TEST_SMTP_HOST=localhost TEST_SMTP_PORT=3465 \
TEST_EMAIL=test@example.com TEST_PASSWORD=password \
go test -tags=integration -race -v ./...- 拆除 完成后
docker stop greenmail && docker rm greenmail测试环境变量
| 变量 | 必填 | 默认 | 描述 |
|---|---|---|---|
TEST_IMAP_HOST | 是\* | -- | IMAP服务器主机名。如果未设置,则跳过测试。 |
TEST_IMAP_PORT | 没有 | 3993 | IMAPS端口 |
TEST_SMTP_HOST | 是\* | -- | SMTP服务器主机名。如果未设置,则跳过测试。 |
TEST_SMTP_PORT | 没有 | 3465 | SMTPS端口 |
TEST_EMAIL | 没有 | test@example.com | 测试帐户的电子邮件地址 |
TEST_USERNAME | 否 | 本地部分 TEST_EMAIL | IMAP/SMTP登录用户名(Greenmail仅使用本地部分) |
TEST_PASSWORD | 没有 | password | 帐户密码 |
\*如果对应 HOST 变量未设置,则跳过该测试文件的测试并显示消息(未失败)。
测试涵盖哪些内容
互联网消息访问协议 (internal/imap/integration_test.go --7次测试):
| 测试 | 它验证了什么 |
|---|---|
ConnectAndListFolders | TLS连接、身份验证、文件夹列表、收件箱存在 |
SendAndListMessages | SMTP发送→ IMAP接收往返,正文内容匹配 |
SearchBySubject | 按主题字符串进行IMAP搜索 |
DeleteMessagePermanent | 标记为已删除+删除,验证消息已消失 |
MoveMessage | IMAP移动到另一个文件夹(如果服务器缺少MOVE扩展名,则跳过) |
DraftWorkflow | 保存草稿→ GetDraft→ DeleteDraft生命周期(如果没有APPENDUID,则跳过) |
MarkReadAndFlag | 设置读取/标记标志,通过GetMessage进行验证 |
SMTP (internal/smtp/integration_test.go --4次测试):
| 测试 | 它验证了什么 |
|---|---|
SendPlainText | 纯文本电子邮件传递,通过IMAP验证正文内容 |
SendHTML | HTML电子邮件传递,内容类型验证为 text/html |
SendWithAttachment | 带附件的多部分MIME,在元数据中验证文件名 |
RateLimitTokenConsumption | 发送会消耗速率限制令牌 |
故障排除
| 症状 | 原因 | 修复 |
|---|---|---|
EOF 或 connection reset 已连接 | Greenmail已绑定 127.0.0.1 容器内 | 添加 -Dgreenmail.hostname=0.0.0.0 到 GREENMAIL_OPTS |
TLS handshake failure /证书错误 | 自签名证书被拒绝 | 测试配置已设置 InsecureSkipVerify: true --如果编写新的测试,也要这样做 |
Invalid login/password | 使用完整电子邮件作为用户名 | Greenmail只需要本地部分(test,不 test@example.com).集 TEST_USERNAME 或者让它默认。 |
STARTTLS 端口3993上出错 | 在隐式TLS端口上使用STARTTLS | 测试配置集 UseStartTLS=false。不要使用端口3143/3025(纯端口,无TLS)。 |
| 测试以“未设置”跳过 | TEST_IMAP_HOST / TEST_SMTP_HOST 未导出 | 导出环境变量或使用 make test-integration 目标 |
MoveMessage 测试跳过 | Greenmail可能不支持MOVE | 预期--测试使用 t.Skip() |
持续集成
集成测试通过以下方式在GitHub Actions中自动运行 integration 工作中 .github/workflows/ci.yml。该作业使用Greenmail服务容器,无需手动设置Docker。有关确切的配置,请参阅工作流文件。
覆盖
要生成组合单元+集成覆盖率报告:
# With Greenmail running (see above):
TEST_IMAP_HOST=localhost TEST_IMAP_PORT=3993 \
TEST_SMTP_HOST=localhost TEST_SMTP_PORT=3465 \
TEST_EMAIL=test@example.com TEST_PASSWORD=password \
go test -tags=integration -race -coverprofile=coverage.out ./...
go tool cover -func=coverage.out | tail -1 # total percentage
go tool cover -html=coverage.out # open in browser建筑
mcp-server-email/
├── cmd/mcp-server-email/ # Entry point
└── internal/
├── auth/ # OAuth2 device code flow, XOAUTH2 SASL, token store
├── config/ # Multi-account configuration, provider auto-detection
├── imap/ # IMAP client (split by concern), connection pool, Operations interface
│ ├── client.go # Client struct, lifecycle, shared helpers
│ ├── client_messages.go # List, search, get, attachments
│ ├── client_folders.go # Folder ops, role cache
│ ├── client_drafts.go # Draft save/get/delete
│ ├── client_flags.go # Flags, move, copy, delete
│ └── pool.go # Connection pool with configurable close timeout
├── log/ # Structured logging (slog) initialization
├── models/ # Email model, message ID codec, error types
├── resources/ # email://status resource
├── retry/ # Token-bucket rate limiter
├── smtp/ # SMTP client, Operations interface
└── tools/ # 22 MCP tool handlers + registration工具处理程序通过以下方式与IMAP/SMTP客户端解耦 imap.Operations 和 smtp.Operations 接口,支持使用模拟进行全面的单元测试。
依赖项
此项目使用 go imap v2 (目前为v2.0.0-beta.8)。 v2 API还不稳定-在v2.0.0版本之前可能会发生突破性的变化。 我们确定了确切的版本 go.mod 并在稳定版发布后迅速升级。
