actionmailer 3.2.9 → 6.1.7.6

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of actionmailer might be problematic. Click here for more details.

@@ -1,8 +1,10 @@
1
- require 'abstract_controller/collector'
2
- require 'active_support/core_ext/hash/reverse_merge'
3
- require 'active_support/core_ext/array/extract_options'
1
+ # frozen_string_literal: true
4
2
 
5
- module ActionMailer #:nodoc:
3
+ require "abstract_controller/collector"
4
+ require "active_support/core_ext/hash/reverse_merge"
5
+ require "active_support/core_ext/array/extract_options"
6
+
7
+ module ActionMailer
6
8
  class Collector
7
9
  include AbstractController::Collector
8
10
  attr_reader :responses
@@ -15,13 +17,13 @@ module ActionMailer #:nodoc:
15
17
 
16
18
  def any(*args, &block)
17
19
  options = args.extract_options!
18
- raise "You have to supply at least one format" if args.empty?
20
+ raise ArgumentError, "You have to supply at least one format" if args.empty?
19
21
  args.each { |type| send(type, options.dup, &block) }
20
22
  end
21
23
  alias :all :any
22
24
 
23
- def custom(mime, options={})
24
- options.reverse_merge!(:content_type => mime.to_s)
25
+ def custom(mime, options = {})
26
+ options.reverse_merge!(content_type: mime.to_s)
25
27
  @context.formats = [mime.to_sym]
26
28
  options[:body] = block_given? ? yield : @default_render.call
27
29
  @responses << options
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_job"
4
+
5
+ module ActionMailer
6
+ # The <tt>ActionMailer::DeliveryJob</tt> class is used when you
7
+ # want to send emails outside of the request-response cycle.
8
+ #
9
+ # Exceptions are rescued and handled by the mailer class.
10
+ class DeliveryJob < ActiveJob::Base # :nodoc:
11
+ queue_as { ActionMailer::Base.deliver_later_queue_name }
12
+
13
+ rescue_from StandardError, with: :handle_exception_with_mailer_class
14
+
15
+ before_perform do
16
+ ActiveSupport::Deprecation.warn <<~MSG.squish
17
+ Sending mail with DeliveryJob and Parameterized::DeliveryJob
18
+ is deprecated and will be removed in Rails 7.0.
19
+ Please use MailDeliveryJob instead.
20
+ MSG
21
+ end
22
+
23
+ def perform(mailer, mail_method, delivery_method, *args) #:nodoc:
24
+ mailer.constantize.public_send(mail_method, *args).send(delivery_method)
25
+ end
26
+ ruby2_keywords(:perform) if respond_to?(:ruby2_keywords, true)
27
+
28
+ private
29
+ # "Deserialize" the mailer class name by hand in case another argument
30
+ # (like a Global ID reference) raised DeserializationError.
31
+ def mailer_class
32
+ if mailer = Array(@serialized_arguments).first || Array(arguments).first
33
+ mailer.constantize
34
+ end
35
+ end
36
+
37
+ def handle_exception_with_mailer_class(exception)
38
+ if klass = mailer_class
39
+ klass.handle_exception exception
40
+ else
41
+ raise exception
42
+ end
43
+ end
44
+ end
45
+ end
@@ -1,72 +1,68 @@
1
- require 'tmpdir'
1
+ # frozen_string_literal: true
2
+
3
+ require "tmpdir"
2
4
 
3
5
  module ActionMailer
4
- # This module handles everything related to mail delivery, from registering new
5
- # delivery methods to configuring the mail object to be sent.
6
+ # This module handles everything related to mail delivery, from registering
7
+ # new delivery methods to configuring the mail object to be sent.
6
8
  module DeliveryMethods
7
9
  extend ActiveSupport::Concern
8
10
 
9
11
  included do
10
- class_attribute :delivery_methods, :delivery_method
11
-
12
12
  # Do not make this inheritable, because we always want it to propagate
13
- cattr_accessor :raise_delivery_errors
14
- self.raise_delivery_errors = true
15
-
16
- cattr_accessor :perform_deliveries
17
- self.perform_deliveries = true
13
+ cattr_accessor :raise_delivery_errors, default: true
14
+ cattr_accessor :perform_deliveries, default: true
15
+ cattr_accessor :deliver_later_queue_name, default: :mailers
18
16
 
19
- self.delivery_methods = {}.freeze
20
- self.delivery_method = :smtp
17
+ class_attribute :delivery_methods, default: {}.freeze
18
+ class_attribute :delivery_method, default: :smtp
21
19
 
22
20
  add_delivery_method :smtp, Mail::SMTP,
23
- :address => "localhost",
24
- :port => 25,
25
- :domain => 'localhost.localdomain',
26
- :user_name => nil,
27
- :password => nil,
28
- :authentication => nil,
29
- :enable_starttls_auto => true
21
+ address: "localhost",
22
+ port: 25,
23
+ domain: "localhost.localdomain",
24
+ user_name: nil,
25
+ password: nil,
26
+ authentication: nil,
27
+ enable_starttls_auto: true
30
28
 
31
29
  add_delivery_method :file, Mail::FileDelivery,
32
- :location => defined?(Rails.root) ? "#{Rails.root}/tmp/mails" : "#{Dir.tmpdir}/mails"
30
+ location: defined?(Rails.root) ? "#{Rails.root}/tmp/mails" : "#{Dir.tmpdir}/mails"
33
31
 
34
32
  add_delivery_method :sendmail, Mail::Sendmail,
35
- :location => '/usr/sbin/sendmail',
36
- :arguments => '-i -t'
33
+ location: "/usr/sbin/sendmail",
34
+ arguments: "-i"
37
35
 
38
36
  add_delivery_method :test, Mail::TestMailer
39
37
  end
40
38
 
39
+ # Helpers for creating and wrapping delivery behavior, used by DeliveryMethods.
41
40
  module ClassMethods
42
41
  # Provides a list of emails that have been delivered by Mail::TestMailer
43
- delegate :deliveries, :deliveries=, :to => Mail::TestMailer
42
+ delegate :deliveries, :deliveries=, to: Mail::TestMailer
44
43
 
45
- # Adds a new delivery method through the given class using the given symbol
46
- # as alias and the default options supplied:
47
- #
48
- # Example:
44
+ # Adds a new delivery method through the given class using the given
45
+ # symbol as alias and the default options supplied.
49
46
  #
50
47
  # add_delivery_method :sendmail, Mail::Sendmail,
51
- # :location => '/usr/sbin/sendmail',
52
- # :arguments => '-i -t'
53
- #
54
- def add_delivery_method(symbol, klass, default_options={})
48
+ # location: '/usr/sbin/sendmail',
49
+ # arguments: '-i'
50
+ def add_delivery_method(symbol, klass, default_options = {})
55
51
  class_attribute(:"#{symbol}_settings") unless respond_to?(:"#{symbol}_settings")
56
- send(:"#{symbol}_settings=", default_options)
52
+ public_send(:"#{symbol}_settings=", default_options)
57
53
  self.delivery_methods = delivery_methods.merge(symbol.to_sym => klass).freeze
58
54
  end
59
55
 
60
- def wrap_delivery_behavior(mail, method=nil) #:nodoc:
61
- method ||= self.delivery_method
56
+ def wrap_delivery_behavior(mail, method = nil, options = nil) # :nodoc:
57
+ method ||= delivery_method
62
58
  mail.delivery_handler = self
63
59
 
64
60
  case method
65
61
  when NilClass
66
62
  raise "Delivery method cannot be nil"
67
63
  when Symbol
68
- if klass = delivery_methods[method.to_sym]
69
- mail.delivery_method(klass, send(:"#{method}_settings"))
64
+ if klass = delivery_methods[method]
65
+ mail.delivery_method(klass, (send(:"#{method}_settings") || {}).merge(options || {}))
70
66
  else
71
67
  raise "Invalid delivery method #{method.inspect}"
72
68
  end
@@ -79,7 +75,7 @@ module ActionMailer
79
75
  end
80
76
  end
81
77
 
82
- def wrap_delivery_behavior!(*args) #:nodoc:
78
+ def wrap_delivery_behavior!(*args) # :nodoc:
83
79
  self.class.wrap_delivery_behavior(message, *args)
84
80
  end
85
81
  end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActionMailer
4
+ # Returns the version of the currently loaded Action Mailer as a <tt>Gem::Version</tt>.
5
+ def self.gem_version
6
+ Gem::Version.new VERSION::STRING
7
+ end
8
+
9
+ module VERSION
10
+ MAJOR = 6
11
+ MINOR = 1
12
+ TINY = 7
13
+ PRE = "6"
14
+
15
+ STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
16
+ end
17
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "base64"
4
+
5
+ module ActionMailer
6
+ # Implements a mailer preview interceptor that converts image tag src attributes
7
+ # that use inline cid: style URLs to data: style URLs so that they are visible
8
+ # when previewing an HTML email in a web browser.
9
+ #
10
+ # This interceptor is enabled by default. To disable it, delete it from the
11
+ # <tt>ActionMailer::Base.preview_interceptors</tt> array:
12
+ #
13
+ # ActionMailer::Base.preview_interceptors.delete(ActionMailer::InlinePreviewInterceptor)
14
+ #
15
+ class InlinePreviewInterceptor
16
+ PATTERN = /src=(?:"cid:[^"]+"|'cid:[^']+')/i
17
+
18
+ include Base64
19
+
20
+ def self.previewing_email(message) #:nodoc:
21
+ new(message).transform!
22
+ end
23
+
24
+ def initialize(message) #:nodoc:
25
+ @message = message
26
+ end
27
+
28
+ def transform! #:nodoc:
29
+ return message if html_part.blank?
30
+
31
+ html_part.body = html_part.decoded.gsub(PATTERN) do |match|
32
+ if part = find_part(match[9..-2])
33
+ %[src="#{data_url(part)}"]
34
+ else
35
+ match
36
+ end
37
+ end
38
+
39
+ message
40
+ end
41
+
42
+ private
43
+ attr_reader :message
44
+
45
+ def html_part
46
+ @html_part ||= message.html_part
47
+ end
48
+
49
+ def data_url(part)
50
+ "data:#{part.mime_type};base64,#{strict_encode64(part.body.raw_source)}"
51
+ end
52
+
53
+ def find_part(cid)
54
+ message.all_parts.find { |p| p.attachment? && p.cid == cid }
55
+ end
56
+ end
57
+ end
@@ -1,22 +1,39 @@
1
- require 'active_support/core_ext/array/wrap'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/log_subscriber"
2
4
 
3
5
  module ActionMailer
6
+ # Implements the ActiveSupport::LogSubscriber for logging notifications when
7
+ # email is delivered or received.
4
8
  class LogSubscriber < ActiveSupport::LogSubscriber
9
+ # An email was delivered.
5
10
  def deliver(event)
6
- recipients = Array.wrap(event.payload[:to]).join(', ')
7
- info("\nSent mail to #{recipients} (%1.fms)" % event.duration)
8
- debug(event.payload[:mail])
11
+ info do
12
+ perform_deliveries = event.payload[:perform_deliveries]
13
+ if perform_deliveries
14
+ "Delivered mail #{event.payload[:message_id]} (#{event.duration.round(1)}ms)"
15
+ else
16
+ "Skipped delivery of mail #{event.payload[:message_id]} as `perform_deliveries` is false"
17
+ end
18
+ end
19
+
20
+ debug { event.payload[:mail] }
9
21
  end
10
22
 
11
- def receive(event)
12
- info("\nReceived mail (%.1fms)" % event.duration)
13
- debug(event.payload[:mail])
23
+ # An email was generated.
24
+ def process(event)
25
+ debug do
26
+ mailer = event.payload[:mailer]
27
+ action = event.payload[:action]
28
+ "#{mailer}##{action}: processed outbound mail in #{event.duration.round(1)}ms"
29
+ end
14
30
  end
15
31
 
32
+ # Use the logger configured for ActionMailer::Base.
16
33
  def logger
17
34
  ActionMailer::Base.logger
18
35
  end
19
36
  end
20
37
  end
21
38
 
22
- ActionMailer::LogSubscriber.attach_to :action_mailer
39
+ ActionMailer::LogSubscriber.attach_to :action_mailer
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_job"
4
+
5
+ module ActionMailer
6
+ # The <tt>ActionMailer::MailDeliveryJob</tt> class is used when you
7
+ # want to send emails outside of the request-response cycle. It supports
8
+ # sending either parameterized or normal mail.
9
+ #
10
+ # Exceptions are rescued and handled by the mailer class.
11
+ class MailDeliveryJob < ActiveJob::Base # :nodoc:
12
+ queue_as { ActionMailer::Base.deliver_later_queue_name }
13
+
14
+ rescue_from StandardError, with: :handle_exception_with_mailer_class
15
+
16
+ def perform(mailer, mail_method, delivery_method, args:, kwargs: nil, params: nil)
17
+ mailer_class = params ? mailer.constantize.with(params) : mailer.constantize
18
+ message = if kwargs
19
+ mailer_class.public_send(mail_method, *args, **kwargs)
20
+ else
21
+ mailer_class.public_send(mail_method, *args)
22
+ end
23
+ message.send(delivery_method)
24
+ end
25
+
26
+ private
27
+ # "Deserialize" the mailer class name by hand in case another argument
28
+ # (like a Global ID reference) raised DeserializationError.
29
+ def mailer_class
30
+ if mailer = Array(@serialized_arguments).first || Array(arguments).first
31
+ mailer.constantize
32
+ end
33
+ end
34
+
35
+ def handle_exception_with_mailer_class(exception)
36
+ if klass = mailer_class
37
+ klass.handle_exception exception
38
+ else
39
+ raise exception
40
+ end
41
+ end
42
+ end
43
+ end
@@ -1,15 +1,30 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActionMailer
4
+ # Provides helper methods for ActionMailer::Base that can be used for easily
5
+ # formatting messages, accessing mailer or message instances, and the
6
+ # attachments list.
2
7
  module MailHelper
3
- # Uses Text::Format to take the text and format it, indented two spaces for
4
- # each line, and wrapped at 72 columns.
8
+ # Take the text and format it, indented two spaces for each line, and
9
+ # wrapped at 72 columns:
10
+ #
11
+ # text = <<-TEXT
12
+ # This is
13
+ # the paragraph.
14
+ #
15
+ # * item1 * item2
16
+ # TEXT
17
+ #
18
+ # block_format text
19
+ # # => " This is the paragraph.\n\n * item1\n * item2\n"
5
20
  def block_format(text)
6
- formatted = text.split(/\n\r\n/).collect { |paragraph|
21
+ formatted = text.split(/\n\r?\n/).collect { |paragraph|
7
22
  format_paragraph(paragraph)
8
- }.join("\n")
23
+ }.join("\n\n")
9
24
 
10
25
  # Make list points stand on their own line
11
- formatted.gsub!(/[ ]*([*]+) ([^*]*)/) { |s| " #{$1} #{$2.strip}\n" }
12
- formatted.gsub!(/[ ]*([#]+) ([^#]*)/) { |s| " #{$1} #{$2.strip}\n" }
26
+ formatted.gsub!(/[ ]*([*]+) ([^*]*)/) { " #{$1} #{$2.strip}\n" }
27
+ formatted.gsub!(/[ ]*([#]+) ([^#]*)/) { " #{$1} #{$2.strip}\n" }
13
28
 
14
29
  formatted
15
30
  end
@@ -26,14 +41,14 @@ module ActionMailer
26
41
 
27
42
  # Access the message attachments list.
28
43
  def attachments
29
- @_message.attachments
44
+ mailer.attachments
30
45
  end
31
46
 
32
47
  # Returns +text+ wrapped at +len+ columns and indented +indent+ spaces.
48
+ # By default column length +len+ equals 72 characters and indent
49
+ # +indent+ equal two spaces.
33
50
  #
34
- # === Examples
35
- #
36
- # my_text = "Here is a sample text with more than 40 characters"
51
+ # my_text = 'Here is a sample text with more than 40 characters'
37
52
  #
38
53
  # format_paragraph(my_text, 25, 4)
39
54
  # # => " Here is a sample text with\n more than 40 characters"
@@ -41,15 +56,16 @@ module ActionMailer
41
56
  sentences = [[]]
42
57
 
43
58
  text.split.each do |word|
44
- if (sentences.last + [word]).join(' ').length > len
59
+ if sentences.first.present? && (sentences.last + [word]).join(" ").length > len
45
60
  sentences << [word]
46
61
  else
47
62
  sentences.last << word
48
63
  end
49
64
  end
50
65
 
51
- sentences.map { |sentence|
52
- "#{" " * indent}#{sentence.join(' ')}"
66
+ indentation = " " * indent
67
+ sentences.map! { |sentence|
68
+ "#{indentation}#{sentence.join(' ')}"
53
69
  }.join "\n"
54
70
  end
55
71
  end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ begin
4
+ require "mail"
5
+ rescue LoadError => error
6
+ if error.message.match?(/net\/smtp/)
7
+ $stderr.puts "You don't have net-smtp installed in your application. Please add it to your Gemfile and run bundle install"
8
+ raise
9
+ end
10
+ end
@@ -0,0 +1,178 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "delegate"
4
+
5
+ module ActionMailer
6
+ # The <tt>ActionMailer::MessageDelivery</tt> class is used by
7
+ # ActionMailer::Base when creating a new mailer.
8
+ # <tt>MessageDelivery</tt> is a wrapper (+Delegator+ subclass) around a lazy
9
+ # created <tt>Mail::Message</tt>. You can get direct access to the
10
+ # <tt>Mail::Message</tt>, deliver the email or schedule the email to be sent
11
+ # through Active Job.
12
+ #
13
+ # Notifier.welcome(User.first) # an ActionMailer::MessageDelivery object
14
+ # Notifier.welcome(User.first).deliver_now # sends the email
15
+ # Notifier.welcome(User.first).deliver_later # enqueue email delivery as a job through Active Job
16
+ # Notifier.welcome(User.first).message # a Mail::Message object
17
+ class MessageDelivery < Delegator
18
+ def initialize(mailer_class, action, *args) #:nodoc:
19
+ @mailer_class, @action, @args = mailer_class, action, args
20
+
21
+ # The mail is only processed if we try to call any methods on it.
22
+ # Typical usage will leave it unloaded and call deliver_later.
23
+ @processed_mailer = nil
24
+ @mail_message = nil
25
+ end
26
+ ruby2_keywords(:initialize) if respond_to?(:ruby2_keywords, true)
27
+
28
+ # Method calls are delegated to the Mail::Message that's ready to deliver.
29
+ def __getobj__ #:nodoc:
30
+ @mail_message ||= processed_mailer.message
31
+ end
32
+
33
+ # Unused except for delegator internals (dup, marshalling).
34
+ def __setobj__(mail_message) #:nodoc:
35
+ @mail_message = mail_message
36
+ end
37
+
38
+ # Returns the resulting Mail::Message
39
+ def message
40
+ __getobj__
41
+ end
42
+
43
+ # Was the delegate loaded, causing the mailer action to be processed?
44
+ def processed?
45
+ @processed_mailer || @mail_message
46
+ end
47
+
48
+ # Enqueues the email to be delivered through Active Job. When the
49
+ # job runs it will send the email using +deliver_now!+. That means
50
+ # that the message will be sent bypassing checking +perform_deliveries+
51
+ # and +raise_delivery_errors+, so use with caution.
52
+ #
53
+ # Notifier.welcome(User.first).deliver_later!
54
+ # Notifier.welcome(User.first).deliver_later!(wait: 1.hour)
55
+ # Notifier.welcome(User.first).deliver_later!(wait_until: 10.hours.from_now)
56
+ # Notifier.welcome(User.first).deliver_later!(priority: 10)
57
+ #
58
+ # Options:
59
+ #
60
+ # * <tt>:wait</tt> - Enqueue the email to be delivered with a delay
61
+ # * <tt>:wait_until</tt> - Enqueue the email to be delivered at (after) a specific date / time
62
+ # * <tt>:queue</tt> - Enqueue the email on the specified queue
63
+ # * <tt>:priority</tt> - Enqueues the email with the specified priority
64
+ #
65
+ # By default, the email will be enqueued using <tt>ActionMailer::DeliveryJob</tt>. Each
66
+ # <tt>ActionMailer::Base</tt> class can specify the job to use by setting the class variable
67
+ # +delivery_job+.
68
+ #
69
+ # class AccountRegistrationMailer < ApplicationMailer
70
+ # self.delivery_job = RegistrationDeliveryJob
71
+ # end
72
+ def deliver_later!(options = {})
73
+ enqueue_delivery :deliver_now!, options
74
+ end
75
+
76
+ # Enqueues the email to be delivered through Active Job. When the
77
+ # job runs it will send the email using +deliver_now+.
78
+ #
79
+ # Notifier.welcome(User.first).deliver_later
80
+ # Notifier.welcome(User.first).deliver_later(wait: 1.hour)
81
+ # Notifier.welcome(User.first).deliver_later(wait_until: 10.hours.from_now)
82
+ # Notifier.welcome(User.first).deliver_later(priority: 10)
83
+ #
84
+ # Options:
85
+ #
86
+ # * <tt>:wait</tt> - Enqueue the email to be delivered with a delay.
87
+ # * <tt>:wait_until</tt> - Enqueue the email to be delivered at (after) a specific date / time.
88
+ # * <tt>:queue</tt> - Enqueue the email on the specified queue.
89
+ # * <tt>:priority</tt> - Enqueues the email with the specified priority
90
+ #
91
+ # By default, the email will be enqueued using <tt>ActionMailer::DeliveryJob</tt>. Each
92
+ # <tt>ActionMailer::Base</tt> class can specify the job to use by setting the class variable
93
+ # +delivery_job+.
94
+ #
95
+ # class AccountRegistrationMailer < ApplicationMailer
96
+ # self.delivery_job = RegistrationDeliveryJob
97
+ # end
98
+ def deliver_later(options = {})
99
+ enqueue_delivery :deliver_now, options
100
+ end
101
+
102
+ # Delivers an email without checking +perform_deliveries+ and +raise_delivery_errors+,
103
+ # so use with caution.
104
+ #
105
+ # Notifier.welcome(User.first).deliver_now!
106
+ #
107
+ def deliver_now!
108
+ processed_mailer.handle_exceptions do
109
+ message.deliver!
110
+ end
111
+ end
112
+
113
+ # Delivers an email:
114
+ #
115
+ # Notifier.welcome(User.first).deliver_now
116
+ #
117
+ def deliver_now
118
+ processed_mailer.handle_exceptions do
119
+ message.deliver
120
+ end
121
+ end
122
+
123
+ private
124
+ # Returns the processed Mailer instance. We keep this instance
125
+ # on hand so we can delegate exception handling to it.
126
+ def processed_mailer
127
+ @processed_mailer ||= @mailer_class.new.tap do |mailer|
128
+ mailer.process @action, *@args
129
+ end
130
+ end
131
+
132
+ def enqueue_delivery(delivery_method, options = {})
133
+ if processed?
134
+ ::Kernel.raise "You've accessed the message before asking to " \
135
+ "deliver it later, so you may have made local changes that would " \
136
+ "be silently lost if we enqueued a job to deliver it. Why? Only " \
137
+ "the mailer method *arguments* are passed with the delivery job! " \
138
+ "Do not access the message in any way if you mean to deliver it " \
139
+ "later. Workarounds: 1. don't touch the message before calling " \
140
+ "#deliver_later, 2. only touch the message *within your mailer " \
141
+ "method*, or 3. use a custom Active Job instead of #deliver_later."
142
+ else
143
+ job = @mailer_class.delivery_job
144
+
145
+ if use_new_args?(job)
146
+ job.set(options).perform_later(
147
+ @mailer_class.name, @action.to_s, delivery_method.to_s, args: @args)
148
+ elsif job <= DeliveryJob
149
+ job.set(options).perform_later(
150
+ @mailer_class.name, @action.to_s, delivery_method.to_s, *@args)
151
+ else
152
+ ActiveSupport::Deprecation.warn(<<~EOM)
153
+ In Rails 7.0, Action Mailer will pass the mail arguments inside the `:args` keyword argument.
154
+ The `perform` method of the #{job} needs to change and forward the mail arguments
155
+ from the `args` keyword argument.
156
+
157
+ The `perform` method should now look like:
158
+
159
+ `def perform(mailer, mail_method, delivery, args:)`
160
+ EOM
161
+
162
+ job.set(options).perform_later(
163
+ @mailer_class.name, @action.to_s, delivery_method.to_s, *@args)
164
+ end
165
+ end
166
+ end
167
+
168
+ def use_new_args?(job)
169
+ parameters = job.public_instance_method(:perform).parameters
170
+
171
+ parameters.find do |key, name|
172
+ return true if key == :keyreq && name == :args
173
+
174
+ key == :keyrest and name != :**
175
+ end
176
+ end
177
+ end
178
+ end