actionmailer 5.2.8.1 → 6.0.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +123 -39
- data/MIT-LICENSE +1 -1
- data/README.rdoc +5 -39
- data/lib/action_mailer/base.rb +56 -22
- data/lib/action_mailer/delivery_job.rb +9 -0
- data/lib/action_mailer/gem_version.rb +4 -4
- data/lib/action_mailer/inline_preview_interceptor.rb +1 -3
- data/lib/action_mailer/log_subscriber.rb +6 -2
- data/lib/action_mailer/mail_delivery_job.rb +43 -0
- data/lib/action_mailer/message_delivery.rb +10 -3
- data/lib/action_mailer/parameterized.rb +25 -7
- data/lib/action_mailer/preview.rb +21 -5
- data/lib/action_mailer/railtie.rb +18 -7
- data/lib/action_mailer/test_case.rb +0 -2
- data/lib/action_mailer/test_helper.rb +32 -14
- data/lib/action_mailer.rb +2 -1
- data/lib/rails/generators/mailer/mailer_generator.rb +1 -1
- metadata +20 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fe6f6cbc34bc7f86f69dfa5dfc71f59aa29683c80a50de2df742cc32ab56f874
|
4
|
+
data.tar.gz: 8ad68f46ec8fb91e8965228a592f99a1b95b2f6af13302ac6fa12534ce185cae
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7fa6e8431a41a9fcf48c6a176d854bf8ffa83a18e9d050098417382fcc35bde9d4f7f7098423b9b784f00c00b6beafc50588fa7d900710bb0ead0249ff2c9e17
|
7
|
+
data.tar.gz: 7c06b4dcaadaf47f69c245c0b897d32a3af564552ae7a65a1576bd709945f67f0a3434b3ed77cd057d3e0f8e5ee03ca538d3aff33acf5c063b4931a5d09bdb34
|
data/CHANGELOG.md
CHANGED
@@ -1,134 +1,218 @@
|
|
1
|
-
## Rails
|
1
|
+
## Rails 6.0.6 (September 09, 2022) ##
|
2
2
|
|
3
3
|
* No changes.
|
4
4
|
|
5
5
|
|
6
|
-
## Rails 5.
|
6
|
+
## Rails 6.0.5.1 (July 12, 2022) ##
|
7
7
|
|
8
8
|
* No changes.
|
9
9
|
|
10
10
|
|
11
|
-
## Rails
|
11
|
+
## Rails 6.0.5 (May 09, 2022) ##
|
12
12
|
|
13
13
|
* No changes.
|
14
14
|
|
15
15
|
|
16
|
-
## Rails
|
16
|
+
## Rails 6.0.4.8 (April 26, 2022) ##
|
17
17
|
|
18
18
|
* No changes.
|
19
19
|
|
20
20
|
|
21
|
-
## Rails
|
21
|
+
## Rails 6.0.4.7 (March 08, 2022) ##
|
22
22
|
|
23
23
|
* No changes.
|
24
24
|
|
25
25
|
|
26
|
-
## Rails
|
26
|
+
## Rails 6.0.4.6 (February 11, 2022) ##
|
27
27
|
|
28
28
|
* No changes.
|
29
29
|
|
30
30
|
|
31
|
-
## Rails
|
31
|
+
## Rails 6.0.4.5 (February 11, 2022) ##
|
32
32
|
|
33
33
|
* No changes.
|
34
34
|
|
35
35
|
|
36
|
-
## Rails
|
36
|
+
## Rails 6.0.4.4 (December 15, 2021) ##
|
37
37
|
|
38
38
|
* No changes.
|
39
39
|
|
40
40
|
|
41
|
-
## Rails
|
41
|
+
## Rails 6.0.4.3 (December 14, 2021) ##
|
42
42
|
|
43
43
|
* No changes.
|
44
44
|
|
45
45
|
|
46
|
-
## Rails
|
46
|
+
## Rails 6.0.4.2 (December 14, 2021) ##
|
47
47
|
|
48
48
|
* No changes.
|
49
49
|
|
50
50
|
|
51
|
-
## Rails
|
51
|
+
## Rails 6.0.4.1 (August 19, 2021) ##
|
52
52
|
|
53
53
|
* No changes.
|
54
54
|
|
55
55
|
|
56
|
-
## Rails
|
56
|
+
## Rails 6.0.4 (June 15, 2021) ##
|
57
57
|
|
58
58
|
* No changes.
|
59
59
|
|
60
60
|
|
61
|
-
## Rails
|
61
|
+
## Rails 6.0.3.7 (May 05, 2021) ##
|
62
62
|
|
63
63
|
* No changes.
|
64
64
|
|
65
65
|
|
66
|
-
## Rails
|
66
|
+
## Rails 6.0.3.6 (March 26, 2021) ##
|
67
67
|
|
68
68
|
* No changes.
|
69
69
|
|
70
70
|
|
71
|
-
## Rails
|
71
|
+
## Rails 6.0.3.5 (February 10, 2021) ##
|
72
72
|
|
73
73
|
* No changes.
|
74
74
|
|
75
75
|
|
76
|
-
## Rails
|
76
|
+
## Rails 6.0.3.4 (October 07, 2020) ##
|
77
77
|
|
78
78
|
* No changes.
|
79
79
|
|
80
80
|
|
81
|
-
## Rails
|
81
|
+
## Rails 6.0.3.3 (September 09, 2020) ##
|
82
82
|
|
83
83
|
* No changes.
|
84
84
|
|
85
85
|
|
86
|
-
## Rails
|
86
|
+
## Rails 6.0.3.2 (June 17, 2020) ##
|
87
87
|
|
88
88
|
* No changes.
|
89
89
|
|
90
90
|
|
91
|
-
## Rails
|
91
|
+
## Rails 6.0.3.1 (May 18, 2020) ##
|
92
92
|
|
93
93
|
* No changes.
|
94
94
|
|
95
95
|
|
96
|
-
## Rails
|
96
|
+
## Rails 6.0.3 (May 06, 2020) ##
|
97
97
|
|
98
98
|
* No changes.
|
99
99
|
|
100
100
|
|
101
|
-
## Rails
|
101
|
+
## Rails 6.0.2.2 (March 19, 2020) ##
|
102
102
|
|
103
|
-
*
|
103
|
+
* No changes.
|
104
104
|
|
105
|
-
|
105
|
+
|
106
|
+
## Rails 6.0.2.1 (December 18, 2019) ##
|
107
|
+
|
108
|
+
* No changes.
|
109
|
+
|
110
|
+
|
111
|
+
## Rails 6.0.2 (December 13, 2019) ##
|
112
|
+
|
113
|
+
* Fix ActionMailer assertions don't work for parameterized mail with legacy delivery job.
|
114
|
+
|
115
|
+
*bogdanvlviv*
|
116
|
+
|
117
|
+
|
118
|
+
## Rails 6.0.1 (November 5, 2019) ##
|
119
|
+
|
120
|
+
* No changes.
|
106
121
|
|
107
122
|
|
108
|
-
## Rails
|
123
|
+
## Rails 6.0.0 (August 16, 2019) ##
|
109
124
|
|
110
|
-
*
|
111
|
-
|
125
|
+
* No changes.
|
126
|
+
|
127
|
+
|
128
|
+
## Rails 6.0.0.rc2 (July 22, 2019) ##
|
129
|
+
|
130
|
+
* No changes.
|
131
|
+
|
132
|
+
|
133
|
+
## Rails 6.0.0.rc1 (April 24, 2019) ##
|
134
|
+
|
135
|
+
* No changes.
|
136
|
+
|
137
|
+
|
138
|
+
## Rails 6.0.0.beta3 (March 11, 2019) ##
|
139
|
+
|
140
|
+
* No changes.
|
112
141
|
|
113
|
-
*Jimmy Bourassa*
|
114
142
|
|
115
|
-
|
143
|
+
## Rails 6.0.0.beta2 (February 25, 2019) ##
|
144
|
+
|
145
|
+
* No changes.
|
146
|
+
|
147
|
+
|
148
|
+
## Rails 6.0.0.beta1 (January 18, 2019) ##
|
149
|
+
|
150
|
+
* Deprecate `ActionMailer::Base.receive` in favor of [Action Mailbox](https://github.com/rails/rails/tree/master/actionmailbox).
|
151
|
+
|
152
|
+
*George Claghorn*
|
153
|
+
|
154
|
+
* Add `MailDeliveryJob` for delivering both regular and parameterized mail. Deprecate using `DeliveryJob` and `Parameterized::DeliveryJob`.
|
155
|
+
|
156
|
+
*Gannon McGibbon*
|
157
|
+
|
158
|
+
* Fix ActionMailer assertions not working when a Mail defines
|
159
|
+
a custom delivery job class
|
160
|
+
|
161
|
+
*Edouard Chin*
|
162
|
+
|
163
|
+
* Mails with multipart `format` blocks with implicit render now also check for
|
164
|
+
a template name in options hash instead of only using the action name.
|
165
|
+
|
166
|
+
*Marcus Ilgner*
|
167
|
+
|
168
|
+
* `ActionDispatch::IntegrationTest` includes `ActionMailer::TestHelper` module by default.
|
169
|
+
|
170
|
+
*Ricardo Díaz*
|
171
|
+
|
172
|
+
* Add `perform_deliveries` to a payload of `deliver.action_mailer` notification.
|
173
|
+
|
174
|
+
*Yoshiyuki Kinjo*
|
175
|
+
|
176
|
+
* Change delivery logging message when `perform_deliveries` is false.
|
177
|
+
|
178
|
+
*Yoshiyuki Kinjo*
|
179
|
+
|
180
|
+
* Allow call `assert_enqueued_email_with` with no block.
|
181
|
+
|
182
|
+
Example:
|
183
|
+
```
|
184
|
+
def test_email
|
185
|
+
ContactMailer.welcome.deliver_later
|
186
|
+
assert_enqueued_email_with ContactMailer, :welcome
|
187
|
+
end
|
188
|
+
|
189
|
+
def test_email_with_arguments
|
190
|
+
ContactMailer.welcome("Hello", "Goodbye").deliver_later
|
191
|
+
assert_enqueued_email_with ContactMailer, :welcome, args: ["Hello", "Goodbye"]
|
192
|
+
end
|
193
|
+
```
|
194
|
+
|
195
|
+
*bogdanvlviv*
|
196
|
+
|
197
|
+
* Ensure mail gem is eager autoloaded when eager load is true to prevent thread deadlocks.
|
198
|
+
|
199
|
+
*Samuel Cochran*
|
116
200
|
|
117
|
-
|
118
|
-
ContactMailer.welcome.deliver_later
|
119
|
-
end
|
201
|
+
* Perform email jobs in `assert_emails`.
|
120
202
|
|
121
|
-
*
|
203
|
+
*Gannon McGibbon*
|
122
204
|
|
123
|
-
*
|
205
|
+
* Add `Base.unregister_observer`, `Base.unregister_observers`,
|
206
|
+
`Base.unregister_interceptor`, `Base.unregister_interceptors`,
|
207
|
+
`Base.unregister_preview_interceptor` and `Base.unregister_preview_interceptors`.
|
208
|
+
This makes it possible to dynamically add and remove email observers and
|
209
|
+
interceptors at runtime in the same way they're registered.
|
124
210
|
|
125
|
-
|
126
|
-
self.delivery_job = MyCustomDeliveryJob
|
211
|
+
*Claudio Ortolina*, *Kota Miyake*
|
127
212
|
|
128
|
-
|
129
|
-
end
|
213
|
+
* Rails 6 requires Ruby 2.5.0 or newer.
|
130
214
|
|
131
|
-
*
|
215
|
+
*Jeremy Daer*, *Kasper Timm Hansen*
|
132
216
|
|
133
217
|
|
134
|
-
Please check [5-
|
218
|
+
Please check [5-2-stable](https://github.com/rails/rails/blob/5-2-stable/actionmailer/CHANGELOG.md) for previous changes.
|
data/MIT-LICENSE
CHANGED
data/README.rdoc
CHANGED
@@ -13,6 +13,8 @@ Additionally, an Action Mailer class can be used to process incoming email,
|
|
13
13
|
such as allowing a blog to accept new posts from an email (which could even
|
14
14
|
have been sent from a phone).
|
15
15
|
|
16
|
+
You can read more about Action Mailer in the {Action Mailer Basics}[https://edgeguides.rubyonrails.org/action_mailer_basics.html] guide.
|
17
|
+
|
16
18
|
== Sending emails
|
17
19
|
|
18
20
|
The framework works by initializing any instance variables you want to be
|
@@ -93,42 +95,6 @@ Example:
|
|
93
95
|
.....
|
94
96
|
end
|
95
97
|
|
96
|
-
== Receiving emails
|
97
|
-
|
98
|
-
To receive emails, you need to implement a public instance method called
|
99
|
-
+receive+ that takes an email object as its single parameter. The Action Mailer
|
100
|
-
framework has a corresponding class method, which is also called +receive+, that
|
101
|
-
accepts a raw, unprocessed email as a string, which it then turns into the email
|
102
|
-
object and calls the receive instance method.
|
103
|
-
|
104
|
-
Example:
|
105
|
-
|
106
|
-
class Mailman < ActionMailer::Base
|
107
|
-
def receive(email)
|
108
|
-
page = Page.find_by(address: email.to.first)
|
109
|
-
page.emails.create(
|
110
|
-
subject: email.subject, body: email.body
|
111
|
-
)
|
112
|
-
|
113
|
-
if email.has_attachments?
|
114
|
-
email.attachments.each do |attachment|
|
115
|
-
page.attachments.create({
|
116
|
-
file: attachment, description: email.subject
|
117
|
-
})
|
118
|
-
end
|
119
|
-
end
|
120
|
-
end
|
121
|
-
end
|
122
|
-
|
123
|
-
This Mailman can be the target for Postfix or other MTAs. In Rails, you would use
|
124
|
-
the runner in the trivial case like this:
|
125
|
-
|
126
|
-
rails runner 'Mailman.receive(STDIN.read)'
|
127
|
-
|
128
|
-
However, invoking Rails in the runner for each mail to be received is very
|
129
|
-
resource intensive. A single instance of Rails should be run within a daemon, if
|
130
|
-
it is going to process more than just a limited amount of email.
|
131
|
-
|
132
98
|
== Configuration
|
133
99
|
|
134
100
|
The Base class has the full list of configuration options. Here's an example:
|
@@ -150,7 +116,7 @@ The latest version of Action Mailer can be installed with RubyGems:
|
|
150
116
|
|
151
117
|
Source code can be downloaded as part of the Rails project on GitHub:
|
152
118
|
|
153
|
-
* https://github.com/rails/rails/tree/
|
119
|
+
* https://github.com/rails/rails/tree/main/actionmailer
|
154
120
|
|
155
121
|
|
156
122
|
== License
|
@@ -164,7 +130,7 @@ Action Mailer is released under the MIT license:
|
|
164
130
|
|
165
131
|
API documentation is at
|
166
132
|
|
167
|
-
*
|
133
|
+
* https://api.rubyonrails.org
|
168
134
|
|
169
135
|
Bug reports for the Ruby on Rails project can be filed here:
|
170
136
|
|
@@ -172,4 +138,4 @@ Bug reports for the Ruby on Rails project can be filed here:
|
|
172
138
|
|
173
139
|
Feature requests should be discussed on the rails-core mailing list here:
|
174
140
|
|
175
|
-
* https://
|
141
|
+
* https://discuss.rubyonrails.org/c/rubyonrails-core
|
data/lib/action_mailer/base.rb
CHANGED
@@ -408,7 +408,7 @@ module ActionMailer
|
|
408
408
|
# really useful if you need to validate a self-signed and/or a wildcard certificate. You can use the name
|
409
409
|
# of an OpenSSL verify constant (<tt>'none'</tt> or <tt>'peer'</tt>) or directly the constant
|
410
410
|
# (<tt>OpenSSL::SSL::VERIFY_NONE</tt> or <tt>OpenSSL::SSL::VERIFY_PEER</tt>).
|
411
|
-
#
|
411
|
+
# * <tt>:ssl/:tls</tt> Enables the SMTP connection to use SMTP/TLS (SMTPS: SMTP over direct TLS connection)
|
412
412
|
#
|
413
413
|
# * <tt>sendmail_settings</tt> - Allows you to override options for the <tt>:sendmail</tt> delivery method.
|
414
414
|
# * <tt>:location</tt> - The location of the sendmail executable. Defaults to <tt>/usr/sbin/sendmail</tt>.
|
@@ -475,11 +475,21 @@ module ActionMailer
|
|
475
475
|
observers.flatten.compact.each { |observer| register_observer(observer) }
|
476
476
|
end
|
477
477
|
|
478
|
+
# Unregister one or more previously registered Observers.
|
479
|
+
def unregister_observers(*observers)
|
480
|
+
observers.flatten.compact.each { |observer| unregister_observer(observer) }
|
481
|
+
end
|
482
|
+
|
478
483
|
# Register one or more Interceptors which will be called before mail is sent.
|
479
484
|
def register_interceptors(*interceptors)
|
480
485
|
interceptors.flatten.compact.each { |interceptor| register_interceptor(interceptor) }
|
481
486
|
end
|
482
487
|
|
488
|
+
# Unregister one or more previously registered Interceptors.
|
489
|
+
def unregister_interceptors(*interceptors)
|
490
|
+
interceptors.flatten.compact.each { |interceptor| unregister_interceptor(interceptor) }
|
491
|
+
end
|
492
|
+
|
483
493
|
# Register an Observer which will be notified when mail is delivered.
|
484
494
|
# Either a class, string or symbol can be passed in as the Observer.
|
485
495
|
# If a string or symbol is passed in it will be camelized and constantized.
|
@@ -487,6 +497,13 @@ module ActionMailer
|
|
487
497
|
Mail.register_observer(observer_class_for(observer))
|
488
498
|
end
|
489
499
|
|
500
|
+
# Unregister a previously registered Observer.
|
501
|
+
# Either a class, string or symbol can be passed in as the Observer.
|
502
|
+
# If a string or symbol is passed in it will be camelized and constantized.
|
503
|
+
def unregister_observer(observer)
|
504
|
+
Mail.unregister_observer(observer_class_for(observer))
|
505
|
+
end
|
506
|
+
|
490
507
|
# Register an Interceptor which will be called before mail is sent.
|
491
508
|
# Either a class, string or symbol can be passed in as the Interceptor.
|
492
509
|
# If a string or symbol is passed in it will be camelized and constantized.
|
@@ -494,6 +511,13 @@ module ActionMailer
|
|
494
511
|
Mail.register_interceptor(observer_class_for(interceptor))
|
495
512
|
end
|
496
513
|
|
514
|
+
# Unregister a previously registered Interceptor.
|
515
|
+
# Either a class, string or symbol can be passed in as the Interceptor.
|
516
|
+
# If a string or symbol is passed in it will be camelized and constantized.
|
517
|
+
def unregister_interceptor(interceptor)
|
518
|
+
Mail.unregister_interceptor(observer_class_for(interceptor))
|
519
|
+
end
|
520
|
+
|
497
521
|
def observer_class_for(value) # :nodoc:
|
498
522
|
case value
|
499
523
|
when String, Symbol
|
@@ -541,6 +565,11 @@ module ActionMailer
|
|
541
565
|
# end
|
542
566
|
# end
|
543
567
|
def receive(raw_mail)
|
568
|
+
ActiveSupport::Deprecation.warn(<<~MESSAGE.squish)
|
569
|
+
ActionMailer::Base.receive is deprecated and will be removed in Rails 6.1.
|
570
|
+
Use Action Mailbox to process inbound email.
|
571
|
+
MESSAGE
|
572
|
+
|
544
573
|
ActiveSupport::Notifications.instrument("receive.action_mailer") do |payload|
|
545
574
|
mail = Mail.new(raw_mail)
|
546
575
|
set_payload_for_mail(payload, mail)
|
@@ -562,17 +591,17 @@ module ActionMailer
|
|
562
591
|
end
|
563
592
|
|
564
593
|
private
|
565
|
-
|
566
594
|
def set_payload_for_mail(payload, mail)
|
567
|
-
payload[:
|
568
|
-
payload[:
|
569
|
-
payload[:
|
570
|
-
payload[:
|
571
|
-
payload[:
|
572
|
-
payload[:
|
573
|
-
payload[:
|
574
|
-
payload[:
|
575
|
-
payload[:
|
595
|
+
payload[:mail] = mail.encoded
|
596
|
+
payload[:mailer] = name
|
597
|
+
payload[:message_id] = mail.message_id
|
598
|
+
payload[:subject] = mail.subject
|
599
|
+
payload[:to] = mail.to
|
600
|
+
payload[:from] = mail.from
|
601
|
+
payload[:bcc] = mail.bcc if mail.bcc.present?
|
602
|
+
payload[:cc] = mail.cc if mail.cc.present?
|
603
|
+
payload[:date] = mail.date
|
604
|
+
payload[:perform_deliveries] = mail.perform_deliveries
|
576
605
|
end
|
577
606
|
|
578
607
|
def method_missing(method_name, *args)
|
@@ -582,6 +611,7 @@ module ActionMailer
|
|
582
611
|
super
|
583
612
|
end
|
584
613
|
end
|
614
|
+
ruby2_keywords(:method_missing) if respond_to?(:ruby2_keywords, true)
|
585
615
|
|
586
616
|
def respond_to_missing?(method, include_all = false)
|
587
617
|
action_methods.include?(method.to_s) || super
|
@@ -843,7 +873,6 @@ module ActionMailer
|
|
843
873
|
end
|
844
874
|
|
845
875
|
private
|
846
|
-
|
847
876
|
# Used by #mail to set the content type of the message.
|
848
877
|
#
|
849
878
|
# It will use the given +user_content_type+, or multipart if the mail
|
@@ -877,7 +906,7 @@ module ActionMailer
|
|
877
906
|
# If the subject has interpolations, you can pass them through the +interpolations+ parameter.
|
878
907
|
def default_i18n_subject(interpolations = {}) # :doc:
|
879
908
|
mailer_scope = self.class.mailer_name.tr("/", ".")
|
880
|
-
I18n.t(:subject, interpolations.merge(scope: [mailer_scope, action_name], default: action_name.humanize))
|
909
|
+
I18n.t(:subject, **interpolations.merge(scope: [mailer_scope, action_name], default: action_name.humanize))
|
881
910
|
end
|
882
911
|
|
883
912
|
# Emails do not support relative path links.
|
@@ -914,11 +943,9 @@ module ActionMailer
|
|
914
943
|
assignable.each { |k, v| message[k] = v }
|
915
944
|
end
|
916
945
|
|
917
|
-
def collect_responses(headers)
|
946
|
+
def collect_responses(headers, &block)
|
918
947
|
if block_given?
|
919
|
-
|
920
|
-
yield(collector)
|
921
|
-
collector.responses
|
948
|
+
collect_responses_from_block(headers, &block)
|
922
949
|
elsif headers[:body]
|
923
950
|
collect_responses_from_text(headers)
|
924
951
|
else
|
@@ -926,6 +953,13 @@ module ActionMailer
|
|
926
953
|
end
|
927
954
|
end
|
928
955
|
|
956
|
+
def collect_responses_from_block(headers)
|
957
|
+
templates_name = headers[:template_name] || action_name
|
958
|
+
collector = ActionMailer::Collector.new(lookup_context) { render(templates_name) }
|
959
|
+
yield(collector)
|
960
|
+
collector.responses
|
961
|
+
end
|
962
|
+
|
929
963
|
def collect_responses_from_text(headers)
|
930
964
|
[{
|
931
965
|
body: headers.delete(:body),
|
@@ -938,10 +972,10 @@ module ActionMailer
|
|
938
972
|
templates_name = headers[:template_name] || action_name
|
939
973
|
|
940
974
|
each_template(Array(templates_path), templates_name).map do |template|
|
941
|
-
|
975
|
+
format = template.format || self.formats.first
|
942
976
|
{
|
943
|
-
body: render(template: template),
|
944
|
-
content_type:
|
977
|
+
body: render(template: template, formats: [format]),
|
978
|
+
content_type: Mime[format].to_s
|
945
979
|
}
|
946
980
|
end
|
947
981
|
end
|
@@ -951,7 +985,7 @@ module ActionMailer
|
|
951
985
|
if templates.empty?
|
952
986
|
raise ActionView::MissingTemplate.new(paths, name, paths, false, "mailer")
|
953
987
|
else
|
954
|
-
templates.uniq(&:
|
988
|
+
templates.uniq(&:format).each(&block)
|
955
989
|
end
|
956
990
|
end
|
957
991
|
|
@@ -983,7 +1017,7 @@ module ActionMailer
|
|
983
1017
|
end
|
984
1018
|
|
985
1019
|
def instrument_name
|
986
|
-
"action_mailer"
|
1020
|
+
"action_mailer"
|
987
1021
|
end
|
988
1022
|
|
989
1023
|
ActiveSupport.run_load_hooks(:action_mailer, self)
|
@@ -12,9 +12,18 @@ module ActionMailer
|
|
12
12
|
|
13
13
|
rescue_from StandardError, with: :handle_exception_with_mailer_class
|
14
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 6.1.
|
19
|
+
Please use MailDeliveryJob instead.
|
20
|
+
MSG
|
21
|
+
end
|
22
|
+
|
15
23
|
def perform(mailer, mail_method, delivery_method, *args) #:nodoc:
|
16
24
|
mailer.constantize.public_send(mail_method, *args).send(delivery_method)
|
17
25
|
end
|
26
|
+
ruby2_keywords(:perform) if respond_to?(:ruby2_keywords, true)
|
18
27
|
|
19
28
|
private
|
20
29
|
# "Deserialize" the mailer class name by hand in case another argument
|
@@ -9,8 +9,12 @@ module ActionMailer
|
|
9
9
|
# An email was delivered.
|
10
10
|
def deliver(event)
|
11
11
|
info do
|
12
|
-
|
13
|
-
|
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
|
14
18
|
end
|
15
19
|
|
16
20
|
debug { event.payload[:mail] }
|
@@ -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
|
@@ -23,13 +23,14 @@ module ActionMailer
|
|
23
23
|
@processed_mailer = nil
|
24
24
|
@mail_message = nil
|
25
25
|
end
|
26
|
+
ruby2_keywords(:initialize) if respond_to?(:ruby2_keywords, true)
|
26
27
|
|
27
28
|
# Method calls are delegated to the Mail::Message that's ready to deliver.
|
28
29
|
def __getobj__ #:nodoc:
|
29
30
|
@mail_message ||= processed_mailer.message
|
30
31
|
end
|
31
32
|
|
32
|
-
# Unused except for delegator internals (dup,
|
33
|
+
# Unused except for delegator internals (dup, marshalling).
|
33
34
|
def __setobj__(mail_message) #:nodoc:
|
34
35
|
@mail_message = mail_message
|
35
36
|
end
|
@@ -135,9 +136,15 @@ module ActionMailer
|
|
135
136
|
"#deliver_later, 2. only touch the message *within your mailer " \
|
136
137
|
"method*, or 3. use a custom Active Job instead of #deliver_later."
|
137
138
|
else
|
138
|
-
args = @mailer_class.name, @action.to_s, delivery_method.to_s, *@args
|
139
139
|
job = @mailer_class.delivery_job
|
140
|
-
|
140
|
+
|
141
|
+
if job <= MailDeliveryJob
|
142
|
+
job.set(options).perform_later(
|
143
|
+
@mailer_class.name, @action.to_s, delivery_method.to_s, args: @args)
|
144
|
+
else
|
145
|
+
job.set(options).perform_later(
|
146
|
+
@mailer_class.name, @action.to_s, delivery_method.to_s, *@args)
|
147
|
+
end
|
141
148
|
end
|
142
149
|
end
|
143
150
|
end
|
@@ -115,17 +115,26 @@ module ActionMailer
|
|
115
115
|
super
|
116
116
|
end
|
117
117
|
end
|
118
|
+
ruby2_keywords(:method_missing) if respond_to?(:ruby2_keywords, true)
|
118
119
|
|
119
120
|
def respond_to_missing?(method, include_all = false)
|
120
121
|
@mailer.respond_to?(method, include_all)
|
121
122
|
end
|
122
123
|
end
|
123
124
|
|
125
|
+
class DeliveryJob < ActionMailer::DeliveryJob # :nodoc:
|
126
|
+
def perform(mailer, mail_method, delivery_method, params, *args)
|
127
|
+
mailer.constantize.with(params).public_send(mail_method, *args).send(delivery_method)
|
128
|
+
end
|
129
|
+
ruby2_keywords(:perform) if respond_to?(:ruby2_keywords, true)
|
130
|
+
end
|
131
|
+
|
124
132
|
class MessageDelivery < ActionMailer::MessageDelivery # :nodoc:
|
125
133
|
def initialize(mailer_class, action, params, *args)
|
126
134
|
super(mailer_class, action, *args)
|
127
135
|
@params = params
|
128
136
|
end
|
137
|
+
ruby2_keywords(:initialize) if respond_to?(:ruby2_keywords, true)
|
129
138
|
|
130
139
|
private
|
131
140
|
def processed_mailer
|
@@ -139,16 +148,25 @@ module ActionMailer
|
|
139
148
|
if processed?
|
140
149
|
super
|
141
150
|
else
|
142
|
-
|
143
|
-
|
151
|
+
job = delivery_job_class
|
152
|
+
|
153
|
+
if job <= MailDeliveryJob
|
154
|
+
job.set(options).perform_later(
|
155
|
+
@mailer_class.name, @action.to_s, delivery_method.to_s, params: @params, args: @args)
|
156
|
+
else
|
157
|
+
job.set(options).perform_later(
|
158
|
+
@mailer_class.name, @action.to_s, delivery_method.to_s, @params, *@args)
|
159
|
+
end
|
144
160
|
end
|
145
161
|
end
|
146
|
-
end
|
147
162
|
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
163
|
+
def delivery_job_class
|
164
|
+
if @mailer_class.delivery_job <= MailDeliveryJob
|
165
|
+
@mailer_class.delivery_job
|
166
|
+
else
|
167
|
+
Parameterized::DeliveryJob
|
168
|
+
end
|
169
|
+
end
|
152
170
|
end
|
153
171
|
end
|
154
172
|
end
|
@@ -31,22 +31,38 @@ module ActionMailer
|
|
31
31
|
interceptors.flatten.compact.each { |interceptor| register_preview_interceptor(interceptor) }
|
32
32
|
end
|
33
33
|
|
34
|
+
# Unregister one or more previously registered Interceptors.
|
35
|
+
def unregister_preview_interceptors(*interceptors)
|
36
|
+
interceptors.flatten.compact.each { |interceptor| unregister_preview_interceptor(interceptor) }
|
37
|
+
end
|
38
|
+
|
34
39
|
# Register an Interceptor which will be called before mail is previewed.
|
35
40
|
# Either a class or a string can be passed in as the Interceptor. If a
|
36
41
|
# string is passed in it will be constantized.
|
37
42
|
def register_preview_interceptor(interceptor)
|
38
|
-
preview_interceptor =
|
43
|
+
preview_interceptor = interceptor_class_for(interceptor)
|
44
|
+
|
45
|
+
unless preview_interceptors.include?(preview_interceptor)
|
46
|
+
preview_interceptors << preview_interceptor
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# Unregister a previously registered Interceptor.
|
51
|
+
# Either a class or a string can be passed in as the Interceptor. If a
|
52
|
+
# string is passed in it will be constantized.
|
53
|
+
def unregister_preview_interceptor(interceptor)
|
54
|
+
preview_interceptors.delete(interceptor_class_for(interceptor))
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
def interceptor_class_for(interceptor)
|
39
59
|
case interceptor
|
40
60
|
when String, Symbol
|
41
61
|
interceptor.to_s.camelize.constantize
|
42
62
|
else
|
43
63
|
interceptor
|
44
64
|
end
|
45
|
-
|
46
|
-
unless preview_interceptors.include?(preview_interceptor)
|
47
|
-
preview_interceptors << preview_interceptor
|
48
65
|
end
|
49
|
-
end
|
50
66
|
end
|
51
67
|
end
|
52
68
|
|
@@ -46,10 +46,25 @@ module ActionMailer
|
|
46
46
|
register_preview_interceptors(options.delete(:preview_interceptors))
|
47
47
|
register_observers(options.delete(:observers))
|
48
48
|
|
49
|
+
if delivery_job = options.delete(:delivery_job)
|
50
|
+
self.delivery_job = delivery_job.constantize
|
51
|
+
end
|
52
|
+
|
49
53
|
options.each { |k, v| send("#{k}=", v) }
|
50
54
|
end
|
51
55
|
|
52
|
-
ActiveSupport.on_load(:action_dispatch_integration_test)
|
56
|
+
ActiveSupport.on_load(:action_dispatch_integration_test) do
|
57
|
+
include ActionMailer::TestHelper
|
58
|
+
include ActionMailer::TestCase::ClearTestDeliveries
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
initializer "action_mailer.set_autoload_paths" do |app|
|
63
|
+
options = app.config.action_mailer
|
64
|
+
|
65
|
+
if options.show_previews && options.preview_path
|
66
|
+
ActiveSupport::Dependencies.autoload_paths << options.preview_path
|
67
|
+
end
|
53
68
|
end
|
54
69
|
|
55
70
|
initializer "action_mailer.compile_config_methods" do
|
@@ -69,12 +84,8 @@ module ActionMailer
|
|
69
84
|
|
70
85
|
if options.show_previews
|
71
86
|
app.routes.prepend do
|
72
|
-
get "/rails/mailers"
|
73
|
-
get "/rails/mailers/*path"
|
74
|
-
end
|
75
|
-
|
76
|
-
if options.preview_path
|
77
|
-
ActiveSupport::Dependencies.autoload_paths << options.preview_path
|
87
|
+
get "/rails/mailers" => "rails/mailers#index", internal: true
|
88
|
+
get "/rails/mailers/*path" => "rails/mailers#preview", internal: true
|
78
89
|
end
|
79
90
|
end
|
80
91
|
end
|
@@ -22,7 +22,6 @@ module ActionMailer
|
|
22
22
|
end
|
23
23
|
|
24
24
|
private
|
25
|
-
|
26
25
|
def clear_test_deliveries
|
27
26
|
if ActionMailer::Base.delivery_method == :test
|
28
27
|
ActionMailer::Base.deliveries.clear
|
@@ -76,7 +75,6 @@ module ActionMailer
|
|
76
75
|
end
|
77
76
|
|
78
77
|
private
|
79
|
-
|
80
78
|
def initialize_test_deliveries
|
81
79
|
set_delivery_method :test
|
82
80
|
@old_perform_deliveries = ActionMailer::Base.perform_deliveries
|
@@ -28,13 +28,13 @@ module ActionMailer
|
|
28
28
|
#
|
29
29
|
# assert_emails 2 do
|
30
30
|
# ContactMailer.welcome.deliver_now
|
31
|
-
# ContactMailer.welcome.
|
31
|
+
# ContactMailer.welcome.deliver_later
|
32
32
|
# end
|
33
33
|
# end
|
34
|
-
def assert_emails(number)
|
34
|
+
def assert_emails(number, &block)
|
35
35
|
if block_given?
|
36
36
|
original_count = ActionMailer::Base.deliveries.size
|
37
|
-
|
37
|
+
perform_enqueued_jobs(only: ->(job) { delivery_job_filter(job) }, &block)
|
38
38
|
new_count = ActionMailer::Base.deliveries.size
|
39
39
|
assert_equal number, new_count - original_count, "#{number} emails expected, but #{new_count - original_count} were sent"
|
40
40
|
else
|
@@ -90,10 +90,23 @@ module ActionMailer
|
|
90
90
|
# end
|
91
91
|
# end
|
92
92
|
def assert_enqueued_emails(number, &block)
|
93
|
-
assert_enqueued_jobs
|
93
|
+
assert_enqueued_jobs(number, only: ->(job) { delivery_job_filter(job) }, &block)
|
94
94
|
end
|
95
95
|
|
96
|
-
# Asserts that
|
96
|
+
# Asserts that a specific email has been enqueued, optionally
|
97
|
+
# matching arguments.
|
98
|
+
#
|
99
|
+
# def test_email
|
100
|
+
# ContactMailer.welcome.deliver_later
|
101
|
+
# assert_enqueued_email_with ContactMailer, :welcome
|
102
|
+
# end
|
103
|
+
#
|
104
|
+
# def test_email_with_arguments
|
105
|
+
# ContactMailer.welcome("Hello", "Goodbye").deliver_later
|
106
|
+
# assert_enqueued_email_with ContactMailer, :welcome, args: ["Hello", "Goodbye"]
|
107
|
+
# end
|
108
|
+
#
|
109
|
+
# If a block is passed, that block should cause the specified email
|
97
110
|
# to be enqueued.
|
98
111
|
#
|
99
112
|
# def test_email_in_block
|
@@ -106,20 +119,17 @@ module ActionMailer
|
|
106
119
|
#
|
107
120
|
# def test_parameterized_email
|
108
121
|
# assert_enqueued_email_with ContactMailer, :welcome,
|
109
|
-
# args: {email: 'user@example.com} do
|
122
|
+
# args: {email: 'user@example.com'} do
|
110
123
|
# ContactMailer.with(email: 'user@example.com').welcome.deliver_later
|
111
124
|
# end
|
112
125
|
# end
|
113
126
|
def assert_enqueued_email_with(mailer, method, args: nil, queue: "mailers", &block)
|
114
|
-
if args.is_a?
|
115
|
-
|
116
|
-
args = [mailer.to_s, method.to_s, "deliver_now", args]
|
127
|
+
args = if args.is_a?(Hash)
|
128
|
+
[mailer.to_s, method.to_s, "deliver_now", params: args, args: []]
|
117
129
|
else
|
118
|
-
|
119
|
-
args = [mailer.to_s, method.to_s, "deliver_now", *args]
|
130
|
+
[mailer.to_s, method.to_s, "deliver_now", args: Array(args)]
|
120
131
|
end
|
121
|
-
|
122
|
-
assert_enqueued_with(job: job, args: args, queue: queue, &block)
|
132
|
+
assert_enqueued_with(job: mailer.delivery_job, args: args, queue: queue, &block)
|
123
133
|
end
|
124
134
|
|
125
135
|
# Asserts that no emails are enqueued for later delivery.
|
@@ -138,7 +148,15 @@ module ActionMailer
|
|
138
148
|
# end
|
139
149
|
# end
|
140
150
|
def assert_no_enqueued_emails(&block)
|
141
|
-
|
151
|
+
assert_enqueued_emails 0, &block
|
142
152
|
end
|
153
|
+
|
154
|
+
private
|
155
|
+
def delivery_job_filter(job)
|
156
|
+
job_class = job.is_a?(Hash) ? job.fetch(:job) : job.class
|
157
|
+
|
158
|
+
Base.descendants.map(&:delivery_job).include?(job_class) ||
|
159
|
+
ActionMailer::Parameterized::DeliveryJob == job_class
|
160
|
+
end
|
143
161
|
end
|
144
162
|
end
|
data/lib/action_mailer.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
#--
|
4
|
-
# Copyright (c) 2004-
|
4
|
+
# Copyright (c) 2004-2019 David Heinemeier Hansson
|
5
5
|
#
|
6
6
|
# Permission is hereby granted, free of charge, to any person obtaining
|
7
7
|
# a copy of this software and associated documentation files (the
|
@@ -52,6 +52,7 @@ module ActionMailer
|
|
52
52
|
autoload :TestHelper
|
53
53
|
autoload :MessageDelivery
|
54
54
|
autoload :DeliveryJob
|
55
|
+
autoload :MailDeliveryJob
|
55
56
|
|
56
57
|
def self.eager_load!
|
57
58
|
super
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: actionmailer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 6.0.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Heinemeier Hansson
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-09-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: actionpack
|
@@ -16,42 +16,42 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - '='
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: 6.0.6
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - '='
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
26
|
+
version: 6.0.6
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: actionview
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - '='
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
33
|
+
version: 6.0.6
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - '='
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version:
|
40
|
+
version: 6.0.6
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: activejob
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - '='
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version:
|
47
|
+
version: 6.0.6
|
48
48
|
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - '='
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version:
|
54
|
+
version: 6.0.6
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: mail
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -86,8 +86,8 @@ dependencies:
|
|
86
86
|
- - "~>"
|
87
87
|
- !ruby/object:Gem::Version
|
88
88
|
version: '2.0'
|
89
|
-
description: Email on Rails. Compose, deliver,
|
90
|
-
|
89
|
+
description: Email on Rails. Compose, deliver, and test emails using the familiar
|
90
|
+
controller/view pattern. First-class support for multipart email and attachments.
|
91
91
|
email: david@loudthinking.com
|
92
92
|
executables: []
|
93
93
|
extensions: []
|
@@ -104,6 +104,7 @@ files:
|
|
104
104
|
- lib/action_mailer/gem_version.rb
|
105
105
|
- lib/action_mailer/inline_preview_interceptor.rb
|
106
106
|
- lib/action_mailer/log_subscriber.rb
|
107
|
+
- lib/action_mailer/mail_delivery_job.rb
|
107
108
|
- lib/action_mailer/mail_helper.rb
|
108
109
|
- lib/action_mailer/message_delivery.rb
|
109
110
|
- lib/action_mailer/parameterized.rb
|
@@ -117,12 +118,16 @@ files:
|
|
117
118
|
- lib/rails/generators/mailer/mailer_generator.rb
|
118
119
|
- lib/rails/generators/mailer/templates/application_mailer.rb.tt
|
119
120
|
- lib/rails/generators/mailer/templates/mailer.rb.tt
|
120
|
-
homepage:
|
121
|
+
homepage: https://rubyonrails.org
|
121
122
|
licenses:
|
122
123
|
- MIT
|
123
124
|
metadata:
|
124
|
-
|
125
|
-
changelog_uri: https://github.com/rails/rails/blob/
|
125
|
+
bug_tracker_uri: https://github.com/rails/rails/issues
|
126
|
+
changelog_uri: https://github.com/rails/rails/blob/v6.0.6/actionmailer/CHANGELOG.md
|
127
|
+
documentation_uri: https://api.rubyonrails.org/v6.0.6/
|
128
|
+
mailing_list_uri: https://discuss.rubyonrails.org/c/rubyonrails-talk
|
129
|
+
source_code_uri: https://github.com/rails/rails/tree/v6.0.6/actionmailer
|
130
|
+
rubygems_mfa_required: 'true'
|
126
131
|
post_install_message:
|
127
132
|
rdoc_options: []
|
128
133
|
require_paths:
|
@@ -131,7 +136,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
131
136
|
requirements:
|
132
137
|
- - ">="
|
133
138
|
- !ruby/object:Gem::Version
|
134
|
-
version: 2.
|
139
|
+
version: 2.5.0
|
135
140
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
136
141
|
requirements:
|
137
142
|
- - ">="
|
@@ -142,5 +147,5 @@ requirements:
|
|
142
147
|
rubygems_version: 3.3.3
|
143
148
|
signing_key:
|
144
149
|
specification_version: 4
|
145
|
-
summary: Email composition
|
150
|
+
summary: Email composition and delivery framework (part of Rails).
|
146
151
|
test_files: []
|