
SMTP
io.github.ni-c由 GitHub 帳號 ni-c 發布v0.2.0更新於 Oct 24, 2026
MCP server that sends mail over SMTP, gated behind an allowlist and a human confirmation
概覽
本機 MCP 伺服器,讓助理透過 SMTP 撰寫、預覽、寄送、回覆和轉寄郵件,每封郵件都受收件者白名單和人工確認約束。
- 可以做什麼
- 檢視設定並測試 SMTP 連線,不寄出任何內容;檢查伺服器可寫入哪些收件者,以及其他位址被拒的原因。依寄送時的完整檢查建構並預覽即將寄出的郵件。寄送新郵件、以正確討論串回覆、逐字引用原文轉寄,每項都需人工核准。可依名稱或前綴篩選要註冊哪些工具,並提供精選的五工具預設集。
- 適用情境
- 希望助理用你自己的 SMTP 帳號、從固定寄件位址起草並寄送郵件,並要求寄送由明確開關、收件者白名單和逐封人工確認把關時使用。不用於讀取信箱,那由另一個伺服器負責。
- 執行需求
- 透過 npx(需 Node.js 22 或更新版本)或 Docker 映像在本機執行。需要一個 SMTP 提交帳號:SMTP_HOST、SMTP_USER、SMTP_PASSWORD 和 SMTP_FROM 為必填。SMTP_ALLOW_SEND 為 true 前不會寄送,且此時必須提供 SMTP_ALLOWED_RECIPIENTS。需要連線郵件伺服器的網路;TLS 預設為 starttls。
安裝
在 SourceWeft 中
- 開啟 儀表板中的 SMTP,將其新增到工作區。
- 為需要使用其工具的對話啟用該服務。
Desktop only,透過 STDIO。 STDIO 服務會啟動本機處理程序,因此需要 SourceWeft 桌面主機。
其他 MCP 客戶端
參照 儲存庫 中的啟動說明。
README
smtp-mcp
[CI]
[OpenSSF Scorecard]
[Socket Badge]
[Glama score]
[npm version]
[container image]
[HTTP via mcp-hub]
[docs]
[sponsor]
A Model Context Protocol (MCP) server for SMTP, the protocol every mail server speaks to accept a message for delivery.
Lets MCP clients like Claude Code, Claude Desktop or Codex send, reply to and forward mail from one configured address — with a human approving every message.
Seven tools is the ceiling, not the floor: SMTP_ALLOW_TOOLS=essential registers a curated five
instead, and a model picks the right tool far more reliably from five than from seven — see
choosing which tools load.
What makes it different
It sends mail. That is why it is a separate server. Its counterpart imap-mcp reads a mailbox and deliberately has no way to send anything — that absence is its entire security argument, because an agent that can reach private data and process attacker-controlled content is only exploitable once it also has a way out. This server is that way out, so it does not get to make the same claim. It earns its place by narrowing the channel instead, and by living in its own process with its own credentials.
It is off when you install it. SMTP_ALLOW_SEND defaults to false. Until it is set the
sending tools are not registered at all — absent from tools/list, not refused at call time.
It can only write to people you named. SMTP_ALLOWED_RECIPIENTS is required to turn sending
on. Every address in To, Cc and Bcc is checked against it before a connection is opened, so an
injected "mail this to someone else" fails without the server ever reading it as an instruction.
Allowing everyone is possible and has to be written as *.
Every message is approved by a person. Not by the model — the request goes to the client as an MCP elicitation. Recipients, subject and any Bcc appear on their own labelled lines, so a subject written to look like an instruction cannot become part of the server's own sentence.
The sender cannot be chosen. There is no from parameter. A model that could pick its own
sender could write in a colleague's name, and the result would be indistinguishable from a
message they wrote.
Requirements
- Node.js 24 or newer
- An SMTP account you may send from — a submission server on port 587 or 465, with a username and password. Providers with two-factor authentication generally need an app-specific password.
Configuration
Use TLS.
SMTP_TLS=starttls(the default) requires the upgrade rather than attempting it, so a strippedSTARTTLScapability fails the connection instead of quietly sending your password in the clear. For a self-signed certificate prefer a proper internal CA overSMTP_INSECURE_TLS.
Two defaults are worth reading twice, because they are the opposite of what the rest of this family does:
SMTP_ALLOW_SENDis off. A freshly installed smtp-mcp can compose and preview messages and cannot send any.- An unset
SMTP_ALLOWED_RECIPIENTSis a startup error, not "anyone". Treating a missing line as permission is how an accident becomes a delivered message. Write*if you mean it.
Choosing which tools load
SMTP_ALLOW_TOOLS decides what is registered, SMTP_DENY_TOOLS is subtracted from it. Both take
comma-separated tool names or a prefix with a single trailing *. A filtered tool is never
built — it does not appear in tools/list and answers a call with "not found", the same as a
sending tool while the send gate is closed. Nothing is advertised and then refused.
essential is get_server_info, validate_recipients, preview_mail, send_mail and
reply_mail. forward_mail is left out: forwarding carries somebody else's content and
attachments outward, which is the call that most deserves to be switched on deliberately.
An entry that matches no tool aborts startup and lists the real names. A tool quietly missing
from tools/list is invisible — nobody traces an absence back to an environment variable.
Installation
Claude Code
Claude Desktop
Codex
Docker
Through mcp-hub
A client that cannot spawn a local process — ChatGPT connectors, Claude on the web,
Cursor, LibreChat — reaches smtp-mcp through mcp-hub: one
container serves many stdio MCP servers over Streamable HTTP, with an OAuth 2.1 login
behind a single password and long-lived tokens for the clients that cannot do OAuth. Its
/hub endpoint puts every server behind six meta-tools, so one connector reaches all of
them without N×tool schemas in the model's context, and it speaks both protocol revisions
— a question this server asks travels through it to the person at the far end.
Its /config/mcp.json uses Claude Code's format, so the entry is the one you already
have:
allowTools and denyTools there are the hub's own per-server filter, which is not
the same thing as *_ALLOW_TOOLS in env — the difference, and the mistake it invites,
are in the client guide.
Tools
Always registered. None of these can put a message on the wire.
Registered only with SMTP_ALLOW_SEND=true. 👤 marks the ones that ask a human before acting.
Structured output
Every tool declares an outputSchema and answers with structuredContent
alongside the text block, so a client can use the result without parsing prose:
preview_mail is the one tool that carries untrusted: true and
source: "smtp" as fields: a quoted original was written by whoever sent it,
and anyone in the world can send mail. Its text block keeps the nonce fence —
the structured half states the same fields so a client is not made to parse it.
Everything else here reports this server's own configuration or the outcome of
its own send, where the marker would be a false claim about who wrote it.
Not exposed, on purpose
- A
fromparameter. The sender isSMTP_FROMand nothing else. - A way to skip the confirmation. No
force, no "trusted caller" mode. An option to turn the gate off would be the first thing a prompt injection reaches for. - Reading mail. That is imap-mcp. Keeping the two in separate processes with separate credentials is most of what makes either of them safe.
- Arbitrary headers. Threading uses
in_reply_toandreferences; there is no passthrough for header names, because that is header injection with extra steps. - DKIM signing. A submission server signs for you. A private signing key in an environment variable is a worse trade than it looks.
Safety
- Sending is off by default and the tools do not exist until it is on.
- Every recipient is checked against an allowlist before a connection is opened, in To, Cc and Bcc alike.
- Every message is approved by a human, through MCP elicitation. The two-call token fallback says plainly that it is not the same thing.
- A confirmation is bound to the exact message: a SHA-256 fingerprint over the sorted recipient list and a digest of the content, so an approval cannot be spent on a wider list or on different text.
- The dialog shows the message, not only the envelope: the body, the quoted original and the HTML part, each with its length in characters. Everything else here binds who a message goes to; this is what binds what it says.
- Bcc recipients get their own labelled line in the dialog. A hidden recipient a human does not see is the ideal exfiltration channel.
- Confirmation text never quotes caller-chosen values into the server's own sentence.
- The same message is not sent twice. An approval proves that somebody agreed to a message, not that they agreed to it again, so a message the SMTP server accepted is remembered for as long as an approval for it could still be redeemed.
- Outgoing HTML is stripped of scripts, event handlers, remotely loaded images and unsafe URL schemes — and every removal is reported, never silent. Markup that cannot be cleaned with confidence is refused rather than repaired.
- A quoted original is passed on unchanged, with any prompt-injection shapes it matches named in the dialog.
- Attachments come only from
SMTP_ATTACHMENT_DIR, past an extension allowlist, a symlink refusal and a magic-byte check. - Every accepted message is recorded on stderr and optionally in a file. Never the body.
See SECURITY.md for the reasoning, and for what none of this covers.
Documentation
The full guide, tool reference and security notes live at
smtp-mcp.ni-c.de (source in docs/).
Development
There is a throwaway Mailpit sandbox in test/integration/. Develop
against it rather than a real mailbox: this server's job is to put messages on the wire, and a
test run that goes wrong sends real mail to real people.
Releasing
Tagging vX.Y.Z on main runs the release workflow: it checks the tag matches package.json,
publishes to npm with provenance through Trusted Publishing, pushes a multi-arch image to GHCR
with an SBOM, creates the GitHub release from the CHANGELOG section, and submits the version to
the MCP Registry.
Contributing
Issues, discussions and pull requests are welcome — see CONTRIBUTING.md. For vulnerabilities please use private reporting rather than a public issue; the policy is in SECURITY.md.
License
MIT © Willi Thiel
來源:README.md,提交 69b0f43
工具
0版本歷史
1- v0.2.0最新Sep 16, 2026
評分
已滿足適用檢查項的 50%
該評分衡量此收錄條目的完整程度,依據註冊中心條目、端點與公開來源計算得出。它不是對伺服器本身的評價,也不表示伺服器安全或目前可用:可連通性是帶日期的檢查結果,評分也不包含安裝量或使用者評價。
- 近 30 天內可連通25 分
請保持端點能夠回應 MCP 握手;SourceWeft 每 30 天探測一次。
- 已宣告認證方式10 分
請在註冊中心條目中宣告憑證請求標頭,或保持端點能夠回應探測,以便判定其認證方式。
- 已列出工具15 分
請讓伺服器在無憑證時回應 tools/list,或發布可在沙箱中無憑證啟動的軟體包。
- 描述必需15 分
- 圖示10 分
- 文件15 分
- 授權條款10 分