内容
<h1 align="center">欢迎使用 protonmail-rs 👋</h1>
> 一个非官方的、纯 Rust 实现的 Proton Mail 客户端 — 库、命令行工具和 MCP 服务器。
一个非官方的、纯 Rust 实现的 **Proton Mail** 客户端:一个库 (`proton-core`),一个命令行工具 (`protonmail-cli`),和一个 MCP 服务器 (`proton-mcp`)。端到端 OpenPGP 加密和 SRP 身份验证与官方 Proton 客户端兼容,基于 Proton 自己的 Rust crates 实现。
> 非官方,不隶属于 Proton AG。请自行承担风险。
已针对实时账户验证:SRP 登录(包括验证码)、会话恢复、密钥解锁、**发送**(端到端加密)、**列表**、**阅读 + 解密 + 签名验证** 均可正常工作。
---
## 工具列表
| Crate (crates.io) | 二进制文件 | 角色 |
|---|---|---|
| [`proton-core`](https://crates.io/crates/proton-core) | — | SDK — 传输、身份验证、加密、模型、API、邮件服务 |
| [`protonmail-cli`](https://crates.io/crates/protonmail-cli) | `protonmail-cli` | 命令行前端(clap) |
| [`proton-mcp`](https://crates.io/crates/proton-mcp) | `proton-mcp` | MCP 服务器,向 LLM 代理公开邮件工具(rmcp) |
需要 Rust **≥ 1.96**。
```bash
# 从 crates.io 安装:
cargo install protonmail-cli # -> protonmail-cli 二进制文件
cargo install proton-mcp # -> proton-mcp
# 或从源代码构建:
cargo build --release # -> target/release/{protonmail-cli, proton-mcp}
```
---
## 功能列表 — `proton-core`(SDK)
### 身份验证
- **SRP 登录**(SRP-6a)通过 `proton-srp` — 服务器签名的模数验证,客户端/服务器证明交换,哈希版本 V0–V4。
- **双因素身份验证(TOTP)**。
- **双密码账户** — 读取 `PasswordMode`;支持独立的邮箱密码。
- **人类验证 / 验证码** — 可插拔的解析器,API 代码 9001(重试带有 `x-pm-human-verification-token`)。
- **会话持久性** — 每个配置文件,多配置文件;非机密元数据存储在磁盘上(0600),机密(令牌 + 密钥口令)存储在 **OS 密钥链**(`keyring`)。
- **会话恢复** — 从保存的会话重新打开 + 解锁密钥,无需重新输入密码。
- **令牌刷新** — 自动刷新 401(旋转令牌持续),单次重试。
- **注销** — 服务器端会话撤销 + 本地清除。
- **客户端伪装** — 可配置的 `x-pm-appversion` + `User-Agent`(网页 / iOS / Android 预设)。
### 加密(纯 Rust,无 cgo)
- **密钥层次解锁** — 用户密钥(bcrypt 邮箱密码 KDF → 密钥口令)和地址密钥(每个密钥令牌解密 + **签名验证**,跳过坏令牌)。
- **邮箱密码 KDF** — bcrypt,最后 31 个字节约定,与主用户密钥匹配的盐。
- **消息体解密**,带有 **签名判决**(`Verified` / `Unsigned` / `Unverified` / `Invalid`);非致命签名失败。
- **MIME 提取** — `multipart/*` 正文解析(`mail-parser`)到可显示的文本/HTML 部分。
- **附件解密** — 密钥包 → 会话密钥 → 数据包。
- **外出加密** — 新鲜的 AES-256 会话密钥,加密 + 签名正文;每个收件人的会话密钥包装;自加密存储草稿。
- **附件加密** — 会话密钥 + 数据包 + 分离签名;转发时重新加密。
### 传输
- `reqwest`(rustls TLS,cookie 存储);基本 URL + 应用程序版本可配置。
- Proton 信封处理(`Code` 1000/1001 = 成功)。
- 自动重试:**401 → 刷新**,**429 → Retry-After 回退**,**9001 → 人类验证**。
- 类型错误,带有 CLI 退出代码映射。
### 邮件功能
- **阅读**:列出消息,列出对话(线程),阅读消息(解密 + 判决),阅读完整线程(延迟加载 + 解密每个),计数。
- **搜索**(服务器端):关键词,来自,至,主题,日期范围,文件夹,未读。
- **发送**:撰写,**回复 / 回复所有 / 转发**(转发重新加密原始附件),**计划发送**,**过期/自毁**,**取消计划发送**。内部 = 完整的 **端到端加密**(类型 1);**外部带有 PGP/WKD 密钥 = PGP-inline(类型 8)**;无密钥外部 = 明文(类型 4,警告)。
- **附件**:列出,下载(解密)单个/所有,上传(加密)发送。
- **组织**:移动到文件夹,垃圾桶,永久删除,标记已读/未读,星标/取消星标,应用/删除标签 — **适用于消息和对话**。
- **标签/文件夹**:列出,创建,删除。
- **草稿**:保存/编辑/列出/删除(无需发送)。
- **Sieve 过滤器**:列出/创建(原始 Sieve)/验证/删除/启用/禁用。
- **联系人**(读取):列出联系人和联系人邮箱;**地址**列表。
- **本地缓存 + 同步**:SQLite 缓存由 Proton **事件流**(`sync`)提供;离线缓存读取(`list --cached`)。
- **加密全文搜索**:在解密的正文上构建本地 **FTS5** 索引(`index`)并私密地/离线搜索它们(`search`)— 服务器永远不会看到查询。
### 可观察性
- **详细日志记录**(`tracing`)— `init_tracing(verbose)`;记录每个登录阶段,密钥解锁步骤,加密/解密操作,发送管道阶段和 HTTP 请求/响应。绝不会记录机密和明文。
---
## `protonmail-cli` — 命令
每个命令和标志都在 **[docs/CLI.md](docs/CLI.md)** 中记录(从 `--help` 生成)。完整界面的快速参考:
```
protonmail-cli [GLOBALS] <command>
GLOBALS: --profile --json -v/-vv/-vvv --api-url --app-version --client web|ios|android
--user-agent --totp --mailbox-password --captcha-token --captcha-chrome
ENV: PROTON_USER PROTON_PASSWORD PROTON_TOTP PROTON_MAILBOX_PASSWORD PROTON_HV_TOKEN RUST_LOG
COMPOSE (send/reply/forward/drafts save|edit): --to --cc --bcc --from --subject
--body <text|-> --html --attach <file> --send-at <ts> --expires <secs>
--eo-password --eo-hint # send only: encrypted-outside for keyless recipients
login | logout | whoami
messages list [--folder inbox] [--page --page-size --unread --cached] | search [filters] |
read <REF> [--format text|html|raw] [--body-only] [--output <file>] |
send <COMPOSE> | reply <REF> [--all] | forward <REF> --to | cancel-send <REF> |
spam <REF…> | ham <REF…> | unsubscribe <REF> | empty <folder> | undelete <ID…> |
receipt <REF> | label <add|rm> <LABEL_ID> <REF…> |
move <REF…> --dest | trash <REF…> | delete <REF…> |
mark <read|unread> <REF…> | star <REF…> | unstar <REF…>
conversations list | search | read <ID> | move <ID…> --dest | trash <ID…> |
mark <read|unread> <ID…> | star | unstar |
snooze <ID…> (--until <ts> | --in 30m|2h|1d) | unsnooze <ID…>
attachments list <MSG> [--include-inline] | download <MSG> [<ATT>] [--output-dir|--all|--include-inline]
drafts list | save <COMPOSE> | edit <ID> <COMPOSE> | delete <ID…>
filters list | create --name --sieve <-|text> | check --sieve | delete|enable|disable <ID>
labels list [--folders] | create --name [--color --folder --parent] | delete <ID…> |
update <ID> [--name --color --parent]
contacts list | emails [--email]
addresses list | update <ID> [--display-name --signature]
settings get | sign <on|off> | attach-public-key <on|off>
counts [--conversations]
export --out <dir> [--folder all] [--max 100] # write messages to .eml files
watch [--interval 30] [--folder <f>] # continuous cache sync until ^C
sync [--backfill <folder>] # one-shot event-stream sync
index [--folder all] [--max-pages --page-size] # build local encrypted FTS index
search <query> [--limit 25] # query the local FTS index (offline)
```
`<REF>` = 确切的消息 ID 或自由文本(唯一搜索匹配);`<ID>` = 确切的 ID。任何命令都带有 `--json` 以输出机器可读内容。验证码:登录自动打开它;通过控制台代码片段/书签解决,或传递 `--captcha-token`,或 `--captcha-chrome`(隔离,自动关闭窗口)。
---
## `proton-mcp` — MCP 服务器(适用于 LLM 代理)
重用 `protonmail-cli login` 会话(代理永远不会看到密码)。传输:**stdio**(默认)和 **Streamable HTTP**(`--http <addr>`)。通过 `-v` 详细记录。源代码是 `src/tools/` 下的**一个文件**。
**56 个工具** — 与 CLI 完全兼容(除身份验证/监视/导出外):
- **消息 — 读取:** `list_messages`,`search_messages`,`read_message`,`list_attachments`,`download_attachment`,`list_labels`,`counts`。
- **消息 — 写入:** `send_message`,`reply_message`,`forward_message`,`cancel_scheduled_send`,`move_message`,`trash_message`,`delete_messages`,`undelete_messages`,`empty_folder`,`report_spam`,`report_ham`,`unsubscribe`,`send_read_receipt`,`mark_read`,`star_message`,`apply_label`,`remove_label`。
- **对话:** `list_conversations`,`read_conversation`,`search_conversations`,`move_conversation`,`trash_conversation`,`mark_conversation`,`star_conversation`,`snooze_conversation`,`unsnooze_conversation`。
- **草稿:** `list_drafts`,`save_draft`,`update_draft`,`delete_draft`。
- **过滤器(Sieve):** `list_filters`,`create_filter`,`check_filter`,`delete_filter`,`enable_filter`,`disable_filter`。
- **标签/文件夹:** `create_label`,`delete_label`,`update_label`。
- **设置/地址/联系人:** `get_settings`,`set_sign`,`set_attach_public_key`,`list_addresses`,`update_address`,`list_contacts`,`list_contact_emails`。
- **本地缓存/搜索:** `sync_cache`,`index_cache`,`search_local`。
**安全性:** 破坏性/结构性工具(发送,移动,垃圾桶,**删除**,**清空文件夹**,草稿,过滤器,标签,设置,...)需要 `confirm` 并返回**预演**,除非 `confirm: true`(或服务器启动时带有 `--allow-writes`);`empty_folder`/`delete_messages` 预演带有明确的不可逆警告。良性切换(`mark_*`,`star_*`,`snooze_*`)和所有读取操作直接执行。发送默认使用您的**主地址**(按 `Order` 的第一个别名)— 传递 `from` 以选择另一个别名。读取返回**签名判决**;验证码从不自动解决(返回“运行 `protonmail-cli login`”)。
**Claude Desktop 配置:**
```json
{ "mcpServers": { "proton-mail": {
"command": "/abs/path/protonmail-rs/target/release/proton-mcp",
"args": ["--profile","default"] } } }
```
---
## 详细/调试
```bash
protonmail-cli -vv whoami # login/resume + key unlock, step by step
protonmail-cli -vv messages read <ID> # + decryption + signature verdict
protonmail-cli -vv messages send … # + full send pipeline
RUST_LOG=proton_core::http=debug … # just HTTP
proton-mcp -vv --profile default # MCP verbose (to stderr)
```
## 测试
```bash
cargo test --workspace # offline: crypto round-trips, transport, HV, api, cli, mcp
# live (real account; opt-in):
PROTON_TEST_USER=… PROTON_TEST_PASSWORD=… [PROTON_TEST_TOTP=…] [PROTON_TEST_SEND=1] \
cargo test -p proton-core --test live -- --nocapture --test-threads=1
```
## 安全
- 邮箱密码从不以明文写入磁盘;密钥口令 + 令牌存储在 OS 密钥链中。
- 地址密钥令牌签名在解锁时验证;SRP 服务器证明 + 签名模数在登录时验证。
- 通过 rustls 进行 TLS。详细日志排除所有机密和明文。
## 范围/延迟
已实现:完整的邮件(读取/线程,搜索,发送/回复/转发包括 **PGP 外部** 和 **加密外部**,附件,组织),**草稿**,**Sieve 过滤器**,**邮件设置(读取)+ 垃圾邮件/汉姆/取消订阅/清空文件夹/延迟**,**联系人(读取)+ 地址**,**事件同步 + SQLite 缓存**,**本地加密全文搜索**,**消息正文的 HTML 净化**,CLI,MCP,验证码,详细日志记录。
**未实现(故意,避免未经测试的代码):**
- **密钥透明度**(纪元/VRF/证书透明度链)— `proton-crypto` 仅公开结果类型;完整的验证是一项大型独立工作。收件人密钥被信任为服务器返回它们。
- **FIDO2/WebAuthn 2FA** — 需要硬件密钥 + CTAP 客户端 + 现场测试;登录**检测** FIDO2 仅限账户并返回明确的错误。使用 TOTP 或应用程序/桥接密码。
- 远程图像代理,密钥/地址管理(生成/轮换),自动回复/假期,Drive / Calendar / Pass。
---
## 贡献
欢迎提出问题和 PR — 请参阅 [CONTRIBUTING.md](CONTRIBUTING.md)。在打开 PR 之前运行 `cargo fmt --all --check`,`cargo clippy --all-targets --all-features -- -D warnings`,和 `cargo test --workspace`。发布流程: [RELEASING.md](RELEASING.md)。
## 安全
此客户端处理凭证、私钥和明文邮件。请根据 [SECURITY.md](SECURITY.md) 私密报告漏洞 — 不要公开提出问题。
## 许可证
[MIT](LICENSE) © Filippo Finke。
> **免责声明:** 非官方,不隶属于或获得 Proton AG 的认可。“Proton”,“Proton Mail”及相关商标归 Proton AG 所有。请自行承担风险。
## 作者
👤 **Filippo Finke**
- 网站:https://filippofinke.ch
- Github:[@filippofinke](https://github.com/filippofinke)
- LinkedIn:[@filippofinke](https://linkedin.com/in/filippofinke)
## 显示您的支持
如果该项目对您有帮助,请给一个 ⭐️!
<a href="https://www.buymeacoffee.com/filippofinke">
<img src="https://github.com/filippofinke/filippofinke/raw/main/images/buymeacoffe.png" alt="Buy Me A McFlurry">
</a>