Deep in Rails: ActionMailer#deliver Part VI

Posted by admin 20/12/2009 at 09h41

So now we know how Rails sends emails. What can we do with that knowledge?

All kinds of stuff.

One of my clients needed the ability to send messages through 3 different SMTP servers. They wanted it to be easy to use for their developers and allow them to change out SMTP servers for each mailer method. Now that we know how AM does itâ??s thing, we can use that knowledge to create a quick patch and solve the above problem.

Weâll create a new file in out Rails app inside lib/ and call it action_mailer_hacks.rb. Inside of the file add the following (dont worry, weâll go over each line)

module ActionMailerHacks

    module InstanceMethods
        def deliver_with_switchable_smtp!(mail = @mail)
            unless logger.nil?
                logger.info  "Switching SMTP server to: #{new_smtp.inspect}"
            end
            ActionMailer::Base.smtp_settings = new_smtp unless new_smtp.nil?
            deliver_without_switchable_smtp!(mail = @mail)
        end

    end

    def self.included(receiver)
        receiver.send :include, InstanceMethods
        receiver.class_eval do
            adv_attr_accessor :new_smtp
            alias_method_chain :deliver!, :switchable_smtp
        end
    end
end


ActionMailer::Base.send :include, ActionMailerHacks

First, in module InstanceMethods, we create a new deliver method that will switch the SMTP server from AM. We do some quick logging and then set AM::Base.smtp_settings to the new smtp server. After we do that, we call deliver_without_switchable_smtp which gets created when we do our alias_method_chaining later down the page.

When this module is included we include the InstanceMethods module into the receiver and then run class_eval so that we can create a new adv_attr_accessor called new_smtp and then call alias_method_chain to create our without method. After that we include this whole module into AM::Base and weâre done with the hack. Add require "action_mailer_hacks.rb" to your environment.rb file and weâre ready for the mailer.

Now we move on to MessageMailer and actually use the hack.

class MessageMailer < ActionMailer::Base
  def contact_form(msg_from, message)
    subject    'Im contacting you'
    recipients "someemail@somedomain.com"
        new_smtp   :address => 'mail.someplace.com', :port => 25, :domain => 'someplace.com', :authentication => :login, :user_name => 'xxxxdddd', :password => 'secret'
    from       msg_from
    sent_on    Time.now
    body       :message => message
  end
end

All we do is call new_smtp with our new server address and then this method gets delivered through that SMTP server. Thatâ??s it. Simple and clean, exactly how I like it.

Well, that was fun. Next time, weâll look through something a little shorter, maybe migrations. Until then, have fun and keep codinâ

This entry was posted on 20/12/2009 at 09h41 and Posted in . You can follow any response to this entry through the Atom feed. You can leave a comment .

Tags , , , ,


Comments

Leave a comment