Railsでsendgridを使ってメールを一斉送信したい

こんにちは!kossyです!



さて、今回はRailsでメール配信サービスとしてsendgridを使っている場合に、
メールを一斉送信する方法について、ブログに残してみたいと思います。




環境
Ruby 2.5.1
Rails 5.2.3
MacOS Mojave




なお、sendgridでメール送信を行う設定周りについては説明を割愛します。
configには以下の記事が参考になると思います。
https://sendgrid.kke.co.jp/docs/Integrate/Frameworks/rubyonrails.html



X-SMTPAPIを使う!

sendgridにはメール送信APIとして、SMTP-APIとWeb-APIがあるのですが、
SMTP-APIの機能に複数の宛先を選択する機能が用意されています。

今回はこのSMTP-API(別名X-SMTPAPI)の「複数の宛先を選択する機能」を使って、一斉送信をする例を紹介します。


例としてApplicationMailerクラスを継承したUserMailerクラスが定義してあるとします。

class UserMailer < ApplicationMailer

  def send_announcement_mail(subject, content, emails)
    @content = content
    xsmtp_api_params = { to: emails }
    headers['X-SMTPAPI'] = JSON.generate(xsmtp_api_params)
    mail(to: emails, subject: subject)
  end
end


headers['X-SMTPAPI']にjsonを格納する事で、簡単に一斉送信が可能になります。

send_announcement_mailメソッドの引数には、emailsが格納された配列を渡します。

呼び出し元のコードはこんな感じ。

class AnnouncementsController < ApplicationController
  def create
    @announcement = Announcement.new(announcement_params)
    if @announcement.save
      UserMailer.send_announcement_email(@announcement.subject, @announcement.content, User.all.pluck(:email)).deliver_later
    else
      # 例外処理
    end
  end
end

@announcementオブジェクトはattrとしてsubjectとcontentを持っていて、@announcementがDBに保存されたあと、
send_announcement_emailを呼び出し、subjectとcontentとUser全員のemailの配列をpluckメソッドを使って取り出して引数として渡しています。



to: emails とすると、宛先が見えてしまうのでは?と懸念された方がいるかもしれません。
が、公式リファレンスにその辺りのことがきちんと書かれていました。

このリクエストはSendGridで分解され、各宛先にはToヘッダに個別に宛先指定(他の人の宛先が見えることはありません)されたメールが届きます。

引用: https://sendgrid.kke.co.jp/blog/?p=4232


このように、sendgridのX-SMTPAPIを使えば、簡単にメールの一斉配信機能を実装することができます。
X-SMTPAPIには他にも機能があるので、興味のある方は、

https://qiita.com/wawoon/items/6de229ca5e891c00452b
https://sendgrid.kke.co.jp/docs/API_Reference/SMTP_API/building_an_smtp_email.html

上記の記事を読んでみてください。