abstract all of the ActionMailer delivery methods into their own classes. thereby the following are equivalent
ActionMailer::Base.delivery_method = :smtp ActionMailer::Base.delivery_method = ActionMailer::DeliveryMethod::Smtp we could equally set our own custom object as long as it provides the instance method :perform_delivery(mail) eg. class MySmsDeliveryMethod def perform_delivery(mail) Sms.send(mail['to'], mail['body']) end end MySmsMailer.delivery_method = MySmsDeliveryMethod.new Signed-off-by: José Valim <jose.valim@gmail.com>
This commit is contained in:
parent
3f56038612
commit
f4f76772fb
|
@ -44,6 +44,7 @@ Rake::RDocTask.new { |rdoc|
|
|||
rdoc.rdoc_files.include('README', 'CHANGELOG')
|
||||
rdoc.rdoc_files.include('lib/action_mailer.rb')
|
||||
rdoc.rdoc_files.include('lib/action_mailer/*.rb')
|
||||
rdoc.rdoc_files.include('lib/action_mailer/delivery_method/*.rb')
|
||||
}
|
||||
|
||||
spec = eval(File.read('actionmailer.gemspec'))
|
||||
|
|
|
@ -33,6 +33,7 @@ module ActionMailer
|
|||
|
||||
autoload :AdvAttrAccessor, 'action_mailer/adv_attr_accessor'
|
||||
autoload :Base, 'action_mailer/base'
|
||||
autoload :DeliveryMethod, 'action_mailer/delivery_method'
|
||||
autoload :Helpers, 'action_mailer/helpers'
|
||||
autoload :Part, 'action_mailer/part'
|
||||
autoload :PartContainer, 'action_mailer/part_container'
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
require 'tmpdir'
|
||||
|
||||
require "active_support/core_ext/class"
|
||||
# Use the old layouts until actionmailer gets refactored
|
||||
require "action_controller/legacy/layout"
|
||||
|
@ -232,7 +230,7 @@ module ActionMailer #:nodoc:
|
|||
# * <tt>raise_delivery_errors</tt> - Whether or not errors should be raised if the email fails to be delivered.
|
||||
#
|
||||
# * <tt>delivery_method</tt> - Defines a delivery method. Possible values are <tt>:smtp</tt> (default), <tt>:sendmail</tt>, <tt>:test</tt>,
|
||||
# and <tt>:file</tt>.
|
||||
# and <tt>:file</tt>. Or you may provide a custom delivery method object eg. MyOwnDeliveryMethodClass.new
|
||||
#
|
||||
# * <tt>perform_deliveries</tt> - Determines whether <tt>deliver_*</tt> methods are actually carried out. By default they are,
|
||||
# but this can be turned off to help functional testing.
|
||||
|
@ -270,35 +268,21 @@ module ActionMailer #:nodoc:
|
|||
|
||||
cattr_accessor :logger
|
||||
|
||||
@@smtp_settings = {
|
||||
:address => "localhost",
|
||||
:port => 25,
|
||||
:domain => 'localhost.localdomain',
|
||||
:user_name => nil,
|
||||
:password => nil,
|
||||
:authentication => nil,
|
||||
:enable_starttls_auto => true,
|
||||
}
|
||||
cattr_accessor :smtp_settings
|
||||
class << self
|
||||
delegate :settings, :settings=, :to => ActionMailer::DeliveryMethod::File, :prefix => :file
|
||||
delegate :settings, :settings=, :to => ActionMailer::DeliveryMethod::Sendmail, :prefix => :sendmail
|
||||
delegate :settings, :settings=, :to => ActionMailer::DeliveryMethod::Smtp, :prefix => :smtp
|
||||
|
||||
@@sendmail_settings = {
|
||||
:location => '/usr/sbin/sendmail',
|
||||
:arguments => '-i -t'
|
||||
}
|
||||
cattr_accessor :sendmail_settings
|
||||
|
||||
@@file_settings = {
|
||||
:location => defined?(Rails) ? "#{Rails.root}/tmp/mails" : "#{Dir.tmpdir}/mails"
|
||||
}
|
||||
|
||||
cattr_accessor :file_settings
|
||||
def delivery_method=(method_name)
|
||||
@delivery_method = ActionMailer::DeliveryMethod.lookup_method(method_name)
|
||||
end
|
||||
end
|
||||
self.delivery_method = :smtp
|
||||
superclass_delegating_reader :delivery_method
|
||||
|
||||
@@raise_delivery_errors = true
|
||||
cattr_accessor :raise_delivery_errors
|
||||
|
||||
superclass_delegating_accessor :delivery_method
|
||||
self.delivery_method = :smtp
|
||||
|
||||
@@perform_deliveries = true
|
||||
cattr_accessor :perform_deliveries
|
||||
|
||||
|
@ -552,7 +536,7 @@ module ActionMailer #:nodoc:
|
|||
|
||||
ActiveSupport::Notifications.instrument(:deliver_mail, :mail => @mail) do
|
||||
begin
|
||||
__send__("perform_delivery_#{delivery_method}", mail) if perform_deliveries
|
||||
self.delivery_method.perform_delivery(mail) if perform_deliveries
|
||||
rescue Exception => e # Net::SMTP errors or sendmail pipe errors
|
||||
raise e if raise_delivery_errors
|
||||
end
|
||||
|
@ -720,39 +704,6 @@ module ActionMailer #:nodoc:
|
|||
@mail = m
|
||||
end
|
||||
|
||||
def perform_delivery_smtp(mail)
|
||||
destinations = mail.destinations
|
||||
mail.ready_to_send
|
||||
sender = (mail['return-path'] && mail['return-path'].spec) || mail['from']
|
||||
|
||||
smtp = Net::SMTP.new(smtp_settings[:address], smtp_settings[:port])
|
||||
smtp.enable_starttls_auto if smtp_settings[:enable_starttls_auto] && smtp.respond_to?(:enable_starttls_auto)
|
||||
smtp.start(smtp_settings[:domain], smtp_settings[:user_name], smtp_settings[:password],
|
||||
smtp_settings[:authentication]) do |smtp|
|
||||
smtp.sendmail(mail.encoded, sender, destinations)
|
||||
end
|
||||
end
|
||||
|
||||
def perform_delivery_sendmail(mail)
|
||||
sendmail_args = sendmail_settings[:arguments]
|
||||
sendmail_args += " -f \"#{mail['return-path']}\"" if mail['return-path']
|
||||
IO.popen("#{sendmail_settings[:location]} #{sendmail_args}","w+") do |sm|
|
||||
sm.print(mail.encoded.gsub(/\r/, ''))
|
||||
sm.flush
|
||||
end
|
||||
end
|
||||
|
||||
def perform_delivery_test(mail)
|
||||
deliveries << mail
|
||||
end
|
||||
|
||||
def perform_delivery_file(mail)
|
||||
FileUtils.mkdir_p file_settings[:location]
|
||||
|
||||
(mail.to + mail.cc + mail.bcc).uniq.each do |to|
|
||||
File.open(File.join(file_settings[:location], to), 'a') { |f| f.write(mail) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Base.class_eval do
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
require "active_support/core_ext/class"
|
||||
module ActionMailer
|
||||
module DeliveryMethod
|
||||
|
||||
autoload :File, 'action_mailer/delivery_method/file'
|
||||
autoload :Sendmail, 'action_mailer/delivery_method/sendmail'
|
||||
autoload :Smtp, 'action_mailer/delivery_method/smtp'
|
||||
autoload :Test, 'action_mailer/delivery_method/test'
|
||||
|
||||
# Creates a new DeliveryMethod object according to the given options.
|
||||
#
|
||||
# If no arguments are passed to this method, then a new
|
||||
# ActionMailer::DeliveryMethod::Stmp object will be returned.
|
||||
#
|
||||
# If you pass a Symbol as the first argument, then a corresponding
|
||||
# delivery method class under the ActionMailer::DeliveryMethod namespace
|
||||
# will be created.
|
||||
# For example:
|
||||
#
|
||||
# ActionMailer::DeliveryMethod.lookup_method(:sendmail)
|
||||
# # => returns a new ActionMailer::DeliveryMethod::Sendmail object
|
||||
#
|
||||
# If the first argument is not a Symbol, then it will simply be returned:
|
||||
#
|
||||
# ActionMailer::DeliveryMethod.lookup_method(MyOwnDeliveryMethod.new)
|
||||
# # => returns MyOwnDeliveryMethod.new
|
||||
def self.lookup_method(delivery_method)
|
||||
case delivery_method
|
||||
when Symbol
|
||||
method_name = delivery_method.to_s.camelize
|
||||
method_class = ActionMailer::DeliveryMethod.const_get(method_name)
|
||||
method_class.new()
|
||||
when nil
|
||||
Smtp.new
|
||||
else
|
||||
delivery_method
|
||||
end
|
||||
end
|
||||
|
||||
# An abstract delivery method class. There are multiple delivery method
|
||||
# classes, documented under
|
||||
# See the classes under the ActionMailer::DeliveryMethod, e.g.
|
||||
# ActionMailer::DeliveryMethod::Smtp.
|
||||
# Smtp is the default delivery method for production
|
||||
# while Test is used in testing.
|
||||
#
|
||||
# each delivery method exposes just one method
|
||||
#
|
||||
# delivery_method = ActionMailer::DeliveryMethod::Smtp.new
|
||||
#
|
||||
# delivery_method.perform_delivery(mail) # send the mail via smtp
|
||||
class Method
|
||||
superclass_delegating_accessor :settings
|
||||
self.settings = {}
|
||||
end
|
||||
|
||||
end
|
||||
end
|
|
@ -0,0 +1,21 @@
|
|||
require 'tmpdir'
|
||||
module ActionMailer
|
||||
module DeliveryMethod
|
||||
|
||||
# A delivery method implementation which writes all mails to a file.
|
||||
class File < Method
|
||||
|
||||
self.settings = {
|
||||
:location => defined?(Rails) ? "#{Rails.root}/tmp/mails" : "#{Dir.tmpdir}/mails"
|
||||
}
|
||||
|
||||
def perform_delivery(mail)
|
||||
FileUtils.mkdir_p settings[:location]
|
||||
|
||||
(mail.to + mail.cc + mail.bcc).uniq.each do |to|
|
||||
::File.open(::File.join(settings[:location], to), 'a') { |f| f.write(mail) }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,22 @@
|
|||
module ActionMailer
|
||||
module DeliveryMethod
|
||||
|
||||
# A delivery method implementation which sends via sendmail.
|
||||
class Sendmail < Method
|
||||
|
||||
self.settings = {
|
||||
:location => '/usr/sbin/sendmail',
|
||||
:arguments => '-i -t'
|
||||
}
|
||||
|
||||
def perform_delivery(mail)
|
||||
sendmail_args = settings[:arguments]
|
||||
sendmail_args += " -f \"#{mail['return-path']}\"" if mail['return-path']
|
||||
IO.popen("#{settings[:location]} #{sendmail_args}","w+") do |sm|
|
||||
sm.print(mail.encoded.gsub(/\r/, ''))
|
||||
sm.flush
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,31 @@
|
|||
module ActionMailer
|
||||
module DeliveryMethod
|
||||
|
||||
# A delivery method implementation which sends via smtp.
|
||||
class Smtp < Method
|
||||
|
||||
self.settings = {
|
||||
:address => "localhost",
|
||||
:port => 25,
|
||||
:domain => 'localhost.localdomain',
|
||||
:user_name => nil,
|
||||
:password => nil,
|
||||
:authentication => nil,
|
||||
:enable_starttls_auto => true,
|
||||
}
|
||||
|
||||
def perform_delivery(mail)
|
||||
destinations = mail.destinations
|
||||
mail.ready_to_send
|
||||
sender = (mail['return-path'] && mail['return-path'].spec) || mail['from']
|
||||
|
||||
smtp = Net::SMTP.new(settings[:address], settings[:port])
|
||||
smtp.enable_starttls_auto if settings[:enable_starttls_auto] && smtp.respond_to?(:enable_starttls_auto)
|
||||
smtp.start(settings[:domain], settings[:user_name], settings[:password],
|
||||
settings[:authentication]) do |smtp|
|
||||
smtp.sendmail(mail.encoded, sender, destinations)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,12 @@
|
|||
module ActionMailer
|
||||
module DeliveryMethod
|
||||
|
||||
# A delivery method implementation designed for testing, which just appends each record to the :deliveries array
|
||||
class Test < Method
|
||||
|
||||
def perform_delivery(mail)
|
||||
ActionMailer::Base.deliveries << mail
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -11,6 +11,21 @@ class FileDeliveryMethodMailer < ActionMailer::Base
|
|||
self.delivery_method = :file
|
||||
end
|
||||
|
||||
class CustomDeliveryMethod
|
||||
attr_accessor :custom_deliveries
|
||||
def initialize()
|
||||
@customer_deliveries = []
|
||||
end
|
||||
|
||||
def self.perform_delivery(mail)
|
||||
self.custom_deliveries << mail
|
||||
end
|
||||
end
|
||||
|
||||
class CustomerDeliveryMailer < ActionMailer::Base
|
||||
self.delivery_method = CustomDeliveryMethod.new
|
||||
end
|
||||
|
||||
class ActionMailerBase_delivery_method_Test < Test::Unit::TestCase
|
||||
def setup
|
||||
set_delivery_method :smtp
|
||||
|
@ -21,7 +36,7 @@ class ActionMailerBase_delivery_method_Test < Test::Unit::TestCase
|
|||
end
|
||||
|
||||
def test_should_be_the_default_smtp
|
||||
assert_equal :smtp, ActionMailer::Base.delivery_method
|
||||
assert_instance_of ActionMailer::DeliveryMethod::Smtp, ActionMailer::Base.delivery_method
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -35,7 +50,7 @@ class DefaultDeliveryMethodMailer_delivery_method_Test < Test::Unit::TestCase
|
|||
end
|
||||
|
||||
def test_should_be_the_default_smtp
|
||||
assert_equal :smtp, DefaultDeliveryMethodMailer.delivery_method
|
||||
assert_instance_of ActionMailer::DeliveryMethod::Smtp, DefaultDeliveryMethodMailer.delivery_method
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -49,7 +64,7 @@ class NonDefaultDeliveryMethodMailer_delivery_method_Test < Test::Unit::TestCase
|
|||
end
|
||||
|
||||
def test_should_be_the_set_delivery_method
|
||||
assert_equal :sendmail, NonDefaultDeliveryMethodMailer.delivery_method
|
||||
assert_instance_of ActionMailer::DeliveryMethod::Sendmail, NonDefaultDeliveryMethodMailer.delivery_method
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -63,7 +78,7 @@ class FileDeliveryMethodMailer_delivery_method_Test < Test::Unit::TestCase
|
|||
end
|
||||
|
||||
def test_should_be_the_set_delivery_method
|
||||
assert_equal :file, FileDeliveryMethodMailer.delivery_method
|
||||
assert_instance_of ActionMailer::DeliveryMethod::File, FileDeliveryMethodMailer.delivery_method
|
||||
end
|
||||
|
||||
def test_should_default_location_to_the_tmpdir
|
||||
|
@ -71,3 +86,16 @@ class FileDeliveryMethodMailer_delivery_method_Test < Test::Unit::TestCase
|
|||
end
|
||||
end
|
||||
|
||||
class CustomDeliveryMethodMailer_delivery_method_Test < Test::Unit::TestCase
|
||||
def setup
|
||||
set_delivery_method :smtp
|
||||
end
|
||||
|
||||
def teardown
|
||||
restore_delivery_method
|
||||
end
|
||||
|
||||
def test_should_be_the_set_delivery_method
|
||||
assert_instance_of CustomDeliveryMethod, CustomerDeliveryMailer.delivery_method
|
||||
end
|
||||
end
|
||||
|
|
|
@ -554,7 +554,7 @@ class ActionMailerTest < Test::Unit::TestCase
|
|||
|
||||
def test_doesnt_raise_errors_when_raise_delivery_errors_is_false
|
||||
ActionMailer::Base.raise_delivery_errors = false
|
||||
TestMailer.any_instance.expects(:perform_delivery_test).raises(Exception)
|
||||
TestMailer.delivery_method.expects(:perform_delivery).raises(Exception)
|
||||
assert_nothing_raised { TestMailer.deliver_signed_up(@recipient) }
|
||||
end
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ end
|
|||
|
||||
class TestHelperMailerTest < ActionMailer::TestCase
|
||||
def test_setup_sets_right_action_mailer_options
|
||||
assert_equal :test, ActionMailer::Base.delivery_method
|
||||
assert_instance_of ActionMailer::DeliveryMethod::Test, ActionMailer::Base.delivery_method
|
||||
assert ActionMailer::Base.perform_deliveries
|
||||
assert_equal [], ActionMailer::Base.deliveries
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue