Geen omschrijving

Codex bc997b5cda chore: initialize git baseline 1 maand geleden
certs bc997b5cda chore: initialize git baseline 1 maand geleden
docker bc997b5cda chore: initialize git baseline 1 maand geleden
public bc997b5cda chore: initialize git baseline 1 maand geleden
src bc997b5cda chore: initialize git baseline 1 maand geleden
.dockerignore bc997b5cda chore: initialize git baseline 1 maand geleden
.env.example bc997b5cda chore: initialize git baseline 1 maand geleden
.gitignore bc997b5cda chore: initialize git baseline 1 maand geleden
Dockerfile bc997b5cda chore: initialize git baseline 1 maand geleden
README.md bc997b5cda chore: initialize git baseline 1 maand geleden
docker-compose.yml bc997b5cda chore: initialize git baseline 1 maand geleden
package.json bc997b5cda chore: initialize git baseline 1 maand geleden

README.md

MailHub

MailHub 是一个 Docker 化的发信域名管理面板和发送 API。它负责:

  • 添加发信域名并生成验证 TXT。
  • 为每个域名生成 DKIM key 和 DNS 记录。
  • 读取当前公网 DNS,合并已有 SPF 和第三方发信 include。
  • 给出 SPF、DKIM、DMARC、PTR、发信主机 A 记录的状态和建议。
  • 通过内部 Postfix 出站队列发送邮件,API 会先给邮件加 DKIM 签名。

运行

cd /www/wwwroot/mail.ss5.xyz
docker compose up -d --build
docker compose ps
docker compose logs -f app postfix

管理面板默认监听宿主机 127.0.0.1:3025,nginx 已反代到 mail-send.ss5.xyz

面板使用 HTML 登录页和 Cookie 会话。登录账号和 API Token 在 .env

  • ADMIN_USER
  • ADMIN_PASSWORD
  • API_TOKEN
  • SESSION_SECRET 可选;不设置时会从管理密码和 API Token 派生。

SMTP 公网发信

MailHub 现在提供公网 SMTP Submission。所有发信端口都需要 SMTP AUTH,未认证不会转发邮件,避免开放中继。

连接信息:

Host: in.ss5.xyz
Port 25:   SMTP + STARTTLS + AUTH
Port 587:  SMTP Submission + STARTTLS + AUTH
Port 465:  SMTPS implicit TLS + AUTH
Port 2525: SMTP + STARTTLS + AUTH
Username: 在面板左侧“SMTP 凭据”中配置
Password: 在面板左侧“SMTP 凭据”中配置,保存后不会回显

默认 SUBMISSION_ALLOW_INSECURE_AUTH=false,也就是 25/587/2525 必须先 STARTTLS 才允许 AUTH;465 连接建立时就是 TLS。

.env 中的 SUBMISSION_USERNAMESUBMISSION_PASSWORD 只用于首次初始化数据库。初始化后以面板保存的 SMTP 凭据为准,修改后无需重启。

当前 TLS 证书位于:

certs/mail-send.ss5.xyz.crt
certs/mail-send.ss5.xyz.key

这是一张自签名证书,只用于先把协议跑通。正式公网使用建议替换为包含 in.ss5.xyz 的可信证书,然后重启:

docker compose up -d app

当前默认配置

MAIL_HOSTNAME=in.ss5.xyz
SENDING_IP=8.231.54.11
DEFAULT_SPF_MECHANISMS=include:spf.mailjet.com
SMTP_HOST=postfix
SMTP_PORT=25

如果实际出站 IP 不是 8.231.54.11,需要同步修改 .env 和面板里对应域名的“发信 IP”。

DNS 重点

SPF 只能保留一条 v=spf1 TXT。不要为了 Mailjet、飞书、本机发信分别添加多条 SPF;要合并为一条。

in.ss5.xyz 测试记录

请为 in.ss5.xyz 添加或确认以下记录:

in.ss5.xyz.  A  8.231.54.11
_mailhub.in.ss5.xyz.  TXT  mailhub-verification=9e45358e44624ce991c655e9c19b847f8c98
mh202607._domainkey.in.ss5.xyz.  TXT  v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuaQrn0IrsNDVsbn160yOR7DMBaOkXegtlhUCvHYdKCy5Aa/rUcGvUI3gbLoo6m9QEiLs3EAJo29Y9RBbv3lQn/PvAKtfrTuT6Zo1BfcIhe9wJvipgAkH+hFmB4aNZ7MMTKE7vOztOHJooyyiJSHhgBqCVSG4fP7hr+vz5X8kAPXfasQnChHAmA1zM/m41/7qyo78C4pbqBiMAkkGV0zwNhaR1Fy1hdKx4IGpmrMrm5/sye4MK8dMD3jXooJ1Efv+Sh0HjpvKrN8zcxqvNDPusmIgZBxCN49m4R0dYsldK/v/KOeQJVfd+B6U0/2O8p2JHpd5Y1eaJjbREvFsKI30aQIDAQAB
in.ss5.xyz.  TXT  v=spf1 ip4:8.231.54.11 a:in.ss5.xyz include:spf.mailjet.com ~all
_dmarc.in.ss5.xyz.  TXT  v=DMARC1; p=none; rua=mailto:dmarc@in.ss5.xyz; adkim=s; aspf=s; pct=100

还需要在 IP 服务商控制台设置反向解析:

8.231.54.11  PTR  in.ss5.xyz

当前检测到 8.231.54.11 的 PTR 仍是 11.54.231.8.bc.googleusercontent.com

当前 ss5.xyz 已检测到两条 SPF,建议合并为:

v=spf1 include:spf.mailjet.com include:_netblocks.m.feishu.cn include:spf.ss5.xyz.com include:spf.97admin.com ip4:8.231.54.11 a:ali.ss5.xyz -all

当前测试发信主机使用 in.ss5.xyz,它应当解析到 8.231.54.11。二者需要保持对齐:

  • 如果由当前 Docker 服务器发信,把 in.ss5.xyz A 记录和 IP 的 PTR 都指向 8.231.54.11
  • 如果实际由 39.108.92.239 发信,把 .env 和域名设置里的 SENDING_IP 改为 39.108.92.239

PTR 反向解析需要在云厂商或 IP 服务商控制台设置,普通域名 DNS 控制台不能设置。

发送 API

curl -X POST http://mail-send.ss5.xyz/api/send \
  -H "Authorization: Bearer <API_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{
    "from": "noreply@ss5.xyz",
    "to": "user@example.com",
    "subject": "Hello from MailHub",
    "text": "Signed with DKIM and queued by Postfix."
  }'

SMTP 发信时,Host 使用 in.ss5.xyz。任意已添加并完成 DNS 配置的发信域名,都可以使用该域名下任意邮箱地址作为 From,例如 notice@example.combilling@example.comnoreply@example.com。本服务会按 From 所属域名查找 DKIM 私钥并签名。

生产发信前确认:

  • 服务器出站 25 端口没有被云厂商拦截。
  • 服务器入站 25/465/587/2525 已在云防火墙和系统防火墙放行。
  • SPF、DKIM、DMARC 均通过。
  • 发信 IP 的 PTR 指向 MAIL_HOSTNAME
  • MAIL_HOSTNAME 的 A 记录指回发信 IP。
  • 新 IP 先小流量预热,避免突然大批量发送。