在 Debian 12 + Docker + FRP 环境下,用 本地自签名证书 打造一台可 双向收发外网邮件 的个人/小团队邮件服务器。
全程无 Let’s Encrypt,5 分钟上线,5 分钟排坑。

组件 说明
宿主机 内网 PC(192.168.100.9)
外网入口 FRP → 101.43.11.156:25/587/993…
外发 IP 36.163.145.138(NAT)
域名 owin.work
镜像 mailserver/docker-mailserver:latest

2 一键部署流程

# 2.1 创建持久目录
mkdir -p {config,maildata,maillogs}
mkdir -p config/ssl/demoCA
# 2.2 手动生成自签名证书
mkdir -p config/ssl
openssl req -x509 -newkey rsa:4096 -nodes \
  -keyout config/ssl/mail.owin.work-key.pem \
  -out config/ssl/mail.owin.work-cert.pem \
  -days 365 -subj "/CN=mail.owin.work"
touch config/ssl/demoCA/cacert.pem   # 占位文件

# 2.3 启动容器(映射全部端口)
docker run -d \
  --name mailserver \
  --hostname mail.owin.work \
  --restart=always \
  -e TZ=Asia/Shanghai \
  -e SSL_TYPE=manual \
  -e SSL_CERT_PATH=/tmp/docker-mailserver/ssl/mail.owin.work-cert.pem \
  -e SSL_KEY_PATH=/tmp/docker-mailserver/ssl/mail.owin.work-key.pem \
  -e ENABLE_CLAMAV=0 \
  -e ENABLE_FAIL2BAN=0 \
  -p 25:25 -p 143:143 -p 465:465 -p 587:587 \
  -p 993:993 -p 995:995 -p 110:110 -p 4190:4190 \
  -v "$PWD/config:/tmp/docker-mailserver" \
  -v "$PWD/maildata:/var/mail" \
  -v "$PWD/maillogs:/var/log/mail" \
  mailserver/docker-mailserver:latest

3 账号管理

# 新增
docker exec mailserver setup email add user@owin.work 密码

# 列表
docker exec mailserver setup email list

# 删除
docker exec mailserver setup email del user@owin.work

4 DKIM(降垃圾箱必备)

# 生成密钥
docker exec mailserver setup config dkim

# 复制 TXT 记录
docker exec mailserver cat /tmp/docker-mailserver/opendkim/keys/owin.work/mail.txt

DNS 加一条 TXT:

主机名: mail._domainkey
值: v=DKIM1; h=sha256; k=rsa; p=MIIBIjANBgkq…(整段)
TTL: 600

5 DNS 总览

记录 主机名 TTL
A mail.owin.work 101.43.11.15 600
TXT @ v=spf1 ip4:36.16.15.138 ~all 600
TXT mail._domainkey DKIM 公钥 600
MX @ mail.owin.work 10 600

6 客户端配置

协议 服务器 端口 加密 用户名
SMTP mail.owin.work 587 STARTTLS user@owin.work
IMAP mail.owin.work 993 SSL user@owin.work

7 关闭入站 SPF 检查(避免 回信被拒)

docker-mailserver 默认启用 policyd-spf,会把外部来信(如 163)当外网 IP 做 SPF 比对,导致误拒。
一键关闭即可:

docker exec -it mailserver bash -c \
  "postconf -e 'policyd-spf_time_limit = 3600' && \
   postconf -e 'smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination' && \
   postfix reload"

8 一键重启脚本(保存为 restart.sh

#!/bin/bash
docker rm -f mailserver
docker run -d \
  --name mailserver \
  --hostname mail.owin.work \
  --restart=always \
  -e TZ=Asia/Shanghai \
  -e SSL_TYPE=manual \
  -e SSL_CERT_PATH=/tmp/docker-mailserver/ssl/mail.owin.work-cert.pem \
  -e SSL_KEY_PATH=/tmp/docker-mailserver/ssl/mail.owin.work-key.pem \
  -e ENABLE_CLAMAV=0 \
  -e ENABLE_FAIL2BAN=0 \
  -p 25:25 -p 143:143 -p 465:465 -p 587:587 \
  -p 993:993 -p 995:995 -p 110:110 -p 4190:4190 \
  -v "$PWD/config:/tmp/docker-mailserver" \
  -v "$PWD/maildata:/var/mail" \
  -v "$PWD/maillogs:/var/log/mail" \
  mailserver/docker-mailserver:latest

保存后 chmod +x restart.sh,随时一键重建。

9 踩坑 & 解决一览

阶段 现象 原因 解决
发信 550 SPF 外发 IP≠SPF TXT 写真实外发 IP
收信 550 SPF 入站 SPF 误拒 关闭 policyd-spf
证书 530 STARTTLS 证书缺失 本地自签名 + SSL_TYPE=manual
账号 535 Auth 未创建用户 setup email add
DKIM 550 Content 无签名 加 DKIM TXT

10 验证

发信:Foxmail → 163 → 日志出现 250 OK
收信:163 → 你的服务器 → Foxmail 实时收到
邮件服务器 双向收发完成!

证书对齐

进入持久卷目录

cd config/ssl

建立软链接(不改原文件,只让内部路径对齐)

ln -sf mail.owin.work-cert.pem cert.pem
ln -sf mail.owin.work-key.pem  key.pem

重启容器让脚本重新加载证书

docker restart mailserver