7

Is there a simple way of telling Devise to send all email via delayed_job?

jigfox
  • 18,057
  • 3
  • 60
  • 73
Neil Middleton
  • 22,105
  • 18
  • 80
  • 134

4 Answers4

12

Alternatively, instead of using the Delayed::Mailer gem, you can quite easily implement and use your own ActionMailer "delivery method", one that...

  1. intercepts mail delivery from ActionMailer
  2. stores the email in a table (optional)
  3. creates a Delayed::Job that references the stored email
  4. delivers the stored email when the delayed job is executed

Do something along the lines of:

# in config/application.rb
ActionMailer::Base.add_delivery_method :queued, Mail::QueuedDelivery

# in config/environment.rb (or one of the config/environments/*.rb files)
config.action_mailer.delivery_method = :queued # ie. Mail::QueuedDelivery

# in lib/mail/queued_delivery.rb
module Mail
  class QueuedDelivery

    def initialize(values = {})
      # (optional)
    end

    def deliver!(mail)
      email = Email.create!(:delivery_handler => mail.delivery_handler.name, :message => mail.to_s)
      Delayed::Job.enqueue Jobs::Email::DeliverEmail.new(email.id)
    end

  end # class QueueDelivery
end # module Mail

The Delayed::Job you need to implement would then...

  1. retrieve the stored email from the database -- email = ::Email.find_by_id(email_id)
  2. deliver the email via the mail gem -- Mail::Message.new(email.message).deliver

That's it... hope this help!

pvandenberk
  • 4,649
  • 2
  • 26
  • 14
3

I have no idea what Devise is but I guess it is third-party gem you don't want to modify. Try delayed_job_mailer. You can extend Devise mailers by monkey patching them to use delayed_job.

class SomeExistingMailer
  include Delayed::Mailer
end

or if you want to send all app emails via delayed job by default:

# config/initializers/delayed_mailer.rb
class ActionMailer::Base
  include Delayed::Mailer
end
gertas
  • 16,869
  • 1
  • 76
  • 58
  • I tried your 2nd suggestion which would be amazing if it worked, but got an error "/Users/bhellman/Sites/cline/config/initializers/delayed_mailer.rb:3: uninitialized constant Delayed::Mailer (NameError)" – AnApprentice Nov 08 '10 at 16:52
  • This seems to me that Delayed mailer gem wasn't loaded. Did you specified it in Gemfile, eventually require it in environment.rb – gertas Nov 09 '10 at 09:56
2

I found that none of the above worked for me. I'm using Devise 2.0.4 and Rails 3.2.2 with delayed_job_active_record 0.3.2

The way devise actually talks about doing something like this in the comments in the code is to override the methods in the User class. Thus, I solved it like so, and it works perfectly:

app/models/User.rb

def send_on_create_confirmation_instructions
  Devise::Mailer.delay.confirmation_instructions(self)
end
def send_reset_password_instructions
  Devise::Mailer.delay.reset_password_instructions(self)
end
def send_unlock_instructions
  Devise::Mailer.delay.unlock_instructions(self)
end
hrdwdmrbl
  • 4,814
  • 2
  • 32
  • 41
0

There is now the devise-async project which achieves exactly this:

John Bachir
  • 22,495
  • 29
  • 154
  • 227