内容
# Postern
[](https://github.com/skyphusion-labs/postern/releases)
[](https://github.com/skyphusion-labs/postern/actions/workflows/ci.yml)
[](https://www.npmjs.com/package/@skyphusion/postern-mcp)
[](https://pypi.org/project/postern-client/)
适用于人类和代理的电子邮件。Postern 是一个可自行托管的邮箱,基于 Cloudflare:它发送和接收邮件,将每封邮件存储在可搜索的存储中,并暴露一个结构化的 API,供代理和人类客户端(IMAP/Webmail)使用。Cloudflare Email 是每个接缝处的默认传输方式,但永远不是硬依赖。
人类和代理都**以自己的身份发送邮件**,使用每个身份的凭证,而不是共享邮箱(参见 [docs/SEND-IDENTITIES.md](docs/SEND-IDENTITIES.md))。代理通过 **MCP**([`@skyphusion/postern-mcp`](https://www.npmjs.com/package/@skyphusion/postern-mcp))与邮箱进行原生交互,作为一等公民,而不是事后才添加的功能。
从一个新的克隆开始,只需使用您自己的域名,您就可以部署它,发送一封邮件,并接收和读取它。外发邮件需要在 **Workers Paid** 计划(每月 5 美元)上使用 Cloudflare Email Sending;通过 Email Routing 进行内发邮件,免费计划也可以使用。参见 **[DEPLOY.md](DEPLOY.md)** 了解快速安装步骤,[**inbound/smoke.mjs](inbound/smoke.mjs)** 了解脚本化的 v1.0 验收测试(问题 #25)。
## 实时试用
实时只读演示:[https://demo.posternonline.com](https://demo.posternonline.com)。打开 `/webmail` 并使用下面的演示令牌登录。
向 **任何** `@posternonline.com` 地址发送邮件,观察它出现在邮箱中。这就是产品的工作原理:Email Routing -> worker -> D1 store。
演示令牌是只读范围的,公开可见:发送、回复和删除被 API 范围墙拒绝,Webmail 隐藏了撰写功能。演示邮箱是共享且公开的,因此请勿发送任何私人邮件。
代理的 MCP 配置:
```
POSTERN_API_URL=https://demo.posternonline.com
POSTERN_API_TOKEN=a5fb2da1a13ab468adc1d147272126a4a977f3db44ace5c961ce87d26e0055d8
```
大约 10 分钟内运行您自己的:请参阅 [DEPLOY.md](DEPLOY.md)。
一个仓库中有六个接口(一个存储,一个 API):
| 路径 | 角色 |
|------|------|
| **`inbound/`** | 核心 Cloudflare Worker:摄取、存储(D1 + R2 + Vectorize)、邮箱 API、发送 |
| **`relay/`** | 可选的 Go SMTP 守护进程:环回摄取、提交 587/465、BYO 调度 |
| **`mcp/`** | 代理的 MCP 服务器([`@skyphusion/postern-mcp`](https://www.npmjs.com/package/@skyphusion/postern-mcp) 在 npm 上) |
| **`webmail/`** | 嵌入在 `/webmail` 中的浏览器 UI:读取,以及令牌可发送时的撰写/回复 |
| **`imap/`** | IMAP 代理(读取、`\Seen`、删除)适用于 Thunderbird / mutt / iOS Mail |
| **`clients/python/`** | 标准库 HTTP 客户端 + CLI([`postern-client`](https://pypi.org/project/postern-client/) 在 PyPI 上) |
```mermaid
flowchart TD
subgraph transports[传输缝隙]
cfIn[CF 电子邮件路由]
cfOut[CF 电子邮件发送]
relay[postern-relay SMTP]
end
subgraph core[inbound Worker]
store[(D1 + R2 + Vectorize)]
api[邮箱 API + RPC]
end
subgraph clients[客户端]
webmail[webmail]
imap[imap]
mcp[mcp]
py[clients/python]
end
cfIn --> store
relay --> store
api --> cfOut
api --> relay
webmail --> api
imap --> api
mcp --> api
py --> api
```
参见 [docs/architecture.md](docs/architecture.md) 了解完整的视觉地图(入站/出站序列,客户端门)。 [docs/CONTRACT.md](docs/CONTRACT.md) 是权威的数据模型; [docs/INTEGRATION.md](docs/INTEGRATION.md) 涵盖 RPC + REST 调用者设置。
## 适用于人类的电子邮件:Webmail 和 IMAP
代理使用结构化 API;人类获得两个通往同一邮箱的门户,都是该 API 的客户端(而非第二个存储):
- **Webmail** (`webmail/`):一个自包含的页面(纯 HTML/CSS/JS,无构建步骤),由 Worker 在 **`/webmail`** 处提供服务。粘贴您的 API 源和令牌,浏览邮箱(列表、读取、线程、搜索);当令牌可发送时,撰写和回复解锁。
- **IMAP 代理** (`imap/`):一个小型 Twisted 服务器,作为 IMAP(读取、`\Seen` 读/未读标志和删除)呈现 API,因此 Thunderbird / mutt / iOS Mail 也可以打开邮箱。
Webmail 在令牌可发送时添加撰写/回复功能;IMAP 通过 `both` 范围的令牌添加读取/未读(`\Seen`)和删除功能。两者都是 API 客户端,而非第二个存储,所有发送都通过结构化 API 进行。
在 Webmail 中渲染的 HTML 电子邮件(安全地,在沙盒 iframe 中;无脚本,无远程跟踪器运行):

收件箱列表、邮件阅读视图和搜索:

| 读取消息(信任裁决 + 附件) | 搜索邮箱 |
|---|---|
|  |  |
> 上面的截图使用合成示例数据。参见 [webmail/README.md](webmail/README.md) 了解设置和安全模型(BYO-token,令牌仅在 `sessionStorage` 中,无 `innerHTML` 消息内容,锁定 CSP)。
## 快速开始
完整的步骤在 [DEPLOY.md](DEPLOY.md) 中。简而言之:
```bash
cd inbound
npx wrangler d1 create postern # 将 database_id 粘贴到 wrangler.jsonc 中
npx wrangler r2 bucket create postern-attachments
# 编辑 wrangler.jsonc:database_id + DEFAULT_FROM / ALLOWED_FROM_DOMAIN
npx wrangler d1 execute postern --remote --file=schema.sql
npx wrangler secret put POSTERN_API_TOKEN # openssl rand -hex 32
npm install && npm run deploy
```
然后将入站邮件路由到 Worker(Email Routing -> Routing Rules -> 捕获所有到 Worker),并运行 smoke(参见 DEPLOY.md)。
## 客户端包
部署后,连接代理和脚本,无需克隆仓库。两个包都与同一个令牌门控邮箱 API 通信;它们是存储的客户端,而不是存储的第二个副本。
| 包 | 注册表 | 安装 | 文档 |
|---------|----------|---------|------|
| **@skyphusion/postern-mcp** | [npm](https://www.npmjs.com/package/@skyphusion/postern-mcp) | `npx -y @skyphusion/postern-mcp` | [mcp/README.md](mcp/README.md) |
| **postern-client** | [PyPI](https://pypi.org/project/postern-client/) | `pip install postern-client` | [clients/python/README.md](clients/python/README.md) |
使用您部署的源和令牌进行配置:
```bash
export POSTERN_API_URL=https://postern.<your-account>.workers.dev
export POSTERN_API_TOKEN=<read-scoped token>
```
**MCP(Cursor / Claude Code):** 使用 `command: npx` 添加 MCP 服务器条目,`args: ["-y", "@skyphusion/postern-mcp"]`,以及上面的 env 变量在 `env` 中。发送工具(`mailbox_send`、`mailbox_reply`)仅在设置 `POSTERN_SEND_TOKEN` 时注册(请参见 [docs/SEND-IDENTITIES.md](docs/SEND-IDENTITIES.md))。
**Python CLI:** `postern ping`、`postern list`、`postern search`、`postern send` 等;请参见 [clients/python/README.md](clients/python/README.md)。
发布标签:`postern-mcp-v*`(npm CI)和 GitHub Release `v*` 匹配 `clients/python/pyproject.toml`(PyPI CI)。请参见 [docs/INTEGRATION.md](docs/INTEGRATION.md)。
## 认证
- **相同账户 Workers:** `MailboxService` RPC 入口点(或旧的 `EmailService` 别名),无令牌。
- **其他人:** `Authorization: Bearer <POSTERN_API_TOKEN>`,恒定时间比较。
- 传输(`/ingest`,中继 `/dispatch`)使用单独的 `POSTERN_TRANSPORT_TOKEN`,而非 API 令牌,因此 API 令牌泄露无法注入邮件,反之亦然。
## 中继(可选,自带 SMTP)
Go >= 1.22:
```bash
cd relay
go mod tidy
go build -o postern-relay .
```
通过 env 配置(无值嵌入):`POSTERN_INGEST_URL`(或旧的 `EMAIL_WORKER_URL`)、`POSTERN_TRANSPORT_TOKEN` 和 `DEFAULT_FROM` / `FROM_DOMAIN` 用于域外发件人重写。中继使用信封 `RCPT TO` 作为收件人;如果邮件的 `From` 不在允许的域中,则重写为 `DEFAULT_FROM`,原始邮件保留为 `Reply-To`。
## 惯例
源码、提交或文档中没有 em/en 破折号。提交使用惯例提交(`feat(inbound): ...`、`fix(relay): ...`)。
---
## 操作参考部署(skyphusion)
这些说明特定于维护者的部署,不需要运行 Postern。陌生人应改为遵循 [DEPLOY.md](DEPLOY.md)。
参考实例从 `skyphusion.org`(和 `.net`)发送邮件,两者都已加入 Email Sending,并通过 CI 在每次 `main` 构建成功后将 Worker 部署到 Cloudflare。树中没有存储秘密:`POSTERN_API_TOKEN` 是一个 Worker 秘密,在部署时未被触及。
## 适用人群
自行托管、构建代理和邮件管理员,他们希望在 Cloudflare 上拥有一个属于自己的邮箱:一个可搜索的存储,一个适用于人类和代理的 API,包含 Webmail 和 IMAP。
## 链接
- **快速入门:** [DEPLOY.md](DEPLOY.md)
- **Skyphusion Labs:** https://skyphusion.org · **组织:** https://github.com/skyphusion-labs
- **相关:** [prism](https://github.com/skyphusion-labs/prism) (AI 游乐场), [search-mcp](https://github.com/skyphusion-labs/search-mcp)
## 许可证
此存储库中的服务器核心是 [AGPL-3.0-only](LICENSE):Postern 是您自行托管的软件,如果您为他人运行网络服务,则必须提供相同的源代码。
两个已发布的客户端集成是 MIT 许可的,因此可以轻松嵌入到任何代码库中:MCP 服务器 [`@skyphusion/postern-mcp`](mcp/LICENSE) 和 Python 客户端 [`postern-client`](clients/python/LICENSE)。每个包都附带自己的 `LICENSE` 和元数据,管理该包。
参见 [NOTICE](NOTICE) 了解简要版本, [PRIVACY.md](PRIVACY.md) 了解自行托管对数据的影响(简要版本:Skyphusion Labs 运营的是空的,因此我们不持有您的邮件)。