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â