快速搭建一台邮件服务器

用网站域名发送邮件是不是很酷的一件事, 当然作用远远不止如此, 来看看搭建一台邮件服务器是多么便捷吧\( ̄︶ ̄*\))

0%

准备环境

域名: example.com
系统: Ubuntu20
工具: docker-compose

创建工作目录

mkdir /data/mail-server

下载相关文件

DMS_GITHUB_URL='https://raw.githubusercontent.com/docker-mailserver/docker-mailserver/master' && \
wget "${DMS_GITHUB_URL}/docker-compose.yml" && \
wget "${DMS_GITHUB_URL}/mailserver.env" &&
wget "${DMS_GITHUB_URL}/setup.sh" && chmod a+x ./setup.sh

修改配置

基础配置 - 修改docker-compose.yml

  • example.com替换成要自己的域名
services:
mailserver:
image: docker.io/mailserver/docker-mailserver:latest
container_name: mailserver
hostname: mail
domainname: example.com
env_file: mailserver.env
...

高级配置 - 修改mailserver.env

  • 详细说明Environment Variables - Docker Mailserver
    PS: 这里使用默认配置就行了, 推荐用 docker-compose.yml添加环境变量的方式 来进行修改

启动服务

docker-compose up -d

查看日志输出是否正常

docker-compose logs -f

这里提示要创建账户, 使用setup.sh进行创建

./setup.sh email add <user@domain> [<password>]

# 例子 密码稍后可以更改为更复杂的
./setup.sh email add admin@example.com password

设置别名

./setup.sh alias add postmaster@<domain> <user@domain>

# 例子
./setup.sh alias add postmaster@example.com admin@example.com

PS: 使用./setup.sh help可以查看命令说明

添加DNS记录

在相应的DNS服务中配置, 注意将IP替换成邮件服务器的IP
SPF 官方文档: https://docker-mailserver.github.io/docker-mailserver/edge/config/best-practices/spf/

类型 名称 说明
A mail 10.11.12.13 邮件服务器地址, 名称可以随意改, 推荐使用mail
MX @ mail.example.com. MX记录, 指定了发送邮件时的收信服务器, 通过设置优先级转发邮件
TXT @ v=spf1 mx include:mail.example.com ~all SPF记录, 告知了可以用这个域发邮件的主机, 防止别人伪造你来发邮件
TXT _dmarc v=DMARC1; p=none; rua=mailto:dmarc.report@example.com; ruf=mailto:dmarc.report@example.com; sp=none; ri=86400 告诉发件人邮件受SPF/DKIM保护

配置OpenDKIM

DKIM 官方文档: https://docker-mailserver.github.io/docker-mailserver/edge/config/best-practices/dkim/

创建大小为1024位的密钥(密钥大小最好在512到2048位之间)

./setup.sh config dkim keysize 1024

密钥文件存放在docker-data/dms/config/opendkim/keys目录下

查看生成的值

cat docker-data/dms/config/opendkim/keys/example.com/mail.txt

PS:重新生成的话, 直接删除文件夹即可

再将其合并起来, 这是要添加的DNS记录值

v=DKIM1; h=sha256; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC+t0EBt4tRKq3hVGOgaOfvA8NbG92xNsCIWVfG6eA5If3vlE6iDg3KKU+Q6GyZD20W0I/Q2BqLIyMehiWnJO0vKrIlNfsNIiugBTyVZpxBlQhxk1dNJ29g6alZbY9PRye0WYxkKiIc9aIz+YptYS2kClIpmgjaHtncFcvTltbkOwIDAQAB

在DNS服务商添加相应的记录

类型 名称
TXT mail._domainkey v=DKIM1; h=sha256; k=rsa; p=MIGfMA0GCSqGSIb3DQE...

等待几分钟后再检查记录DNS是否生效

dig mail._domainkey.example.com TXT

配置 SSL

等待DNS生效的时间, 让我们先配置一下证书吧.
文档: https://docker-mailserver.github.io/docker-mailserver/edge/config/security/ssl/

生成证书

在工作目录下运行镜像快速生成mail.example.com证书
注意: 将example.com替换成自己的域名, 80端口开放且不要被占用

docker run --rm -it \
-v "${PWD}/docker-data/certbot/certs/:/etc/letsencrypt/" \
-v "${PWD}/docker-data/certbot/logs/:/var/log/letsencrypt/" \
-p 80:80 \
certbot/certbot certonly --standalone -d mail.example.com

根据提示操作生成, 完成后docker-data/certbot/certs目录结构应该和下面一样

docker-data/certbot/certs
├── accounts
├── archive
├── csr
├── keys
├── live
├── renewal
└── renewal-hooks

配置证书自动续期

创建renew-certbot.sh文件

vim renew-certbot.sh

添加以下内容, 注意工作目录是否一致
PS: 使用Nginx之类反代, 可以在续期前停止服务, 续期完后打开

docker run --rm -it \
-v "/data/mail-server/docker-data/certbot/certs/:/etc/letsencrypt/" \
-v "/data/mail-server/docker-data/certbot/logs/:/var/log/letsencrypt/" \
-p 80:80 \
-p 443:443 \
certbot/certbot renew
chmod a+x renew-certbot.sh

测试是否正常, 注意443端口需开放

./renew-certbot.sh

添加到计划任务crontab -e

30 0 * * * /data/mail-server/renew-certbot.sh > /dev/null

修改服务配置

修改docker-compose. yml配置文件, 添加环境变量SSL_TYPE和证书映射路径.

services:
mailserver:
environment:
- SSL_TYPE=letsencrypt
volumes:
- ./docker-data/certbot/certs/:/etc/letsencrypt

完整配置如下:

services:
mailserver:
image: docker.io/mailserver/docker-mailserver:latest
container_name: mailserver
hostname: mail
domainname: example.com
env_file: mailserver.env
ports:
- "25:25" # SMTP (explicit TLS => STARTTLS)
- "143:143" # IMAP4 (explicit TLS => STARTTLS)
- "993:993" # IMAP4 (implicit TLS)
- "587:587" # ESMTP (explicit TLS => STARTTLS)
- "465:465" # ESMTP (implicit TLS)
environment:
- SSL_TYPE=letsencrypt
volumes:
- ./docker-data/dms/mail-data/:/var/mail/
- ./docker-data/dms/mail-state/:/var/mail-state/
- ./docker-data/dms/mail-logs/:/var/log/mail/
- ./docker-data/dms/config/:/tmp/docker-mailserver/
- ./docker-data/certbot/certs/:/etc/letsencrypt
- /etc/localtime:/etc/localtime:ro
restart: always
stop_grace_period: 1m
cap_add:
- NET_ADMIN
healthcheck:
test: "ss --listening --tcp | grep -P 'LISTEN.+:smtp' || exit 1"
timeout: 3s
retries: 0

更新配置

docker-compose down && docker-compose up -d mailserver

测试证书是否生效

docker exec mailserver openssl s_client \
-connect 0.0.0.0:25 \
-starttls smtp \
-CApath /etc/ssl/certs/

正常情况下会输出证书修改信息, 若没有则检查证书目录路径挂载是否正确, 容器配置是否更新.

开放相关端口

进入 https://www.checktls.com/TestReceiver 进行TLS测试, 填入mail.example.com, 查看外部访问是否正常.

自定义证书

这里不推荐使用其它工具生成的证书, 配置不方便而且容易有意外.

准备好SSL证书文件, 这里是使用的是acme.sh生成的证书 -> Nginx 使用 acme.sh 配置 SSL 证书
修改docker-compose.yml, 添加以下配置.

volumes:
- /usr/local/nginx/certs/mail.example.com/:/tmp/dms/custom-certs/:ro
environment:
- SSL_TYPE=manual
# 这里记得修改成挂载目录下对应的文件名
- SSL_CERT_PATH=/tmp/dms/custom-certs/fullchain.cer
- SSL_KEY_PATH=/tmp/dms/custom-certs/cert.key

到这一步不出意外应该可以正常收邮件了, 可以向其邮件地址发送邮件查看后台是否出现日志来进行测试.


邮件客户端登录

这里使用Win自带的邮箱客户端进行演示(其它客户端操作大同小异)

首先先添加账户, 选择带有POP/IMAP的邮箱

填入邮箱地址和密码登录, 邮箱和别名可用./setup.sh email list查看
注意用户名一定要填完整邮件地址

邮件服务器填mail.example.com, 认证类型选择IMAP4, 补全其它选框进行登录

PS: 登录不成功可以查看后台日志, 是否出现记录, 日志信息是什么一一解决

测试优化

进入 Newsletters spam test 进行测试, 发送测试邮件后会给出相应的分数(过低会被扔进垃圾邮箱), 然后再根据提示去优化分数或定位问题.

或者使用 Microsoft Remote Connectivity Analyzer 进行测试
image-20230130145336996

其它配置(可选)

添加日志报告

...
environment:
- REPORT_RECIPIENT=qaqiowo@gmail.com # 报告接收人
- LOGWATCH_INTERVAL=daily # 每隔一天发送日志报告 周使用 weekly

启用POP3认证

修改docker-compose.yml, 添加端口映射和配置环境变量

services:
mailserver:
ports:
...
- "110:110" # POP3
- "995:995" # POP3 (with TLS)
environment:
- ENABLE_POP3=1
...

更新配置

docker-compose down && docker-compose up -d mailserver

启用邮件转发

修改docker-compose.yml, 添加SPOOF_PROTECTION=1环境变量

services:
mailserver:
environment:
- SPOOF_PROTECTION=1

转发到谷歌邮箱, 往info@example.com发送邮件会被external-account@gmail.com接收到(而且可以设置多个别名)

# 邮件后缀需要加上 .gmail, 这里使用别名进行添加
./setup.sh alias add info@example.com info.gmail@example.com
./setup.sh alias add info.gmail@example.com external-account@gmail.com

PS: 转发不生效检查日志, 若出现PTR记录错误, 则需修改服务器的rDNC, 通常在服务器提供商处修改.

邮件服务更新

docker-compose pull
docker-compose down && docker-compose up -d mailserver

疑难杂症

  • 邮件发送接收不到

    查看IP是否被封: https://mxtoolbox.com/blacklists.aspx

应用方向

  • 内部邮件服务器
  • 网站自动化注册
  • 匿名邮箱
  • ...

无代码快速实现

使用 cloudflare.com 服务, 更改域名DNS服务器, 一键启用域名邮件(免费). | 2022-05


参考文档

https://docker-mailserver.github.io/docker-mailserver/edge/
https://github.com/docker-mailserver/docker-mailserver

------------ 已触及底线了 感谢您的阅读 ------------
  • 本文作者: OWQ
  • 本文链接: https://www.owq.world/mail-server/
  • 版权声明: 本站所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处( ̄︶ ̄)↗