用 Cloudflare + SendGrid 在自己的 domain 免費收發 email

前言

要架一個 mail server 並不容易,除了要隨時跑著一台伺服器外,家用或 VPS 的 IP 也不夠純淨,通常會被 Google 跟 Microsoft 當成垃圾信。

此文會介紹怎麼使用 Cloudflare 來收信並轉寄到 Gmail,並從 Gmail 透過 SendGrid 來寄信,而且可以用無限多個 email address。

Email flow

Cloudflare 收信

Cloudflare 免費方案提供了無限用量的 Email Routing 服務,可以將收到的 email 轉寄到指定的信箱,而且支援 Catch-all。

在 Dashboard 啟用 Email Routing 後,Cloudflare 會自動替你設定三個 MX record 跟一個 SPF record,可以在 Settings Tab 看到。為了後續 SendGrid 的設定,我們必須先將它 Unlock,不然 Cloudflare 不會讓我們動這四個 record。

Email Routing records

開啟 Email Routing 後,先在 Destination addresses 新增自己的 Gmail 並驗證,接下來就可以去 Routing Rules 新增路由規則。

要接收所有 email 可以直接使用 Catch-all,也可以針對不同的 email address 設定不同的轉寄規則。

Routing Rules

SendGrid 寄信

SendGrid 是一個可以用 API、SMTP Relay 來寄信的服務,免費方案每天可以寄 100 封,驗證 domain 後可以使用任意 email address 來寄信。

要註冊 SendGrid 帳號需要一點技巧,如果從官網註冊的話有 99% 會被擋掉(至少我不是那 1%,送了三次都被擋==),個人用戶開 ticket 也只會等三天然後被拒絕,這時我們可以用 Google Cloud Platform 裡面的 Marketplace 來訂閱 SendGrid Free Plan,理論上只要開一張 ticket 證明一下你是誰就可以了,內容大致如下:

To have your account reviewed, please reply back to this email with the following:
1. User Identification
Your first and last name to help us confirm your identity.
Any of your personal social media profiles such as LinkedIn, Facebook, Twitter, or your online portfolio such as GitHub or Upwork, showing your full name.
An email address which matches your website domain or a screenshot of a receipt that verifies domain ownership.
2. Intended Use Case
A complete description of the services/products your organization provides to better understand the nature of your business.
3. Email Type
Will you be sending Transactional or Marketing emails?
How will your recipient's email addresses be collected (opt-in)? Please provide a link to an accessible website for your organization or a screenshot of the registration flow. If the website is not publicly available yet, a mock-up of the sign-up page will suffice.

成功註冊後,先在 Settings > Sender Authentication 驗證自己的 domain,依照指示設定三個 CNAME record (emXXX.、s1._domainkey、s1._domainkey) 跟一個 TXT record (_dmarc)。

設定完成後建議 Single Sender Verification 也一同設定,我不太確定會不會影響被當垃圾信的機率。

Sender Authentication

設定完後就可以在 Settings > API Keys 新增一個 API Key,權限可以只給 Mail Send

Gmail 設定

拿到 SendGrid 的 API Key 後,就可以在 Gmail 設定 SMTP Relay 了,這樣就可以用 SendGrid 來寄信了。

點開右上角齒輪 > 查看所有設定 > 帳戶和匯入 > 選擇寄件地址 > 添加另一個電子郵件地址,名稱任取,電子郵件地址為你的 domain,照下列設定 SMTP 伺服器並儲存:

  • SMTP 伺服器:smtp.sendgrid.net
  • 連接埠:587
  • 使用者名稱:apikey
  • 密碼:你的 SendGrid API Key
  • 採用 TLS 的加密連線 (建議使用)

Gmail SMTP settings

Gmail SMTP settings

接下來在寄信時就可以選這個 email address 來寄信了 🎉

SPF、DKIM、DMARC

為了避免被當成垃圾信,我們還需要確認 SPF、DKIM 跟 DMARC 有正確設定。

SPF

Sender Policy Framework 用來確認寄件者是否有權利使用這個 domain 來寄信。在這案例中會有兩個寄件者,分別是用來寄信的 SendGrid,還有 Cloudflare 轉寄給你。DNS record 會長這樣:

Type Name Value
TXT @ v=spf1 include:_spf.mx.cloudflare.net include:sendgrid.net ~all

其中 include 代表允許這些 domain 下的 IP 來寄信,~all 代表把不符合規則的信標記為垃圾信。

DKIM

DomainKeys Identified Mail 用來簽署寄出的 email。在 SendGrid 設定時便已設定好兩個 domain key,DNS record 長這樣:

Type Name Value
CNAME s1._domainkey s1._domainkey.uXXXX.wlXXX.sendgrid.net
CNAME s2._domainkey s2._domainkey.uXXXX.wlXXX.sendgrid.net

DMARC

Domain-based Message Authentication Reporting and Conformance 用來告訴收信者這個 domain 的寄信規則。

Cloudflare 提供了 DMARC Management,啟用後會設定一個 TXT record,DNS record 長這樣:

Type Name Value
TXT _dmarc v=DMARC1; p=quarantine; rua=mailto:xxxx@dmarc-reports.cloudflare.net

其中 p 代表不符合規則的信要怎麼處理,none 代表不處理,quarantine 代表標記為垃圾信,reject 會直接拒收。 rua 代表收件者該把狀況通報給誰,這裡是通報給 Cloudflare 自動分配的 email,不用動它。

結語

筆者用這個方法大概一年多了,收信、寄信都沒問題,但就是有時會被 Gmail 當成垃圾信,通常是因為 domain 的信譽不夠好,可以透過 Gmail Postmaster Tools 來看收信狀況還有被當垃圾信的原因。

另外 SendGrid 還有提供自訂 domain 的連結追蹤(Link Branding)、開信追蹤(Pixel tracking,domain 信譽不好會被當垃圾圖片QQ)等功能,可以摸索看看。