Asynchronous email deliveries using Resque and resque_action_mailer_backend

The Rails 3 Way

The Rails 3 Way

Check the GitHub repo here and a sample application using it here.

If you have ever sent emails using ActionMailer during a user request you probably noticed that if the email sending fails or takes too long your user might not be really happy with the speed of your application. Making the email sending process an asynchronous one is usually the simplest solution for this problem and there are plenty of tools to do that like ar_mailer, that stores emails in your database and then uses a specific daemon to send them.

ar_mailer and other solutions are quite enough for most of your problems but what if you’re already using Resque to run your asynchronous jobs? Why bother using yet another daemon to do the email sending jobs with all the hassle of managing if you can use your current Resque setup to do it?

With this in mind I sat a bit and wrote this simple gem that lets you do exactly that, send your emails asynchronously using a Resque worker and without changing a single line of your email sending code. Following the same philosophy of ar_mailer, the resque_action_mailer_backend doesn’t require you to call fancy methods on your mailers, you just keep them as they are now and instead of changing them you just change the delivery method to :resque, like this (in a environment file, like “development.rb”):

config.action_mailer.delivery_method = :resque

The gem uses your ActionMailer::Base.smtp_settings configuration to deliver the emails, so you don’t have to change anything in there, just be sure that the SMTP credentials are correct so the worker can deliver emails without issues. The default queue name is “:headbanger_resque_mailer”, but you can change it to whatever you’d like to with this code:

Headbanger::ResqueMailer.queue = :your_email_queue

This single line of code changed will now make all your emails be queued to Resque and they’ll be sent as soon as a worker is available for it. Now you only have to tell your rails application to load the resque_action_mailer_backend gem (in your environment.rb):

config.gem "resque_action_mailer_backend"

You can check a some hints on using this setup at this sample project.

And you’re ready to start sending emails asynchronously using your resque workers!

Enjoy!

10 Responses to “Asynchronous email deliveries using Resque and resque_action_mailer_backend”

  1. Tweets that mention Asynchronous email deliveries using Resque and resque_action_mailer_backend « Codeshooter’s Weblog -- Topsy.com Says:

    […] This post was mentioned on Twitter by cmilfont and Maurício Linhares, Ruby Reflector. Ruby Reflector said: Top Ruby Article: Asynchronous email deliveries using Resque and resque_action_mailer_backend: http://bit.ly/9LjNvn […]

  2. Millisami Says:

    How to use this with Rails3? Coz I noticed that the example is based on Rails2.

    • Maurício Linhares Says:

      Hi Millisami,

      Unfortunately I’m not running Rails 3 in any of my projects right now and I did not test it in there so I can’t say for sure if it runs or not. If someone is willing to give it a try and patch it if it doesn’t work I’d be greatly thankful :)

  3. Gabe da Silveira Says:

    Is there some advantage to this as compared to http://github.com/zapnap/resque_mailer?

    • Maurício Linhares Says:

      The main difference is that the resque_mailer gem requires you to change the way you send emails, doesn’t allow you to pass non-JSONable objects to your deliver_* methods and generates the emails at the Resque worker, while the resque_action_mailer_backend doesn’t require you to change anything in your mailers, just change the mailing backend.

      • Nick Plante Says:

        resque_mailer shouldn’t require you to change anything in your mailers. Other than including a module in them. But different approaches are cool too :).

        Not sure what you mean about non-JSONable objects. Passing objects that can’t be serialized (like those that are AR-backed) seems like a bad idea in general? Perhaps I just don’t understand the use case.

        • Maurício Linhares Says:

          Hi Nick,

          When I tried resque_mailer the main issue was this one -> http://github.com/zapnap/resque_mailer/blob/master/lib/resque_mailer/rails2.rb#L14

          You send in the objets passed to deliver directly to Resque, which requires them to be JSON-able objects and in all systems I’ve worked on it’s quite common to do something like that:

          PostMailer.deliver_post_created( @post )

          And I couldn’t do it with your gem, I would have to pass the @post.id value and then load the post at the mailer, which wasn’t an option as we have lots of mailers around and I would not need something like that if I was going to use ar_mailer, so I wrote my own version of “ar_mailer” but backed by resque :)

          • Nick Plante Says:

            Fair enough, there’s definitely room for different solutions! Was just curious what didn’t work for you.

            Fwiw, RM is implemented that way on purpose. Personally I prefer to pass objects by ID whenever I know they’re going to be queued and handled by some other process, because the database connection in the object won’t persist. It’s not hard to hide that level of detail and do another lookup automatically on an AR-backed object, but it seemed unnecessary to me and would likely increase reader confusion rather than decrease it.

            In any case, I’m not familiar with ar_mailer but glad you found a solution that works for you. Cheers!

  4. Aarthi Says:

    Hi can you please help me out…. i have done everything as specified in http://github.com/mauricio/resque_action_mailer_backend_example . i have installed Resque gem….. but when i say rake resque:work QUEUE=* VERBOSE=1 in my terminal it gives me the following error.. *** Starting worker aarthi-desktop:2330:critical,high
    rake aborted!
    Connection refused – Unable to connect to Redis on localhost:6379

    Please help me out..


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: