SendGrid API v3
この記事はSendGrid Advent Calendar 2016の23日目の記事です。
今年1番のSendGrid界隈のニュースといえば2016年6月にリリースされたSendGrid v3のリリースではないでしょうか。よりRESTFulになり、細やかなオプション制御にも対応しつつ便利になりました。クラウドワークスでも社内で利用しているサービスをv3 APIに対応したのでその際の課題や対応するためのワークアラウンドを共有します。
v2とv3の違い
v2 APIとv3 APIで筆者が感じる大きな違いは、APIに渡すのに必要なデータの構造が整理されて取り扱いしやすくなった点です。メール送信のapiを例にあげると、v2 APIでは下図のようにメール送信に必要な情報として宛先と埋め込みたいテキストを別々の配列として渡していました。正しく動いている時は問題ないですが、開発中であるとかバグで配列の数や位置がずれたときに意図しない相手に意図していない埋め込みテキストのメールを送信してしまいかねない構造になっています。
一方v3 APIでは1通のメール送信に必要なデータが SendGrid::Personalization
としてまとめられているため、構造的に送信先と埋め込みデータがズレるといったことが起きにくくなっています。
開発しているシステムの堅牢性を向上する意味でもv3 APIへ移行する意義は十分ありそうです。他にも送信時にリンクのトラッキングの有無を設定できるようになったり細やかな要求に耐えられるようになりました。
v3 APIの日本語エンコーディングの問題
メール送信の日本語処理について公式にもいくつかの不具合があるとアナウンスされています。こちらの利用環境でも、とある不具合に遭遇しました。
具体的にはSubstitution
を使ってメール本文の埋め込みテキストを置換してメール送信するとSubject
が生のUTF-8のまま送信されてしまう問題がありました。Gmailではそのまま表示されるので気が付きにくいです1。
回避策としては以下のようにSubject
にも空のSubstitution
を渡すことでBASE64エンコードしてくれるようになります2。
sendgrid = SendGrid::API.new(api_key: SENDGRID_API_KEY)
mail = SendGrid::Mail.new
from_name, from_addr = from.split(' ')
mail.from = SendGrid::Email.new(email: from_addr, name: from_name)
# 件名の後ろに置換用のダミーを追加します
mail.subject = subject + "_dummy_"
to.size.times do |i|
personalization = SendGrid::Personalization.new
personalization.to = SendGrid::Email.new(email: to[i], name: names[i])
personalization.substitutions = SendGrid::Substitution.new(key: '_fullname_', value: names[i])
# 件名をエンコードさせるためダミーを空文字で置換します
personalization.substitutions = SendGrid::Substitution.new(key: '_dummy_', value: "")
mail.personalizations = personalization
end
sendgrid.client.mail._('send').post(request_body: mail.to_json)
と、これを書いている2016年12月現在、この問題は修正されたとの連絡をいただきました!
現在では本文のみ置換していてもSubject
を問題なくエンコード文字列にしてくれるようです(まだ試せていない)。
認証とapi_key
v3 APIは基本的にapi_key
での利用が前提になります。v2 APIでID/Passで認証で呼び出していた場合はAPIライブラリの初期化まわりを書き換える必要があります。また、api_key
の利用目的によって実行できる操作を許可したり制限したりすることができます。使いたい機能に絞った権限を付与して安全に利用できます。サブユーザーの切り替えについても直接ID/passで認証するのではなくそれぞれのサブユーザーで生成したapi_key
を利用します。
権限の付与
api_key
はWebのSendGridダッシュボードで生成できます。しかし、残念なことにWebからは割り当てられない権限がたくさんあります。以下のAPIリファレンスに載っている細かい権限については権限を与奪するAPIをcurl
などで叩いて設定します。
権限の付与には、より強い権限をもった認証をしないとできないのでマスターアカウントのパスワードで認証してAPIを叩いて設定します。たとえば以下はサブユーザーのStatsを参照するための権限を付与しするためのリクエストになります。
curl -u "user:password" --request PUT --http1.1 --header 'Content-Type: application/json' "https://api.sendgrid.com/v3/api_keys/API_KEY" --data '{"name": "melma_stats", "scopes": ["subusers.create","subusers.read","subusers.stats.read","subusers.stats.monthly.read","subusers.stats.sums.read", "subusers.credits.read","subusers.monitor.read","subusers.reputations.read","email_activity.read","stats.read","stats.global.read","browsers.stats.read","devices.stats.read","geo.stats.read","mailbox_providers.stats.read","clients.desktop.stats.read","clients.phone.stats.read","clients.stats.read","clients.tablet.stats.read","clients.webmail.stats.read","categories.stats.read","user.webhooks.parse.stats.read","categories.stats.sums.read"]}'
まとめ
api_key
の取り扱いとより構造化されたメッセージの組み立てを意識してリファレンスを読めばとくに迷うことなく移行できると思います。
curlですぐ試せる例付きの日本語リファレンスが役に立ちます。いつもお世話になってます。ありがとうございます。