actionmailer 4.2.11 → 5.1.0
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 +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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: fa279066a475c28daeb75c73d61bc75b20d79dcd
|
4
|
+
data.tar.gz: d470281fac5bfd09afdb3fd6e53de8de5a454b40
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d1fa1024d0423ac5d26b0c6b28958ca059caac10d5efe7a017209a92414786f2ddab63dd06962dddee8e4c0e84151f395a7f740d51d0e59cdc8472cdc156efd1
|
7
|
+
data.tar.gz: 0b17b0eba794f38550fd074829ec7c7f64d8028ace9ccae242e88297c964ab36a111cd49f5e1bcc7f77c54f3f6e5961d73dcb56cdaec783256f7de34f52a5761
|
data/CHANGELOG.md
CHANGED
@@ -1,152 +1,33 @@
|
|
1
|
-
## Rails
|
1
|
+
## Rails 5.1.0 (April 27, 2017) ##
|
2
2
|
|
3
|
-
*
|
4
|
-
|
5
|
-
|
6
|
-
## Rails 4.2.10 (September 27, 2017) ##
|
7
|
-
|
8
|
-
* No changes.
|
9
|
-
|
10
|
-
|
11
|
-
## Rails 4.2.9 (June 26, 2017) ##
|
12
|
-
|
13
|
-
* No changes.
|
14
|
-
|
15
|
-
|
16
|
-
## Rails 4.2.8 (February 21, 2017) ##
|
17
|
-
|
18
|
-
* No changes.
|
19
|
-
|
20
|
-
|
21
|
-
## Rails 4.2.7 (July 12, 2016) ##
|
22
|
-
|
23
|
-
* Removes `-t` from default Sendmail arguments to match the underlying
|
24
|
-
`Mail::Sendmail` setting.
|
25
|
-
|
26
|
-
*Clayton Liggitt*
|
27
|
-
|
28
|
-
|
29
|
-
## Rails 4.2.6 (March 07, 2016) ##
|
30
|
-
|
31
|
-
* No changes.
|
32
|
-
|
33
|
-
|
34
|
-
## Rails 4.2.5.2 (February 26, 2016) ##
|
35
|
-
|
36
|
-
* No changes.
|
37
|
-
|
38
|
-
|
39
|
-
## Rails 4.2.5.1 (January 25, 2015) ##
|
40
|
-
|
41
|
-
* No changes.
|
42
|
-
|
43
|
-
|
44
|
-
## Rails 4.2.5 (November 12, 2015) ##
|
45
|
-
|
46
|
-
* No changes.
|
47
|
-
|
48
|
-
|
49
|
-
## Rails 4.2.4 (August 24, 2015) ##
|
50
|
-
|
51
|
-
* No Changes *
|
52
|
-
|
53
|
-
|
54
|
-
## Rails 4.2.3 (June 25, 2015) ##
|
55
|
-
|
56
|
-
* `assert_emails` in block form use the given number as expected value.
|
57
|
-
This makes the error message much easier to understand.
|
3
|
+
* Add `:args` to `process.action_mailer` event.
|
58
4
|
|
59
5
|
*Yuji Yaginuma*
|
60
6
|
|
61
|
-
*
|
62
|
-
a
|
63
|
-
|
64
|
-
*Remo Mueller*
|
65
|
-
|
66
|
-
* Mailer previews no longer crash when the `mail` method wasn't called
|
67
|
-
(`NullMail`).
|
68
|
-
|
69
|
-
Fixes #19849.
|
70
|
-
|
71
|
-
*Yves Senn*
|
72
|
-
|
73
|
-
* Make sure labels and values line up in mailer previews.
|
74
|
-
|
75
|
-
*Yves Senn*
|
76
|
-
|
77
|
-
|
78
|
-
## Rails 4.2.2 (June 16, 2015) ##
|
79
|
-
|
80
|
-
* No Changes *
|
81
|
-
|
82
|
-
|
83
|
-
## Rails 4.2.1 (March 19, 2015) ##
|
84
|
-
|
85
|
-
* No Changes *
|
86
|
-
|
87
|
-
|
88
|
-
## Rails 4.2.0 (December 20, 2014) ##
|
89
|
-
|
90
|
-
* `MailerGenerator` now generates layouts by default. The HTML mailer layout
|
91
|
-
now includes `<html>` and `<body>` tags which improve the spam rating in
|
92
|
-
some spam detection engines. Mailers now inherit from `ApplicationMailer`
|
93
|
-
which sets the default layout.
|
94
|
-
|
95
|
-
*Andy Jeffries*
|
96
|
-
|
97
|
-
* `link_to` and `url_for` now generate URLs by default in templates.
|
98
|
-
Passing `only_path: false` is no longer needed.
|
99
|
-
|
100
|
-
Fixes #16497 and #16589.
|
101
|
-
|
102
|
-
*Xavier Noria*, *Richard Schneeman*
|
103
|
-
|
104
|
-
* Attachments can now be added while rendering the mail template.
|
105
|
-
|
106
|
-
Fixes #16974.
|
107
|
-
|
108
|
-
*Christian Felder*
|
109
|
-
|
110
|
-
* Add `#deliver_later` and `#deliver_now` methods and deprecate `#deliver` in
|
111
|
-
favor of `#deliver_now`. `#deliver_later` will enqueue a job to render and
|
112
|
-
deliver the mail instead of delivering it immediately. The job is enqueued
|
113
|
-
using the new Active Job framework in Rails and will use the queue that you
|
114
|
-
have configured in Rails.
|
115
|
-
|
116
|
-
*DHH*, *Abdelkader Boudih*, *Cristian Bica*
|
117
|
-
|
118
|
-
* `ActionMailer::Previews` are now class methods instead of instance methods.
|
119
|
-
|
120
|
-
*Cristian Bica*
|
121
|
-
|
122
|
-
* Deprecate `*_path` helpers in email views. They generated broken links in
|
123
|
-
email views and were not the intention of most developers. The `*_url`
|
124
|
-
helper is recommended instead.
|
125
|
-
|
126
|
-
*Richard Schneeman*
|
127
|
-
|
128
|
-
* Raise an exception when attachments are added after `mail` is called.
|
129
|
-
This is a safeguard to prevent invalid emails.
|
7
|
+
* Add parameterized invocation of mailers as a way to share before filters and defaults between actions.
|
8
|
+
See `ActionMailer::Parameterized` for a full example of the benefit.
|
130
9
|
|
131
|
-
|
10
|
+
*DHH*
|
132
11
|
|
133
|
-
|
12
|
+
* Allow lambdas to be used as lazy defaults in addition to procs.
|
134
13
|
|
135
|
-
*
|
14
|
+
*DHH*
|
136
15
|
|
137
|
-
|
138
|
-
|
16
|
+
* Mime type: allow to custom content type when setting body in headers
|
17
|
+
and attachments.
|
139
18
|
|
140
|
-
|
19
|
+
Example:
|
141
20
|
|
142
|
-
|
21
|
+
def test_emails
|
22
|
+
attachments["invoice.pdf"] = "This is test File content"
|
23
|
+
mail(body: "Hello there", content_type: "text/html")
|
24
|
+
end
|
143
25
|
|
144
|
-
*
|
145
|
-
`config.action_mailer.preview_interceptors`.
|
26
|
+
*Minh Quy*
|
146
27
|
|
147
|
-
|
28
|
+
* Exception handling: use `rescue_from` to handle exceptions raised by
|
29
|
+
mailer actions, by message delivery, and by deferred delivery jobs.
|
148
30
|
|
149
|
-
*
|
31
|
+
*Jeremy Daer*
|
150
32
|
|
151
|
-
Please check [
|
152
|
-
for previous changes.
|
33
|
+
Please check [5-0-stable](https://github.com/rails/rails/blob/5-0-stable/actionmailer/CHANGELOG.md) for previous changes.
|
data/MIT-LICENSE
CHANGED
data/README.rdoc
CHANGED
@@ -146,11 +146,11 @@ The Base class has the full list of configuration options. Here's an example:
|
|
146
146
|
|
147
147
|
The latest version of Action Mailer can be installed with RubyGems:
|
148
148
|
|
149
|
-
|
149
|
+
$ gem install actionmailer
|
150
150
|
|
151
151
|
Source code can be downloaded as part of the Rails project on GitHub
|
152
152
|
|
153
|
-
* https://github.com/rails/rails/tree/
|
153
|
+
* https://github.com/rails/rails/tree/master/actionmailer
|
154
154
|
|
155
155
|
|
156
156
|
== License
|
@@ -173,4 +173,3 @@ Bug reports can be filed for the Ruby on Rails project here:
|
|
173
173
|
Feature requests should be discussed on the rails-core mailing list here:
|
174
174
|
|
175
175
|
* https://groups.google.com/forum/?fromgroups#!forum/rubyonrails-core
|
176
|
-
|
data/lib/action_mailer.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
#--
|
2
|
-
# Copyright (c) 2004-
|
2
|
+
# Copyright (c) 2004-2017 David Heinemeier Hansson
|
3
3
|
#
|
4
4
|
# Permission is hereby granted, free of charge, to any person obtaining
|
5
5
|
# a copy of this software and associated documentation files (the
|
@@ -21,15 +21,15 @@
|
|
21
21
|
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
22
|
#++
|
23
23
|
|
24
|
-
require
|
25
|
-
require
|
24
|
+
require "abstract_controller"
|
25
|
+
require "action_mailer/version"
|
26
26
|
|
27
27
|
# Common Active Support usage in Action Mailer
|
28
|
-
require
|
29
|
-
require
|
30
|
-
require
|
31
|
-
require
|
32
|
-
require
|
28
|
+
require "active_support/rails"
|
29
|
+
require "active_support/core_ext/class"
|
30
|
+
require "active_support/core_ext/module/attr_internal"
|
31
|
+
require "active_support/core_ext/string/inflections"
|
32
|
+
require "active_support/lazy_load_hooks"
|
33
33
|
|
34
34
|
module ActionMailer
|
35
35
|
extend ::ActiveSupport::Autoload
|
@@ -42,15 +42,16 @@ module ActionMailer
|
|
42
42
|
autoload :DeliveryMethods
|
43
43
|
autoload :InlinePreviewInterceptor
|
44
44
|
autoload :MailHelper
|
45
|
+
autoload :Parameterized
|
45
46
|
autoload :Preview
|
46
|
-
autoload :Previews,
|
47
|
+
autoload :Previews, "action_mailer/preview"
|
47
48
|
autoload :TestCase
|
48
49
|
autoload :TestHelper
|
49
50
|
autoload :MessageDelivery
|
50
51
|
autoload :DeliveryJob
|
51
52
|
end
|
52
53
|
|
53
|
-
autoload :Mime,
|
54
|
+
autoload :Mime, "action_dispatch/http/mime_type"
|
54
55
|
|
55
56
|
ActiveSupport.on_load(:action_view) do
|
56
57
|
ActionView::Base.default_formats ||= Mime::SET.symbols
|
data/lib/action_mailer/base.rb
CHANGED
@@ -1,10 +1,11 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
1
|
+
require "mail"
|
2
|
+
require "action_mailer/collector"
|
3
|
+
require "active_support/core_ext/string/inflections"
|
4
|
+
require "active_support/core_ext/hash/except"
|
5
|
+
require "active_support/core_ext/module/anonymous"
|
6
6
|
|
7
|
-
require
|
7
|
+
require "action_mailer/log_subscriber"
|
8
|
+
require "action_mailer/rescuable"
|
8
9
|
|
9
10
|
module ActionMailer
|
10
11
|
# Action Mailer allows you to send email from your application using a mailer model and views.
|
@@ -21,11 +22,11 @@ module ActionMailer
|
|
21
22
|
# the mailer views, options on the mail itself such as the <tt>:from</tt> address, and attachments.
|
22
23
|
#
|
23
24
|
# class ApplicationMailer < ActionMailer::Base
|
24
|
-
# default from: 'from@
|
25
|
+
# default from: 'from@example.com'
|
25
26
|
# layout 'mailer'
|
26
27
|
# end
|
27
28
|
#
|
28
|
-
# class
|
29
|
+
# class NotifierMailer < ApplicationMailer
|
29
30
|
# default from: 'no-reply@example.com',
|
30
31
|
# return_path: 'system@example.com'
|
31
32
|
#
|
@@ -86,9 +87,9 @@ module ActionMailer
|
|
86
87
|
# Like Action Controller, each mailer class has a corresponding view directory in which each
|
87
88
|
# method of the class looks for a template with its name.
|
88
89
|
#
|
89
|
-
# To define a template to be used with a
|
90
|
+
# To define a template to be used with a mailer, create an <tt>.erb</tt> file with the same
|
90
91
|
# name as the method in your mailer model. For example, in the mailer defined above, the template at
|
91
|
-
# <tt>app/views/
|
92
|
+
# <tt>app/views/notifier_mailer/welcome.text.erb</tt> would be used to generate the email.
|
92
93
|
#
|
93
94
|
# Variables defined in the methods of your mailer model are accessible as instance variables in their
|
94
95
|
# corresponding view.
|
@@ -132,38 +133,41 @@ module ActionMailer
|
|
132
133
|
#
|
133
134
|
# config.action_mailer.default_url_options = { host: "example.com" }
|
134
135
|
#
|
135
|
-
#
|
136
|
-
#
|
137
|
-
#
|
138
|
-
# <tt>
|
136
|
+
# You can also define a <tt>default_url_options</tt> method on individual mailers to override these
|
137
|
+
# default settings per-mailer.
|
138
|
+
#
|
139
|
+
# By default when <tt>config.force_ssl</tt> is true, URLs generated for hosts will use the HTTPS protocol.
|
139
140
|
#
|
140
141
|
# = Sending mail
|
141
142
|
#
|
142
|
-
# Once a mailer action and template are defined, you can deliver your message or
|
143
|
-
# for
|
143
|
+
# Once a mailer action and template are defined, you can deliver your message or defer its creation and
|
144
|
+
# delivery for later:
|
145
|
+
#
|
146
|
+
# NotifierMailer.welcome(User.first).deliver_now # sends the email
|
147
|
+
# mail = NotifierMailer.welcome(User.first) # => an ActionMailer::MessageDelivery object
|
148
|
+
# mail.deliver_now # generates and sends the email now
|
144
149
|
#
|
145
|
-
#
|
146
|
-
#
|
147
|
-
#
|
150
|
+
# The <tt>ActionMailer::MessageDelivery</tt> class is a wrapper around a delegate that will call
|
151
|
+
# your method to generate the mail. If you want direct access to the delegator, or <tt>Mail::Message</tt>,
|
152
|
+
# you can call the <tt>message</tt> method on the <tt>ActionMailer::MessageDelivery</tt> object.
|
148
153
|
#
|
149
|
-
#
|
150
|
-
# you want direct access to the <tt>Mail::Message</tt> object you can call the <tt>message</tt> method on
|
151
|
-
# the <tt>ActionMailer::MessageDelivery</tt> object.
|
154
|
+
# NotifierMailer.welcome(User.first).message # => a Mail::Message object
|
152
155
|
#
|
153
|
-
#
|
156
|
+
# Action Mailer is nicely integrated with Active Job so you can generate and send emails in the background
|
157
|
+
# (example: outside of the request-response cycle, so the user doesn't have to wait on it):
|
154
158
|
#
|
155
|
-
#
|
156
|
-
# of the request-response cycle, so the user doesn't have to wait on it):
|
159
|
+
# NotifierMailer.welcome(User.first).deliver_later # enqueue the email sending to Active Job
|
157
160
|
#
|
158
|
-
#
|
161
|
+
# Note that <tt>deliver_later</tt> will execute your method from the background job.
|
159
162
|
#
|
160
163
|
# You never instantiate your mailer class. Rather, you just call the method you defined on the class itself.
|
164
|
+
# All instance methods are expected to return a message object to be sent.
|
161
165
|
#
|
162
166
|
# = Multipart Emails
|
163
167
|
#
|
164
168
|
# Multipart messages can also be used implicitly because Action Mailer will automatically detect and use
|
165
169
|
# multipart templates, where each template is named after the name of the action, followed by the content
|
166
|
-
# type. Each such detected template will be added as a separate part
|
170
|
+
# type. Each such detected template will be added to the message, as a separate part.
|
167
171
|
#
|
168
172
|
# For example, if the following templates exist:
|
169
173
|
# * signup_notification.text.erb
|
@@ -184,7 +188,7 @@ module ActionMailer
|
|
184
188
|
#
|
185
189
|
# Sending attachment in emails is easy:
|
186
190
|
#
|
187
|
-
# class
|
191
|
+
# class NotifierMailer < ApplicationMailer
|
188
192
|
# def welcome(recipient)
|
189
193
|
# attachments['free_book.pdf'] = File.read('path/to/file.pdf')
|
190
194
|
# mail(to: recipient, subject: "New account information")
|
@@ -200,19 +204,32 @@ module ActionMailer
|
|
200
204
|
# If you need to send attachments with no content, you need to create an empty view for it,
|
201
205
|
# or add an empty body parameter like this:
|
202
206
|
#
|
203
|
-
# class
|
207
|
+
# class NotifierMailer < ApplicationMailer
|
204
208
|
# def welcome(recipient)
|
205
209
|
# attachments['free_book.pdf'] = File.read('path/to/file.pdf')
|
206
210
|
# mail(to: recipient, subject: "New account information", body: "")
|
207
211
|
# end
|
208
212
|
# end
|
209
213
|
#
|
214
|
+
# You can also send attachments with html template, in this case you need to add body, attachments,
|
215
|
+
# and custom content type like this:
|
216
|
+
#
|
217
|
+
# class NotifierMailer < ApplicationMailer
|
218
|
+
# def welcome(recipient)
|
219
|
+
# attachments["free_book.pdf"] = File.read("path/to/file.pdf")
|
220
|
+
# mail(to: recipient,
|
221
|
+
# subject: "New account information",
|
222
|
+
# content_type: "text/html",
|
223
|
+
# body: "<html><body>Hello there</body></html>")
|
224
|
+
# end
|
225
|
+
# end
|
226
|
+
#
|
210
227
|
# = Inline Attachments
|
211
228
|
#
|
212
229
|
# You can also specify that a file should be displayed inline with other HTML. This is useful
|
213
230
|
# if you want to display a corporate logo or a photo.
|
214
231
|
#
|
215
|
-
# class
|
232
|
+
# class NotifierMailer < ApplicationMailer
|
216
233
|
# def welcome(recipient)
|
217
234
|
# attachments.inline['photo.png'] = File.read('path/to/photo.png')
|
218
235
|
# mail(to: recipient, subject: "Here is what we look like")
|
@@ -251,7 +268,7 @@ module ActionMailer
|
|
251
268
|
# Action Mailer provides some intelligent defaults for your emails, these are usually specified in a
|
252
269
|
# default method inside the class definition:
|
253
270
|
#
|
254
|
-
# class
|
271
|
+
# class NotifierMailer < ApplicationMailer
|
255
272
|
# default sender: 'system@example.com'
|
256
273
|
# end
|
257
274
|
#
|
@@ -259,8 +276,8 @@ module ActionMailer
|
|
259
276
|
# <tt>ActionMailer::Base</tt> sets the following:
|
260
277
|
#
|
261
278
|
# * <tt>mime_version: "1.0"</tt>
|
262
|
-
# * <tt>charset: "UTF-8"
|
263
|
-
# * <tt>content_type: "text/plain"
|
279
|
+
# * <tt>charset: "UTF-8"</tt>
|
280
|
+
# * <tt>content_type: "text/plain"</tt>
|
264
281
|
# * <tt>parts_order: [ "text/plain", "text/enriched", "text/html" ]</tt>
|
265
282
|
#
|
266
283
|
# <tt>parts_order</tt> and <tt>charset</tt> are not actually valid <tt>Mail::Message</tt> header fields,
|
@@ -269,27 +286,26 @@ module ActionMailer
|
|
269
286
|
# As you can pass in any header, you need to either quote the header as a string, or pass it in as
|
270
287
|
# an underscored symbol, so the following will work:
|
271
288
|
#
|
272
|
-
# class
|
289
|
+
# class NotifierMailer < ApplicationMailer
|
273
290
|
# default 'Content-Transfer-Encoding' => '7bit',
|
274
291
|
# content_description: 'This is a description'
|
275
292
|
# end
|
276
293
|
#
|
277
|
-
# Finally, Action Mailer also supports passing <tt>Proc</tt> objects into the default hash,
|
278
|
-
# can define methods that evaluate as the message is being generated:
|
294
|
+
# Finally, Action Mailer also supports passing <tt>Proc</tt> and <tt>Lambda</tt> objects into the default hash,
|
295
|
+
# so you can define methods that evaluate as the message is being generated:
|
279
296
|
#
|
280
|
-
# class
|
281
|
-
# default 'X-Special-Header' => Proc.new { my_method }
|
297
|
+
# class NotifierMailer < ApplicationMailer
|
298
|
+
# default 'X-Special-Header' => Proc.new { my_method }, to: -> { @inviter.email_address }
|
282
299
|
#
|
283
300
|
# private
|
284
|
-
#
|
285
301
|
# def my_method
|
286
302
|
# 'some complex call'
|
287
303
|
# end
|
288
304
|
# end
|
289
305
|
#
|
290
|
-
# Note that the proc is evaluated right at the start of the mail message generation, so if you
|
291
|
-
# set something in the
|
292
|
-
# mailer method, it will get
|
306
|
+
# Note that the proc/lambda is evaluated right at the start of the mail message generation, so if you
|
307
|
+
# set something in the default hash using a proc, and then set the same thing inside of your
|
308
|
+
# mailer method, it will get overwritten by the mailer method.
|
293
309
|
#
|
294
310
|
# It is also possible to set these default options that will be used in all mailers through
|
295
311
|
# the <tt>default_options=</tt> configuration in <tt>config/application.rb</tt>:
|
@@ -302,7 +318,7 @@ module ActionMailer
|
|
302
318
|
# This may be useful, for example, when you want to add default inline attachments for all
|
303
319
|
# messages sent out by a certain mailer class:
|
304
320
|
#
|
305
|
-
# class
|
321
|
+
# class NotifierMailer < ApplicationMailer
|
306
322
|
# before_action :add_inline_attachment!
|
307
323
|
#
|
308
324
|
# def welcome
|
@@ -310,7 +326,6 @@ module ActionMailer
|
|
310
326
|
# end
|
311
327
|
#
|
312
328
|
# private
|
313
|
-
#
|
314
329
|
# def add_inline_attachment!
|
315
330
|
# attachments.inline["footer.jpg"] = File.read('/path/to/filename.jpg')
|
316
331
|
# end
|
@@ -321,8 +336,9 @@ module ActionMailer
|
|
321
336
|
# callbacks in the same manner that you would use callbacks in classes that
|
322
337
|
# inherit from <tt>ActionController::Base</tt>.
|
323
338
|
#
|
324
|
-
# Note that unless you have a specific reason to do so, you should prefer
|
325
|
-
# rather than after_action in your
|
339
|
+
# Note that unless you have a specific reason to do so, you should prefer
|
340
|
+
# using <tt>before_action</tt> rather than <tt>after_action</tt> in your
|
341
|
+
# Action Mailer classes so that headers are parsed properly.
|
326
342
|
#
|
327
343
|
# = Previewing emails
|
328
344
|
#
|
@@ -330,9 +346,9 @@ module ActionMailer
|
|
330
346
|
# <tt>ActionMailer::Base.preview_path</tt>. Since most emails do something interesting
|
331
347
|
# with database data, you'll need to write some scenarios to load messages with fake data:
|
332
348
|
#
|
333
|
-
# class
|
349
|
+
# class NotifierMailerPreview < ActionMailer::Preview
|
334
350
|
# def welcome
|
335
|
-
#
|
351
|
+
# NotifierMailer.welcome(User.first)
|
336
352
|
# end
|
337
353
|
# end
|
338
354
|
#
|
@@ -388,13 +404,13 @@ module ActionMailer
|
|
388
404
|
# to use it. Defaults to <tt>true</tt>.
|
389
405
|
# * <tt>:openssl_verify_mode</tt> - When using TLS, you can set how OpenSSL checks the certificate. This is
|
390
406
|
# really useful if you need to validate a self-signed and/or a wildcard certificate. You can use the name
|
391
|
-
# of an OpenSSL verify constant (<tt>'none'</tt
|
392
|
-
# <tt>
|
393
|
-
# <tt
|
407
|
+
# of an OpenSSL verify constant (<tt>'none'</tt> or <tt>'peer'</tt>) or directly the constant
|
408
|
+
# (<tt>OpenSSL::SSL::VERIFY_NONE</tt> or <tt>OpenSSL::SSL::VERIFY_PEER</tt>).
|
409
|
+
# <tt>:ssl/:tls</tt> Enables the SMTP connection to use SMTP/TLS (SMTPS: SMTP over direct TLS connection)
|
394
410
|
#
|
395
411
|
# * <tt>sendmail_settings</tt> - Allows you to override options for the <tt>:sendmail</tt> delivery method.
|
396
412
|
# * <tt>:location</tt> - The location of the sendmail executable. Defaults to <tt>/usr/sbin/sendmail</tt>.
|
397
|
-
# * <tt>:arguments</tt> - The command line arguments. Defaults to <tt>-i
|
413
|
+
# * <tt>:arguments</tt> - The command line arguments. Defaults to <tt>-i</tt> with <tt>-f sender@address</tt>
|
398
414
|
# added automatically before the message is sent.
|
399
415
|
#
|
400
416
|
# * <tt>file_settings</tt> - Allows you to override options for the <tt>:file</tt> delivery method.
|
@@ -414,8 +430,12 @@ module ActionMailer
|
|
414
430
|
#
|
415
431
|
# * <tt>deliveries</tt> - Keeps an array of all the emails sent out through the Action Mailer with
|
416
432
|
# <tt>delivery_method :test</tt>. Most useful for unit and functional testing.
|
433
|
+
#
|
434
|
+
# * <tt>deliver_later_queue_name</tt> - The name of the queue used with <tt>deliver_later</tt>. Defaults to +mailers+.
|
417
435
|
class Base < AbstractController::Base
|
418
436
|
include DeliveryMethods
|
437
|
+
include Rescuable
|
438
|
+
include Parameterized
|
419
439
|
include Previews
|
420
440
|
|
421
441
|
abstract!
|
@@ -427,6 +447,7 @@ module ActionMailer
|
|
427
447
|
include AbstractController::Translation
|
428
448
|
include AbstractController::AssetPaths
|
429
449
|
include AbstractController::Callbacks
|
450
|
+
include AbstractController::Caching
|
430
451
|
|
431
452
|
include ActionView::Layouts
|
432
453
|
|
@@ -438,8 +459,6 @@ module ActionMailer
|
|
438
459
|
|
439
460
|
helper ActionMailer::MailHelper
|
440
461
|
|
441
|
-
private_class_method :new #:nodoc:
|
442
|
-
|
443
462
|
class_attribute :default_params
|
444
463
|
self.default_params = {
|
445
464
|
mime_version: "1.0",
|
@@ -463,31 +482,27 @@ module ActionMailer
|
|
463
482
|
# Either a class, string or symbol can be passed in as the Observer.
|
464
483
|
# If a string or symbol is passed in it will be camelized and constantized.
|
465
484
|
def register_observer(observer)
|
466
|
-
|
467
|
-
when String, Symbol
|
468
|
-
observer.to_s.camelize.constantize
|
469
|
-
else
|
470
|
-
observer
|
471
|
-
end
|
472
|
-
|
473
|
-
Mail.register_observer(delivery_observer)
|
485
|
+
Mail.register_observer(observer_class_for(observer))
|
474
486
|
end
|
475
487
|
|
476
488
|
# Register an Interceptor which will be called before mail is sent.
|
477
489
|
# Either a class, string or symbol can be passed in as the Interceptor.
|
478
490
|
# If a string or symbol is passed in it will be camelized and constantized.
|
479
491
|
def register_interceptor(interceptor)
|
480
|
-
|
481
|
-
|
482
|
-
interceptor.to_s.camelize.constantize
|
483
|
-
else
|
484
|
-
interceptor
|
485
|
-
end
|
492
|
+
Mail.register_interceptor(observer_class_for(interceptor))
|
493
|
+
end
|
486
494
|
|
487
|
-
|
495
|
+
def observer_class_for(value) # :nodoc:
|
496
|
+
case value
|
497
|
+
when String, Symbol
|
498
|
+
value.to_s.camelize.constantize
|
499
|
+
else
|
500
|
+
value
|
501
|
+
end
|
488
502
|
end
|
503
|
+
private :observer_class_for
|
489
504
|
|
490
|
-
# Returns the name of current mailer. This method is also being used as a path for a view lookup.
|
505
|
+
# Returns the name of the current mailer. This method is also being used as a path for a view lookup.
|
491
506
|
# If this is an anonymous mailer, this method will return +anonymous+ instead.
|
492
507
|
def mailer_name
|
493
508
|
@mailer_name ||= anonymous? ? "anonymous" : name.underscore
|
@@ -544,13 +559,9 @@ module ActionMailer
|
|
544
559
|
end
|
545
560
|
end
|
546
561
|
|
547
|
-
|
548
|
-
super || action_methods.include?(method.to_s)
|
549
|
-
end
|
550
|
-
|
551
|
-
protected
|
562
|
+
private
|
552
563
|
|
553
|
-
def set_payload_for_mail(payload, mail)
|
564
|
+
def set_payload_for_mail(payload, mail)
|
554
565
|
payload[:mailer] = name
|
555
566
|
payload[:message_id] = mail.message_id
|
556
567
|
payload[:subject] = mail.subject
|
@@ -562,13 +573,17 @@ module ActionMailer
|
|
562
573
|
payload[:mail] = mail.encoded
|
563
574
|
end
|
564
575
|
|
565
|
-
def method_missing(method_name, *args)
|
576
|
+
def method_missing(method_name, *args)
|
566
577
|
if action_methods.include?(method_name.to_s)
|
567
578
|
MessageDelivery.new(self, method_name, *args)
|
568
579
|
else
|
569
580
|
super
|
570
581
|
end
|
571
582
|
end
|
583
|
+
|
584
|
+
def respond_to_missing?(method, include_all = false)
|
585
|
+
action_methods.include?(method.to_s) || super
|
586
|
+
end
|
572
587
|
end
|
573
588
|
|
574
589
|
attr_internal :message
|
@@ -577,32 +592,30 @@ module ActionMailer
|
|
577
592
|
# will be initialized according to the named method. If not, the mailer will
|
578
593
|
# remain uninitialized (useful when you only need to invoke the "receive"
|
579
594
|
# method, for instance).
|
580
|
-
def initialize
|
595
|
+
def initialize
|
581
596
|
super()
|
582
597
|
@_mail_was_called = false
|
583
598
|
@_message = Mail.new
|
584
|
-
process(method_name, *args) if method_name
|
585
599
|
end
|
586
600
|
|
587
601
|
def process(method_name, *args) #:nodoc:
|
588
602
|
payload = {
|
589
603
|
mailer: self.class.name,
|
590
|
-
action: method_name
|
604
|
+
action: method_name,
|
605
|
+
args: args
|
591
606
|
}
|
592
607
|
|
593
608
|
ActiveSupport::Notifications.instrument("process.action_mailer", payload) do
|
594
|
-
lookup_context.skip_default_locale!
|
595
|
-
|
596
609
|
super
|
597
610
|
@_message = NullMail.new unless @_mail_was_called
|
598
611
|
end
|
599
612
|
end
|
600
613
|
|
601
614
|
class NullMail #:nodoc:
|
602
|
-
def body;
|
615
|
+
def body; "" end
|
603
616
|
def header; {} end
|
604
617
|
|
605
|
-
def respond_to?(string, include_all=false)
|
618
|
+
def respond_to?(string, include_all = false)
|
606
619
|
true
|
607
620
|
end
|
608
621
|
|
@@ -662,21 +675,21 @@ module ActionMailer
|
|
662
675
|
#
|
663
676
|
# mail.attachments['filename.jpg'] = File.read('/path/to/filename.jpg')
|
664
677
|
#
|
665
|
-
# If you do this, then Mail will take the file name and work out the mime type
|
666
|
-
# set the Content-Type, Content-Disposition, Content-Transfer-Encoding
|
667
|
-
#
|
678
|
+
# If you do this, then Mail will take the file name and work out the mime type.
|
679
|
+
# It will also set the Content-Type, Content-Disposition, Content-Transfer-Encoding
|
680
|
+
# and encode the contents of the attachment in Base64.
|
668
681
|
#
|
669
682
|
# You can also specify overrides if you want by passing a hash instead of a string:
|
670
683
|
#
|
671
|
-
# mail.attachments['filename.jpg'] = {mime_type: 'application/
|
684
|
+
# mail.attachments['filename.jpg'] = {mime_type: 'application/gzip',
|
672
685
|
# content: File.read('/path/to/filename.jpg')}
|
673
686
|
#
|
674
|
-
# If you want to use
|
675
|
-
#
|
676
|
-
#
|
687
|
+
# If you want to use encoding other than Base64 then you will need to pass encoding
|
688
|
+
# type along with the pre-encoded content as Mail doesn't know how to decode the
|
689
|
+
# data:
|
677
690
|
#
|
678
691
|
# file_content = SpecialEncode(File.read('/path/to/filename.jpg'))
|
679
|
-
# mail.attachments['filename.jpg'] = {mime_type: 'application/
|
692
|
+
# mail.attachments['filename.jpg'] = {mime_type: 'application/gzip',
|
680
693
|
# encoding: 'SpecialEncoding',
|
681
694
|
# content: file_content }
|
682
695
|
#
|
@@ -798,151 +811,173 @@ module ActionMailer
|
|
798
811
|
# end
|
799
812
|
#
|
800
813
|
def mail(headers = {}, &block)
|
801
|
-
return
|
802
|
-
|
803
|
-
m = @_message
|
814
|
+
return message if @_mail_was_called && headers.blank? && !block
|
804
815
|
|
805
816
|
# At the beginning, do not consider class default for content_type
|
806
817
|
content_type = headers[:content_type]
|
807
818
|
|
808
|
-
|
809
|
-
default_values = {}
|
810
|
-
self.class.default.each do |k,v|
|
811
|
-
default_values[k] = v.is_a?(Proc) ? instance_eval(&v) : v
|
812
|
-
end
|
813
|
-
|
814
|
-
# Handle defaults
|
815
|
-
headers = headers.reverse_merge(default_values)
|
816
|
-
headers[:subject] ||= default_i18n_subject
|
819
|
+
headers = apply_defaults(headers)
|
817
820
|
|
818
821
|
# Apply charset at the beginning so all fields are properly quoted
|
819
|
-
|
822
|
+
message.charset = charset = headers[:charset]
|
820
823
|
|
821
824
|
# Set configure delivery behavior
|
822
|
-
wrap_delivery_behavior!(headers
|
825
|
+
wrap_delivery_behavior!(headers[:delivery_method], headers[:delivery_method_options])
|
823
826
|
|
824
|
-
|
825
|
-
assignable = headers.except(:parts_order, :content_type, :body, :template_name, :template_path)
|
826
|
-
assignable.each { |k, v| m[k] = v }
|
827
|
+
assign_headers_to_message(message, headers)
|
827
828
|
|
828
829
|
# Render the templates and blocks
|
829
830
|
responses = collect_responses(headers, &block)
|
830
831
|
@_mail_was_called = true
|
831
832
|
|
832
|
-
create_parts_from_responses(
|
833
|
+
create_parts_from_responses(message, responses)
|
833
834
|
|
834
835
|
# Setup content type, reapply charset and handle parts order
|
835
|
-
|
836
|
-
|
836
|
+
message.content_type = set_content_type(message, content_type, headers[:content_type])
|
837
|
+
message.charset = charset
|
837
838
|
|
838
|
-
if
|
839
|
-
|
840
|
-
|
839
|
+
if message.multipart?
|
840
|
+
message.body.set_sort_order(headers[:parts_order])
|
841
|
+
message.body.sort_parts!
|
841
842
|
end
|
842
843
|
|
843
|
-
|
844
|
+
message
|
844
845
|
end
|
845
846
|
|
846
|
-
|
847
|
-
|
848
|
-
|
849
|
-
|
850
|
-
|
851
|
-
|
852
|
-
|
853
|
-
|
854
|
-
|
855
|
-
|
856
|
-
|
857
|
-
|
858
|
-
|
859
|
-
|
860
|
-
|
861
|
-
|
862
|
-
|
863
|
-
|
864
|
-
|
847
|
+
private
|
848
|
+
|
849
|
+
# Used by #mail to set the content type of the message.
|
850
|
+
#
|
851
|
+
# It will use the given +user_content_type+, or multipart if the mail
|
852
|
+
# message has any attachments. If the attachments are inline, the content
|
853
|
+
# type will be "multipart/related", otherwise "multipart/mixed".
|
854
|
+
#
|
855
|
+
# If there is no content type passed in via headers, and there are no
|
856
|
+
# attachments, or the message is multipart, then the default content type is
|
857
|
+
# used.
|
858
|
+
def set_content_type(m, user_content_type, class_default) # :doc:
|
859
|
+
params = m.content_type_parameters || {}
|
860
|
+
case
|
861
|
+
when user_content_type.present?
|
862
|
+
user_content_type
|
863
|
+
when m.has_attachments?
|
864
|
+
if m.attachments.detect(&:inline?)
|
865
|
+
["multipart", "related", params]
|
866
|
+
else
|
867
|
+
["multipart", "mixed", params]
|
868
|
+
end
|
869
|
+
when m.multipart?
|
870
|
+
["multipart", "alternative", params]
|
865
871
|
else
|
866
|
-
|
872
|
+
m.content_type || class_default
|
867
873
|
end
|
868
|
-
when m.multipart?
|
869
|
-
["multipart", "alternative", params]
|
870
|
-
else
|
871
|
-
m.content_type || class_default
|
872
874
|
end
|
873
|
-
end
|
874
875
|
|
875
|
-
|
876
|
-
|
877
|
-
|
878
|
-
|
879
|
-
|
880
|
-
|
881
|
-
|
882
|
-
|
876
|
+
# Translates the +subject+ using Rails I18n class under <tt>[mailer_scope, action_name]</tt> scope.
|
877
|
+
# If it does not find a translation for the +subject+ under the specified scope it will default to a
|
878
|
+
# humanized version of the <tt>action_name</tt>.
|
879
|
+
# If the subject has interpolations, you can pass them through the +interpolations+ parameter.
|
880
|
+
def default_i18n_subject(interpolations = {}) # :doc:
|
881
|
+
mailer_scope = self.class.mailer_name.tr("/", ".")
|
882
|
+
I18n.t(:subject, interpolations.merge(scope: [mailer_scope, action_name], default: action_name.humanize))
|
883
|
+
end
|
884
|
+
|
885
|
+
# Emails do not support relative path links.
|
886
|
+
def self.supports_path? # :doc:
|
887
|
+
false
|
888
|
+
end
|
889
|
+
|
890
|
+
def apply_defaults(headers)
|
891
|
+
default_values = self.class.default.map do |key, value|
|
892
|
+
[
|
893
|
+
key,
|
894
|
+
value.is_a?(Proc) ? instance_exec(&value) : value
|
895
|
+
]
|
896
|
+
end.to_h
|
897
|
+
|
898
|
+
headers_with_defaults = headers.reverse_merge(default_values)
|
899
|
+
headers_with_defaults[:subject] ||= default_i18n_subject
|
900
|
+
headers_with_defaults
|
901
|
+
end
|
902
|
+
|
903
|
+
def assign_headers_to_message(message, headers)
|
904
|
+
assignable = headers.except(:parts_order, :content_type, :body, :template_name,
|
905
|
+
:template_path, :delivery_method, :delivery_method_options)
|
906
|
+
assignable.each { |k, v| message[k] = v }
|
907
|
+
end
|
883
908
|
|
884
|
-
|
885
|
-
|
909
|
+
def collect_responses(headers)
|
910
|
+
if block_given?
|
911
|
+
collector = ActionMailer::Collector.new(lookup_context) { render(action_name) }
|
912
|
+
yield(collector)
|
913
|
+
collector.responses
|
914
|
+
elsif headers[:body]
|
915
|
+
collect_responses_from_text(headers)
|
916
|
+
else
|
917
|
+
collect_responses_from_templates(headers)
|
918
|
+
end
|
919
|
+
end
|
886
920
|
|
887
|
-
|
888
|
-
|
889
|
-
yield(collector)
|
890
|
-
responses = collector.responses
|
891
|
-
elsif headers[:body]
|
892
|
-
responses << {
|
921
|
+
def collect_responses_from_text(headers)
|
922
|
+
[{
|
893
923
|
body: headers.delete(:body),
|
894
|
-
content_type:
|
895
|
-
}
|
896
|
-
|
897
|
-
templates_path = headers.delete(:template_path) || self.class.mailer_name
|
898
|
-
templates_name = headers.delete(:template_name) || action_name
|
924
|
+
content_type: headers[:content_type] || "text/plain"
|
925
|
+
}]
|
926
|
+
end
|
899
927
|
|
900
|
-
|
901
|
-
|
928
|
+
def collect_responses_from_templates(headers)
|
929
|
+
templates_path = headers[:template_path] || self.class.mailer_name
|
930
|
+
templates_name = headers[:template_name] || action_name
|
902
931
|
|
903
|
-
|
932
|
+
each_template(Array(templates_path), templates_name).map do |template|
|
933
|
+
self.formats = template.formats
|
934
|
+
{
|
904
935
|
body: render(template: template),
|
905
936
|
content_type: template.type.to_s
|
906
937
|
}
|
907
938
|
end
|
908
939
|
end
|
909
940
|
|
910
|
-
|
911
|
-
|
941
|
+
def each_template(paths, name, &block)
|
942
|
+
templates = lookup_context.find_all(name, paths)
|
943
|
+
if templates.empty?
|
944
|
+
raise ActionView::MissingTemplate.new(paths, name, paths, false, "mailer")
|
945
|
+
else
|
946
|
+
templates.uniq(&:formats).each(&block)
|
947
|
+
end
|
948
|
+
end
|
912
949
|
|
913
|
-
|
914
|
-
|
915
|
-
|
916
|
-
|
917
|
-
|
918
|
-
|
950
|
+
def create_parts_from_responses(m, responses)
|
951
|
+
if responses.size == 1 && !m.has_attachments?
|
952
|
+
responses[0].each { |k, v| m[k] = v }
|
953
|
+
elsif responses.size > 1 && m.has_attachments?
|
954
|
+
container = Mail::Part.new
|
955
|
+
container.content_type = "multipart/alternative"
|
956
|
+
responses.each { |r| insert_part(container, r, m.charset) }
|
957
|
+
m.add_part(container)
|
958
|
+
else
|
959
|
+
responses.each { |r| insert_part(m, r, m.charset) }
|
960
|
+
end
|
919
961
|
end
|
920
|
-
end
|
921
962
|
|
922
|
-
|
923
|
-
|
924
|
-
|
925
|
-
|
926
|
-
container = Mail::Part.new
|
927
|
-
container.content_type = "multipart/alternative"
|
928
|
-
responses.each { |r| insert_part(container, r, m.charset) }
|
929
|
-
m.add_part(container)
|
930
|
-
else
|
931
|
-
responses.each { |r| insert_part(m, r, m.charset) }
|
963
|
+
def insert_part(container, response, charset)
|
964
|
+
response[:charset] ||= charset
|
965
|
+
part = Mail::Part.new(response)
|
966
|
+
container.add_part(part)
|
932
967
|
end
|
933
|
-
end
|
934
968
|
|
935
|
-
|
936
|
-
|
937
|
-
|
938
|
-
|
939
|
-
|
969
|
+
# This and #instrument_name is for caching instrument
|
970
|
+
def instrument_payload(key)
|
971
|
+
{
|
972
|
+
mailer: mailer_name,
|
973
|
+
key: key
|
974
|
+
}
|
975
|
+
end
|
940
976
|
|
941
|
-
|
942
|
-
|
943
|
-
|
944
|
-
end
|
977
|
+
def instrument_name
|
978
|
+
"action_mailer".freeze
|
979
|
+
end
|
945
980
|
|
946
|
-
|
981
|
+
ActiveSupport.run_load_hooks(:action_mailer, self)
|
947
982
|
end
|
948
983
|
end
|