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 被濫用,索性將郵件服務的端口全都封鎖了。

使用如下腳本檢測你的服務器是否具備搭建郵件服務器的條件:

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"

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

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/目錄,所以配置為:

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 填寫如下設置即可。

"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