CINXE.COM

Action Mailer Basics — Ruby on Rails Guides

<!doctype html> <html dir="ltr" lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Action Mailer Basics — Ruby on Rails Guides</title> <link rel="stylesheet" type="text/css" href="stylesheets/style-6fc5bf25e695f363fd1dd3d9dbb2f997.css" data-turbo-track="reload"> <link rel="stylesheet" type="text/css" href="stylesheets/print-a87ee66d50ce96bb83ac082f1249fe3e.css" media="print"> <link rel="stylesheet" type="text/css" href="stylesheets/highlight-2794201d063bd2e4dbd0f0874c2a3f6f.css" data-turbo-track="reload"> <link rel="icon" href="images/favicon.ico" sizes="any"> <link rel="apple-touch-icon" href="images/icon.png"> <link rel="canonical" href="https://guides.rubyonrails.org/action_mailer_basics.html"> <script src="javascripts/@hotwired--turbo-764f59c7edbeb902a9068c0340dd274e.js" data-turbo-track="reload"></script> <script src="javascripts/clipboard-8b7aed6f069f0cf58eeae353cd2f898b.js" data-turbo-track="reload"></script> <script src="javascripts/guides-751b87e159daf790ddf7e8e88ad8465a.js" data-turbo-track="reload"></script> <meta property="og:title" content="Action Mailer Basics — Ruby on Rails Guides" /> <meta name="description" content="Action Mailer BasicsThis guide covers sending emails from your Rails application.After reading this guide, you will know: How to generate and edit Action Mailer classes and mailer views. How to send attachments and multipart emails. How to use Action Mailer callbacks. How to configure Action Mailer for your environment. How to preview emails and test your Action Mailer classes." /> <meta property="og:description" content="Action Mailer BasicsThis guide covers sending emails from your Rails application.After reading this guide, you will know: How to generate and edit Action Mailer classes and mailer views. How to send attachments and multipart emails. How to use Action Mailer callbacks. How to configure Action Mailer for your environment. How to preview emails and test your Action Mailer classes." /> <meta property="og:locale" content="en_US" /> <meta property="og:site_name" content="Ruby on Rails Guides" /> <meta property="og:image" content="https://avatars.githubusercontent.com/u/4223" /> <meta property="og:type" content="website" /> <link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link href="https://fonts.googleapis.com/css2?family=Noto+Sans+Arabic:wght@100..900&display=swap" rel="stylesheet"> <link href="https://fonts.googleapis.com/css2?family=Heebo:wght@100..900&family=Noto+Sans+Arabic:wght@100..900&display=swap" rel="stylesheet"> <meta name="theme-color" content="#C81418"> </head> <body dir="ltr" class="guide no-js"> <script> document.body.classList.remove('no-js') </script> <a id="main-skip-link" href="#main" class="skip-link" data-turbo="false"> Skip to main content </a> <div id="mobile-navigation-bar"> <div class="wrapper"> <strong class="more-info-label">More at <a href="https://rubyonrails.org/">rubyonrails.org:</a> </strong> <button type="button" class="js-only red-button more-info-button" id="more-info" aria-controls="more-info-links" aria-expanded="false"> More Ruby on Rails </button> <ul id="more-info-links" class="more-info-links hidden"> <li class="more-info"><a href="https://rubyonrails.org/blog">Blog</a></li> <li class="more-info"><a href="https://guides.rubyonrails.org/">Guides</a></li> <li class="more-info"><a href="https://api.rubyonrails.org/">API</a></li> <li class="more-info"><a href="https://discuss.rubyonrails.org/">Forum</a></li> <li class="more-info"><a href="https://github.com/rails/rails">Contribute on GitHub</a></li> </ul> </div> </div> <header id="page-header"> <div class="wrapper clearfix"> <nav id="feature-nav"> <div class="header-logo"> <a href="index.html" title="Guides home for v8.0.1 Guides">Guides</a> <span id="version-switcher" class="js-only"> <label for="version-switcher-select">Version: <span class="visibly-hidden">pick from the list to go to that Rails version's guides</span></label> <select id="version-switcher-select" class="guides-version"> <option value="https://edgeguides.rubyonrails.org/">Edge</option> <option value="https://guides.rubyonrails.org/v8.0/action_mailer_basics.html" selected>8.0</option> <option value="https://guides.rubyonrails.org/v7.2/action_mailer_basics.html">7.2</option> <option value="https://guides.rubyonrails.org/v7.1/action_mailer_basics.html">7.1</option> <option value="https://guides.rubyonrails.org/v7.0/action_mailer_basics.html">7.0</option> <option value="https://guides.rubyonrails.org/v6.1/action_mailer_basics.html">6.1</option> <option value="https://guides.rubyonrails.org/v6.0/action_mailer_basics.html">6.0</option> <option value="https://guides.rubyonrails.org/v5.2/action_mailer_basics.html">5.2</option> <option value="https://guides.rubyonrails.org/v5.1/action_mailer_basics.html">5.1</option> <option value="https://guides.rubyonrails.org/v5.0/action_mailer_basics.html">5.0</option> <option value="https://guides.rubyonrails.org/v4.2/action_mailer_basics.html">4.2</option> <option value="https://guides.rubyonrails.org/v4.1/action_mailer_basics.html">4.1</option> <option value="https://guides.rubyonrails.org/v4.0/action_mailer_basics.html">4.0</option> <option value="https://guides.rubyonrails.org/v3.2/action_mailer_basics.html">3.2</option> <option value="https://guides.rubyonrails.org/v3.1/action_mailer_basics.html">3.1</option> <option value="https://guides.rubyonrails.org/v3.0/action_mailer_basics.html">3.0</option> <option value="https://guides.rubyonrails.org/v2.3/action_mailer_basics.html">2.3</option> </select> </span> </div> <ul class="nav"> <li><a class="nav-item" id="home_nav" href="https://rubyonrails.org/">Home</a></li> <li class="guides-index guides-index-large"> <a href="index.html" id="guides-menu-button" data-aria-controls="guides" data-aria-expanded="false" class="guides-index-item nav-item">Guides Index</a> <div id="guides" class="clearfix" style="display: none;"> <hr /> <dl class="guides-section-container"> <div class="guides-section"> <dt>Start Here</dt> <dd><a href="getting_started.html">Getting Started with Rails</a></dd> <dd><a href="install_ruby_on_rails.html">Install Ruby on Rails</a></dd> </div> <div class="guides-section"> <dt>Models</dt> <dd><a href="active_record_basics.html">Active Record Basics</a></dd> <dd><a href="active_record_migrations.html">Active Record Migrations</a></dd> <dd><a href="active_record_validations.html">Active Record Validations</a></dd> <dd><a href="active_record_callbacks.html">Active Record Callbacks</a></dd> <dd><a href="association_basics.html">Active Record Associations</a></dd> <dd><a href="active_record_querying.html">Active Record Query Interface</a></dd> <dd><a href="active_model_basics.html">Active Model Basics</a></dd> </div> <div class="guides-section"> <dt>Views</dt> <dd><a href="action_view_overview.html">Action View Overview</a></dd> <dd><a href="layouts_and_rendering.html">Layouts and Rendering in Rails</a></dd> <dd><a href="action_view_helpers.html">Action View Helpers</a></dd> <dd><a href="form_helpers.html">Action View Form Helpers</a></dd> </div> <div class="guides-section"> <dt>Controllers</dt> <dd><a href="action_controller_overview.html">Action Controller Overview</a></dd> <dd><a href="action_controller_advanced_topics.html">Action Controller Advanced Topics</a></dd> <dd><a href="routing.html">Rails Routing from the Outside In</a></dd> </div> <div class="guides-section"> <dt>Other Components</dt> <dd><a href="active_support_core_extensions.html">Active Support Core Extensions</a></dd> <dd><a href="action_mailer_basics.html">Action Mailer Basics</a></dd> <dd><a href="action_mailbox_basics.html">Action Mailbox Basics</a></dd> <dd><a href="action_text_overview.html">Action Text Overview</a></dd> <dd><a href="active_job_basics.html">Active Job Basics</a></dd> <dd><a href="active_storage_overview.html">Active Storage Overview</a></dd> <dd><a href="action_cable_overview.html">Action Cable Overview</a></dd> </div> <div class="guides-section"> <dt>Digging Deeper</dt> <dd><a href="i18n.html">Rails Internationalization (I18n) API</a></dd> <dd><a href="testing.html">Testing Rails Applications</a></dd> <dd><a href="debugging_rails_applications.html">Debugging Rails Applications</a></dd> <dd><a href="configuring.html">Configuring Rails Applications</a></dd> <dd><a href="command_line.html">The Rails Command Line</a></dd> <dd><a href="asset_pipeline.html">The Asset Pipeline</a></dd> <dd><a href="working_with_javascript_in_rails.html">Working with JavaScript in Rails</a></dd> <dd><a href="autoloading_and_reloading_constants.html">Autoloading and Reloading</a></dd> <dd><a href="api_app.html">Using Rails for API-only Applications</a></dd> </div> <div class="guides-section"> <dt>Going to Production</dt> <dd><a href="tuning_performance_for_deployment.html">Tuning Performance for Deployment</a></dd> <dd><a href="caching_with_rails.html">Caching with Rails: An Overview</a></dd> <dd><a href="security.html">Securing Rails Applications</a></dd> <dd><a href="error_reporting.html">Error Reporting in Rails Applications</a></dd> </div> <div class="guides-section"> <dt>Advanced Active Record</dt> <dd><a href="active_record_multiple_databases.html">Multiple Databases</a></dd> <dd><a href="active_record_composite_primary_keys.html">Composite Primary Keys</a></dd> </div> <div class="guides-section"> <dt>Extending Rails</dt> <dd><a href="rails_on_rack.html">Rails on Rack</a></dd> <dd><a href="generators.html">Creating and Customizing Rails Generators &amp; Templates</a></dd> </div> <div class="guides-section"> <dt>Contributing</dt> <dd><a href="contributing_to_ruby_on_rails.html">Contributing to Ruby on Rails</a></dd> <dd><a href="api_documentation_guidelines.html">API Documentation Guidelines</a></dd> <dd><a href="ruby_on_rails_guides_guidelines.html">Guides Guidelines</a></dd> <dd><a href="development_dependencies_install.html">Installing Rails Core Development Dependencies</a></dd> </div> <div class="guides-section"> <dt>Policies</dt> <dd><a href="maintenance_policy.html">Maintenance Policy</a></dd> </div> <div class="guides-section"> <dt>Release Notes</dt> <dd><a href="upgrading_ruby_on_rails.html">Upgrading Ruby on Rails</a></dd> <dd><a href="8_0_release_notes.html">Version 8.0 - November 2024</a></dd> <dd><a href="7_2_release_notes.html">Version 7.2 - August 2024</a></dd> <dd><a href="7_1_release_notes.html">Version 7.1 - October 2023</a></dd> <dd><a href="7_0_release_notes.html">Version 7.0 - December 2021</a></dd> <dd><a href="6_1_release_notes.html">Version 6.1 - December 2020</a></dd> <dd><a href="6_0_release_notes.html">Version 6.0 - August 2019</a></dd> <dd><a href="5_2_release_notes.html">Version 5.2 - April 2018</a></dd> <dd><a href="5_1_release_notes.html">Version 5.1 - April 2017</a></dd> <dd><a href="5_0_release_notes.html">Version 5.0 - June 2016</a></dd> <dd><a href="4_2_release_notes.html">Version 4.2 - December 2014</a></dd> <dd><a href="4_1_release_notes.html">Version 4.1 - April 2014</a></dd> <dd><a href="4_0_release_notes.html">Version 4.0 - June 2013</a></dd> <dd><a href="3_2_release_notes.html">Version 3.2 - January 2012</a></dd> <dd><a href="3_1_release_notes.html">Version 3.1 - August 2011</a></dd> <dd><a href="3_0_release_notes.html">Version 3.0 - August 2010</a></dd> <dd><a href="2_3_release_notes.html">Version 2.3 - March 2009</a></dd> <dd><a href="2_2_release_notes.html">Version 2.2 - November 2008</a></dd> </div> </dl> </div> </li> <li><a class="nav-item" href="contributing_to_ruby_on_rails.html">Contribute</a></li> <li class="guides-index guides-index-small js-only"> <label for="guides-selector"> Navigate to a guide: </label> <select id="guides-selector" class="guides-index-item nav-item"> <option value="index.html">Guides Index</option> <optgroup label="Start Here"> <option value="getting_started.html">Getting Started with Rails</option> <option value="install_ruby_on_rails.html">Install Ruby on Rails</option> </optgroup> <optgroup label="Models"> <option value="active_record_basics.html">Active Record Basics</option> <option value="active_record_migrations.html">Active Record Migrations</option> <option value="active_record_validations.html">Active Record Validations</option> <option value="active_record_callbacks.html">Active Record Callbacks</option> <option value="association_basics.html">Active Record Associations</option> <option value="active_record_querying.html">Active Record Query Interface</option> <option value="active_model_basics.html">Active Model Basics</option> </optgroup> <optgroup label="Views"> <option value="action_view_overview.html">Action View Overview</option> <option value="layouts_and_rendering.html">Layouts and Rendering in Rails</option> <option value="action_view_helpers.html">Action View Helpers</option> <option value="form_helpers.html">Action View Form Helpers</option> </optgroup> <optgroup label="Controllers"> <option value="action_controller_overview.html">Action Controller Overview</option> <option value="action_controller_advanced_topics.html">Action Controller Advanced Topics</option> <option value="routing.html">Rails Routing from the Outside In</option> </optgroup> <optgroup label="Other Components"> <option value="active_support_core_extensions.html">Active Support Core Extensions</option> <option value="action_mailer_basics.html">Action Mailer Basics</option> <option value="action_mailbox_basics.html">Action Mailbox Basics</option> <option value="action_text_overview.html">Action Text Overview</option> <option value="active_job_basics.html">Active Job Basics</option> <option value="active_storage_overview.html">Active Storage Overview</option> <option value="action_cable_overview.html">Action Cable Overview</option> </optgroup> <optgroup label="Digging Deeper"> <option value="i18n.html">Rails Internationalization (I18n) API</option> <option value="testing.html">Testing Rails Applications</option> <option value="debugging_rails_applications.html">Debugging Rails Applications</option> <option value="configuring.html">Configuring Rails Applications</option> <option value="command_line.html">The Rails Command Line</option> <option value="asset_pipeline.html">The Asset Pipeline</option> <option value="working_with_javascript_in_rails.html">Working with JavaScript in Rails</option> <option value="autoloading_and_reloading_constants.html">Autoloading and Reloading</option> <option value="api_app.html">Using Rails for API-only Applications</option> </optgroup> <optgroup label="Going to Production"> <option value="tuning_performance_for_deployment.html">Tuning Performance for Deployment</option> <option value="caching_with_rails.html">Caching with Rails: An Overview</option> <option value="security.html">Securing Rails Applications</option> <option value="error_reporting.html">Error Reporting in Rails Applications</option> </optgroup> <optgroup label="Advanced Active Record"> <option value="active_record_multiple_databases.html">Multiple Databases</option> <option value="active_record_composite_primary_keys.html">Composite Primary Keys</option> </optgroup> <optgroup label="Extending Rails"> <option value="rails_on_rack.html">Rails on Rack</option> <option value="generators.html">Creating and Customizing Rails Generators &amp; Templates</option> </optgroup> <optgroup label="Contributing"> <option value="contributing_to_ruby_on_rails.html">Contributing to Ruby on Rails</option> <option value="api_documentation_guidelines.html">API Documentation Guidelines</option> <option value="ruby_on_rails_guides_guidelines.html">Guides Guidelines</option> <option value="development_dependencies_install.html">Installing Rails Core Development Dependencies</option> </optgroup> <optgroup label="Policies"> <option value="maintenance_policy.html">Maintenance Policy</option> </optgroup> <optgroup label="Release Notes"> <option value="upgrading_ruby_on_rails.html">Upgrading Ruby on Rails</option> <option value="8_0_release_notes.html">Version 8.0 - November 2024</option> <option value="7_2_release_notes.html">Version 7.2 - August 2024</option> <option value="7_1_release_notes.html">Version 7.1 - October 2023</option> <option value="7_0_release_notes.html">Version 7.0 - December 2021</option> <option value="6_1_release_notes.html">Version 6.1 - December 2020</option> <option value="6_0_release_notes.html">Version 6.0 - August 2019</option> <option value="5_2_release_notes.html">Version 5.2 - April 2018</option> <option value="5_1_release_notes.html">Version 5.1 - April 2017</option> <option value="5_0_release_notes.html">Version 5.0 - June 2016</option> <option value="4_2_release_notes.html">Version 4.2 - December 2014</option> <option value="4_1_release_notes.html">Version 4.1 - April 2014</option> <option value="4_0_release_notes.html">Version 4.0 - June 2013</option> <option value="3_2_release_notes.html">Version 3.2 - January 2012</option> <option value="3_1_release_notes.html">Version 3.1 - August 2011</option> <option value="3_0_release_notes.html">Version 3.0 - August 2010</option> <option value="2_3_release_notes.html">Version 2.3 - March 2009</option> <option value="2_2_release_notes.html">Version 2.2 - November 2008</option> </optgroup> </select> </li> </ul> </nav> </div> </header> <hr class="hide" /> <main id="main"> <article> <header id="feature"> <div class="wrapper"> <h1>Action Mailer Basics</h1><p>This guide covers sending emails from your Rails application.</p><p>After reading this guide, you will know:</p> <ul> <li>How to generate and edit Action Mailer classes and mailer views.</li> <li>How to send attachments and multipart emails.</li> <li>How to use Action Mailer callbacks.</li> <li>How to configure Action Mailer for your environment.</li> <li>How to preview emails and test your Action Mailer classes.</li> </ul> <nav id="column-side" aria-label="Chapter" class="guide-index" data-turbo="false"> <a id="chapter-nav-skip-link" href="#article-body" class="skip-link"> Skip to article body </a> <h2 class="chapter"> <picture aria-hidden="true"> <!-- Using the `source` HTML tag to set the dark theme image --> <source srcset="images/icon_book-close-bookmark-1-wht.svg" media="(prefers-color-scheme: dark)" /> <img src="images/icon_book-close-bookmark-1.svg" alt="Chapter Icon" /> </picture> Chapters </h2> <ol class="chapters"> <li><a href="#what-is-action-mailer-questionmark">What is Action Mailer?</a></li> <li><a href="#creating-a-mailer-and-views">Creating a Mailer and Views</a> <ul> <li><a href="#generate-the-mailer">Generate the Mailer</a></li> <li><a href="#edit-the-mailer">Edit the Mailer</a></li> <li><a href="#create-a-mailer-view">Create a Mailer View</a></li> <li><a href="#call-the-mailer">Call the Mailer</a></li> </ul></li> <li><a href="#multipart-emails-and-attachments">Multipart Emails and Attachments</a> <ul> <li><a href="#adding-attachments">Adding Attachments</a></li> <li><a href="#making-inline-attachments">Making Inline Attachments</a></li> <li><a href="#multipart-emails">Multipart Emails</a></li> </ul></li> <li><a href="#mailer-views-and-layouts">Mailer Views and Layouts</a> <ul> <li><a href="#configuring-custom-view-paths">Configuring Custom View Paths</a></li> <li><a href="#generating-urls-in-action-mailer-views">Generating URLs in Action Mailer Views</a></li> <li><a href="#adding-images-in-action-mailer-views">Adding Images in Action Mailer Views</a></li> <li><a href="#caching-mailer-view">Caching Mailer View</a></li> <li><a href="#action-mailer-layouts">Action Mailer Layouts</a></li> </ul></li> <li><a href="#sending-email">Sending Email</a> <ul> <li><a href="#sending-email-to-multiple-recipients">Sending Email to Multiple Recipients</a></li> <li><a href="#sending-email-with-name">Sending Email with Name</a></li> <li><a href="#sending-email-with-subject-translation">Sending Email with Subject Translation</a></li> <li><a href="#sending-emails-without-template-rendering">Sending Emails without Template Rendering</a></li> <li><a href="#sending-emails-with-dynamic-delivery-options">Sending Emails with Dynamic Delivery Options</a></li> </ul></li> <li><a href="#action-mailer-callbacks">Action Mailer Callbacks</a> <ul> <li><a href="#before-action"><code>before_action</code></a></li> <li><a href="#after-action"><code>after_action</code></a></li> <li><a href="#after-deliver"><code>after_deliver</code></a></li> </ul></li> <li><a href="#action-mailer-view-helpers">Action Mailer View Helpers</a></li> <li><a href="#action-mailer-configuration">Action Mailer Configuration</a> <ul> <li><a href="#example-action-mailer-configuration">Example Action Mailer Configuration</a></li> <li><a href="#action-mailer-configuration-for-gmail">Action Mailer Configuration for Gmail</a></li> </ul></li> <li><a href="#previewing-and-testing-mailers">Previewing and Testing Mailers</a> <ul> <li><a href="#previewing-emails">Previewing Emails</a></li> <li><a href="#rescuing-errors">Rescuing Errors</a></li> </ul></li> <li><a href="#intercepting-and-observing-emails">Intercepting and Observing Emails</a> <ul> <li><a href="#intercepting-emails">Intercepting Emails</a></li> <li><a href="#observing-emails">Observing Emails</a></li> </ul></li> </ol> </nav> </div> </header> <div class="wrapper"> <div id="column-main"> <section id="article-body"> <h2 id="what-is-action-mailer-questionmark"><a class="anchorlink" href="#what-is-action-mailer-questionmark" data-turbo="false"><span>1</span> What is Action Mailer?</a></h2><p>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 <a href="action_mailbox_basics.html">Action Mailbox</a>, which deals with <em>receiving</em> emails.</p><p>Action Mailer uses classes (called "mailers") and views to create and configure the email to send. Mailers are classes that inherit from <a href="https://api.rubyonrails.org/v8.0.1/classes/ActionMailer/Base.html"><code>ActionMailer::Base</code></a>. Mailer classes are similar to controller classes. Both have:</p> <ul> <li>Instance variables that are accessible in views.</li> <li>The ability to use layouts and partials.</li> <li>The ability to access a params hash.</li> <li>Actions and associated views in <code>app/views</code>.</li> </ul> <h2 id="creating-a-mailer-and-views"><a class="anchorlink" href="#creating-a-mailer-and-views" data-turbo="false"><span>2</span> Creating a Mailer and Views</a></h2><p>This section will provide a step-by-step guide to sending email with Action Mailer. Here are the details of each step.</p><h3 id="generate-the-mailer"><a class="anchorlink" href="#generate-the-mailer" data-turbo="false"><span>2.1</span> Generate the Mailer</a></h3><p>First, you use the "mailer" generator to create the Mailer related classes:</p><div class="interstitial code"> <pre><code class="highlight console"><span class="gp">$</span><span class="w"> </span><span class="nb">bin/rails </span>generate mailer User <span class="go">create app/mailers/user_mailer.rb</span> <span class="go">invoke erb</span> <span class="go">create app/views/user_mailer</span> <span class="go">invoke test_unit</span> <span class="go">create test/mailers/user_mailer_test.rb</span> <span class="go">create test/mailers/previews/user_mailer_preview.rb</span> </code></pre> <button class="clipboard-button" data-clipboard-text="bin/rails generate mailer User ">Copy</button> </div> <p>Like the <code>UserMailer</code> below, all generated Mailer classes inherit from <code>ApplicationMailer</code>:</p><div class="interstitial code"> <pre><code class="highlight ruby"><span class="c1"># app/mailers/user_mailer.rb</span> <span class="k">class</span> <span class="nc">UserMailer</span> <span class="o">&lt;</span> <span class="no">ApplicationMailer</span> <span class="k">end</span> </code></pre> <button class="clipboard-button" data-clipboard-text="class UserMailer < ApplicationMailer end ">Copy</button> </div> <p>The <code>ApplicationMailer</code> class inherits from <code>ActionMailer::Base</code>, and can be used to define attributes common to all Mailers:</p><div class="interstitial code"> <pre><code class="highlight ruby"><span class="c1"># app/mailers/application_mailer.rb</span> <span class="k">class</span> <span class="nc">ApplicationMailer</span> <span class="o">&lt;</span> <span class="no">ActionMailer</span><span class="o">::</span><span class="no">Base</span> <span class="n">default</span> <span class="ss">from: </span><span class="s2">"from@example.com"</span> <span class="n">layout</span> <span class="s2">"mailer"</span> <span class="k">end</span> </code></pre> <button class="clipboard-button" data-clipboard-text="class ApplicationMailer < ActionMailer::Base default from: &quot;from@example.com&quot; layout &quot;mailer&quot; end ">Copy</button> </div> <p>If you don't want to use a generator, you can also manually add a file to the <code>app/mailers</code> directory. Make sure that your class inherits from <code>ApplicationMailer</code>:</p><div class="interstitial code"> <pre><code class="highlight ruby"><span class="c1"># app/mailers/custom_mailer.rb</span> <span class="k">class</span> <span class="nc">CustomMailer</span> <span class="o">&lt;</span> <span class="no">ApplicationMailer</span> <span class="k">end</span> </code></pre> <button class="clipboard-button" data-clipboard-text="class CustomMailer < ApplicationMailer end ">Copy</button> </div> <h3 id="edit-the-mailer"><a class="anchorlink" href="#edit-the-mailer" data-turbo="false"><span>2.2</span> Edit the Mailer</a></h3><p>The <code>UserMailer</code> in <code>app/mailers/user_mailer.rb</code> initially doesn't have any methods. So next, we add methods (aka actions) to the mailer that will send specific emails.</p><p>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.</p><p>Let's add a method called <code>welcome_email</code> to the <code>UserMailer</code>, that will send an email to the user's registered email address:</p><div class="interstitial code"> <pre><code class="highlight ruby"><span class="k">class</span> <span class="nc">UserMailer</span> <span class="o">&lt;</span> <span class="no">ApplicationMailer</span> <span class="n">default</span> <span class="ss">from: </span><span class="s2">"notifications@example.com"</span> <span class="k">def</span> <span class="nf">welcome_email</span> <span class="vi">@user</span> <span class="o">=</span> <span class="n">params</span><span class="p">[</span><span class="ss">:user</span><span class="p">]</span> <span class="vi">@url</span> <span class="o">=</span> <span class="s2">"http://example.com/login"</span> <span class="n">mail</span><span class="p">(</span><span class="ss">to: </span><span class="vi">@user</span><span class="p">.</span><span class="nf">email</span><span class="p">,</span> <span class="ss">subject: </span><span class="s2">"Welcome to My Awesome Site"</span><span class="p">)</span> <span class="k">end</span> <span class="k">end</span> </code></pre> <button class="clipboard-button" data-clipboard-text="class UserMailer < ApplicationMailer default from: &quot;notifications@example.com&quot; def welcome_email @user = params[:user] @url = &quot;http://example.com/login&quot; mail(to: @user.email, subject: &quot;Welcome to My Awesome Site&quot;) end end ">Copy</button> </div> <div class="interstitial note"><p>The method names in mailers do not have to end in <code>_email</code>.</p></div><p>Here is a quick explanation of the Mailer related methods used above:</p> <ul> <li>The <a href="https://api.rubyonrails.org/v8.0.1/classes/ActionMailer/Base.html#method-c-default"><code>default</code></a> method sets default values for all emails sent from <em>this</em> mailer. In this case, we use it to set the <code>:from</code> header value for all messages in this class. This can be overridden on a per-email basis.</li> <li>The <a href="https://api.rubyonrails.org/v8.0.1/classes/ActionMailer/Base.html#method-i-mail"><code>mail</code></a> method creates the actual email message. We use it to specify the values of headers like <code>:to</code> and <code>:subject</code> per email.</li> </ul> <p>There is also the <a href="https://api.rubyonrails.org/v8.0.1/classes/ActionMailer/Base.html#method-i-headers"><code>headers</code></a> method (not used above), which is used to specify email headers with a hash or by calling <code>headers[:field_name] = 'value'</code>.</p><p>It is possible to specify an action directly while using the generator like this:</p><div class="interstitial code"> <pre><code class="highlight console"><span class="gp">$</span><span class="w"> </span><span class="nb">bin/rails </span>generate mailer User welcome_email </code></pre> <button class="clipboard-button" data-clipboard-text="bin/rails generate mailer User welcome_email ">Copy</button> </div> <p>The above will generate the <code>UserMailer</code> with an empty <code>welcome_email</code> method.</p><p>You can also send multiple emails from a single mailer class. It can be convenient to group related emails together. For example, the above <code>UserMailer</code> can have a <code>goodbye_email</code> (and corresponding view) in addition to the <code>welcome_email</code>.</p><h3 id="create-a-mailer-view"><a class="anchorlink" href="#create-a-mailer-view" data-turbo="false"><span>2.3</span> Create a Mailer View</a></h3><p>Next, for the <code>welcome_email</code> action, you'll need to create a matching view in a file called <code>welcome_email.html.erb</code> in the <code>app/views/user_mailer/</code> directory. Here is a sample HTML template that can be used for the welcome email:</p><div class="interstitial code"> <pre><code class="highlight erb"><span class="nt">&lt;h1&gt;</span>Welcome to example.com, <span class="cp">&lt;%=</span> <span class="vi">@user</span><span class="p">.</span><span class="nf">name</span> <span class="cp">%&gt;</span><span class="nt">&lt;/h1&gt;</span> <span class="nt">&lt;p&gt;</span> You have successfully signed up to example.com, your username is: <span class="cp">&lt;%=</span> <span class="vi">@user</span><span class="p">.</span><span class="nf">login</span> <span class="cp">%&gt;</span>.<span class="nt">&lt;br&gt;</span> <span class="nt">&lt;/p&gt;</span> <span class="nt">&lt;p&gt;</span> To login to the site, just follow this link: <span class="cp">&lt;%=</span> <span class="n">link_to</span> <span class="err">'</span><span class="n">login</span><span class="sb">`, login_url </span><span class="cp">%&gt;</span>. <span class="nt">&lt;/p&gt;</span> <span class="nt">&lt;p&gt;</span>Thanks for joining and have a great day!<span class="nt">&lt;/p&gt;</span> </code></pre> <button class="clipboard-button" data-clipboard-text="<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 login to the site, just follow this link: <%= link_to 'login`, login_url %>. </p> <p>Thanks for joining and have a great day!</p> ">Copy</button> </div> <div class="interstitial note"><p>the above is the content of the <code>&lt;body&gt;</code> tag. It will be embedded in the default mailer layout, which contains the <code>&lt;html&gt;</code> tag. See <a href="#mailer-views-and-layouts">Mailer layouts</a> for more.</p></div><p>You can also create a text version of the above email and store it in <code>welcome_email.text.erb</code> in the <code>app/views/user_mailer/</code> directory (notice the <code>.text.erb</code> extension vs. the <code>html.erb</code>). 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:</p><div class="interstitial code"> <pre><code class="highlight erb">Welcome to example.com, <span class="cp">&lt;%=</span> <span class="vi">@user</span><span class="p">.</span><span class="nf">name</span> <span class="cp">%&gt;</span> =============================================== You have successfully signed up to example.com, your username is: <span class="cp">&lt;%=</span> <span class="vi">@user</span><span class="p">.</span><span class="nf">login</span> <span class="cp">%&gt;</span>. To login to the site, just follow this link: <span class="cp">&lt;%=</span> <span class="vi">@url</span> <span class="cp">%&gt;</span>. Thanks for joining and have a great day! </code></pre> <button class="clipboard-button" data-clipboard-text="Welcome to example.com, <%= @user.name %> =============================================== You have successfully signed up to example.com, your username is: <%= @user.login %>. To login to the site, just follow this link: <%= @url %>. Thanks for joining and have a great day! ">Copy</button> </div> <p>Notice that in both HTML and text email templates you can use the instance variables <code>@user</code> and <code>@url</code>.</p><p>Now, when you call the <code>mail</code> method, Action Mailer will detect the two templates(text and HTML) and automatically generate a <code>multipart/alternative</code> email.</p><h3 id="call-the-mailer"><a class="anchorlink" href="#call-the-mailer" data-turbo="false"><span>2.4</span> Call the Mailer</a></h3><p>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.</p><p>Let's see an example of using the <code>UserMailer</code> to send a welcome email when a user is successfully created.</p><p>First, let's create a <code>User</code> scaffold:</p><div class="interstitial code"> <pre><code class="highlight console"><span class="gp">$</span><span class="w"> </span><span class="nb">bin/rails </span>generate scaffold user name email login <span class="gp">$</span><span class="w"> </span><span class="nb">bin/rails </span>db:migrate </code></pre> <button class="clipboard-button" data-clipboard-text="bin/rails generate scaffold user name email login bin/rails db:migrate ">Copy</button> </div> <p>Next, we edit the <code>create</code> action in the <code>UserController</code> to send a welcome email when a new user is created. We do this by inserting a call to <code>UserMailer.with(user: @user).welcome_email</code> right after the user is successfully saved.</p><div class="interstitial note"><p>We use <a href="https://api.rubyonrails.org/v8.0.1/classes/ActionMailer/MessageDelivery.html#method-i-deliver_later"><code>deliver_later</code></a> 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 <code>deliver_later</code> method is backed by <a href="active_job_basics.html#action-mailer">Active Job</a>.</p></div><div class="interstitial code"> <pre><code class="highlight ruby"><span class="k">class</span> <span class="nc">UsersController</span> <span class="o">&lt;</span> <span class="no">ApplicationController</span> <span class="c1"># ...</span> <span class="k">def</span> <span class="nf">create</span> <span class="vi">@user</span> <span class="o">=</span> <span class="no">User</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="n">user_params</span><span class="p">)</span> <span class="n">respond_to</span> <span class="k">do</span> <span class="o">|</span><span class="nb">format</span><span class="o">|</span> <span class="k">if</span> <span class="vi">@user</span><span class="p">.</span><span class="nf">save</span> <span class="c1"># Tell the UserMailer to send a welcome email after save</span> <span class="no">UserMailer</span><span class="p">.</span><span class="nf">with</span><span class="p">(</span><span class="ss">user: </span><span class="vi">@user</span><span class="p">).</span><span class="nf">welcome_email</span><span class="p">.</span><span class="nf">deliver_later</span> <span class="nb">format</span><span class="p">.</span><span class="nf">html</span> <span class="p">{</span> <span class="n">redirect_to</span> <span class="n">user_url</span><span class="p">(</span><span class="vi">@user</span><span class="p">),</span> <span class="ss">notice: </span><span class="s2">"User was successfully created."</span> <span class="p">}</span> <span class="nb">format</span><span class="p">.</span><span class="nf">json</span> <span class="p">{</span> <span class="n">render</span> <span class="ss">:show</span><span class="p">,</span> <span class="ss">status: :created</span><span class="p">,</span> <span class="ss">location: </span><span class="vi">@user</span> <span class="p">}</span> <span class="k">else</span> <span class="nb">format</span><span class="p">.</span><span class="nf">html</span> <span class="p">{</span> <span class="n">render</span> <span class="ss">:new</span><span class="p">,</span> <span class="ss">status: :unprocessable_entity</span> <span class="p">}</span> <span class="nb">format</span><span class="p">.</span><span class="nf">json</span> <span class="p">{</span> <span class="n">render</span> <span class="ss">json: </span><span class="vi">@user</span><span class="p">.</span><span class="nf">errors</span><span class="p">,</span> <span class="ss">status: :unprocessable_entity</span> <span class="p">}</span> <span class="k">end</span> <span class="k">end</span> <span class="k">end</span> <span class="c1"># ...</span> <span class="k">end</span> </code></pre> <button class="clipboard-button" data-clipboard-text="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: &quot;User was successfully created.&quot; } 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 ">Copy</button> </div> <p>Any key-value pair passed to <a href="https://api.rubyonrails.org/v8.0.1/classes/ActionMailer/Parameterized/ClassMethods.html#method-i-with"><code>with</code></a> becomes the <code>params</code> for the Mailer action. For example, <code>with(user: @user, account: @user.account)</code> makes <code>params[:user]</code> and <code>params[:account]</code> available in the Mailer action.</p><p>With the above mailer, view, and controller set up, if you create a new <code>User</code>, 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:</p><div class="interstitial code"> <pre><code class="highlight console"><span class="go">[ActiveJob] [ActionMailer::MailDeliveryJob] [ec4b3786-b9fc-4b5e-8153-9153095e1cbf] Delivered mail 6661f55087e34_1380c7eb86934d@Bhumis-MacBook-Pro.local.mail (19.9ms)</span> <span class="go">[ActiveJob] [ActionMailer::MailDeliveryJob] [ec4b3786-b9fc-4b5e-8153-9153095e1cbf] Date: Thu, 06 Jun 2024 12:43:44 -0500</span> <span class="go">From: notifications@example.com</span> <span class="go">To: test@gmail.com</span> <span class="gp">Message-ID: &lt;6661f55087e34_1380c7eb86934d@Bhumis-MacBook-Pro.local.mail&gt;</span> <span class="go">Subject: Welcome to My Awesome Site</span> <span class="go">Mime-Version: 1.0</span> <span class="gp">Content-Type: multipart/alternative;</span> <span class="gp"> boundary="--==_mimepart_6661f55086194_1380c7eb869259";</span> <span class="go"> charset=UTF-8</span> <span class="go">Content-Transfer-Encoding: 7bit</span> <span class="go">----==_mimepart_6661f55086194_1380c7eb869259</span> <span class="gp">Content-Type: text/plain;</span> <span class="c">...</span> <span class="go">----==_mimepart_6661f55086194_1380c7eb869259</span> <span class="gp">Content-Type: text/html;</span> <span class="c">...</span> </code></pre> <button class="clipboard-button" data-clipboard-text="">Copy</button> </div> <p>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 <code>welcome_email</code> as above:</p><div class="interstitial code"> <pre><code class="highlight irb"><span class="gp">irb&gt;</span><span class="w"> </span><span class="n">user</span> <span class="o">=</span> <span class="no">User</span><span class="p">.</span><span class="nf">first</span> <span class="gp">irb&gt;</span><span class="w"> </span><span class="no">UserMailer</span><span class="p">.</span><span class="nf">with</span><span class="p">(</span><span class="ss">user: </span><span class="n">user</span><span class="p">).</span><span class="nf">welcome_email</span><span class="p">.</span><span class="nf">deliver_later</span> </code></pre> <button class="clipboard-button" data-clipboard-text="user = User.first UserMailer.with(user: user).welcome_email.deliver_later ">Copy</button> </div> <p>If you want to send emails right away (from a cronjob for example) you can call <a href="https://api.rubyonrails.org/v8.0.1/classes/ActionMailer/MessageDelivery.html#method-i-deliver_now"><code>deliver_now</code></a>:</p><div class="interstitial code"> <pre><code class="highlight ruby"><span class="k">class</span> <span class="nc">SendWeeklySummary</span> <span class="k">def</span> <span class="nf">run</span> <span class="no">User</span><span class="p">.</span><span class="nf">find_each</span> <span class="k">do</span> <span class="o">|</span><span class="n">user</span><span class="o">|</span> <span class="no">UserMailer</span><span class="p">.</span><span class="nf">with</span><span class="p">(</span><span class="ss">user: </span><span class="n">user</span><span class="p">).</span><span class="nf">weekly_summary</span><span class="p">.</span><span class="nf">deliver_now</span> <span class="k">end</span> <span class="k">end</span> <span class="k">end</span> </code></pre> <button class="clipboard-button" data-clipboard-text="class SendWeeklySummary def run User.find_each do |user| UserMailer.with(user: user).weekly_summary.deliver_now end end end ">Copy</button> </div> <p>A method like <code>weekly_summary</code> from <code>UserMailer</code> would return an <a href="https://api.rubyonrails.org/v8.0.1/classes/ActionMailer/MessageDelivery.html"><code>ActionMailer::MessageDelivery</code></a> object, which has the methods <code>deliver_now</code> or <code>deliver_later</code> to send itself now or later. The <code>ActionMailer::MessageDelivery</code> object is a wrapper around a <a href="https://api.rubyonrails.org/v8.0.1/classes/Mail/Message.html"><code>Mail::Message</code></a>. If you want to inspect, alter, or do anything else with the <code>Mail::Message</code> object you can access it with the <a href="https://api.rubyonrails.org/v8.0.1/classes/ActionMailer/MessageDelivery.html#method-i-message"><code>message</code></a> method on the <code>ActionMailer::MessageDelivery</code> object.</p><p>Here is an example of the <code>MessageDelivery</code> object from the Rails console example above:</p><div class="interstitial code"> <pre><code class="highlight irb"><span class="gp">irb&gt;</span><span class="w"> </span><span class="no">UserMailer</span><span class="p">.</span><span class="nf">with</span><span class="p">(</span><span class="ss">user: </span><span class="n">user</span><span class="p">).</span><span class="nf">weekly_summary</span> <span class="c">#&lt;ActionMailer::MailDeliveryJob:0x00007f84cb0367c0</span> <span class="go"> @_halted_callback_hook_called=nil,</span> <span class="go"> @_scheduled_at_time=nil,</span> <span class="go"> @arguments=</span> <span class="go"> ["UserMailer",</span> <span class="go"> "welcome_email",</span> <span class="go"> "deliver_now",</span> <span class="go"> {:params=&gt;</span> <span class="go"> {:user=&gt;</span> <span class="c"> #&lt;User:0x00007f84c9327198</span> <span class="go"> id: 1,</span> <span class="go"> name: "Bhumi",</span> <span class="go"> email: "hi@gmail.com",</span> <span class="go"> login: "Bhumi",</span> <span class="go"> created_at: Thu, 06 Jun 2024 17:43:44.424064000 UTC +00:00,</span> <span class="go"> updated_at: Thu, 06 Jun 2024 17:43:44.424064000 UTC +00:00&gt;},</span> <span class="go"> :args=&gt;[]}],</span> <span class="go"> @exception_executions={},</span> <span class="go"> @executions=0,</span> <span class="go"> @job_id="07747748-59cc-4e88-812a-0d677040cd5a",</span> <span class="go"> @priority=nil,</span> </code></pre> <button class="clipboard-button" data-clipboard-text="UserMailer.with(user: user).weekly_summary ">Copy</button> </div> <h2 id="multipart-emails-and-attachments"><a class="anchorlink" href="#multipart-emails-and-attachments" data-turbo="false"><span>3</span> Multipart Emails and Attachments</a></h2><p>The <code>multipart</code> 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 <code>text/html</code> and <code>text/plain</code>). The <code>multipart</code> type encapsulates sending multiple files together in one transaction such as attaching multiple files to an email for example.</p><h3 id="adding-attachments"><a class="anchorlink" href="#adding-attachments" data-turbo="false"><span>3.1</span> Adding Attachments</a></h3><p>You can add an attachment with Action Mailer by passing the file name and content to the <a href="https://api.rubyonrails.org/v8.0.1/classes/ActionMailer/Base.html#method-i-attachments">attachments method</a>. Action Mailer will automatically guess the <code>mime_type</code>, set the <code>encoding</code>, and create the attachment.</p><div class="interstitial code"> <pre><code class="highlight ruby"><span class="n">attachments</span><span class="p">[</span><span class="s2">"filename.jpg"</span><span class="p">]</span> <span class="o">=</span> <span class="no">File</span><span class="p">.</span><span class="nf">read</span><span class="p">(</span><span class="s2">"/path/to/filename.jpg"</span><span class="p">)</span> </code></pre> <button class="clipboard-button" data-clipboard-text="attachments[&quot;filename.jpg&quot;] = File.read(&quot;/path/to/filename.jpg&quot;) ">Copy</button> </div> <p>When the <code>mail</code> method is triggered, it will send a multipart email with an attachment, properly nested with the top level being <code>multipart/mixed</code> and the first part being a <code>multipart/alternative</code> containing the plain text and HTML email messages.</p><p>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.</p><div class="interstitial code"> <pre><code class="highlight ruby"><span class="n">encoded_content</span> <span class="o">=</span> <span class="no">SpecialEncode</span><span class="p">(</span><span class="no">File</span><span class="p">.</span><span class="nf">read</span><span class="p">(</span><span class="s2">"/path/to/filename.jpg"</span><span class="p">))</span> <span class="n">attachments</span><span class="p">[</span><span class="s2">"filename.jpg"</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span> <span class="ss">mime_type: </span><span class="s2">"application/gzip"</span><span class="p">,</span> <span class="ss">encoding: </span><span class="s2">"SpecialEncoding"</span><span class="p">,</span> <span class="ss">content: </span><span class="n">encoded_content</span> <span class="p">}</span> </code></pre> <button class="clipboard-button" data-clipboard-text="encoded_content = SpecialEncode(File.read(&quot;/path/to/filename.jpg&quot;)) attachments[&quot;filename.jpg&quot;] = { mime_type: &quot;application/gzip&quot;, encoding: &quot;SpecialEncoding&quot;, content: encoded_content } ">Copy</button> </div> <div class="interstitial note"><p>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 <code>Hash</code> to the <code>attachments</code> method. If you specify an encoding, Action Mailer will not try to Base64 encode the attachment.</p></div><h3 id="making-inline-attachments"><a class="anchorlink" href="#making-inline-attachments" data-turbo="false"><span>3.2</span> Making Inline Attachments</a></h3><p>Sometimes, you may want to send an attachment (e.g. image) inline, so it appears within the email body.</p><p>In order to do this, first, you turn an attachment into an inline attachment by calling <code>#inline</code>:</p><div class="interstitial code"> <pre><code class="highlight ruby"><span class="k">def</span> <span class="nf">welcome</span> <span class="n">attachments</span><span class="p">.</span><span class="nf">inline</span><span class="p">[</span><span class="s2">"image.jpg"</span><span class="p">]</span> <span class="o">=</span> <span class="no">File</span><span class="p">.</span><span class="nf">read</span><span class="p">(</span><span class="s2">"/path/to/image.jpg"</span><span class="p">)</span> <span class="k">end</span> </code></pre> <button class="clipboard-button" data-clipboard-text="def welcome attachments.inline[&quot;image.jpg&quot;] = File.read(&quot;/path/to/image.jpg&quot;) end ">Copy</button> </div> <p>Then in the view, you can reference <code>attachments</code> as a hash and specify the file you want to show inline. You can call <code>url</code> on the hash and pass the result into the <a href="https://api.rubyonrails.org/v8.0.1/classes/ActionView/Helpers/AssetTagHelper.html#method-i-image_tag"><code>image_tag</code></a> method:</p><div class="interstitial code"> <pre><code class="highlight erb"><span class="nt">&lt;p&gt;</span>Hello there, this is the image you requested:<span class="nt">&lt;/p&gt;</span> <span class="cp">&lt;%=</span> <span class="n">image_tag</span> <span class="n">attachments</span><span class="p">[</span><span class="s1">'image.jpg'</span><span class="p">].</span><span class="nf">url</span> <span class="cp">%&gt;</span> </code></pre> <button class="clipboard-button" data-clipboard-text="<p>Hello there, this is the image you requested:</p> <%= image_tag attachments['image.jpg'].url %> ">Copy</button> </div> <p>Since this is a standard call to <code>image_tag</code> you can pass in an options hash after the attachment URL as well:</p><div class="interstitial code"> <pre><code class="highlight erb"><span class="nt">&lt;p&gt;</span>Hello there, this is our image<span class="nt">&lt;/p&gt;</span> <span class="cp">&lt;%=</span> <span class="n">image_tag</span> <span class="n">attachments</span><span class="p">[</span><span class="s1">'image.jpg'</span><span class="p">].</span><span class="nf">url</span><span class="p">,</span> <span class="ss">alt: </span><span class="s1">'My Photo'</span><span class="p">,</span> <span class="ss">class: </span><span class="s1">'photos'</span> <span class="cp">%&gt;</span> </code></pre> <button class="clipboard-button" data-clipboard-text="<p>Hello there, this is our image</p> <%= image_tag attachments['image.jpg'].url, alt: 'My Photo', class: 'photos' %> ">Copy</button> </div> <h3 id="multipart-emails"><a class="anchorlink" href="#multipart-emails" data-turbo="false"><span>3.3</span> Multipart Emails</a></h3><p>As demonstrated in <a href="#create-a-mailer-view">Create a Mailer View</a>, Action Mailer will automatically send multipart emails if you have different templates for the same action. For example, if you have a <code>UserMailer</code> with <code>welcome_email.text.erb</code> and <code>welcome_email.html.erb</code> in <code>app/views/user_mailer</code>, Action Mailer will automatically send a multipart email with both the HTML and text versions included as separate parts.</p><p>The <a href="https://github.com/mikel/mail">Mail</a> gem has helper methods for making a <code>multipart/alternate</code> email for <code>text/plain</code> and <code>text/html</code> <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types">MIME types</a> and you can manually create any other type of MIME email.</p><div class="interstitial note"><p>The order of the parts getting inserted is determined by the <code>:parts_order</code> inside of the <code>ActionMailer::Base.default</code> method.</p></div><p>Multipart is also used when you send attachments with email.</p><h2 id="mailer-views-and-layouts"><a class="anchorlink" href="#mailer-views-and-layouts" data-turbo="false"><span>4</span> Mailer Views and Layouts</a></h2><p>Action Mailer uses view files to specify the content to be sent in emails. Mailer views are located in the <code>app/views/name_of_mailer_class</code> directory by default. Similar to a controller view, the name of the file matches the name of the mailer method.</p><p>Mailer views are rendered within a layout, similar to controller views. Mailer layouts are located in <code>app/views/layouts</code>. The default layout is <code>mailer.html.erb</code> and <code>mailer.text.erb</code>. This sections covers various features around mailer views and layouts.</p><h3 id="configuring-custom-view-paths"><a class="anchorlink" href="#configuring-custom-view-paths" data-turbo="false"><span>4.1</span> Configuring Custom View Paths</a></h3><p>It is possible to change the default mailer view for your action in various ways, as shown below.</p><p>There is a <code>template_path</code> and <code>template_name</code> option to the <code>mail</code> method:</p><div class="interstitial code"> <pre><code class="highlight ruby"><span class="k">class</span> <span class="nc">UserMailer</span> <span class="o">&lt;</span> <span class="no">ApplicationMailer</span> <span class="n">default</span> <span class="ss">from: </span><span class="s2">"notifications@example.com"</span> <span class="k">def</span> <span class="nf">welcome_email</span> <span class="vi">@user</span> <span class="o">=</span> <span class="n">params</span><span class="p">[</span><span class="ss">:user</span><span class="p">]</span> <span class="vi">@url</span> <span class="o">=</span> <span class="s2">"http://example.com/login"</span> <span class="n">mail</span><span class="p">(</span><span class="ss">to: </span><span class="vi">@user</span><span class="p">.</span><span class="nf">email</span><span class="p">,</span> <span class="ss">subject: </span><span class="s2">"Welcome to My Awesome Site"</span><span class="p">,</span> <span class="ss">template_path: </span><span class="s2">"notifications"</span><span class="p">,</span> <span class="ss">template_name: </span><span class="s2">"hello"</span><span class="p">)</span> <span class="k">end</span> <span class="k">end</span> </code></pre> <button class="clipboard-button" data-clipboard-text="class UserMailer < ApplicationMailer default from: &quot;notifications@example.com&quot; def welcome_email @user = params[:user] @url = &quot;http://example.com/login&quot; mail(to: @user.email, subject: &quot;Welcome to My Awesome Site&quot;, template_path: &quot;notifications&quot;, template_name: &quot;hello&quot;) end end ">Copy</button> </div> <p>The above configures the <code>mail</code> method to look for a template with the name <code>hello</code> in the <code>app/views/notifications</code> directory. You can also specify an array of paths for <code>template_path</code>, and they will be searched in order.</p><p>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:</p><div class="interstitial code"> <pre><code class="highlight ruby"><span class="k">class</span> <span class="nc">UserMailer</span> <span class="o">&lt;</span> <span class="no">ApplicationMailer</span> <span class="n">default</span> <span class="ss">from: </span><span class="s2">"notifications@example.com"</span> <span class="k">def</span> <span class="nf">welcome_email</span> <span class="vi">@user</span> <span class="o">=</span> <span class="n">params</span><span class="p">[</span><span class="ss">:user</span><span class="p">]</span> <span class="vi">@url</span> <span class="o">=</span> <span class="s2">"http://example.com/login"</span> <span class="n">mail</span><span class="p">(</span><span class="ss">to: </span><span class="vi">@user</span><span class="p">.</span><span class="nf">email</span><span class="p">,</span> <span class="ss">subject: </span><span class="s2">"Welcome to My Awesome Site"</span><span class="p">)</span> <span class="k">do</span> <span class="o">|</span><span class="nb">format</span><span class="o">|</span> <span class="nb">format</span><span class="p">.</span><span class="nf">html</span> <span class="p">{</span> <span class="n">render</span> <span class="s2">"another_template"</span> <span class="p">}</span> <span class="nb">format</span><span class="p">.</span><span class="nf">text</span> <span class="p">{</span> <span class="n">render</span> <span class="ss">plain: </span><span class="s2">"hello"</span> <span class="p">}</span> <span class="k">end</span> <span class="k">end</span> <span class="k">end</span> </code></pre> <button class="clipboard-button" data-clipboard-text="class UserMailer < ApplicationMailer default from: &quot;notifications@example.com&quot; def welcome_email @user = params[:user] @url = &quot;http://example.com/login&quot; mail(to: @user.email, subject: &quot;Welcome to My Awesome Site&quot;) do |format| format.html { render &quot;another_template&quot; } format.text { render plain: &quot;hello&quot; } end end end ">Copy</button> </div> <p>This will render the template <code>another_template.html.erb</code> for the HTML part and "hello" for the text part. The <a href="https://api.rubyonrails.org/v8.0.1/classes/ActionController/Rendering.html#method-i-render">render</a> method is the same one used inside of Action Controller, so you can use all the same options, such as <code>:plain</code>, <code>:inline</code>, etc.</p><p>Lastly, if you need to render a template located outside of the default <code>app/views/mailer_name/</code> directory, you can apply the <a href="https://api.rubyonrails.org/v8.0.1/classes/ActionView/ViewPaths/ClassMethods.html#method-i-prepend_view_path"><code>prepend_view_path</code></a>, like so:</p><div class="interstitial code"> <pre><code class="highlight ruby"><span class="k">class</span> <span class="nc">UserMailer</span> <span class="o">&lt;</span> <span class="no">ApplicationMailer</span> <span class="n">prepend_view_path</span> <span class="s2">"custom/path/to/mailer/view"</span> <span class="c1"># This will try to load "custom/path/to/mailer/view/welcome_email" template</span> <span class="k">def</span> <span class="nf">welcome_email</span> <span class="c1"># ...</span> <span class="k">end</span> <span class="k">end</span> </code></pre> <button class="clipboard-button" data-clipboard-text="class UserMailer < ApplicationMailer prepend_view_path &quot;custom/path/to/mailer/view&quot; # This will try to load &quot;custom/path/to/mailer/view/welcome_email&quot; template def welcome_email # ... end end ">Copy</button> </div> <p>There is also an <a href="https://api.rubyonrails.org/v8.0.1/classes/ActionView/ViewPaths/ClassMethods.html#method-i-append_view_path"><code>append_view_path</code></a> method.</p><h3 id="generating-urls-in-action-mailer-views"><a class="anchorlink" href="#generating-urls-in-action-mailer-views" data-turbo="false"><span>4.2</span> Generating URLs in Action Mailer Views</a></h3><p>In order to add URLs to your mailer, you need set the <code>host</code> value to your application's domain first. This is because, unlike controllers, the mailer instance doesn't have any context about the incoming request.</p><p>You can configure the default <code>host</code> across the application in <code>config/application.rb</code>:</p><div class="interstitial code"> <pre><code class="highlight ruby"><span class="n">config</span><span class="p">.</span><span class="nf">action_mailer</span><span class="p">.</span><span class="nf">default_url_options</span> <span class="o">=</span> <span class="p">{</span> <span class="ss">host: </span><span class="s2">"example.com"</span> <span class="p">}</span> </code></pre> <button class="clipboard-button" data-clipboard-text="config.action_mailer.default_url_options = { host: &quot;example.com&quot; } ">Copy</button> </div> <p>Once the <code>host</code> is configured, it is recommended that email views use the <code>*_url</code> with the full URL, and not the <code>*_path</code> helpers with relative URL. Since email clients do not have web request context, <code>*_path</code> helpers have no base URL to form complete web addresses.</p><p>For example, instead of:</p><div class="interstitial code"> <pre><code class="highlight erb"><span class="cp">&lt;%=</span> <span class="n">link_to</span> <span class="s1">'welcome'</span><span class="p">,</span> <span class="n">welcome_path</span> <span class="cp">%&gt;</span> </code></pre> <button class="clipboard-button" data-clipboard-text="<%= link_to 'welcome', welcome_path %> ">Copy</button> </div> <p>Use:</p><div class="interstitial code"> <pre><code class="highlight erb"><span class="cp">&lt;%=</span> <span class="n">link_to</span> <span class="s1">'welcome'</span><span class="p">,</span> <span class="n">welcome_url</span> <span class="cp">%&gt;</span> </code></pre> <button class="clipboard-button" data-clipboard-text="<%= link_to 'welcome', welcome_url %> ">Copy</button> </div> <p>By using the full URL, your links will work correctly in your emails.</p><h4 id="generating-urls-with-url-for"><a class="anchorlink" href="#generating-urls-with-url-for" data-turbo="false"><span>4.2.1</span> Generating URLs with <code>url_for</code></a></h4><p>The <a href="https://api.rubyonrails.org/v8.0.1/classes/ActionView/RoutingUrlFor.html#method-i-url_for"><code>url_for</code></a> helper generates a full URL, by default, in templates.</p><p>If you haven't configured the <code>:host</code> option globally, you'll need to pass it to <code>url_for</code>.</p><div class="interstitial code"> <pre><code class="highlight erb"><span class="cp">&lt;%=</span> <span class="n">url_for</span><span class="p">(</span><span class="ss">host: </span><span class="s1">'example.com'</span><span class="p">,</span> <span class="ss">controller: </span><span class="s1">'welcome'</span><span class="p">,</span> <span class="ss">action: </span><span class="s1">'greeting'</span><span class="p">)</span> <span class="cp">%&gt;</span> </code></pre> <button class="clipboard-button" data-clipboard-text="<%= url_for(host: 'example.com', controller: 'welcome', action: 'greeting') %> ">Copy</button> </div> <h4 id="generating-urls-with-named-routes"><a class="anchorlink" href="#generating-urls-with-named-routes" data-turbo="false"><span>4.2.2</span> Generating URLs with Named Routes</a></h4><p>Similar to other URLs, you need to use the <code>*_url</code> variant of named route helpers in emails as well.</p><p>You either configure the <code>:host</code> option globally or make sure to pass it to the URL helper:</p><div class="interstitial code"> <pre><code class="highlight erb"><span class="cp">&lt;%=</span> <span class="n">user_url</span><span class="p">(</span><span class="vi">@user</span><span class="p">,</span> <span class="ss">host: </span><span class="s1">'example.com'</span><span class="p">)</span> <span class="cp">%&gt;</span> </code></pre> <button class="clipboard-button" data-clipboard-text="<%= user_url(@user, host: 'example.com') %> ">Copy</button> </div> <h3 id="adding-images-in-action-mailer-views"><a class="anchorlink" href="#adding-images-in-action-mailer-views" data-turbo="false"><span>4.3</span> Adding Images in Action Mailer Views</a></h3><p>In order to use the <code>image_tag</code> helper in emails, you need to specify the <code>:asset_host</code> parameter. This is because a mailer instance doesn't have any context about the incoming request.</p><p>Usually the <code>:asset_host</code> is consistent across the application, so you can configure it globally in <code>config/application.rb</code>:</p><div class="interstitial code"> <pre><code class="highlight ruby"><span class="n">config</span><span class="p">.</span><span class="nf">action_mailer</span><span class="p">.</span><span class="nf">asset_host</span> <span class="o">=</span> <span class="s2">"http://example.com"</span> </code></pre> <button class="clipboard-button" data-clipboard-text="config.action_mailer.asset_host = &quot;http://example.com&quot; ">Copy</button> </div> <div class="interstitial note"><p>Because we can't infer the protocol from the request, you'll need to specify a protocol such as <code>http://</code> or <code>https://</code> in the <code>:asset_host</code> config.</p></div><p>Now you can display an image inside your email.</p><div class="interstitial code"> <pre><code class="highlight erb"><span class="cp">&lt;%=</span> <span class="n">image_tag</span> <span class="s1">'image.jpg'</span> <span class="cp">%&gt;</span> </code></pre> <button class="clipboard-button" data-clipboard-text="<%= image_tag 'image.jpg' %> ">Copy</button> </div> <h3 id="caching-mailer-view"><a class="anchorlink" href="#caching-mailer-view" data-turbo="false"><span>4.4</span> Caching Mailer View</a></h3><p>You can perform fragment caching in mailer views, similar to application views, using the <a href="https://api.rubyonrails.org/v8.0.1/classes/ActionView/Helpers/CacheHelper.html#method-i-cache"><code>cache</code></a> method.</p><div class="interstitial code"> <pre><code class="highlight erb"><span class="cp">&lt;%</span> <span class="n">cache</span> <span class="k">do</span> <span class="cp">%&gt;</span> <span class="cp">&lt;%=</span> <span class="vi">@company</span><span class="p">.</span><span class="nf">name</span> <span class="cp">%&gt;</span> <span class="cp">&lt;%</span> <span class="k">end</span> <span class="cp">%&gt;</span> </code></pre> <button class="clipboard-button" data-clipboard-text="<% cache do %> <%= @company.name %> <% end %> ">Copy</button> </div> <p>And to use this feature, you need to enable it in your application's <code>config/environments/*.rb</code> file:</p><div class="interstitial code"> <pre><code class="highlight ruby"><span class="n">config</span><span class="p">.</span><span class="nf">action_mailer</span><span class="p">.</span><span class="nf">perform_caching</span> <span class="o">=</span> <span class="kp">true</span> </code></pre> <button class="clipboard-button" data-clipboard-text="config.action_mailer.perform_caching = true ">Copy</button> </div> <p>Fragment caching is also supported in multipart emails. Read more about caching in the <a href="caching_with_rails.html">Rails caching guide</a>.</p><h3 id="action-mailer-layouts"><a class="anchorlink" href="#action-mailer-layouts" data-turbo="false"><span>4.5</span> Action Mailer Layouts</a></h3><p>Just like controller layouts, you can also have mailer layouts. Mailer layouts are located in <code>app/views/layouts</code>. Here is the default layout:</p><div class="interstitial code"> <pre><code class="highlight html"># app/views/layouts/mailer.html.erb <span class="cp">&lt;!DOCTYPE html&gt;</span> <span class="nt">&lt;html&gt;</span> <span class="nt">&lt;head&gt;</span> <span class="nt">&lt;meta</span> <span class="na">http-equiv=</span><span class="s">"Content-Type"</span> <span class="na">content=</span><span class="s">"text/html; charset=utf-8"</span><span class="nt">&gt;</span> <span class="nt">&lt;style&gt;</span> <span class="c">/* Email styles need to be inline */</span> <span class="nt">&lt;/style&gt;</span> <span class="nt">&lt;/head&gt;</span> <span class="nt">&lt;body&gt;</span> <span class="nt">&lt;</span><span class="err">%=</span> <span class="na">yield</span> <span class="err">%</span><span class="nt">&gt;</span> <span class="nt">&lt;/body&gt;</span> <span class="nt">&lt;/html&gt;</span> </code></pre> <button class="clipboard-button" data-clipboard-text="# app/views/layouts/mailer.html.erb <!DOCTYPE html> <html> <head> <meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=utf-8&quot;> <style> /* Email styles need to be inline */ </style> </head> <body> <%= yield %> </body> </html> ">Copy</button> </div> <p>The above layout is in a file <code>mailer.html.erb</code>. The default layout name is specified in the <code>ApplicationMailer</code>, as we saw earlier with the line <code>layout "mailer"</code> in the <a href="#generate-the-mailer">Generate Mailer</a> section. Similar to controller layouts, you use <code>yield</code> to render the mailer view inside the layout.</p><p>To use a different layout for a given mailer, call <a href="https://api.rubyonrails.org/v8.0.1/classes/ActionView/Layouts/ClassMethods.html#method-i-layout"><code>layout</code></a>:</p><div class="interstitial code"> <pre><code class="highlight ruby"><span class="k">class</span> <span class="nc">UserMailer</span> <span class="o">&lt;</span> <span class="no">ApplicationMailer</span> <span class="n">layout</span> <span class="s2">"awesome"</span> <span class="c1"># Use awesome.(html|text).erb as the layout</span> <span class="k">end</span> </code></pre> <button class="clipboard-button" data-clipboard-text="class UserMailer < ApplicationMailer layout &quot;awesome&quot; # Use awesome.(html|text).erb as the layout end ">Copy</button> </div> <p>To use a specific layout for a given email, you can pass in a <code>layout: 'layout_name'</code> option to the render call inside the format block:</p><div class="interstitial code"> <pre><code class="highlight ruby"><span class="k">class</span> <span class="nc">UserMailer</span> <span class="o">&lt;</span> <span class="no">ApplicationMailer</span> <span class="k">def</span> <span class="nf">welcome_email</span> <span class="n">mail</span><span class="p">(</span><span class="ss">to: </span><span class="n">params</span><span class="p">[</span><span class="ss">:user</span><span class="p">].</span><span class="nf">email</span><span class="p">)</span> <span class="k">do</span> <span class="o">|</span><span class="nb">format</span><span class="o">|</span> <span class="nb">format</span><span class="p">.</span><span class="nf">html</span> <span class="p">{</span> <span class="n">render</span> <span class="ss">layout: </span><span class="s2">"my_layout"</span> <span class="p">}</span> <span class="nb">format</span><span class="p">.</span><span class="nf">text</span> <span class="k">end</span> <span class="k">end</span> <span class="k">end</span> </code></pre> <button class="clipboard-button" data-clipboard-text="class UserMailer < ApplicationMailer def welcome_email mail(to: params[:user].email) do |format| format.html { render layout: &quot;my_layout&quot; } format.text end end end ">Copy</button> </div> <p>The above will render the HTML part using the <code>my_layout.html.erb</code> file and the text part with the usual <code>user_mailer.text.erb</code> file.</p><h2 id="sending-email"><a class="anchorlink" href="#sending-email" data-turbo="false"><span>5</span> Sending Email</a></h2><h3 id="sending-email-to-multiple-recipients"><a class="anchorlink" href="#sending-email-to-multiple-recipients" data-turbo="false"><span>5.1</span> Sending Email to Multiple Recipients</a></h3><p>It is possible to send an email to more than one recipient by setting the <code>:to</code> 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.</p><p>For example, to inform all admins of a new registration:</p><div class="interstitial code"> <pre><code class="highlight ruby"><span class="k">class</span> <span class="nc">AdminMailer</span> <span class="o">&lt;</span> <span class="no">ApplicationMailer</span> <span class="n">default</span> <span class="ss">to: </span><span class="o">-&gt;</span> <span class="p">{</span> <span class="no">Admin</span><span class="p">.</span><span class="nf">pluck</span><span class="p">(</span><span class="ss">:email</span><span class="p">)</span> <span class="p">},</span> <span class="ss">from: </span><span class="s2">"notification@example.com"</span> <span class="k">def</span> <span class="nf">new_registration</span><span class="p">(</span><span class="n">user</span><span class="p">)</span> <span class="vi">@user</span> <span class="o">=</span> <span class="n">user</span> <span class="n">mail</span><span class="p">(</span><span class="ss">subject: </span><span class="s2">"New User Signup: </span><span class="si">#{</span><span class="vi">@user</span><span class="p">.</span><span class="nf">email</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span> <span class="k">end</span> <span class="k">end</span> </code></pre> <button class="clipboard-button" data-clipboard-text="class AdminMailer < ApplicationMailer default to: -> { Admin.pluck(:email) }, from: &quot;notification@example.com&quot; def new_registration(user) @user = user mail(subject: &quot;New User Signup: #{@user.email}&quot;) end end ">Copy</button> </div> <p>The same format can be used to add multiple carbon copy (cc) and blind carbon copy (bcc) recipients, by setting the <code>:cc</code> and <code>:bcc</code> keys respectively (similarly to the <code>:to</code> field).</p><h3 id="sending-email-with-name"><a class="anchorlink" href="#sending-email-with-name" data-turbo="false"><span>5.2</span> Sending Email with Name</a></h3><p>It's possible to show the name, in addition to the email address, of the person who receives the email or sends the email.</p><p>To show the name of the person when they receive the email, you can use <a href="https://api.rubyonrails.org/v8.0.1/classes/ActionMailer/Base.html#method-i-email_address_with_name"><code>email_address_with_name</code></a> method in <code>to:</code>:</p><div class="interstitial code"> <pre><code class="highlight ruby"><span class="k">def</span> <span class="nf">welcome_email</span> <span class="vi">@user</span> <span class="o">=</span> <span class="n">params</span><span class="p">[</span><span class="ss">:user</span><span class="p">]</span> <span class="n">mail</span><span class="p">(</span> <span class="ss">to: </span><span class="n">email_address_with_name</span><span class="p">(</span><span class="vi">@user</span><span class="p">.</span><span class="nf">email</span><span class="p">,</span> <span class="vi">@user</span><span class="p">.</span><span class="nf">name</span><span class="p">),</span> <span class="ss">subject: </span><span class="s2">"Welcome to My Awesome Site"</span> <span class="p">)</span> <span class="k">end</span> </code></pre> <button class="clipboard-button" data-clipboard-text="def welcome_email @user = params[:user] mail( to: email_address_with_name(@user.email, @user.name), subject: &quot;Welcome to My Awesome Site&quot; ) end ">Copy</button> </div> <p>The same method in <code>from:</code> works to display the name of the sender:</p><div class="interstitial code"> <pre><code class="highlight ruby"><span class="k">class</span> <span class="nc">UserMailer</span> <span class="o">&lt;</span> <span class="no">ApplicationMailer</span> <span class="n">default</span> <span class="ss">from: </span><span class="n">email_address_with_name</span><span class="p">(</span><span class="s2">"notification@example.com"</span><span class="p">,</span> <span class="s2">"Example Company Notifications"</span><span class="p">)</span> <span class="k">end</span> </code></pre> <button class="clipboard-button" data-clipboard-text="class UserMailer < ApplicationMailer default from: email_address_with_name(&quot;notification@example.com&quot;, &quot;Example Company Notifications&quot;) end ">Copy</button> </div> <p>If the name is blank (<code>nil</code> or empty string), it returns the email address.</p><h3 id="sending-email-with-subject-translation"><a class="anchorlink" href="#sending-email-with-subject-translation" data-turbo="false"><span>5.3</span> Sending Email with Subject Translation</a></h3><p>If you don't pass a subject to the mail method, Action Mailer will try to find it in your translations. See the <a href="i18n.html#translations-for-action-mailer-e-mail-subjects">Internationalization Guide</a> for more.</p><h3 id="sending-emails-without-template-rendering"><a class="anchorlink" href="#sending-emails-without-template-rendering" data-turbo="false"><span>5.4</span> Sending Emails without Template Rendering</a></h3><p>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 <code>:body</code> option. Remember to set the <code>:content_type</code> option, such as setting it to <code>text/html</code> below. Rails will default to <code>text/plain</code> as the content type.</p><div class="interstitial code"> <pre><code class="highlight ruby"><span class="k">class</span> <span class="nc">UserMailer</span> <span class="o">&lt;</span> <span class="no">ApplicationMailer</span> <span class="k">def</span> <span class="nf">welcome_email</span> <span class="n">mail</span><span class="p">(</span><span class="ss">to: </span><span class="n">params</span><span class="p">[</span><span class="ss">:user</span><span class="p">].</span><span class="nf">email</span><span class="p">,</span> <span class="ss">body: </span><span class="n">params</span><span class="p">[</span><span class="ss">:email_body</span><span class="p">],</span> <span class="ss">content_type: </span><span class="s2">"text/html"</span><span class="p">,</span> <span class="ss">subject: </span><span class="s2">"Already rendered!"</span><span class="p">)</span> <span class="k">end</span> <span class="k">end</span> </code></pre> <button class="clipboard-button" data-clipboard-text="class UserMailer < ApplicationMailer def welcome_email mail(to: params[:user].email, body: params[:email_body], content_type: &quot;text/html&quot;, subject: &quot;Already rendered!&quot;) end end ">Copy</button> </div> <h3 id="sending-emails-with-dynamic-delivery-options"><a class="anchorlink" href="#sending-emails-with-dynamic-delivery-options" data-turbo="false"><span>5.5</span> Sending Emails with Dynamic Delivery Options</a></h3><p>If you wish to override the default delivery <a href="#action-mailer-configuration">configuration</a> (e.g. SMTP credentials) while delivering emails, you can do this using <code>delivery_method_options</code> in the mailer action.</p><div class="interstitial code"> <pre><code class="highlight ruby"><span class="k">class</span> <span class="nc">UserMailer</span> <span class="o">&lt;</span> <span class="no">ApplicationMailer</span> <span class="k">def</span> <span class="nf">welcome_email</span> <span class="vi">@user</span> <span class="o">=</span> <span class="n">params</span><span class="p">[</span><span class="ss">:user</span><span class="p">]</span> <span class="vi">@url</span> <span class="o">=</span> <span class="n">user_url</span><span class="p">(</span><span class="vi">@user</span><span class="p">)</span> <span class="n">delivery_options</span> <span class="o">=</span> <span class="p">{</span> <span class="ss">user_name: </span><span class="n">params</span><span class="p">[</span><span class="ss">:company</span><span class="p">].</span><span class="nf">smtp_user</span><span class="p">,</span> <span class="ss">password: </span><span class="n">params</span><span class="p">[</span><span class="ss">:company</span><span class="p">].</span><span class="nf">smtp_password</span><span class="p">,</span> <span class="ss">address: </span><span class="n">params</span><span class="p">[</span><span class="ss">:company</span><span class="p">].</span><span class="nf">smtp_host</span> <span class="p">}</span> <span class="n">mail</span><span class="p">(</span><span class="ss">to: </span><span class="vi">@user</span><span class="p">.</span><span class="nf">email</span><span class="p">,</span> <span class="ss">subject: </span><span class="s2">"Please see the Terms and Conditions attached"</span><span class="p">,</span> <span class="ss">delivery_method_options: </span><span class="n">delivery_options</span><span class="p">)</span> <span class="k">end</span> <span class="k">end</span> </code></pre> <button class="clipboard-button" data-clipboard-text="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: &quot;Please see the Terms and Conditions attached&quot;, delivery_method_options: delivery_options) end end ">Copy</button> </div> <h2 id="action-mailer-callbacks"><a class="anchorlink" href="#action-mailer-callbacks" data-turbo="false"><span>6</span> Action Mailer Callbacks</a></h2><p>Action Mailer allows for you to specify a <a href="https://api.rubyonrails.org/v8.0.1/classes/AbstractController/Callbacks/ClassMethods.html#method-i-before_action"><code>before_action</code></a>, <a href="https://api.rubyonrails.org/v8.0.1/classes/AbstractController/Callbacks/ClassMethods.html#method-i-after_action"><code>after_action</code></a>, and <a href="https://api.rubyonrails.org/v8.0.1/classes/AbstractController/Callbacks/ClassMethods.html#method-i-around_action"><code>around_action</code></a> to configure the message, and <a href="https://api.rubyonrails.org/v8.0.1/classes/ActionMailer/Callbacks/ClassMethods.html#method-i-before_deliver"><code>before_deliver</code></a>, <a href="https://api.rubyonrails.org/v8.0.1/classes/ActionMailer/Callbacks/ClassMethods.html#method-i-after_deliver"><code>after_deliver</code></a> and <a href="https://api.rubyonrails.org/v8.0.1/classes/ActionMailer/Callbacks/ClassMethods.html#method-i-around_deliver"><code>around_deliver</code></a> to control the delivery.</p><p>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).</p><p>Here are some examples of when you may use one of these callbacks with mailers.</p><h3 id="before-action"><a class="anchorlink" href="#before-action" data-turbo="false"><span>6.1</span> <code>before_action</code></a></h3><p>You can use a <code>before_action</code> to set instance variables, populate the mail object with defaults, or insert default headers and attachments.</p><div class="interstitial code"> <pre><code class="highlight ruby"><span class="k">class</span> <span class="nc">InvitationsMailer</span> <span class="o">&lt;</span> <span class="no">ApplicationMailer</span> <span class="n">before_action</span> <span class="ss">:set_inviter_and_invitee</span> <span class="n">before_action</span> <span class="p">{</span> <span class="vi">@account</span> <span class="o">=</span> <span class="n">params</span><span class="p">[</span><span class="ss">:inviter</span><span class="p">].</span><span class="nf">account</span> <span class="p">}</span> <span class="n">default</span> <span class="ss">to: </span><span class="o">-&gt;</span> <span class="p">{</span> <span class="vi">@invitee</span><span class="p">.</span><span class="nf">email_address</span> <span class="p">},</span> <span class="ss">from: </span><span class="o">-&gt;</span> <span class="p">{</span> <span class="n">common_address</span><span class="p">(</span><span class="vi">@inviter</span><span class="p">)</span> <span class="p">},</span> <span class="ss">reply_to: </span><span class="o">-&gt;</span> <span class="p">{</span> <span class="vi">@inviter</span><span class="p">.</span><span class="nf">email_address_with_name</span> <span class="p">}</span> <span class="k">def</span> <span class="nf">account_invitation</span> <span class="n">mail</span> <span class="ss">subject: </span><span class="s2">"</span><span class="si">#{</span><span class="vi">@inviter</span><span class="p">.</span><span class="nf">name</span><span class="si">}</span><span class="s2"> invited you to their Basecamp (</span><span class="si">#{</span><span class="vi">@account</span><span class="p">.</span><span class="nf">name</span><span class="si">}</span><span class="s2">)"</span> <span class="k">end</span> <span class="k">def</span> <span class="nf">project_invitation</span> <span class="vi">@project</span> <span class="o">=</span> <span class="n">params</span><span class="p">[</span><span class="ss">:project</span><span class="p">]</span> <span class="vi">@summarizer</span> <span class="o">=</span> <span class="no">ProjectInvitationSummarizer</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="vi">@project</span><span class="p">.</span><span class="nf">bucket</span><span class="p">)</span> <span class="n">mail</span> <span class="ss">subject: </span><span class="s2">"</span><span class="si">#{</span><span class="vi">@inviter</span><span class="p">.</span><span class="nf">name</span><span class="p">.</span><span class="nf">familiar</span><span class="si">}</span><span class="s2"> added you to a project in Basecamp (</span><span class="si">#{</span><span class="vi">@account</span><span class="p">.</span><span class="nf">name</span><span class="si">}</span><span class="s2">)"</span> <span class="k">end</span> <span class="kp">private</span> <span class="k">def</span> <span class="nf">set_inviter_and_invitee</span> <span class="vi">@inviter</span> <span class="o">=</span> <span class="n">params</span><span class="p">[</span><span class="ss">:inviter</span><span class="p">]</span> <span class="vi">@invitee</span> <span class="o">=</span> <span class="n">params</span><span class="p">[</span><span class="ss">:invitee</span><span class="p">]</span> <span class="k">end</span> <span class="k">end</span> </code></pre> <button class="clipboard-button" data-clipboard-text="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: &quot;#{@inviter.name} invited you to their Basecamp (#{@account.name})&quot; end def project_invitation @project = params[:project] @summarizer = ProjectInvitationSummarizer.new(@project.bucket) mail subject: &quot;#{@inviter.name.familiar} added you to a project in Basecamp (#{@account.name})&quot; end private def set_inviter_and_invitee @inviter = params[:inviter] @invitee = params[:invitee] end end ">Copy</button> </div> <h3 id="after-action"><a class="anchorlink" href="#after-action" data-turbo="false"><span>6.2</span> <code>after_action</code></a></h3><p>You can use an <code>after_action</code> callback with a similar setup as a <code>before_action</code> but also have access to instance variables that were set in your mailer action.</p><p>You can also use an <code>after_action</code> to override delivery method settings by updating <code>mail.delivery_method.settings</code>.</p><div class="interstitial code"> <pre><code class="highlight ruby"><span class="k">class</span> <span class="nc">UserMailer</span> <span class="o">&lt;</span> <span class="no">ApplicationMailer</span> <span class="n">before_action</span> <span class="p">{</span> <span class="vi">@business</span><span class="p">,</span> <span class="vi">@user</span> <span class="o">=</span> <span class="n">params</span><span class="p">[</span><span class="ss">:business</span><span class="p">],</span> <span class="n">params</span><span class="p">[</span><span class="ss">:user</span><span class="p">]</span> <span class="p">}</span> <span class="n">after_action</span> <span class="ss">:set_delivery_options</span><span class="p">,</span> <span class="ss">:prevent_delivery_to_guests</span><span class="p">,</span> <span class="ss">:set_business_headers</span> <span class="k">def</span> <span class="nf">feedback_message</span> <span class="k">end</span> <span class="k">def</span> <span class="nf">campaign_message</span> <span class="k">end</span> <span class="kp">private</span> <span class="k">def</span> <span class="nf">set_delivery_options</span> <span class="c1"># You have access to the mail instance,</span> <span class="c1"># @business and @user instance variables here</span> <span class="k">if</span> <span class="vi">@business</span> <span class="o">&amp;&amp;</span> <span class="vi">@business</span><span class="p">.</span><span class="nf">has_smtp_settings?</span> <span class="n">mail</span><span class="p">.</span><span class="nf">delivery_method</span><span class="p">.</span><span class="nf">settings</span><span class="p">.</span><span class="nf">merge!</span><span class="p">(</span><span class="vi">@business</span><span class="p">.</span><span class="nf">smtp_settings</span><span class="p">)</span> <span class="k">end</span> <span class="k">end</span> <span class="k">def</span> <span class="nf">prevent_delivery_to_guests</span> <span class="k">if</span> <span class="vi">@user</span> <span class="o">&amp;&amp;</span> <span class="vi">@user</span><span class="p">.</span><span class="nf">guest?</span> <span class="n">mail</span><span class="p">.</span><span class="nf">perform_deliveries</span> <span class="o">=</span> <span class="kp">false</span> <span class="k">end</span> <span class="k">end</span> <span class="k">def</span> <span class="nf">set_business_headers</span> <span class="k">if</span> <span class="vi">@business</span> <span class="n">headers</span><span class="p">[</span><span class="s2">"X-SMTPAPI-CATEGORY"</span><span class="p">]</span> <span class="o">=</span> <span class="vi">@business</span><span class="p">.</span><span class="nf">code</span> <span class="k">end</span> <span class="k">end</span> <span class="k">end</span> </code></pre> <button class="clipboard-button" data-clipboard-text="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 &amp;&amp; @business.has_smtp_settings? mail.delivery_method.settings.merge!(@business.smtp_settings) end end def prevent_delivery_to_guests if @user &amp;&amp; @user.guest? mail.perform_deliveries = false end end def set_business_headers if @business headers[&quot;X-SMTPAPI-CATEGORY&quot;] = @business.code end end end ">Copy</button> </div> <h3 id="after-deliver"><a class="anchorlink" href="#after-deliver" data-turbo="false"><span>6.3</span> <code>after_deliver</code></a></h3><p>You could use an <code>after_deliver</code> to record the delivery of the message. It also allows observer/interceptor-like behaviors, but with access to the full mailer context.</p><div class="interstitial code"> <pre><code class="highlight ruby"><span class="k">class</span> <span class="nc">UserMailer</span> <span class="o">&lt;</span> <span class="no">ApplicationMailer</span> <span class="n">after_deliver</span> <span class="ss">:mark_delivered</span> <span class="n">before_deliver</span> <span class="ss">:sandbox_staging</span> <span class="n">after_deliver</span> <span class="ss">:observe_delivery</span> <span class="k">def</span> <span class="nf">feedback_message</span> <span class="vi">@feedback</span> <span class="o">=</span> <span class="n">params</span><span class="p">[</span><span class="ss">:feedback</span><span class="p">]</span> <span class="k">end</span> <span class="kp">private</span> <span class="k">def</span> <span class="nf">mark_delivered</span> <span class="n">params</span><span class="p">[</span><span class="ss">:feedback</span><span class="p">].</span><span class="nf">touch</span><span class="p">(</span><span class="ss">:delivered_at</span><span class="p">)</span> <span class="k">end</span> <span class="c1"># An Interceptor alternative.</span> <span class="k">def</span> <span class="nf">sandbox_staging</span> <span class="n">message</span><span class="p">.</span><span class="nf">to</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"sandbox@example.com"</span><span class="p">]</span> <span class="k">if</span> <span class="no">Rails</span><span class="p">.</span><span class="nf">env</span><span class="p">.</span><span class="nf">staging?</span> <span class="k">end</span> <span class="c1"># A callback has more context than the comparable Observer example.</span> <span class="k">def</span> <span class="nf">observe_delivery</span> <span class="no">EmailDelivery</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="n">message</span><span class="p">,</span> <span class="nb">self</span><span class="p">.</span><span class="nf">class</span><span class="p">,</span> <span class="n">action_name</span><span class="p">,</span> <span class="n">params</span><span class="p">)</span> <span class="k">end</span> <span class="k">end</span> </code></pre> <button class="clipboard-button" data-clipboard-text="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 = [&quot;sandbox@example.com&quot;] 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 ">Copy</button> </div> <p>Mailer callbacks abort further processing if <code>body</code> is set to a non-nil value. <code>before_deliver</code> can abort with <code>throw :abort</code>.</p><h2 id="action-mailer-view-helpers"><a class="anchorlink" href="#action-mailer-view-helpers" data-turbo="false"><span>7</span> Action Mailer View Helpers</a></h2><p>Action Mailer views have access to most of the same helpers as regular views.</p><p>There are also some Action Mailer-specific helper methods available in <a href="https://api.rubyonrails.org/v8.0.1/classes/ActionMailer/MailHelper.html"><code>ActionMailer::MailHelper</code></a>. For example, these allow accessing the mailer instance from your view with <a href="https://api.rubyonrails.org/v8.0.1/classes/ActionMailer/MailHelper.html#method-i-mailer"><code>mailer</code></a>, and accessing the message as <a href="https://api.rubyonrails.org/v8.0.1/classes/ActionMailer/MailHelper.html#method-i-message"><code>message</code></a>:</p><div class="interstitial code"> <pre><code class="highlight erb"><span class="cp">&lt;%=</span> <span class="n">stylesheet_link_tag</span> <span class="n">mailer</span><span class="p">.</span><span class="nf">name</span><span class="p">.</span><span class="nf">underscore</span> <span class="cp">%&gt;</span> <span class="nt">&lt;h1&gt;</span><span class="cp">&lt;%=</span> <span class="n">message</span><span class="p">.</span><span class="nf">subject</span> <span class="cp">%&gt;</span><span class="nt">&lt;/h1&gt;</span> </code></pre> <button class="clipboard-button" data-clipboard-text="<%= stylesheet_link_tag mailer.name.underscore %> <h1><%= message.subject %></h1> ">Copy</button> </div> <h2 id="action-mailer-configuration"><a class="anchorlink" href="#action-mailer-configuration" data-turbo="false"><span>8</span> Action Mailer Configuration</a></h2><p>This section shows some example configurations for Action Mailer.</p><p>For more details on the various configuration options, see the <a href="configuring.html#configuring-action-mailer">Configuring Rails Applications</a> guide. You can specify configuration options in environment specific files such as production.rb.</p><h3 id="example-action-mailer-configuration"><a class="anchorlink" href="#example-action-mailer-configuration" data-turbo="false"><span>8.1</span> Example Action Mailer Configuration</a></h3><p>Here is an example using the <code>:sendmail</code> delivery method, added to a <code>config/environments/$RAILS_ENV.rb</code> file:</p><div class="interstitial code"> <pre><code class="highlight ruby"><span class="n">config</span><span class="p">.</span><span class="nf">action_mailer</span><span class="p">.</span><span class="nf">delivery_method</span> <span class="o">=</span> <span class="ss">:sendmail</span> <span class="c1"># Defaults to:</span> <span class="c1"># config.action_mailer.sendmail_settings = {</span> <span class="c1"># location: '/usr/sbin/sendmail',</span> <span class="c1"># arguments: %w[ -i ]</span> <span class="c1"># }</span> <span class="n">config</span><span class="p">.</span><span class="nf">action_mailer</span><span class="p">.</span><span class="nf">perform_deliveries</span> <span class="o">=</span> <span class="kp">true</span> <span class="n">config</span><span class="p">.</span><span class="nf">action_mailer</span><span class="p">.</span><span class="nf">raise_delivery_errors</span> <span class="o">=</span> <span class="kp">true</span> <span class="n">config</span><span class="p">.</span><span class="nf">action_mailer</span><span class="p">.</span><span class="nf">default_options</span> <span class="o">=</span> <span class="p">{</span> <span class="ss">from: </span><span class="s2">"no-reply@example.com"</span> <span class="p">}</span> </code></pre> <button class="clipboard-button" data-clipboard-text="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: &quot;no-reply@example.com&quot; } ">Copy</button> </div> <h3 id="action-mailer-configuration-for-gmail"><a class="anchorlink" href="#action-mailer-configuration-for-gmail" data-turbo="false"><span>8.2</span> Action Mailer Configuration for Gmail</a></h3><p>Add this to your <code>config/environments/$RAILS_ENV.rb</code> file to send via Gmail:</p><div class="interstitial code"> <pre><code class="highlight ruby"><span class="n">config</span><span class="p">.</span><span class="nf">action_mailer</span><span class="p">.</span><span class="nf">delivery_method</span> <span class="o">=</span> <span class="ss">:smtp</span> <span class="n">config</span><span class="p">.</span><span class="nf">action_mailer</span><span class="p">.</span><span class="nf">smtp_settings</span> <span class="o">=</span> <span class="p">{</span> <span class="ss">address: </span><span class="s2">"smtp.gmail.com"</span><span class="p">,</span> <span class="ss">port: </span><span class="mi">587</span><span class="p">,</span> <span class="ss">domain: </span><span class="s2">"example.com"</span><span class="p">,</span> <span class="ss">user_name: </span><span class="no">Rails</span><span class="p">.</span><span class="nf">application</span><span class="p">.</span><span class="nf">credentials</span><span class="p">.</span><span class="nf">dig</span><span class="p">(</span><span class="ss">:smtp</span><span class="p">,</span> <span class="ss">:user_name</span><span class="p">),</span> <span class="ss">password: </span><span class="no">Rails</span><span class="p">.</span><span class="nf">application</span><span class="p">.</span><span class="nf">credentials</span><span class="p">.</span><span class="nf">dig</span><span class="p">(</span><span class="ss">:smtp</span><span class="p">,</span> <span class="ss">:password</span><span class="p">),</span> <span class="ss">authentication: </span><span class="s2">"plain"</span><span class="p">,</span> <span class="ss">enable_starttls: </span><span class="kp">true</span><span class="p">,</span> <span class="ss">open_timeout: </span><span class="mi">5</span><span class="p">,</span> <span class="ss">read_timeout: </span><span class="mi">5</span> <span class="p">}</span> </code></pre> <button class="clipboard-button" data-clipboard-text="config.action_mailer.delivery_method = :smtp config.action_mailer.smtp_settings = { address: &quot;smtp.gmail.com&quot;, port: 587, domain: &quot;example.com&quot;, user_name: Rails.application.credentials.dig(:smtp, :user_name), password: Rails.application.credentials.dig(:smtp, :password), authentication: &quot;plain&quot;, enable_starttls: true, open_timeout: 5, read_timeout: 5 } ">Copy</button> </div> <div class="interstitial note"><p>Google <a href="https://support.google.com/accounts/answer/6010255">blocks sign-ins</a> from apps it deems less secure. You can <a href="https://www.google.com/settings/security/lesssecureapps">change your Gmail settings</a> to allow the attempts. If your Gmail account has 2-factor authentication enabled, then you will need to set an <a href="https://myaccount.google.com/apppasswords">app password</a> and use that instead of your regular password.</p></div><h2 id="previewing-and-testing-mailers"><a class="anchorlink" href="#previewing-and-testing-mailers" data-turbo="false"><span>9</span> Previewing and Testing Mailers</a></h2><p>You can find detailed instructions on how to test your mailers in the <a href="testing.html#testing-your-mailers">testing guide</a>.</p><h3 id="previewing-emails"><a class="anchorlink" href="#previewing-emails" data-turbo="false"><span>9.1</span> Previewing Emails</a></h3><p>You can preview rendered email templates visually by visiting a special Action Mailer preview URL. To set up a preview for <code>UserMailer</code>, create a class named <code>UserMailerPreview</code> in the <code>test/mailers/previews/</code> directory. To see the preview of <code>welcome_email</code> from <code>UserMailer</code>, implement a method that has the same name in <code>UserMailerPreview</code> and call <code>UserMailer.welcome_email</code>:</p><div class="interstitial code"> <pre><code class="highlight ruby"><span class="k">class</span> <span class="nc">UserMailerPreview</span> <span class="o">&lt;</span> <span class="no">ActionMailer</span><span class="o">::</span><span class="no">Preview</span> <span class="k">def</span> <span class="nf">welcome_email</span> <span class="no">UserMailer</span><span class="p">.</span><span class="nf">with</span><span class="p">(</span><span class="ss">user: </span><span class="no">User</span><span class="p">.</span><span class="nf">first</span><span class="p">).</span><span class="nf">welcome_email</span> <span class="k">end</span> <span class="k">end</span> </code></pre> <button class="clipboard-button" data-clipboard-text="class UserMailerPreview < ActionMailer::Preview def welcome_email UserMailer.with(user: User.first).welcome_email end end ">Copy</button> </div> <p>Now the preview will be available at <a href="http://localhost:3000/rails/mailers/user_mailer/welcome_email">http://localhost:3000/rails/mailers/user_mailer/welcome_email</a>.</p><p>If you change something in the mailer view at <code>app/views/user_mailer/welcome_email.html.erb</code> or the mailer itself, the preview will automatically be updated. A list of previews are also available in <a href="http://localhost:3000/rails/mailers">http://localhost:3000/rails/mailers</a>.</p><p>By default, these preview classes live in <code>test/mailers/previews</code>. This can be configured using the <code>preview_paths</code> option. For example, if you want to add <code>lib/mailer_previews</code> to it, you can configure it in <code>config/application.rb</code>:</p><div class="interstitial code"> <pre><code class="highlight ruby"><span class="n">config</span><span class="p">.</span><span class="nf">action_mailer</span><span class="p">.</span><span class="nf">preview_paths</span> <span class="o">&lt;&lt;</span> <span class="s2">"</span><span class="si">#{</span><span class="no">Rails</span><span class="p">.</span><span class="nf">root</span><span class="si">}</span><span class="s2">/lib/mailer_previews"</span> </code></pre> <button class="clipboard-button" data-clipboard-text="config.action_mailer.preview_paths << &quot;#{Rails.root}/lib/mailer_previews&quot; ">Copy</button> </div> <h3 id="rescuing-errors"><a class="anchorlink" href="#rescuing-errors" data-turbo="false"><span>9.2</span> Rescuing Errors</a></h3><p>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.</p><p>To rescue errors that occur during any part of the mailing process, use <a href="https://api.rubyonrails.org/v8.0.1/classes/ActiveSupport/Rescuable/ClassMethods.html#method-i-rescue_from">rescue_from</a>:</p><div class="interstitial code"> <pre><code class="highlight ruby"><span class="k">class</span> <span class="nc">NotifierMailer</span> <span class="o">&lt;</span> <span class="no">ApplicationMailer</span> <span class="n">rescue_from</span> <span class="no">ActiveJob</span><span class="o">::</span><span class="no">DeserializationError</span> <span class="k">do</span> <span class="c1"># ...</span> <span class="k">end</span> <span class="n">rescue_from</span> <span class="s2">"SomeThirdPartyService::ApiError"</span> <span class="k">do</span> <span class="c1"># ...</span> <span class="k">end</span> <span class="k">def</span> <span class="nf">notify</span><span class="p">(</span><span class="n">recipient</span><span class="p">)</span> <span class="n">mail</span><span class="p">(</span><span class="ss">to: </span><span class="n">recipient</span><span class="p">,</span> <span class="ss">subject: </span><span class="s2">"Notification"</span><span class="p">)</span> <span class="k">end</span> <span class="k">end</span> </code></pre> <button class="clipboard-button" data-clipboard-text="class NotifierMailer < ApplicationMailer rescue_from ActiveJob::DeserializationError do # ... end rescue_from &quot;SomeThirdPartyService::ApiError&quot; do # ... end def notify(recipient) mail(to: recipient, subject: &quot;Notification&quot;) end end ">Copy</button> </div> <h2 id="intercepting-and-observing-emails"><a class="anchorlink" href="#intercepting-and-observing-emails" data-turbo="false"><span>10</span> Intercepting and Observing Emails</a></h2><p>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.</p><h3 id="intercepting-emails"><a class="anchorlink" href="#intercepting-emails" data-turbo="false"><span>10.1</span> Intercepting Emails</a></h3><p>Interceptors allow you to make modifications to emails before they are handed off to the delivery agents. An interceptor class must implement the <code>.delivering_email(message)</code> method which will be called before the email is sent.</p><div class="interstitial code"> <pre><code class="highlight ruby"><span class="k">class</span> <span class="nc">SandboxEmailInterceptor</span> <span class="k">def</span> <span class="nc">self</span><span class="o">.</span><span class="nf">delivering_email</span><span class="p">(</span><span class="n">message</span><span class="p">)</span> <span class="n">message</span><span class="p">.</span><span class="nf">to</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"sandbox@example.com"</span><span class="p">]</span> <span class="k">end</span> <span class="k">end</span> </code></pre> <button class="clipboard-button" data-clipboard-text="class SandboxEmailInterceptor def self.delivering_email(message) message.to = [&quot;sandbox@example.com&quot;] end end ">Copy</button> </div> <p>The interceptor needs to be registered using the <code>interceptors</code> config option. You can do this in an initializer file like <code>config/initializers/mail_interceptors.rb</code>:</p><div class="interstitial code"> <pre><code class="highlight ruby"><span class="no">Rails</span><span class="p">.</span><span class="nf">application</span><span class="p">.</span><span class="nf">configure</span> <span class="k">do</span> <span class="k">if</span> <span class="no">Rails</span><span class="p">.</span><span class="nf">env</span><span class="p">.</span><span class="nf">staging?</span> <span class="n">config</span><span class="p">.</span><span class="nf">action_mailer</span><span class="p">.</span><span class="nf">interceptors</span> <span class="o">=</span> <span class="sx">%w[SandboxEmailInterceptor]</span> <span class="k">end</span> <span class="k">end</span> </code></pre> <button class="clipboard-button" data-clipboard-text="Rails.application.configure do if Rails.env.staging? config.action_mailer.interceptors = %w[SandboxEmailInterceptor] end end ">Copy</button> </div> <div class="interstitial note"><p>The example above uses a custom environment called "staging" for a production-like server but for testing purposes. You can read <a href="configuring.html#creating-rails-environments">Creating Rails Environments</a> for more information about custom Rails environments.</p></div><h3 id="observing-emails"><a class="anchorlink" href="#observing-emails" data-turbo="false"><span>10.2</span> Observing Emails</a></h3><p>Observers give you access to the email message <em>after</em> it has been sent. An observer class must implement the <code>:delivered_email(message)</code> method, which will be called after the email is sent.</p><div class="interstitial code"> <pre><code class="highlight ruby"><span class="k">class</span> <span class="nc">EmailDeliveryObserver</span> <span class="k">def</span> <span class="nc">self</span><span class="o">.</span><span class="nf">delivered_email</span><span class="p">(</span><span class="n">message</span><span class="p">)</span> <span class="no">EmailDelivery</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="n">message</span><span class="p">)</span> <span class="k">end</span> <span class="k">end</span> </code></pre> <button class="clipboard-button" data-clipboard-text="class EmailDeliveryObserver def self.delivered_email(message) EmailDelivery.log(message) end end ">Copy</button> </div> <p>Similar to interceptors, you must register observers using the <code>observers</code> config option. You can do this in an initializer file like <code>config/initializers/mail_observers.rb</code>:</p><div class="interstitial code"> <pre><code class="highlight ruby"><span class="no">Rails</span><span class="p">.</span><span class="nf">application</span><span class="p">.</span><span class="nf">configure</span> <span class="k">do</span> <span class="n">config</span><span class="p">.</span><span class="nf">action_mailer</span><span class="p">.</span><span class="nf">observers</span> <span class="o">=</span> <span class="sx">%w[EmailDeliveryObserver]</span> <span class="k">end</span> </code></pre> <button class="clipboard-button" data-clipboard-text="Rails.application.configure do config.action_mailer.observers = %w[EmailDeliveryObserver] end ">Copy</button> </div> </section> <hr> <footer aria-labelledby="heading-feedback" role="region"> <h2 id="heading-feedback">Feedback</h2> <p> You're encouraged to help improve the quality of this guide. </p> <p> Please contribute if you see any typos or factual errors. To get started, you can read our <a href="https://edgeguides.rubyonrails.org/contributing_to_ruby_on_rails.html#contributing-to-the-rails-documentation">documentation contributions</a> section. </p> <p> You may also find incomplete content or stuff that is not up to date. Please do add any missing documentation for main. Make sure to check <a href="https://edgeguides.rubyonrails.org">Edge Guides</a> first to verify if the issues are already fixed or not on the main branch. Check the <a href="ruby_on_rails_guides_guidelines.html">Ruby on Rails Guides Guidelines</a> for style and conventions. </p> <p> If for whatever reason you spot something to fix but cannot patch it yourself, please <a href="https://github.com/rails/rails/issues">open an issue</a>. </p> <p>And last but not least, any kind of discussion regarding Ruby on Rails documentation is very welcome on the <a href="https://discuss.rubyonrails.org/c/rubyonrails-docs">official Ruby on Rails Forum</a>. </p> </footer> </div> </article> </main> <hr class="hide" /> <footer id="complementary"> <div class="wrapper"> <p>This work is licensed under a <a href="https://creativecommons.org/licenses/by-sa/4.0/">Creative Commons Attribution-ShareAlike 4.0 International</a> License</p> <p>"Rails", "Ruby on Rails", and the Rails logo are trademarks of David Heinemeier Hansson. All rights reserved.</p> </div> </footer> <a href="#main-skip-link" class="back-to-top" data-turbo="false"><span class="visibly-hidden">Back to top</span></a> </body> </html>

Pages: 1 2 3 4 5 6 7 8 9 10