# mail2ai **Repository Path**: chees_cn/mail2ai ## Basic Information - **Project Name**: mail2ai - **Description**: 人工智能邮件集群编排系统 - **Primary Language**: NodeJS - **License**: AGPL-3.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-03-19 - **Last Updated**: 2026-04-02 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Mail2AI - 单机邮件集群系统 [](https://github.com/yourusername/mail2ai/actions/workflows/ci.yml) Mail2AI 是一个基于文件存储的单机邮件集群系统,无需数据库即可实现多租户邮件发送管理。 ## 技术栈 - **后端**: Node.js 20+ + TypeScript 5.8 - **前端**: Vue 3.5 + Vite 6 - **存储**: JSONL 追加日志 + 定期快照 (无需数据库) - **测试**: Vitest 3.0 ## 功能特性 ### 核心功能 - **多租户管理**: 每个租户独立的数据隔离 - **管理员认证**: 基于会话的注册/登录/登出 - **API Key 管理**: 创建/列表/撤销,Key 仅展示一次 - **收件人目录**: 姓名到邮箱的映射,支持模糊匹配检测 - **发件人池管理**: SMTP 配置管理,支持启用/禁用/健康状态 - **任务队列**: 持久化的邮件发送队列 - **定时发送**: 管理员可创建一次性定时发送任务 - **路由轮转**: 基于轮询的发件人选择,支持速率限制和冷却 - **重试机制**: 可重试/永久性失败分类处理 - **SMTP 工作器**: 带持久化尝试日志和不确定结果边界处理 - **审计日志**: 所有管理操作完整记录 ### 安全特性 - **密码安全**: scrypt 哈希 (cost: 16384) + 随机 salt - **API Key 安全**: SHA256 HMAC 验证 + timingSafeEqual - **会话安全**: HMAC 签名 Cookie,支持 HttpOnly + SameSite=Strict + Secure - **租户隔离**: 所有查询强制过滤 tenantId - **输入验证**: 邮箱格式验证、日期验证、参数边界检查 - **并发安全**: 操作队列串行化写入 ## 快速开始 ### 1. 安装依赖 ```bash npm install ``` ### 2. 构建项目 ```bash npm run build ``` ### 3. 运行测试 ```bash npm run test ``` ### 4. 启动后端服务 **方式 1:使用环境变量文件(推荐)** 我们已提供 `.env` 文件,直接启动即可: ```bash # 开发环境 npm run start:backend # 或者使用 dev 脚本(自动加载 .env) cd apps/backend npm run dev ``` **方式 2:手动设置环境变量** Windows PowerShell: ```powershell $env:MAIL2AI_SESSION_SECRET="$(node -e "console.log(require('crypto').randomBytes(32).toString('base64'))")" npm run start:backend ``` Windows CMD: ```cmd set MAIL2AI_SESSION_SECRET=<生成的密钥> npm run start:backend ``` Linux/macOS: ```bash MAIL2AI_SESSION_SECRET=$(openssl rand -base64 32) npm run start:backend ``` **生产环境**: ```bash MAIL2AI_COOKIE_SECURE=true MAIL2AI_SESSION_SECRET=<你的密钥> npm run start:backend ``` ### 5. 访问管理界面 ```bash # 启动前端开发服务器 cd apps/frontend npm run dev ``` 访问 http://localhost:5173 ## 环境变量配置 | 变量 | 默认值 | 说明 | |------|--------|------| | `MAIL2AI_HOST` | `127.0.0.1` | 服务监听地址 | | `MAIL2AI_PORT` | `8787` | 服务端口 | | `MAIL2AI_DATA_DIR` | `.mail2ai-data` | 数据存储目录 | | `MAIL2AI_SESSION_SECRET` | *(Required)* | 会话签名密钥 (生成: openssl rand -base64 32) | | `MAIL2AI_COOKIE_SECURE` | `false` | 启用 Secure Cookie(生产环境建议 true) | **生产环境建议**: ```bash MAIL2AI_HOST=0.0.0.0 \ MAIL2AI_PORT=8787 \ MAIL2AI_DATA_DIR=/var/lib/mail2ai \ MAIL2AI_SESSION_SECRET=$(openssl rand -base64 32) \ MAIL2AI_COOKIE_SECURE=true \ npm run start:backend ``` ## API 文档 ### 认证接口 #### 注册租户管理员 ```http POST /api/v1/auth/register Content-Type: application/json { "tenantId": "my-company", "username": "admin", "password": "secure-password" } ``` #### 登录 ```http POST /api/v1/auth/login Content-Type: application/json { "tenantId": "my-company", "username": "admin", "password": "secure-password" } ``` #### 获取会话信息 ```http GET /api/v1/auth/session Cookie: mail2ai_admin_session=... ``` #### 登出 ```http POST /api/v1/auth/logout Cookie: mail2ai_admin_session=... ``` ### 第三方发送接口 #### 发送邮件(异步) ```http POST /api/v1/external/send X-API-Key: m2a_xxxxx.yyyyy X-Idempotency-Key: unique-key-001 Content-Type: application/json { "recipientName": "Alice", "subject": "Hello", "text": "Plain text content", "html": "
HTML content
" } # 响应: 202 Accepted { "deduplicated": false, "job": { "jobId": "...", "status": "queued", "recipientEmail": "alice@example.com" } } ``` ### 管理接口(需 Cookie 认证) #### API Key 管理 ```http # 创建 API Key POST /api/v1/admin/api-keys { "name": "Production" } # 列表 API Keys GET /api/v1/admin/api-keys # 撤销 API Key POST /api/v1/admin/api-keys/{keyId}/revoke ``` #### 收件人管理 ```http # 创建收件人 POST /api/v1/admin/recipients { "name": "Alice", "email": "alice@example.com" } # 列表收件人 GET /api/v1/admin/recipients # 更新收件人 PATCH /api/v1/admin/recipients/{recipientId} { "name": "Alice Smith", "email": "alice.smith@example.com" } # 禁用收件人 DELETE /api/v1/admin/recipients/{recipientId} ``` #### 发件人管理 ```http # 创建发件人 POST /api/v1/admin/senders { "name": "Primary", "email": "noreply@example.com", "smtpHost": "smtp.example.com", "smtpPort": 587, "secure": false, "smtpUsername": "user", "smtpPassword": "pass" } # 列表发件人 GET /api/v1/admin/senders # 更新发件人 PATCH /api/v1/admin/senders/{senderId} { ... } # 禁用发件人 DELETE /api/v1/admin/senders/{senderId} # 启用发件人 POST /api/v1/admin/senders/{senderId}/enable ``` #### 任务管理 ```http # 创建定时发送 POST /api/v1/admin/schedules { "dueAt": "2026-01-01T00:00:00.000Z", "recipientName": "Alice", "subject": "New Year", "text": "Happy New Year!" } # 列表定时任务 GET /api/v1/admin/schedules # 列表所有任务 GET /api/v1/admin/jobs # 获取任务详情 GET /api/v1/admin/jobs/{jobId} ``` #### 运营监控 ```http # 账户健康状态 GET /api/v1/admin/account-health # 审计日志 GET /api/v1/admin/audit-logs?limit=100 ``` ## 项目结构 ``` mail2ai/ ├── apps/ │ ├── backend/ # Node.js 后端 │ │ ├── src/ │ │ │ ├── auth/ # 认证相关 │ │ │ ├── api-keys/ # API Key 管理 │ │ │ ├── recipients/# 收件人管理 │ │ │ ├── senders/ # 发件人管理 │ │ │ ├── jobs/ # 任务队列 │ │ │ ├── routing/ # 路由引擎 │ │ │ ├── worker/ # SMTP 工作器 │ │ │ ├── audit/ # 审计日志 │ │ │ └── storage/ # 存储层 │ │ └── test/ # 测试 │ └── frontend/ # Vue 前端 │ └── src/ ├── packages/ │ └── shared/ # 共享类型 ├── .github/workflows/ # CI 配置 └── README.md ``` ## 存储与恢复机制 ### 数据模型 - **快照**: 完整状态快照,存储在 `{entity}/snapshot.json` - **日志**: 追加式事件日志,存储在 `{entity}/events.jsonl` - **实体**: auth, api-keys, recipients, senders, jobs, audit ### 恢复流程 1. 读取最新快照(如果有) 2. 重放快照之后的所有日志事件 3. 自动截断损坏的日志尾部 4. 重建内存状态 ### 备份与恢复 ```bash # 备份 sudo systemctl stop mail2ai tar czf mail2ai-backup-$(date +%Y%m%d).tar.gz /var/lib/mail2ai sudo systemctl start mail2ai # 恢复 sudo systemctl stop mail2ai sudo rm -rf /var/lib/mail2ai/* sudo tar xzf mail2ai-backup-20260320.tar.gz -C /var/lib/mail2ai sudo systemctl start mail2ai ``` ## 测试 ### 运行所有测试 ```bash npm run test ``` ### 针对性测试 ```bash # 存储层测试 npm run test -w @mail2ai/backend -- -t "storage" # 认证测试 npm run test -w @mail2ai/backend -- -t "auth api" # 路由引擎测试 npm run test -w @mail2ai/backend -- -t "routing engine" # SMTP 工作器测试 npm run test -w @mail2ai/backend -- -t "smtp worker" ``` ### 测试覆盖率 - **Backend**: 13 个测试文件,21 个测试用例 - **Frontend**: 3 个集成测试 - **总通过率**: 100% ## 开发指南 ### 添加新功能 1. 定义类型(`types.ts`) 2. 实现存储层(`*-store.ts`) 3. 添加事件处理(`apply*Event`) 4. 暴露 API 端点(`auth-api.ts`) 5. 添加前端界面(`App.vue`) 6. 编写测试 ### 代码规范 - 所有字符串输入必须 `trim()` - 邮箱必须验证格式 - 所有写操作必须通过操作队列 - 所有管理操作必须记录审计日志 - 敏感数据(密码、API Key)永不返回明文 ## 生产部署建议 ### 1. 系统要求 - Node.js 20+ - 至少 1GB RAM - 足够的磁盘空间用于日志增长 ### 2. 安全加固 ```bash # 使用强密钥 export MAIL2AI_SESSION_SECRET=$(openssl rand -base64 32) # 启用 Secure Cookie export MAIL2AI_COOKIE_SECURE=true # 限制文件权限 chmod 700 /var/lib/mail2ai ``` ### 3. 监控建议 - 监控磁盘空间(日志增长) - 监控内存使用 - 监控任务队列积压 - 监控发件人健康状态 ### 4. 日志轮转 建议配置系统级日志轮转: ```bash # /etc/logrotate.d/mail2ai /var/lib/mail2ai/*/events.jsonl { daily rotate 30 compress delaycompress missingok notifempty } ``` ## 最近的改进 (2026-04-01) ### 安全审计与修复 本次更新包含全面的安全审计和代码质量改进: - **会话安全强化**: `MAIL2AI_SESSION_SECRET` 现在是必需的环境变量,不再使用默认密钥 - **错误处理改进**: 所有 API 端点添加了详细的错误日志记录,便于生产环境调试 - **竞态条件修复**: 任务认领添加了租约验证,防止多个 worker 同时处理同一任务 - **测试覆盖提升**: 新增 59 个安全相关单元测试,覆盖密码哈希、Cookie 签名、API Key 验证等核心安全组件 ### 测试统计 - **总测试数**: 97 个 (80 backend + 17 frontend) - **测试通过率**: 100% - **新增测试**: 4 个测试文件,59 个测试用例 ## 已知限制 - **单机部署**: 不支持多节点分布式部署 - **无附件**: 暂不支持附件发送 - **无 CC/BCC**: 仅支持单收件人 - **一次性定时**: 不支持周期性定时任务 - **单管理员**: 每个租户仅支持一个管理员账号 - **尽力而为**: SMTP 发送不保证恰好一次投递 ## 路线图 ### v1.1 (计划中) - [ ] 日志轮转和归档 - [ ] 附件支持 - [ ] 邮件模板 - [ ] 多管理员支持 ### v1.2 (计划中) - [ ] 统计分析面板 - [ ] Webhook 通知 - [ ] 性能指标导出 ## 许可证 MIT License ## 贡献 欢迎提交 Issue 和 PR! ## 致谢 - Vue 3 - 前端框架 - Vitest - 测试框架 - Node.js Crypto - 加密功能