postbus-mcp
postbus-mcp
一个自托管的 MCP 服务器,让你和你身边的几个人可以通过 Claude 或其他任何 MCP 客户端处理你的邮箱:搜索、阅读完整会话,以及发送邮件。
适用于任何 IMAP/SMTP 提供商——Gmail、Outlook、Fastmail,甚至你自己的邮件服务器——只需一个普通的应用密码。无需 Google Cloud 项目,无需 OAuth 验证,也没有测试用户限制。
一个实例可服务多个用户。每个人都有自己的 API 令牌,并且只能看到自己的邮箱。由你托管,由你分发令版;没有开放注册。
Claude / MCP client
│ Authorization: Bearer <token>
▼
POST /mcp ──► postbus-mcp ──► SQLite (users + encrypted app passwords)
│
├──► IMAP (imapflow) search, read, threads
└──► SMTP (nodemailer) sending目录
Related MCP server: simple-email-mcp
工作原理
多租户,但体积小。 一个 SQLite 文件包含两张表:users(id 以及 API 令牌的哈希)和 mail_accounts(每个用户的邮箱,应用密码已加密)。无需单独运行数据库服务。
隔离体现在查询中,而不是事后的检查中。 每个 MCP 会话恰好属于一个用户,由 Bearer 令牌决定。MCP 服务器针对每个请求围绕该用户构建,并且每个数据库查询都在其 WHERE 中携带 user_id。别人的别名在你的会话中根本不存在。
提供商接口。 工具层与通用的 MailProvider 交互,不关心 IMAP 或 Gmail。ImapSmtpProvider 是主要实现,可选配 GmailApiProvider。添加第三个提供商无需改动工具层——参见 添加提供商。
快速开始
使用 Docker(推荐)
git clone https://github.com/HalloSouf/postbus-mcp.git
cd postbus-mcp
cp .env.example .env
openssl rand -hex 32 # put the result in .env as MASTER_KEY
docker compose up -d --build
docker compose exec postbus node dist/cli/add-user.js "Soufiane"最后一条命令会恰好打印一次 API 令牌。请立即保存。
在本地使用 Node(22 或更高版本)
npm install
cp .env.example .env
openssl rand -hex 32 # put the result in .env as MASTER_KEY
npm run build
npm run add-user -- "Soufiane"
npm start服务器监听 http://localhost:3000/mcp。GET /health 返回 {"status":"ok"},方便做存活检查。
用户和令牌
令牌由你自己分发;没有自助注册。
命令 | 作用 |
| 创建用户并打印令版(仅一次) |
| 显示用户、邮箱数量和状态 |
| 生成新令版;旧令版立即失效 |
| 删除该用户及其所有邮箱 |
在 Docker 中,以 node dist/cli/<script>.js 方式运行相同的脚本:
docker compose exec postbus node dist/cli/list-users.js
docker compose exec postbus node dist/cli/rotate-token.js WvDnhafdM5yQ每个令版仅存储 SHA-256 哈希,因此丢失的令版无法找回——请改为轮换令版。
连接你的客户端
Claude Desktop
Claude Desktop 使用 stdio,因此需要在中间加上 mcp-remote。在 claude_desktop_config.json 中:
{
"mcpServers": {
"postbus": {
"command": "npx",
"args": [
"-y",
"mcp-remote",
"https://mcp.example.com/mcp",
"--header",
"Authorization: Bearer pb_YOUR_TOKEN_HERE"
]
}
}
}该文件在 macOS 上位于 ~/Library/Application Support/Claude/claude_desktop_config.json,在 Windows 上位于 %APPDATA%\Claude\claude_desktop_config.json。编辑后请重启 Claude Desktop。
Claude Code
claude mcp add --transport http postbus https://mcp.example.com/mcp \
--header "Authorization: Bearer pb_YOUR_TOKEN_HERE"其他客户端
任何支持 Streamable HTTP 的客户端都可以工作:端点 POST /mcp,令版作为 Authorization: Bearer <token>。服务器是无状态的——没有会话 ID,也没有服务器端流——因此 GET /mcp 会刻意返回 405。
关联邮箱
你在对话中用自己的令版完成此操作,无需终端:
把我的 Gmail 关联为“个人”,地址 souf@gmail.com,应用密码 abcd efgh ijkl mnop
Claude 随后会调用 add_mail_account。首先会测试连接(IMAP 和 SMTP 都测试);只有两者都成功才会存储任何信息。
创建应用密码
提供商 | 位置 | 说明 |
Gmail / Workspace | 需要账号开启两步验证 | |
Outook / Microsoft 365 | 需要两步验证;管理员可能阻止 IMAP | |
Fastmail | 设置 → 隐私与安全 → 应用密码 | 选择“邮件(IMAP/SMTP)” |
iCloud | https://account.apple.com → 应用专用密码 | 需要两步验证 |
自有服务器 | 不适用 | 你的邮件密码,或一个专用账号 |
当提供商提供应用密码时,切勿使用你的常规密码。
主机和端口
对于已知提供商,postbus-mcp 会自动填写这些信息——你只需提供别名、邮箱和应用密码:
Gmail、Google Workspace、Outlook、Hotmail、Microsoft 365、Fastmail、iCloud、Yahoo、Zoho、Proton(通过 Bridge)。
对于其他提供商,请自己传入这些信息:
imap_host: imap.yourdomain.com imap_port: 993 (TLS)
smtp_host: smtp.yourdomain.com smtp_port: 465 (TLS) or 587 (STARTTLS)端口 993 和 465 从一开始就使用 TLS;在其他端口上,如果服务器支持,则使用 STARTTLS。如果该假设不适用于你的服务器,请显式传入 imap_secure 或 smtp_secure。
可用工具
工具 | 作用 |
| 列出你的邮箱,包含别名和邮件地址 |
| 关联一个 IMAP/SMTP 邮箱和应用密码(先测试连接) |
| 解除邮箱关联并清除已存储的应用密码 |
| 使用 Gmail 风格语法搜索;每条消息返回一个 |
| 获取单条消息的完整内容:头部、正文、附件元数据 |
| 获取会话中的所有消息,按时间从旧到新 |
| 立即发送新消息(支持 cc、bcc、reply-to、html) |
每个工具都只会访问令牌所属用户的邮箱。
搜索语法
search_emails 使用 Gmail 风格的语法。对于 Gmail 邮箱,你的查询会原样发送给 Gmail(通过 X-GM-RAW),因此 Gmail 搜索栏中可用的任何语法在这里都可用。对于其他 IMAP 服务器,查询会被转换:
术语 | Gmail | 其他 IMAP |
| ✅ | ✅ |
| ✅ | ✅ |
| ✅ | ✅ |
| ✅ | ✅ |
| ✅ | ✅ |
| ✅ | ✅(事后过滤) |
| ✅ | ✅(通过 SPECIAL-USE) |
| ✅ | ✅ |
| ✅ | ⚠️ 合并为一个文本条件 |
| ✅ | ❌ 忽略 |
示例:
from:boss@company.com is:unread newer_than:7d
subject:"march invoice" has:attachment
in:sent to:client@example.com older_than:1m空查询会返回收件箱中最新的消息。
会话线程
每个 search_emails 结果都带有 threadId,get_thread 使用它来拉取整个会话——按时间顺序排列,包含每条消息的发件人、主题、日期和正文。
根据服务器可用的能力,有两种方式:
Gmail(
X-GM-THRID)和 RFC 8474 服务器(OBJECTID) 会自行提供稳定的线程 ID。我们直接使用它,threadId看起来像srv:1829384756。其他所有 IMAP 服务器 没有线程概念。在这种情况下,我们根据标准的
Message-ID、In-Reply-To和References头重建会话:该链中的第一个 id 是线程的根。这些threadId值以ref:开头。
获取时,如果服务器有“所有邮件”文件夹,我们会从那里查找;否则会在收件箱、已发送和归档中查找——这样你自己的回复也会出现在会话中。
在 Traefik 后面部署
此仓库中的 docker-compose.yml 是一个可运行的示例。其核心内容:
services:
postbus:
build: .
restart: unless-stopped
environment:
MASTER_KEY: ${MASTER_KEY:?set MASTER_KEY in .env}
DATABASE_PATH: /data/postbus.db
TRUST_PROXY: "true"
volumes:
- postbus-data:/data
networks: [proxy]
labels:
traefik.enable: "true"
traefik.docker.network: proxy
traefik.http.routers.postbus.rule: Host(`${PUBLIC_HOST:-mcp.example.com}`)
traefik.http.routers.postbus.entrypoints: websecure
traefik.http.routers.postbus.tls.certresolver: letsencrypt
traefik.http.services.postbus.loadbalancer.server.port: "3000"需要注意的事项:
在
.env中将PUBLIC_HOST设置为你自己的主机名;这是域名唯一出现的位置,因此 compose 文件本身无需改动。proxy网络必须存在(docker network create proxy),并且 Traefik 必须连接到此网络。容器本身不发布任何端口:只有 Traefik 可以访问它。
TRUST_PROXY=true让 Express 信任X-Forwarded-*请求头。在 Traefik 处终止 TLS。令牌以 Bearer 凭证形式传输;没有 HTTPS 就会明文传输。
postbus-data卷保存着包含所有加密应用密码的数据库。请将其与MASTER_KEY一同备份——但分开存放。
安全性
MASTER_KEY。 应用密码和刷新令牌使用 AES-256-GCM 存储,每条都有独立的 IV。没有该密钥,服务器拒绝启动。如果丢失,所有人都需要重新关联邮箱,因此请将其与数据库备份分开保存。
令牌。 仅存储 SHA-256 哈希。通过你信任的渠道分享它们,有疑虑时进行轮换(npm run rotate-token)。
隔离。 对 mail_accounts 的每个查询都按 user_id 过滤,并且 MCP 服务器为每个请求围绕单个用户构建,因此不存在可能混淆用户的会话存储。
这不包括什么。 没有速率限制、没有审计日志、没有细粒度权限。这是为你认识的几个人在 TLS 后面使用的。不要将其开放给未知受众。
添加提供商
工具层只与 src/types.ts 中的 MailProvider 交互:
interface MailProvider<A extends MailAccount = MailAccount> {
readonly id: ProviderId;
verify(account: A): Promise<void>;
search(account: A, query: string, maxResults: number): Promise<MessageSummary[]>;
getMessage(account: A, messageId: string): Promise<MessageDetail>;
getThread(account: A, threadId: string): Promise<MessageDetail[]>;
send(
account: A,
to: string,
subject: string,
body: string,
options?: SendOptions,
): Promise<string>;
}提供商收到的是完全解析后的账户,凭据已解密。别名查找发生在工具层,因此提供商无法访问会话用户以外的数据。
要添加一个提供商:
扩展
src/types.ts中的ProviderId和MailAccount联合类型。编写
src/providers/<name>/provider.ts,其中包含一个实现该接口的类。在
src/providers/registry.ts的映射表中添加一行。确保该类型的账户可以访问数据库:在
src/db/accounts.ts中添加save<Name>Account()(机密通过encryptSecret处理),并提供关联方式——在add_mail_account旁边添加一个额外工具,或提供一个 CLI 脚本。
现有工具(search_emails、get_message、get_thread、send_email)无需改动。另请参阅 CONTRIBUTING.md。
可选:通过 API 而非 IMAP 使用 Gmail
在 https://console.cloud.google.com 创建项目。
API 和服务 → 库 → 搜索 "Gmail API" → 启用。
API 和服务 → OAuth 同意屏幕 → 类型选为 外部 → 填写名称和支持邮箱。
在 测试用户 下添加要关联的地址。
凭据 → 创建凭据 → OAuth 客户端 ID → 类型选为 桌面应用。
将客户端 ID 和客户端密钥放入
.env:GOOGLE_CLIENT_ID=xxxxxxxxxxxx.apps.googleusercontent.com GOOGLE_CLIENT_SECRET=GOCSPX-xxxxxxxxxxxxxxxxxxxx OAUTH_CALLBACK_PORT=53682关联一个邮箱。此操作在管理员的机器上运行,因为 Google 会将回调发送到
localhost:npm run list-users # look up the user id npm run link-gmail -- <user-id> work
使用的范围:gmail.readonly、gmail.send、gmail.compose、gmail.labels。
注意: 当 OAuth 同意屏幕设置为 测试 时,刷新令牌会在 7 天后过期,你必须重新关联。这种情况只有在同意屏幕变为 已发布 后才会停止,而对这些范围而言,发布需要 Google 验证。这正是 IMAP 搭配应用专用密码成为主要路径的原因。
开发
npm install
npm run dev # server with hot reload (tsx watch)
npm test # unit tests (vitest)
npm run typecheck # src + tests
npm run format # prettier across the repo
npm run build # into dist/tests/ 中的测试在半秒内运行完毕,并且不会触及进程之外的任何内容:SQLite 在内存中运行,没有任何连接离开机器。它们覆盖了那些可能悄然出错的逻辑——搜索查询转换、消息和线程 ID 的编码、MIME 的解析与组装、加密存储、用户之间的隔离,以及 bearer 中间件。
它们不覆盖的是与真实邮件服务器的通信。为此,请在本地运行 GreenMail:
docker run -d --rm --name greenmail -p 3143:3143 -p 3025:3025 \
-e GREENMAIL_OPTS='-Dgreenmail.setup.test.imap -Dgreenmail.setup.test.smtp -Dgreenmail.users=souf:secret@postbus.test -Dgreenmail.hostname=0.0.0.0' \
greenmail/standalone:2.1.0然后用 imap_host: 127.0.0.1、imap_port: 3143、smtp_host: 127.0.0.1、smtp_port: 3025、username: souf、app_password: secret 关联一个邮箱。
GreenMail 不支持 Gmail 扩展。使用
X-GM-RAW和X-GM-THRID的代码分支只能针对真实的 Gmail 邮箱进行测试。
GitHub Actions 会在每次 push 和 pull request 上运行同样的检查:格式化、类型、对生产依赖执行 npm audit、测试,以及一个 docker 构建——它会启动容器,并验证 /health 有响应,且在没有令牌的情况下 /mcp 返回 401。CI 和容器都运行 Node 24,即当前的 LTS。
项目结构
src/
├── index.ts startup: check MASTER_KEY, open the db, listen
├── config.ts environment configuration
├── crypto.ts AES-256-GCM for secrets, hashing for tokens
├── types.ts MailProvider plus every shared type
├── db/ SQLite: migrations, users, mail_accounts
├── http/ Express app, bearer auth, MCP transport per request
├── providers/
│ ├── registry.ts account -> provider
│ ├── imap/ IMAP/SMTP: connections, search, threading, sending
│ └── gmail/ optional Gmail API provider (OAuth)
├── tools/ the MCP tools (they know no provider)
└── cli/ admin scripts: users and tokens
tests/ unit tests (vitest), mirroring the layout of src/许可证
MIT — 参见 LICENSE。
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables reading and sending emails via IMAP and SMTP through the MCP protocol. Supports multiple email accounts and configuration via UI or environment variables.BSD 3-Clause
- AlicenseBqualityBmaintenanceEnables users to manage email accounts via IMAP/SMTP, including reading, searching, sending emails with attachments and calendar invites, all through natural language interactions with MCP-compatible clients.14MIT
- AlicenseAqualityBmaintenanceMCP server that enables email management (send, read, search, delete, etc.) via IMAP/SMTP, compatible with Gmail, Outlook, Yahoo, iCloud, and other standard mail servers.11MIT
- AlicenseNot gradedqualityAmaintenanceExposes any IMAP mailbox and SMTP relay as MCP tools, enabling email management (read, search, send, delete) through MCP-compatible agents.MIT
Related MCP Connectors
Read, search, send, organize, draft and schedule email across your inboxes from any MCP client.
Hosted email MCP for AI agents with inboxes, send/receive, memory, recovery, and credits.
Fully-managed email as MCP tools - register domains, real mailboxes, send and receive mail.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/HalloSouf/postbus-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server