Add missing bullet point to make clear this is
actually a separate option from
`:openssl_verify_mode`.
Add `:ssl/:tls`-option to guides as well [ci skip]
Without this change, `attachments.inline['my_attachment'].present?`, for example,
would raise the exception `Can't add attachments after mail was called`.
I first brought this issue up at https://github.com/rails/rails/issues/16163#issuecomment-437378347.
Note that this commit addresses only one of the 2 problems I described in that comment.
The other problem is that using `attachments.inline['my_attachment']` for reading an
attachment is unnecessary--it's the same as `attachments['my_attachment']`--even before
`mail` is called. We could add a warning about the unnecessary use of `inline` but I'm
saving that for a later PR since my comment has not received any feedback yet.
Previously this used self.formats= to set the format which render would
use to find templates. This worked, but was untested, and looked a
little confusing because it was doing the mutation within a loop.
This commit replaces the assignment with passing formats: [format] into
the render call, which makes it more obvious that that's the purpose of
the format. It also adds a test to verify the formats being used.
Templates only have one format. Before this commit, templates would be
constructed with a single element array that contained the format. This
commit eliminates the single element array and just implements a
`format` method. This saves one array allocation per template.
Since production applications typically run with log level info and
email adresses should be considered as sensitive data we want to prevent
them from ending up in the logs. In development mode (with log level
debug) they are still logged as part of the Mail::Message object.
- If a Mail defines a custom delivery_job, all ActionMailer assertion
helper (assert_emails, assert_enqueued_emails ...) wouldn't work.
```ruby
MyMailer < ApplicationMailer
self.delivery_job = MyJob
end
# This assertion will fail
assert_emails(1) do
MyMailer.my_mail.deliver_later
end
This PR leverage the new ActiveJob feature that accepts Procs for the
`only` keyword and check if the delivery job is one of ActionMailer
registered ones.
Setting parameterized_delivery_job on a mailer class will cause Parameterized::MessageDelivery to use
the specified job instead of ActionMailer::Parameterized::DeliveryJob:
class MyMailer < ApplicationMailer
self.parameterized_delivery_job = MyCustomDeliveryJob
...
end
Since Rails 6.0 will support Ruby 2.4.1 or higher
`# frozen_string_literal: true` magic comment is enough to make string object frozen.
This magic comment is enabled by `Style/FrozenStringLiteralComment` cop.
* Exclude these files not to auto correct false positive `Regexp#freeze`
- 'actionpack/lib/action_dispatch/journey/router/utils.rb'
- 'activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb'
It has been fixed by https://github.com/rubocop-hq/rubocop/pull/6333
Once the newer version of RuboCop released and available at Code Climate these exclude entries should be removed.
* Replace `String#freeze` with `String#-@` manually if explicit frozen string objects are required
- 'actionpack/test/controller/test_case_test.rb'
- 'activemodel/test/cases/type/string_test.rb'
- 'activesupport/lib/active_support/core_ext/string/strip.rb'
- 'activesupport/test/core_ext/string_ext_test.rb'
- 'railties/test/generators/actions_test.rb'
As @dhh brings up, the point of `ActionDispatch::IntegrationTest` is to
allow users to test the integration of all the pieces called by a
controller. Asserting about the emails and jobs queued is part of that
task.
This commit includes the `ActionMailer::TestHelper` and
`ActiveJob::TestHelper` modules when the ActionMailer and ActiveJob
railties are initialized respectively.
Use attr_reader/attr_writer instead of methods
method is 12% slower
Use flat_map over map.flatten(1)
flatten is 66% slower
Use hash[]= instead of hash.merge! with single arguments
merge! is 166% slower
See https://github.com/rails/rails/pull/32337 for more conversation
* ActionMailer::Base can unregister observer(s) and interceptor(s).
One or multiple mail observers can be unregistered using
`ActionMailer::Base.unregister_observers` or
`ActionMailer::Base.unregister_observer`.
One or multiple mail interceptors can be unregistered using
`ActionMailer::Base.unregister_interceptors` or
`ActionMailer::Base.unregister_interceptor`.
For preview interceptors, it's possible to use
`ActionMailer::Base.unregister_preview_interceptors` or
`ActionMailer::Base.unregister_preview_interceptor`.
* Ensure to be reset registered observer(s) and interceptor(s)
* Add explanation to CHANGELOG
* Add original author's name
[Kota Miyake + Rafael Mendonça França + Claudio Ortolina]
* Eager autoload mail gem when eager load is true
We had a production issue where our Sidekiq worker threads all became
deadlocked while autoloading a file within the mail gem, required via
ActionMailer, despite setting our Rails applicaiton to eager load.
`Mail.eager_autoload!` exists and works great, ActionMailer just doesn't
call it during eager loading. Adding it to the ActionMailer Railtie's
eager_load_namespaces takes care of calling `Mail.eager_autoload!`
during the `eager_load!` initializer.
* 'Mail' isn't defined yet, use before_eager_load instead
* Make sure mail is loaded
* Move eager load of Mail into ActionMailer.eager_load!
[Samuel Cochran + Rafael Mendonça França]
- Remove extra execution of `perform_enqueued_jobs`
since it performs all enqueued jobs in the duration of the block.
- Fix example of using `assert_emails` without block since we
can't use enqueued jobs in this case.
PR #29270 changed the number of arguments that gets passed to Procs
defined in ActionMail::Base.default. With this changeset, Procs can
now have 1 or 0 arguments
Also adds test coverage for AM::Base.default Proc arity.
On the first request, ActionController::Base#action_methods computes
and memoized the list of available actions [1]. With this PR we move
this expensive operation into eager load step to reduce response time
of the first request served in production.
This also reduces the memory footprint when running on forking server
like Unicorn.
[1] a3813dce9a/actionpack/lib/abstract_controller/base.rb (L66-L77)
Setting delivery_job on a mailer class will cause MessageDelivery to use
the specified job instead of ActionMailer::DeliveryJob:
class MyMailer < ApplicationMailer
self.delivery_job = MyCustomDeliveryJob
...
end
* Allow a default value to be declared for class_attribute
* Convert to using class_attribute default rather than explicit setter
* Removed instance_accessor option by mistake
* False is a valid default value
* Documentation
Without this, Action Mailer doesn't work like it used to on version 4.
The following snippet fails since version 5:
> require 'action_mailer'
> ActionMailer::Base
NameError: uninitialized constant ActiveSupport::Rescuable
ActionMailer::Base#instrument_name and
ActionController::Base#instrument_name will be frequently called once
caching is enabled. So it's better to freeze them instead of create new
string on every call.
Also, the instrument name in #instrument_fragment_cache will usually
be "write_fragment.action_controller" or
"read_fragment.action_controller". So freezing them might also gain some
performance improvement. We have done something like this in other places:
https://github.com/rails/rails/blob/master/actionview/lib/action_view/template.rb#L348
The raw_source method is documented as returning the exact value that
was used to create the body; mutating it breaks that contract.
Additionally, if the value used to create the body is blank, raw_source
returns a frozen string which causes the interceptor to raise an error.
If we create nested (namespaced) rails engine such like bukkits-admin,
`bin/rails g scaffold User name:string age:integer`
will create
`bukkits-admin/app/controllers/bukkits/users_controller.rb`
but it should create
`bukkits-admin/app/controllers/bukkits/admin/users_controller.rb`.
In #6643, we changed `namespaced_path` as root path
because we supposed application_controller is always in root
but nested rails engine's application_controller will not.
All indentation was normalized by rubocop auto-correct at 80e66cc4d9.
But comments was still kept absolute position. This commit aligns
comments with method definitions for consistency.
Usually users extends tests classes doing something like:
ActionView::TestCase.include MyCustomTestHelpers
This is bad because it will load the ActionView::TestCase right aways
and this will load ActionController::Base making its on_load hooks to
execute early than it should.
One way to fix this is using the on_load hooks of the components like:
ActiveSupport.on_load(:action_view) do
ActionView::TestCase.include MyCustomTestHelpers
end
The problem with this approach is that the test extension will be only
load when ActionView::Base is loaded and this may happen too late in the
test.
To fix this we are adding hooks to people extend the test classes that
will be loaded exactly when the test classes are needed.
SSL_set_verify(3) explains:
SSL_VERIFY_FAIL_IF_NO_PEER_CERT
Server mode: if the client did not return a certificate, the TLS/SSL
handshake is immediately terminated with a "handshake failure" alert.
This flag must
be used together with SSL_VERIFY_PEER.
Client mode: ignored
SSL_VERIFY_CLIENT_ONCE
Server mode: only request a client certificate on the initial TLS/SSL
handshake. Do not ask for a client certificate again in case of a
renegotiation.
This flag must be used together with SSL_VERIFY_PEER.
Client mode: ignored
The SMTP connection here uses a OpenSSL socket in client mode,
suggesting invalid/ignored flags is rather misleading.
Follows the same pattern as controllers and jobs. Exceptions raised in
delivery jobs (enqueued by `#deliver_later`) are also delegated to the
mailer's rescue_from handlers, so you can handle the DeserializationError
raised by delivery jobs:
```ruby
class MyMailer < ApplicationMailer
rescue_from ActiveJob::DeserializationError do
…
end
```
ActiveSupport::Rescuable polish:
* Add the `rescue_with_handler` class method so exceptions may be
handled at the class level without requiring an instance.
* Rationalize `exception.cause` handling. If no handler matches the
exception, fall back to the handler that matches its cause.
* Handle exceptions raised elsewhere. Pass `object: …` to execute
the `rescue_from` handler (e.g. a method call or a block to
instance_exec) against a different object. Defaults to `self`.
They would be lost when the delivery job is enqueued, otherwise.
Prevents a common, hard-to-find bug like:
```ruby
message = Notifier.welcome(user, foo)
message.message_id = my_generated_message_id
message.deliver_later
```
The message_id is silently lost here! *Only the mailer arguments are
passed to the delivery job.*
This raises an exception now.
Make modifications to the message within the mailer method or use a
custom Active Job to manage delivery instead of using #deliver_later.
After 9d37874732 `ActionDispatch::IntegrationTest`
class is loaded and defined in all Rails environments, not only test but also
production. This is not-intended loading of a class which is only used in
test environment.
To prevent not-intended loading, add `ActiveSupport.run_load_hooks` to
`ActionDispatch::IntegrationTest` with `action_dispatch_integration_test` name
and use it in `ActionMailer`.
Abstract Controller is the common component between Action Mailer and
Action Controller so if we need to share the caching component it need
to be there.