actionmailer 4.2.11 → 5.1.0
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.
Potentially problematic release.
This version of actionmailer might be problematic. Click here for more details.
- checksums.yaml +5 -5
- data/CHANGELOG.md +19 -138
- data/MIT-LICENSE +1 -1
- data/README.rdoc +2 -3
- data/lib/action_mailer.rb +11 -10
- data/lib/action_mailer/base.rb +230 -195
- data/lib/action_mailer/collector.rb +3 -3
- data/lib/action_mailer/delivery_job.rb +24 -3
- data/lib/action_mailer/delivery_methods.rb +11 -8
- data/lib/action_mailer/gem_version.rb +4 -4
- data/lib/action_mailer/inline_preview_interceptor.rb +8 -12
- data/lib/action_mailer/log_subscriber.rb +7 -7
- data/lib/action_mailer/mail_helper.rb +14 -2
- data/lib/action_mailer/message_delivery.rb +51 -41
- data/lib/action_mailer/parameterized.rb +152 -0
- data/lib/action_mailer/preview.rb +20 -19
- data/lib/action_mailer/railtie.rb +23 -13
- data/lib/action_mailer/rescuable.rb +27 -0
- data/lib/action_mailer/test_case.rb +26 -10
- data/lib/action_mailer/test_helper.rb +53 -2
- data/lib/action_mailer/version.rb +1 -1
- data/lib/rails/generators/mailer/USAGE +3 -3
- data/lib/rails/generators/mailer/mailer_generator.rb +21 -4
- data/lib/rails/generators/mailer/templates/application_mailer.rb +3 -1
- data/lib/rails/generators/mailer/templates/mailer.rb +2 -2
- metadata +15 -19
@@ -1,6 +1,6 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
1
|
+
require "abstract_controller/collector"
|
2
|
+
require "active_support/core_ext/hash/reverse_merge"
|
3
|
+
require "active_support/core_ext/array/extract_options"
|
4
4
|
|
5
5
|
module ActionMailer
|
6
6
|
class Collector
|
@@ -1,13 +1,34 @@
|
|
1
|
-
require
|
1
|
+
require "active_job"
|
2
2
|
|
3
3
|
module ActionMailer
|
4
4
|
# The <tt>ActionMailer::DeliveryJob</tt> class is used when you
|
5
5
|
# want to send emails outside of the request-response cycle.
|
6
|
+
#
|
7
|
+
# Exceptions are rescued and handled by the mailer class.
|
6
8
|
class DeliveryJob < ActiveJob::Base # :nodoc:
|
7
|
-
queue_as
|
9
|
+
queue_as { ActionMailer::Base.deliver_later_queue_name }
|
8
10
|
|
9
|
-
|
11
|
+
rescue_from StandardError, with: :handle_exception_with_mailer_class
|
12
|
+
|
13
|
+
def perform(mailer, mail_method, delivery_method, *args) #:nodoc:
|
10
14
|
mailer.constantize.public_send(mail_method, *args).send(delivery_method)
|
11
15
|
end
|
16
|
+
|
17
|
+
private
|
18
|
+
# "Deserialize" the mailer class name by hand in case another argument
|
19
|
+
# (like a Global ID reference) raised DeserializationError.
|
20
|
+
def mailer_class
|
21
|
+
if mailer = Array(@serialized_arguments).first || Array(arguments).first
|
22
|
+
mailer.constantize
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def handle_exception_with_mailer_class(exception)
|
27
|
+
if klass = mailer_class
|
28
|
+
klass.handle_exception exception
|
29
|
+
else
|
30
|
+
raise exception
|
31
|
+
end
|
32
|
+
end
|
12
33
|
end
|
13
34
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require "tmpdir"
|
2
2
|
|
3
3
|
module ActionMailer
|
4
4
|
# This module handles everything related to mail delivery, from registering
|
@@ -16,13 +16,16 @@ module ActionMailer
|
|
16
16
|
cattr_accessor :perform_deliveries
|
17
17
|
self.perform_deliveries = true
|
18
18
|
|
19
|
+
cattr_accessor :deliver_later_queue_name
|
20
|
+
self.deliver_later_queue_name = :mailers
|
21
|
+
|
19
22
|
self.delivery_methods = {}.freeze
|
20
23
|
self.delivery_method = :smtp
|
21
24
|
|
22
25
|
add_delivery_method :smtp, Mail::SMTP,
|
23
26
|
address: "localhost",
|
24
27
|
port: 25,
|
25
|
-
domain:
|
28
|
+
domain: "localhost.localdomain",
|
26
29
|
user_name: nil,
|
27
30
|
password: nil,
|
28
31
|
authentication: nil,
|
@@ -32,8 +35,8 @@ module ActionMailer
|
|
32
35
|
location: defined?(Rails.root) ? "#{Rails.root}/tmp/mails" : "#{Dir.tmpdir}/mails"
|
33
36
|
|
34
37
|
add_delivery_method :sendmail, Mail::Sendmail,
|
35
|
-
location:
|
36
|
-
arguments:
|
38
|
+
location: "/usr/sbin/sendmail",
|
39
|
+
arguments: "-i"
|
37
40
|
|
38
41
|
add_delivery_method :test, Mail::TestMailer
|
39
42
|
end
|
@@ -48,15 +51,15 @@ module ActionMailer
|
|
48
51
|
#
|
49
52
|
# add_delivery_method :sendmail, Mail::Sendmail,
|
50
53
|
# location: '/usr/sbin/sendmail',
|
51
|
-
# arguments: '-i
|
52
|
-
def add_delivery_method(symbol, klass, default_options={})
|
54
|
+
# arguments: '-i'
|
55
|
+
def add_delivery_method(symbol, klass, default_options = {})
|
53
56
|
class_attribute(:"#{symbol}_settings") unless respond_to?(:"#{symbol}_settings")
|
54
57
|
send(:"#{symbol}_settings=", default_options)
|
55
58
|
self.delivery_methods = delivery_methods.merge(symbol.to_sym => klass).freeze
|
56
59
|
end
|
57
60
|
|
58
|
-
def wrap_delivery_behavior(mail, method=nil, options=nil) # :nodoc:
|
59
|
-
method ||=
|
61
|
+
def wrap_delivery_behavior(mail, method = nil, options = nil) # :nodoc:
|
62
|
+
method ||= delivery_method
|
60
63
|
mail.delivery_handler = self
|
61
64
|
|
62
65
|
case method
|
@@ -1,13 +1,13 @@
|
|
1
1
|
module ActionMailer
|
2
|
-
# Returns the version of the currently loaded Action Mailer as a <tt>Gem::Version</tt
|
2
|
+
# Returns the version of the currently loaded Action Mailer as a <tt>Gem::Version</tt>.
|
3
3
|
def self.gem_version
|
4
4
|
Gem::Version.new VERSION::STRING
|
5
5
|
end
|
6
6
|
|
7
7
|
module VERSION
|
8
|
-
MAJOR =
|
9
|
-
MINOR =
|
10
|
-
TINY =
|
8
|
+
MAJOR = 5
|
9
|
+
MINOR = 1
|
10
|
+
TINY = 0
|
11
11
|
PRE = nil
|
12
12
|
|
13
13
|
STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
|
@@ -1,17 +1,17 @@
|
|
1
|
-
require
|
1
|
+
require "base64"
|
2
2
|
|
3
3
|
module ActionMailer
|
4
4
|
# Implements a mailer preview interceptor that converts image tag src attributes
|
5
5
|
# that use inline cid: style urls to data: style urls so that they are visible
|
6
|
-
# when previewing
|
6
|
+
# when previewing an HTML email in a web browser.
|
7
7
|
#
|
8
|
-
# This interceptor is
|
9
|
-
#
|
8
|
+
# This interceptor is enabled by default. To disable it, delete it from the
|
9
|
+
# <tt>ActionMailer::Base.preview_interceptors</tt> array:
|
10
10
|
#
|
11
|
-
# ActionMailer::Base.
|
11
|
+
# ActionMailer::Base.preview_interceptors.delete(ActionMailer::InlinePreviewInterceptor)
|
12
12
|
#
|
13
13
|
class InlinePreviewInterceptor
|
14
|
-
PATTERN
|
14
|
+
PATTERN = /src=(?:"cid:[^"]+"|'cid:[^']+')/i
|
15
15
|
|
16
16
|
include Base64
|
17
17
|
|
@@ -26,7 +26,7 @@ module ActionMailer
|
|
26
26
|
def transform! #:nodoc:
|
27
27
|
return message if html_part.blank?
|
28
28
|
|
29
|
-
|
29
|
+
html_part.body = html_part.decoded.gsub(PATTERN) do |match|
|
30
30
|
if part = find_part(match[9..-2])
|
31
31
|
%[src="#{data_url(part)}"]
|
32
32
|
else
|
@@ -46,16 +46,12 @@ module ActionMailer
|
|
46
46
|
@html_part ||= message.html_part
|
47
47
|
end
|
48
48
|
|
49
|
-
def html_source
|
50
|
-
html_part.body.raw_source
|
51
|
-
end
|
52
|
-
|
53
49
|
def data_url(part)
|
54
50
|
"data:#{part.mime_type};base64,#{strict_encode64(part.body.raw_source)}"
|
55
51
|
end
|
56
52
|
|
57
53
|
def find_part(cid)
|
58
|
-
message.all_parts.find{ |p| p.attachment? && p.cid == cid }
|
54
|
+
message.all_parts.find { |p| p.attachment? && p.cid == cid }
|
59
55
|
end
|
60
56
|
end
|
61
57
|
end
|
@@ -1,14 +1,14 @@
|
|
1
|
-
require
|
1
|
+
require "active_support/log_subscriber"
|
2
2
|
|
3
3
|
module ActionMailer
|
4
4
|
# Implements the ActiveSupport::LogSubscriber for logging notifications when
|
5
|
-
# email is delivered
|
5
|
+
# email is delivered or received.
|
6
6
|
class LogSubscriber < ActiveSupport::LogSubscriber
|
7
7
|
# An email was delivered.
|
8
8
|
def deliver(event)
|
9
9
|
info do
|
10
|
-
recipients = Array(event.payload[:to]).join(
|
11
|
-
"
|
10
|
+
recipients = Array(event.payload[:to]).join(", ")
|
11
|
+
"Sent mail to #{recipients} (#{event.duration.round(1)}ms)"
|
12
12
|
end
|
13
13
|
|
14
14
|
debug { event.payload[:mail] }
|
@@ -16,7 +16,7 @@ module ActionMailer
|
|
16
16
|
|
17
17
|
# An email was received.
|
18
18
|
def receive(event)
|
19
|
-
info { "
|
19
|
+
info { "Received mail (#{event.duration.round(1)}ms)" }
|
20
20
|
debug { event.payload[:mail] }
|
21
21
|
end
|
22
22
|
|
@@ -25,11 +25,11 @@ module ActionMailer
|
|
25
25
|
debug do
|
26
26
|
mailer = event.payload[:mailer]
|
27
27
|
action = event.payload[:action]
|
28
|
-
"
|
28
|
+
"#{mailer}##{action}: processed outbound mail in #{event.duration.round(1)}ms"
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
|
-
# Use the logger configured for ActionMailer::Base
|
32
|
+
# Use the logger configured for ActionMailer::Base.
|
33
33
|
def logger
|
34
34
|
ActionMailer::Base.logger
|
35
35
|
end
|
@@ -4,7 +4,17 @@ module ActionMailer
|
|
4
4
|
# attachments list.
|
5
5
|
module MailHelper
|
6
6
|
# Take the text and format it, indented two spaces for each line, and
|
7
|
-
# wrapped at 72 columns
|
7
|
+
# wrapped at 72 columns:
|
8
|
+
#
|
9
|
+
# text = <<-TEXT
|
10
|
+
# This is
|
11
|
+
# the paragraph.
|
12
|
+
#
|
13
|
+
# * item1 * item2
|
14
|
+
# TEXT
|
15
|
+
#
|
16
|
+
# block_format text
|
17
|
+
# # => " This is the paragraph.\n\n * item1\n * item2\n"
|
8
18
|
def block_format(text)
|
9
19
|
formatted = text.split(/\n\r?\n/).collect { |paragraph|
|
10
20
|
format_paragraph(paragraph)
|
@@ -33,6 +43,8 @@ module ActionMailer
|
|
33
43
|
end
|
34
44
|
|
35
45
|
# Returns +text+ wrapped at +len+ columns and indented +indent+ spaces.
|
46
|
+
# By default column length +len+ equals 72 characters and indent
|
47
|
+
# +indent+ equal two spaces.
|
36
48
|
#
|
37
49
|
# my_text = 'Here is a sample text with more than 40 characters'
|
38
50
|
#
|
@@ -42,7 +54,7 @@ module ActionMailer
|
|
42
54
|
sentences = [[]]
|
43
55
|
|
44
56
|
text.split.each do |word|
|
45
|
-
if sentences.first.present? && (sentences.last + [word]).join(
|
57
|
+
if sentences.first.present? && (sentences.last + [word]).join(" ").length > len
|
46
58
|
sentences << [word]
|
47
59
|
else
|
48
60
|
sentences.last << word
|
@@ -1,8 +1,6 @@
|
|
1
|
-
require
|
2
|
-
require 'active_support/core_ext/string/filters'
|
1
|
+
require "delegate"
|
3
2
|
|
4
3
|
module ActionMailer
|
5
|
-
|
6
4
|
# The <tt>ActionMailer::MessageDelivery</tt> class is used by
|
7
5
|
# <tt>ActionMailer::Base</tt> when creating a new mailer.
|
8
6
|
# <tt>MessageDelivery</tt> is a wrapper (+Delegator+ subclass) around a lazy
|
@@ -15,25 +13,35 @@ module ActionMailer
|
|
15
13
|
# Notifier.welcome(User.first).deliver_later # enqueue email delivery as a job through Active Job
|
16
14
|
# Notifier.welcome(User.first).message # a Mail::Message object
|
17
15
|
class MessageDelivery < Delegator
|
18
|
-
def initialize(
|
19
|
-
@
|
20
|
-
|
21
|
-
|
16
|
+
def initialize(mailer_class, action, *args) #:nodoc:
|
17
|
+
@mailer_class, @action, @args = mailer_class, action, args
|
18
|
+
|
19
|
+
# The mail is only processed if we try to call any methods on it.
|
20
|
+
# Typical usage will leave it unloaded and call deliver_later.
|
21
|
+
@processed_mailer = nil
|
22
|
+
@mail_message = nil
|
22
23
|
end
|
23
24
|
|
25
|
+
# Method calls are delegated to the Mail::Message that's ready to deliver.
|
24
26
|
def __getobj__ #:nodoc:
|
25
|
-
@
|
27
|
+
@mail_message ||= processed_mailer.message
|
26
28
|
end
|
27
29
|
|
28
|
-
|
29
|
-
|
30
|
+
# Unused except for delegator internals (dup, marshaling).
|
31
|
+
def __setobj__(mail_message) #:nodoc:
|
32
|
+
@mail_message = mail_message
|
30
33
|
end
|
31
34
|
|
32
|
-
# Returns the Mail::Message
|
35
|
+
# Returns the resulting Mail::Message
|
33
36
|
def message
|
34
37
|
__getobj__
|
35
38
|
end
|
36
39
|
|
40
|
+
# Was the delegate loaded, causing the mailer action to be processed?
|
41
|
+
def processed?
|
42
|
+
@processed_mailer || @mail_message
|
43
|
+
end
|
44
|
+
|
37
45
|
# Enqueues the email to be delivered through Active Job. When the
|
38
46
|
# job runs it will send the email using +deliver_now!+. That means
|
39
47
|
# that the message will be sent bypassing checking +perform_deliveries+
|
@@ -48,7 +56,7 @@ module ActionMailer
|
|
48
56
|
# * <tt>:wait</tt> - Enqueue the email to be delivered with a delay
|
49
57
|
# * <tt>:wait_until</tt> - Enqueue the email to be delivered at (after) a specific date / time
|
50
58
|
# * <tt>:queue</tt> - Enqueue the email on the specified queue
|
51
|
-
def deliver_later!(options={})
|
59
|
+
def deliver_later!(options = {})
|
52
60
|
enqueue_delivery :deliver_now!, options
|
53
61
|
end
|
54
62
|
|
@@ -61,10 +69,10 @@ module ActionMailer
|
|
61
69
|
#
|
62
70
|
# Options:
|
63
71
|
#
|
64
|
-
# * <tt>:wait</tt> - Enqueue the email to be delivered with a delay
|
65
|
-
# * <tt>:wait_until</tt> - Enqueue the email to be delivered at (after) a specific date / time
|
66
|
-
# * <tt>:queue</tt> - Enqueue the email on the specified queue
|
67
|
-
def deliver_later(options={})
|
72
|
+
# * <tt>:wait</tt> - Enqueue the email to be delivered with a delay.
|
73
|
+
# * <tt>:wait_until</tt> - Enqueue the email to be delivered at (after) a specific date / time.
|
74
|
+
# * <tt>:queue</tt> - Enqueue the email on the specified queue.
|
75
|
+
def deliver_later(options = {})
|
68
76
|
enqueue_delivery :deliver_now, options
|
69
77
|
end
|
70
78
|
|
@@ -74,7 +82,9 @@ module ActionMailer
|
|
74
82
|
# Notifier.welcome(User.first).deliver_now!
|
75
83
|
#
|
76
84
|
def deliver_now!
|
77
|
-
|
85
|
+
processed_mailer.handle_exceptions do
|
86
|
+
message.deliver!
|
87
|
+
end
|
78
88
|
end
|
79
89
|
|
80
90
|
# Delivers an email:
|
@@ -82,34 +92,34 @@ module ActionMailer
|
|
82
92
|
# Notifier.welcome(User.first).deliver_now
|
83
93
|
#
|
84
94
|
def deliver_now
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
def deliver! #:nodoc:
|
89
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
90
|
-
`#deliver!` is deprecated and will be removed in Rails 5. Use
|
91
|
-
`#deliver_now!` to deliver immediately or `#deliver_later!` to
|
92
|
-
deliver through Active Job.
|
93
|
-
MSG
|
94
|
-
|
95
|
-
deliver_now!
|
96
|
-
end
|
97
|
-
|
98
|
-
def deliver #:nodoc:
|
99
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
100
|
-
`#deliver` is deprecated and will be removed in Rails 5. Use
|
101
|
-
`#deliver_now` to deliver immediately or `#deliver_later` to
|
102
|
-
deliver through Active Job.
|
103
|
-
MSG
|
104
|
-
|
105
|
-
deliver_now
|
95
|
+
processed_mailer.handle_exceptions do
|
96
|
+
message.deliver
|
97
|
+
end
|
106
98
|
end
|
107
99
|
|
108
100
|
private
|
101
|
+
# Returns the processed Mailer instance. We keep this instance
|
102
|
+
# on hand so we can delegate exception handling to it.
|
103
|
+
def processed_mailer
|
104
|
+
@processed_mailer ||= @mailer_class.new.tap do |mailer|
|
105
|
+
mailer.process @action, *@args
|
106
|
+
end
|
107
|
+
end
|
109
108
|
|
110
|
-
def enqueue_delivery(delivery_method, options={})
|
111
|
-
|
112
|
-
|
109
|
+
def enqueue_delivery(delivery_method, options = {})
|
110
|
+
if processed?
|
111
|
+
::Kernel.raise "You've accessed the message before asking to " \
|
112
|
+
"deliver it later, so you may have made local changes that would " \
|
113
|
+
"be silently lost if we enqueued a job to deliver it. Why? Only " \
|
114
|
+
"the mailer method *arguments* are passed with the delivery job! " \
|
115
|
+
"Do not access the message in any way if you mean to deliver it " \
|
116
|
+
"later. Workarounds: 1. don't touch the message before calling " \
|
117
|
+
"#deliver_later, 2. only touch the message *within your mailer " \
|
118
|
+
"method*, or 3. use a custom Active Job instead of #deliver_later."
|
119
|
+
else
|
120
|
+
args = @mailer_class.name, @action.to_s, delivery_method.to_s, *@args
|
121
|
+
::ActionMailer::DeliveryJob.set(options).perform_later(*args)
|
122
|
+
end
|
113
123
|
end
|
114
124
|
end
|
115
125
|
end
|
@@ -0,0 +1,152 @@
|
|
1
|
+
module ActionMailer
|
2
|
+
# Provides the option to parameterize mailers in order to share instance variable
|
3
|
+
# setup, processing, and common headers.
|
4
|
+
#
|
5
|
+
# Consider this example that does not use parameterization:
|
6
|
+
#
|
7
|
+
# class InvitationsMailer < ApplicationMailer
|
8
|
+
# def account_invitation(inviter, invitee)
|
9
|
+
# @account = inviter.account
|
10
|
+
# @inviter = inviter
|
11
|
+
# @invitee = invitee
|
12
|
+
#
|
13
|
+
# subject = "#{@inviter.name} invited you to their Basecamp (#{@account.name})"
|
14
|
+
#
|
15
|
+
# mail \
|
16
|
+
# subject: subject,
|
17
|
+
# to: invitee.email_address,
|
18
|
+
# from: common_address(inviter),
|
19
|
+
# reply_to: inviter.email_address_with_name
|
20
|
+
# end
|
21
|
+
#
|
22
|
+
# def project_invitation(project, inviter, invitee)
|
23
|
+
# @account = inviter.account
|
24
|
+
# @project = project
|
25
|
+
# @inviter = inviter
|
26
|
+
# @invitee = invitee
|
27
|
+
# @summarizer = ProjectInvitationSummarizer.new(@project.bucket)
|
28
|
+
#
|
29
|
+
# subject = "#{@inviter.name.familiar} added you to a project in Basecamp (#{@account.name})"
|
30
|
+
#
|
31
|
+
# mail \
|
32
|
+
# subject: subject,
|
33
|
+
# to: invitee.email_address,
|
34
|
+
# from: common_address(inviter),
|
35
|
+
# reply_to: inviter.email_address_with_name
|
36
|
+
# end
|
37
|
+
#
|
38
|
+
# def bulk_project_invitation(projects, inviter, invitee)
|
39
|
+
# @account = inviter.account
|
40
|
+
# @projects = projects.sort_by(&:name)
|
41
|
+
# @inviter = inviter
|
42
|
+
# @invitee = invitee
|
43
|
+
#
|
44
|
+
# subject = "#{@inviter.name.familiar} added you to some new stuff in Basecamp (#{@account.name})"
|
45
|
+
#
|
46
|
+
# mail \
|
47
|
+
# subject: subject,
|
48
|
+
# to: invitee.email_address,
|
49
|
+
# from: common_address(inviter),
|
50
|
+
# reply_to: inviter.email_address_with_name
|
51
|
+
# end
|
52
|
+
# end
|
53
|
+
#
|
54
|
+
# InvitationsMailer.account_invitation(person_a, person_b).deliver_later
|
55
|
+
#
|
56
|
+
# Using parameterized mailers, this can be rewritten as:
|
57
|
+
#
|
58
|
+
# class InvitationsMailer < ApplicationMailer
|
59
|
+
# before_action { @inviter, @invitee = params[:inviter], params[:invitee] }
|
60
|
+
# before_action { @account = params[:inviter].account }
|
61
|
+
#
|
62
|
+
# default to: -> { @invitee.email_address },
|
63
|
+
# from: -> { common_address(@inviter) },
|
64
|
+
# reply_to: -> { @inviter.email_address_with_name }
|
65
|
+
#
|
66
|
+
# def account_invitation
|
67
|
+
# mail subject: "#{@inviter.name} invited you to their Basecamp (#{@account.name})"
|
68
|
+
# end
|
69
|
+
#
|
70
|
+
# def project_invitation
|
71
|
+
# @project = params[:project]
|
72
|
+
# @summarizer = ProjectInvitationSummarizer.new(@project.bucket)
|
73
|
+
#
|
74
|
+
# mail subject: "#{@inviter.name.familiar} added you to a project in Basecamp (#{@account.name})"
|
75
|
+
# end
|
76
|
+
#
|
77
|
+
# def bulk_project_invitation
|
78
|
+
# @projects = params[:projects].sort_by(&:name)
|
79
|
+
#
|
80
|
+
# mail subject: "#{@inviter.name.familiar} added you to some new stuff in Basecamp (#{@account.name})"
|
81
|
+
# end
|
82
|
+
# end
|
83
|
+
#
|
84
|
+
# InvitationsMailer.with(inviter: person_a, invitee: person_b).account_invitation.deliver_later
|
85
|
+
module Parameterized
|
86
|
+
extend ActiveSupport::Concern
|
87
|
+
|
88
|
+
included do
|
89
|
+
attr_accessor :params
|
90
|
+
end
|
91
|
+
|
92
|
+
module ClassMethods
|
93
|
+
# Provide the parameters to the mailer in order to use them in the instance methods and callbacks.
|
94
|
+
#
|
95
|
+
# InvitationsMailer.with(inviter: person_a, invitee: person_b).account_invitation.deliver_later
|
96
|
+
#
|
97
|
+
# See Parameterized documentation for full example.
|
98
|
+
def with(params)
|
99
|
+
ActionMailer::Parameterized::Mailer.new(self, params)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
class Mailer # :nodoc:
|
104
|
+
def initialize(mailer, params)
|
105
|
+
@mailer, @params = mailer, params
|
106
|
+
end
|
107
|
+
|
108
|
+
private
|
109
|
+
def method_missing(method_name, *args)
|
110
|
+
if @mailer.action_methods.include?(method_name.to_s)
|
111
|
+
ActionMailer::Parameterized::MessageDelivery.new(@mailer, method_name, @params, *args)
|
112
|
+
else
|
113
|
+
super
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def respond_to_missing?(method, include_all = false)
|
118
|
+
@mailer.respond_to?(method, include_all)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
class MessageDelivery < ActionMailer::MessageDelivery # :nodoc:
|
123
|
+
def initialize(mailer_class, action, params, *args)
|
124
|
+
super(mailer_class, action, *args)
|
125
|
+
@params = params
|
126
|
+
end
|
127
|
+
|
128
|
+
private
|
129
|
+
def processed_mailer
|
130
|
+
@processed_mailer ||= @mailer_class.new.tap do |mailer|
|
131
|
+
mailer.params = @params
|
132
|
+
mailer.process @action, *@args
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
def enqueue_delivery(delivery_method, options = {})
|
137
|
+
if processed?
|
138
|
+
super
|
139
|
+
else
|
140
|
+
args = @mailer_class.name, @action.to_s, delivery_method.to_s, @params, *@args
|
141
|
+
ActionMailer::Parameterized::DeliveryJob.set(options).perform_later(*args)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
class DeliveryJob < ActionMailer::DeliveryJob # :nodoc:
|
147
|
+
def perform(mailer, mail_method, delivery_method, params, *args)
|
148
|
+
mailer.constantize.with(params).public_send(mail_method, *args).send(delivery_method)
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|