内容
center">
<img src="apps/web/public/submail-logo.png" alt="Submail logo" width="112" height="112">
</p>
<h1 align="center">Submail</h1>
<p align="center"><strong>一个自托管的统一收件箱,适用于人类和AI代理。</strong></p>
<p align="center">连接您已经使用的邮箱,从一个Web界面管理它们,并通过MCP和HTTP提供精心范围的电子邮件工具。</p>
<p align="center">
<a href="README.md">English</a> · <a href="README.zh-CN.md">简体中文</</p>
<p align="center">
<a href="https://github.com/guozhijian611/submail/actions/workflows/ci.yml"><img alt="CI" src="https://github.com/guijian611/submail/actions/workflows/ci.yml/badgea>
<img alt="Node.js 22+" src="img.shields.io/badge/Node.js-22%2B-339933?logo=nodedotjs&logoColor=white">
<img alt="TypeScript" src="https://img.shields.io/badge/TypeScript-5.8-3178C6?logo=typescript&logoColor=white">
<img alt="Docker Compose" src="https://img.shields.io/badge/Docker-Compose-2496ED?logo=docker&logoColor=white">
<img alt="Model Context Protocol" src="https://img.shields.io/badge/MCP-Streamable_HTTP-5A45FF">
</p>
<p align="center">
<a href="#为什么选择Submail">为什么选择Submail</a> ·
<a href="#截图">截图</a> ·
<a href="#快速开始">快速开始</a> ·
<a href="#MCP和发送API">MCP和API</a> ·
<a安全模型">安全</a>
</p>

> [!NOTE]
> Submail不是一个邮件服务器,不会取代Gmail、邮箱或您现商。它连接现有的IMAP/POP3邮箱,通过其发送邮件,并为人员和代理提供一个受控的工作## 为什么选择Submail
| | |
| --- | --- |
| **一个收件箱,多个账户** | 跨多个邮箱搜索、阅读、回复、转发、标记、归档和管理附件。 |
| **为代理构建** | 使用本地、远程Streamable HTTP MCP或直接HTTP发送API,无需维护单独的集成。 |
| **默认权限** | 每个密钥都按功能、邮箱、过期时间和每日发送配额进行范围限定。新密钥以只读权限启动。 |
| **您的数据,您的部署** | 使用SQLite本地运行或使用Docker、Redis/BullMQ和SQLite或MySQL部署。 |
## 功能
账户:** IMAP3接收,SMTP发送,连接测试,提供商预设,应用密码指导和已验证的发送别名。
- **增量同步:** IMAP UID和POP3 UIDL游标,远程读取/星级协调,可发现的特殊文件夹(包括垃圾邮件/垃圾箱),计划作业,有界重试,并发限制和同步历史。
- **统一工作流:** 收件箱,已发送,草稿,已标记,已归档,垃圾邮件,回收站,会话线程,搜索和批量操作。
- **附件:** 同步后集中存储,按需浏览器检索,`.eml`解析,保留设置和广泛的浏览器预览支持。
- **AI辅助:** 兼容OpenAI的提供商,用于摘要,建议的回复和电子邮件撰写的内容放置在编辑器永远不会自动发送。
- **翻译:** Google兼容reTranslate或自定义HTTP提供商,带有长消息分配置的默认语言和对明确检测到的英文邮件的自动翻译(需开启)。
- **MCP和API:** 八个MCP工具和一个直接发送端点,共享相同的授权服务。
- **操作:** 健康检查,最小权限耐用Redis队列,审核保留,SQLite在线备份和。
## 截图
<table>
<tr>
<td width="50%">
<img src="docs/images/subcp-access.jpg" alt="MCP范围和API访问设置 <br><strong>MCP和API访问</strong><账户范围,功能范围,到期时间和每日发送限制。
td>
<td width="50%">
<img src="docs/images/submail-compose.jpg" alt="AI辅助电子邮件撰写器">
<br><strong>AI辅助撰</strong><br>使用AI撰写,审查结果,然后决定是否发送。
</td>
</tr>
</所有截图都使用临时SQLite数据库和合成的`.local`地址。不包含生产邮箱数据。
## 快速开始
### Docker部署
安装带有Compose插件的Docker引擎,然后运行:
```bash
git clone https://github.com/guozhijian611/submail.git
cd submail
./deploy.sh
```
设置脚本允许您选择SQLite、捆绑的MySQL或外部MySQL。它生成密钥,启动Redis和所有服务,构建镜像并等待健康检查。
网关默认绑定到`127.0.0.1:8080`。在将其暴露给互联网之前,请在其前面放置Caddy、Nginx、Tra或带有HTTPS的负载均衡器。
参见完整的[部署指南](docs/deployment.md),了解首位管理员设置、数据库模式、备份/恢复和升级。
### 本地开发
需求:Node.js 22+。
```bash
npm ci
npm run secure:local
npm run dev
```
- Web界面:`http://localhost:5173`
- API:`http://localhost:8787`
- 本地数据库:`apps/api/data/submail.sqlite`
- 队列:默认情况下为内存;设置`SUBMAIL_QUEUE_DRIVER=redis`和`SUBMAIL_REDIS_URL`以测试Redis
`npm run secure:local`创建一个`.env`文件,模式为`600`,并附有专用的主密钥。如果旧的本地数据库仍使用开发密钥,脚本会备份它并重新加密存储的邮箱和集成凭证,而不会打印密钥。
质量检查:
```bash
npm run typecheck
npm test
npm run build
```
## MCP和发送API
在**设置 → MCP 和管理**中创建密钥,选择其范围和允许的邮箱,然后使用远程端点:
```text
https://mail.example.com/mcp
```
每个请求都带有密钥:
```http
Authorization: Bearer sk_submail_xxx
```
可用工具:
| 组 | 工具 |
| --- | --- |
| 读取 | `list_accounts`, `search_mail`, `read_mail` |
| 发送 | `send_mail` |
| AI | `summarize_mail`, `draft_reply`, `compose_mail` |
| 翻译 | `translate_mail` |
本地stdio模式:
```bash
SUBMAIL_API_URL=http://127.0.0.1:8787 \
SUBMAIL_MCP_API_KEY=sk_submail_xxx \
npm run dev:mcp
```
直接发送API:
```bash
curl --fail-with-body 'https://mail.example.com/api/send' \
-H 'Authorization: Bearer sk_submail_xxx' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: order-20260710-0001' \
--data '{
"accountId": "mailbox-account-id",
"to": ["receiver@example.com"],
"subject": "Hello from Submail",
"text": "Sent through the Submail API"
}'
```
API支持文本,HTML,CC/BCC,附件,线程头,幂等键和可选的验证别名。MCP `send_mail`使用相同的传递路径。
## 安全模型
> [!IMPORTANT]
> 电子邮件和附件是不可信的输入。请在HTTPS后面部署,授予最小的范围,保持发送配额低,并在提供商支持时使用应用特定的邮箱密码。
- 邮箱凭证和第三方API密钥使用`SUBMAIL_SECRET`通过AES-GCM加密存储。
- 管理员密码和MCP/API密钥存储为单向哈希;新密钥仅显示一次。
- 密钥可以按功能、邮箱、过期时间和每日发送配额进行限制。
- AI输出永远不会自动发送;它进入编辑器供人类审查。
- 审计日志记录元数据而不是消息正文、提示、电子邮件地址、附件Base64或幂等密钥。
- `SUBMAIL_SECRET`与加密数据绑定。请单独备份它,并在存储凭证后永远不要随意轮换它。
请通过 [GitHub安全通告](../../security/advisories/new) 私密地报告漏洞。在报告之前请阅读 [SECURITY.md](SECURITY.md)。
## 架构
```mermaid
flowchart LR
Browser["浏览器"] --> Web["React + Vite / Nginx"]
Agent["AI / MCP 客户端"] --> MCP["MCP 服务器"]
Web --> API["Express API"]
MCP --> API
API --> DB["SQLite / MySQL"]
API --> Queue["内存 / Redis + BullMQ"]
API --> Mail["IMAP / POP3 / SMTP"]
API --> Services["AI 和翻译提供商"]
```
| 路径 | 责任 |
| --- | --- |
| `apps/web` | React 邮件客户端和管理界面 |
| `apps/api` | 身份验证,邮件同步/发送,存储,队列,AI,翻译,备份和恢复 |
| `apps/mcp` | stdio 和 Streamable HTTP MCP 传输 |
| `scripts` | 本地密钥强化和真实提供商集成检查 |
| `tests` | API,POP3,HTTP MCP,运行时锁定和恢复集成测试 |
| `docs` | 部署操作和功能差距文档 |
## 当前边界
- IMAP同步INBOX以及可发现的已发送、草稿、垃圾邮件/垃圾箱、回收站和存档文件夹,包括远程读取/星级标志。Gmail存档源自All Mail标签(如果可用)。POP3只能读取INBOX。
- 读取、星级、归档和删除状态目前是本地的,不会写回IMAP。
- 尚未实现Gmail和Microsoft OAuth、DKIM签名、DSN退信处理和队列仪表盘。
- SQLite和MySQL数据不会在驱动程序之间自动迁移。
- 默认的免费Google翻译路径是尽力而为的,不适用于机密电子邮件或严格的SLA。自动翻译默认禁用,因为启用它会发送打开的英文电子邮件内容到配置的提供商。
详细实施审查和路线图位于 [docs/gap-review.md](docs/gap-review.md)。
## 贡献
欢迎提出问题和拉取请求。从 [CONTRIBUTING.md](CONTRIBUTING.md) 开始,保持更改集中,并附上相关的测试或渲染的UI证据。
## 项目状态和许可
Submail是一个早期的`0.1.x`项目。由于可选的文档查看器依赖项包含共用许可的组件,因此尚未选择项目范围的许可。公共仓库访问不授予重新分发权限,直到添加`LICENSE`文件;依赖项许可继续独立应用。