SendGridのv3 Mail Send APIのRuby Clientを書いた

年末で少し時間があったので、書こう書こうと思っていたSendGridのv3 Mail Sendを書きました。

V3 Mail Send API Overview - SendGrid Documentation | SendGrid

github.com

READMEのUsageを見ればわかるとおり、ほぼAPIに即した薄いクライアントです。

とりあえず、現状で公式クライアントは利用しにくいので、自作した感じです。 非公式とはいっても公式がスキーマを公開しているので、rakeタスクで公式のスキーマを取得して、メール送信ポストリクエストのボディーのバリデーションをJSON Schemaで行うようにしています。

require 'kani_laser'

client = KaniLaser::Client.new(api_key: 'ZAPZAPZAP')

# see https://sendgrid.com/docs/API_Reference/Web_API_v3/Mail/index.html
client.send_mail(
  personalizations: [
    {
      to: [
        {
          email: 'john@example.com'
        }
      ],
      subject: 'Hello, World!'
    }
  ],
  from: {
    email: 'from_address@example.com'
  },
  content: [
    {
      type: 'text/plain',
      value: 'Hello, World!'
    }
  ]
)

で、公式クライアント

SendGrid公式のRubyクライアントは、あまりインターフェースがよいとは思えなくて

require 'sendgrid-ruby'
include SendGrid

from = SendGrid::Email.new(email: 'test@example.com')
to = SendGrid::Email.new(email: 'test@example.com')
subject = 'Sending with Twilio SendGrid is Fun'
content = SendGrid::Content.new(type: 'text/plain', value: 'and easy to do anywhere, even with Ruby')
mail = SendGrid::Mail.new(from, subject, to, content)

sg = SendGrid::API.new(api_key: ENV['SENDGRID_API_KEY'])
response = sg.client.mail._('send').post(request_body: mail.to_json)
puts response.status_code
puts response.body
puts response.parsed_body
puts response.headers
  • いくつかクラスを利用しているけれどすべてJSON生成のヘルパーで必須ではなく冗長
  • 送信用のメソッドが#_で、ちょっとわかりにくすぎると思う…(メタプログラミングを避けた? あー、sendメソッドが使いにくかったせいか)
  • method_missingを使ったかなり薄いラッパーでメソッドやパラメータのチェックが弱い。ヘルパークラスも空白などを除去しているだけでチェックの役に立っていない
  • 気になる書き方がいくつか(固定文字列のJSONをわざわざパースしてHashにしている・必須引数に空白のデフォルト値を設定している)

といった感じで、うーん…とクビをかしげる状態になっています。 v1からv2への変更で大幅に修正が入っていて、なぜこのようなわかりにくいインターフェースになったのか、ぜんぜん経緯を理解できていないです。v3 APIへの対応リソースが足りなかったんだろうか?

一方でOpen API specificationも公開していて、今回私の書いたKaniLaserはそこからschemaをとってきてリクエストパラメーターのJSONJSON Schemaでパリデーションするようにしています。

リクエストパラメーターのバリデーションができれば、インターフェースはシンプルになりそうですが、公式クライアントはなんか頑張っている?せいで煩雑です。なぜ

API定義はしっかりしているように見えるので、そこからどうとでもクライアントは生成できると思うのですが、なんでこんな状況になっているのかよくわからない…

わからない。全くわからない。


公式がちょちょいとやれば、メタ情報から各種言語のクライアントを自動生成できそうだけれど、なぜやってないんだろう? oas.jsonからクライアントを自動生成できそうだけど。 やっぱりリソースの問題かなぁ、Ruby優先度低いのかなぁ…うーん…

蛇足

https://sendgrid.api-docs.io/ を参照すればちょちょいのちょい…と思っていたんですが、oas.jsondefinitions、足りなくないですかね。email_objectとか。

最終的に https://github.com/sendgrid/sendgrid-oai/ のマスターをスキーマのソースにするようにしたんだけど、これ、正しいのかなぁ

カニレーザー

dic.pixiv.net