diff options
Diffstat (limited to 'actionmailer')
-rw-r--r-- | actionmailer/CHANGELOG.md | 13 | ||||
-rw-r--r-- | actionmailer/lib/action_mailer/base.rb | 24 | ||||
-rw-r--r-- | actionmailer/lib/action_mailer/log_subscriber.rb | 24 | ||||
-rw-r--r-- | actionmailer/lib/action_mailer/railtie.rb | 2 | ||||
-rw-r--r-- | actionmailer/test/abstract_unit.rb | 7 | ||||
-rw-r--r-- | actionmailer/test/base_test.rb | 39 |
6 files changed, 95 insertions, 14 deletions
diff --git a/actionmailer/CHANGELOG.md b/actionmailer/CHANGELOG.md index 4e3a9daf7d..ab93745f60 100644 --- a/actionmailer/CHANGELOG.md +++ b/actionmailer/CHANGELOG.md @@ -1,3 +1,16 @@ +* Deprecate `*_path` helpers in email views. When used they generate + non-working links and are not the intention of most developers. Instead + we recommend to use `*_url` helper. + + *Richard Schneeman* + +* 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 diff --git a/actionmailer/lib/action_mailer/base.rb b/actionmailer/lib/action_mailer/base.rb index 135cf35ac0..bc540aece0 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 @@ -882,6 +897,11 @@ module ActionMailer container.add_part(part) end + # Emails do not support relative path links. + def self.supports_path? + false + end + ActiveSupport.run_load_hooks(:action_mailer, self) end end 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/railtie.rb b/actionmailer/lib/action_mailer/railtie.rb index 6f760732e2..c62d4b5082 100644 --- a/actionmailer/lib/action_mailer/railtie.rb +++ b/actionmailer/lib/action_mailer/railtie.rb @@ -30,7 +30,7 @@ module ActionMailer ActiveSupport.on_load(:action_mailer) do include AbstractController::UrlFor - extend ::AbstractController::Railties::RoutesHelpers.with(app.routes) + extend ::AbstractController::Railties::RoutesHelpers.with(app.routes, false) include app.routes.mounted_helpers register_interceptors(options.delete(:interceptors)) diff --git a/actionmailer/test/abstract_unit.rb b/actionmailer/test/abstract_unit.rb index 2e5242f0b1..28727b62ec 100644 --- a/actionmailer/test/abstract_unit.rb +++ b/actionmailer/test/abstract_unit.rb @@ -49,3 +49,10 @@ end def jruby_skip(message = '') skip message if defined?(JRUBY_VERSION) end + +require 'mocha/setup' # FIXME: stop using mocha + +# FIXME: we have tests that depend on run order, we should fix that and +# remove this method call. +require 'active_support/test_case' +ActiveSupport::TestCase.my_tests_are_order_dependent! 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 |