1. What is Action Mailer?
Action Mailer allows you to send emails from your Rails application. It's one of the two email related components in the Rails framework. The other is Action Mailbox, which deals with receiving emails.
Action Mailer uses classes (called "mailers") and views to create and configure the email to send. Mailers are classes that inherit from ActionMailer::Base
. Mailer classes are similar to controller classes. Both have:
- Instance variables that are accessible in views.
- The ability to use layouts and partials.
- The ability to access a params hash.
- Actions and associated views in
app/views
.
2. Creating a Mailer and Views
This section will provide a step-by-step guide to sending email with Action Mailer. Here are the details of each step.
2.1. Generate the Mailer
First, you use the "mailer" generator to create the Mailer related classes:
$ bin/rails generate mailer User create app/mailers/user_mailer.rb invoke erb create app/views/user_mailer invoke test_unit create test/mailers/user_mailer_test.rb create test/mailers/previews/user_mailer_preview.rb
Like the UserMailer
below, all generated Mailer classes inherit from ApplicationMailer
:
# app/mailers/user_mailer.rb class UserMailer < ApplicationMailer end
The ApplicationMailer
class inherits from ActionMailer::Base
, and can be used to define attributes common to all Mailers:
# app/mailers/application_mailer.rb class ApplicationMailer < ActionMailer::Base default from: "from@example.com" layout "mailer" end
If you don't want to use a generator, you can also manually add a file to the app/mailers
directory. Make sure that your class inherits from ApplicationMailer
:
# app/mailers/custom_mailer.rb class CustomMailer < ApplicationMailer end
2.2. Edit the Mailer
The UserMailer
in app/mailers/user_mailer.rb
initially doesn't have any methods. So next, we add methods (aka actions) to the mailer that will send specific emails.
Mailers have methods called "actions" and they use views to structure their content, similar to controllers. While a controller generates HTML content to send back to the client, a Mailer creates a message to be delivered via email.
Let's add a method called welcome_email
to the UserMailer
, that will send an email to the user's registered email address:
class UserMailer < ApplicationMailer default from: "notifications@example.com" def welcome_email @user = params[:user] @url = "http://example.com/login" mail(to: @user.email, subject: "Welcome to My Awesome Site") end end
The method names in mailers do not have to end in _email
.
Here is a quick explanation of the Mailer related methods used above:
- The
default
method sets default values for all emails sent from this mailer. In this case, we use it to set the:from
header value for all messages in this class. This can be overridden on a per-email basis. - The
mail
method creates the actual email message. We use it to specify the values of headers like:to
and:subject
per email.
There is also the headers
method (not used above), which is used to specify email headers with a hash or by calling headers[:field_name] = 'value'
.
It is possible to specify an action directly while using the generator like this:
$ bin/rails generate mailer User welcome_email
The above will generate the UserMailer
with an empty welcome_email
method.
You can also send multiple emails from a single mailer class. It can be convenient to group related emails together. For example, the above UserMailer
can have a goodbye_email
(and corresponding view) in addition to the welcome_email
.
2.3. Create a Mailer View
Next, for the welcome_email
action, you'll need to create a matching view in a file called welcome_email.html.erb
in the app/views/user_mailer/
directory. Here is a sample HTML template that can be used for the welcome email:
<h1>Welcome to example.com, <%= @user.name %></h1> <p> You have successfully signed up to example.com, your username is: <%= @user.login %>.<br> </p> <p> To log in to the site, just follow this link: <%= link_to 'login', login_url %>. </p> <p>Thanks for joining and have a great day!</p>
The above is the content of the <body>
tag. It will be embedded in the default mailer layout, which contains the <html>
tag. See Mailer layouts for more.
You can also create a text version of the above email and store it in welcome_email.text.erb
in the app/views/user_mailer/
directory (notice the .text.erb
extension vs. the html.erb
). Sending both formats is considered best practice because, in case of HTML rendering issues, the text version can serve as a reliable fallback. Here is a sample text email:
Welcome to example.com, <%= @user.name %> =============================================== You have successfully signed up to example.com, your username is: <%= @user.login %>. To log in to the site, just follow this link: <%= @url %>. Thanks for joining and have a great day!
Notice that in both HTML and text email templates you can use the instance variables @user
and @url
.
Now, when you call the mail
method, Action Mailer will detect the two templates (text and HTML) and automatically generate a multipart/alternative
email.
2.4. Call the Mailer
Once you have a mailer class and view set up, the next step is to actually call the mailer method that renders the email view (i.e. sends the email). Mailers can be thought of as another way of rendering views. Controller actions render a view to be sent over the HTTP protocol. Mailer actions render a view and send it through email protocols instead.
Let's see an example of using the UserMailer
to send a welcome email when a user is successfully created.
First, let's create a User
scaffold:
$ bin/rails generate scaffold user name email login $ bin/rails db:migrate
Next, we edit the create
action in the UserController
to send a welcome email when a new user is created. We do this by inserting a call to UserMailer.with(user: @user).welcome_email
right after the user is successfully saved.
We use deliver_later
to enqueue the email to be sent later. This way, the controller action will continue without waiting for the email sending code to run. The deliver_later
method is backed by Active Job.
class UsersController < ApplicationController # ... def create @user = User.new(user_params) respond_to do |format| if @user.save # Tell the UserMailer to send a welcome email after save UserMailer.with(user: @user).welcome_email.deliver_later format.html { redirect_to user_url(@user), notice: "User was successfully created." } format.json { render :show, status: :created, location: @user } else format.html { render :new, status: :unprocessable_entity } format.json { render json: @user.errors, status: :unprocessable_entity } end end end # ... end
Any key-value pair passed to with
becomes the params
for the Mailer action. For example, with(user: @user, account: @user.account)
makes params[:user]
and params[:account]
available in the Mailer action.
With the above mailer, view, and controller set up, if you create a new User
, you can examine the logs to see the welcome email being sent. The log file will show the text and HTML versions being sent, like this:
[ActiveJob] [ActionMailer::MailDeliveryJob] [ec4b3786-b9fc-4b5e-8153-9153095e1cbf] Delivered mail 6661f55087e34_1380c7eb86934d@Bhumis-MacBook-Pro.local.mail (19.9ms) [ActiveJob] [ActionMailer::MailDeliveryJob] [ec4b3786-b9fc-4b5e-8153-9153095e1cbf] Date: Thu, 06 Jun 2024 12:43:44 -0500 From: notifications@example.com To: test@gmail.com Message-ID: <6661f55087e34_1380c7eb86934d@Bhumis-MacBook-Pro.local.mail> Subject: Welcome to My Awesome Site Mime-Version: 1.0 Content-Type: multipart/alternative; boundary="--==_mimepart_6661f55086194_1380c7eb869259"; charset=UTF-8 Content-Transfer-Encoding: 7bit ----==_mimepart_6661f55086194_1380c7eb869259 Content-Type: text/plain; ... ----==_mimepart_6661f55086194_1380c7eb869259 Content-Type: text/html; ...
You can also call the mailer from the Rails console and send emails, perhaps useful as a test before you have a controller action set up. The below will send the same welcome_email
as above:
irb> user = User.first irb> UserMailer.with(user: user).welcome_email.deliver_later
If you want to send emails right away (from a cronjob for example) you can call deliver_now
:
class SendWeeklySummary def run User.find_each do |user| UserMailer.with(user: user).weekly_summary.deliver_now end end end
A method like weekly_summary
from UserMailer
would return an ActionMailer::MessageDelivery
object, which has the methods deliver_now
or deliver_later
to send itself now or later. The ActionMailer::MessageDelivery
object is a wrapper around a Mail::Message
. If you want to inspect, alter, or do anything else with the Mail::Message
object you can access it with the message
method on the ActionMailer::MessageDelivery
object.
Here is an example of the MessageDelivery
object from the Rails console example above:
irb> UserMailer.with(user: user).weekly_summary #<ActionMailer::MailDeliveryJob:0x00007f84cb0367c0 @_halted_callback_hook_called=nil, @_scheduled_at_time=nil, @arguments= ["UserMailer", "welcome_email", "deliver_now", {:params=> {:user=> #<User:0x00007f84c9327198 id: 1, name: "Bhumi", email: "hi@gmail.com", login: "Bhumi", created_at: Thu, 06 Jun 2024 17:43:44.424064000 UTC +00:00, updated_at: Thu, 06 Jun 2024 17:43:44.424064000 UTC +00:00>}, :args=>[]}], @exception_executions={}, @executions=0, @job_id="07747748-59cc-4e88-812a-0d677040cd5a", @priority=nil,
3. Multipart Emails and Attachments
The multipart
MIME type represents a document that's comprised of multiple component parts, each of which may have its own individual MIME type (such as the text/html
and text/plain
). The multipart
type encapsulates sending multiple files together in one transaction such as attaching multiple files to an email for example.
3.1. Adding Attachments
You can add an attachment with Action Mailer by passing the file name and content to the attachments method. Action Mailer will automatically guess the mime_type
, set the encoding
, and create the attachment.
attachments["filename.jpg"] = File.read("/path/to/filename.jpg")
When the mail
method is triggered, it will send a multipart email with an attachment, properly nested with the top level being multipart/mixed
and the first part being a multipart/alternative
containing the plain text and HTML email messages.
The other way to send attachments is to specify the file name, MIME-type and encoding headers, and content. Action Mailer will use the settings you pass in.
encoded_content = SpecialEncode(File.read("/path/to/filename.jpg")) attachments["filename.jpg"] = { mime_type: "application/gzip", encoding: "SpecialEncoding", content: encoded_content }
Action Mailer will automatically Base64 encode an attachment. If you want something different, you can encode your content and pass in the encoded content as well as the encoding in a Hash
to the attachments
method. If you specify an encoding, Action Mailer will not try to Base64 encode the attachment.
3.2. Making Inline Attachments
Sometimes, you may want to send an attachment (e.g. image) inline, so it appears within the email body.
In order to do this, first, you turn an attachment into an inline attachment by calling #inline
:
def welcome attachments.inline["image.jpg"] = File.read("/path/to/image.jpg") end
Then in the view, you can reference attachments
as a hash and specify the file you want to show inline. You can call url
on the hash and pass the result into the image_tag
method:
<p>Hello there, this is the image you requested:</p> <%= image_tag attachments['image.jpg'].url %>
Since this is a standard call to image_tag
you can pass in an options hash after the attachment URL as well:
<p>Hello there, this is our image</p> <%= image_tag attachments['image.jpg'].url, alt: 'My Photo', class: 'photos' %>
3.3. Multipart Emails
As demonstrated in Create a Mailer View, Action Mailer will automatically send multipart emails if you have different templates for the same action. For example, if you have a UserMailer
with welcome_email.text.erb
and welcome_email.html.erb
in app/views/user_mailer
, Action Mailer will automatically send a multipart email with both the HTML and text versions included as separate parts.
The Mail gem has helper methods for making a multipart/alternate
email for text/plain
and text/html
MIME types and you can manually create any other type of MIME email.
The order of the parts getting inserted is determined by the :parts_order
inside of the ActionMailer::Base.default
method.
Multipart is also used when you send attachments with email.
4. Mailer Views and Layouts
Action Mailer uses view files to specify the content to be sent in emails. Mailer views are located in the app/views/name_of_mailer_class
directory by default. Similar to a controller view, the name of the file matches the name of the mailer method.
Mailer views are rendered within a layout, similar to controller views. Mailer layouts are located in app/views/layouts
. The default layout is mailer.html.erb
and mailer.text.erb
. This section covers various features around mailer views and layouts.
4.1. Configuring Custom View Paths
It is possible to change the default mailer view for your action in various ways, as shown below.
There are template_path
and template_name
options to the mail
method:
class UserMailer < ApplicationMailer default from: "notifications@example.com" def welcome_email @user = params[:user] @url = "http://example.com/login" mail(to: @user.email, subject: "Welcome to My Awesome Site", template_path: "notifications", template_name: "hello") end end
The above configures the mail
method to look for a template with the name hello
in the app/views/notifications
directory. You can also specify an array of paths for template_path
, and they will be searched in order.
If you need more flexibility, you can also pass a block and render a specific template. You can also render plain text inline without using a template file:
class UserMailer < ApplicationMailer default from: "notifications@example.com" def welcome_email @user = params[:user] @url = "http://example.com/login" mail(to: @user.email, subject: "Welcome to My Awesome Site") do |format| format.html { render "another_template" } format.text { render plain: "hello" } end end end
This will render the template another_template.html.erb
for the HTML part and "hello" for the text part. The render method is the same one used inside of Action Controller, so you can use all the same options, such as :plain
, :inline
, etc.
Lastly, if you need to render a template located outside of the default app/views/mailer_name/
directory, you can apply the prepend_view_path
, like so:
class UserMailer < ApplicationMailer prepend_view_path "custom/path/to/mailer/view" # This will try to load "custom/path/to/mailer/view/welcome_email" template def welcome_email # ... end end
There is also an append_view_path
method.
4.2. Generating URLs in Action Mailer Views
In order to add URLs to your mailer, you need to set the host
value to your application's domain first. This is because, unlike controllers, the mailer instance doesn't have any context about the incoming request.
You can configure the default host
across the application in config/application.rb
:
config.action_mailer.default_url_options = { host: "example.com" }
Once the host
is configured, it is recommended that email views use the *_url
with the full URL, and not the *_path
helpers with relative URL. Since email clients do not have web request context, *_path
helpers have no base URL to form complete web addresses.
For example, instead of:
<%= link_to 'welcome', welcome_path %>
Use:
<%= link_to 'welcome', welcome_url %>
By using the full URL, your links will work correctly in your emails.
4.2.1. Generating URLs with url_for
The url_for
helper generates a full URL, by default, in templates.
If you haven't configured the :host
option globally, you'll need to pass it to url_for
.
<%= url_for(host: 'example.com', controller: 'welcome', action: 'greeting') %>
4.2.2. Generating URLs with Named Routes
Similar to other URLs, you need to use the *_url
variant of named route helpers in emails as well.
You either configure the :host
option globally or make sure to pass it to the URL helper:
<%= user_url(@user, host: 'example.com') %>
4.3. Adding Images in Action Mailer Views
In order to use the image_tag
helper in emails, you need to specify the :asset_host
parameter. This is because a mailer instance doesn't have any context about the incoming request.
Usually the :asset_host
is consistent across the application, so you can configure it globally in config/application.rb
:
config.action_mailer.asset_host = "http://example.com"
Because we can't infer the protocol from the request, you'll need to specify a protocol such as http://
or https://
in the :asset_host
config.
Now you can display an image inside your email.
<%= image_tag 'image.jpg' %>
4.4. Caching Mailer View
You can perform fragment caching in mailer views, similar to application views, using the cache
method.
<% cache do %> <%= @company.name %> <% end %>
And to use this feature, you need to enable it in your application's config/environments/*.rb
file:
config.action_mailer.perform_caching = true
Fragment caching is also supported in multipart emails. Read more about caching in the Rails caching guide.
4.5. Action Mailer Layouts
Just like controller layouts, you can also have mailer layouts. Mailer layouts are located in app/views/layouts
. Here is the default layout:
# app/views/layouts/mailer.html.erb <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <style> /* Email styles need to be inline */ </style> </head> <body> <%= yield %> </body> </html>
The above layout is in a file mailer.html.erb
. The default layout name is specified in the ApplicationMailer
, as we saw earlier with the line layout "mailer"
in the Generate Mailer section. Similar to controller layouts, you use yield
to render the mailer view inside the layout.
To use a different layout for a given mailer, call layout
:
class UserMailer < ApplicationMailer layout "awesome" # Use awesome.(html|text).erb as the layout end
To use a specific layout for a given email, you can pass in a layout: 'layout_name'
option to the render call inside the format block:
class UserMailer < ApplicationMailer def welcome_email mail(to: params[:user].email) do |format| format.html { render layout: "my_layout" } format.text end end end
The above will render the HTML part using the my_layout.html.erb
file and the text part with the usual user_mailer.text.erb
file.
5. Sending Email
5.1. Sending Email to Multiple Recipients
It is possible to send an email to more than one recipient by setting the :to
field to a list of email addresses. The list of emails can be an array or a single string with the addresses separated by commas.
For example, to inform all admins of a new registration:
class AdminMailer < ApplicationMailer default to: -> { Admin.pluck(:email) }, from: "notification@example.com" def new_registration(user) @user = user mail(subject: "New User Signup: #{@user.email}") end end
The same format can be used to add multiple carbon copy (cc) and blind carbon copy (bcc) recipients, by setting the :cc
and :bcc
keys respectively (similarly to the :to
field).
5.2. Sending Email with Name
It's possible to show the name, in addition to the email address, of the person who receives the email or sends the email.
To show the name of the person when they receive the email, you can use email_address_with_name
method in to:
:
def welcome_email @user = params[:user] mail( to: email_address_with_name(@user.email, @user.name), subject: "Welcome to My Awesome Site" ) end
The same method in from:
works to display the name of the sender:
class UserMailer < ApplicationMailer default from: email_address_with_name("notification@example.com", "Example Company Notifications") end
If the name is blank (nil
or empty string), it returns the email address.
5.3. Sending Email with Subject Translation
If you don't pass a subject to the mail method, Action Mailer will try to find it in your translations. See the Internationalization Guide for more.
5.4. Sending Emails without Template Rendering
There may be cases in which you want to skip the template rendering step and instead supply the email body as a string. You can achieve this using the :body
option. Remember to set the :content_type
option, such as setting it to text/html
below. Rails will default to text/plain
as the content type.
class UserMailer < ApplicationMailer def welcome_email mail(to: params[:user].email, body: params[:email_body], content_type: "text/html", subject: "Already rendered!") end end
5.5. Sending Emails with Dynamic Delivery Options
If you wish to override the default delivery configuration (e.g. SMTP credentials) while delivering emails, you can do this using delivery_method_options
in the mailer action.
class UserMailer < ApplicationMailer def welcome_email @user = params[:user] @url = user_url(@user) delivery_options = { user_name: params[:company].smtp_user, password: params[:company].smtp_password, address: params[:company].smtp_host } mail(to: @user.email, subject: "Please see the Terms and Conditions attached", delivery_method_options: delivery_options) end end
6. Action Mailer Callbacks
Action Mailer allows for you to specify a before_action
, after_action
, and around_action
to configure the message, and before_deliver
, after_deliver
and around_deliver
to control the delivery.
Callbacks can be specified with a block or a symbol representing a method name in the mailer class, similar to other callbacks (in controllers or models).
Here are some examples of when you may use one of these callbacks with mailers.
6.1. before_action
You can use a before_action
to set instance variables, populate the mail object with defaults, or insert default headers and attachments.
class InvitationsMailer < ApplicationMailer before_action :set_inviter_and_invitee before_action { @account = params[:inviter].account } default to: -> { @invitee.email_address }, from: -> { common_address(@inviter) }, reply_to: -> { @inviter.email_address_with_name } def account_invitation mail subject: "#{@inviter.name} invited you to their Basecamp (#{@account.name})" end def project_invitation @project = params[:project] @summarizer = ProjectInvitationSummarizer.new(@project.bucket) mail subject: "#{@inviter.name.familiar} added you to a project in Basecamp (#{@account.name})" end private def set_inviter_and_invitee @inviter = params[:inviter] @invitee = params[:invitee] end end
6.2. after_action
You can use an after_action
callback with a similar setup as a before_action
but also have access to instance variables that were set in your mailer action.
You can also use an after_action
to override delivery method settings by updating mail.delivery_method.settings
.
class UserMailer < ApplicationMailer before_action { @business, @user = params[:business], params[:user] } after_action :set_delivery_options, :prevent_delivery_to_guests, :set_business_headers def feedback_message end def campaign_message end private def set_delivery_options # You have access to the mail instance, # @business and @user instance variables here if @business && @business.has_smtp_settings? mail.delivery_method.settings.merge!(@business.smtp_settings) end end def prevent_delivery_to_guests if @user && @user.guest? mail.perform_deliveries = false end end def set_business_headers if @business headers["X-SMTPAPI-CATEGORY"] = @business.code end end end
6.3. after_deliver
You could use an after_deliver
to record the delivery of the message. It also allows observer/interceptor-like behaviors, but with access to the full mailer context.
class UserMailer < ApplicationMailer after_deliver :mark_delivered before_deliver :sandbox_staging after_deliver :observe_delivery def feedback_message @feedback = params[:feedback] end private def mark_delivered params[:feedback].touch(:delivered_at) end # An Interceptor alternative. def sandbox_staging message.to = ["sandbox@example.com"] if Rails.env.staging? end # A callback has more context than the comparable Observer example. def observe_delivery EmailDelivery.log(message, self.class, action_name, params) end end
Mailer callbacks abort further processing if body
is set to a non-nil value. before_deliver
can abort with throw :abort
.
7. Action Mailer View Helpers
Action Mailer views have access to most of the same helpers as regular views.
There are also some Action Mailer-specific helper methods available in ActionMailer::MailHelper
. For example, these allow accessing the mailer instance from your view with mailer
, and accessing the message as message
:
<%= stylesheet_link_tag mailer.name.underscore %> <h1><%= message.subject %></h1>
8. Action Mailer Configuration
This section shows some example configurations for Action Mailer.
For more details on the various configuration options, see the Configuring Rails Applications guide. You can specify configuration options in environment specific files such as production.rb.
8.1. Example Action Mailer Configuration
Here is an example using the :sendmail
delivery method, added to a config/environments/$RAILS_ENV.rb
file:
config.action_mailer.delivery_method = :sendmail # Defaults to: # config.action_mailer.sendmail_settings = { # location: '/usr/sbin/sendmail', # arguments: %w[ -i ] # } config.action_mailer.perform_deliveries = true config.action_mailer.raise_delivery_errors = true config.action_mailer.default_options = { from: "no-reply@example.com" }
8.2. Action Mailer Configuration for Gmail
Add this to your config/environments/$RAILS_ENV.rb
file to send via Gmail:
config.action_mailer.delivery_method = :smtp config.action_mailer.smtp_settings = { address: "smtp.gmail.com", port: 587, domain: "example.com", user_name: Rails.application.credentials.dig(:smtp, :user_name), password: Rails.application.credentials.dig(:smtp, :password), authentication: "plain", enable_starttls: true, open_timeout: 5, read_timeout: 5 }
Google blocks sign-ins from apps it deems less secure. You can change your Gmail settings to allow the attempts. If your Gmail account has 2-factor authentication enabled, then you will need to set an app password and use that instead of your regular password.
9. Previewing and Testing Mailers
You can find detailed instructions on how to test your mailers in the testing guide.
9.1. Previewing Emails
You can preview rendered email templates visually by visiting a special Action Mailer preview URL. To set up a preview for UserMailer
, create a class named UserMailerPreview
in the test/mailers/previews/
directory. To see the preview of welcome_email
from UserMailer
, implement a method that has the same name in UserMailerPreview
and call UserMailer.welcome_email
:
class UserMailerPreview < ActionMailer::Preview def welcome_email UserMailer.with(user: User.first).welcome_email end end
Now the preview will be available at http://localhost:3000/rails/mailers/user_mailer/welcome_email.
If you change something in the mailer view at app/views/user_mailer/welcome_email.html.erb
or the mailer itself, the preview will automatically be updated. A list of previews is also available in http://localhost:3000/rails/mailers.
By default, these preview classes live in test/mailers/previews
. This can be configured using the preview_paths
option. For example, if you want to add lib/mailer_previews
to it, you can configure it in config/application.rb
:
config.action_mailer.preview_paths << "#{Rails.root}/lib/mailer_previews"
9.2. Rescuing Errors
Rescue blocks inside of a mailer method cannot rescue errors that occur outside of rendering. For example, record deserialization errors in a background job, or errors from a third-party mail delivery service.
To rescue errors that occur during any part of the mailing process, use rescue_from:
class NotifierMailer < ApplicationMailer rescue_from ActiveJob::DeserializationError do # ... end rescue_from "SomeThirdPartyService::ApiError" do # ... end def notify(recipient) mail(to: recipient, subject: "Notification") end end
10. Intercepting and Observing Emails
Action Mailer provides hooks into the Mail observer and interceptor methods. These allow you to register classes that are called during the mail delivery life cycle of every email sent.
10.1. Intercepting Emails
Interceptors allow you to make modifications to emails before they are handed off to the delivery agents. An interceptor class must implement the .delivering_email(message)
method which will be called before the email is sent.
class SandboxEmailInterceptor def self.delivering_email(message) message.to = ["sandbox@example.com"] end end
The interceptor needs to be registered using the interceptors
config option. You can do this in an initializer file like config/initializers/mail_interceptors.rb
:
Rails.application.configure do if Rails.env.staging? config.action_mailer.interceptors = %w[SandboxEmailInterceptor] end end
The example above uses a custom environment called "staging" for a production-like server but for testing purposes. You can read Creating Rails Environments for more information about custom Rails environments.
10.2. Observing Emails
Observers give you access to the email message after it has been sent. An observer class must implement the :delivered_email(message)
method, which will be called after the email is sent.
class EmailDeliveryObserver def self.delivered_email(message) EmailDelivery.log(message) end end
Similar to interceptors, you must register observers using the observers
config option. You can do this in an initializer file like config/initializers/mail_observers.rb
:
Rails.application.configure do config.action_mailer.observers = %w[EmailDeliveryObserver] end