業務でSendgridのSMTPを用いてメールをユーザー宛に送信していたが、送信されるメール毎にカテゴリーを付与し、コンバージョン率を調査したいとの社内マーケからの要望を受けた。
そのため、SMTPでカテゴリーを付与しようとしたが、カテゴリー設定がSMTPではできないことが判明し、Web APIにて実装しようと思ったところ、意外と参考文献が少なかったので備忘録も兼ねて記事とした🚬
ちなむと今回は、Web APIを用いてメール送信するところが難所なのではなく、カテゴリー付与するところで詰まりました。
また、今回APIの呼び出しに使用したのはsendgrid-ruby
というgem
である。
SendgridのAPI取得
APIの取得に関しては公式ドキュメントを参照して取得して欲しい。
メール送信など単純な使用目的で取得する場合はfull access
を選択してAPI生成すれば問題なし✌️
コード実装
ここからの実装の流れは以下2つの記事を参照した。
最終的なコード
RailsはデフォでAction Mailer(smtp)を使用するので、新規でdelivery methodを追加してあげる。
今回実装したファイルは以下。
# config/initializers/sendgrid.rb
ActionMailer::Base.add_delivery_method :sendgrid, Mail::SendGrid,
api_key: Settings.sendgrid_api #settings.local.ymlの中にあるAPIキーを呼び出す。
# app/mailers/application_mailer.rb
class ApplicationMailer < ActionMailer::Base
def set_sendgrid_settings(category)
ActionMailer::Base.delivery_method = :sendgrid
headers['category'] = category
end
end
# lib/mail/send_grid.rb
class Mail::SendGrid
def initialize(settings)
@settings = settings
end
def deliver!(mail)
sg_mail = set_mail_information(mail)
add_content_and_category(sg_mail, mail)
sg = SendGrid::API.new(api_key: @settings[:api_key])
sg.client.mail._('send').post(request_body: sg_mail.to_json)
end
private
def set_mail_information(mail)
from = SendGrid::Email.new(email: mail.from.first)
to = SendGrid::Email.new(email: mail.to.first)
subject = mail.subject
content = SendGrid::Content.new(type: 'text/plain', value: mail.body.parts[0].body.raw_source)
SendGrid::Mail.new(from, subject, to, content)
end
def add_content_and_category(sg_mail, mail)
sg_mail.add_content(SendGrid::Content.new(type: 'text/html', value: mail.body.parts[1].body.raw_source))
sg_mail.add_category(SendGrid::Category.new(name: mail[:category].value))
end
end
メールが送られるまでの流れ
-
app/mailers/application_mailer.rb
で定義したメソッドset_sendgrid_settings('カテゴリー名')
をmailerファイルの中で呼び出す。
例 )
以下test_mailer.rbのアクション内で定義したset_sendgrid_settings('カテゴリー名')
を呼び出すことで、「test_mailerメソッドのdelivery_methodはsendgridのWeb APIを通して送信しますよ。」と指示する。
※引数でカテゴリー名を渡すことで、sendgridへカテゴリー名も付与することができる。
# app/mailers/test_mailer.rb
class TestMailer < ApplicationMailer
def test_mail
set_sendgrid_settings('This is test category')
mail(from: 'from@example.com', to: 'to@example.com', subject: 'テストメール')
end
end
# app/views/test_mailer/test_mail.text.erb
SendGrid送信テスト
-
set_sendgrid_settings('カテゴリー名')
によって、lib/mail/send_grid.rb
で定義したdeliver!
メソッドが使用できる。
以下のinitialize
によって、config/initializers/sendgrid.rb
が呼び出されAPIを使用することができ、@settings
にAPIキーが代入される。
# lib/mail/send_grid.rb
class Mail::SendGrid
def initialize(settings)
@settings = settings
end
~
- mailerから渡ってきた
mail
変数をsendgrid-ruby
の所定のフォーマットに則って代入する。
以下のset_mail_information(mail)
プライベートメソッドにてgemのフォーマットに則って代入する。
※SendGrid::Email.new()
はgem特有のもの。詳しくは公式まで。
# lib/mail/send_grid.rb
class Mail::SendGrid
~
private
def set_mail_information(mail)
from = SendGrid::Email.new(email: mail.from.first)
to = SendGrid::Email.new(email: mail.to.first)
subject = mail.subject
content = SendGrid::Content.new(type: 'text/plain', value: mail.body.parts[0].body.raw_source)
SendGrid::Mail.new(from, subject, to, content)
end
~
以上の流れでメールは送信できる。
詰まった問題点
そもそも業務でsendgridを使用しているので、text/plain
形式だけではなく、html
形式のメールも送信するマルチパートメールを採用している。(というかどこの企業もそうだと思うが…)
上記までだと、text/plain
形式のメールだけしか送れず、なんならhtml.erbファイルもある場合はエラーが出て送信できない。
あと、カテゴリーに関してもaction mailerのMail::Messageに含まれる引数しか渡せないため、独自に変数を渡すことは不可能だったので、別の方法で実装するしかなかった。
- マルチパートメールどうやって送るの?
- カテゴリー名どうやって付与するねん…
解決方法
結論、gemの特性なのか知らないが、先にtext/plain
形式のメールを指定しなければならないらしい。なので、html
形式はadd_category
というgemのメソッドを使用して追加することに成功した。
カテゴリーは、mailerのactionごとに指定したい場合には、header[:category]
として含める必要があることがわかった。
※カテゴリー名はUS-ASCII文字セットのみ対応(日本語不可)ということにも注意。
該当箇所
html形式のメールはmail.body.parts
の2番目に含まれているので、mail.body.parts[1]
で指定してあげる。(1番目に格納されているのはtext/plain
形式。)
# lib/mail/send_grid.rb
class Mail::SendGrid
~
def add_content_and_category(sg_mail, mail)
sg_mail.add_content(SendGrid::Content.new(type: 'text/html', value: mail.body.parts[1].body.raw_source))
sg_mail.add_category(SendGrid::Category.new(name: mail[:category].value))
end
end
以上でmailerのアクション毎にカテゴリー名を付与した上で、Web APIを経由しメール送信することが可能になった。
Sengridのダッシュボード上でもカテゴリー分け毎のコンバージョン率も確認できて、Webマーケからも感謝されました。めでたしめでたし。