actionmailer 5.2.8 → 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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +57 -38
- data/MIT-LICENSE +1 -2
- data/README.rdoc +5 -39
- data/lib/action_mailer/base.rb +99 -59
- data/lib/action_mailer/delivery_job.rb +9 -0
- data/lib/action_mailer/delivery_methods.rb +1 -1
- 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 -8
- data/lib/action_mailer/mail_delivery_job.rb +43 -0
- data/lib/action_mailer/mail_with_error_handling.rb +10 -0
- data/lib/action_mailer/message_delivery.rb +37 -3
- data/lib/action_mailer/parameterized.rb +25 -7
- data/lib/action_mailer/preview.rb +22 -6
- data/lib/action_mailer/railtie.rb +18 -12
- data/lib/action_mailer/test_case.rb +0 -2
- data/lib/action_mailer/test_helper.rb +33 -15
- data/lib/action_mailer.rb +4 -2
- data/lib/rails/generators/mailer/USAGE +2 -3
- data/lib/rails/generators/mailer/mailer_generator.rb +1 -1
- metadata +39 -19
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 108f3c55ba55b639ad73688d53b9171c521de8f40dcad016babd5602b765743c
|
4
|
+
data.tar.gz: 3cb3c5659972171a6acc740ded03c04d949ede59a99e54e9bc37ae94db0106a2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 48d5ea4f1da22db3495b016ad056ab9f999b2badf04d4aa559b5028fd3ac529630831396c2c04a8acad4b211d4b865b0c0fa1f891c5ec8356310dc37b591804a
|
7
|
+
data.tar.gz: 22852825a97032541031e648936abff15db25b578a81746b6979f78db918e2a4ce3589d724d4f6baaf8f6639ffe25b631a56d7c29128b6bba7e8a5db3d7cf339
|
data/CHANGELOG.md
CHANGED
@@ -1,129 +1,148 @@
|
|
1
|
-
## Rails
|
1
|
+
## Rails 6.1.7.6 (August 22, 2023) ##
|
2
2
|
|
3
3
|
* No changes.
|
4
4
|
|
5
5
|
|
6
|
-
## Rails
|
6
|
+
## Rails 6.1.7.5 (August 22, 2023) ##
|
7
7
|
|
8
8
|
* No changes.
|
9
9
|
|
10
10
|
|
11
|
-
## Rails
|
11
|
+
## Rails 6.1.7.4 (June 26, 2023) ##
|
12
12
|
|
13
13
|
* No changes.
|
14
14
|
|
15
15
|
|
16
|
-
## Rails
|
16
|
+
## Rails 6.1.7.3 (March 13, 2023) ##
|
17
17
|
|
18
18
|
* No changes.
|
19
19
|
|
20
20
|
|
21
|
-
## Rails
|
21
|
+
## Rails 6.1.7.2 (January 24, 2023) ##
|
22
22
|
|
23
23
|
* No changes.
|
24
24
|
|
25
25
|
|
26
|
-
## Rails
|
26
|
+
## Rails 6.1.7.1 (January 17, 2023) ##
|
27
27
|
|
28
28
|
* No changes.
|
29
29
|
|
30
30
|
|
31
|
-
## Rails
|
31
|
+
## Rails 6.1.7 (September 09, 2022) ##
|
32
32
|
|
33
33
|
* No changes.
|
34
34
|
|
35
35
|
|
36
|
-
## Rails
|
36
|
+
## Rails 6.1.6.1 (July 12, 2022) ##
|
37
37
|
|
38
38
|
* No changes.
|
39
39
|
|
40
40
|
|
41
|
-
## Rails
|
41
|
+
## Rails 6.1.6 (May 09, 2022) ##
|
42
42
|
|
43
43
|
* No changes.
|
44
44
|
|
45
45
|
|
46
|
-
## Rails
|
46
|
+
## Rails 6.1.5.1 (April 26, 2022) ##
|
47
47
|
|
48
48
|
* No changes.
|
49
49
|
|
50
50
|
|
51
|
-
## Rails
|
51
|
+
## Rails 6.1.5 (March 09, 2022) ##
|
52
52
|
|
53
53
|
* No changes.
|
54
54
|
|
55
55
|
|
56
|
-
## Rails
|
56
|
+
## Rails 6.1.4.7 (March 08, 2022) ##
|
57
57
|
|
58
58
|
* No changes.
|
59
59
|
|
60
60
|
|
61
|
-
## Rails
|
61
|
+
## Rails 6.1.4.6 (February 11, 2022) ##
|
62
62
|
|
63
63
|
* No changes.
|
64
64
|
|
65
65
|
|
66
|
-
## Rails
|
66
|
+
## Rails 6.1.4.5 (February 11, 2022) ##
|
67
67
|
|
68
68
|
* No changes.
|
69
69
|
|
70
70
|
|
71
|
-
## Rails
|
71
|
+
## Rails 6.1.4.4 (December 15, 2021) ##
|
72
72
|
|
73
73
|
* No changes.
|
74
74
|
|
75
75
|
|
76
|
-
## Rails
|
76
|
+
## Rails 6.1.4.3 (December 14, 2021) ##
|
77
77
|
|
78
78
|
* No changes.
|
79
79
|
|
80
80
|
|
81
|
-
## Rails
|
81
|
+
## Rails 6.1.4.2 (December 14, 2021) ##
|
82
82
|
|
83
83
|
* No changes.
|
84
84
|
|
85
85
|
|
86
|
-
## Rails
|
86
|
+
## Rails 6.1.4.1 (August 19, 2021) ##
|
87
87
|
|
88
88
|
* No changes.
|
89
89
|
|
90
90
|
|
91
|
-
## Rails
|
91
|
+
## Rails 6.1.4 (June 24, 2021) ##
|
92
92
|
|
93
93
|
* No changes.
|
94
94
|
|
95
95
|
|
96
|
-
## Rails
|
96
|
+
## Rails 6.1.3.2 (May 05, 2021) ##
|
97
97
|
|
98
|
-
*
|
98
|
+
* No changes.
|
99
|
+
|
100
|
+
|
101
|
+
## Rails 6.1.3.1 (March 26, 2021) ##
|
102
|
+
|
103
|
+
* No changes.
|
104
|
+
|
105
|
+
|
106
|
+
## Rails 6.1.3 (February 17, 2021) ##
|
107
|
+
|
108
|
+
* No changes.
|
109
|
+
|
110
|
+
|
111
|
+
## Rails 6.1.2.1 (February 10, 2021) ##
|
112
|
+
|
113
|
+
* No changes.
|
114
|
+
|
115
|
+
|
116
|
+
## Rails 6.1.2 (February 09, 2021) ##
|
117
|
+
|
118
|
+
* No changes.
|
119
|
+
|
120
|
+
|
121
|
+
## Rails 6.1.1 (January 07, 2021) ##
|
99
122
|
|
100
|
-
|
123
|
+
* Sets default mailer queue to `"default"` in the mail assertions.
|
101
124
|
|
125
|
+
*Paul Keen*
|
102
126
|
|
103
|
-
## Rails 5.2.0 (April 09, 2018) ##
|
104
127
|
|
105
|
-
|
106
|
-
since it was supported in Rails 5.0 but not deprecated.
|
128
|
+
## Rails 6.1.0 (December 09, 2020) ##
|
107
129
|
|
108
|
-
|
130
|
+
* Change default queue name of the deliver (`:mailers`) job to be the job adapter's
|
131
|
+
default (`:default`).
|
109
132
|
|
110
|
-
*
|
133
|
+
*Rafael Mendonça França*
|
111
134
|
|
112
|
-
|
113
|
-
ContactMailer.welcome.deliver_later
|
114
|
-
end
|
135
|
+
* Remove deprecated `ActionMailer::Base.receive` in favor of [Action Mailbox](https://github.com/rails/rails/tree/master/actionmailbox).
|
115
136
|
|
116
|
-
*
|
137
|
+
*Rafael Mendonça França*
|
117
138
|
|
118
|
-
*
|
139
|
+
* Fix ActionMailer assertions don't work for parameterized mail with legacy delivery job.
|
119
140
|
|
120
|
-
|
121
|
-
self.delivery_job = MyCustomDeliveryJob
|
141
|
+
*bogdanvlviv*
|
122
142
|
|
123
|
-
|
124
|
-
end
|
143
|
+
* Added `email_address_with_name` to properly escape addresses with names.
|
125
144
|
|
126
|
-
*
|
145
|
+
*Sunny Ripert*
|
127
146
|
|
128
147
|
|
129
|
-
Please check [
|
148
|
+
Please check [6-0-stable](https://github.com/rails/rails/blob/6-0-stable/actionmailer/CHANGELOG.md) for previous changes.
|
data/MIT-LICENSE
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
Copyright (c) 2004-
|
1
|
+
Copyright (c) 2004-2022 David Heinemeier Hansson
|
2
2
|
|
3
3
|
Permission is hereby granted, free of charge, to any person obtaining
|
4
4
|
a copy of this software and associated documentation files (the
|
@@ -18,4 +18,3 @@ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
18
18
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
19
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
20
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
21
|
-
|
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
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "
|
3
|
+
require "action_mailer/mail_with_error_handling"
|
4
4
|
require "action_mailer/collector"
|
5
5
|
require "active_support/core_ext/string/inflections"
|
6
6
|
require "active_support/core_ext/hash/except"
|
@@ -16,11 +16,11 @@ module ActionMailer
|
|
16
16
|
#
|
17
17
|
# To use Action Mailer, you need to create a mailer model.
|
18
18
|
#
|
19
|
-
# $ rails generate mailer Notifier
|
19
|
+
# $ bin/rails generate mailer Notifier
|
20
20
|
#
|
21
21
|
# The generated model inherits from <tt>ApplicationMailer</tt> which in turn
|
22
22
|
# inherits from <tt>ActionMailer::Base</tt>. A mailer model defines methods
|
23
|
-
# used to generate an email message. In these methods, you can
|
23
|
+
# used to generate an email message. In these methods, you can set up variables to be used in
|
24
24
|
# the mailer views, options on the mail itself such as the <tt>:from</tt> address, and attachments.
|
25
25
|
#
|
26
26
|
# class ApplicationMailer < ActionMailer::Base
|
@@ -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>.
|
@@ -455,10 +455,6 @@ module ActionMailer
|
|
455
455
|
|
456
456
|
PROTECTED_IVARS = AbstractController::Rendering::DEFAULT_PROTECTED_INSTANCE_VARIABLES + [:@_action_has_layout]
|
457
457
|
|
458
|
-
def _protected_ivars # :nodoc:
|
459
|
-
PROTECTED_IVARS
|
460
|
-
end
|
461
|
-
|
462
458
|
helper ActionMailer::MailHelper
|
463
459
|
|
464
460
|
class_attribute :delivery_job, default: ::ActionMailer::DeliveryJob
|
@@ -475,11 +471,21 @@ module ActionMailer
|
|
475
471
|
observers.flatten.compact.each { |observer| register_observer(observer) }
|
476
472
|
end
|
477
473
|
|
474
|
+
# Unregister one or more previously registered Observers.
|
475
|
+
def unregister_observers(*observers)
|
476
|
+
observers.flatten.compact.each { |observer| unregister_observer(observer) }
|
477
|
+
end
|
478
|
+
|
478
479
|
# Register one or more Interceptors which will be called before mail is sent.
|
479
480
|
def register_interceptors(*interceptors)
|
480
481
|
interceptors.flatten.compact.each { |interceptor| register_interceptor(interceptor) }
|
481
482
|
end
|
482
483
|
|
484
|
+
# Unregister one or more previously registered Interceptors.
|
485
|
+
def unregister_interceptors(*interceptors)
|
486
|
+
interceptors.flatten.compact.each { |interceptor| unregister_interceptor(interceptor) }
|
487
|
+
end
|
488
|
+
|
483
489
|
# Register an Observer which will be notified when mail is delivered.
|
484
490
|
# Either a class, string or symbol can be passed in as the Observer.
|
485
491
|
# If a string or symbol is passed in it will be camelized and constantized.
|
@@ -487,6 +493,13 @@ module ActionMailer
|
|
487
493
|
Mail.register_observer(observer_class_for(observer))
|
488
494
|
end
|
489
495
|
|
496
|
+
# Unregister a previously registered Observer.
|
497
|
+
# Either a class, string or symbol can be passed in as the Observer.
|
498
|
+
# If a string or symbol is passed in it will be camelized and constantized.
|
499
|
+
def unregister_observer(observer)
|
500
|
+
Mail.unregister_observer(observer_class_for(observer))
|
501
|
+
end
|
502
|
+
|
490
503
|
# Register an Interceptor which will be called before mail is sent.
|
491
504
|
# Either a class, string or symbol can be passed in as the Interceptor.
|
492
505
|
# If a string or symbol is passed in it will be camelized and constantized.
|
@@ -494,6 +507,13 @@ module ActionMailer
|
|
494
507
|
Mail.register_interceptor(observer_class_for(interceptor))
|
495
508
|
end
|
496
509
|
|
510
|
+
# Unregister a previously registered Interceptor.
|
511
|
+
# Either a class, string or symbol can be passed in as the Interceptor.
|
512
|
+
# If a string or symbol is passed in it will be camelized and constantized.
|
513
|
+
def unregister_interceptor(interceptor)
|
514
|
+
Mail.unregister_interceptor(observer_class_for(interceptor))
|
515
|
+
end
|
516
|
+
|
497
517
|
def observer_class_for(value) # :nodoc:
|
498
518
|
case value
|
499
519
|
when String, Symbol
|
@@ -527,27 +547,6 @@ module ActionMailer
|
|
527
547
|
# config.action_mailer.default_options = { from: "no-reply@example.org" }
|
528
548
|
alias :default_options= :default
|
529
549
|
|
530
|
-
# Receives a raw email, parses it into an email object, decodes it,
|
531
|
-
# instantiates a new mailer, and passes the email object to the mailer
|
532
|
-
# object's +receive+ method.
|
533
|
-
#
|
534
|
-
# If you want your mailer to be able to process incoming messages, you'll
|
535
|
-
# need to implement a +receive+ method that accepts the raw email string
|
536
|
-
# as a parameter:
|
537
|
-
#
|
538
|
-
# class MyMailer < ActionMailer::Base
|
539
|
-
# def receive(mail)
|
540
|
-
# # ...
|
541
|
-
# end
|
542
|
-
# end
|
543
|
-
def receive(raw_mail)
|
544
|
-
ActiveSupport::Notifications.instrument("receive.action_mailer") do |payload|
|
545
|
-
mail = Mail.new(raw_mail)
|
546
|
-
set_payload_for_mail(payload, mail)
|
547
|
-
new.receive(mail)
|
548
|
-
end
|
549
|
-
end
|
550
|
-
|
551
550
|
# Wraps an email delivery inside of <tt>ActiveSupport::Notifications</tt> instrumentation.
|
552
551
|
#
|
553
552
|
# This method is actually called by the <tt>Mail::Message</tt> object itself
|
@@ -561,18 +560,26 @@ module ActionMailer
|
|
561
560
|
end
|
562
561
|
end
|
563
562
|
|
564
|
-
|
563
|
+
# Returns an email in the format "Name <email@example.com>".
|
564
|
+
def email_address_with_name(address, name)
|
565
|
+
Mail::Address.new.tap do |builder|
|
566
|
+
builder.address = address
|
567
|
+
builder.display_name = name
|
568
|
+
end.to_s
|
569
|
+
end
|
565
570
|
|
571
|
+
private
|
566
572
|
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[:
|
573
|
+
payload[:mail] = mail.encoded
|
574
|
+
payload[:mailer] = name
|
575
|
+
payload[:message_id] = mail.message_id
|
576
|
+
payload[:subject] = mail.subject
|
577
|
+
payload[:to] = mail.to
|
578
|
+
payload[:from] = mail.from
|
579
|
+
payload[:bcc] = mail.bcc if mail.bcc.present?
|
580
|
+
payload[:cc] = mail.cc if mail.cc.present?
|
581
|
+
payload[:date] = mail.date
|
582
|
+
payload[:perform_deliveries] = mail.perform_deliveries
|
576
583
|
end
|
577
584
|
|
578
585
|
def method_missing(method_name, *args)
|
@@ -582,6 +589,7 @@ module ActionMailer
|
|
582
589
|
super
|
583
590
|
end
|
584
591
|
end
|
592
|
+
ruby2_keywords(:method_missing) if respond_to?(:ruby2_keywords, true)
|
585
593
|
|
586
594
|
def respond_to_missing?(method, include_all = false)
|
587
595
|
action_methods.include?(method.to_s) || super
|
@@ -627,6 +635,11 @@ module ActionMailer
|
|
627
635
|
self.class.mailer_name
|
628
636
|
end
|
629
637
|
|
638
|
+
# Returns an email in the format "Name <email@example.com>".
|
639
|
+
def email_address_with_name(address, name)
|
640
|
+
self.class.email_address_with_name(address, name)
|
641
|
+
end
|
642
|
+
|
630
643
|
# Allows you to pass random and unusual headers to the new <tt>Mail::Message</tt>
|
631
644
|
# object which will add them to itself.
|
632
645
|
#
|
@@ -708,7 +721,7 @@ module ActionMailer
|
|
708
721
|
end
|
709
722
|
|
710
723
|
class LateAttachmentsProxy < SimpleDelegator
|
711
|
-
def inline;
|
724
|
+
def inline; self end
|
712
725
|
def []=(_name, _content); _raise_error end
|
713
726
|
|
714
727
|
private
|
@@ -829,8 +842,9 @@ module ActionMailer
|
|
829
842
|
@_mail_was_called = true
|
830
843
|
|
831
844
|
create_parts_from_responses(message, responses)
|
845
|
+
wrap_inline_attachments(message)
|
832
846
|
|
833
|
-
#
|
847
|
+
# Set up content type, reapply charset and handle parts order
|
834
848
|
message.content_type = set_content_type(message, content_type, headers[:content_type])
|
835
849
|
message.charset = charset
|
836
850
|
|
@@ -843,7 +857,6 @@ module ActionMailer
|
|
843
857
|
end
|
844
858
|
|
845
859
|
private
|
846
|
-
|
847
860
|
# Used by #mail to set the content type of the message.
|
848
861
|
#
|
849
862
|
# It will use the given +user_content_type+, or multipart if the mail
|
@@ -859,7 +872,7 @@ module ActionMailer
|
|
859
872
|
when user_content_type.present?
|
860
873
|
user_content_type
|
861
874
|
when m.has_attachments?
|
862
|
-
if m.attachments.
|
875
|
+
if m.attachments.all?(&:inline?)
|
863
876
|
["multipart", "related", params]
|
864
877
|
else
|
865
878
|
["multipart", "mixed", params]
|
@@ -877,7 +890,7 @@ module ActionMailer
|
|
877
890
|
# If the subject has interpolations, you can pass them through the +interpolations+ parameter.
|
878
891
|
def default_i18n_subject(interpolations = {}) # :doc:
|
879
892
|
mailer_scope = self.class.mailer_name.tr("/", ".")
|
880
|
-
I18n.t(:subject, interpolations.merge(scope: [mailer_scope, action_name], default: action_name.humanize))
|
893
|
+
I18n.t(:subject, **interpolations.merge(scope: [mailer_scope, action_name], default: action_name.humanize))
|
881
894
|
end
|
882
895
|
|
883
896
|
# Emails do not support relative path links.
|
@@ -886,12 +899,9 @@ module ActionMailer
|
|
886
899
|
end
|
887
900
|
|
888
901
|
def apply_defaults(headers)
|
889
|
-
default_values = self.class.default.
|
890
|
-
|
891
|
-
|
892
|
-
compute_default(value)
|
893
|
-
]
|
894
|
-
end.to_h
|
902
|
+
default_values = self.class.default.transform_values do |value|
|
903
|
+
compute_default(value)
|
904
|
+
end
|
895
905
|
|
896
906
|
headers_with_defaults = headers.reverse_merge(default_values)
|
897
907
|
headers_with_defaults[:subject] ||= default_i18n_subject
|
@@ -914,11 +924,9 @@ module ActionMailer
|
|
914
924
|
assignable.each { |k, v| message[k] = v }
|
915
925
|
end
|
916
926
|
|
917
|
-
def collect_responses(headers)
|
927
|
+
def collect_responses(headers, &block)
|
918
928
|
if block_given?
|
919
|
-
|
920
|
-
yield(collector)
|
921
|
-
collector.responses
|
929
|
+
collect_responses_from_block(headers, &block)
|
922
930
|
elsif headers[:body]
|
923
931
|
collect_responses_from_text(headers)
|
924
932
|
else
|
@@ -926,6 +934,13 @@ module ActionMailer
|
|
926
934
|
end
|
927
935
|
end
|
928
936
|
|
937
|
+
def collect_responses_from_block(headers)
|
938
|
+
templates_name = headers[:template_name] || action_name
|
939
|
+
collector = ActionMailer::Collector.new(lookup_context) { render(templates_name) }
|
940
|
+
yield(collector)
|
941
|
+
collector.responses
|
942
|
+
end
|
943
|
+
|
929
944
|
def collect_responses_from_text(headers)
|
930
945
|
[{
|
931
946
|
body: headers.delete(:body),
|
@@ -938,10 +953,10 @@ module ActionMailer
|
|
938
953
|
templates_name = headers[:template_name] || action_name
|
939
954
|
|
940
955
|
each_template(Array(templates_path), templates_name).map do |template|
|
941
|
-
|
956
|
+
format = template.format || self.formats.first
|
942
957
|
{
|
943
|
-
body: render(template: template),
|
944
|
-
content_type:
|
958
|
+
body: render(template: template, formats: [format]),
|
959
|
+
content_type: Mime[format].to_s
|
945
960
|
}
|
946
961
|
end
|
947
962
|
end
|
@@ -951,7 +966,28 @@ module ActionMailer
|
|
951
966
|
if templates.empty?
|
952
967
|
raise ActionView::MissingTemplate.new(paths, name, paths, false, "mailer")
|
953
968
|
else
|
954
|
-
templates.uniq(&:
|
969
|
+
templates.uniq(&:format).each(&block)
|
970
|
+
end
|
971
|
+
end
|
972
|
+
|
973
|
+
def wrap_inline_attachments(message)
|
974
|
+
# If we have both types of attachment, wrap all the inline attachments
|
975
|
+
# in multipart/related, but not the actual attachments
|
976
|
+
if message.attachments.detect(&:inline?) && message.attachments.detect { |a| !a.inline? }
|
977
|
+
related = Mail::Part.new
|
978
|
+
related.content_type = "multipart/related"
|
979
|
+
mixed = [ related ]
|
980
|
+
|
981
|
+
message.parts.each do |p|
|
982
|
+
if p.attachment? && !p.inline?
|
983
|
+
mixed << p
|
984
|
+
else
|
985
|
+
related.add_part(p)
|
986
|
+
end
|
987
|
+
end
|
988
|
+
|
989
|
+
message.parts.clear
|
990
|
+
mixed.each { |c| message.add_part(c) }
|
955
991
|
end
|
956
992
|
end
|
957
993
|
|
@@ -983,7 +1019,11 @@ module ActionMailer
|
|
983
1019
|
end
|
984
1020
|
|
985
1021
|
def instrument_name
|
986
|
-
"action_mailer"
|
1022
|
+
"action_mailer"
|
1023
|
+
end
|
1024
|
+
|
1025
|
+
def _protected_ivars
|
1026
|
+
PROTECTED_IVARS
|
987
1027
|
end
|
988
1028
|
|
989
1029
|
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 7.0.
|
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
|
@@ -49,7 +49,7 @@ module ActionMailer
|
|
49
49
|
# arguments: '-i'
|
50
50
|
def add_delivery_method(symbol, klass, default_options = {})
|
51
51
|
class_attribute(:"#{symbol}_settings") unless respond_to?(:"#{symbol}_settings")
|
52
|
-
|
52
|
+
public_send(:"#{symbol}_settings=", default_options)
|
53
53
|
self.delivery_methods = delivery_methods.merge(symbol.to_sym => klass).freeze
|
54
54
|
end
|
55
55
|
|
@@ -9,19 +9,17 @@ 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] }
|
17
21
|
end
|
18
22
|
|
19
|
-
# An email was received.
|
20
|
-
def receive(event)
|
21
|
-
info { "Received mail (#{event.duration.round(1)}ms)" }
|
22
|
-
debug { event.payload[:mail] }
|
23
|
-
end
|
24
|
-
|
25
23
|
# An email was generated.
|
26
24
|
def process(event)
|
27
25
|
debug do
|
@@ -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
|
@@ -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
|
@@ -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
|
@@ -52,12 +53,14 @@ module ActionMailer
|
|
52
53
|
# Notifier.welcome(User.first).deliver_later!
|
53
54
|
# Notifier.welcome(User.first).deliver_later!(wait: 1.hour)
|
54
55
|
# Notifier.welcome(User.first).deliver_later!(wait_until: 10.hours.from_now)
|
56
|
+
# Notifier.welcome(User.first).deliver_later!(priority: 10)
|
55
57
|
#
|
56
58
|
# Options:
|
57
59
|
#
|
58
60
|
# * <tt>:wait</tt> - Enqueue the email to be delivered with a delay
|
59
61
|
# * <tt>:wait_until</tt> - Enqueue the email to be delivered at (after) a specific date / time
|
60
62
|
# * <tt>:queue</tt> - Enqueue the email on the specified queue
|
63
|
+
# * <tt>:priority</tt> - Enqueues the email with the specified priority
|
61
64
|
#
|
62
65
|
# By default, the email will be enqueued using <tt>ActionMailer::DeliveryJob</tt>. Each
|
63
66
|
# <tt>ActionMailer::Base</tt> class can specify the job to use by setting the class variable
|
@@ -76,12 +79,14 @@ module ActionMailer
|
|
76
79
|
# Notifier.welcome(User.first).deliver_later
|
77
80
|
# Notifier.welcome(User.first).deliver_later(wait: 1.hour)
|
78
81
|
# Notifier.welcome(User.first).deliver_later(wait_until: 10.hours.from_now)
|
82
|
+
# Notifier.welcome(User.first).deliver_later(priority: 10)
|
79
83
|
#
|
80
84
|
# Options:
|
81
85
|
#
|
82
86
|
# * <tt>:wait</tt> - Enqueue the email to be delivered with a delay.
|
83
87
|
# * <tt>:wait_until</tt> - Enqueue the email to be delivered at (after) a specific date / time.
|
84
88
|
# * <tt>:queue</tt> - Enqueue the email on the specified queue.
|
89
|
+
# * <tt>:priority</tt> - Enqueues the email with the specified priority
|
85
90
|
#
|
86
91
|
# By default, the email will be enqueued using <tt>ActionMailer::DeliveryJob</tt>. Each
|
87
92
|
# <tt>ActionMailer::Base</tt> class can specify the job to use by setting the class variable
|
@@ -135,9 +140,38 @@ module ActionMailer
|
|
135
140
|
"#deliver_later, 2. only touch the message *within your mailer " \
|
136
141
|
"method*, or 3. use a custom Active Job instead of #deliver_later."
|
137
142
|
else
|
138
|
-
args = @mailer_class.name, @action.to_s, delivery_method.to_s, *@args
|
139
143
|
job = @mailer_class.delivery_job
|
140
|
-
|
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 != :**
|
141
175
|
end
|
142
176
|
end
|
143
177
|
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
|
|
@@ -98,7 +114,7 @@ module ActionMailer
|
|
98
114
|
|
99
115
|
# Returns the underscored name of the mailer preview without the suffix.
|
100
116
|
def preview_name
|
101
|
-
name.
|
117
|
+
name.delete_suffix("Preview").underscore
|
102
118
|
end
|
103
119
|
|
104
120
|
private
|
@@ -18,11 +18,6 @@ module ActionMailer
|
|
18
18
|
paths = app.config.paths
|
19
19
|
options = app.config.action_mailer
|
20
20
|
|
21
|
-
if app.config.force_ssl
|
22
|
-
options.default_url_options ||= {}
|
23
|
-
options.default_url_options[:protocol] ||= "https"
|
24
|
-
end
|
25
|
-
|
26
21
|
options.assets_dir ||= paths["public"].first
|
27
22
|
options.javascripts_dir ||= paths["public/javascripts"].first
|
28
23
|
options.stylesheets_dir ||= paths["public/stylesheets"].first
|
@@ -46,10 +41,25 @@ module ActionMailer
|
|
46
41
|
register_preview_interceptors(options.delete(:preview_interceptors))
|
47
42
|
register_observers(options.delete(:observers))
|
48
43
|
|
44
|
+
if delivery_job = options.delete(:delivery_job)
|
45
|
+
self.delivery_job = delivery_job.constantize
|
46
|
+
end
|
47
|
+
|
49
48
|
options.each { |k, v| send("#{k}=", v) }
|
50
49
|
end
|
51
50
|
|
52
|
-
ActiveSupport.on_load(:action_dispatch_integration_test)
|
51
|
+
ActiveSupport.on_load(:action_dispatch_integration_test) do
|
52
|
+
include ActionMailer::TestHelper
|
53
|
+
include ActionMailer::TestCase::ClearTestDeliveries
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
initializer "action_mailer.set_autoload_paths" do |app|
|
58
|
+
options = app.config.action_mailer
|
59
|
+
|
60
|
+
if options.show_previews && options.preview_path
|
61
|
+
ActiveSupport::Dependencies.autoload_paths << options.preview_path
|
62
|
+
end
|
53
63
|
end
|
54
64
|
|
55
65
|
initializer "action_mailer.compile_config_methods" do
|
@@ -69,12 +79,8 @@ module ActionMailer
|
|
69
79
|
|
70
80
|
if options.show_previews
|
71
81
|
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
|
82
|
+
get "/rails/mailers" => "rails/mailers#index", internal: true
|
83
|
+
get "/rails/mailers/*path" => "rails/mailers#preview", internal: true
|
78
84
|
end
|
79
85
|
end
|
80
86
|
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
|
-
def assert_enqueued_email_with(mailer, method, args: nil, queue: "
|
114
|
-
if args.is_a?
|
115
|
-
|
116
|
-
args = [mailer.to_s, method.to_s, "deliver_now", args]
|
126
|
+
def assert_enqueued_email_with(mailer, method, args: nil, queue: ActionMailer::Base.deliver_later_queue_name || "default", &block)
|
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.to_s, &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-2022 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,11 +52,12 @@ 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
|
58
59
|
|
59
|
-
require "
|
60
|
+
require "action_mailer/mail_with_error_handling"
|
60
61
|
Mail.eager_autoload!
|
61
62
|
end
|
62
63
|
end
|
@@ -66,4 +67,5 @@ autoload :Mime, "action_dispatch/http/mime_type"
|
|
66
67
|
ActiveSupport.on_load(:action_view) do
|
67
68
|
ActionView::Base.default_formats ||= Mime::SET.symbols
|
68
69
|
ActionView::Template::Types.delegate_to Mime
|
70
|
+
ActionView::LookupContext::DetailsKey.clear
|
69
71
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Description:
|
2
2
|
============
|
3
|
-
|
3
|
+
Generates a new mailer and its views. Passes the mailer name, either
|
4
4
|
CamelCased or under_scored, and an optional list of emails as arguments.
|
5
5
|
|
6
6
|
This generates a mailer class in app/mailers and invokes your template
|
@@ -8,10 +8,9 @@ Description:
|
|
8
8
|
|
9
9
|
Example:
|
10
10
|
========
|
11
|
-
rails generate mailer Notifications signup forgot_password invoice
|
11
|
+
bin/rails generate mailer Notifications signup forgot_password invoice
|
12
12
|
|
13
13
|
creates a Notifications mailer class, views, and test:
|
14
14
|
Mailer: app/mailers/notifications_mailer.rb
|
15
15
|
Views: app/views/notifications_mailer/signup.text.erb [...]
|
16
16
|
Test: test/mailers/notifications_mailer_test.rb
|
17
|
-
|
metadata
CHANGED
@@ -1,57 +1,71 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: actionmailer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 6.1.7.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Heinemeier Hansson
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-08-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activesupport
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 6.1.7.6
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 6.1.7.6
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: actionpack
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
16
30
|
requirements:
|
17
31
|
- - '='
|
18
32
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
33
|
+
version: 6.1.7.6
|
20
34
|
type: :runtime
|
21
35
|
prerelease: false
|
22
36
|
version_requirements: !ruby/object:Gem::Requirement
|
23
37
|
requirements:
|
24
38
|
- - '='
|
25
39
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
40
|
+
version: 6.1.7.6
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: actionview
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
30
44
|
requirements:
|
31
45
|
- - '='
|
32
46
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
47
|
+
version: 6.1.7.6
|
34
48
|
type: :runtime
|
35
49
|
prerelease: false
|
36
50
|
version_requirements: !ruby/object:Gem::Requirement
|
37
51
|
requirements:
|
38
52
|
- - '='
|
39
53
|
- !ruby/object:Gem::Version
|
40
|
-
version:
|
54
|
+
version: 6.1.7.6
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
56
|
name: activejob
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
44
58
|
requirements:
|
45
59
|
- - '='
|
46
60
|
- !ruby/object:Gem::Version
|
47
|
-
version:
|
61
|
+
version: 6.1.7.6
|
48
62
|
type: :runtime
|
49
63
|
prerelease: false
|
50
64
|
version_requirements: !ruby/object:Gem::Requirement
|
51
65
|
requirements:
|
52
66
|
- - '='
|
53
67
|
- !ruby/object:Gem::Version
|
54
|
-
version:
|
68
|
+
version: 6.1.7.6
|
55
69
|
- !ruby/object:Gem::Dependency
|
56
70
|
name: mail
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -86,8 +100,8 @@ dependencies:
|
|
86
100
|
- - "~>"
|
87
101
|
- !ruby/object:Gem::Version
|
88
102
|
version: '2.0'
|
89
|
-
description: Email on Rails. Compose, deliver,
|
90
|
-
|
103
|
+
description: Email on Rails. Compose, deliver, and test emails using the familiar
|
104
|
+
controller/view pattern. First-class support for multipart email and attachments.
|
91
105
|
email: david@loudthinking.com
|
92
106
|
executables: []
|
93
107
|
extensions: []
|
@@ -104,7 +118,9 @@ files:
|
|
104
118
|
- lib/action_mailer/gem_version.rb
|
105
119
|
- lib/action_mailer/inline_preview_interceptor.rb
|
106
120
|
- lib/action_mailer/log_subscriber.rb
|
121
|
+
- lib/action_mailer/mail_delivery_job.rb
|
107
122
|
- lib/action_mailer/mail_helper.rb
|
123
|
+
- lib/action_mailer/mail_with_error_handling.rb
|
108
124
|
- lib/action_mailer/message_delivery.rb
|
109
125
|
- lib/action_mailer/parameterized.rb
|
110
126
|
- lib/action_mailer/preview.rb
|
@@ -117,13 +133,17 @@ files:
|
|
117
133
|
- lib/rails/generators/mailer/mailer_generator.rb
|
118
134
|
- lib/rails/generators/mailer/templates/application_mailer.rb.tt
|
119
135
|
- lib/rails/generators/mailer/templates/mailer.rb.tt
|
120
|
-
homepage:
|
136
|
+
homepage: https://rubyonrails.org
|
121
137
|
licenses:
|
122
138
|
- MIT
|
123
139
|
metadata:
|
124
|
-
|
125
|
-
changelog_uri: https://github.com/rails/rails/blob/
|
126
|
-
|
140
|
+
bug_tracker_uri: https://github.com/rails/rails/issues
|
141
|
+
changelog_uri: https://github.com/rails/rails/blob/v6.1.7.6/actionmailer/CHANGELOG.md
|
142
|
+
documentation_uri: https://api.rubyonrails.org/v6.1.7.6/
|
143
|
+
mailing_list_uri: https://discuss.rubyonrails.org/c/rubyonrails-talk
|
144
|
+
source_code_uri: https://github.com/rails/rails/tree/v6.1.7.6/actionmailer
|
145
|
+
rubygems_mfa_required: 'true'
|
146
|
+
post_install_message:
|
127
147
|
rdoc_options: []
|
128
148
|
require_paths:
|
129
149
|
- lib
|
@@ -131,7 +151,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
131
151
|
requirements:
|
132
152
|
- - ">="
|
133
153
|
- !ruby/object:Gem::Version
|
134
|
-
version: 2.
|
154
|
+
version: 2.5.0
|
135
155
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
136
156
|
requirements:
|
137
157
|
- - ">="
|
@@ -139,8 +159,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
139
159
|
version: '0'
|
140
160
|
requirements:
|
141
161
|
- none
|
142
|
-
rubygems_version: 3.
|
143
|
-
signing_key:
|
162
|
+
rubygems_version: 3.3.3
|
163
|
+
signing_key:
|
144
164
|
specification_version: 4
|
145
|
-
summary: Email composition
|
165
|
+
summary: Email composition and delivery framework (part of Rails).
|
146
166
|
test_files: []
|