diff options
Diffstat (limited to 'actionmailer/lib')
-rw-r--r-- | actionmailer/lib/action_mailer.rb | 3 | ||||
-rw-r--r-- | actionmailer/lib/action_mailer/base.rb | 47 | ||||
-rw-r--r-- | actionmailer/lib/action_mailer/delivery_job.rb | 8 | ||||
-rw-r--r-- | actionmailer/lib/action_mailer/gem_version.rb | 2 | ||||
-rw-r--r-- | actionmailer/lib/action_mailer/inline_preview_interceptor.rb | 4 | ||||
-rw-r--r-- | actionmailer/lib/action_mailer/log_subscriber.rb | 8 | ||||
-rw-r--r-- | actionmailer/lib/action_mailer/mail_delivery_job.rb | 38 | ||||
-rw-r--r-- | actionmailer/lib/action_mailer/message_delivery.rb | 12 | ||||
-rw-r--r-- | actionmailer/lib/action_mailer/parameterized.rb | 31 | ||||
-rw-r--r-- | actionmailer/lib/action_mailer/railtie.rb | 25 | ||||
-rw-r--r-- | actionmailer/lib/action_mailer/test_helper.rb | 25 |
11 files changed, 152 insertions, 51 deletions
diff --git a/actionmailer/lib/action_mailer.rb b/actionmailer/lib/action_mailer.rb index 69eae65d60..953c5fb508 100644 --- a/actionmailer/lib/action_mailer.rb +++ b/actionmailer/lib/action_mailer.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true #-- -# Copyright (c) 2004-2018 David Heinemeier Hansson +# Copyright (c) 2004-2019 David Heinemeier Hansson # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -52,6 +52,7 @@ module ActionMailer autoload :TestHelper autoload :MessageDelivery autoload :DeliveryJob + autoload :MailDeliveryJob def self.eager_load! super diff --git a/actionmailer/lib/action_mailer/base.rb b/actionmailer/lib/action_mailer/base.rb index 7f22af83b0..c1ac9c2ad1 100644 --- a/actionmailer/lib/action_mailer/base.rb +++ b/actionmailer/lib/action_mailer/base.rb @@ -565,6 +565,11 @@ module ActionMailer # end # end def receive(raw_mail) + ActiveSupport::Deprecation.warn(<<~MESSAGE.squish) + ActionMailer::Base.receive is deprecated and will be removed in Rails 6.1. + Use Action Mailbox to process inbound email. + MESSAGE + ActiveSupport::Notifications.instrument("receive.action_mailer") do |payload| mail = Mail.new(raw_mail) set_payload_for_mail(payload, mail) @@ -588,15 +593,16 @@ module ActionMailer private def set_payload_for_mail(payload, mail) - payload[:mailer] = name - payload[:message_id] = mail.message_id - payload[:subject] = mail.subject - payload[:to] = mail.to - payload[:from] = mail.from - payload[:bcc] = mail.bcc if mail.bcc.present? - payload[:cc] = mail.cc if mail.cc.present? - payload[:date] = mail.date - payload[:mail] = mail.encoded + payload[:mail] = mail.encoded + payload[:mailer] = name + payload[:message_id] = mail.message_id + payload[:subject] = mail.subject + payload[:to] = mail.to + payload[:from] = mail.from + payload[:bcc] = mail.bcc if mail.bcc.present? + payload[:cc] = mail.cc if mail.cc.present? + payload[:date] = mail.date + payload[:perform_deliveries] = mail.perform_deliveries end def method_missing(method_name, *args) @@ -938,11 +944,9 @@ module ActionMailer assignable.each { |k, v| message[k] = v } end - def collect_responses(headers) + def collect_responses(headers, &block) if block_given? - collector = ActionMailer::Collector.new(lookup_context) { render(action_name) } - yield(collector) - collector.responses + collect_responses_from_block(headers, &block) elsif headers[:body] collect_responses_from_text(headers) else @@ -950,6 +954,13 @@ module ActionMailer end end + def collect_responses_from_block(headers) + templates_name = headers[:template_name] || action_name + collector = ActionMailer::Collector.new(lookup_context) { render(templates_name) } + yield(collector) + collector.responses + end + def collect_responses_from_text(headers) [{ body: headers.delete(:body), @@ -962,10 +973,10 @@ module ActionMailer templates_name = headers[:template_name] || action_name each_template(Array(templates_path), templates_name).map do |template| - self.formats = template.formats + format = template.format || self.formats.first { - body: render(template: template), - content_type: template.type.to_s + body: render(template: template, formats: [format]), + content_type: Mime[format].to_s } end end @@ -975,7 +986,7 @@ module ActionMailer if templates.empty? raise ActionView::MissingTemplate.new(paths, name, paths, false, "mailer") else - templates.uniq(&:formats).each(&block) + templates.uniq(&:format).each(&block) end end @@ -1007,7 +1018,7 @@ module ActionMailer end def instrument_name - "action_mailer".freeze + "action_mailer" end ActiveSupport.run_load_hooks(:action_mailer, self) diff --git a/actionmailer/lib/action_mailer/delivery_job.rb b/actionmailer/lib/action_mailer/delivery_job.rb index 40f26d8ad1..f228006920 100644 --- a/actionmailer/lib/action_mailer/delivery_job.rb +++ b/actionmailer/lib/action_mailer/delivery_job.rb @@ -12,6 +12,14 @@ module ActionMailer rescue_from StandardError, with: :handle_exception_with_mailer_class + before_perform do + ActiveSupport::Deprecation.warn <<~MSG.squish + Sending mail with DeliveryJob and Parameterized::DeliveryJob + is deprecated and will be removed in Rails 6.1. + Please use MailDeliveryJob instead. + MSG + end + def perform(mailer, mail_method, delivery_method, *args) #:nodoc: mailer.constantize.public_send(mail_method, *args).send(delivery_method) end diff --git a/actionmailer/lib/action_mailer/gem_version.rb b/actionmailer/lib/action_mailer/gem_version.rb index 72eb5d61e8..4efcd966db 100644 --- a/actionmailer/lib/action_mailer/gem_version.rb +++ b/actionmailer/lib/action_mailer/gem_version.rb @@ -10,7 +10,7 @@ module ActionMailer MAJOR = 6 MINOR = 0 TINY = 0 - PRE = "alpha" + PRE = "beta3" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/actionmailer/lib/action_mailer/inline_preview_interceptor.rb b/actionmailer/lib/action_mailer/inline_preview_interceptor.rb index 8a12f805cc..2b97ac5b94 100644 --- a/actionmailer/lib/action_mailer/inline_preview_interceptor.rb +++ b/actionmailer/lib/action_mailer/inline_preview_interceptor.rb @@ -40,9 +40,7 @@ module ActionMailer end private - def message - @message - end + attr_reader :message def html_part @html_part ||= message.html_part diff --git a/actionmailer/lib/action_mailer/log_subscriber.rb b/actionmailer/lib/action_mailer/log_subscriber.rb index 87cfbfff28..26910f20f0 100644 --- a/actionmailer/lib/action_mailer/log_subscriber.rb +++ b/actionmailer/lib/action_mailer/log_subscriber.rb @@ -9,8 +9,12 @@ module ActionMailer # An email was delivered. def deliver(event) info do - recipients = Array(event.payload[:to]).join(", ") - "Sent mail to #{recipients} (#{event.duration.round(1)}ms)" + perform_deliveries = event.payload[:perform_deliveries] + if perform_deliveries + "Delivered mail #{event.payload[:message_id]} (#{event.duration.round(1)}ms)" + else + "Skipped delivery of mail #{event.payload[:message_id]} as `perform_deliveries` is false" + end end debug { event.payload[:mail] } diff --git a/actionmailer/lib/action_mailer/mail_delivery_job.rb b/actionmailer/lib/action_mailer/mail_delivery_job.rb new file mode 100644 index 0000000000..609c6a72d9 --- /dev/null +++ b/actionmailer/lib/action_mailer/mail_delivery_job.rb @@ -0,0 +1,38 @@ +# frozen_string_literal: true + +require "active_job" + +module ActionMailer + # The <tt>ActionMailer::MailDeliveryJob</tt> class is used when you + # want to send emails outside of the request-response cycle. It supports + # sending either parameterized or normal mail. + # + # Exceptions are rescued and handled by the mailer class. + class MailDeliveryJob < ActiveJob::Base # :nodoc: + queue_as { ActionMailer::Base.deliver_later_queue_name } + + rescue_from StandardError, with: :handle_exception_with_mailer_class + + def perform(mailer, mail_method, delivery_method, args:, params: nil) #:nodoc: + mailer_class = params ? mailer.constantize.with(params) : mailer.constantize + mailer_class.public_send(mail_method, *args).send(delivery_method) + end + + private + # "Deserialize" the mailer class name by hand in case another argument + # (like a Global ID reference) raised DeserializationError. + def mailer_class + if mailer = Array(@serialized_arguments).first || Array(arguments).first + mailer.constantize + end + end + + def handle_exception_with_mailer_class(exception) + if klass = mailer_class + klass.handle_exception exception + else + raise exception + end + end + end +end diff --git a/actionmailer/lib/action_mailer/message_delivery.rb b/actionmailer/lib/action_mailer/message_delivery.rb index 2377aeb9a5..1e5cab6d47 100644 --- a/actionmailer/lib/action_mailer/message_delivery.rb +++ b/actionmailer/lib/action_mailer/message_delivery.rb @@ -29,7 +29,7 @@ module ActionMailer @mail_message ||= processed_mailer.message end - # Unused except for delegator internals (dup, marshaling). + # Unused except for delegator internals (dup, marshalling). def __setobj__(mail_message) #:nodoc: @mail_message = mail_message end @@ -135,10 +135,18 @@ module ActionMailer "#deliver_later, 2. only touch the message *within your mailer " \ "method*, or 3. use a custom Active Job instead of #deliver_later." else - args = @mailer_class.name, @action.to_s, delivery_method.to_s, *@args job = @mailer_class.delivery_job + args = arguments_for(job, delivery_method) job.set(options).perform_later(*args) end end + + def arguments_for(delivery_job, delivery_method) + if delivery_job <= MailDeliveryJob + [@mailer_class.name, @action.to_s, delivery_method.to_s, args: @args] + else + [@mailer_class.name, @action.to_s, delivery_method.to_s, *@args] + end + end end end diff --git a/actionmailer/lib/action_mailer/parameterized.rb b/actionmailer/lib/action_mailer/parameterized.rb index 5e768e7106..0a97af8105 100644 --- a/actionmailer/lib/action_mailer/parameterized.rb +++ b/actionmailer/lib/action_mailer/parameterized.rb @@ -121,6 +121,12 @@ module ActionMailer end end + class DeliveryJob < ActionMailer::DeliveryJob # :nodoc: + def perform(mailer, mail_method, delivery_method, params, *args) + mailer.constantize.with(params).public_send(mail_method, *args).send(delivery_method) + end + end + class MessageDelivery < ActionMailer::MessageDelivery # :nodoc: def initialize(mailer_class, action, params, *args) super(mailer_class, action, *args) @@ -139,16 +145,27 @@ module ActionMailer if processed? super else - args = @mailer_class.name, @action.to_s, delivery_method.to_s, @params, *@args - ActionMailer::Parameterized::DeliveryJob.set(options).perform_later(*args) + job = delivery_job_class + args = arguments_for(job, delivery_method) + job.set(options).perform_later(*args) end end - end - class DeliveryJob < ActionMailer::DeliveryJob # :nodoc: - def perform(mailer, mail_method, delivery_method, params, *args) - mailer.constantize.with(params).public_send(mail_method, *args).send(delivery_method) - end + def delivery_job_class + if @mailer_class.delivery_job <= MailDeliveryJob + @mailer_class.delivery_job + else + Parameterized::DeliveryJob + end + end + + def arguments_for(delivery_job, delivery_method) + if delivery_job <= MailDeliveryJob + [@mailer_class.name, @action.to_s, delivery_method.to_s, params: @params, args: @args] + else + [@mailer_class.name, @action.to_s, delivery_method.to_s, @params, *@args] + end + end end end end diff --git a/actionmailer/lib/action_mailer/railtie.rb b/actionmailer/lib/action_mailer/railtie.rb index 69578471b0..893a4a25b1 100644 --- a/actionmailer/lib/action_mailer/railtie.rb +++ b/actionmailer/lib/action_mailer/railtie.rb @@ -46,10 +46,25 @@ module ActionMailer register_preview_interceptors(options.delete(:preview_interceptors)) register_observers(options.delete(:observers)) + if delivery_job = options.delete(:delivery_job) + self.delivery_job = delivery_job.constantize + end + options.each { |k, v| send("#{k}=", v) } end - ActiveSupport.on_load(:action_dispatch_integration_test) { include ActionMailer::TestCase::ClearTestDeliveries } + ActiveSupport.on_load(:action_dispatch_integration_test) do + include ActionMailer::TestHelper + include ActionMailer::TestCase::ClearTestDeliveries + end + end + + initializer "action_mailer.set_autoload_paths" do |app| + options = app.config.action_mailer + + if options.show_previews && options.preview_path + ActiveSupport::Dependencies.autoload_paths << options.preview_path + end end initializer "action_mailer.compile_config_methods" do @@ -69,12 +84,8 @@ module ActionMailer if options.show_previews app.routes.prepend do - get "/rails/mailers" => "rails/mailers#index", internal: true - get "/rails/mailers/*path" => "rails/mailers#preview", internal: true - end - - if options.preview_path - ActiveSupport::Dependencies.autoload_paths << options.preview_path + get "/rails/mailers" => "rails/mailers#index", internal: true + get "/rails/mailers/*path" => "rails/mailers#preview", internal: true end end end diff --git a/actionmailer/lib/action_mailer/test_helper.rb b/actionmailer/lib/action_mailer/test_helper.rb index a4751916af..e222301dff 100644 --- a/actionmailer/lib/action_mailer/test_helper.rb +++ b/actionmailer/lib/action_mailer/test_helper.rb @@ -34,7 +34,7 @@ module ActionMailer def assert_emails(number, &block) if block_given? original_count = ActionMailer::Base.deliveries.size - perform_enqueued_jobs(only: [ActionMailer::DeliveryJob, ActionMailer::Parameterized::DeliveryJob], &block) + perform_enqueued_jobs(only: ->(job) { delivery_job_filter(job) }, &block) new_count = ActionMailer::Base.deliveries.size assert_equal number, new_count - original_count, "#{number} emails expected, but #{new_count - original_count} were sent" else @@ -90,7 +90,7 @@ module ActionMailer # end # end def assert_enqueued_emails(number, &block) - assert_enqueued_jobs number, only: [ ActionMailer::DeliveryJob, ActionMailer::Parameterized::DeliveryJob ], &block + assert_enqueued_jobs(number, only: ->(job) { delivery_job_filter(job) }, &block) end # Asserts that a specific email has been enqueued, optionally @@ -124,15 +124,12 @@ module ActionMailer # end # end def assert_enqueued_email_with(mailer, method, args: nil, queue: "mailers", &block) - if args.is_a? Hash - job = ActionMailer::Parameterized::DeliveryJob - args = [mailer.to_s, method.to_s, "deliver_now", args] + args = if args.is_a?(Hash) + [mailer.to_s, method.to_s, "deliver_now", params: args, args: []] else - job = ActionMailer::DeliveryJob - args = [mailer.to_s, method.to_s, "deliver_now", *args] + [mailer.to_s, method.to_s, "deliver_now", args: Array(args)] end - - assert_enqueued_with(job: job, args: args, queue: queue, &block) + assert_enqueued_with(job: mailer.delivery_job, args: args, queue: queue, &block) end # Asserts that no emails are enqueued for later delivery. @@ -151,7 +148,15 @@ module ActionMailer # end # end def assert_no_enqueued_emails(&block) - assert_no_enqueued_jobs only: [ ActionMailer::DeliveryJob, ActionMailer::Parameterized::DeliveryJob ], &block + assert_enqueued_emails 0, &block end + + private + + def delivery_job_filter(job) + job_class = job.is_a?(Hash) ? job.fetch(:job) : job.class + + Base.descendants.map(&:delivery_job).include?(job_class) + end end end |