為什麼信會進垃圾桶

Gmail、Outlook、Yahoo 的垃圾郵件過濾器在判斷一封信時看兩件事:

技術信譽:這封信真的是你寄的嗎?

  • SPF:這個 IP 被授權從你的 domain 發信了嗎?
  • DKIM:這封信有你的私鑰簽名嗎?
  • DMARC:SPF 和 DKIM 都失敗時,要怎麼處理?

內容與行為信譽:你的寄信行為像不像 spammer?

  • 退信率高不高(hard bounce)
  • 用戶標記 spam 的比率高不高
  • 一次寄大量 email 給從來沒互動過的地址

技術部分是基礎,設錯了直接進垃圾桶;內容和行為部分是長期累積,做錯了 domain 信譽慢慢下降。


標準做法:子域名 + Cloudflare DNS

實際設定環境通常是:Cloudflare 管主域名 DNS,行銷部門用子域名發信:

主網站:        example.com           → Cloudflare 管
交易信:        mail.example.com      → 後端系統發(訂單確認、密碼重設)
行銷信:        newsletter.example.com → 行銷工具發(電子報、促銷)

這個架構是對的——子域名隔離信譽,行銷信的 spam 舉報率不會拖累交易信。

Cloudflare 的關鍵設定:橘色雲朵一定要關掉

Cloudflare DNS 記錄有兩種模式:

  • 🟠 橘色(Proxied):流量走 Cloudflare CDN
  • 🔘 灰色(DNS only):單純 DNS 解析

Email 相關的所有記錄必須是灰色(DNS only)

記錄類型為什麼要灰色
SPFTXTTXT 記錄本身不會被 proxy,但確認灰色是好習慣
DKIMCNAME橘色會讓 Cloudflare 把 CNAME 轉成 A record,provider 驗不到
DMARCTXT同 SPF
Bounce domainCNAME最常踩的雷——橘色導致 DMARC alignment 壞掉
MXMX本來就不能 proxy

SendGrid 要你設的 bounce domain 是一筆 CNAME:

bounce.mail.example.com  CNAME  sendgrid.net

如果這筆 CNAME 在 Cloudflare 開了橘色 proxy,Cloudflare 把它解析成自己的 IP,SendGrid 的 bounce server 找不到——DMARC alignment 斷掉,信繼續進垃圾桶,而且你找不到原因。


SPF(Sender Policy Framework)

SPF 是一筆 DNS TXT 記錄,列出哪些 IP 或服務被允許從你的 domain 發信:

# mail.example.com 的 SPF
v=spf1 include:sendgrid.net include:amazonses.com -all
  • include:sendgrid.net:SendGrid 的 IP 被授權代發
  • -all:不在清單的來源直接拒絕(生產環境用這個,不要用 ~all

SPF 最多 10 次 DNS lookup:每個 include: 遞迴計算,超過 10 次接收方判定 SPF fail。同時用多個 provider 時要注意。


DKIM(DomainKeys Identified Mail)

DKIM 用非對稱加密在每封信加數位簽名,接收方用 DNS 上的 public key 驗證:

設定流程

  1. 在 email provider 產生 key pair,provider 持有 private key
  2. 把 public key 加到 Cloudflare DNS(灰色 CNAME 或 TXT):
s1._domainkey.mail.example.com  TXT  "v=DKIM1; k=rsa; p=MIGfMA0..."
  1. Provider 用 private key 在每封信的 header 加簽名,接收方查 DNS 驗簽

DKIM 通過 = 信件內容沒被篡改、確實從你的 domain 出去的。


DMARC(Domain-based Message Authentication)

DMARC 宣告「SPF/DKIM 失敗的信怎麼處理」,並且讓你收到失敗報告:

# Cloudflare DNS TXT record
_dmarc.mail.example.com  TXT  "v=DMARC1; p=reject; rua=mailto:dmarc@example.com; pct=100"

建議的升級路徑

  1. 先設 p=none,用 rua 收報告——看有哪些合法來源沒通過
  2. 確認所有合法 sender 都通過後 → p=quarantine
  3. 觀察 2–4 週沒問題 → p=reject

報告原始 XML 很難看,用 dmarcian.comMxToolbox 解讀。


DMARC Alignment:最常被忽略的細節

SPF 和 DKIM 各自通過,不代表 DMARC 通過。DMARC 還要求對齊

From: hello@mail.example.com
  • SPF alignmentMAIL FROM(Envelope From)的 domain 必須和 From header 同根域名
  • DKIM alignmentd= 欄位必須和 From header 同根域名

常見問題:SendGrid 預設的 MAIL FROMbounces.sendgrid.net——和你的 mail.example.com 根域名不同,DMARC 的 SPF 檢查失敗,只剩 DKIM 撐著,信譽分數下降。

解法:在 SendGrid 設定自訂 bounce domain:

SendGrid → Settings → Sender Authentication → Custom Bounce Domain
設定:bounce.mail.example.com

Cloudflare DNS(灰色 CNAME):
bounce.mail.example.com  CNAME  sendgrid.net

設完後 MAIL FROMbounce.mail.example.com,和 From: hello@mail.example.com 同根域名(example.com),DMARC alignment 通過。


Shared IP 問題:設好了還是進垃圾桶

最常見的實際困境:子域名設好了、SPF/DKIM/DMARC 都對了、換過 SendGrid 也試過 Resend——信還是進垃圾桶。

根本原因:共用 IP 的信譽拖累

SendGrid、Resend、Mailgun 免費和低價方案是 shared IP pool——你和成千上萬其他用戶共用同一批 IP。其中有人在發垃圾信,整個 IP 段信譽變差,你的信跟著受牽連。換 provider 但還是 shared IP,問題沒解決。

標準解法

方案費用適合
AWS SES shared IP$0.10 / 千封先試,SES 的 IP pool 素質比 SendGrid free tier 好
Dedicated IP90/月確定問題在 IP 信譽後升級

AWS SES 注意:預設在沙盒模式,要申請 production access 才能寄給任意地址。新的 dedicated IP 需要 4–8 週 warm-up。

Warm-up 排程(新 IP 必做):

第 1 週:每天 ≤ 200 封(只寄給最活躍用戶)
第 2 週:每天 ≤ 500 封
第 3 週:每天 ≤ 1,000 封
第 4 週:每天 ≤ 5,000 封

退信處理(Bounce Management)

退信率超過 5% 是危險線——Gmail/Outlook 看到你的退信率高,會開始懲罰你的 domain。

Hard bounce(地址不存在)要永久封鎖,不能再寄:

// Provider webhook 自動處理
app.post('/webhooks/sendgrid', async (req, res) => {
  for (const event of JSON.parse(req.body.toString())) {
    if (event.event === 'bounce') {
      await emailSuppression.add(event.email, 'hard_bounce');
    }
    if (event.event === 'spamreport') {
      await notificationPrefs.disableMarketing(event.email);
    }
  }
  res.json({ ok: true });
});

詳細的應用層設計見 Notification 設計


郵件內容雷區

  • 圖片比例不能太高(純圖片 email 幾乎直接進垃圾桶)
  • HTML 版本必須附 plain text 版本
  • 行銷信必須有退訂連結(CAN-SPAM / GDPR 法規要求)
  • Gmail 2024 起要求 bulk sender 支援 List-Unsubscribe header

診斷流程

信進垃圾桶時的排查順序:

1. Cloudflare DNS 確認:email 相關 CNAME/TXT 全部是灰色雲朵
2. mail-tester.com 送測試信,看評分(9+/10 才算合格)
3. MxToolbox 確認 SPF/DKIM/DMARC 語法正確
4. 確認 SendGrid bounce domain 設為自訂子域名(DMARC alignment)
5. Google Postmaster Tools 查 domain 信譽分數
6. 還是有問題 → 換 AWS SES shared IP 試試
7. 特定接收方(企業信箱)有問題 → 確認是接收方政策問題

mail-tester.com 是最快的診斷工具,寄一封測試信就能看到每一項的詳細結果。


設定 Checklist

□ Cloudflare:email 相關 CNAME/TXT 全部改灰色(DNS only)
□ SPF TXT 設定,用 -all
□ DKIM CNAME/TXT 加到 DNS(灰色)
□ 自訂 bounce domain(SendGrid Sender Authentication)
□ DMARC 先設 p=none + rua
□ 行銷信和交易信用不同子域名
□ 新 IP/domain warm-up(前 4 週遞增)
□ Provider webhook 處理 bounce 和 spam report
□ 行銷信加 List-Unsubscribe header
□ Google Postmaster Tools 設定監控
□ DMARC 報告 2–4 週後升 p=quarantine → p=reject

延伸閱讀