6.5 KiB
6.5 KiB
多邮箱帐号收发系统
一个基于 Node.js + Express + SQLite 的多邮箱工作台,支持在网页中统一管理多个邮箱渠道与邮箱帐号,进行收信、查看邮件、发信,以及通过 API 调用邮件能力。
功能特性
- 支持配置多个邮箱渠道,如 QQ 邮箱、163 邮箱和自定义 IMAP/SMTP 渠道
- 支持导入邮箱帐号与授权码
- 三栏式 Web 界面:邮箱帐号、邮件列表、邮件详情
- 支持网页写邮件、发邮件、查看邮件详情
- 支持拉取多文件夹邮件,不限于
INBOX - 支持按需补拉单封邮件正文,避免全量同步过慢
- 支持批量导入导出邮箱信息
- 提供 API 用于发邮件、获取邮件列表、获取最新一封邮件
技术栈
- Node.js
- Express
- SQLite
better-sqlite3 - SMTP
nodemailer - IMAP
imapflow - 前端:原生 HTML / CSS / JavaScript
目录结构
mail-sr/
├── public/
│ ├── index.html
│ ├── styles.css
│ └── app.js
├── db.js
├── mailService.js
├── server.js
├── Dockerfile
├── docker-compose.yml
└── README.md
本地启动
1. 安装依赖
npm install
2. 配置环境变量
cp .env.example .env
默认环境变量:
PORT=3000
DB_PATH=./mail.db
3. 启动服务
npm start
访问地址:http://localhost:3000
Docker 部署
项目已经提供 Dockerfile 和 docker-compose.yml,可以直接用 Docker Compose 部署。
1. 准备环境变量
cp .env.example .env
如果你不需要额外环境变量,默认配置即可。
2. 构建并启动
docker compose up -d --build
启动后访问:http://localhost:3000
3. 停止服务
docker compose down
4. 查看日志
docker compose logs -f
5. 数据持久化
Docker Compose 默认使用命名卷 mail-sr-data 持久化 SQLite 数据库,容器重建后数据不会丢失。
容器内数据库路径:
/data/mail.db
内置邮箱渠道
系统默认会初始化以下渠道:
- QQ邮箱
- IMAP:
imap.qq.com:993 - SMTP:
smtp.qq.com:465
- IMAP:
- 163邮箱
- IMAP:
imap.163.com:993 - SMTP:
smtp.163.com:465
- IMAP:
说明:通常需要在邮箱后台开启 IMAP/SMTP,并使用授权码,而不是邮箱登录密码。
Web 使用说明
1. 渠道管理
在设置弹窗中可以新增渠道,填写:
- 渠道名称
- 渠道标识 code
- IMAP 主机、端口、是否 SSL
- SMTP 主机、端口、是否 SSL
2. 单个邮箱帐号导入
在设置弹窗中填写:
- 渠道
- 邮箱帐号
- 授权码
- 发件人名称,可选
3. 批量导入导出
支持以下格式,每行一条:
渠道名----帐号----授权码
例如:
QQ邮箱----demo@qq.com----abcd1234
163邮箱----demo@163.com----efgh5678
说明:
- 导入时按“渠道名”匹配已有渠道
- 如果渠道不存在,会直接报错
- 如果同一渠道下邮箱已存在,则更新授权码
- 导出会导出全部帐号,格式同上
4. 收信
点击左侧邮箱帐号后会:
- 复制邮箱号到剪贴板
- 立即触发收信
- 拉取全部可读文件夹中的最近邮件
- 在中间栏展示邮件列表
- 在右侧显示邮件详情
为了避免 IMAP 全量拉取过慢,系统使用“两阶段策略”:
- 先同步邮件列表与头信息
- 打开某封邮件时再按需拉取正文详情
5. 发信
点击左上角“写邮件”按钮,选择当前邮箱帐号后即可发信。
API 文档
健康检查
curl http://localhost:3000/api/health
查询渠道
curl http://localhost:3000/api/channels
新增渠道
curl -X POST http://localhost:3000/api/channels \
-H 'Content-Type: application/json' \
-d '{
"name": "企业邮箱",
"code": "corp",
"imap_host": "imap.example.com",
"imap_port": 993,
"imap_secure": true,
"smtp_host": "smtp.example.com",
"smtp_port": 465,
"smtp_secure": true
}'
查询帐号列表
curl http://localhost:3000/api/accounts
新增邮箱帐号
curl -X POST http://localhost:3000/api/accounts \
-H 'Content-Type: application/json' \
-d '{
"channel_id": 1,
"email": "your-account@qq.com",
"auth_code": "邮箱授权码",
"display_name": "业务邮箱"
}'
删除邮箱帐号
curl -X DELETE http://localhost:3000/api/accounts/1
批量导出帐号
curl http://localhost:3000/api/accounts/export
批量导入帐号
curl -X POST http://localhost:3000/api/accounts/import \
-H 'Content-Type: application/json' \
-d '{
"content": "QQ邮箱----demo@qq.com----abcd1234\n163邮箱----demo@163.com----efgh5678"
}'
发送邮件
curl -X POST http://localhost:3000/api/send \
-H 'Content-Type: application/json' \
-d '{
"accountId": 1,
"to": "target@example.com",
"subject": "测试邮件",
"text": "这是一封来自 API 的测试邮件"
}'
获取邮件列表
首次建议带 refresh=true,从远程 IMAP 同步最新邮件。
curl "http://localhost:3000/api/messages?accountId=1&limit=20&refresh=true"
获取最新一封邮件
curl "http://localhost:3000/api/messages/latest?accountId=1&refresh=true"
获取单封邮件详情
curl "http://localhost:3000/api/accounts/1/messages/INBOX%3A123?refresh=true"
说明:uid 需要使用 URL 编码。
数据说明
channels:邮箱渠道配置accounts:邮箱帐号和授权码mail_cache:同步后的邮件缓存
默认本地数据库文件为:
./mail.db
如果通过 Docker 运行,则默认为:
/data/mail.db
部署建议
- 生产环境建议使用反向代理,如 Nginx 或 Traefik
- 建议通过 HTTPS 暴露服务
- 当前授权码存储在 SQLite 中,生产环境建议改为加密存储
- 建议增加访问控制与登录认证,避免未授权访问
当前实现边界
- 当前未实现附件上传与下载
- 当前未实现用户登录、权限和多租户隔离
- 当前邮件缓存为本地 SQLite,不适合超大规模并发
- 当前 HTML 邮件正文做了基础清理,但不是完整沙箱渲染
后续建议
如果准备继续往生产方向演进,建议优先补以下能力:
- 用户登录与权限管理
- 授权码加密存储
- 附件收发
- 邮件标签、已读未读、分页
- 定时自动拉取邮件
- 发信模板和批量发信
- 更完整的 HTML 邮件安全隔离策略