ReefPointsBlog

Rails 4.0 Sneak Peek: Asynchronous ActionMailer

Brian Cardarella

My previous deep dive into the Rails 4.0 Queueing system was motivated by a patch to Rails I was working on while at RailsCamp New England this past weekend. I'm happy to say that Rails 4.0 now has an optional asynchronous ActionMailer.

The API for pushing your emails to the background is very simple. If you want to make this change application wide simply set it in your application.rb (or in any of the environment files)

1
config.action_mailer.async = true

Or if you want to only make specific mailers asynchrounous

1
2
3
class WelcomeMailer < ActionMailer::Base
  self.async = true
end

That's it! Any messages that are being delivered will be sent as a background job. In fact, the rendering is happening on the background as well.

You will need to take care that the arguments you are passing your mailers can be properly marshalled. Instead of:

1
WelcomeMailer.welcome(@user).deliver

You should do:

1
WelcomeMailer.welcome(@user.id).deliver

Then in your mailer:

1
2
3
4
5
6
class WelcomeMailer < ActionMailer::Base
  def welcome(id)
    @user = User.find(id)
    ...
  end
end

Switching it up

The default queueing system is Rails.queue, but you can override this to use any queueing system you want by overriding ActionMailer::Base#queue.

1
2
3
4
5
class WelcomeMailer < ActionMailer::Base
  def queue
    MyQueue.new
  end
end

Your custom queue should expect the jobs to respond to #run, same as Rails.queue.

Credit

Much of the original code was cribbed (with permission) from Nick Plante's resque_mailer gem.