actionmailer 7.0.8.1 → 7.2.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +15 -114
- data/MIT-LICENSE +1 -1
- data/README.rdoc +2 -2
- data/lib/action_mailer/base.rb +63 -52
- data/lib/action_mailer/callbacks.rb +31 -0
- data/lib/action_mailer/delivery_methods.rb +4 -3
- data/lib/action_mailer/deprecator.rb +7 -0
- data/lib/action_mailer/form_builder.rb +37 -0
- data/lib/action_mailer/gem_version.rb +3 -3
- data/lib/action_mailer/inline_preview_interceptor.rb +2 -0
- data/lib/action_mailer/log_subscriber.rb +7 -2
- data/lib/action_mailer/mail_delivery_job.rb +7 -2
- data/lib/action_mailer/mail_helper.rb +13 -3
- data/lib/action_mailer/message_delivery.rb +20 -12
- data/lib/action_mailer/parameterized.rb +12 -8
- data/lib/action_mailer/preview.rb +8 -8
- data/lib/action_mailer/queued_delivery.rb +12 -0
- data/lib/action_mailer/railtie.rb +11 -16
- data/lib/action_mailer/rescuable.rb +2 -0
- data/lib/action_mailer/test_case.rb +9 -4
- data/lib/action_mailer/test_helper.rb +114 -11
- data/lib/action_mailer/version.rb +1 -1
- data/lib/action_mailer.rb +11 -2
- data/lib/rails/generators/mailer/USAGE +12 -8
- data/lib/rails/generators/mailer/templates/mailer.rb.tt +3 -1
- metadata +26 -70
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActionMailer
|
4
|
+
# = Action Mailer Form Builder
|
5
|
+
#
|
6
|
+
# Override the default form builder for all views rendered by this
|
7
|
+
# mailer and any of its descendants. Accepts a subclass of
|
8
|
+
# ActionView::Helpers::FormBuilder.
|
9
|
+
#
|
10
|
+
# While emails typically will not include forms, this can be used
|
11
|
+
# by views that are shared between controllers and mailers.
|
12
|
+
#
|
13
|
+
# For more information, see +ActionController::FormBuilder+.
|
14
|
+
module FormBuilder
|
15
|
+
extend ActiveSupport::Concern
|
16
|
+
|
17
|
+
included do
|
18
|
+
class_attribute :_default_form_builder, instance_accessor: false
|
19
|
+
end
|
20
|
+
|
21
|
+
module ClassMethods
|
22
|
+
# Set the form builder to be used as the default for all forms
|
23
|
+
# in the views rendered by this mailer and its subclasses.
|
24
|
+
#
|
25
|
+
# ==== Parameters
|
26
|
+
# * <tt>builder</tt> - Default form builder, an instance of ActionView::Helpers::FormBuilder
|
27
|
+
def default_form_builder(builder)
|
28
|
+
self._default_form_builder = builder
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# Default form builder for the mailer
|
33
|
+
def default_form_builder
|
34
|
+
self.class._default_form_builder
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -1,15 +1,15 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module ActionMailer
|
4
|
-
# Returns the currently loaded version of Action Mailer as a
|
4
|
+
# Returns the currently loaded version of Action Mailer as a +Gem::Version+.
|
5
5
|
def self.gem_version
|
6
6
|
Gem::Version.new VERSION::STRING
|
7
7
|
end
|
8
8
|
|
9
9
|
module VERSION
|
10
10
|
MAJOR = 7
|
11
|
-
MINOR =
|
12
|
-
TINY =
|
11
|
+
MINOR = 2
|
12
|
+
TINY = 2
|
13
13
|
PRE = "1"
|
14
14
|
|
15
15
|
STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
|
@@ -3,6 +3,8 @@
|
|
3
3
|
require "base64"
|
4
4
|
|
5
5
|
module ActionMailer
|
6
|
+
# = Action Mailer \InlinePreviewInterceptor
|
7
|
+
#
|
6
8
|
# Implements a mailer preview interceptor that converts image tag src attributes
|
7
9
|
# that use inline cid: style URLs to data: style URLs so that they are visible
|
8
10
|
# when previewing an HTML email in a web browser.
|
@@ -3,14 +3,17 @@
|
|
3
3
|
require "active_support/log_subscriber"
|
4
4
|
|
5
5
|
module ActionMailer
|
6
|
+
# = Action Mailer \LogSubscriber
|
7
|
+
#
|
6
8
|
# Implements the ActiveSupport::LogSubscriber for logging notifications when
|
7
9
|
# email is delivered or received.
|
8
10
|
class LogSubscriber < ActiveSupport::LogSubscriber
|
9
11
|
# An email was delivered.
|
10
12
|
def deliver(event)
|
11
13
|
info do
|
12
|
-
|
13
|
-
|
14
|
+
if exception = event.payload[:exception_object]
|
15
|
+
"Failed delivery of mail #{event.payload[:message_id]} error_class=#{exception.class} error_message=#{exception.message.inspect}"
|
16
|
+
elsif event.payload[:perform_deliveries]
|
14
17
|
"Delivered mail #{event.payload[:message_id]} (#{event.duration.round(1)}ms)"
|
15
18
|
else
|
16
19
|
"Skipped delivery of mail #{event.payload[:message_id]} as `perform_deliveries` is false"
|
@@ -19,6 +22,7 @@ module ActionMailer
|
|
19
22
|
|
20
23
|
debug { event.payload[:mail] }
|
21
24
|
end
|
25
|
+
subscribe_log_level :deliver, :debug
|
22
26
|
|
23
27
|
# An email was generated.
|
24
28
|
def process(event)
|
@@ -28,6 +32,7 @@ module ActionMailer
|
|
28
32
|
"#{mailer}##{action}: processed outbound mail in #{event.duration.round(1)}ms"
|
29
33
|
end
|
30
34
|
end
|
35
|
+
subscribe_log_level :process, :debug
|
31
36
|
|
32
37
|
# Use the logger configured for ActionMailer::Base.
|
33
38
|
def logger
|
@@ -3,13 +3,18 @@
|
|
3
3
|
require "active_job"
|
4
4
|
|
5
5
|
module ActionMailer
|
6
|
-
#
|
6
|
+
# = Action Mailer \MailDeliveryJob
|
7
|
+
#
|
8
|
+
# The +ActionMailer::MailDeliveryJob+ class is used when you
|
7
9
|
# want to send emails outside of the request-response cycle. It supports
|
8
10
|
# sending either parameterized or normal mail.
|
9
11
|
#
|
10
12
|
# Exceptions are rescued and handled by the mailer class.
|
11
13
|
class MailDeliveryJob < ActiveJob::Base # :nodoc:
|
12
|
-
queue_as
|
14
|
+
queue_as do
|
15
|
+
mailer_class = arguments.first.constantize
|
16
|
+
mailer_class.deliver_later_queue_name
|
17
|
+
end
|
13
18
|
|
14
19
|
rescue_from StandardError, with: :handle_exception_with_mailer_class
|
15
20
|
|
@@ -1,6 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module ActionMailer
|
4
|
+
# = Action Mailer \MailHelper
|
5
|
+
#
|
4
6
|
# Provides helper methods for ActionMailer::Base that can be used for easily
|
5
7
|
# formatting messages, accessing mailer or message instances, and the
|
6
8
|
# attachments list.
|
@@ -23,10 +25,18 @@ module ActionMailer
|
|
23
25
|
}.join("\n\n")
|
24
26
|
|
25
27
|
# Make list points stand on their own line
|
26
|
-
|
27
|
-
formatted.
|
28
|
+
output = +""
|
29
|
+
splits = formatted.split(/(\*+|\#+)/)
|
30
|
+
while line = splits.shift
|
31
|
+
if line.start_with?("*", "#") && splits.first&.start_with?(" ")
|
32
|
+
output.chomp!(" ") while output.end_with?(" ")
|
33
|
+
output << " #{line} #{splits.shift.strip}\n"
|
34
|
+
else
|
35
|
+
output << line
|
36
|
+
end
|
37
|
+
end
|
28
38
|
|
29
|
-
|
39
|
+
output
|
30
40
|
end
|
31
41
|
|
32
42
|
# Access the mailer instance.
|
@@ -3,11 +3,13 @@
|
|
3
3
|
require "delegate"
|
4
4
|
|
5
5
|
module ActionMailer
|
6
|
-
#
|
6
|
+
# = Action Mailer \MessageDelivery
|
7
|
+
#
|
8
|
+
# The +ActionMailer::MessageDelivery+ class is used by
|
7
9
|
# ActionMailer::Base when creating a new mailer.
|
8
10
|
# <tt>MessageDelivery</tt> is a wrapper (+Delegator+ subclass) around a lazy
|
9
|
-
# created
|
10
|
-
#
|
11
|
+
# created +Mail::Message+. You can get direct access to the
|
12
|
+
# +Mail::Message+, deliver the email or schedule the email to be sent
|
11
13
|
# through Active Job.
|
12
14
|
#
|
13
15
|
# Notifier.welcome(User.first) # an ActionMailer::MessageDelivery object
|
@@ -62,9 +64,10 @@ module ActionMailer
|
|
62
64
|
# * <tt>:queue</tt> - Enqueue the email on the specified queue
|
63
65
|
# * <tt>:priority</tt> - Enqueues the email with the specified priority
|
64
66
|
#
|
65
|
-
# By default, the email will be enqueued using
|
66
|
-
#
|
67
|
-
# +
|
67
|
+
# By default, the email will be enqueued using ActionMailer::MailDeliveryJob on
|
68
|
+
# the default queue. Mailer classes can customize the queue name used for the default
|
69
|
+
# job by assigning a +deliver_later_queue_name+ class variable, or provide a custom job
|
70
|
+
# by assigning a +delivery_job+. When a custom job is used, it controls the queue name.
|
68
71
|
#
|
69
72
|
# class AccountRegistrationMailer < ApplicationMailer
|
70
73
|
# self.delivery_job = RegistrationDeliveryJob
|
@@ -88,9 +91,10 @@ module ActionMailer
|
|
88
91
|
# * <tt>:queue</tt> - Enqueue the email on the specified queue.
|
89
92
|
# * <tt>:priority</tt> - Enqueues the email with the specified priority
|
90
93
|
#
|
91
|
-
# By default, the email will be enqueued using
|
92
|
-
#
|
93
|
-
# +
|
94
|
+
# By default, the email will be enqueued using ActionMailer::MailDeliveryJob on
|
95
|
+
# the default queue. Mailer classes can customize the queue name used for the default
|
96
|
+
# job by assigning a +deliver_later_queue_name+ class variable, or provide a custom job
|
97
|
+
# by assigning a +delivery_job+. When a custom job is used, it controls the queue name.
|
94
98
|
#
|
95
99
|
# class AccountRegistrationMailer < ApplicationMailer
|
96
100
|
# self.delivery_job = RegistrationDeliveryJob
|
@@ -106,7 +110,9 @@ module ActionMailer
|
|
106
110
|
#
|
107
111
|
def deliver_now!
|
108
112
|
processed_mailer.handle_exceptions do
|
109
|
-
|
113
|
+
processed_mailer.run_callbacks(:deliver) do
|
114
|
+
message.deliver!
|
115
|
+
end
|
110
116
|
end
|
111
117
|
end
|
112
118
|
|
@@ -116,13 +122,15 @@ module ActionMailer
|
|
116
122
|
#
|
117
123
|
def deliver_now
|
118
124
|
processed_mailer.handle_exceptions do
|
119
|
-
|
125
|
+
processed_mailer.run_callbacks(:deliver) do
|
126
|
+
message.deliver
|
127
|
+
end
|
120
128
|
end
|
121
129
|
end
|
122
130
|
|
123
131
|
private
|
124
132
|
# Returns the processed Mailer instance. We keep this instance
|
125
|
-
# on hand so we can delegate exception handling to it.
|
133
|
+
# on hand so we can run callbacks and delegate exception handling to it.
|
126
134
|
def processed_mailer
|
127
135
|
@processed_mailer ||= @mailer_class.new.tap do |mailer|
|
128
136
|
mailer.process @action, *@args
|
@@ -1,6 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module ActionMailer
|
4
|
+
# = Action Mailer \Parameterized
|
5
|
+
#
|
4
6
|
# Provides the option to parameterize mailers in order to share instance variable
|
5
7
|
# setup, processing, and common headers.
|
6
8
|
#
|
@@ -88,7 +90,11 @@ module ActionMailer
|
|
88
90
|
extend ActiveSupport::Concern
|
89
91
|
|
90
92
|
included do
|
91
|
-
|
93
|
+
attr_writer :params
|
94
|
+
|
95
|
+
def params
|
96
|
+
@params ||= {}
|
97
|
+
end
|
92
98
|
end
|
93
99
|
|
94
100
|
module ClassMethods
|
@@ -108,14 +114,13 @@ module ActionMailer
|
|
108
114
|
end
|
109
115
|
|
110
116
|
private
|
111
|
-
def method_missing(method_name,
|
112
|
-
if @mailer.action_methods.include?(method_name.
|
113
|
-
ActionMailer::Parameterized::MessageDelivery.new(@mailer, method_name, @params,
|
117
|
+
def method_missing(method_name, ...)
|
118
|
+
if @mailer.action_methods.include?(method_name.name)
|
119
|
+
ActionMailer::Parameterized::MessageDelivery.new(@mailer, method_name, @params, ...)
|
114
120
|
else
|
115
121
|
super
|
116
122
|
end
|
117
123
|
end
|
118
|
-
ruby2_keywords(:method_missing)
|
119
124
|
|
120
125
|
def respond_to_missing?(method, include_all = false)
|
121
126
|
@mailer.respond_to?(method, include_all)
|
@@ -123,11 +128,10 @@ module ActionMailer
|
|
123
128
|
end
|
124
129
|
|
125
130
|
class MessageDelivery < ActionMailer::MessageDelivery # :nodoc:
|
126
|
-
def initialize(mailer_class, action, params,
|
127
|
-
super(mailer_class, action,
|
131
|
+
def initialize(mailer_class, action, params, ...)
|
132
|
+
super(mailer_class, action, ...)
|
128
133
|
@params = params
|
129
134
|
end
|
130
|
-
ruby2_keywords(:initialize)
|
131
135
|
|
132
136
|
private
|
133
137
|
def processed_mailer
|
@@ -7,11 +7,11 @@ module ActionMailer
|
|
7
7
|
extend ActiveSupport::Concern
|
8
8
|
|
9
9
|
included do
|
10
|
-
#
|
10
|
+
# Add the location of mailer previews through app configuration:
|
11
11
|
#
|
12
|
-
# config.action_mailer.
|
12
|
+
# config.action_mailer.preview_paths << "#{Rails.root}/lib/mailer_previews"
|
13
13
|
#
|
14
|
-
mattr_accessor :
|
14
|
+
mattr_accessor :preview_paths, instance_writer: false, default: []
|
15
15
|
|
16
16
|
# Enable or disable mailer previews through app configuration:
|
17
17
|
#
|
@@ -79,7 +79,7 @@ module ActionMailer
|
|
79
79
|
# Returns all mailer preview classes.
|
80
80
|
def all
|
81
81
|
load_previews if descendants.empty?
|
82
|
-
descendants
|
82
|
+
descendants.sort_by { |mailer| mailer.name.titleize }
|
83
83
|
end
|
84
84
|
|
85
85
|
# Returns the mail object for the given email name. The registered preview
|
@@ -119,13 +119,13 @@ module ActionMailer
|
|
119
119
|
|
120
120
|
private
|
121
121
|
def load_previews
|
122
|
-
|
123
|
-
Dir["#{preview_path}/**/*_preview.rb"].sort.each { |file|
|
122
|
+
preview_paths.each do |preview_path|
|
123
|
+
Dir["#{preview_path}/**/*_preview.rb"].sort.each { |file| require file }
|
124
124
|
end
|
125
125
|
end
|
126
126
|
|
127
|
-
def
|
128
|
-
Base.
|
127
|
+
def preview_paths
|
128
|
+
Base.preview_paths
|
129
129
|
end
|
130
130
|
|
131
131
|
def show_previews
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActionMailer
|
4
|
+
module QueuedDelivery
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
class_attribute :delivery_job, default: ::ActionMailer::MailDeliveryJob
|
9
|
+
class_attribute :deliver_later_queue_name, default: :mailers
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -8,8 +8,13 @@ require "abstract_controller/railties/routes_helpers"
|
|
8
8
|
module ActionMailer
|
9
9
|
class Railtie < Rails::Railtie # :nodoc:
|
10
10
|
config.action_mailer = ActiveSupport::OrderedOptions.new
|
11
|
+
config.action_mailer.preview_paths = []
|
11
12
|
config.eager_load_namespaces << ActionMailer
|
12
13
|
|
14
|
+
initializer "action_mailer.deprecator", before: :load_environment_config do |app|
|
15
|
+
app.deprecators[:action_mailer] = ActionMailer.deprecator
|
16
|
+
end
|
17
|
+
|
13
18
|
initializer "action_mailer.logger" do
|
14
19
|
ActiveSupport.on_load(:action_mailer) { self.logger ||= Rails.logger }
|
15
20
|
end
|
@@ -23,10 +28,7 @@ module ActionMailer
|
|
23
28
|
options.stylesheets_dir ||= paths["public/stylesheets"].first
|
24
29
|
options.show_previews = Rails.env.development? if options.show_previews.nil?
|
25
30
|
options.cache_store ||= Rails.cache
|
26
|
-
|
27
|
-
if options.show_previews
|
28
|
-
options.preview_path ||= defined?(Rails.root) ? "#{Rails.root}/test/mailers/previews" : nil
|
29
|
-
end
|
31
|
+
options.preview_paths |= ["#{Rails.root}/test/mailers/previews"]
|
30
32
|
|
31
33
|
# make sure readers methods get compiled
|
32
34
|
options.asset_host ||= app.config.asset_host
|
@@ -40,6 +42,7 @@ module ActionMailer
|
|
40
42
|
register_interceptors(options.delete(:interceptors))
|
41
43
|
register_preview_interceptors(options.delete(:preview_interceptors))
|
42
44
|
register_observers(options.delete(:observers))
|
45
|
+
self.preview_paths |= options[:preview_paths]
|
43
46
|
|
44
47
|
if delivery_job = options.delete(:delivery_job)
|
45
48
|
self.delivery_job = delivery_job.constantize
|
@@ -65,12 +68,9 @@ module ActionMailer
|
|
65
68
|
end
|
66
69
|
end
|
67
70
|
|
68
|
-
initializer "action_mailer.set_autoload_paths" do |app|
|
71
|
+
initializer "action_mailer.set_autoload_paths", before: :set_autoload_paths do |app|
|
69
72
|
options = app.config.action_mailer
|
70
|
-
|
71
|
-
if options.show_previews && options.preview_path
|
72
|
-
ActiveSupport::Dependencies.autoload_paths << options.preview_path
|
73
|
-
end
|
73
|
+
app.config.paths["test/mailers/previews"].concat(options.preview_paths)
|
74
74
|
end
|
75
75
|
|
76
76
|
initializer "action_mailer.compile_config_methods" do
|
@@ -79,18 +79,13 @@ module ActionMailer
|
|
79
79
|
end
|
80
80
|
end
|
81
81
|
|
82
|
-
initializer "action_mailer.eager_load_actions" do
|
83
|
-
ActiveSupport.on_load(:after_initialize) do
|
84
|
-
ActionMailer::Base.descendants.each(&:action_methods) if config.eager_load
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
82
|
config.after_initialize do |app|
|
89
83
|
options = app.config.action_mailer
|
90
84
|
|
91
85
|
if options.show_previews
|
92
86
|
app.routes.prepend do
|
93
|
-
get "/rails/mailers"
|
87
|
+
get "/rails/mailers" => "rails/mailers#index", internal: true
|
88
|
+
get "/rails/mailers/download/*path" => "rails/mailers#download", internal: true
|
94
89
|
get "/rails/mailers/*path" => "rails/mailers#preview", internal: true
|
95
90
|
end
|
96
91
|
end
|
@@ -1,6 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module ActionMailer # :nodoc:
|
4
|
+
# = Action Mailer \Rescuable
|
5
|
+
#
|
4
6
|
# Provides
|
5
7
|
# {rescue_from}[rdoc-ref:ActiveSupport::Rescuable::ClassMethods#rescue_from]
|
6
8
|
# for mailers. Wraps mailer action processing, mail job processing, and mail
|
@@ -74,6 +74,15 @@ module ActionMailer
|
|
74
74
|
end
|
75
75
|
end
|
76
76
|
|
77
|
+
# Reads the fixture file for the given mailer.
|
78
|
+
#
|
79
|
+
# This is useful when testing mailers by being able to write the body of
|
80
|
+
# an email inside a fixture. See the testing guide for a concrete example:
|
81
|
+
# https://guides.rubyonrails.org/testing.html#revenge-of-the-fixtures
|
82
|
+
def read_fixture(action)
|
83
|
+
IO.readlines(File.join(Rails.root, "test", "fixtures", self.class.mailer_class.name.underscore, action))
|
84
|
+
end
|
85
|
+
|
77
86
|
private
|
78
87
|
def initialize_test_deliveries
|
79
88
|
set_delivery_method :test
|
@@ -110,10 +119,6 @@ module ActionMailer
|
|
110
119
|
def encode(subject)
|
111
120
|
Mail::Encodings.q_value_encode(subject, charset)
|
112
121
|
end
|
113
|
-
|
114
|
-
def read_fixture(action)
|
115
|
-
IO.readlines(File.join(Rails.root, "test", "fixtures", self.class.mailer_class.name.underscore, action))
|
116
|
-
end
|
117
122
|
end
|
118
123
|
|
119
124
|
include Behavior
|
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "active_support/core_ext/array/extract_options"
|
3
4
|
require "active_job"
|
4
5
|
|
5
6
|
module ActionMailer
|
@@ -33,10 +34,8 @@ module ActionMailer
|
|
33
34
|
# end
|
34
35
|
def assert_emails(number, &block)
|
35
36
|
if block_given?
|
36
|
-
|
37
|
-
|
38
|
-
new_count = ActionMailer::Base.deliveries.size
|
39
|
-
assert_equal number, new_count - original_count, "#{number} emails expected, but #{new_count - original_count} were sent"
|
37
|
+
diff = capture_emails(&block).length
|
38
|
+
assert_equal number, diff, "#{number} emails expected, but #{diff} were sent"
|
40
39
|
else
|
41
40
|
assert_equal number, ActionMailer::Base.deliveries.size
|
42
41
|
end
|
@@ -94,18 +93,50 @@ module ActionMailer
|
|
94
93
|
end
|
95
94
|
|
96
95
|
# Asserts that a specific email has been enqueued, optionally
|
97
|
-
# matching arguments.
|
96
|
+
# matching arguments and/or params.
|
98
97
|
#
|
99
98
|
# def test_email
|
100
99
|
# ContactMailer.welcome.deliver_later
|
101
100
|
# assert_enqueued_email_with ContactMailer, :welcome
|
102
101
|
# end
|
103
102
|
#
|
103
|
+
# def test_email_with_parameters
|
104
|
+
# ContactMailer.with(greeting: "Hello").welcome.deliver_later
|
105
|
+
# assert_enqueued_email_with ContactMailer, :welcome, args: { greeting: "Hello" }
|
106
|
+
# end
|
107
|
+
#
|
104
108
|
# def test_email_with_arguments
|
105
109
|
# ContactMailer.welcome("Hello", "Goodbye").deliver_later
|
106
110
|
# assert_enqueued_email_with ContactMailer, :welcome, args: ["Hello", "Goodbye"]
|
107
111
|
# end
|
108
112
|
#
|
113
|
+
# def test_email_with_named_arguments
|
114
|
+
# ContactMailer.welcome(greeting: "Hello", farewell: "Goodbye").deliver_later
|
115
|
+
# assert_enqueued_email_with ContactMailer, :welcome, args: [{ greeting: "Hello", farewell: "Goodbye" }]
|
116
|
+
# end
|
117
|
+
#
|
118
|
+
# def test_email_with_parameters_and_arguments
|
119
|
+
# ContactMailer.with(greeting: "Hello").welcome("Cheers", "Goodbye").deliver_later
|
120
|
+
# assert_enqueued_email_with ContactMailer, :welcome, params: { greeting: "Hello" }, args: ["Cheers", "Goodbye"]
|
121
|
+
# end
|
122
|
+
#
|
123
|
+
# def test_email_with_parameters_and_named_arguments
|
124
|
+
# ContactMailer.with(greeting: "Hello").welcome(farewell: "Goodbye").deliver_later
|
125
|
+
# assert_enqueued_email_with ContactMailer, :welcome, params: { greeting: "Hello" }, args: [{farewell: "Goodbye"}]
|
126
|
+
# end
|
127
|
+
#
|
128
|
+
# def test_email_with_parameterized_mailer
|
129
|
+
# ContactMailer.with(greeting: "Hello").welcome.deliver_later
|
130
|
+
# assert_enqueued_email_with ContactMailer.with(greeting: "Hello"), :welcome
|
131
|
+
# end
|
132
|
+
#
|
133
|
+
# def test_email_with_matchers
|
134
|
+
# ContactMailer.with(greeting: "Hello").welcome("Cheers", "Goodbye").deliver_later
|
135
|
+
# assert_enqueued_email_with ContactMailer, :welcome,
|
136
|
+
# params: ->(params) { /hello/i.match?(params[:greeting]) },
|
137
|
+
# args: ->(args) { /cheers/i.match?(args[0]) }
|
138
|
+
# end
|
139
|
+
#
|
109
140
|
# If a block is passed, that block should cause the specified email
|
110
141
|
# to be enqueued.
|
111
142
|
#
|
@@ -123,13 +154,23 @@ module ActionMailer
|
|
123
154
|
# ContactMailer.with(email: 'user@example.com').welcome.deliver_later
|
124
155
|
# end
|
125
156
|
# end
|
126
|
-
def assert_enqueued_email_with(mailer, method, args: nil, queue:
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
[mailer.to_s, method.to_s, "deliver_now", args: Array(args)]
|
157
|
+
def assert_enqueued_email_with(mailer, method, params: nil, args: nil, queue: nil, &block)
|
158
|
+
if mailer.is_a? ActionMailer::Parameterized::Mailer
|
159
|
+
params = mailer.instance_variable_get(:@params)
|
160
|
+
mailer = mailer.instance_variable_get(:@mailer)
|
131
161
|
end
|
132
|
-
|
162
|
+
|
163
|
+
args = Array(args) unless args.is_a?(Proc)
|
164
|
+
queue ||= mailer.deliver_later_queue_name || ActiveJob::Base.default_queue_name
|
165
|
+
|
166
|
+
expected = ->(job_args) do
|
167
|
+
job_kwargs = job_args.extract_options!
|
168
|
+
|
169
|
+
[mailer.to_s, method.to_s, "deliver_now"] == job_args &&
|
170
|
+
params === job_kwargs[:params] && args === job_kwargs[:args]
|
171
|
+
end
|
172
|
+
|
173
|
+
assert_enqueued_with(job: mailer.delivery_job, args: expected, queue: queue.to_s, &block)
|
133
174
|
end
|
134
175
|
|
135
176
|
# Asserts that no emails are enqueued for later delivery.
|
@@ -151,6 +192,68 @@ module ActionMailer
|
|
151
192
|
assert_enqueued_emails 0, &block
|
152
193
|
end
|
153
194
|
|
195
|
+
# Delivers all enqueued emails. If a block is given, delivers all of the emails
|
196
|
+
# that were enqueued throughout the duration of the block. If a block is
|
197
|
+
# not given, delivers all the enqueued emails up to this point in the test.
|
198
|
+
#
|
199
|
+
# def test_deliver_enqueued_emails
|
200
|
+
# deliver_enqueued_emails do
|
201
|
+
# ContactMailer.welcome.deliver_later
|
202
|
+
# end
|
203
|
+
#
|
204
|
+
# assert_emails 1
|
205
|
+
# end
|
206
|
+
#
|
207
|
+
# def test_deliver_enqueued_emails_without_block
|
208
|
+
# ContactMailer.welcome.deliver_later
|
209
|
+
#
|
210
|
+
# deliver_enqueued_emails
|
211
|
+
#
|
212
|
+
# assert_emails 1
|
213
|
+
# end
|
214
|
+
#
|
215
|
+
# If the +:queue+ option is specified,
|
216
|
+
# then only the emails(s) enqueued to a specific queue will be performed.
|
217
|
+
#
|
218
|
+
# def test_deliver_enqueued_emails_with_queue
|
219
|
+
# deliver_enqueued_emails queue: :external_mailers do
|
220
|
+
# CustomerMailer.deliver_later_queue_name = :external_mailers
|
221
|
+
# CustomerMailer.welcome.deliver_later # will be performed
|
222
|
+
# EmployeeMailer.deliver_later_queue_name = :internal_mailers
|
223
|
+
# EmployeeMailer.welcome.deliver_later # will not be performed
|
224
|
+
# end
|
225
|
+
#
|
226
|
+
# assert_emails 1
|
227
|
+
# end
|
228
|
+
#
|
229
|
+
# If the +:at+ option is specified, then only delivers emails enqueued to deliver
|
230
|
+
# immediately or before the given time.
|
231
|
+
def deliver_enqueued_emails(queue: nil, at: nil, &block)
|
232
|
+
perform_enqueued_jobs(only: ->(job) { delivery_job_filter(job) }, queue: queue, at: at, &block)
|
233
|
+
end
|
234
|
+
|
235
|
+
# Returns any emails that are sent in the block.
|
236
|
+
#
|
237
|
+
# def test_emails
|
238
|
+
# emails = capture_emails do
|
239
|
+
# ContactMailer.welcome.deliver_now
|
240
|
+
# end
|
241
|
+
# assert_equal "Hi there", emails.first.subject
|
242
|
+
#
|
243
|
+
# emails = capture_emails do
|
244
|
+
# ContactMailer.welcome.deliver_now
|
245
|
+
# ContactMailer.welcome.deliver_later
|
246
|
+
# end
|
247
|
+
# assert_equal "Hi there", emails.first.subject
|
248
|
+
# end
|
249
|
+
def capture_emails(&block)
|
250
|
+
original_count = ActionMailer::Base.deliveries.size
|
251
|
+
deliver_enqueued_emails(&block)
|
252
|
+
new_count = ActionMailer::Base.deliveries.size
|
253
|
+
diff = new_count - original_count
|
254
|
+
ActionMailer::Base.deliveries.last(diff)
|
255
|
+
end
|
256
|
+
|
154
257
|
private
|
155
258
|
def delivery_job_filter(job)
|
156
259
|
job_class = job.is_a?(Hash) ? job.fetch(:job) : job.class
|