blog.waterlow.work

Ruby, Rails, js, etc...

sendgrid-rubyを使ったSendGridでのメール送信

はじめに

この記事は「Sansan Advent Calendar 2016」7日目の記事です。
昨日はerikoobeさんによる「エンジニア未経験者が Ruby を学んでみた件」でした。
特に「2. 未経験者から見た、エンジニアの世界」は共感できたのと同時に、やる気のある人へのサポートはやっぱり大切だなと感じました。

この記事の概要

SendGridが公開しているgemを使って、webapi経由でメール送信する方法をざっくり紹介する。

背景

SendGridとは?

SendGridクラウドベースのメール配信サービスです。smtpサーバを自前で運用することなくメール送信を行うことが出来ます。
この点ではAmazon Simple Email ServiceやMailChimpも同等の機能を持っています。
また、配信だけでなくバウンス後の処理や開封、クリック数取得等のさまざまことをwebapi経由で行えることも特徴の一つです。

なぜこの記事を書いたか

最近までたくさんメールを送る仕事をしていたのですが、smtp→webapiにかえることで配信時間をかなり圧縮出来たので、ぜひ布教していきたいと思いまとめてみました。

前提

SendGridのアカウント取得、apikeyの発行ができている。

サンプル

以下サンプルコードです。(gemのインストールは適宜おこなってください。)

github.com

require 'sendgrid-ruby'
require 'dotenv'
Dotenv.load
API_KEY = ENV['API_KEY']
USERS = [
  { email: 'to1@example.com', name: 'to1', fullname: 'to_user1' },
  { email: 'to2@example.com', name: 'to2', fullname: 'to_user2' }
]

mail          = SendGrid::Mail.new
mail.from     = SendGrid::Email.new(email: 'from@example.com')
mail.contents = SendGrid::Content.new(type: 'text/plain', value: "%name%さん\nあなたのフルネームは%fullname%です")

USERS.each do |u|
  email, name, fullname = u.values_at(:email, :name, :fullname)

  sp = SendGrid::Personalization.new
  sp.to = SendGrid::Email.new(email: email)
  sp.subject = "#{name}さんこんにちは"
  sp.substitutions = SendGrid::Substitution.new(key: '%name%',     value: name)
  sp.substitutions = SendGrid::Substitution.new(key: '%fullname%', value: fullname)
  mail.personalizations = sp
end

sg = SendGrid::API.new(api_key: API_KEY)
response = sg.client.mail._('send').post(request_body: mail.to_json)

登場するclass

SendGrid::Mail

SendGrid::Mail#to_jsonを呼ぶことで、現在持っているインスタンス変数からHash形式でrequest_bodyを作ります。
SendGrid::Mail#personalizations=は、内部ではArray#pushを使っている。インスタンス変数@personalizationsを書き換えるわけではない。

SendGrid::Email

送信先、受信先のメールアドレスや表示名を扱うのに用いる。

SendGrid::Content

メールの本文、type(text, html)を指定するためのクラス。

SendGrid::Personalization

送信先、件名、substitutions等を扱うクラス。どんな項目が指定できるできるかは以下を参考に。
personalizations

気になる点

インタフェースがいけてない

SendGrid::Mail#personalizations=とかSendGrid::Mail#to_jsonとか、パット見と違う挙動なものが多いのでは??

ソースが読みにくい

gemのプロダクトコードはsendgrid/helpers/mail/mail.rbという1つのファイルに集約されている。

その他

本家のreadmeにはsendgrid/helpers/mail/mail.rbを使わない方法も記載されています。
without-mail-helper-class

参考までに上に書いたサンプルコードのhelper使わない版も書いてみました。

mail_info = {
  from: { email: 'from@example.com' },
  content: [
    { type: 'text/plain', value: "%name%さん\nあなたのフルネームは%fullname%です" }
  ]
}

mail_info[:personalizations] = USERS.map do |u|
  email, name, fullname = u.values_at(:email, :name, :fullname)

  { to:            [{ email: email }],
    subject:       "#{name}さんこんにちは",
    substitutions: { '%name%': name, '%fullname%': fullname } }
end

sg = SendGrid::API.new(api_key: API_KEY)
response = sg.client.mail._('send').post(request_body: mail_info)

SendGrid::APIもだいたい40行くらいのコードなので、sendgrid-rubyを使わない方法もありかなとは思いまいた。 その際はsendgrid-rubyが内部的に使っているruby_http_clientを使うもよし、メールを送信するだけなら全て自分で書いてしまってもいいかなと思います。(webapiにリクエスト送るだけだし。)

まとめ

以上、SendGridが公開しているgemを使って、webapi経由でメール送信する方法でした。 apiクライアントの設計に興味が湧いてきたので、他のgemのソースも読んでみたいと思います!

さいごに

明日はTakeruTakahashiさんの記事です!引き続き「Sansan Advent Calendar 2016」をお楽しみに!