Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
Customizing ActionMailer delivery methods
# Resque job to do the true outbound sending
class DeliverEmailJob
include ProjectName::Job::Logging
@queue = :mail_queue
def self.perform(args)
message = QueuedEmail.get!(args["message_id"])"Delivering (%s) to %s" % [message.subject, message.formatted_recipient])
# This is the important bit, QueueDeliveryMailer rebuilds the email, but overrides the delivery method (see file)
# Again, using delayed_job, this could be simplified as you could just receive the original Mail::Message
QueueDeliveryMailer.original_email(message).deliver"Mail delivered to %s" % [message.formatted_recipient])
# in config/initializers/mailer.rb, add a custom delivery_method to ActionMailer
ActionMailer::Base.add_delivery_method :queued, ProjectName::QueuedDeliveryMethod
# in config/environments/production.rb (or other environment)
config.action_mailer.delivery_method = :queued # make the default delivery_method your queue
config.mail_queue_outbound_delivery_method = :smtp # define new config option that specifies how to really deliver mail (used later)
config.action_mailer.smtp_settings = { # set the settings for whatever outbound delivery method you're going to use
:address => "",
:port => 25,
:domain => "",
:user_name => "",
:password => "smtp-password"
class QueueDeliveryMailer < ActionMailer::Base
# override the delivery method with the outbound delivery method you config'd earlier
self.delivery_method = Rails.application.config.mail_queue_outbound_delivery_method
layout nil
def original_email(email)
# This is just creating the same email from the DB record that was saved for queueing
mail(:from => email.formatted_sender,
:to => email.formatted_recipient,
:reply_to => email.formatted_reply_to,
:subject => email.subject) do |format|
format.text { render :text => email.body }
module ProjectName
class QueuedDeliveryMethod
def deliver!(mail)
# we're actually tracking the mail in the DB, but you can store it anywhere ready for passing to Resque
# if you don't care about analyzing your sent email data, and you're using delayed_job, this would be simpler
message = QueuedEmail.create(
:subject => mail.subject,
:body => mail.body,
:recipient_address =>,
:recipient_name => mail[:to].display_names.first,
:sender_address => mail.from.first,
:sender_name => mail[:from].display_names.first,
:reply_to_address => mail.reply_to ? mail.reply_to.first : nil,
:reply_to_name => mail.reply_to ? mail[:reply_to].display_names.first : nil
# once it's written somewhere internal to the app, tell Resque to process the sending in the background
Resque.enqueue(DeliverEmailJob, :message_id =>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.