aboutsummaryrefslogtreecommitdiffstats
path: root/actionmailer
diff options
context:
space:
mode:
Diffstat (limited to 'actionmailer')
-rw-r--r--actionmailer/CHANGELOG.md41
-rw-r--r--actionmailer/MIT-LICENSE2
-rw-r--r--actionmailer/README.rdoc40
-rw-r--r--actionmailer/actionmailer.gemspec8
-rw-r--r--actionmailer/lib/action_mailer.rb3
-rw-r--r--actionmailer/lib/action_mailer/base.rb29
-rw-r--r--actionmailer/lib/action_mailer/delivery_job.rb8
-rw-r--r--actionmailer/lib/action_mailer/gem_version.rb2
-rw-r--r--actionmailer/lib/action_mailer/log_subscriber.rb5
-rw-r--r--actionmailer/lib/action_mailer/mail_delivery_job.rb38
-rw-r--r--actionmailer/lib/action_mailer/message_delivery.rb10
-rw-r--r--actionmailer/lib/action_mailer/parameterized.rb30
-rw-r--r--actionmailer/lib/action_mailer/railtie.rb20
-rw-r--r--actionmailer/lib/action_mailer/test_helper.rb25
-rw-r--r--actionmailer/test/abstract_unit.rb2
-rw-r--r--actionmailer/test/base_test.rb63
-rw-r--r--actionmailer/test/caching_test.rb10
-rw-r--r--actionmailer/test/fixtures/base_mailer/implicit_multipart_formats.html.erb1
-rw-r--r--actionmailer/test/fixtures/base_mailer/implicit_multipart_formats.text.erb1
-rw-r--r--actionmailer/test/legacy_delivery_job_test.rb83
-rw-r--r--actionmailer/test/log_subscriber_test.rb12
-rw-r--r--actionmailer/test/mailers/base_mailer.rb15
-rw-r--r--actionmailer/test/message_delivery_test.rb16
-rw-r--r--actionmailer/test/parameterized_test.rb41
-rw-r--r--actionmailer/test/test_helper_test.rb47
25 files changed, 414 insertions, 138 deletions
diff --git a/actionmailer/CHANGELOG.md b/actionmailer/CHANGELOG.md
index db6fc7ee9c..182c43551d 100644
--- a/actionmailer/CHANGELOG.md
+++ b/actionmailer/CHANGELOG.md
@@ -1,13 +1,32 @@
-* Allow ActionMailer classes to configure the parameterized delivery job
- Example:
- ```
- class MyMailer < ApplicationMailer
- self.parameterized_delivery_job = MyCustomDeliveryJob
- ...
- end
- ```
+## Rails 6.0.0.beta3 (March 11, 2019) ##
+
+* No changes.
+
+
+## Rails 6.0.0.beta2 (February 25, 2019) ##
+
+* No changes.
+
+
+## Rails 6.0.0.beta1 (January 18, 2019) ##
+
+* Deprecate `ActionMailer::Base.receive` in favor of [Action Mailbox](https://github.com/rails/rails/tree/master/actionmailbox).
+
+ *George Claghorn*
+
+* Add `MailDeliveryJob` for delivering both regular and parameterized mail. Deprecate using `DeliveryJob` and `Parameterized::DeliveryJob`.
+
+ *Gannon McGibbon*
+
+* Fix ActionMailer assertions not working when a Mail defines
+ a custom delivery job class
+
+ *Edouard Chin*
+
+* Mails with multipart `format` blocks with implicit render now also check for
+ a template name in options hash instead of only using the action name.
- *Luke Pearce*
+ *Marcus Ilgner*
* `ActionDispatch::IntegrationTest` includes `ActionMailer::TestHelper` module by default.
@@ -54,9 +73,9 @@
*Claudio Ortolina*, *Kota Miyake*
-* Rails 6 requires Ruby 2.4.1 or newer.
+* Rails 6 requires Ruby 2.5.0 or newer.
- *Jeremy Daer*
+ *Jeremy Daer*, *Kasper Timm Hansen*
Please check [5-2-stable](https://github.com/rails/rails/blob/5-2-stable/actionmailer/CHANGELOG.md) for previous changes.
diff --git a/actionmailer/MIT-LICENSE b/actionmailer/MIT-LICENSE
index 1cb3add0fc..ab7c27c209 100644
--- a/actionmailer/MIT-LICENSE
+++ b/actionmailer/MIT-LICENSE
@@ -1,4 +1,4 @@
-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
diff --git a/actionmailer/README.rdoc b/actionmailer/README.rdoc
index 14dfb82234..0db4b2668b 100644
--- a/actionmailer/README.rdoc
+++ b/actionmailer/README.rdoc
@@ -13,6 +13,8 @@ Additionally, an Action Mailer class can be used to process incoming email,
such as allowing a blog to accept new posts from an email (which could even
have been sent from a phone).
+You can read more about Action Mailer in the {Action Mailer Basics}[https://edgeguides.rubyonrails.org/action_mailer_basics.html] guide.
+
== Sending emails
The framework works by initializing any instance variables you want to be
@@ -93,42 +95,6 @@ Example:
.....
end
-== Receiving emails
-
-To receive emails, you need to implement a public instance method called
-+receive+ that takes an email object as its single parameter. The Action Mailer
-framework has a corresponding class method, which is also called +receive+, that
-accepts a raw, unprocessed email as a string, which it then turns into the email
-object and calls the receive instance method.
-
-Example:
-
- class Mailman < ActionMailer::Base
- def receive(email)
- page = Page.find_by(address: email.to.first)
- page.emails.create(
- subject: email.subject, body: email.body
- )
-
- if email.has_attachments?
- email.attachments.each do |attachment|
- page.attachments.create({
- file: attachment, description: email.subject
- })
- end
- end
- end
- end
-
-This Mailman can be the target for Postfix or other MTAs. In Rails, you would use
-the runner in the trivial case like this:
-
- rails runner 'Mailman.receive(STDIN.read)'
-
-However, invoking Rails in the runner for each mail to be received is very
-resource intensive. A single instance of Rails should be run within a daemon, if
-it is going to process more than just a limited amount of email.
-
== Configuration
The Base class has the full list of configuration options. Here's an example:
@@ -164,7 +130,7 @@ Action Mailer is released under the MIT license:
API documentation is at
-* http://api.rubyonrails.org
+* https://api.rubyonrails.org
Bug reports for the Ruby on Rails project can be filed here:
diff --git a/actionmailer/actionmailer.gemspec b/actionmailer/actionmailer.gemspec
index 6f8d6d0699..cadccb905b 100644
--- a/actionmailer/actionmailer.gemspec
+++ b/actionmailer/actionmailer.gemspec
@@ -6,16 +6,16 @@ Gem::Specification.new do |s|
s.platform = Gem::Platform::RUBY
s.name = "actionmailer"
s.version = version
- s.summary = "Email composition, delivery, and receiving framework (part of Rails)."
- s.description = "Email on Rails. Compose, deliver, receive, and test emails using the familiar controller/view pattern. First-class support for multipart email and attachments."
+ s.summary = "Email composition and delivery framework (part of Rails)."
+ s.description = "Email on Rails. Compose, deliver, and test emails using the familiar controller/view pattern. First-class support for multipart email and attachments."
- s.required_ruby_version = ">= 2.4.1"
+ s.required_ruby_version = ">= 2.5.0"
s.license = "MIT"
s.author = "David Heinemeier Hansson"
s.email = "david@loudthinking.com"
- s.homepage = "http://rubyonrails.org"
+ s.homepage = "https://rubyonrails.org"
s.files = Dir["CHANGELOG.md", "README.rdoc", "MIT-LICENSE", "lib/**/*"]
s.require_path = "lib"
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 509d859ac3..c1ac9c2ad1 100644
--- a/actionmailer/lib/action_mailer/base.rb
+++ b/actionmailer/lib/action_mailer/base.rb
@@ -462,7 +462,6 @@ module ActionMailer
helper ActionMailer::MailHelper
class_attribute :delivery_job, default: ::ActionMailer::DeliveryJob
- class_attribute :parameterized_delivery_job, default: ::ActionMailer::Parameterized::DeliveryJob
class_attribute :default_params, default: {
mime_version: "1.0",
charset: "UTF-8",
@@ -566,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)
@@ -589,6 +593,7 @@ module ActionMailer
private
def set_payload_for_mail(payload, mail)
+ payload[:mail] = mail.encoded
payload[:mailer] = name
payload[:message_id] = mail.message_id
payload[:subject] = mail.subject
@@ -597,7 +602,6 @@ module ActionMailer
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[:perform_deliveries] = mail.perform_deliveries
end
@@ -940,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
@@ -952,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),
@@ -964,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
@@ -977,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
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/log_subscriber.rb b/actionmailer/lib/action_mailer/log_subscriber.rb
index 25c99342c2..26910f20f0 100644
--- a/actionmailer/lib/action_mailer/log_subscriber.rb
+++ b/actionmailer/lib/action_mailer/log_subscriber.rb
@@ -10,11 +10,10 @@ module ActionMailer
def deliver(event)
info do
perform_deliveries = event.payload[:perform_deliveries]
- recipients = Array(event.payload[:to]).join(", ")
if perform_deliveries
- "Sent mail to #{recipients} (#{event.duration.round(1)}ms)"
+ "Delivered mail #{event.payload[:message_id]} (#{event.duration.round(1)}ms)"
else
- "Skipped sending mail to #{recipients} as `perform_deliveries` is false"
+ "Skipped delivery of mail #{event.payload[:message_id]} as `perform_deliveries` is false"
end
end
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 a57980c322..1e5cab6d47 100644
--- a/actionmailer/lib/action_mailer/message_delivery.rb
+++ b/actionmailer/lib/action_mailer/message_delivery.rb
@@ -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 0fe417affe..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,17 +145,27 @@ module ActionMailer
if processed?
super
else
- args = @mailer_class.name, @action.to_s, delivery_method.to_s, @params, *@args
- job = @mailer_class.parameterized_delivery_job
+ 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 bb6141b406..893a4a25b1 100644
--- a/actionmailer/lib/action_mailer/railtie.rb
+++ b/actionmailer/lib/action_mailer/railtie.rb
@@ -46,6 +46,10 @@ 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
@@ -55,6 +59,14 @@ module ActionMailer
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
ActiveSupport.on_load(:action_mailer) do
config.compile_methods! if config.respond_to?(:compile_methods!)
@@ -72,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
diff --git a/actionmailer/test/abstract_unit.rb b/actionmailer/test/abstract_unit.rb
index f647896374..448807c144 100644
--- a/actionmailer/test/abstract_unit.rb
+++ b/actionmailer/test/abstract_unit.rb
@@ -33,6 +33,8 @@ I18n.enforce_available_locales = false
FIXTURE_LOAD_PATH = File.expand_path("fixtures", __dir__)
ActionMailer::Base.view_paths = FIXTURE_LOAD_PATH
+ActionMailer::Base.delivery_job = ActionMailer::MailDeliveryJob
+
class ActiveSupport::TestCase
include ActiveSupport::Testing::MethodCallAssertions
diff --git a/actionmailer/test/base_test.rb b/actionmailer/test/base_test.rb
index cbbee9fae8..c07fca5b5e 100644
--- a/actionmailer/test/base_test.rb
+++ b/actionmailer/test/base_test.rb
@@ -90,18 +90,18 @@ class BaseTest < ActiveSupport::TestCase
test "can pass random headers in as a hash to mail" do
hash = { "X-Special-Domain-Specific-Header" => "SecretValue",
- "In-Reply-To" => "1234@mikel.me.com" }
+ "In-Reply-To" => "<1234@mikel.me.com>" }
mail = BaseMailer.welcome(hash)
assert_equal("SecretValue", mail["X-Special-Domain-Specific-Header"].decoded)
- assert_equal("1234@mikel.me.com", mail["In-Reply-To"].decoded)
+ assert_equal("<1234@mikel.me.com>", mail["In-Reply-To"].decoded)
end
test "can pass random headers in as a hash to headers" do
hash = { "X-Special-Domain-Specific-Header" => "SecretValue",
- "In-Reply-To" => "1234@mikel.me.com" }
+ "In-Reply-To" => "<1234@mikel.me.com>" }
mail = BaseMailer.welcome_with_headers(hash)
assert_equal("SecretValue", mail["X-Special-Domain-Specific-Header"].decoded)
- assert_equal("1234@mikel.me.com", mail["In-Reply-To"].decoded)
+ assert_equal("<1234@mikel.me.com>", mail["In-Reply-To"].decoded)
end
# Attachments
@@ -307,6 +307,16 @@ class BaseTest < ActiveSupport::TestCase
assert_equal("HTML Implicit Multipart", email.parts[1].body.encoded)
end
+ test "implicit multipart formats" do
+ email = BaseMailer.implicit_multipart_formats
+ assert_equal(2, email.parts.size)
+ assert_equal("multipart/alternative", email.mime_type)
+ assert_equal("text/plain", email.parts[0].mime_type)
+ assert_equal("Implicit Multipart [:text]", email.parts[0].body.encoded)
+ assert_equal("text/html", email.parts[1].mime_type)
+ assert_equal("Implicit Multipart [:html]", email.parts[1].body.encoded)
+ end
+
test "implicit multipart with sort order" do
order = ["text/html", "text/plain"]
with_default BaseMailer, parts_order: order do
@@ -544,6 +554,12 @@ class BaseTest < ActiveSupport::TestCase
assert_equal("TEXT Implicit Multipart", mail.text_part.body.decoded)
end
+ test "you can specify a different template for multipart render" do
+ mail = BaseMailer.implicit_different_template_with_block("explicit_multipart_templates").deliver
+ assert_equal("HTML Explicit Multipart Templates", mail.html_part.body.decoded)
+ assert_equal("TEXT Explicit Multipart Templates", mail.text_part.body.decoded)
+ end
+
test "should raise if missing template in implicit render" do
assert_raises ActionView::MissingTemplate do
BaseMailer.implicit_different_template("missing_template").deliver_now
@@ -891,22 +907,35 @@ class BaseTest < ActiveSupport::TestCase
end
test "notification for process" do
- begin
- events = []
- ActiveSupport::Notifications.subscribe("process.action_mailer") do |*args|
- events << ActiveSupport::Notifications::Event.new(*args)
- end
+ events = []
+ ActiveSupport::Notifications.subscribe("process.action_mailer") do |*args|
+ events << ActiveSupport::Notifications::Event.new(*args)
+ end
- BaseMailer.welcome(body: "Hello there").deliver_now
+ BaseMailer.welcome(body: "Hello there").deliver_now
- assert_equal 1, events.length
- assert_equal "process.action_mailer", events[0].name
- assert_equal "BaseMailer", events[0].payload[:mailer]
- assert_equal :welcome, events[0].payload[:action]
- assert_equal [{ body: "Hello there" }], events[0].payload[:args]
- ensure
- ActiveSupport::Notifications.unsubscribe "process.action_mailer"
+ assert_equal 1, events.length
+ assert_equal "process.action_mailer", events[0].name
+ assert_equal "BaseMailer", events[0].payload[:mailer]
+ assert_equal :welcome, events[0].payload[:action]
+ assert_equal [{ body: "Hello there" }], events[0].payload[:args]
+ ensure
+ ActiveSupport::Notifications.unsubscribe "process.action_mailer"
+ end
+
+ test "notification for deliver" do
+ events = []
+ ActiveSupport::Notifications.subscribe("deliver.action_mailer") do |*args|
+ events << ActiveSupport::Notifications::Event.new(*args)
end
+
+ BaseMailer.welcome(body: "Hello there").deliver_now
+
+ assert_equal 1, events.length
+ assert_equal "deliver.action_mailer", events[0].name
+ assert_not_nil events[0].payload[:message_id]
+ ensure
+ ActiveSupport::Notifications.unsubscribe "deliver.action_mailer"
end
private
diff --git a/actionmailer/test/caching_test.rb b/actionmailer/test/caching_test.rb
index 22f310f39f..b658c96ec7 100644
--- a/actionmailer/test/caching_test.rb
+++ b/actionmailer/test/caching_test.rb
@@ -124,7 +124,7 @@ class FunctionalFragmentCachingTest < BaseCachingTest
assert_match expected_body, email.body.encoded
assert_match expected_body,
- @store.read("views/caching_mailer/fragment_cache:#{template_digest("caching_mailer/fragment_cache")}/caching")
+ @store.read("views/caching_mailer/fragment_cache:#{template_digest("caching_mailer/fragment_cache", "html")}/caching")
end
def test_fragment_caching_in_partials
@@ -133,7 +133,7 @@ class FunctionalFragmentCachingTest < BaseCachingTest
assert_match(expected_body, email.body.encoded)
assert_match(expected_body,
- @store.read("views/caching_mailer/_partial:#{template_digest("caching_mailer/_partial")}/caching"))
+ @store.read("views/caching_mailer/_partial:#{template_digest("caching_mailer/_partial", "html")}/caching"))
end
def test_skip_fragment_cache_digesting
@@ -183,15 +183,15 @@ class FunctionalFragmentCachingTest < BaseCachingTest
end
assert_equal "caching_mailer", payload[:mailer]
- assert_equal [ :views, "caching_mailer/fragment_cache:#{template_digest("caching_mailer/fragment_cache")}", :caching ], payload[:key]
+ assert_equal [ :views, "caching_mailer/fragment_cache:#{template_digest("caching_mailer/fragment_cache", "html")}", :caching ], payload[:key]
ensure
@mailer.enable_fragment_cache_logging = true
end
private
- def template_digest(name)
- ActionView::Digestor.digest(name: name, finder: @mailer.lookup_context)
+ def template_digest(name, format)
+ ActionView::Digestor.digest(name: name, format: format, finder: @mailer.lookup_context)
end
end
diff --git a/actionmailer/test/fixtures/base_mailer/implicit_multipart_formats.html.erb b/actionmailer/test/fixtures/base_mailer/implicit_multipart_formats.html.erb
new file mode 100644
index 0000000000..0179b070b8
--- /dev/null
+++ b/actionmailer/test/fixtures/base_mailer/implicit_multipart_formats.html.erb
@@ -0,0 +1 @@
+Implicit Multipart <%= formats.inspect %> \ No newline at end of file
diff --git a/actionmailer/test/fixtures/base_mailer/implicit_multipart_formats.text.erb b/actionmailer/test/fixtures/base_mailer/implicit_multipart_formats.text.erb
new file mode 100644
index 0000000000..0179b070b8
--- /dev/null
+++ b/actionmailer/test/fixtures/base_mailer/implicit_multipart_formats.text.erb
@@ -0,0 +1 @@
+Implicit Multipart <%= formats.inspect %> \ No newline at end of file
diff --git a/actionmailer/test/legacy_delivery_job_test.rb b/actionmailer/test/legacy_delivery_job_test.rb
new file mode 100644
index 0000000000..3a3872df47
--- /dev/null
+++ b/actionmailer/test/legacy_delivery_job_test.rb
@@ -0,0 +1,83 @@
+# frozen_string_literal: true
+
+require "abstract_unit"
+require "active_job"
+require "mailers/params_mailer"
+require "mailers/delayed_mailer"
+
+class LegacyDeliveryJobTest < ActiveSupport::TestCase
+ include ActiveJob::TestHelper
+
+ class LegacyDeliveryJob < ActionMailer::DeliveryJob
+ end
+
+ setup do
+ @previous_logger = ActiveJob::Base.logger
+ ActiveJob::Base.logger = Logger.new(nil)
+
+ @previous_delivery_method = ActionMailer::Base.delivery_method
+ ActionMailer::Base.delivery_method = :test
+
+ @previous_deliver_later_queue_name = ActionMailer::Base.deliver_later_queue_name
+ ActionMailer::Base.deliver_later_queue_name = :test_queue
+ end
+
+ teardown do
+ ActiveJob::Base.logger = @previous_logger
+ ParamsMailer.deliveries.clear
+
+ ActionMailer::Base.delivery_method = @previous_delivery_method
+ ActionMailer::Base.deliver_later_queue_name = @previous_deliver_later_queue_name
+ end
+
+ test "should send parameterized mail correctly" do
+ mail = ParamsMailer.with(inviter: "david@basecamp.com", invitee: "jason@basecamp.com").invitation
+ args = [
+ "ParamsMailer",
+ "invitation",
+ "deliver_now",
+ { inviter: "david@basecamp.com", invitee: "jason@basecamp.com" },
+ ]
+
+ with_delivery_job(LegacyDeliveryJob) do
+ assert_deprecated do
+ assert_performed_with(job: ActionMailer::Parameterized::DeliveryJob, args: args) do
+ mail.deliver_later
+ end
+ end
+ end
+ end
+
+ test "should send mail correctly" do
+ mail = DelayedMailer.test_message(1, 2, 3)
+ args = [
+ "DelayedMailer",
+ "test_message",
+ "deliver_now",
+ 1,
+ 2,
+ 3,
+ ]
+
+ with_delivery_job(LegacyDeliveryJob) do
+ assert_deprecated do
+ assert_performed_with(job: LegacyDeliveryJob, args: args) do
+ mail.deliver_later
+ end
+ end
+ end
+ end
+
+ private
+
+ def with_delivery_job(job)
+ old_params_delivery_job = ParamsMailer.delivery_job
+ old_regular_delivery_job = DelayedMailer.delivery_job
+ ParamsMailer.delivery_job = job
+ DelayedMailer.delivery_job = job
+ yield
+ ensure
+ ParamsMailer.delivery_job = old_params_delivery_job
+ DelayedMailer.delivery_job = old_regular_delivery_job
+ end
+end
diff --git a/actionmailer/test/log_subscriber_test.rb b/actionmailer/test/log_subscriber_test.rb
index 7686fd10c9..f09f1997c0 100644
--- a/actionmailer/test/log_subscriber_test.rb
+++ b/actionmailer/test/log_subscriber_test.rb
@@ -24,11 +24,11 @@ class AMLogSubscriberTest < ActionMailer::TestCase
end
def test_deliver_is_notified
- BaseMailer.welcome.deliver_now
+ BaseMailer.welcome(message_id: "123@abc").deliver_now
wait
assert_equal(1, @logger.logged(:info).size)
- assert_match(/Sent mail to system@test\.lindsaar\.net/, @logger.logged(:info).first)
+ assert_match(/Delivered mail 123@abc/, @logger.logged(:info).first)
assert_equal(2, @logger.logged(:debug).size)
assert_match(/BaseMailer#welcome: processed outbound mail in [\d.]+ms/, @logger.logged(:debug).first)
@@ -38,11 +38,11 @@ class AMLogSubscriberTest < ActionMailer::TestCase
end
def test_deliver_message_when_perform_deliveries_is_false
- BaseMailer.welcome_without_deliveries.deliver_now
+ BaseMailer.welcome_without_deliveries(message_id: "123@abc").deliver_now
wait
assert_equal(1, @logger.logged(:info).size)
- assert_match("Skipped sending mail to system@test.lindsaar.net as `perform_deliveries` is false", @logger.logged(:info).first)
+ assert_match("Skipped delivery of mail 123@abc as `perform_deliveries` is false", @logger.logged(:info).first)
assert_equal(2, @logger.logged(:debug).size)
assert_match(/BaseMailer#welcome_without_deliveries: processed outbound mail in [\d.]+ms/, @logger.logged(:debug).first)
@@ -53,7 +53,9 @@ class AMLogSubscriberTest < ActionMailer::TestCase
def test_receive_is_notified
fixture = File.read(File.expand_path("fixtures/raw_email", __dir__))
- TestMailer.receive(fixture)
+ assert_deprecated do
+ TestMailer.receive(fixture)
+ end
wait
assert_equal(1, @logger.logged(:info).size)
assert_match(/Received mail/, @logger.logged(:info).first)
diff --git a/actionmailer/test/mailers/base_mailer.rb b/actionmailer/test/mailers/base_mailer.rb
index a3101207dc..6bd58304e2 100644
--- a/actionmailer/test/mailers/base_mailer.rb
+++ b/actionmailer/test/mailers/base_mailer.rb
@@ -21,8 +21,8 @@ class BaseMailer < ActionMailer::Base
mail(template_name: "welcome", template_path: path)
end
- def welcome_without_deliveries
- mail(template_name: "welcome")
+ def welcome_without_deliveries(hash = {})
+ mail({ template_name: "welcome" }.merge!(hash))
mail.perform_deliveries = false
end
@@ -62,6 +62,10 @@ class BaseMailer < ActionMailer::Base
mail(hash)
end
+ def implicit_multipart_formats(hash = {})
+ mail(hash)
+ end
+
def implicit_with_locale(hash = {})
mail(hash)
end
@@ -111,6 +115,13 @@ class BaseMailer < ActionMailer::Base
mail(template_name: template_name)
end
+ def implicit_different_template_with_block(template_name = "")
+ mail(template_name: template_name) do |format|
+ format.text
+ format.html
+ end
+ end
+
def explicit_different_template(template_name = "")
mail do |format|
format.text { render template: "#{mailer_name}/#{template_name}" }
diff --git a/actionmailer/test/message_delivery_test.rb b/actionmailer/test/message_delivery_test.rb
index f8dcb3f4ba..46260f6414 100644
--- a/actionmailer/test/message_delivery_test.rb
+++ b/actionmailer/test/message_delivery_test.rb
@@ -64,20 +64,20 @@ class MessageDeliveryTest < ActiveSupport::TestCase
end
test "should enqueue the email with :deliver_now delivery method" do
- assert_performed_with(job: ActionMailer::DeliveryJob, args: ["DelayedMailer", "test_message", "deliver_now", 1, 2, 3]) do
+ assert_performed_with(job: ActionMailer::MailDeliveryJob, args: ["DelayedMailer", "test_message", "deliver_now", args: [1, 2, 3]]) do
@mail.deliver_later
end
end
test "should enqueue the email with :deliver_now! delivery method" do
- assert_performed_with(job: ActionMailer::DeliveryJob, args: ["DelayedMailer", "test_message", "deliver_now!", 1, 2, 3]) do
+ assert_performed_with(job: ActionMailer::MailDeliveryJob, args: ["DelayedMailer", "test_message", "deliver_now!", args: [1, 2, 3]]) do
@mail.deliver_later!
end
end
test "should enqueue a delivery with a delay" do
travel_to Time.new(2004, 11, 24, 01, 04, 44) do
- assert_performed_with(job: ActionMailer::DeliveryJob, at: Time.current + 10.minutes, args: ["DelayedMailer", "test_message", "deliver_now", 1, 2, 3]) do
+ assert_performed_with(job: ActionMailer::MailDeliveryJob, at: Time.current + 10.minutes, args: ["DelayedMailer", "test_message", "deliver_now", args: [1, 2, 3]]) do
@mail.deliver_later wait: 10.minutes
end
end
@@ -85,13 +85,13 @@ class MessageDeliveryTest < ActiveSupport::TestCase
test "should enqueue a delivery at a specific time" do
later_time = Time.current + 1.hour
- assert_performed_with(job: ActionMailer::DeliveryJob, at: later_time, args: ["DelayedMailer", "test_message", "deliver_now", 1, 2, 3]) do
+ assert_performed_with(job: ActionMailer::MailDeliveryJob, at: later_time, args: ["DelayedMailer", "test_message", "deliver_now", args: [1, 2, 3]]) do
@mail.deliver_later wait_until: later_time
end
end
test "should enqueue the job on the correct queue" do
- assert_performed_with(job: ActionMailer::DeliveryJob, args: ["DelayedMailer", "test_message", "deliver_now", 1, 2, 3], queue: "test_queue") do
+ assert_performed_with(job: ActionMailer::MailDeliveryJob, args: ["DelayedMailer", "test_message", "deliver_now", args: [1, 2, 3]], queue: "test_queue") do
@mail.deliver_later
end
end
@@ -100,17 +100,17 @@ class MessageDeliveryTest < ActiveSupport::TestCase
old_delivery_job = DelayedMailer.delivery_job
DelayedMailer.delivery_job = DummyJob
- assert_performed_with(job: DummyJob, args: ["DelayedMailer", "test_message", "deliver_now", 1, 2, 3]) do
+ assert_performed_with(job: DummyJob, args: ["DelayedMailer", "test_message", "deliver_now", args: [1, 2, 3]]) do
@mail.deliver_later
end
DelayedMailer.delivery_job = old_delivery_job
end
- class DummyJob < ActionMailer::DeliveryJob; end
+ class DummyJob < ActionMailer::MailDeliveryJob; end
test "can override the queue when enqueuing mail" do
- assert_performed_with(job: ActionMailer::DeliveryJob, args: ["DelayedMailer", "test_message", "deliver_now", 1, 2, 3], queue: "another_queue") do
+ assert_performed_with(job: ActionMailer::MailDeliveryJob, args: ["DelayedMailer", "test_message", "deliver_now", args: [1, 2, 3]], queue: "another_queue") do
@mail.deliver_later(queue: :another_queue)
end
end
diff --git a/actionmailer/test/parameterized_test.rb b/actionmailer/test/parameterized_test.rb
index d3b34fc3e3..7dd6156744 100644
--- a/actionmailer/test/parameterized_test.rb
+++ b/actionmailer/test/parameterized_test.rb
@@ -7,6 +7,9 @@ require "mailers/params_mailer"
class ParameterizedTest < ActiveSupport::TestCase
include ActiveJob::TestHelper
+ class DummyDeliveryJob < ActionMailer::MailDeliveryJob
+ end
+
setup do
@previous_logger = ActiveJob::Base.logger
ActiveJob::Base.logger = Logger.new(nil)
@@ -35,7 +38,14 @@ class ParameterizedTest < ActiveSupport::TestCase
end
test "enqueue the email with params" do
- assert_performed_with(job: ActionMailer::Parameterized::DeliveryJob, args: ["ParamsMailer", "invitation", "deliver_now", { inviter: "david@basecamp.com", invitee: "jason@basecamp.com" } ]) do
+ args = [
+ "ParamsMailer",
+ "invitation",
+ "deliver_now",
+ params: { inviter: "david@basecamp.com", invitee: "jason@basecamp.com" },
+ args: [],
+ ]
+ assert_performed_with(job: ActionMailer::MailDeliveryJob, args: args) do
@mail.deliver_later
end
end
@@ -55,15 +65,28 @@ class ParameterizedTest < ActiveSupport::TestCase
end
test "should enqueue a parameterized request with the correct delivery job" do
- old_delivery_job = ParamsMailer.parameterized_delivery_job
- ParamsMailer.parameterized_delivery_job = ParameterizedDummyJob
-
- assert_performed_with(job: ParameterizedDummyJob, args: ["ParamsMailer", "invitation", "deliver_now", { inviter: "david@basecamp.com", invitee: "jason@basecamp.com" } ]) do
- @mail.deliver_later
+ args = [
+ "ParamsMailer",
+ "invitation",
+ "deliver_now",
+ params: { inviter: "david@basecamp.com", invitee: "jason@basecamp.com" },
+ args: [],
+ ]
+
+ with_delivery_job DummyDeliveryJob do
+ assert_performed_with(job: DummyDeliveryJob, args: args) do
+ @mail.deliver_later
+ end
end
-
- ParamsMailer.parameterized_delivery_job = old_delivery_job
end
- class ParameterizedDummyJob < ActionMailer::Parameterized::DeliveryJob; end
+ private
+
+ def with_delivery_job(job)
+ old_delivery_job = ParamsMailer.delivery_job
+ ParamsMailer.delivery_job = job
+ yield
+ ensure
+ ParamsMailer.delivery_job = old_delivery_job
+ end
end
diff --git a/actionmailer/test/test_helper_test.rb b/actionmailer/test/test_helper_test.rb
index d31170706b..60e2389aa8 100644
--- a/actionmailer/test/test_helper_test.rb
+++ b/actionmailer/test/test_helper_test.rb
@@ -24,6 +24,13 @@ class TestHelperMailer < ActionMailer::Base
end
end
+class CustomDeliveryJob < ActionMailer::MailDeliveryJob
+end
+
+class CustomDeliveryMailer < TestHelperMailer
+ self.delivery_job = CustomDeliveryJob
+end
+
class TestHelperMailerTest < ActionMailer::TestCase
include ActiveSupport::Testing::Stream
@@ -69,6 +76,26 @@ class TestHelperMailerTest < ActionMailer::TestCase
end
end
+ def test_assert_emails_with_custom_delivery_job
+ assert_nothing_raised do
+ assert_emails(1) do
+ silence_stream($stdout) do
+ CustomDeliveryMailer.test.deliver_later
+ end
+ end
+ end
+ end
+
+ def test_assert_emails_with_custom_parameterized_delivery_job
+ assert_nothing_raised do
+ assert_emails(1) do
+ silence_stream($stdout) do
+ CustomDeliveryMailer.with(foo: "bar").test_parameter_args.deliver_later
+ end
+ end
+ end
+ end
+
def test_assert_emails_with_enqueued_emails
assert_nothing_raised do
assert_emails 1 do
@@ -201,6 +228,16 @@ class TestHelperMailerTest < ActionMailer::TestCase
assert_match(/2 .* but 1/, error.message)
end
+ def test_assert_enqueued_emails_with_custom_delivery_job
+ assert_nothing_raised do
+ assert_enqueued_emails(1) do
+ silence_stream($stdout) do
+ CustomDeliveryMailer.test.deliver_later
+ end
+ end
+ end
+ end
+
def test_assert_enqueued_emails_too_many_sent
error = assert_raise ActiveSupport::TestCase::Assertion do
assert_enqueued_emails 1 do
@@ -252,6 +289,16 @@ class TestHelperMailerTest < ActionMailer::TestCase
end
end
+ def test_assert_enqueued_email_with_when_mailer_has_custom_delivery_job
+ assert_nothing_raised do
+ assert_enqueued_email_with CustomDeliveryMailer, :test do
+ silence_stream($stdout) do
+ CustomDeliveryMailer.test.deliver_later
+ end
+ end
+ end
+ end
+
def test_assert_enqueued_email_with_with_no_block
assert_nothing_raised do
silence_stream($stdout) do