SendGrid
SendGridDay 23

SendGrid v2 APIからv3 APIへの移行で押さえておくポイント

More than 1 year has passed since last update.

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では下図のようにメール送信に必要な情報として宛先と埋め込みたいテキストを別々の配列として渡していました。正しく動いている時は問題ないですが、開発中であるとかバグで配列の数や位置がずれたときに意図しない相手に意図していない埋め込みテキストのメールを送信してしまいかねない構造になっています。

v2 API Mail send

一方v3 APIでは1通のメール送信に必要なデータが SendGrid::Personalization としてまとめられているため、構造的に送信先と埋め込みデータがズレるといったことが起きにくくなっています。

image

開発しているシステムの堅牢性を向上する意味でもv3 APIへ移行する意義は十分ありそうです。他にも送信時にリンクのトラッキングの有無を設定できるようになったり細やかな要求に耐えられるようになりました。

v3 APIの日本語エンコーディングの問題

メール送信の日本語処理について公式にもいくつかの不具合があるとアナウンスされています。こちらの利用環境でも、とある不具合に遭遇しました。

具体的にはSubstitutionを使ってメール本文の埋め込みテキストを置換してメール送信するとSubjectが生のUTF-8のまま送信されてしまう問題がありました。Gmailではそのまま表示されるので気が付きにくいです1

回避策としては以下のようにSubjectにも空のSubstitutionを渡すことでBASE64エンコードしてくれるようになります2

send_v3_api.rb
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ですぐ試せる例付きの日本語リファレンスが役に立ちます。いつもお世話になってます。ありがとうございます。


  1. ガラケーで確認しました 

  2. v2 APIではquoted-printableエンコードされます