Home DietPi部署邮件服务
Post
Cancel

DietPi部署邮件服务

docker mailserver(下文简称 DMS),是一个部署起来非常简单的邮件服务器方案。使用 docker 不和其他服务冲突,只包含邮件服务器非常简洁,最小安装需要的内存小于 500M,项目开发活跃。

背景知识

邮件服务主要参与者

  • MUA:客户端,如 K9 Mail
  • MTA:处理发送和接收,如 Postfix
    • 外向邮件给到 MTA,之后 MTA 一跳一跳给到最终收件人的 MTA
    • 内向邮件由 MTA 接收,之后给到 MDA
  • MDA:暂存邮件,提供给客户端,如 Dovecot
1
2
Sending an email:    MUA ----> MTA ----> (MTA relays) ----> MDA
Fetching an email:   MUA <--------------------------------- MDA

收发邮件涉及的端口和协议

image

上述参考

前置准备

  • 一个域名:可以用 freenom 申请,在家部署可以结合 dynu 的 ddns。下文这个域名都用 example.com 代表,复制命令时注意替换
  • 设备:少量邮箱,不开杀毒和垃圾邮件过滤的话 DMS 很不吃内存,大概几百 M。硬盘看邮件数量。如果开 vps 注意下述端口问题
  • 端口:25,465,993。如果用了 NAT 这几个端口要穿出去;如果用 vps 要提前查好,很多 vps 墙掉了往外发邮件的 25 端口,一些可以发工单申请开,实在开不了 25 端口可以用发送代理服务,下文有步骤
  • 需要 https 证书的域名:imap.example.com,smtp.example.com,推荐 letsencrypt 配置
  • 时间:dns 记录如果设错了,修改之后生效会需要一定时间,测试阶段可以把 TTL 设到最小。其他的操作都不是很耗时

安装

过完这一部分应该可以正常邮件和发站内邮件。

下载需要的文件

1
2
3
4
5
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 +x ./setup.sh

测试 docker,下面命令不是报错输出就行

1
./setup.sh help

修改配置文件内容

  • docker-compose.yml
    • hostname:一般叫 mail
    • domainname:服务器网址,如 example.com
    • volumes 加一条- /etc/letsencrypt:/etc/letsencrypt:ro:letsencrypt 的证书可能用软链接,docker 里和 host 里的路径需要完全相同,挂载的文件夹需要包含软链接文件和原文件
    • 可以注释掉 143 和 587 端口,这两个是允许明文收发邮件的不推荐用
  • mailserver.env
    • SSL_TYPE: letsencrypt

启停 DMS 用以下命令。注意:不要用 start/stop 或者 ctrl-c,可能导致问题

1
2
docker-compose up # 会占用一个tty显示log
docker-compose down

当调试完成的差不多,可以将 DMS 作为一个进程启动。DMS 默认配置会自动启动,这样系统 enable docker 的话,邮件服务开机后就会自动启动

1
docker-compose up -d

启动 docker mailserver

1
docker-compose up

以下命令都假设在docker-compose.ymlcontainer_name没改(默认是mailserver)。

首次启动时 dovecot 需要至少一个账户才能启动。首次启动之后开另一个命令行添加账户

1
./setup.sh email add me@example.com

别名 postmaster 账户

1
./setup.sh alias add postmaster@example.com me@example.com

要让其他邮件服务器可以找到负责 example.com 的邮件服务器,需要在 dns 里添加 mx(mail exchange) 记录。按照上面的配置,mx 记录的值应该是 mail.example.com。下面是一个例子

image

到这里就应该可以正常收邮件和发站内信了。DMS 不提供 web 界面,可以用 k9 mail app,nextcloud 的 mail 插件等查看邮件。配置过程中收邮件的协议应该是 imap,端口 993;发邮件的协议应该是 smtp,端口 465。这两个端口都是强制加密的,客户端和自己的邮件服务器之间的通信不会有明文邮件内容。

收多个域名的邮件

比如邮件服务器在 mail.example.com 上,想要收 me@another.com 邮箱的邮件。如果你能修改 another.com 的 mx 记录,这个非常简单。

首先在 DMS 里创建一个用户 me@another.com

1
docker exec -it mailserver setup email add me@another.com

之后给 another.com 添加 mx 记录。你会发现 mx 记录除了一个网址之外还有一个数,这代表这条 mx 记录的优先级,数越小优先级越高,一般是 10 的倍数。其他人在给 another.com 发邮件时会按 mx 记录优先级从高到低(那个数字从小到大)一个一个尝试,成功投递就不往后试了。你可以给自己的服务器一个高优先级,之后给一个第三方可靠的方案,比如 zoho(用自己的域名免费)或者 proton mail(用自己的域名应该收费)一个低的优先级作为备份。一个例子

image

上述参考

发送

为了在你收到一封邮件时可以相信:这个邮件真的是声称的发送者发的,内容没被篡改,发送者可以代表这个域名发邮件,发邮件比收配置起来复杂很多。首先确定你的网络环境可以从 25 端口往外发东西,否则就算能用 25 以外的端口发出邮件,接收方大概率也会拒收。

以下是个人对三个机制的理解,仅供参考。

DKIM(DomainKeys Identified Mail)

验证邮件发送者真的是声称的发送者。大概的机制应该类似 https,用私钥签名,公钥验证。在邮箱域名下会有一个 email._domainkey 的 txt 记录,里面包含一个公钥字符串。邮件发送时用邮件服务器上存的私钥+邮件的一些信息和内容生成一个签名,这样接收方可以验证邮件确实来自声称的发送方,而且内容在发送过程中没被篡改。如果你因为 25 的原因不能直接发出邮件,这个没必要配。

SPF(Sender Policy Framework)

一个白名单,也是一个 txt dns 记录,里面列出谁可以代表这个域名发邮件。

DMARC(Domain based Message Authentication, Reporting and Conformance)

DKIM 是一个检测,SPF 是一个白名单

v=DMARC1; p=none; rua=mailto:dmarc.report@linhan.ml; ruf=mailto:dmarc.report@linhan.ml; sp=none; ri=86400

  • p:如果 SPF/DKIM 校验没过,怎么处理这封邮件
    • none:Reports possible suspicious mail messages, but all mail is sent to inbox
    • quarantine:Fail SPF/DKIM policy, then message is sent to SPAM/Junk folder
    • reject:Fail SPF/DKIM policy, then message is dropped and not delivered at all
  • sp:和 p 一样,不过是给这个域名的子域名的。如果不计划用子域名,推荐设成 reject

DMARC 生成/校验工具

SMTP 代理

如果你服务器所在的网络环境不允许从 25 端口往外发邮件,可以用一个 smtp 代理。邮件先发到 smtp 代理,之后代理从他的 25 端口发出邮件。可选的服务商有很多,DMS 推荐了mailgunsendgridaws ses。我用的sendinblue,每天有 300 封免费额度。

DMS 方面的配置参考这里,填写 RELAY_HOST,RELAY_PORT,RELAY_USER,RELAY_PASSWORD 就行,信息服务商都会提供。

用代理的话 DKIM 是在代理那签,不需要自己配。DMARC 和自己直接发送没区别。自己的 spf 需要包含代理的 spf 规则。查一个服务商的 spf 规则可以用mxtoolbox。一般应该都是 spf.服务域名。比如这是 sendinblue 的 spf lookup 结果。这样你的 spf dns 记录应该就是如下:

1
v=spf1 include:spf.sendinblue.com -all

如果你还用了一个备份邮件服务,那需要结合两家的 spf,比如下面这样

1
v=spf1 include:spf.sendinblue.com include:spf.zoho.eu -all

注意 dns 记录不要超过 256 个字符。

更新

用 watchtower 可以在 dockerhub 镜像有更新时自动进行更新和重启 DMS,需要在 DMS 的 docker-compose.yml 中添加

1
2
3
4
5
6
  watchtower:
    image: containrrr/watchtower
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - /root/.docker/config.json:/config.json
    command: --interval 86400 --cleanup true

–no-restart:不重启

管理

列出服务器上所有的邮箱

1
./setup.sh email list
All Rights Reserved.

Python类型注解

-