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