From 8771674e4c902ba97c67936482316e9a2f8e9bf7 Mon Sep 17 00:00:00 2001 From: Sean Doyle Date: Wed, 26 Jul 2023 10:19:54 -0400 Subject: [PATCH] Support deferred Mailer deliver with `deliver_later` Re-opens [#4224][] By default, all `Devise::Models::Authenticatable`-initiated Action Mailer deliveries are transmitted immediately (within the request-response cycle). Transmitting emails and interacting with any third-party services over SMTP or HTTP risk service outages and other types of network-related failures. This commit adds support for deferring delivery to be done from an Action Job background worker queue through the [deliver_later][] method. ```ruby # config/initializers/devise.rb Devise.mailer_delivery_method = :deliver_later ``` [#4224]: https://github.com/heartcombo/devise/pull/4224 [deliver_now]: https://edgeapi.rubyonrails.org/classes/ActionMailer/MessageDelivery.html#method-i-deliver_now [deliver_later]: https://edgeapi.rubyonrails.org/classes/ActionMailer/MessageDelivery.html#method-i-deliver_later --- CHANGELOG.md | 1 + lib/devise.rb | 4 ++++ lib/devise/models/authenticatable.rb | 2 +- lib/generators/templates/devise.rb | 3 +++ test/mailers/mailer_test.rb | 16 ++++++++++++++++ 5 files changed, 25 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b2c9b55e3..b4b943da9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ * enhancements * Removed deprecations warning output for `Devise::Models::Authenticatable::BLACKLIST_FOR_SERIALIZATION` (@soartec-lab) + * Added `Devise.mailer_delivery_method` configuration to enable deferring email delivery with `:deliver_later` [#5610](https://github.com/heartcombo/devise/pull/5610) [@seanpdoyle](https://github.com/seanpdoyle) Please check [4-stable](https://github.com/heartcombo/devise/blob/4-stable/CHANGELOG.md) for previous changes. diff --git a/lib/devise.rb b/lib/devise.rb index 3847e190c..cd2cd1261 100644 --- a/lib/devise.rb +++ b/lib/devise.rb @@ -166,6 +166,10 @@ module Test mattr_accessor :send_password_change_notification @@send_password_change_notification = false + # Used to control when to deliver Action Mailer emails + mattr_accessor :mailer_delivery_method + @@mailer_delivery_method = :deliver_now + # Scoped views. Since it relies on fallbacks to render default views, it's # turned off by default. mattr_accessor :scoped_views diff --git a/lib/devise/models/authenticatable.rb b/lib/devise/models/authenticatable.rb index df964537e..d75beea28 100644 --- a/lib/devise/models/authenticatable.rb +++ b/lib/devise/models/authenticatable.rb @@ -192,7 +192,7 @@ def devise_mailer # def send_devise_notification(notification, *args) message = devise_mailer.send(notification, self, *args) - message.deliver_now + message.public_send(Devise.mailer_delivery_method) end def downcase_keys diff --git a/lib/generators/templates/devise.rb b/lib/generators/templates/devise.rb index 9e6744bd7..de55822ab 100644 --- a/lib/generators/templates/devise.rb +++ b/lib/generators/templates/devise.rb @@ -29,6 +29,9 @@ # Configure the class responsible to send e-mails. # config.mailer = 'Devise::Mailer' + # Configure when to send e-mails. + # config.mailer_delivery_method = :deliver_now + # Configure the parent class responsible to send e-mails. # config.parent_mailer = 'ActionMailer::Base' diff --git a/test/mailers/mailer_test.rb b/test/mailers/mailer_test.rb index 6f9f568e8..c27023453 100644 --- a/test/mailers/mailer_test.rb +++ b/test/mailers/mailer_test.rb @@ -43,4 +43,20 @@ def computed_reply_to assert mail.from, "from@example.com" assert mail.reply_to, "reply_to@example.com" end + + test "defaults to immediate delivery" do + create_user + + assert_not_empty ActionMailer::Base.deliveries + assert_empty ActiveJob::Base.queue_adapter.enqueued_jobs + end + + test "supports deferred delivery with Devise.mailer_delivery_method = :deliver_later" do + swap Devise, mailer_delivery_method: :deliver_later do + create_user + + assert_empty ActionMailer::Base.deliveries + assert_not_empty ActiveJob::Base.queue_adapter.enqueued_jobs + end + end end