关于 SMTP
SMTP 是通过已配置 SMTP 账户发送邮件的 MCP 服务。发送功能默认关闭,需明确启用;收件人受白名单限制,每封邮件都需人工批准。
主要功能
- 01撰写和预览邮件
- 02发送、回复和转发邮件
- 03通过白名单限制收件人
- 04发送前要求人工批准
- 05使用固定发件地址
- 06配置 TLS 和发送限制
适用场景
- 01发送前预览邮件
- 02向允许的收件人发送已批准邮件
- 03经确认后回复或转发邮件
MCP 相关
向 MCP 客户端提供 SMTP 配置检查、收件人验证、邮件预览、连接测试,以及启用发送后可用的发送、回复和转发工具。发送工具默认关闭,每封邮件均需人工批准。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
npx -y @ni-c/smtp-mcpSMTP_HOSTHostname of the SMTP server, e.g. smtp.example.net.SMTP_PORTPort. Defaults to 587 for starttls, 465 for implicit, 25 for none.SMTP_TLSstarttls (default), implicit or none. STARTTLS is required, never opportunistic.SMTP_USERUsername for SMTP authentication.SMTP_PASSWORD密钥Password or app-specific password for SMTP authentication.SMTP_FROMThe only sender this server will use, e.g. "Name <[email protected]>". There is no from parameter.SMTP_REPLY_TOReply-To header on every message, e.g. "Team <[email protected]>". Unset means no Reply-To header and replies go to SMTP_FROM. There is no reply_to parameter.SMTP_ALLOW_SENDSet to "true" to register the sending tools. Defaults to false: the server cannot send until it is set.SMTP_ALLOWED_RECIPIENTSComma-separated addresses and @domains this server may write to. Required with SMTP_ALLOW_SEND=true; "*" allows any.SMTP_MAX_RECIPIENTSMaximum distinct recipients across To, Cc and Bcc in one message. Default 10.SMTP_MAX_SENDS_PER_HOURSliding hourly cap on messages sent. Default 20.SMTP_MAX_MESSAGE_BYTESMaximum size of the composed message. Default 10485760.SMTP_MAX_ATTACHMENT_BYTESMaximum size of a single attachment. Default 5242880.SMTP_ATTACHMENT_DIRDirectory attachments are read from. Unset means attachments are unavailable.SMTP_ATTACHMENT_TYPESComma-separated content types that may be attached. Defaults to a document and image allowlist.SMTP_SIGNATUREText appended below the standard signature delimiter of every message.SMTP_AUDIT_LOGFile the audit lines are appended to, in addition to stderr.SMTP_ALLOW_TOOLSComma-separated tool names, a prefix with one trailing *, or "essential" for the curated preset.SMTP_DENY_TOOLSComma-separated tool names or prefixes to remove, applied after SMTP_ALLOW_TOOLS.SMTP_INSECURE_TLSSet to "true" to accept self-signed certificates. Prefer a proper internal CA.本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
smtp-mcp
一个用于 SMTP 的模型上下文协议(MCP)服务。SMTP 是每个邮件服务都使用的协议,用于接收待投递的邮件。
它让 Claude Code、Claude Desktop 或 Codex 等 MCP 客户端能够从一个已配置的地址发送、回复和转发邮件,并由人工审批每封邮件。
七个工具是上限,而不是最低要求:设置 SMTP_ALLOW_TOOLS=essential 即可改为注册精选的五个工具。模型从五个工具中选择正确工具的可靠性远高于从七个中选择。请参阅选择要加载的工具。
## 特色
它会发送邮件。这就是它需要作为独立服务存在的原因。 它的对应项目 imap-mcp 负责读取邮箱,并且有意不提供发送任何内容的能力——这一限制本身就是它的全部安全依据,因为只有当 Agent 在能够访问私密数据并处理攻击者控制的内容时,同时还拥有向外发送的途径,才可能被利用。 本服务正是这个向外发送的途径,因此不能作出同样的安全承诺。它通过收窄通信渠道来证明自身价值,并运行在拥有独立凭据的独立进程中。
安装后默认关闭。 SMTP_ALLOW_SEND 默认值为 false。在设置该变量之前,发送工具根本不会注册——它们不会出现在 tools/list 中,而不是等到调用时才被拒绝。
它只能向你指定的人发送邮件。 必须设置 SMTP_ALLOWED_RECIPIENTS 才能启用发送功能。建立连接之前,系统会检查 To、Cc 和 Bcc 中的每个地址是否在允许列表内,因此,注入的“把这封邮件发给其他人”指令不会生效,服务器也不会将其当作指令来读取。允许所有收件人也是可以的,但必须明确写为 *。
每封邮件都必须经人批准。 批准者不是模型——请求会以 MCP elicitation 的形式发送给客户端。收件人、主题和任何 Bcc 内容都会各自在带标签的独立行中显示,因此,伪装成指令的主题不会被误认为是服务器自己的语句。
无法选择发件人。 没有 from 参数。如果模型可以自行选择发件人,就能冒用同事的名义发送邮件,收件人也无法分辨邮件是否真由该同事撰写。
要求
- Node.js 22 或更高版本
- 一个允许你发送邮件的 SMTP 账户——使用 587 或 465 端口的提交服务器,以及用户名和密码。启用了双重身份验证的服务商通常需要使用专用应用密码。
配置
请使用 TLS。
SMTP_TLS=starttls(默认值)要求先升级连接,而不是尝试升级;因此,如果STARTTLS能力被剥除,连接就会失败,而不会悄悄以明文发送密码。对于自签名证书,建议使用正规的内部 CA,而非SMTP_INSECURE_TLS。 | 变量 | 必填 | 默认值 | 说明 | | --------------------------- | --------------------------- | ---------------------------- | ------------------------------------------------------------------------------------------------- | |SMTP_HOST| 是 | — | SMTP 服务器的主机名,例如smtp.example.net。 | |SMTP_USER| 是 | — | SMTP 身份验证用户名。 | |SMTP_PASSWORD| 是 | — | 密码或应用专用密码。 | |SMTP_FROM| 是 | — | 唯一使用的发件人,例如Name <[email protected]>。没有from参数。 | |SMTP_REPLY_TO| 否 | — | 每封邮件的 Reply-To,例如Team <[email protected]>。未设置时,回复将发送至SMTP_FROM。 | |SMTP_PORT| 否 | 587 / 465 / 25 | 取决于SMTP_TLS。 | |SMTP_TLS| 否 |starttls|starttls、implicit或none。绝不使用机会式 TLS。 | |SMTP_ALLOW_SEND| 否 |false| 设置为true以注册发送工具。 | |SMTP_ALLOWED_RECIPIENTS| 设置SMTP_ALLOW_SEND=true时 | — | 以逗号分隔的地址和@域名。*表示允许任何收件人。 | |SMTP_MAX_RECIPIENTS| 否 |10| 单封邮件中 To、Cc 和 Bcc 的不同收件人数量。 | |SMTP_MAX_SENDS_PER_HOUR| 否 |20| 滑动每小时发送上限。 | |SMTP_MAX_MESSAGE_BYTES| 否 |10485760| 组装后邮件的大小上限。 | |SMTP_MAX_ATTACHMENT_BYTES| 否 |5242880| 单个附件的大小上限。 | |SMTP_ATTACHMENT_DIR| 否 | — | 读取附件的目录。未设置时不添加附件。 | |SMTP_ATTACHMENT_TYPES| 否 | 文档和图像白名单 | 以逗号分隔的可附加内容类型。text/html和application/zip需显式启用。 | |SMTP_SIGNATURE| 否 | — | 添加在标准--分隔符下方的文本。 | |SMTP_AUDIT_LOG| 否 | — | 追加审计日志行的文件;同时也会写入 stderr。 | |SMTP_ALLOW_TOOLS| 否 | — | 工具名称、末尾带一个*的前缀,或essential。 | |SMTP_DENY_TOOLS| 否 | — | 在应用SMTP_ALLOW_TOOLS后移除相应工具。 | |SMTP_INSECURE_TLS| 否 |false| 接受自签名证书。 | |ELICITATION| 否 |true|false会将审批对话框替换为两次调用令牌。不带前缀。 | 有两个默认设置值得再读一遍,因为它们与这一系列其他项目的做法恰恰相反:
SMTP_ALLOW_SEND默认关闭。 全新安装的 smtp-mcp 可以撰写和预览邮件,但无法发送任何邮件。- 未设置
SMTP_ALLOWED_RECIPIENTS会导致启动错误,而不是允许「任何人」。 把缺失的配置项当作授权,正是意外最终变成已发送邮件的原因。如果你确实想允许所有人,请写*。
选择加载哪些工具
SMTP_ALLOW_TOOLS 决定注册哪些工具,SMTP_DENY_TOOLS 会从中排除工具。两者都接受以逗号分隔的工具名称,或末尾带单个 * 的前缀。经过筛选的工具不会被构建——它不会出现在 tools/list 中,调用时会像发送功能关闭时的发送工具一样返回「未找到」。不会先公开工具,再拒绝调用。
SMTP_ALLOW_TOOLS=essential # the curated five
SMTP_ALLOW_TOOLS='get_server_info,preview_mail'
SMTP_DENY_TOOLS=forward_mail # everything else, minus forwarding
essential 包含 get_server_info、validate_recipients、preview_mail、send_mail 和
reply_mail。这里不包含 forward_mail:转发会将他人的内容和附件发给外部,因此它最值得经过深思熟虑后再启用。
如果某个条目与任何工具都不匹配,启动就会中止,并列出实际的工具名称。某个工具悄无声息地从 tools/list 中消失后,没人会追查它的缺失是否与环境变量有关。
安装
Claude Code
claude mcp add smtp -- npx -y @ni-c/smtp-mcp
Claude Desktop
{
"mcpServers": {
"smtp": {
"command": "npx",
"args": ["-y", "@ni-c/smtp-mcp"],
"env": {
"SMTP_HOST": "smtp.example.net",
"SMTP_USER": "[email protected]",
"SMTP_PASSWORD": "app-specific-password",
"SMTP_FROM": "Your Name <[email protected]>",
"SMTP_ALLOW_SEND": "true",
"SMTP_ALLOWED_RECIPIENTS": "@example.net"
}
}
}
}
Codex
[mcp_servers.smtp]
command = "npx"
args = ["-y", "@ni-c/smtp-mcp"]
[mcp_servers.smtp.env]
SMTP_HOST = "smtp.example.net"
SMTP_USER = "[email protected]"
SMTP_PASSWORD = "app-specific-password"
SMTP_FROM = "Your Name <[email protected]>"
SMTP_ALLOW_SEND = "true"
SMTP_ALLOWED_RECIPIENTS = "@example.net"
Docker
docker run --rm -i \
-e SMTP_HOST=smtp.example.net \
-e [email protected] \
-e SMTP_PASSWORD=app-specific-password \
-e SMTP_FROM='Your Name <[email protected]>' \
-e SMTP_ALLOW_SEND=true \
-e [email protected] \
ghcr.io/ni-c/smtp-mcp
通过 mcp-hub
无法启动本地进程的客户端——ChatGPT 连接器、Claude 网页版、Cursor、LibreChat——可以通过 mcp-hub 访问 smtp-mcp:一个容器通过 Streamable HTTP 为多个 stdio MCP 服务提供服务,并通过单个密码进行 OAuth 2.1 登录,同时为无法使用 OAuth 的客户端提供长期有效的令牌。其 /hub 端点通过六个元工具为每个服务提供访问入口,因此一个连接器就能访问所有服务,无需在模型上下文中加入 N 倍的工具架构;它也支持两个协议修订版本——本服务提出的问题会经由它传递给另一端的人。
它的 /config/mcp.json 使用 Claude Code 的格式,因此可以直接使用已有配置:
{
"mcpServers": {
"smtp-mcp": {
"command": "npx",
"args": ["-y", "@ni-c/smtp-mcp"],
"env": {
"SMTP_HOST": "smtp.example.net",
"SMTP_USER": "[email protected]",
"SMTP_PASSWORD": "…",
"SMTP_FROM": "Your Name <[email protected]>",
"SMTP_ALLOW_TOOLS": "essential"
},
"denyTools": ["send_mail", "reply_mail"]
}
}
}
其中的 allowTools 和 denyTools 是 mcp-hub 自己针对每个服务的筛选配置,与 env 中的 *_ALLOW_TOOLS 并不相同——两者的区别,以及由此可能导致的误用,都在客户端指南中。
工具
始终注册。以下工具都无法发送邮件。
| 工具 | 功能 |
|---|---|
get_server_info | 提供端点、固定发件人、允许列表、限制,以及发送功能是否开启。 |
validate_recipients | 提供本服务可以发送邮件的地址,以及其他地址被拒绝的原因。不会建立连接。 |
preview_mail | 构建与 send_mail 完全相同的邮件并展示出来。会运行发送邮件时的所有检查。 |
test_connection | 建立连接、协商 TLS、进行身份验证,然后断开连接。不会发送任何邮件;最多每 10 秒执行一次。 |
仅在 SMTP_ALLOW_SEND=true 时注册。👤 表示操作前会征求人工确认。
| 工具 | 功能 |
|---|---|
send_mail 👤 | 发送新邮件。 |
reply_mail 👤 | 发送回复,并将其归入原邮件的对话串;根据主题自动添加 Re: 。 |
forward_mail 👤 | 将邮件转发给新收件人,并逐字引用原邮件内容。 |
结构化输出
每个工具都会声明一个 outputSchema,并在文本块旁附带 structuredContent 作为响应,
这样客户端无需解析散文即可使用结果:
{
"sent": true,
"already_sent": false,
"message_id": "<b1c9…@example.net>",
"accepted": ["[email protected]", "[email protected]"],
"rejected": [],
"bytes": 1284,
"sends_remaining_this_hour": 9,
"note": "The SMTP server accepted the message. It cannot be recalled.",
}
preview_mail 是唯一带有 untrusted: true 和
source: "smtp" 字段的工具:引用的原文由发件人撰写,
而世界上的任何人都可以发送邮件。它的文本块保留了 nonce 围栏——
结构化部分会说明相同的字段,因此客户端无需解析这些字段。
这里的其他所有内容都报告此服务自身的配置或其发送操作的结果;如果加上该标记,
就会错误地声称内容的撰写者身份。
有意不提供的功能
from参数。 发件人只能是SMTP_FROM。- 跳过确认的方式。 没有
force,也没有“可信调用方”模式。关闭 确认门槛的选项会是提示注入最先尝试利用的东西。 - 读取邮件。 这由 imap-mcp 负责。将两者放在 独立进程中,并使用各自独立的凭据,是保障它们安全的关键所在。
- 任意标头。 线程处理使用
in_reply_to和references;不支持直接传递 标头名称,因为这无异于多绕几步的标头注入。 - DKIM 签名。 提交服务器会为你签名。将私有签名密钥放在环境变量中,实际风险比看起来更大。
安全
- 默认禁用发送,只有启用后工具才会出现。
- 在打开连接前,会将每位收件人都与允许列表核对,To、Cc 和 Bcc 收件人一视同仁。
- 每封邮件都必须由人工批准,通过 MCP elicitation 完成。双调用令牌回退机制 会明确说明它并不等同于人工批准。
- 确认与具体邮件绑定:使用排序后的收件人列表的 SHA-256 指纹和内容摘要, 因此不能将一份批准用于范围更广的收件人列表或不同的文本。
- 对话框会显示邮件内容,而不只是信封:正文、引用的原文和 HTML 部分,并分别显示字符数。这里的其他措施都用于约束邮件的收件人; 这一措施则用于约束邮件的内容。
- Bcc 收件人会在对话框中单独列出并标明。 人工看不到的隐藏收件人 是理想的数据外传渠道。
- 确认文本绝不会将调用方选择的值直接引用到服务自己的句子中。
- 同一封邮件不会发送两次。 批准只能证明有人同意发送某封邮件, 不能证明他们再次同意发送,因此,只要对应的批准仍有可能被兑换, 就会记住 SMTP 服务器已接受的邮件。
- 会清除外发 HTML 中的脚本、事件处理程序、远程加载的图像和不安全的 URL 方案——并报告每一项移除操作,绝不会静默处理。 对于无法确信能够清理的标记, 会直接拒绝,而不是尝试修复。
- 引用的原文会原样传递,并在对话框中列出其中匹配到的提示注入模式。
- 附件只能来自
SMTP_ATTACHMENT_DIR,且必须通过扩展名允许列表、符号链接拒绝 和魔数检查。 - 每封被接受的邮件都会记录到 stderr,并可选择写入文件。绝不记录正文。
关于背后的考量,以及这些措施未涵盖的内容,请参阅 SECURITY.md。
文档
完整指南、工具参考和安全说明请见
smtp-mcp.ni-c.de(源文件位于 docs/)。
开发
npm install
npm test
npm run build
test/integration/ 中有一个一次性 Mailpit 沙箱。请在其中开发,
而不要使用真实邮箱:此服务的职责是将邮件发送到网络上,而配置错误的
测试运行会将真实邮件发送给真实的人。
docker compose -f test/integration/compose.yml up -d --wait
npm run build && npm run test:integration
发布
在 main 上为 vX.Y.Z 打标签会运行发布工作流:检查标签是否与 package.json 一致,通过 Trusted Publishing 发布到 npm,将包含 SBOM 的多架构镜像推送到 GHCR,根据 CHANGELOG 中的章节创建 GitHub 发布,并将该版本提交到 MCP Registry。
贡献
欢迎提交问题、参与讨论和发起拉取请求——请参阅 CONTRIBUTING.md。如需报告漏洞,请使用 私密报告渠道, 不要公开提交问题;相关政策见 SECURITY.md。
许可证
MIT © Willi Thiel
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。