Featured image of post docker-mailserver 邮件服务器搭建记录

docker-mailserver 邮件服务器搭建记录

本文详细讲解如何用 docker-mailserver 搭建邮件服务器,从配置文件、使用 Caddy 自动申请和维护 TLS 证书、DNS 到 DKIM、SPF 等发信认证,附带完整操作步骤和注意事项。

某天早上醒来,发现收件箱里多了封邮件,通知我的邮箱在韩国登录,当时认为只是偶尔的 IP 误判,也就没有多想。可接下来几天,时不时又有新的邮件进来,而且每次 IP 都不一样,这下可就有些问题了,再不采取行动,怕不是邮箱真的要被拿去群发邮件。于是赶紧删掉了域名的 MX、SPF、DMARC 记录,寻找新的解决方案。

我原本只是想改改密码,结果呢,腾讯企业邮箱改密码的入口真的巨能藏,到处都找不到。算了,迁移,何必受这气。

于是就有了这篇文章,从最开始的开放防火墙端口开始,到最后的优化送达率,我将分享我搭建 docker-mailserver 邮件服务器的经验,希望能帮你少踩些坑。

搭建 docker-mailserver 邮件服务器前的准备

防火墙的处理

首先先开放防火墙的邮件服务常用端口,分别是25143465587993,各分支开放端口的操作不同,请自行谷歌或询问 AI,以 Ubuntu 使用的ufw为例:

1
2
3
4
5
ufw allow 25
ufw allow 143
ufw allow 465
ufw allow 587
ufw allow 993

我的防火墙比较特殊,用到了ufwTo Fix The Docker and UFW Security Flaw Without Disabling Iptables 一文中提到的配置。所以当我想要把 Docker 容器的端口暴露在外时需要做出额外的配置。

1
2
3
4
5
6
# 开放邮件服务器所需的端口
ufw route allow proto tcp from any to any port 25
ufw route allow proto tcp from any to any port 143
ufw route allow proto tcp from any to any port 465
ufw route allow proto tcp from any to any port 587
ufw route allow proto tcp from any to any port 993

验证你的服务器是否具备搭建条件

很多服务器,尤其是各种廉价的 VPS,并不适合搭建 docker-mailserver,各大邮件服务商为了过滤垃圾邮件,索性将所有曾经有过 Spam 行为的 IP 全部列入黑名单。如果你的 IP 被某个 Spammer 使用过,而恰好又被你的服务器提供商分配给了你,而你折腾了几个小时的邮件服务器却愣是收不到邮件,最后发现竟是 IP 被列入黑名单的原因,我不知道你会作何感想。

有的服务器提供商的 IP 乍一看确实不在邮件黑名单中,但实际上搭建好之后还是无法发送邮件,为什么?因为服务器提供商担心 IP 被滥用,索性将邮件服务的端口全都封锁了。

使用如下脚本检测你的服务器是否具备搭建邮件服务器的条件:

1
bash <(curl -sL IP.Check.Place)

不能搭建邮件服务器 可以搭建邮件服务器

如果在这一步发现你的服务器不适合搭建甚至不能搭建docker-mailserver,那就趁早打住吧,想办法换一个更干净、限制更少的 IP 再说。

搭建过程

拉取配置文件

docker-mailserver 需要配置的配置文件有两个,compose.yamlmailserver.env,分别拉取配置文件:

1
2
3
4
mkdir mailserver && cd mailserver
sudo apt install wget
wget -O compose.yaml "https://raw.githubusercontent.com/docker-mailserver/docker-mailserver/master/compose.yaml"
wget -O mailserver.env "https://github.com/docker-mailserver/docker-mailserver/blob/master/mailserver.env"

根据需求,可以修改不同的配置,下面是我修改的部分:

1
2
3
4
5
POSTMASTER_ADDRESS=webmaster@l3zc.com
TZ=Asia/Shanghai
SSL_TYPE=manual
SSL_CERT_PATH=/certs/cert.crt
SSL_KEY_PATH=/certs/cert.key

用 Caddy 准备和自动维护 TLS 证书1

因为我已经在使用 Caddy,所以我这次就打算直接使用 Caddy 来自动维护证书。根据项目的官方文档,我只需要在 Caddyfile 里新增一个子域名,Caddy 就可以自动帮我维护证书。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
mail.example.com {
  tls internal {
    # ?? 这不是直接生成的内部证书么
    key_type rsa2048
  }

  # Optional, can be useful for troubleshooting
  # connection to Caddy with correct certificate:
  respond "Hello DMS"
}

当我更新完 DNS 记录,实际操作起来发现,我的情况比较特殊:我这台服务器上并没有用到 Caddy 的自动申请证书功能,而是使用了15年有效期的泛域名 Cloudflare Origin Certificate。即使我不为这个子域名指定证书文件,Caddy 也会在加载这张泛域名证书后认为无需再申请新的证书。这就很尴尬了,用 Caddy 的时候 Cloudflare Origin Certificate 和邮件服务器只能二选一。只好安装了dns.providers.cloudflare,并放弃使用 Cloudflare Origin Certificate,转而让 Caddy 自动为每个子域名申请和维护 TLS/SSL 证书,反正都是自动的,眼不见心不烦。

安装dns.providers.cloudflare后的全局配置:

1
2
3
{
        acme_dns cloudflare {API_KEY}
}

最后把 Caddy 的证书存储位置映射到 docker-mailserver 容器内。

1
2
volumes:
   - /home/user/.local/share/caddy/certificates/acme-v02.api.letsencrypt.org-directory/yourdomain.tld/:/certs/

如果 Caddy 以 root 用户运行,则证书的位置应当为/root/.local/share/caddy/certificates/acme-v02.api.letsencrypt.org-directory/yourdomain.tld/,做出相应的修改即可。

然后就是之前提到过的配置,我将证书存储位置映射到了容器内的/certs/目录,所以配置为:

1
2
SSL_CERT_PATH=/certs/cert.crt
SSL_KEY_PATH=/certs/cert.key

首次启动容器

首次启动容器需要立即(120 秒内)创建新的 Postmaster 账号。

1
2
docker compose up -d
docker exec -it <CONTAINER NAME> setup email add <postmaster@yourdomain.tld>

优化送达率

DNS 记录

  • 一条 A 记录,名称随意(假设为mail),指向服务器 IP(Cloudflare 需使用「仅 DNS」)
  • 一条 MX 记录,Apex 域(@),指向mail.yourdomain.tld
  • 一条 TXT 记录(SPF),Apex 域(@),可以在这里生成(可选)。
  • 一条 TXT 记录(DMARC),名称_dmarc,可以在这里生成(可选)。
  • 一条 TXT 记录(DKIM),名称mail._domainkey,具体配置在后文(可选)。

DKIM, SPF 和 DMARC2

什么是 DKIM,SPF 和 DMARC?简单来说,DKIM 是一个数字签名机制;SPF 类似于「员工名单」,记录所有合法的发件服务器;DMARC 则用于指示收件方的服务器如何处理未通过 DKIM 和 SPF 验证的邮件。3

首先设置 DKIM,在服务器上生成公私钥对。

1
docker exec -it <CONTAINER NAME> setup config dkim

生成后的公私钥对可以在映射的容器目录./docker-data/dms/config/opendkim/keys/下找到。

mail.txt 便是公钥的 DNS Zone file Cloudflare 的导入入口

下载 mail.txt(复制其内所有内容粘贴到本地文件也可以),将其导入到 Cloudflare Dashboard 即可完成 DKIM 设置。需要注意配置完成 DKIM 后需要重启容器才能生效。4

1
docker compose up -d --force-recreate

前面提到 SPF 相当于一个「员工名单」,既然我合法的发件服务器只有一台,那么 DNS 填写如下设置即可。

1
"v=spf1 mx ~all"

再就是 DMARC,可以使用前面提到的模板生成,这里不再赘述。

如果你的域名服务商拥有自己的设置向导(例如 Cloudflare),亦可以使用它们简化设置流程。

客户端设置

客户端设置相对就很简单了,IMAP 和 SMTP 服务器都是mail.yourdomain.ltd,开启 SSL 后端口分别是 465 和 993,登录即可。

设置示例

善用 MailTester

至此我们已经完成了搭建 docker-mailserver 邮件服务器的整个过程,在开始发送邮件之前,我们可以使用 MailTester 测试我们的配置是否正确。如果测试结果是 10/10,那么我们的 docker-mailserver 邮件服务器应该会拥有漂亮的送达率,好好享受吧。

完美的评分

如果不是 10/10,也不要着急,认真查看扣分的原因,对症下药,一项一项解决即可。

TODO-List

  • 配套 WebUI