diff options
Diffstat (limited to 'actionmailer')
-rw-r--r-- | actionmailer/CHANGELOG.md | 16 | ||||
-rw-r--r-- | actionmailer/lib/action_mailer/base.rb | 19 | ||||
-rw-r--r-- | actionmailer/lib/action_mailer/log_subscriber.rb | 24 | ||||
-rw-r--r-- | actionmailer/lib/action_mailer/preview.rb | 12 | ||||
-rw-r--r-- | actionmailer/lib/action_mailer/railtie.rb | 10 | ||||
-rw-r--r-- | actionmailer/test/abstract_unit.rb | 26 | ||||
-rw-r--r-- | actionmailer/test/asset_host_test.rb | 17 | ||||
-rw-r--r-- | actionmailer/test/base_test.rb | 39 | ||||
-rw-r--r-- | actionmailer/test/delivery_methods_test.rb | 2 | ||||
-rw-r--r-- | actionmailer/test/fixtures/test_helper_mailer/welcome | 1 | ||||
-rw-r--r-- | actionmailer/test/i18n_with_controller_test.rb | 18 | ||||
-rw-r--r-- | actionmailer/test/test_helper_test.rb | 9 |
12 files changed, 140 insertions, 53 deletions
diff --git a/actionmailer/CHANGELOG.md b/actionmailer/CHANGELOG.md index 97ff62fa87..bcfde6d96f 100644 --- a/actionmailer/CHANGELOG.md +++ b/actionmailer/CHANGELOG.md @@ -1,3 +1,19 @@ +* Raise an exception when attachments are added after `mail` was called. + This is a safeguard to prevent invalid emails. + + Fixes #16163. + + *Yves Senn* + +* Add `config.action_mailer.show_previews` configuration option. + + This config option can be used to enable the mail preview in environments + other than development (such as staging). + + Defaults to `true` in development and false elsewhere. + + *Leonard Garvey* + * Allow preview interceptors to be registered through `config.action_mailer.preview_interceptors`. diff --git a/actionmailer/lib/action_mailer/base.rb b/actionmailer/lib/action_mailer/base.rb index 135cf35ac0..d9b88ec608 100644 --- a/actionmailer/lib/action_mailer/base.rb +++ b/actionmailer/lib/action_mailer/base.rb @@ -394,7 +394,7 @@ module ActionMailer # implement for a custom delivery agent. # # * <tt>perform_deliveries</tt> - Determines whether emails are actually sent from Action Mailer when you - # call <tt>.deliver</tt> on an mail message or on an Action Mailer method. This is on by default but can + # call <tt>.deliver</tt> on an email message or on an Action Mailer method. This is on by default but can # be turned off to aid in functional testing. # # * <tt>deliveries</tt> - Keeps an array of all the emails sent out through the Action Mailer with @@ -649,7 +649,22 @@ module ActionMailer # mail.attachments[0] # => Mail::Part (first attachment) # def attachments - @_message.attachments + if @_mail_was_called + LateAttachmentsProxy.new(@_message.attachments) + else + @_message.attachments + end + end + + class LateAttachmentsProxy < SimpleDelegator + def inline; _raise_error end + def []=(_name, _content); _raise_error end + + private + def _raise_error + raise RuntimeError, "Can't add attachments after `mail` was called.\n" \ + "Make sure to use `attachments[]=` before calling `mail`." + end end # The main method that creates the message and renders the email templates. There are diff --git a/actionmailer/lib/action_mailer/log_subscriber.rb b/actionmailer/lib/action_mailer/log_subscriber.rb index e4aaab34b1..5b57c75ec3 100644 --- a/actionmailer/lib/action_mailer/log_subscriber.rb +++ b/actionmailer/lib/action_mailer/log_subscriber.rb @@ -6,25 +6,27 @@ module ActionMailer class LogSubscriber < ActiveSupport::LogSubscriber # An email was delivered. def deliver(event) - return unless logger.info? - recipients = Array(event.payload[:to]).join(', ') - info("\nSent mail to #{recipients} (#{event.duration.round(1)}ms)") - debug(event.payload[:mail]) + info do + recipients = Array(event.payload[:to]).join(', ') + "\nSent mail to #{recipients} (#{event.duration.round(1)}ms)" + end + + debug { event.payload[:mail] } end # An email was received. def receive(event) - return unless logger.info? - info("\nReceived mail (#{event.duration.round(1)}ms)") - debug(event.payload[:mail]) + info { "\nReceived mail (#{event.duration.round(1)}ms)" } + debug { event.payload[:mail] } end # An email was generated. def process(event) - return unless logger.debug? - mailer = event.payload[:mailer] - action = event.payload[:action] - debug("\n#{mailer}##{action}: processed outbound mail in #{event.duration.round(1)}ms") + debug do + mailer = event.payload[:mailer] + action = event.payload[:action] + "\n#{mailer}##{action}: processed outbound mail in #{event.duration.round(1)}ms" + end end # Use the logger configured for ActionMailer::Base diff --git a/actionmailer/lib/action_mailer/preview.rb b/actionmailer/lib/action_mailer/preview.rb index 33a9faa7e7..33de1dc049 100644 --- a/actionmailer/lib/action_mailer/preview.rb +++ b/actionmailer/lib/action_mailer/preview.rb @@ -11,6 +11,14 @@ module ActionMailer # mattr_accessor :preview_path, instance_writer: false + # Enable or disable mailer previews through app configuration: + # + # config.action_mailer.show_previews = true + # + # Defaults to true for development environment + # + mattr_accessor :show_previews, instance_writer: false + # :nodoc: mattr_accessor :preview_interceptors, instance_writer: false self.preview_interceptors = [] @@ -94,6 +102,10 @@ module ActionMailer Base.preview_path end + def show_previews #:nodoc: + Base.show_previews + end + def inform_preview_interceptors(message) #:nodoc: Base.preview_interceptors.each do |interceptor| interceptor.previewing_email(message) diff --git a/actionmailer/lib/action_mailer/railtie.rb b/actionmailer/lib/action_mailer/railtie.rb index 671551fa53..6f760732e2 100644 --- a/actionmailer/lib/action_mailer/railtie.rb +++ b/actionmailer/lib/action_mailer/railtie.rb @@ -18,8 +18,9 @@ module ActionMailer options.assets_dir ||= paths["public"].first options.javascripts_dir ||= paths["public/javascripts"].first options.stylesheets_dir ||= paths["public/stylesheets"].first + options.show_previews = Rails.env.development? if options.show_previews.nil? - if Rails.env.development? + if options.show_previews options.preview_path ||= defined?(Rails.root) ? "#{Rails.root}/test/mailers/previews" : nil end @@ -37,6 +38,13 @@ module ActionMailer register_observers(options.delete(:observers)) options.each { |k,v| send("#{k}=", v) } + + if options.show_previews + app.routes.append do + get '/rails/mailers' => "rails/mailers#index" + get '/rails/mailers/*path' => "rails/mailers#preview" + end + end end end diff --git a/actionmailer/test/abstract_unit.rb b/actionmailer/test/abstract_unit.rb index 4e5a9c3715..98d266bd73 100644 --- a/actionmailer/test/abstract_unit.rb +++ b/actionmailer/test/abstract_unit.rb @@ -26,27 +26,9 @@ I18n.enforce_available_locales = false FIXTURE_LOAD_PATH = File.expand_path('fixtures', File.dirname(__FILE__)) ActionMailer::Base.view_paths = FIXTURE_LOAD_PATH -class MockSMTP - def self.deliveries - @@deliveries - end - - def initialize - @@deliveries = [] - end - - def sendmail(mail, from, to) - @@deliveries << [mail, from, to] - end - - def start(*args) - yield self - end -end - -class Net::SMTP - def self.new(*args) - MockSMTP.new +class Rails + def self.root + File.expand_path('../', File.dirname(__FILE__)) end end @@ -67,3 +49,5 @@ end def jruby_skip(message = '') skip message if defined?(JRUBY_VERSION) end + +require 'mocha/setup' # FIXME: stop using mocha diff --git a/actionmailer/test/asset_host_test.rb b/actionmailer/test/asset_host_test.rb index 00f1348a53..9ba67c2842 100644 --- a/actionmailer/test/asset_host_test.rb +++ b/actionmailer/test/asset_host_test.rb @@ -31,25 +31,10 @@ class AssetHostTest < ActiveSupport::TestCase def test_asset_host_as_one_argument_proc AssetHostMailer.config.asset_host = Proc.new { |source| if source.starts_with?('/images') - "http://images.example.com" - else - "http://assets.example.com" + 'http://images.example.com' end } mail = AssetHostMailer.email_with_asset assert_equal %Q{<img alt="Somelogo" src="http://images.example.com/images/somelogo.png" />}, mail.body.to_s.strip end - - def test_asset_host_as_two_argument_proc - ActionController::Base.config.asset_host = Proc.new {|source,request| - if request && request.ssl? - "https://www.example.com" - else - "http://www.example.com" - end - } - mail = nil - assert_nothing_raised { mail = AssetHostMailer.email_with_asset } - assert_equal %Q{<img alt="Somelogo" src="http://www.example.com/images/somelogo.png" />}, mail.body.to_s.strip - end end diff --git a/actionmailer/test/base_test.rb b/actionmailer/test/base_test.rb index 229ded8e04..6116d1e29f 100644 --- a/actionmailer/test/base_test.rb +++ b/actionmailer/test/base_test.rb @@ -232,6 +232,45 @@ class BaseTest < ActiveSupport::TestCase end end + test "adding attachments after mail was called raises exception" do + class LateAttachmentMailer < ActionMailer::Base + def welcome + mail body: "yay", from: "welcome@example.com", to: "to@example.com" + attachments['invoice.pdf'] = 'This is test File content' + end + end + + e = assert_raises(RuntimeError) { LateAttachmentMailer.welcome } + assert_match(/Can't add attachments after `mail` was called./, e.message) + end + + test "adding inline attachments after mail was called raises exception" do + class LateInlineAttachmentMailer < ActionMailer::Base + def welcome + mail body: "yay", from: "welcome@example.com", to: "to@example.com" + attachments.inline['invoice.pdf'] = 'This is test File content' + end + end + + e = assert_raises(RuntimeError) { LateInlineAttachmentMailer.welcome } + assert_match(/Can't add attachments after `mail` was called./, e.message) + end + + test "accessing attachments works after mail was called" do + class LateAttachmentAccessorMailer < ActionMailer::Base + def welcome + attachments['invoice.pdf'] = 'This is test File content' + mail body: "yay", from: "welcome@example.com", to: "to@example.com" + + unless attachments.map(&:filename) == ["invoice.pdf"] + raise Minitest::Assertion, "Should allow access to attachments" + end + end + end + + assert_nothing_raised { LateAttachmentAccessorMailer.welcome } + end + # Implicit multipart test "implicit multipart" do email = BaseMailer.implicit_multipart diff --git a/actionmailer/test/delivery_methods_test.rb b/actionmailer/test/delivery_methods_test.rb index 16e8638542..a76ac6d295 100644 --- a/actionmailer/test/delivery_methods_test.rb +++ b/actionmailer/test/delivery_methods_test.rb @@ -108,6 +108,7 @@ class MailDeliveryTest < ActiveSupport::TestCase end test "delivery method can be customized per instance" do + Mail::SMTP.any_instance.expects(:deliver!) email = DeliveryMailer.welcome.deliver assert_instance_of Mail::SMTP, email.delivery_method email = DeliveryMailer.welcome(delivery_method: :test).deliver @@ -117,7 +118,6 @@ class MailDeliveryTest < ActiveSupport::TestCase test "delivery method can be customized in subclasses not changing the parent" do DeliveryMailer.delivery_method = :test assert_equal :smtp, ActionMailer::Base.delivery_method - $BREAK = true email = DeliveryMailer.welcome.deliver assert_instance_of Mail::TestMailer, email.delivery_method end diff --git a/actionmailer/test/fixtures/test_helper_mailer/welcome b/actionmailer/test/fixtures/test_helper_mailer/welcome new file mode 100644 index 0000000000..61ce70d578 --- /dev/null +++ b/actionmailer/test/fixtures/test_helper_mailer/welcome @@ -0,0 +1 @@ +Welcome!
\ No newline at end of file diff --git a/actionmailer/test/i18n_with_controller_test.rb b/actionmailer/test/i18n_with_controller_test.rb index d9d588a950..ee36b89dd6 100644 --- a/actionmailer/test/i18n_with_controller_test.rb +++ b/actionmailer/test/i18n_with_controller_test.rb @@ -28,8 +28,23 @@ class ActionMailerI18nWithControllerTest < ActionDispatch::IntegrationTest get ':controller(/:action(/:id))' end + class RoutedRackApp + attr_reader :routes + + def initialize(routes, &blk) + @routes = routes + @stack = ActionDispatch::MiddlewareStack.new(&blk).build(@routes) + end + + def call(env) + @stack.call(env) + end + end + + APP = RoutedRackApp.new(Routes) + def app - Routes + APP end teardown do @@ -37,6 +52,7 @@ class ActionMailerI18nWithControllerTest < ActionDispatch::IntegrationTest end def test_send_mail + Mail::SMTP.any_instance.expects(:deliver!) with_translation 'de', email_subject: '[Anmeldung] Willkommen' do get '/test/send_mail' assert_equal "Mail sent - Subject: [Anmeldung] Willkommen", @response.body diff --git a/actionmailer/test/test_helper_test.rb b/actionmailer/test/test_helper_test.rb index 7c7f0b6fdc..1ff08a3b6e 100644 --- a/actionmailer/test/test_helper_test.rb +++ b/actionmailer/test/test_helper_test.rb @@ -1,3 +1,4 @@ +# encoding: utf-8 require 'abstract_unit' class TestHelperMailer < ActionMailer::Base @@ -36,6 +37,14 @@ class TestHelperMailerTest < ActionMailer::TestCase assert_equal "UTF-8", charset end + def test_encode + assert_equal '=?UTF-8?Q?This_is_=E3=81=82_string?=', encode('This is あ string') + end + + def test_read_fixture + assert_equal ['Welcome!'], read_fixture('welcome') + end + def test_assert_emails assert_nothing_raised do assert_emails 1 do |