SendGridのメール内リンクをSSL化する


SendGridには、受信者がメールを開封したこと(Open)、メール内のリンクをクリックしたこと(Click)を検知するOpen/Click Trackingという機能があります[1]

Open/Click Trackingを有効にするとデフォルトでは画像やリンクのURLがsendgrid.netドメインになります。これを任意のドメインに変更する機能がLink Brandingです。設定すると以下のようにメール内リンクのURLがhttp://(サブドメイン).(ドメイン)/hogeとなります。

これを見るとわかるようにリンクURLのスキーマはHTTPです。これをHTTPSにしたいというケースはあると思います。例えばHSTSをサブドメインにも強制している(includeSubDomains)とリンクにアクセスできなくなってしまいます。
SendGridのドキュメントには、スキーマをHTTPSにする方法が書かれています。と言ってもSendGrid自体はSSL証明書をホスティングできないので、間にCDNサービスや自前のプロキシを挟むことになります。

今回はCloudflareを使ってリンクURLをSSL化してみたので手順を紹介します。Cloudflareは無料でSSL証明書を使わせてくれるので全部タダで手軽にできます。

必要なもの

  • ドメイン
    • お名前ドットコムで無料ドメインを用意しました
  • SendGridアカウント
    • 無料会員登録はこちらから(審査あり)
  • Cloudflareアカウント
    • 用意したドメインのネームサーバをCloudflareに移しておきます

手順

1. Sender Authenticationの設定(SendGrid)

Sender Authenticationとは、メールの送信ドメイン認証設定(Domain Authentication)と先ほど登場したLink Brandingの2つの総称です。リンクURLに関係するのはLink Brandingだけですが、2つとも設定が必要だそうです[2]
手順はこちらの記事も詳しいです。

https://zenn.dev/kikutaro/articles/3b92dc0447fecd#sendgridのdomain-authentication%2Flink-branding

流れとしては自分のドメインを入力して表示されたDNSレコード(CNAME)を設定するだけです。以下はLink Branding用のレコードです。

途中、「Advanced Settings」の「Use a custom link subdomain」をチェックすると好きなサブドメインを指定できます。ここではlinkをサブドメインにしました。

CloudflareでDNSレコードをいじります。「Proxy status」のところがProxiedになっていると思うのでスイッチをオフにしてDNS onlyにしてSaveします。


設定が反映されているかdigします。

$ dig link.example.com cname +short
sendgrid.net.
$ dig 23456.example.com cname +short
sendgrid.net.

確認できたらSendGridの画面に戻り、Verifyボタンを押します。It workedの画面が表示されたらOKです。

2. Page Rulesの設定(Cloudflare)

Page Rulesでは特定のURLアクセスに対してどんな挙動をさせるかを設定できます。ここでlink.example.comドメインに対してSSLを設定します。

左側ペインの「Rules」を選んで新しいページルールを追加します。

URLはlink.example.com/*とします。settingとしてSSLを選択し、Fullを選びます。

デプロイして戻ると設定が反映されていることがわかります。

3. プロキシの設定(Cloudflare)

CloudflareのDNSの設定画面に戻ります。先ほどCNAMEレコードを設定したlink.example.comを検索し、「DNS only」となっていたProxy statusをスイッチオンして「Proxied」に変えてSaveします。

DNS onlyではCNAMEレコードでlink.example.comのエイリアスとしてsendgrid.netが指定されていただけでしたが、「Proxied」に変えることによってlink.example.comへのHTTPリクエストがCloudflareの(リバース)プロキシを経由するようになります。こうすることにより、先ほど設定したページルールに則ってCloudflareが動作します。

もう一度digしてみましょう。CNAMEレコードがなくなり、代わりにCloudflareのAレコードが設定されていることがわかります。

$ dig link.example.com cname +short # Answerなし
$ dig link.example.com a +short
172.67.147.32
104.21.63.150

心配性なのでリバースプロキシが本当にsendgrid.netにリダイレクトしているか見てみたいと思います。直で https://sendgrid.net にアクセスすると、nginxの404 Not Foundが返ります。https://link.example.comにアクセスしてみると同じくnginxの404 Not Foundが返ったので正常にリダイレクトされているようです[3]。鍵マークをクリックするとCloudflareの証明書が確認できます。

また、http://link.example.comにもアクセスしてみましょう。同様にnginxの404 Not Foundが返っていて、sendgrid.netにリダイレクトされています。HTTPでも正しくリダイレクトするようにしておかないと、以前送信したメールのリンク(HTTP)が切れてしまいます。

ちなみに、プロキシの設定を行うことで、元々SendGridのLink Brandingで指示されたDNSレコードを変えてしまったわけですが、この状態をSendGridが自動検知してリンク置換をやめたりはしません。このままメールを送信してもリンクは独自ドメインhttp://link.example.comで送られ、クリックすると正常に遷移します(HTTPのアクセスもsendgrid.netにリダイレクトされるので)。ただ、この時点でLink Brandingのlink.example.comの設定をもう一度VerifyするとSendGridがDNSレコードを確かめにいってしまうので、Link Brandingは一度設定したら触らない方が良いです。

4. SendGridへ問い合わせ

ここまでできたらサポートに問い合わせてと書いてあるので問い合わせます。日本代理店の構造計画研究所からアカウントを契約した場合は以下でも良いです。

https://sendgrid.kke.co.jp/

米国に問い合わせたからか半日ぐらい待ちましたが、設定完了の返事がきました。

再度メールを送ってみると、無事HTTPSになっていました🎉

注意点

  • スキーマの変更はアカウント単位だということです。アカウントに新たにLink Brandingのドメインを追加すると、そのドメインのもURLもHTTPSで送られます。ドメインを複数使うならサブユーザをドメインごとに使った方が良さそう。
  • 自前のプロキシを用意する場合の手順はこちら
脚注
  1. Open TrackingはHTMLメール内に配置した見えない画像へのアクセスを検知します。詳しい仕組みはこの記事とか ↩︎

  2. 米国SendGridサポート曰く ↩︎

  3. 正しくリダイレクトされることは正しく設定を完了するための必要条件であって十分条件ではありません。メール内リンクはhttps://link.example.com/ls/click?upn=hogehugaのようにクエリパラメータ等がつきますが、このような情報(たぶんヘッダも含め)が正しくSendGridに渡る必要があります。 ↩︎