内容
# 浏览工具
一个用于浏览和搜索由 [notmuch](https://notmuchmail.org/) 索引的电子邮件存档的单静态二进制HTTP服务器。
浏览工具是我们所期望的存档阅读器。在依赖 [netviel](https://github.com/djcb/netviel) (notmuch附带的优秀Python/SPA前端)和经典的基于PHP的`notmore`多年后,我们希望结合两者的优点——一个精致的、以键盘驱动的Web界面和一个干净的编程API——所有这些都包含在一个自包含的二进制文件中,没有运行时文件依赖。
结果是一个快速的、本地优先的存档浏览器,使用Rust、Dioxus SSR和Axum构建。每个资产都在编译时嵌入。界面在没有JavaScript的情况下工作,并通过JavaScript增强:类似vim的导航、命令调色板、内联附件预览和通过cookie持久化的深色/浅色主题,以便服务器在首次加载时正确渲染。
**MCP(模型上下文协议)集成**是一等公民。连接Claude Desktop、Claude Code或任何MCP客户端到 `http://localhost:8000/mcp`,并以对话方式探索您的存档。AI可以搜索线程、以纯文本或markdown读取消息、从PDF/DOCX/XLSX附件中提取文本并总结对话——所有这些都不需要离开终端。
---
## 功能
- **单个静态二进制文件** — 所有CSS、JS、图标和模板都通过`include_str!`嵌入。没有运行时文件依赖。
- **键盘驱动的UI** — `j`/`k`导航线程,`o`打开,`/`搜索,`?`帮助,`⌘K`或`Ctrl+K`命令调色板。
- **精致的三列布局** — 标签/发件人侧边栏、线程列表和带有内联附件预览(PDF、图像、视频、文本)的阅读器窗格。
- **安全的电子邮件渲染** — HTML正文使用`ammonia`进行净化;纯文本正文转换为HTML,支持嵌套`<blockquote>`和自动链接URL。
- **本地`libnotmuch`集成** — 直接Rust绑定,无子进程生成。查询在5,000+消息的存档上返回<50ms。
- **自动初始化** — 将浏览工具指向邮件目录,它会在第一次运行时创建和索引notmuch数据库。
- **深色/浅色主题** — 基于cookie,以便服务器在第一个字节到达浏览器之前知道您的偏好。
- **JSON REST API** — 用于搜索、线程、附件、标签和统计的干净、文档齐全的端点。
- **MCP服务器** — 通过模型上下文协议进行AI辅助存档探索。搜索、读取、总结和从附件中提取文档文本,以对话方式进行。
---
## 快速入门
### 先决条件
- Rust工具链(稳定版,1.75+)
- `libnotmuch`开发库
- Debian/Ubuntu:`apt-get install libnotmuch-dev`
- Fedora:`dnf install notmuch-devel`
- Arch:`pacman -S notmuch`
### 构建
```bash
git clone https://github.com/daemonp/rummage.git
cd rummage
cargo build --release
```
二进制文件位于 `./target/release/rummage`。
### 运行
将其指向邮件目录。浏览工具会在第一次运行时自动创建和索引notmuch数据库:
```bash
# 自动创建和索引
./target/release/rummage --maildir ~/Mail/Archive --notmuch-config ~/.notmuch-config
# 强制完全重新索引并退出
./target/release/rummage --maildir ~/Mail/Archive --index
# 跳过自动初始化(如果数据库丢失,则失败)
./target/release/rummage --maildir ~/Mail/Archive --no-auto-index
# 绑定到不同的主机/端口
./target/release/rummage --maildir ~/Mail/Archive --host 0.0.0.0 --port 3000
```
然后打开 [http://127.0.0.1:8000](http://127.0.0.1:8000)。
### Docker
官方镜像基于Alpine Linux构建,具有最小的占用空间(~50 MB)。
**不需要notmuch配置文件** — 浏览工具会在第一次运行时自动创建和索引数据库。
```bash
# 本地构建
docker build -t rummage .
# 最简单的运行 — 只需挂载邮件目录
docker run -p 8000:8000 \
-v ~/Mail/Archive:/mail \
rummage
# 使用现有的notmuch配置(可选 — 用于自定义标签/钩子)
docker run -p 8000:8000 \
-v ~/Mail/Archive:/mail \
-v ~/.notmuch:/notmuch \
-e NOTMUCH_CONFIG=/notmuch/notmuch-config \
rummage
# 完整的生产设置
docker run -d --name rummage -p 8000:8000 \
-v /data/email:/mail \
-v $(pwd)/notmuch-config:/notmuch:ro \
-e RUMMAGE_MAILDIR=/mail \
-e RUMMAGE_HOST=0.0.0.0 \
-e RUMMAGE_PORT=8000 \
-e NOTMUCH_CONFIG=/notmuch/notmuch-config \
-e RUMMAGE_MCP_ALLOWED_HOSTS=email-archive.myawesomehouse.com \
ghcr.io/daemonp/rummage:master
```
**卷:**
| 路径 | 目的 | 是否必需 |
|---|---|---|
| `/mail` | 您的邮件目录存档。notmuch数据库在其中自动创建,路径为`/mail/.notmuch/`。 | **是** |
| `/notmuch` | 自定义`notmuch-config`文件的可选目录。 | 否 |
**环境变量:**
| 变量 | 默认值 | 描述 |
|---|---|---|
| `RUMMAGE_MAILDIR` | `/mail` | 邮件目录路径(通过镜像CMD设置) |
| `RUMMAGE_HOST` | `0.0.0.0` | 绑定地址 |
| `RUMMAGE_PORT` | `8000` | 监听端口 |
| `NOTMUCH_CONFIG` | `/notmuch/notmuch-config` | 标准notmuch配置路径(可选) |
| `RUMMAGE_NOTMUCH_CONFIG` | — | 浏览工具特定的覆盖(可选) |
| `RUMMAGE_MCP_ALLOWED_HOSTS` | `localhost,127.0.0.1,::1` | MCP DNS重新绑定保护的允许主机头 |
> **注意:** Notmuch在其数据库树内存储其数据库(`maildir/.notmuch/`)。没有单独的`database_path`选项 — 这是notmuch约定。如果您以只读方式挂载邮件目录,则自动初始化将失败;请以读写方式挂载或在本地预先构建索引。
---
## Web界面
浏览工具提供服务器渲染的HTML,带有轻量级JavaScript增强功能。界面在没有JavaScript的情况下完全工作,并针对速度进行渐进式增强。
### 键盘快捷键
| 键 | 操作 |
|---|---|
| `j` / `k` | 下一个/上一个线程 |
| `o` 或 `Enter` | 在阅读器窗格中打开选定的线程 |
| `↑` / `↓` | 在搜索结果中导航 |
| `/` | 聚焦搜索框 |
| `?` | 显示键盘快捷键帮助 |
| `u` | 打开选定线程的原始`.eml`文件 |
| `⌘K` 或 `Ctrl+K` | 打开命令调色板 |
### 命令调色板
按 `⌘K`(Mac)或 `Ctrl+K`(Linux/Windows)打开命令调色板。搜索运算符、跳转到保存的查询、切换主题或直接导航到帮助。
---
## JSON API
所有JSON端点均返回 `Content-Type: application/json`。相同的搜索也可以通过 `GET /search?q=…` 使用 `Accept: application/json` 进行。
| 方法 | 路径 | 描述 | 查询参数 |
|---|---|---|---|
| GET | `/api/search` | 搜索线程 | `q`(必需) |
| GET | `/api/thread/:id` | 获取线程中的消息 | 无 |
| GET | `/api/attachment` | 下载附件 | `msg`、`part` |
| GET | `/api/message/:id` | 下载原始`.eml`文件 | 无 |
| GET | `/api/tags` | 列出所有标签及其计数 | 无 |
| GET | `/api/stats` | 存档范围的统计信息 | 无 |
示例:
```bash
curl -H "Accept: application/json" "http://localhost:8000/search?q=from:alice%20since:2024-01-01"
```
---
## MCP — AI辅助存档探索
浏览工具在 `/mcp`(可流式传输的HTTP传输)处公开 [模型上下文协议](https://modelcontextprotocol.io/) 服务器。连接您的MCP客户端,并以对话方式探索您的存档。
### MCP可以执行的操作
- **搜索** — 通过自然语言或原始语法运行notmuch查询
- **读取线程** — 以纯文本、markdown或HTML获取完整对话
- **总结** — 要求AI总结线程、列出行动项或确定关键决策
- **提取附件** — 从PDF、DOCX、XLSX、PPTX和旧版DOC/XLS文件中提取文本(通过 [batdoc](https://github.com/daemonp/batdoc))
- **按标签和发件人浏览** — 在深入之前发现存档中有什么
- **查找相关线程** — 发现通过参与者、主题或标签连接的对话
### 配置
添加到您的MCP客户端(例如,Claude Desktop):
```json
{
"mcpServers": {
"rummage": {
"url": "http://localhost:8000/mcp"
}
}
}
```
MCP服务器默认情况下是只读的,并且在本地运行。无需凭证,无需云,无需数据离开您的机器。
---
## 配置
浏览工具从命令行标志和环境变量中读取配置。如果存在当前工作目录中的`.env`文件,则会自动加载。
| 标志 | 环境变量 | 默认值 | 描述 |
|---|---|---|---|
| `--maildir` | `RUMMAGE_MAILDIR` | — | 邮件目录存档路径 |
| `--notmuch-config` | `RUMMAGE_NOTMUCH_CONFIG` | — | notmuch配置文件路径 |
| `--port` | `RUMMAGE_PORT` | `8000` | HTTP服务器端口 |
| `--host` | `RUMMAGE_HOST` | `127.0.0.1` | HTTP服务器绑定地址 |
| `--index` | — | — | 强制重新索引并退出 |
| `--no-auto-index` | — | — | 跳过自动初始化 |
| `--no-webui` | — | false | 禁用HTML路由和静态资产 |
| `--no-mcp` | — | false | 禁用 `/mcp` 处的MCP传输 |
| `--mcp-allowed-hosts` | `RUMMAGE_MCP_ALLOWED_HOSTS` | `localhost,127.0.0.1,::1` | 用于MCP的允许主机头(反向代理安全) |
---
## 架构
- **Dioxus SSR** — 用Rust编写的服务器渲染HTML组件。相同的组件可以编译为本地/桌面应用程序。
- **Axum** — 带有安全标头(CSP,X-Frame-Options)中间件的轻量级异步HTTP服务器。
- **单个阻塞DB工作线程** — `libnotmuch`不是线程安全的(它在内部使用`Rc<>`)。所有数据库访问都通过专用`spawn_blocking`工作线程序列化,该线程通过`mpsc`通道接收请求。
- **mail-parser** — 用于正文提取和附件处理的纯Rust MIME解析。
- **ammonia** — HTML净化。剥离`<script>`、事件处理程序和危险属性。
- **linkify** — 在纯文本正文中自动链接URL和电子邮件地址。
- **batdoc-core** — 用于MCP附件读取的纯Rust文档文本提取。
---
## 致谢
浏览工具建立在两个优秀项目的肩膀上,它们为notmuch社区服务了多年:
- **[netviel](https://github.com/djcb/netviel)** — 随notmuch附带的Python/SPA前端。其干净的API和快速搜索为存档浏览设定了标准。我们使用了多年,并从中学习了很多。
- **notmore** — 经典的PHP服务器渲染接口,证明了无需沉重的客户端框架即可简单有效地浏览电子邮件存档。
我们结合了两者的最佳创意:netviel的速度和API,以及notmore的简单性和服务器渲染的可靠性,然后添加了一层现代的Rust工具和通过MCP的AI可访问性。
---
## 许可证
MIT