Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
17
Help us understand the problem. What are the problem?

More than 3 years have passed since last update.

ActionMailer の送信ログをとりたい

たまたま Rails の ActionMailer について調べてみる機会がありましたので、そこに見られた Observer について書きたいと思います。

ご存知のように、メールの送信というものは失敗する可能性があります。ですので、できうるかぎりメールはユーザに届けたい!という場合は、再送の手間をかけなければいけないこともあるわけですが、そうした際に必要になってくるのは、そう、送信ログです。ActionMailer では簡単に送信ログがとれますので、今回はそれについて書いてみます。

たとえば次のようなメールアクションがあったとします。

app/mailers/foo_mailer.rb
class FooMailer < ActionMailer::Base
  def foo(recipient_email_address)
    mail(to: recipient_email_address, body: 'foo')
  end
end

このメールを送信するには、ご存知のように

FooMailer.foo('to@example.com').deliver_now

というふうにするわけですが、今回はログを取得したいので、これを実行するまえにあらかじめ ActiveSupport::Notification でサブスクライブしておきます。

ActiveSupport::Notification.subscribe("deliver.action_mailer") do |name, start, finish, id, payload|
  puts "name: #{name}"
  puts "payload: #{payload}"
end

こうしておくと、送信処理の直前に次のようなアウトプットが得られるようになります。

name: deliver.action_mailer
payload: {:mailer=>"FooMailer", :message_id=>nil, :subject=>"Foo", :to=>["to@example.com"], ...}

なお、 "deliver.action_mailer" は「送信時」(実際に送信する直前)のイベントですが、これを "process.action_mailer" にすれば「送信処理の前」(アクション、つまり今回の場合であれば FooMailer.foo 実行の直前)のイベントを購読できます。

interceptors と observers

ActiveSupport::NotificationActionMailerdeliver_mail(送信処理)や process(アクションの実行)で発火するようになっていますが、Mail 自体にも Observer を加えるしくみが用意されており、ActionMailer からは register_interceptorsregister_observers からそうした Observer を登録しておくことができます。

たとえば

class MyInterceptor
  def self.delivering_email(mail)
    puts mail.inspect
  end
end

class MyObserver
  def self.delivered_email(mail)
    puts mail.inspect
  end
end

ActionMailer::Base.register_interceptors(:my_interceptor)
ActionMailer::Base.register_observers(:my_observer)

としておけば、送信処理の直前で MyInterceptor.delivering_email を割り込ませることができ、送信後に MyObserver.delivered_email を実行させることができます。

さいごに

もちろん、 ActionMailer::Base#deliver_mail メソッドを直接上書きしても、送信処理の前に割り込みをすることはできるだろうと思います(この場合、super を呼ばなければ送信そのものをキャンセルすることもできそうです)。

しかし、こうした Observer を使えるしくみが用意されているので、もし用途に適しているようであれば、活用してみたほうがキレイな実装になるかな?と思います。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
17
Help us understand the problem. What are the problem?