Mailezine 引擎
Mailezine 是 Mailez 的第一方邮件引擎,单二进制 + 可插拔存储形态。 它是全部档位(开发 / 社区版 / 企业版)的唯一引擎——协议能力与 邮件功能在两个版本间完全一致,版本差别只在存储规模与授权功能。
版本间的关系
| 社区版 | 企业版 | |
|---|---|---|
| 引擎 | Mailezine(同一二进制) | Mailezine(同一二进制) |
| 存储 | Pebble KV + 本地 FS blob(单节点) | TiDB KV + MinIO/S3 blob(分布式) |
| 网关 | nginx 仅 HTTP/ACME | 同左 |
| 邮件端口 | 引擎直出 + 内化隐式 TLS(465/993/995) | 同左 |
| 平台 | Linux / macOS / Windows 原生 | 同左 |
| 扩展 | — | 对象存储弹性扩展、多实例 HA、TiDB 横向扩容 |
两版共用同一个 backend 控制面(目录/认证/管理控制台/Webmail)。
传统 Postfix + Dovecot 架构的存量部署使用 mailezine migrate 原地迁入。
设计理念
- 单二进制 — 一个可执行文件包含所有功能
- 可插拔存储 — pebble(本地开发/单机) / tidb(分布式水平扩展) + S3/MinIO blob
- 全协议自研 — SMTP / IMAP / POP3 / ManageSieve,go-msgauth 等 MIT 库
- 一套引擎 — 社区版与企业版运行同一份代码,升级只动存储与授权
当前状态
已完成:
- ✅ SMTP 收发 / 校验 / 反垃圾 / 本地投递 / 出站队列(含 SRS、限速)
- ✅ IMAP 读路径(CONDSTORE / QRESYNC / SORT / ACL / QUOTA / ID 等 25+ 扩展)
- ✅ POP3 / ManageSieve / Sieve 执行器
- ✅ Pebble / TiDB KV + MinIO/S3 blob 存储闭环
- ✅ 全文搜索(bleve,默认开启;中文按双字切分精准检索)+ Tika 附件文本提取(PDF / Office / ODF)
- ✅ 集群两形态(企业版):active-passive 租约容灾,或 multi 档全服务 多活(任意副本服务任意账户;出站队列按消息事务认领、崩溃租约接管、 单例 worker 跨节点租约、FTS 每节点收敛、按账户写 pin;真实双进程 kill -9 故障演练验证)、隐式 TLS
- ✅ 归档捕获与出站 DLP 审批(对接控制面,见管理控制台文档)
- ✅ 旧架构(Postfix+Dovecot / Maildir)→ Pebble/TiDB 单向迁移工具
- ✅ 三平台(Linux/macOS/Windows)全量测试全绿
基准测试(10,000 人企业负载)
内部基准,2026-09 重测(同机同时段 A/B 对比;"传统方案"列为同机运行的 Postfix + Dovecot 架构基准,各栈与配套控制面对比):
| 指标 | 传统方案(postdove) | Mailezine | 提升 | 说明 |
|---|---|---|---|---|
| 收件吞吐 | 3.1 msg/s | 13.6 msg/s | 4.4× | 同样硬件每秒多收 3.4 倍邮件 |
| 收件 p50 | 6.19 s | 1.35 s | 4.6× | 新邮件几乎即时到达 |
| 提交吞吐 | 2.2 msg/s | 6.8 msg/s | 3.1× | 大批量外发队列同样从容 |
| IMAP FETCH p50 | 35.97 ms | 20.96 ms | 1.7× | 读信更跟手,长列表滚动流畅 |
| 队列投递 | 2.1 msg/s | 7.2 msg/s | 3.4× | 退信与延迟投递更少 |
| 入队→投递 p50 | 35.6 s | 5.30 s | 6.7× | 端到端送达快近 7 倍 |
| 队列积压 | 122 封 | 0 封 | 清零 | 高负载下零积压 |
| 空闲内存(整栈) | ~162 MiB | ~6.4 MiB | 1/25 | 小主机也能轻松运行 |
| 负载内存峰值 | ~270 MiB | ~73 MiB | 1/3.7 | 邮件洪峰下内存依旧平稳 |
独立开发
# 1. 准备 dev 目录与口令桩
$env:MAILEZINE_DIRECTORY_FILE = "internal/directory/testdata/dev-directory.json"
$env:MAILEZINE_AUTH_DEV_FILE = "internal/auth/testdata/dev-passwords.json"
# 2. 启动(默认监听 :11480 健康端点)
go run ./cmd/mailezine
# 默认再监听 :1025(SMTP 收信)、:1587(Submission)、:1143(IMAP)、
# :10110(POP3)、:11490(ManageSieve)
# 3. 验证
curl http://127.0.0.1:11480/health
# 4. 端到端冒烟(本地投递 + 中继入队)
go test ./cmd/mailezine -run TestEndToEnd -v
配置
全部可通过环境变量覆盖(也可用 MAILEZINE_CONFIG 指定 TOML 覆盖文件):
| 变量 | 默认 | 说明 |
|---|---|---|
MAILEZINE_STORAGE_BACKEND | pebble | pebble | tidb |
MAILEZINE_ROCKS_PATH | — | pebble KV 路径(必填) |
MAILEZINE_STORAGE_DSN | — | TiDB DSN(tidb 后端必填) |
MAILEZINE_S3_ENDPOINT | 空 | 设置后 blob 走 S3/MinIO;空 = 本地 FS |
MAILEZINE_S3_ACCESS_KEY / MAILEZINE_S3_SECRET_KEY / MAILEZINE_S3_BUCKET | — | S3 凭据与桶 |
MAILEZINE_BLOB_COMPRESSION | false | blob 落盘压缩(文本压缩 60–80%) |
MAILEZINE_FTS_ENABLED | true | 默认开启 bleve 全文搜索,设 false 关闭 |
MAILEZINE_FTS_TIKA_URL | 空 | 如 http://tika:9998;启用附件文本提取 |
MAILEZINE_HA_ENABLED | false | 多实例 active-passive HA |
MAILEZINE_HA_LEASE_PATH | 空 | 共享租约文件;空 = 回退 S3 桶租约 |
MAILEZINE_CLUSTER_MODE | single | multi = 引擎全服务多活(需 TiDB,与 HA 互斥) |
MAILEZINE_CLUSTER_NODE_ID | 自动 | 多活节点标识(compose 副本留空自动生成) |
MAILEZINE_QUEUE_CLAIM_LEASE_SECONDS | 600 | 多活投递认领租期(须大于最慢单次投递) |
MAILEZINE_ACCOUNT_GATE_ENABLED | true | 多活按账户写 pin(咨询式,等待超时照常写入) |
MAILEZINE_ARCHIVE_ENABLED / MAILEZINE_ARCHIVE_URL | false / 空 | 归档捕获,转发控制面归档存储 |
MAILEZINE_DLP_ENABLED / MAILEZINE_DLP_URL | false / 空 | 出站 DLP 扫描 + 审批,失败放行 |
MAILEZ_LICENSE_FILE | 空 | 企业版授权文件(平台级,未配置 = 开发版,不限邮箱数) |
MAILEZ_LICENSE_REQUIRED | false | true 时缺失/无效授权拒绝启动 |
MAILEZINE_DIRECTORY_FILE / MAILEZINE_AUTH_DEV_FILE | — | dev 模式目录/口令桩 |
MAILEZINE_BACKEND_ADDRESS | 127.0.0.1:8080 | backend 控制面地址 |
MAILEZINE_STACK_SECRET | 空 | 控制面 /stack API 共享密钥 |
MAILEZINE_HOSTNAME | 本机名 | EHLO / Authentication-Results 主机名 |
MAILEZINE_RSPAMD_URL | 空 | Rspamd 反垃圾扫描(社区版即可用):如 http://mail-filter:11333/checkv2;配置后优先于内置基础档 |
MAILEZINE_RSPAMD_LEARN_URL / MAILEZINE_RSPAMD_PASSWORD | 空 | Rspamd 垃圾学习(企业版):controller 端点与口令,跨 Junk 边界自动 learn_spam/learn_ham + fuzzy |
MAILEZINE_JUNK_ENABLED | true | 内置基础反垃圾(社区版默认层):认证结果计分 + DNSBL + 名单;配置 Rspamd 时自动让位 |
MAILEZINE_JUNK_HEADER_SCORE / MAILEZINE_JUNK_REJECT_SCORE | 4.5 / 12 | 打 X-Spam 头 / MTA 拒绝的分数阈值(刻意宽松,宁漏勿杀) |
MAILEZINE_JUNK_RBLS | bl.spamcop.net | DNSBL 区,逗号分隔;空 = 禁用 DNSBL 查询 |
MAILEZINE_JUNK_WHITELIST / MAILEZINE_JUNK_BLACKLIST | 空 | 完整地址、裸域名或 @domain,逗号分隔 |
MAILEZINE_JUNK_GREYLIST | false | 对模糊带分数的首见发件人灰名单(一小时内重试放行) |
MAILEZINE_SMTPS_ADDR / MAILEZINE_IMAPS_ADDR / MAILEZINE_POP3S_ADDR | 空 | 隐式 TLS 端口(需证书) |
迁移工具
传统架构(Dovecot Maildir 存储)迁入 KV 存储时,使用 mailezine migrate:
# maildir → pebble(本地 KV)
go run ./cmd/mailezine migrate --src /var/vmail --dst /var/lib/mailezine
# maildir → tidb(分布式 KV,可选 S3 blob)
go run ./cmd/mailezine migrate --src /var/vmail --to tidb --dsn "root:@tcp(127.0.0.1:4000)/mailezine"
迁移保留每邮箱顺序、标志、关键字与内部日期;UID/UIDVALIDITY 按存储
不变量重新分配,客户端按 RFC 3501 自动重同步。--dry-run 可先扫描统计
不写入。maildir 读取侧为 POSIX-only,其他平台提供说明桩。
授权(企业版)
企业版通过离线签名的授权文件(Ed25519)控制授权范围。
授权为软件永久授权:内含 edition(enterprise)与 max_mailboxes
(用户/邮箱数上限,永久生效),没有到期时间。未配置授权时以开发版
运行(不限);生产部署挂载授权文件并设置 MAILEZ_LICENSE_REQUIRED=true,
缺失或无效授权将拒绝启动。授权文件由 Mailez HQ 签发(cmd/license),
管理控制台按同一授权在创建邮箱时执行邮箱数上限校验(用户数/邮箱数)。
年度技术服务(支持、SLA、上线护航)是独立于授权的按年订阅,由
MAILEZ_SERVICE_FILE 加载(cmd/license service issue 签发)。服务证书
社区版与企业版都可以挂载,只表示服务权益、不锁定软件功能。