🦉 一个用 Go 语言实现的邮件开发测试工具,完全兼容 MailDev,提供更好的性能和更丰富的功能
OwlMail 是一个用于开发和测试环境的 SMTP 服务器和 Web 界面,可以捕获和查看所有发送的邮件。它是 MailDev 的 Go 语言实现,提供 100% API 兼容性,同时带来更好的性能、更低的资源占用和更丰富的功能。
- ✅ SMTP 服务器 - 接收和存储所有发送的邮件(默认端口 1025)
- ✅ Web 界面 - 通过浏览器查看和管理邮件(默认端口 1080)
- ✅ 邮件持久化 - 邮件保存为
.eml文件,支持从目录加载 - ✅ 邮件转发 - 支持将邮件转发到真实的 SMTP 服务器
- ✅ 自动中继 - 支持自动转发所有邮件,带规则过滤
- ✅ SMTP 认证 - 支持 PLAIN/LOGIN 认证
- ✅ TLS/STARTTLS - 支持加密连接
- ✅ SMTPS - 支持端口 465 的直接 TLS 连接(OwlMail 独有)
- 🆕 批量操作 - 批量删除、批量标记已读
- 🆕 邮件统计 - 获取邮件统计信息
- 🆕 邮件预览 - 轻量级邮件预览 API
- 🆕 邮件导出 - 导出邮件为 ZIP 文件
- 🆕 配置管理 API - 完整的配置管理(GET/PUT/PATCH)
- 🆕 强大的搜索 - 全文搜索、日期范围过滤、排序
- 🆕 改进的 RESTful API - 更规范的 API 设计(
/api/v1/*)
- ✅ 100% MailDev API 兼容 - 所有 MailDev API 端点都得到支持
- ✅ 环境变量完全兼容 - 优先使用 MailDev 环境变量,无需修改配置
- ✅ 自动中继规则兼容 - JSON 配置文件格式完全兼容
- ⚡ 单一二进制 - 编译为单一可执行文件,无需运行时
- ⚡ 低资源占用 - Go 语言编译,内存占用更低
- ⚡ 快速启动 - 启动速度更快
- ⚡ 高并发 - Go 协程,并发性能更好
# 克隆仓库
git clone https://github.com/soulteary/owlmail.git
cd owlmail
# 编译
go build -o owlmail ./cmd/owlmail
# 运行
./owlmailgo install github.com/soulteary/owlmail/cmd/owlmail@latest
owlmail# 使用默认配置启动(SMTP: 1025, Web: 1080)
./owlmail
# 自定义端口
./owlmail -smtp 1025 -web 1080
# 使用环境变量
export MAILDEV_SMTP_PORT=1025
export MAILDEV_WEB_PORT=1080
./owlmail使用 OwlMail 最简单的方式是从 GitHub Container Registry 拉取预构建的镜像:
# 拉取最新镜像
docker pull ghcr.io/soulteary/owlmail:latest
# 拉取特定版本(使用提交 SHA)
docker pull ghcr.io/soulteary/owlmail:sha-49b5f35
# 运行容器
docker run -d \
-p 1025:1025 \
-p 1080:1080 \
--name owlmail \
ghcr.io/soulteary/owlmail:latest可用标签:
latest- 最新稳定版本sha-<commit>- 特定提交 SHA(例如:sha-49b5f35)main- main 分支的最新版本
多架构支持:
镜像支持 linux/amd64 和 linux/arm64 两种架构。Docker 会自动为您的平台拉取正确的镜像。
查看所有可用镜像: GitHub Packages
# 为当前架构构建镜像
docker build -t owlmail .
# 运行容器
docker run -d \
-p 1025:1025 \
-p 1080:1080 \
--name owlmail \
owlmail对于 aarch64 (ARM64) 或其他架构,请使用 Docker Buildx:
# 启用 buildx(如果尚未启用)
docker buildx create --use --name multiarch-builder
# 为多个架构构建
docker buildx build \
--platform linux/amd64,linux/arm64 \
-t owlmail:latest \
--load .
# 或构建并推送到镜像仓库
docker buildx build \
--platform linux/amd64,linux/arm64 \
-t your-registry/owlmail:latest \
--push .
# 为特定架构构建(例如 aarch64/arm64)
docker buildx build \
--platform linux/arm64 \
-t owlmail:latest \
--load .注意:Dockerfile 现在支持使用 TARGETOS 和 TARGETARCH 构建参数进行多架构构建,这些参数由 Docker Buildx 自动设置。
| 参数 | 环境变量 | 默认值 | 说明 |
|---|---|---|---|
-smtp |
MAILDEV_SMTP_PORT / OWLMAIL_SMTP_PORT |
1025 | SMTP 端口 |
-ip |
MAILDEV_IP / OWLMAIL_SMTP_HOST |
localhost | SMTP 主机 |
-web |
MAILDEV_WEB_PORT / OWLMAIL_WEB_PORT |
1080 | Web API 端口 |
-web-ip |
MAILDEV_WEB_IP / OWLMAIL_WEB_HOST |
localhost | Web API 主机 |
-mail-directory |
MAILDEV_MAIL_DIRECTORY / OWLMAIL_MAIL_DIR |
- | 邮件存储目录 |
-web-user |
MAILDEV_WEB_USER / OWLMAIL_WEB_USER |
- | HTTP Basic Auth 用户名 |
-web-password |
MAILDEV_WEB_PASS / OWLMAIL_WEB_PASSWORD |
- | HTTP Basic Auth 密码 |
-https |
MAILDEV_HTTPS / OWLMAIL_HTTPS_ENABLED |
false | 启用 HTTPS |
-https-cert |
MAILDEV_HTTPS_CERT / OWLMAIL_HTTPS_CERT |
- | HTTPS 证书文件 |
-https-key |
MAILDEV_HTTPS_KEY / OWLMAIL_HTTPS_KEY |
- | HTTPS 私钥文件 |
-outgoing-host |
MAILDEV_OUTGOING_HOST / OWLMAIL_OUTGOING_HOST |
- | 出站 SMTP 主机 |
-outgoing-port |
MAILDEV_OUTGOING_PORT / OWLMAIL_OUTGOING_PORT |
587 | 出站 SMTP 端口 |
-outgoing-user |
MAILDEV_OUTGOING_USER / OWLMAIL_OUTGOING_USER |
- | 出站 SMTP 用户名 |
-outgoing-pass |
MAILDEV_OUTGOING_PASS / OWLMAIL_OUTGOING_PASSWORD |
- | 出站 SMTP 密码 |
-outgoing-secure |
MAILDEV_OUTGOING_SECURE / OWLMAIL_OUTGOING_SECURE |
false | 出站 SMTP TLS |
-auto-relay |
MAILDEV_AUTO_RELAY / OWLMAIL_AUTO_RELAY |
false | 启用自动中继 |
-auto-relay-addr |
MAILDEV_AUTO_RELAY_ADDR / OWLMAIL_AUTO_RELAY_ADDR |
- | 自动中继地址 |
-auto-relay-rules |
MAILDEV_AUTO_RELAY_RULES / OWLMAIL_AUTO_RELAY_RULES |
- | 自动中继规则文件 |
-smtp-user |
MAILDEV_INCOMING_USER / OWLMAIL_SMTP_USER |
- | SMTP 认证用户名 |
-smtp-password |
MAILDEV_INCOMING_PASS / OWLMAIL_SMTP_PASSWORD |
- | SMTP 认证密码 |
-tls |
MAILDEV_INCOMING_SECURE / OWLMAIL_TLS_ENABLED |
false | 启用 SMTP TLS |
-tls-cert |
MAILDEV_INCOMING_CERT / OWLMAIL_TLS_CERT |
- | SMTP TLS 证书文件 |
-tls-key |
MAILDEV_INCOMING_KEY / OWLMAIL_TLS_KEY |
- | SMTP TLS 私钥文件 |
-log-level |
MAILDEV_VERBOSE / MAILDEV_SILENT / OWLMAIL_LOG_LEVEL |
normal | 日志级别 |
-use-uuid-for-email-id |
OWLMAIL_USE_UUID_FOR_EMAIL_ID |
false | 使用 UUID 作为邮件 ID(默认使用 8 字符随机字符串) |
OwlMail 完全支持 MailDev 环境变量,优先使用 MailDev 环境变量,如果不存在则使用 OwlMail 环境变量。这意味着你可以直接使用 MailDev 的配置,无需修改。
# 直接使用 MailDev 环境变量(推荐)
export MAILDEV_SMTP_PORT=1025
export MAILDEV_WEB_PORT=1080
export MAILDEV_OUTGOING_HOST=smtp.gmail.com
./owlmail
# 或使用 OwlMail 环境变量
export OWLMAIL_SMTP_PORT=1025
export OWLMAIL_WEB_PORT=1080
./owlmailOwlMail 使用标准化的 API 响应格式:
成功响应:
{
"code": "EMAIL_DELETED",
"message": "Email deleted",
"data": { ... }
}错误响应:
{
"code": "EMAIL_NOT_FOUND",
"error": "EMAIL_NOT_FOUND",
"message": "Email not found"
}code 字段包含标准化的错误/成功代码,可用于国际化。message 字段提供英文文本以保持向后兼容。
OwlMail 支持两种邮件 ID 格式,所有 API 端点都兼容这两种格式:
- 8 字符随机字符串:默认格式,例如
aB3dEfGh - UUID 格式:36 字符标准 UUID,例如
550e8400-e29b-41d4-a716-446655440000
在 API 请求中使用 :id 参数时,可以使用任意一种格式。例如:
GET /email/aB3dEfGh- 使用随机字符串 IDGET /email/550e8400-e29b-41d4-a716-446655440000- 使用 UUID ID
OwlMail 完全兼容 MailDev 的所有 API 端点:
GET /email- 获取所有邮件(支持分页和过滤)- 查询参数:
limit(默认: 50, 最大: 1000) - 返回邮件数量offset(默认: 0) - 跳过的邮件数量q- 全文搜索查询from- 按发件人邮箱地址过滤to- 按收件人邮箱地址过滤dateFrom- 按起始日期过滤(YYYY-MM-DD 格式)dateTo- 按结束日期过滤(YYYY-MM-DD 格式)read- 按已读状态过滤(true/false)sortBy- 排序字段(time, subject)sortOrder- 排序顺序(asc, desc,默认: desc)
- 示例:
GET /email?limit=20&offset=0&q=test&sortBy=time&sortOrder=desc
- 查询参数:
GET /email/:id- 获取单个邮件DELETE /email/:id- 删除单个邮件DELETE /email/all- 删除所有邮件PATCH /email/read-all- 标记所有邮件为已读PATCH /email/:id/read- 标记单个邮件为已读
GET /email/:id/html- 获取邮件 HTML 内容GET /email/:id/attachment/:filename- 下载附件GET /email/:id/download- 下载原始 .eml 文件GET /email/:id/source- 获取邮件原始源码
POST /email/:id/relay- 转发邮件到配置的 SMTP 服务器POST /email/:id/relay/:relayTo- 转发邮件到指定地址
GET /config- 获取配置信息GET /healthz- 健康检查GET /reloadMailsFromDirectory- 重新加载邮件目录GET /socket.io- WebSocket 连接(标准 WebSocket,非 Socket.IO)
GET /email/stats- 获取邮件统计信息GET /email/preview- 获取邮件预览(轻量级)
POST /email/batch/delete- 批量删除邮件POST /email/batch/read- 批量标记已读
GET /email/export- 导出邮件为 ZIP 文件
GET /config/outgoing- 获取出站配置PUT /config/outgoing- 更新出站配置PATCH /config/outgoing- 部分更新出站配置
OwlMail 提供了更规范的 RESTful API 设计:
GET /api/v1/emails- 获取所有邮件(复数资源)- 查询参数:与
GET /email相同(limit, offset, q, from, to, dateFrom, dateTo, read, sortBy, sortOrder) - 示例:
GET /api/v1/emails?limit=20&offset=0&q=test&sortBy=time&sortOrder=desc
- 查询参数:与
GET /api/v1/emails/:id- 获取单个邮件DELETE /api/v1/emails/:id- 删除单个邮件DELETE /api/v1/emails- 删除所有邮件DELETE /api/v1/emails/batch- 批量删除PATCH /api/v1/emails/read- 标记所有邮件为已读PATCH /api/v1/emails/:id/read- 标记单个邮件为已读PATCH /api/v1/emails/batch/read- 批量标记已读GET /api/v1/emails/stats- 邮件统计GET /api/v1/emails/preview- 邮件预览GET /api/v1/emails/export- 导出邮件POST /api/v1/emails/reload- 重新加载邮件GET /api/v1/settings- 获取所有设置GET /api/v1/settings/outgoing- 获取出站配置PUT /api/v1/settings/outgoing- 更新出站配置PATCH /api/v1/settings/outgoing- 部分更新出站配置GET /api/v1/health- 健康检查GET /api/v1/version- 版本信息GET /api/v1/ws- WebSocket 连接
详细 API 文档(含原文、附件、转发等子资源与操作路径)请参考:API 重构记录
# 启动 OwlMail
./owlmail -smtp 1025 -web 1080
# 在应用中配置 SMTP
SMTP_HOST=localhost
SMTP_PORT=1025# 转发到 Gmail SMTP
./owlmail \
-outgoing-host smtp.gmail.com \
-outgoing-port 587 \
-outgoing-user your-email@gmail.com \
-outgoing-pass your-password \
-outgoing-secure# 创建自动中继规则文件 (relay-rules.json)
cat > relay-rules.json <<EOF
[
{ "allow": "*" },
{ "deny": "*@test.com" },
{ "allow": "ok@test.com" }
]
EOF
# 启动自动中继
./owlmail \
-outgoing-host smtp.gmail.com \
-outgoing-port 587 \
-outgoing-user your-email@gmail.com \
-outgoing-pass your-password \
-auto-relay \
-auto-relay-rules relay-rules.json./owlmail \
-https \
-https-cert /path/to/cert.pem \
-https-key /path/to/key.pem \
-web 1080./owlmail \
-smtp-user admin \
-smtp-password secret \
-smtp 1025./owlmail \
-tls \
-tls-cert /path/to/cert.pem \
-tls-key /path/to/key.pem \
-smtp 1025注意:启用 TLS 时,OwlMail 会自动在 465 端口启动 SMTPS 服务器,除了常规 SMTP 服务器外。SMTPS 服务器使用直接 TLS 连接(无需 STARTTLS)。这是 OwlMail 的独有功能。
OwlMail 支持两种邮件 ID 格式:
- 默认格式:8 字符随机字符串(例如:
aB3dEfGh) - UUID 格式:36 字符标准 UUID(例如:
550e8400-e29b-41d4-a716-446655440000)
使用 UUID 格式可以提供更好的唯一性和可追溯性,特别适合需要与外部系统集成的场景。
# 使用命令行参数启用 UUID
./owlmail -use-uuid-for-email-id
# 使用环境变量启用 UUID
export OWLMAIL_USE_UUID_FOR_EMAIL_ID=true
./owlmail
# 结合其他配置使用
./owlmail \
-use-uuid-for-email-id \
-smtp 1025 \
-web 1080注意事项:
- 默认使用 8 字符随机字符串,兼容 MailDev 的行为
- 启用 UUID 后,所有新接收的邮件将使用 UUID 格式的 ID
- API 同时支持两种格式的 ID,可以正常查询、删除和操作邮件
- 已存在的邮件 ID 格式不会改变,只有新邮件会使用新的 ID 格式
OwlMail 完全兼容 MailDev,可以无缝替换:
OwlMail 优先使用 MailDev 环境变量,无需修改配置:
# MailDev 配置
export MAILDEV_SMTP_PORT=1025
export MAILDEV_WEB_PORT=1080
export MAILDEV_OUTGOING_HOST=smtp.gmail.com
# 直接使用 OwlMail(无需修改环境变量)
./owlmail所有 MailDev API 端点都得到支持,现有客户端代码无需修改:
# MailDev API
curl http://localhost:1080/email
# OwlMail 完全兼容
curl http://localhost:1080/email如果使用 WebSocket,需要从 Socket.IO 改为标准 WebSocket:
// MailDev (Socket.IO)
const socket = io('/socket.io');
socket.on('newMail', (email) => { /* ... */ });
// OwlMail (标准 WebSocket)
const ws = new WebSocket('ws://localhost:1080/socket.io');
ws.onmessage = (event) => {
const data = JSON.parse(event.data);
if (data.type === 'new') { /* ... */ }
};详细迁移指南请参考:OwlMail × MailDev:功能与 API 完整对比与迁移白皮书
# 运行所有测试
go test ./...
# 运行测试并查看覆盖率
go test -cover ./...
# 运行特定包的测试
go test ./internal/api/...
go test ./internal/mailserver/...OwlMail/
├── cmd/
│ └── owlmail/ # 主程序入口
├── internal/
│ ├── api/ # Web API 实现
│ ├── common/ # 通用工具(日志、错误处理)
│ ├── maildev/ # MailDev 兼容层
│ ├── mailserver/ # SMTP 服务器实现
│ ├── outgoing/ # 邮件转发实现
│ └── types/ # 类型定义
├── web/ # Web 前端文件
├── go.mod # Go 模块定义
└── README.md # 本文档
欢迎贡献!请遵循以下步骤:
- Fork 本仓库
- 创建特性分支 (
git checkout -b feature/AmazingFeature) - 提交更改 (
git commit -m 'Add some AmazingFeature') - 推送到分支 (
git push origin feature/AmazingFeature) - 开启 Pull Request
本项目采用 MIT 许可证 - 查看 LICENSE 文件了解详情。
- MailDev - 原始项目灵感
- emersion/go-smtp - SMTP 服务器库
- emersion/go-message - 邮件解析库
- Fiber - Web 框架
- gorilla/websocket - WebSocket 库
如果遇到问题或有建议,请在 GitHub Issues 中提交。
如果这个项目对你有帮助,请给一个 Star ⭐!
OwlMail - 用 Go 语言实现的邮件开发测试工具,完全兼容 MailDev 🦉


