你可以把 Email 寄送的過程想像成**「古代送信」,而 SMTP(寄信協定)本身設計得非常老舊且沒有安全感,就像一個毫無防備的郵差**。
為什麼 Gmail、Outlook 會把你的信當垃圾信?核心原因只有一個:「身分不明,缺乏信任」。
以下是用最白話的方式解釋這「三大護法」加上「黑名單」的運作邏輯:
1. 根本原因:SMTP 的天生缺陷
SMTP 協定在幾十年前發明時,並沒有設計「驗證身分」的功能。
這意味著,任何人都可以躲在暗巷裡,寫一封信,然後在信封寄件人(From)填上 president@whitehouse.gov。郵差(SMTP)根本看不出來這是假的,照樣幫你送。
為了防止這種「冒名頂替」,現代郵件系統發展出了三道檢查關卡:
2. 第一關:SPF (Sender Policy Framework) —— 「警衛與訪客名單」
- 概念:這是一份白名單。
- 運作:Gmail 收到你的信時,會去查你的 DNS(警衛室)問:「請問 IP
1.2.3.4(這位郵差) 有資格代表mydomain.com送信嗎?」- 如果沒有 SPF:Gmail 覺得這個郵差是隨便路過的,可疑 –> 垃圾信。
- 如果有 SPF:確認這是在名單上的合法郵差 –> 通過。
3. 第二關:DKIM (DomainKeys Identified Mail) —— 「完整的蠟封」
- 概念:這是一個數位簽名(防偽標籤)。
- 運作:就算郵差是對的,信件內容有沒有在半路被駭客竄改過?或者這是不是別人偽造了你的信頭?DKIM 就像是在信封口蓋了一個**「獨一無二的火漆蠟封」**(私鑰加密)。
- 沒有 DKIM:Gmail 收到信,發現信封沒封口,誰都能塞廣告進去 –> 垃圾信。
- 有 DKIM:Gmail 用你的公鑰檢查蠟封,發現完好無損 –> 確認是原廠出品,內容未被竄改。
4. 第三關:DMARC —— 「老闆的指令」
- 概念:這是一本指導手冊。
- 運作:如果有駭客偽造了你的信,導致 SPF 或 DKIM 檢查失敗了,Gmail 該怎麼辦?是直接丟掉?還是放進垃圾桶?還是通知你?DMARC 就是你(網域擁有者)告訴 Gmail:「如果有人冒充我(驗證失敗),請直接把它拒絕(Reject)!」
- 沒有 DMARC:Gmail 雖然抓到了假信,但不知道怎麼處理,可能會為了怕誤判而勉強收下,但也降低了你網域的權威性。
5. 隱藏大魔王:IP 信譽 (IP Reputation) —— 「前科紀錄」
就算你上述三種證件都齊全了,為什麼還會進垃圾桶?
- 原因:因為送信的那個 IP 位址(例如 AWS EC2 的 IP)可能有**「前科」**。
- 情境:如果上一位租用這個 IP 的人是用來發送百萬封詐騙信的,這個 IP 就會在國際反垃圾組織(如 Spamhaus)的黑名單上。
- 結果:Gmail 一看:「喔,這個 IP 是個慣犯!」不管你的證件多齊全,直接拒收。
總結
這就是為什麼我們要用 AWS SES:
- 解決 IP 前科:Amazon 會維護 IP 的清潔度,確保它們不在黑名單上。
- 解決 SPF/DKIM:讓 Gmail 相信**「這封信真的是你寄的,而且你授權了 Amazon 幫你跑腿」。
下面讓我們詳細講述設定的流程
1. AWS SES 前置作業 (在 AWS Console 操作)
這部分需要在 AWS 網頁介面上完成,請確保您選對了 Region (區域)(選有支援 SES 的區域)。
A1. 驗證網域 (Verify Domain)
- 進入 SES Console -> Configuration -> Identities。
- 點擊 Create identity -> 選擇 Domain。
- 輸入您的網域
mydomain.com。 - Publish DNS records to Route53: 請「不要」勾選此選項(保持未勾選狀態,除非您用Route53 管理您的網域)。
- Advanced DKIM settings: 選擇 Easy DKIM (預設值)。
- DKIM signing key length: 選擇 RSA_2048_BIT (比較通用) 或 1024 都可以。
- 點擊 Create identity。
A2. 獲取 CNAME 紀錄 (DKIM)
建立完成後,畫面會跳轉到該網域的詳細資訊頁面。往下滑,您會看到一個 「DKIM DNS records」 的區塊。
這裡會有 3 組 CNAME 紀錄。AWS 會給您兩個欄位:
- Name (主機名稱 / Host)
- Value (內容 / Target)
A3. 到您的 DNS 託管商新增紀錄
現在,請開另一個分頁,登入您的 DNS 管理後台。
您需要將那 3 組 CNAME 逐一新增進去。
⚠️ 超級重要的陷阱 (請務必注意)
大多數 DNS 託管商(如 Cloudflare, GoDaddy)在輸入「Name (Host)」時,會自動幫您補上網域後綴。
- AWS 顯示的 Name:
abcde12345._domainkey.mydomain.com - 您在 DNS 後台只需輸入:
abcde12345._domainkey
如果您把整串貼上去,就會變成 ...mydomain.com.mydomain.com,導致驗證失敗!
A4. 除了 CNAME,別忘了 SPF (重要!)
因為您要透過 AWS SES 寄信,您必須在 DNS 告訴全世界:「AWS SES 是我授權的寄件人」。
請在您的 DNS 後台檢查 TXT 紀錄 (SPF):
- 如果本來沒有 SPF 紀錄: 新增一條 TXT 紀錄:
- Host/Name:
@ - Value:
v=spf1 include:amazonses.com ~all
- Host/Name:
- 如果原本已經有 SPF 紀錄 (例如原本是設給 EC2 本機寄信): 請修改原本那條紀錄,把 AWS SES 加進去。
- 舊的可能長這樣:
v=spf1 mx ip4:1.2.3.4 ~all - 修改後:
v=spf1 mx ip4:1.2.3.4 include:amazonses.com ~all
- 舊的可能長這樣:
(重點就是一定要出現 include:amazonses.com 這段文字)
設定完後,通常等待 5 分鐘到 1 小時,回到 AWS SES Console 重新整理頁面,當 Status 變成綠色的 Verified,就代表成功了!如果沒成功,請檢查你輸入的DNS資訊是否正確,任何微小的錯誤都會導致驗證失敗
B. 申請移出沙盒 (Production Access) 剛開通的 SES 處於「沙盒模式 (Sandbox)」,只能寄信給「已經驗證過」的 Email。您必須申請移出沙盒才能寄給外面的陌生人。
- 在 SES Console 首頁上方會看到一個藍色警告條。
- 點擊 Request production access。
- 填寫用途(用英文寫:My mail server is for personal business communication, not for marketing spam…)。
- 通常需要等待數小時到一天審核。
C. 取得 SMTP 帳號密碼 (關鍵!) 注意:這不是您登入 AWS 的 IAM 帳號,這是 SES 專用的。
- 進入 SES Console -> SMTP Settings。
- 記下 SMTP Endpoint (例如:
email-smtp.us-east-1.amazonaws.com)。 - 點擊 Create SMTP credentials。
- AWS 會產生一組 IAM User Name、Smtp Username 和 Smtp Password。
- 請務必下載 CSV 或複製下來! 這個長得很像亂碼的密碼只會顯示這一次。
2. 安裝 SASL 相依套件
Postfix 需要這個套件才能拿著帳號密碼去向 AWS SES 登入。
sudo apt update
sudo apt install libsasl2-modules postfix-pcre -y
3. 設定 Postfix 指定 Relay Host
我們要修改 main.cf,告訴 Postfix:「以後寄給外部的信,不要自己送,全部轉交給 AWS SES。」
開啟設定檔:
sudo nano /etc/postfix/main.cf
請找到 relayhost 這一行(預設可能是空的),並在檔案的最下方加入/修改以下設定區塊:
# ==============================
# AWS SES Relay Configuration
# ==============================
# 1. 指定 AWS SES 的伺服器 (請換成您在步驟 1-C 看到的 Endpoint)
# 注意:要把網址用中括號 [] 包起來,並指定 :587
# 中括號的意思是「不要查 MX 紀錄,直接連線」,這能加速連線
relayhost = [email-smtp.us-east-1.amazonaws.com]:587
# 2. 啟用 SASL 認證 (Postfix 作為客戶端向 SES 登入)
smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
smtp_sasl_security_options = noanonymous
smtp_sasl_mechanism_filter = login
# 3. 強制使用 TLS 加密 (AWS 要求一定要加密)
smtp_use_tls = yes
smtp_tls_security_level = encrypt
smtp_tls_note_starttls_offer = yes
# 4. 指定 CA 憑證位置 (確保能驗證 AWS 的 SSL 憑證)
smtp_tls_CAfile = /etc/ssl/certs/ca-certificates.crt
存檔離開。
4. 建立密碼檔 (sasl_passwd)
我們要把剛剛從 AWS 拿到的 SMTP 帳號密碼寫入檔案。
建立新檔案:
sudo nano /etc/postfix/sasl_passwd
貼上以下內容(請替換成您自己的資料): 格式:[Endpoint]:587 Username:Password
[email-smtp.us-east-1.amazonaws.com]:587 AKIAIOSFODNN7EXAMPLE:AgGbq...VERY...LONG...PASSWORD...
(注意:前面的 Endpoint 也要加上中括號 [],必須跟 main.cf 裡寫的一模一樣)
存檔離開。
5. 雜湊密碼並保護檔案
這個檔案裡有明碼密碼,非常危險,我們要把權限鎖死,並轉換成 Postfix 讀得懂的 hash 檔。
# 1. 轉換成資料庫格式 (會產生 sasl_passwd.db)
sudo postmap hash:/etc/postfix/sasl_passwd
# 2. 將檔案的所屬群組改為 postfix (這樣 postfix 才有資格讀)
sudo chgrp postfix /etc/postfix/sasl_passwd /etc/postfix/sasl_passwd.db
# 4. 移除明碼檔案 (或是移到安全的地方備份)
# 這裡我們先改權限讓 root能讀寫 postfix能讀,確保安全
sudo chmod 0640 /etc/postfix/sasl_passwd /etc/postfix/sasl_passwd.db
# 3. 重啟 Postfix
sudo systemctl restart postfix
6. 最終驗收:寄信到 Gmail
現在,請再次打開您的郵件軟體(手機或電腦),透過您的 Mail Server 寄一封信給您的 Gmail。
觀察重點:
- 檢查 Log (
/var/log/mail.log): 您應該會看到類似這樣的訊息:status=sent (250 Ok ...)且會顯示連線到email-smtp.us-east-1.amazonaws.com。 - 檢查 Gmail 收件匣: 打開收到的信,點擊「顯示原始郵件 (Show Original)」。
- SPF: PASS
- DKIM: PASS (如果您在 AWS 有開啟 DKIM)
- DMARC: PASS (如果您 DNS 有設對)
- Encryption: Standard encryption (TLS)
如果 Log 顯示 Authentication failed:
- 檢查
sasl_passwd裡的帳號密碼是否填錯(是 SMTP 帳號,不是 IAM 帳號)。 - 檢查
relayhost和sasl_passwd裡的中括號[]是否一致。 - 記得每次改完
sasl_passwd都要執行sudo postmap hash:/etc/postfix/sasl_passwd。
全系列總結
恭喜您!經過這長途跋涉,您已經完成了一項許多工程師都覺得頭痛的任務。
您現在擁有一台:
- 獨立自主 的郵件伺服器 (Linux + Postfix + Dovecot)。
- 資料庫管理 的虛擬帳號系統 (MariaDB + SHA512)。
- 企業級 的傳輸安全性 (TLS + Let’s Encrypt)。
- 高信譽 的寄信通道 (AWS SES)。
現在,您可以自由地開設無限個 Email 帳號,掌控自己的數據,並享受自架服務的樂趣了!另外特別推薦使用Roundcube webmail作為你的Webmail解決方案,這個老牌的Webmail解決方案不但更新頻繁,還有強大的社群以及外掛程式(例如兩步驟驗證2FA等等),絕對值得您一試!