Skip to main content
Glama
postbus-mcp

postbus-mcp

by HalloSouf

postbus-mcp

Code quality Docker License: MIT

一个自托管的 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"},方便做存活检查。


用户和令牌

令牌由你自己分发;没有自助注册。

命令

作用

npm run add-user -- "Name"

创建用户并打印令版(仅一次)

npm run list-users

显示用户、邮箱数量和状态

npm run rotate-token -- <id>

生成新令版;旧令版立即失效

npm run remove-user -- <id>

删除该用户及其所有邮箱

在 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

https://myaccount.google.com/apppasswords

需要账号开启两步验证

Outook / Microsoft 365

https://account.microsoft.com/security

需要两步验证;管理员可能阻止 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。


可用工具

工具

作用

list_accounts

列出你的邮箱,包含别名和邮件地址

add_mail_account

关联一个 IMAP/SMTP 邮箱和应用密码(先测试连接)

remove_mail_account

解除邮箱关联并清除已存储的应用密码

search_emails

使用 Gmail 风格语法搜索;每条消息返回一个 id 和 threadId

get_message

获取单条消息的完整内容:头部、正文、附件元数据

get_thread

获取会话中的所有消息,按时间从旧到新

send_email

立即发送新消息(支持 cc、bcc、reply-to、html)

每个工具都只会访问令牌所属用户的邮箱。


搜索语法

search_emails 使用 Gmail 风格的语法。对于 Gmail 邮箱,你的查询会原样发送给 Gmail(通过 X-GM-RAW),因此 Gmail 搜索栏中可用的任何语法在这里都可用。对于其他 IMAP 服务器,查询会被转换:

术语

Gmail

其他 IMAP

from:、to:、cc:、bcc:、subject:

✅

✅

is:unread、is:read、is:starred、is:answered

✅

✅

newer_than:7d、older_than:2w(d/w/m/y)

✅

✅

after:2026-01-01、before:2026/03/01

✅

✅

larger:5M、smaller:100k

✅

✅

has:attachment

✅

✅(事后过滤)

in:inbox、in:sent、in:archive、in:all、in:trash

✅

✅(通过 SPECIAL-USE)

-from:someone(排除)

✅

✅

"exact phrase" 和松散词语

✅

⚠️ 合并为一个文本条件

label:、filename:、category:

✅

❌ 忽略

示例:

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>;
}

提供商收到的是完全解析后的账户,凭据已解密。别名查找发生在工具层,因此提供商无法访问会话用户以外的数据。

要添加一个提供商:

  1. 扩展 src/types.ts 中的 ProviderId 和 MailAccount 联合类型。

  2. 编写 src/providers/<name>/provider.ts,其中包含一个实现该接口的类。

  3. 在 src/providers/registry.ts 的映射表中添加一行。

  4. 确保该类型的账户可以访问数据库:在 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

  1. 在 https://console.cloud.google.com 创建项目。

  2. API 和服务 → 库 → 搜索 "Gmail API" → 启用。

  3. API 和服务 → OAuth 同意屏幕 → 类型选为 外部 → 填写名称和支持邮箱。

  4. 在 测试用户 下添加要关联的地址。

  5. 凭据 → 创建凭据 → OAuth 客户端 ID → 类型选为 桌面应用。

  6. 将客户端 ID 和客户端密钥放入 .env:

    GOOGLE_CLIENT_ID=xxxxxxxxxxxx.apps.googleusercontent.com
    GOOGLE_CLIENT_SECRET=GOCSPX-xxxxxxxxxxxxxxxxxxxx
    OAUTH_CALLBACK_PORT=53682
  7. 关联一个邮箱。此操作在管理员的机器上运行,因为 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。

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables 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
  • A
    license
    B
    quality
    B
    maintenance
    Enables 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.
    1
    32 PyPI
    4
    MIT
  • A
    license
    B
    quality
    A
    maintenance
    Connects MCP clients to any IMAP/SMTP email account, enabling email search, reading, sending, replying, forwarding, flagging, moving, and folder management via natural language.
    17
    MIT
  • A
    license
    B
    quality
    C
    maintenance
    Enables email integration through MCP, including sending, receiving, searching, replying to, and forwarding emails, plus folder management and multi-account support with encrypted credential storage.
    40
    1,013 npm
    MIT