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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA256:
3
- metadata.gz: b441b0885c1dd49404f23031657598065b2fa50b1150bf230f3322a29ce69b2e
4
- data.tar.gz: ff7c3927b3a2dd42b3f75803e2b4e9964529d635cbb59190eab40e2ceb81bdc9
2
+ SHA1:
3
+ metadata.gz: fa279066a475c28daeb75c73d61bc75b20d79dcd
4
+ data.tar.gz: d470281fac5bfd09afdb3fd6e53de8de5a454b40
5
5
  SHA512:
6
- metadata.gz: 5b80b0a4613bef47583205737a9caf5eb37e49ca840f9df4b99df0304699011eb44cd23a2ca654023e0875c7014f89ab0f5b5576798dd16f2e9f87e8dcee7053
7
- data.tar.gz: 4a089a463850903265e0fc8faaa729daafb3e26c8c9665a9802ba6343cabb944006717fb909b4cc59a934036d460d5a591e45593dee46cd27404976f81f903bb
6
+ metadata.gz: d1fa1024d0423ac5d26b0c6b28958ca059caac10d5efe7a017209a92414786f2ddab63dd06962dddee8e4c0e84151f395a7f740d51d0e59cdc8472cdc156efd1
7
+ data.tar.gz: 0b17b0eba794f38550fd074829ec7c7f64d8028ace9ccae242e88297c964ab36a111cd49f5e1bcc7f77c54f3f6e5961d73dcb56cdaec783256f7de34f52a5761
@@ -1,152 +1,33 @@
1
- ## Rails 4.2.11 (November 27, 2018) ##
1
+ ## Rails 5.1.0 (April 27, 2017) ##
2
2
 
3
- * No changes.
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
- * Mailer preview now uses `url_for` to fix links to emails for apps running on
62
- a subdirectory.
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
- Fixes #16163.
10
+ *DHH*
132
11
 
133
- *Yves Senn*
12
+ * Allow lambdas to be used as lazy defaults in addition to procs.
134
13
 
135
- * Add `config.action_mailer.show_previews` configuration option.
14
+ *DHH*
136
15
 
137
- This configuration option can be used to enable the mail preview in
138
- environments other than development (such as staging).
16
+ * Mime type: allow to custom content type when setting body in headers
17
+ and attachments.
139
18
 
140
- Defaults to `true` in development and `false` elsewhere.
19
+ Example:
141
20
 
142
- *Leonard Garvey*
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
- * Allow preview interceptors to be registered through
145
- `config.action_mailer.preview_interceptors`.
26
+ *Minh Quy*
146
27
 
147
- See #15739.
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
- *Yves Senn*
31
+ *Jeremy Daer*
150
32
 
151
- Please check [4-1-stable](https://github.com/rails/rails/blob/4-1-stable/actionmailer/CHANGELOG.md)
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.
@@ -1,4 +1,4 @@
1
- Copyright (c) 2004-2014 David Heinemeier Hansson
1
+ Copyright (c) 2004-2017 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
@@ -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
- % [sudo] gem install actionmailer
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/4-2-stable/actionmailer
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
-
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2004-2014 David Heinemeier Hansson
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 'abstract_controller'
25
- require 'action_mailer/version'
24
+ require "abstract_controller"
25
+ require "action_mailer/version"
26
26
 
27
27
  # Common Active Support usage in Action Mailer
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'
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, 'action_mailer/preview'
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, 'action_dispatch/http/mime_type'
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
@@ -1,10 +1,11 @@
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'
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 'action_mailer/log_subscriber'
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@exmaple.com'
25
+ # default from: 'from@example.com'
25
26
  # layout 'mailer'
26
27
  # end
27
28
  #
28
- # class Notifier < ApplicationMailer
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 mailing, create an <tt>.erb</tt> file with the same
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/notifier/welcome.text.erb</tt> would be used to generate the email.
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
- # When you decide to set a default <tt>:host</tt> for your mailers, then you need to make sure to use the
136
- # <tt>only_path: false</tt> option when using <tt>url_for</tt>. Since the <tt>url_for</tt> view helper
137
- # will generate relative URLs by default when a <tt>:host</tt> option isn't explicitly provided, passing
138
- # <tt>only_path: false</tt> will ensure that absolute URLs are generated.
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 create it and save it
143
- # for delivery later:
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
- # Notifier.welcome(User.first).deliver_now # sends the email
146
- # mail = Notifier.welcome(User.first) # => an ActionMailer::MessageDelivery object
147
- # mail.deliver_now # sends the email
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
- # The <tt>ActionMailer::MessageDelivery</tt> class is a wrapper around a <tt>Mail::Message</tt> object. If
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
- # Notifier.welcome(User.first).message # => a Mail::Message object
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
- # Action Mailer is nicely integrated with Active Job so you can send emails in the background (example: outside
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
- # Notifier.welcome(User.first).deliver_later # enqueue the email sending to Active Job
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 to the message.
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 Notifier < ApplicationMailer
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 Notifier < ApplicationMailer
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 Notifier < ApplicationMailer
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 Notifier < ApplicationMailer
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",</tt>
263
- # * <tt>content_type: "text/plain",</tt>
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 Notifier < ApplicationMailer
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, so you
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 Notifier < ApplicationMailer
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 defaults using a proc, and then set the same thing inside of your
292
- # mailer method, it will get over written by the mailer method.
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 Notifier < ApplicationMailer
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 using before_action
325
- # rather than after_action in your Action Mailer classes so that headers are parsed properly.
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 NotifierPreview < ActionMailer::Preview
349
+ # class NotifierMailerPreview < ActionMailer::Preview
334
350
  # def welcome
335
- # Notifier.welcome(User.first)
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>, <tt>'peer'</tt>, <tt>'client_once'</tt>,
392
- # <tt>'fail_if_no_peer_cert'</tt>) or directly the constant (<tt>OpenSSL::SSL::VERIFY_NONE</tt>,
393
- # <tt>OpenSSL::SSL::VERIFY_PEER</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 -t</tt> with <tt>-f sender@address</tt>
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
- delivery_observer = case observer
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
- delivery_interceptor = case interceptor
481
- when String, Symbol
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
- Mail.register_interceptor(delivery_interceptor)
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
- def respond_to?(method, include_private = false) #:nodoc:
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) #:nodoc:
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) # :nodoc:
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(method_name=nil, *args)
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; '' end
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 and
667
- # base64 encode the contents of the attachment all for you.
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/x-gzip',
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 a different encoding than Base64, you can pass an encoding in,
675
- # but then it is up to you to pass in the content pre-encoded, and don't expect
676
- # Mail to know how to decode this data:
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/x-gzip',
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 @_message if @_mail_was_called && headers.blank? && !block
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
- # Call all the procs (if any)
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
- m.charset = charset = headers[:charset]
822
+ message.charset = charset = headers[:charset]
820
823
 
821
824
  # Set configure delivery behavior
822
- wrap_delivery_behavior!(headers.delete(:delivery_method), headers.delete(:delivery_method_options))
825
+ wrap_delivery_behavior!(headers[:delivery_method], headers[:delivery_method_options])
823
826
 
824
- # Assign all headers except parts_order, content_type and body
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(m, responses)
833
+ create_parts_from_responses(message, responses)
833
834
 
834
835
  # Setup content type, reapply charset and handle parts order
835
- m.content_type = set_content_type(m, content_type, headers[:content_type])
836
- m.charset = charset
836
+ message.content_type = set_content_type(message, content_type, headers[:content_type])
837
+ message.charset = charset
837
838
 
838
- if m.multipart?
839
- m.body.set_sort_order(headers[:parts_order])
840
- m.body.sort_parts!
839
+ if message.multipart?
840
+ message.body.set_sort_order(headers[:parts_order])
841
+ message.body.sort_parts!
841
842
  end
842
843
 
843
- m
844
+ message
844
845
  end
845
846
 
846
- protected
847
-
848
- # Used by #mail to set the content type of the message.
849
- #
850
- # It will use the given +user_content_type+, or multipart if the mail
851
- # message has any attachments. If the attachments are inline, the content
852
- # type will be "multipart/related", otherwise "multipart/mixed".
853
- #
854
- # If there is no content type passed in via headers, and there are no
855
- # attachments, or the message is multipart, then the default content type is
856
- # used.
857
- def set_content_type(m, user_content_type, class_default)
858
- params = m.content_type_parameters || {}
859
- case
860
- when user_content_type.present?
861
- user_content_type
862
- when m.has_attachments?
863
- if m.attachments.detect { |a| a.inline? }
864
- ["multipart", "related", params]
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
- ["multipart", "mixed", params]
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
- # Translates the +subject+ using Rails I18n class under <tt>[mailer_scope, action_name]</tt> scope.
876
- # If it does not find a translation for the +subject+ under the specified scope it will default to a
877
- # humanized version of the <tt>action_name</tt>.
878
- # If the subject has interpolations, you can pass them through the +interpolations+ parameter.
879
- def default_i18n_subject(interpolations = {})
880
- mailer_scope = self.class.mailer_name.tr('/', '.')
881
- I18n.t(:subject, interpolations.merge(scope: [mailer_scope, action_name], default: action_name.humanize))
882
- end
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
- def collect_responses(headers) #:nodoc:
885
- responses = []
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
- if block_given?
888
- collector = ActionMailer::Collector.new(lookup_context) { render(action_name) }
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: self.class.default[:content_type] || "text/plain"
895
- }
896
- else
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
- each_template(Array(templates_path), templates_name) do |template|
901
- self.formats = template.formats
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
- responses << {
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
- responses
911
- end
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
- def each_template(paths, name, &block) #:nodoc:
914
- templates = lookup_context.find_all(name, paths)
915
- if templates.empty?
916
- raise ActionView::MissingTemplate.new(paths, name, paths, false, 'mailer')
917
- else
918
- templates.uniq { |t| t.formats }.each(&block)
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
- def create_parts_from_responses(m, responses) #:nodoc:
923
- if responses.size == 1 && !m.has_attachments?
924
- responses[0].each { |k,v| m[k] = v }
925
- elsif responses.size > 1 && m.has_attachments?
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
- def insert_part(container, response, charset) #:nodoc:
936
- response[:charset] ||= charset
937
- part = Mail::Part.new(response)
938
- container.add_part(part)
939
- end
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
- # Emails do not support relative path links.
942
- def self.supports_path?
943
- false
944
- end
977
+ def instrument_name
978
+ "action_mailer".freeze
979
+ end
945
980
 
946
- ActiveSupport.run_load_hooks(:action_mailer, self)
981
+ ActiveSupport.run_load_hooks(:action_mailer, self)
947
982
  end
948
983
  end