Action Mailerをカスタマイズしてメール送信をテストしよう

皆さんメール送信のテストはどのように実施していますか?

Mailtrap.io のようなテスト用のFake SMTPサーバーを提供するようなサービスを利用していますか?実はメール送信を上手にコントロールする方法があります、そうRailsならね。

今度、1ヶ月ほど台湾へ行ってくる予定の旅するエンジニア三宅です。

今回紹介するのはメール送信のテストをするためにAction Mailerを上手にコントロールする方法を紹介します。

ActionMailer::Base.register_interceptorの紹介

ステージング環境などでメール送信のテストを行いたいという時に、バッチで実行される一斉メール送信などを確認するのって難しいですよね。

一度に大量にメールが送信されてしまいてんやわんやということにも。

そんなときはRailsに標準で用意されているActionMailer::Base.register_interceptorを使ってみましょう。

Action Mailer Basics — Ruby on Rails Guides
http://guides.rubyonrails.org/v4.2/action_mailer_basics.html#intercepting-emails

上記のRails Guideのリンク先を読んでいただければわかると思いますが ActionMailer::Base.register_interceptor を使うことでメール送信の処理をインターセプトできます。

まずは処理をインターセプトしたときに実行する処理が書かれたクラスを用意します。

# frozen_string_literal: true

class SandboxEmailInterceptor
  class << self
    def delivering_email(message)
      return if allow_to_send_email?(message)
      message.perform_deliveries = false
    end

    private

    def allow_to_send_email?(message)
      message.to.all? { |email| Settings.action_mailer.allow_to_send_emails.include?(email) }
    end
  end
end

難しい処理ではありませんが、簡単に説明するとメール送信前にdelivering_emailが呼び出されるので、そこで送信可能なメールアドレスであれば送信するという処理になっています。

上記のコードでは送信先が全て許可されたメールアドレスであることを要求していますが、用途に分けて処理を変えることも可能です。(送信可能な人だけに送信するとか)

perform_deliveriesfalseにするとメール送信がキャンセルされるようになっています。

設定にはRailsでの開発ではおなじみのrailsconfig/configを使用しています。

Action Mailer Basics — Ruby on Rails Guides
http://guides.rubyonrails.org/v4.2/action_mailer_basics.html#action-mailer-configuration

あとはinitializersにファイルを作って上記のクラスを使ってメール送信をインターセプトするように設定します。今回の場合はsandbox_email_inceptor.rbと名付けました。

# frozen_string_literal: true

ActionMailer::Base.register_interceptor(SandboxEmailInterceptor) if Settings.action_mailer.sandbox

これで Settings.action_mailer.sandbox をtrueにすることで、Settings.action_mailer.allow_to_send_emailsに設定されているメールだけにメールが送信されるようになります。

Appendix

Railsで用意された機能のように書いてありますが、実はAction Mailerでは内部でmikel/mailというgemが使用されており、メール送信をインターセプトする処理も、その中で書かれています。

詳しい処理については知りたい方は、RailsのActionMailer::Base.register_interceptorからコードを辿っていくと面白いかと思います。

それほど複雑なコードではないので、すぐに流れが追えるのではないかと思います。

内部の処理を読んでみると勉強になることもあるので、自身で読んでみることをオススメします。

最後に

駆け足でActionMailer::Base.register_interceptorについて紹介しましたが、いかがでしたでしょうか?

Railsには便利な仕組みが最初から用意されていて本当に便利ですよね。

皆さんもRails Guideを読み込んでみると、今まで知らなかったような便利な機能が見つかるかもしれません。

Railsって本当に良いもんですね。さよなら、さよなら、さよなら。

TimeCrowdに戻る