内容
<!-- mcp-name: io.github.BigCactusLabs/dead-letter -->
<p align="center">
<img src="docs/brand/production/readme-logo.png" width="128" alt="dead-letter">
</p>
# dead-letter
[](https://pypi.org/project/dead-letter/)
[](https://pypi.org/project/dead-letter/)
[](LICENSE)
**您的 `.eml` 文件值得第二次生命。**
dead-letter 将电子邮件导出转换为干净的 Markdown,并附带 YAML 前置信息 — 线程拆分、签名剥离、附件提取、日历解析。一个文件或一万个。
## ✨ 功能
- **高保真转换** — HTML 净化、Gmail/Outlook 线程分割、内联图像处理和日历事件摘要
- **命令行界面** — 指向一个文件或目录即可
- **本地网页界面** — 黑色指挥中心界面,支持拖放导入、监视模式、转换等级徽章、处理历史和每任务诊断
- **收件箱/文件柜工作流** — 将 `.eml` 文件放入收件箱,让 dead-letter 将 Markdown 包组织到文件柜中
- **安装验证** — `dead-letter doctor` 检查您的运行时环境
- **转换报告** — 可选的 JSON 报告,包含每个文件的诊断信息,包括附件引用/保留计数,用于自动化和审计
- **MCP 服务器** — 与 Claude Desktop、Claude Code、Codex 等 MCP 客户端集成
- **Claude 插件** — 一键安装在 Claude Code 或 Cowork 中,支持四个斜杠命令(`/dead-letter:convert`、`/dead-letter:summarize`、`/dead-letter:triage`、`/dead-letter:cabinet`)
- **Python API** — `from dead_letter import convert` 即可开始
## 🧠 为 LLM 管道而建
原始 `.eml` 文件是下游 LLM 和检索管道的嘈杂输入 — MIME 头、 multipart 边界、重复的 HTML/纯文本正文和编码附件都混入文本路径中。
dead-letter 将其标准化为带有 YAML 前置信息的 Markdown,以便消息文本和元数据在无需 MIME 解析或 base64 清理的情况下即可用于分块或索引。默认的 `convert()` 和 `convert_dir()` 运行会为每个消息写入单个 `.md` 文件,并将附件名称保留在前置信息中。
如果您希望文件系统工件也分开,捆绑和文件柜工作流程会写入 `message.md` 以及在 `attachments/` 下保留的解码文件。Markdown 准备好进行文本摄取,而 PDF、电子表格、日历文件和其他保留的二进制附件保持清洁地分开,以便您已经使用的下游解析器。
对于直接的 LLM 集成,MCP 服务器允许 Claude Desktop、Claude Code、Codex 等 MCP 客户端直接调用 dead-letter 的转换工具,而无需使用 shell。
### 📊 Token 成本基准
dead-letter 的价值不在于比其他所有替代方案更少的 token — 而在于 **每个 token 的保真度**:最廉价的表示方式可以保持电子邮件 *完整*。在合成的 HTML 线程、附件和新闻稿语料库中测量(tokenizer `o200k_base`,中位数):
- **比原始 `.eml` 少约 88% 的 token** — 带有 PDF 附件的单个电子邮件原始约 126k token,而转换后约 180 token。
- **唯一保留电子邮件完整的表示方式** — 线程结构、每个消息的发件人归属、链接和附件元数据都得以保留。朴素的文本提取更便宜,正是因为它 *丢弃* 了它们(0/2 附件保留,而 dead-letter 保留 2/2)。
基准测试对其损失持开放态度:当您不介意丢弃附件、链接和线程结构时,朴素提取的 token 数量更少。完整方法、完整表格(包括这些行)、tokenizer 公开和一键重现都在 [`benchmarks/`](benchmarks/) 中。
## 📦 安装
在 Apple silicon macOS 上使用 Homebrew:
```bash
brew tap BigCactusLabs/tap
brew install dead-letter
```
Homebrew 公式仅安装核心命令行界面:`dead-letter convert` 和 `dead-letter doctor`。它故意不包含可选的网页界面或 MCP 服务器依赖项堆栈。
使用 pip:
```bash
pip install dead-letter # 核心 + 命令行界面
pip install dead-letter[cli] # + 监视文件(用于后端/网页监视模式)
pip install dead-letter[ui] # + 网页界面、API 服务器和监视模式
pip install dead-letter[mcp] # + MCP 服务器
```
使用 [pipx](https://pipx.pypa.io/) 进行隔离的网页界面或 MCP 安装:
```bash
pipx install 'dead-letter[ui]' # 安装 dead-letter 和 dead-letter-ui
pipx install 'dead-letter[mcp]' # 安装 dead-letter 和 dead-letter-mcp
```
从源代码:
```bash
git clone https://github.com/BigCactusLabs/dead-letter.git
cd dead-letter
uv sync --extra dev # 所有额外功能
uv sync --extra ui # 仅网页界面
uv sync --extra mcp # 仅 MCP 服务器
```
## 🚀 快速开始
**命令行界面** — 转换单个文件:
```bash
dead-letter convert message.eml
```
转换整个目录:
```bash
dead-letter convert inbox/ --output out/
```
生成 JSON 转换报告:
```bash
dead-letter convert inbox/ --output out/ --report
```
检查运行时环境:
```bash
dead-letter doctor
```
目录转换递归扫描 `.eml` 文件,区分大小写后缀,跳过符号链接文件,并重复在树内解析别名。
**网页界面** — 启动本地服务器:
```bash
dead-letter-ui --host 127.0.0.1 --port 8765
```
打开 `http://127.0.0.1:8765` — 在首次启动时,设置提示建议默认收件箱和文件柜文件夹。配置或跳过以开始转换。使用拖放或文件选择器导入 `.eml` 文件。单个文件导入使用文件模式,而多文件拖放创建单个目录模式批处理作业。混合拖放在跳过非 `.eml` 文件之前请求确认。
## 🐍 Python API
```python
from dead_letter import convert
result = convert("message.eml")
print(result.subject, result.sender)
print(result.output) # 生成的 .md 文件的路径
```
带有选项:
```python
from dead_letter import convert, ConvertOptions
result = convert("message.eml", options=ConvertOptions(
strip_signatures=True,
strip_quoted_headers=True,
))
```
剥离签名图像(徽标,社交图标)和跟踪像素:
```python
result = convert("message.eml", options=ConvertOptions(
strip_signature_images=True,
strip_tracking_pixels=True,
))
```
启用后,这些过滤器会从渲染的 Markdown 中删除匹配的图像,并从捆绑附件输出中省略剥离的内联签名/跟踪资产。
捆绑转换(Markdown + 附件 + 源在一个目录中):
```python
from dead_letter import convert_to_bundle
bundle = convert_to_bundle("message.eml", bundle_root="cabinet/", source_handling="copy")
print(bundle.markdown) # cabinet/message/message.md
print(bundle.attachments) # 在 cabinet/message/attachments/ 下保留的提取文件
```
`source_handling="copy"` 保留原始 `.eml` 文件。如果省略,`convert_to_bundle()` 默认 `source_handling="move"` 并将源消息移动到捆绑中。
保留的提取附件文件名在写入 `attachments/` 之前规范化为安全基准名称。
质量诊断包括引用/保留附件计数,当消息具有可保留的附件时,以便机器可检测丢弃的工件。参见 [质量诊断](docs/reference/quality-diagnostics.md)。
批处理:
```python
from dead_letter import convert_dir
for r in convert_dir("inbox/", output="out/"):
print(f"{'✓' if r.success else '✗'} {r.source.name}")
```
## 🔌 MCP 服务器
dead-letter 配备了一个 [MCP](https://modelcontextprotocol.io/) 服务器,以便 LLM 客户端可以直接转换 `.eml` 文件,而无需使用 shell。
安装和启动:
```bash
pip install dead-letter[mcp]
dead-letter-mcp
```
从源代码检出:
```bash
uv run --extra mcp dead-letter-mcp
```
**Claude Desktop** — 添加到 `claude_desktop_config.json`:
```json
{
"mcpServers": {
"dead-letter": {
"command": "uv",
"args": ["--directory", "/path/to/dead-letter", "run", "--extra", "mcp", "dead-letter-mcp"]
}
}
}
```
**Claude Code 或 Cowork(推荐 - Claude 插件):**
```
/plugin marketplace add BigCactusLabs/bigcactuslabs-plugins
/plugin install dead-letter
```
该插件捆绑了 MCP 服务器(通过 `uvx`,无需 `pip install` — 仅需 `uv` 在 `PATH` 上),并添加了四个斜杠命令:`/dead-letter:convert`、`/dead-letter:summarize`、`/dead-letter:triage`、`/dead-letter:cabinet`。通过插件处理的电子邮件内容被视为不受信任的数据,而不是指令,因此不会遵循工具使用、凭证和消息中嵌入的提取请求。源代码位于 [`plugin/`](plugin/)。
市场通过此仓库的 `release` 分支分发插件,该分支仅在发布版本时移动;捆绑的 MCP 服务器固定到确切的 PyPI 版本,因此安装是可复制的,仅在发布版本时自动更新。
**Claude Code(手动 MCP 添加 - 替代方案):**
```bash
claude mcp add dead-letter -- uv run --extra mcp dead-letter-mcp
```
**Codex:**
```bash
codex mcp add dead-letter -- uv run --extra mcp dead-letter-mcp
codex mcp list
```
`codex mcp add` 命令注册本地 `dead-letter` MCP 服务器,`codex mcp list` 验证其可用性。
## 🗂 项目结构
```
src/dead_letter/
├── core/ # 转换管道(MIME,HTML,线程,渲染)
├── backend/ # 命令行界面,API 服务器,作业运行器,监视模式,MCP 服务器
└── frontend/ # 静态网页界面(Alpine.js ES 模块 + 普通 fetch)
tests/
├── core/ # 转换管道测试,带有 .eml 固定装置
├── backend/ # API,作业和监视测试
├── plugin/ # Claude 插件清单,技能和命令测试
└── frontend/ # JavaScript 单元测试
```
## 🧪 测试
```bash
uv run pytest -q tests/core # 转换管道
uv run pytest -q tests/backend # API 和作业运行器
uv run pytest -q tests/plugin # Claude 插件清单,技能和命令表面
node --test tests/frontend/*.test.js # 前端
```
CI 在 PR 和推送到 `main` 或 `feat/**` 分支时运行所有四个命令,使用的命令相同,加上
`npx --yes @anthropic-ai/claude-code@2.1.145 plugin validate plugin/` 和
`node --check src/dead_letter/frontend/static/app.js`.
## 📚 文档
- [文档索引](docs/README.md) — 公共文档登录页面
- [运行时契约](docs/reference/v4-runtime-contracts.md) — 完整 API 和核心行为规范
- [前端状态模型](docs/reference/frontend-state-model.md)
- [质量诊断](docs/reference/quality-diagnostics.md)
- [品牌和样式指南](docs/brand/style-guide.md)
- [变更日志](CHANGELOG.md)
- [贡献](CONTRIBUTING.md)
- [代理指南](AGENTS.md) — 在此仓库中为 AI 编程代理提供的操作指南
## 🔧 我们喜欢的工具
- **[MarkEdit](https://github.com/MarkEdit-app/MarkEdit)** — Markdown 的 TextEdit,原生 macOS,约 4 MB。在此处打开 dead-letter 输出,就像它诞生时一样。
- **[mo](https://github.com/k1LoW/mo)** — 本地 Markdown 查看器,在浏览器中渲染文件并实时重新加载。将它指向您的文件柜,并像阅读订阅源一样阅读转换后的邮件。
## ⚠️ 已知限制
- 仅限本地 — 无远程服务器,无身份验证
- 内存作业注册表(状态在重启时重置)
- 单用户,单机
## License
[PolyForm Noncommercial 1.0.0](LICENSE) — 免费用于个人,教育和非营利用途。商业用途需要从 [Big Cactus Labs](https://github.com/BigCactusLabs) 获取单独的许可证。