前提
邮箱服务器域名需要https证书,certbot证书申请教程
DNS
TTL是什么
在DNS中,TTL是"Time to Live"的缩写,表示DNS记录在网络上的生存时间。TTL是一个整数值,以秒为单位。当DNS客户端查询某个域名的DNS记录时,它会向DNS服务器发送查询请求。DNS服务器会返回相应的DNS记录,并在响应中包含该记录的TTL值。客户端收到响应后,会使用该记录的TTL值来确定该记录可以在本地缓存多长时间,超过该时间后,客户端会去重新查询DNS服务器以获取最新的DNS记录。邮件服务器没有完全搭建好的情况下,TTL不要设置太长时间,出现问题不太好调试
DNS设置
- 添加A记录,将邮箱域名(mail.example.com)指向你的服务器IP地址
- 添加MX记录,将邮件域([email protected],其中example.com就代表邮件域)指向第一步的邮箱域名,优先级默认为10(数字越低,优先级越高)
- 设置PTR记录(或者叫rDNS),可以通过ip地址反向解析出邮箱域名。不设置也没关系,但是会被某些服务器标记为垃圾邮件
DNS验证
# 验证MX记录
$ dig +short MX example.com
mail.example.com
# 验证A记录
$ dig +short A mail.example.com
11.22.33.44
# 验证rDNS(PTR)记录
$ dig +short -x 11.22.33.44
mail.example.com
也可以用在线网站验证
docker-compose.yml
访问https://github.com/docker-mailserver/docker-mailserver,
找到docker-compose.yml和mailserver.env,将这两个文件下载到服务器,保存在同一个目录里
对docker-compose.yml文件进行两处修改
-
environment中添加环境变量
SSL_TYPE=letsencrypt
-
把certbot申请的https证书挂载到docker-mailserver容器中
来自docker mailserver官方文档的一段话:
etc/letsencrypt/live
stores provisioned certificates in individual folders named by their FQDN.Make sure that the entire folder is mounted to docker-mailserver as there are typically symlinks from
/etc/letsencrypt/live/mail.example.com
to/etc/letsencrypt/archive
.意思是要将整个cert目录挂载到容器中,避免出现软引用问题导致证书找不到
修改后的docker-compose.yml文件如下所示
services:
mailserver:
image: ghcr.io/docker-mailserver/docker-mailserver:latest
container_name: mailserver
# Provide the FQDN of your mail server here (Your DNS MX record should point to this value)
hostname: <你的邮箱服务器域名,比如smtp.example.com>
env_file: mailserver.env
# environment的优先级更高,会覆盖.env文件中相同的环境变量
environment:
- SSL_TYPE=letsencrypt
- TZ=Asia/Shanghai
# More information about the mail-server ports:
# https://docker-mailserver.github.io/docker-mailserver/latest/config/security/understanding-the-ports/
# To avoid conflicts with yaml base-60 float, DO NOT remove the quotation marks.
ports:
- "25:25" # SMTP (explicit TLS => STARTTLS)
- "143:143" # IMAP4 (explicit TLS => STARTTLS)
- "465:465" # ESMTP (implicit TLS)
- "587:587" # ESMTP (explicit TLS => STARTTLS)
- "993:993" # IMAP4 (implicit TLS)
volumes:
- </path/to/your/certs-dir>:/etc/letsencrypt
- $PWD/volume/mail-data/:/var/mail/
- $PWD/volume/dms/mail-state/:/var/mail-state/
- $PWD/volume/dms/mail-logs/:/var/log/mail/
- $PWD/volume/dms/config/:/tmp/docker-mailserver/
- /etc/localtime:/etc/localtime:ro
restart: always
stop_grace_period: 1m
# Uncomment if using `ENABLE_FAIL2BAN=1`:
# cap_add:
# - NET_ADMIN
healthcheck:
test: "ss --listening --tcp | grep -P 'LISTEN.+:smtp' || exit 1"
timeout: 3s
retries: 0
环境变量
ENABLE_CLAMAV
病毒扫描。默认关闭。会占用大量的服务器资源,默认关闭。0:关闭 1:开启ENABLE_FAIL2BAN
登录密码多次失败,会将IP封禁。我曾经就因为自己输错密码导致被墙,容器内自带的setup命令可以解除封禁。默认关闭。0:关闭 1:开启 如果启用 Fail2Ban,请不要忘记将以下行添加到 docker-compose.yml:cap_add: - NET_ADMIN
SPOOF_PROTECTION
用户只能发送自己的邮件,避免发件人地址伪造,默认关闭(Each user only send with his own or his alias addresses) 0:关闭 1:开启
运行Docker-Mailserver
# 调试阶段,建议不要添加 -d 参数,看日志比较麻烦
docker compose up
运行后,有三件重要的事情要做
- Docker Mailserver规定首次运行容器时必须创建第一个邮箱账号,否则容器会自动退出
# 邮箱前缀随意,不一定非要是admin docker exec -it <CONTAINER NAME> setup email add [email protected]
- 为[email protected]这个邮箱地址添加一个别名(其实可以把刚才创建的第一个邮箱账号设置成postmaster的别名)
postmaster账号在Docker-Mailserver中扮演着非常重要的角色,它可以帮助管理员及时了解邮件服务器的运行情况,并进行相应的处理和调整,主要有以下几个用途:docker exec -it <CONTAINER NAME> setup alias add [email protected] [email protected]
- 用于接收系统警告和错误信息
- 用于接收未能送达的邮件
- 用于接收管理员通知和系统警报
- 验证https证书的有效性
或者可以在线验证:https://www.checktls.com/TestReceiver# 在服务器上运行以下代码 docker exec <mailserver-container-name> openssl s_client \ -connect 0.0.0.0:25 \ -starttls smtp \ -CApath /etc/ssl/certs/
其他配置
DNS添加DKIM记录
DKIM(DomainKeys Identified Mail)是一种邮件验证技术,它可以防止电子邮件被伪造和篡改。DKIM将邮件的头部和正文内容进行加密,并生成一个数字签名,这个数字签名可以验证邮件是否真的来自于发送者所声明的域名,以及邮件是否在传输过程中被篡改了。
输入以下命令,生成DKIM密钥,然后重新启动docker-mailserver
docker exec -it mailserver setup config dkim
进入volume挂载路径./dms/config/opendkim/keys/<yourdomain.com>
,可以看到mail.private和mail.txt两个文件,将mail.txt上传到cloudflare的DNS记录中
DNS添加SPF记录
SPF(Sender Policy Framework)是一种用于验证发件人身份的技术,它可以指定哪些IP地址可以用于发送特定域名的邮件。
# 给domain.com这个邮件域域设置一条TXT记录,TTL设置时间短一点
v=spf1 a mx ip4:108.182.201.242 -all
v=spf1
表示这是 SPF记录的版本号,目前只有一个版本a
表示授权由域名对应的A记录中列出的IP地址发送邮件mx
表示授权由域名对应的MX记录中列出的IP地址发送邮件ip4:108.182.201.242
表示授权指定的IPv4地址发送邮件- SoftFail和HardFail是两种策略,用于指定未经授权的发件人邮件如何处理
~all
宽容策略。如果发件人的IP地址不在SPF记录中指定的允许列表中,那么收件方的邮件服务器不会拒绝该邮件,而是将该邮件标记为“软失败”,并将其放入接收方的垃圾邮件文件夹或者标记为垃圾邮件。-all
严格策略。如果发件人的IP地址不在SPF记录中指定的允许列表中,那么收件方的邮件服务器会拒绝该邮件,并将其退回给发件人或者直接删除
更多的SPF语法规则在这里http://www.open-spf.org/SPF_Record_Syntax/
DNS添加DMARC记录
DMARC(Domain-based Message Authentication, Reporting, and Conformance)是一种邮件验证技术,它可以帮助域名所有者控制其域名下的邮件发送,防止电子邮件被伪造和滥用。DMARC是SPF和DKIM的补充,可以对SPF和DKIM的验证结果进行汇总和分析,并指定如何处理未经验证或验证失败的邮件。简单来说,就是防止其他人用你的邮箱地址向别人发送邮件
DMARC 策略共有 11 个标签。在这 11 个标签中,v
和p
标签是必需的,我们强烈建议也使用rua
标签和ruf
标签以便接收报告。标签详情:https://mxtoolbox.com/dmarc/details/what-is-a-dmarc-record,还有个中文文档:https://dmarcly.com/blog/zh-CN/getting-started-with-dmarc
例子:
v=DMARC1; p=reject; rua=mailto:[email protected]; ruf=mailto:[email protected]; sp=reject; aspf=s; adkim=s; rf=iodef; ri=86400
工具:
发送/接收邮件
Docker Mailserver没有提供webui,因此发送邮件和接收邮件要借助第三方网站或邮件客户端,连接时的端口号优先用大数字(如:SMTP选587,IMAP选993,POP选995)
接收邮件优先用IMAP,IMAP和POP3的区别可以看这篇文章
Docker Mailserver默认不启用POP3,需要将端口110和995和环境变量ENABLE_POP3添加到docker-compose.yml
mailserver:
ports:
- "110:110" # POP3
- "995:995" # POP3 (TLS)
environment:
- ENABLE_POP3=1
重启才能生效,检查pop3端口有没有打开
# 显示协议名
lsof -i | grep LISTEN
# 显示端口号
lsof -i -n -P | grep LISTEN
也可以用代码发邮件
❗邮件发送成功后,邮件服务器不会保存邮件的副本。如果你有这个需要的话,发送邮件时请一定"密码抄送"给你的备份邮件
邮件健康值检测
常用命令
查看用户列表
docker exec -it mailserver setup email list
添加用户
docker exec -it mailserver setup email add <EMAIL ADDRESS> [<PASSWORD>]
# 比如
docker exec -it mailserver setup email add [email protected] "password123"
修改邮箱账户的密码
docker exec -it mailserver setup email update <EMAIL ADDRESS> [<PASSWORD>]
# 比如
docker exec -it mailserver setup email update [email protected] "password123"
setup命令还有一些其他功能
# 查看setup命令帮助
docker exec -it mailserver setup
常见问题
邮件发送失败
- 优先检查DMARC记录中
RUA
和RUF
填写的邮箱地址,以及[email protected]账号的alia别名。设置无误的情况下,你会在你的邮箱中收到"邮件发送失败"的提醒,可以快读定位问题 - 利用在线DNS工具检测每项记录的值(A,MX,DKIM,SPF,DMARC)是否正确。DNS缓存会导致某些记录值不是最新的,需要把TTL调小
- 你的域名开启了CDN代理,邮箱服务器使用的不是80端口和443端口,CDN代理服务器可能会拒绝非80和443端口的请求
- 还有一个可能的原因,DNS上设置了TLSA记录,删除了再看看
第三方客户端无法连接到邮件服务器
lsof -i -n -P
查看端口是否处于被监听状态iptbales -L
查看端口是否被其他软件过滤,比如:ufw、fail2ban- 用端口扫描工具检测下,端口是否开放。有可能是服务器厂家禁用了端口
nmap -p 25,143,465,587,993,110,995 <服务器IP地址>
- 检查DNS设置,参考最最最上面第一步
- 检查HTTPS证书是否有效