Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

switch mail delivery method in rails during runtime

I'm trying to setup a rails application so that I can choose between different mail delivery methods depending on whether some condition is true or not.

So, given two delivery methods:

ActionMailer::Base.add_delivery_method :foo
ActionMailer::Base.add_delivery_method :bar

I thought I'd be able to just create an email interceptor to do something like this:

class DeliveryMethodChooser
  def self.delivering_email(message)
    if some_condition
      # code to use mail delivery method foo
    else
      # code to use mail delivery method bar
    end
  end
end

The problem though, is that I'm not sure how to actually set change what mail delivery method is used for a given message. Any ideas? Is it even possible to dynamically choose what delivery_method to use?

like image 750
Frost Avatar asked Jul 04 '11 13:07

Frost


4 Answers

You can create a separate ActionMailer subclass and change the delivery_method + smtp_settings like this:

class BulkMailer < ActionMailer::Base  
  self.delivery_method = Rails.env.production? ? :smtp : :test
  self.smtp_settings = {
    address:   ENV['OTHER_SMTP_SERVER'],
    port:      ENV['OTHER_SMTP_PORT'],
    user_name: ENV['OTHER_SMTP_LOGIN'],
    password:  ENV['OTHER_SMTP_PASSWORD']
  }

  # Emails below will use the delivery_method and smtp_settings defined above instead of the defaults in production.rb

  def some_email user_id
    @user = User.find(user_id)
    mail to: @user.email, subject: "Hello #{@user.name}"
  end
end
like image 77
Brian Armstrong Avatar answered Nov 16 '22 02:11

Brian Armstrong


So, it turns out that you can actually pass a Proc as a default parameter to ActionMailer.

It's therefore fully possible to do this:

class SomeMailer < ActiveMailer::Base
  default :delivery_method => Proc.new { some_condition ? :foo : :bar }
end

I'm not sure I really sure I like this solution, but it works for the time being and it will only be for a relatively short amount of time.

like image 20
Frost Avatar answered Nov 16 '22 01:11

Frost


You can pass a :delivery_method option to the mail method as well:

def notification
  mail(:from => '[email protected]',           
       :to => '[email protected]', 
       :subject => 'Subject',
       :delivery_method => some_condition ? :foo : :bar)
end
like image 28
jankubr Avatar answered Nov 16 '22 02:11

jankubr


Note that you can also open up the application's configuration to dynamically change the delivery method application-wide:

SomeRailsApplication::Application.configure do
  config.action_mailer.delivery_method = :file
end

This can be useful in db/seeds.rb if you send account confirmation emails upon account creation, for example.

like image 29
Jamil Elie Bou Kheir Avatar answered Nov 16 '22 03:11

Jamil Elie Bou Kheir