Sending email is a pivotal part of most web apps. Receipts, notifications, alerts – you name it. But wrestling with the mail servers and edge cases of email can be a headache for developers. What if there was an elegant solution to tame this beast within Ruby on Rails apps?
There is! It’s called Action Mailer.
Action Mailer streamlines sending email by adapting Rails’ conventions for controllers and views into the world of email. Read on to see how Action Mailer makes sending mail a breeze.
What is Action Mailer and Why It Matters
Action Mailer is a core component of the Ruby on Rails framework that provides a simple and intuitive way to send emails within a Rails application. In a nutshell, Action Mailer allows you to generate, customize, and deliver both text and HTML emails using familiar MVC patterns.
At first glance, Action Mailer may seem like an odd man out compared to Rails’ standard MVC setup. After all, who sends emails via a web controller? But once you dive in, you’ll see that Action Mailer perfectly aligns with Rails’ philosophy of convention over configuration.
Overview
Like controllers, Action Mailer uses methods called “actions” to package up reusable logic for generating emails. These actions can render templates to build the content, working exactly like regular Rails views. The only difference is instead of rendering a webpage, they render an email body.
Action Mailer seamlessly integrates with Rails’ config, routing, and asset pipeline. This means you can preview emails right alongside your other views, and access helpers, layouts, images, stylesheets and more. Best of all, there’s no hassle setting up authentication or encryption – that all comes built-in.
Under the hood, Action Mailer is a wrapper around the Mail gem. But you typically don’t need to worry about Mail’s lower level interface, since Action Mailer provides a clean higher level API.
Use Cases
Some common use cases for Action Mailer include:
- User onboarding – Send welcome emails when a new user signs up
- Notifications – Email users when certain events occur like new comments
- Marketing campaigns – Newsletters, promotions, event reminders etc.
- System alerts – Admin notifications for errors, monitoring alerts etc.
- Order receipts – Send order confirmations and tracking info
- Password reset – Enable password resets via emailed magic links
- Document delivery – Attach invoices, receipts, reports etc.
- Customer support – Let users respond via email right from your app
Action Mailer can also receive inbound emails and funnel them into your back end for processing. This powers functionality like “reply by email” without needing a 3rd party service.
Why It Matters
Here are some key reasons Action Mailer can be a game changer for your Rails app:
- Productivity – Templating and reuse supercharges your email efforts
- Familiarity – Use what you know – Rails views, helpers, assets etc.
- Maintainability – Keep email management tidy in one codebase
- Testability – Leverage Rails’ great testing framework
- Reliability – Let Rails handle the email plumbing for you
- Flexibility – Craft text, HTML, multipart etc. with ease
- Analysis – Intercept and observe emails for debugging
- Deliverability – Built-in tools to optimize inbox delivery
The bottom line is that Action Mailer provides a lean, simple way to manage a core app requirement: sending emails. And it handles this in a uniquely Rails way that meshes beautifully with the rest of the framework.
How Action Mailer Works
Now that you know what Action Mailer is and why it matters, let’s dive into how it actually works under the hood. We’ll cover Action Mailer’s relationship to controllers and views, how to generate mailers, and the end-to-end flow for sending emails.
Relationship to Controllers and Views
Action Mailer classes inherit from ActionMailer::Base
and live in the app/mailers
folder. Each mailer contains “actions” which work similarly to controller actions: they package up reusable chunks of mailing logic.
For example, you may have a UserMailer
with actions like welcome_email
and forgot_password_email
. Each action would handle sending the relevant type of email.
Mailer actions have access to a params
hash just like controllers do, allowing you to pass arbitrary data from the calling context.
Views work the same way too. Mailer actions render templates located in app/views
to build the email body content. For example, UserMailer#welcome_email
would render:
app/views/user_mailer/welcome_email.html.erb
app/views/user_mailer/welcome_email.text.erb
These templates have access to any instance variables set in the action, just like regular views.
Overall, the fundamental MVC concepts translate directly from controllers and views to mailers and email templates.
Generating Mailers and Templates
Let’s look at how to generate a new mailer using Rails generators:
$ rails generate mailer UserMailer
This will generate:
app/mailers/user_mailer.rb
app/views/user_mailer/
folder- Tests for your mailer
To create an email action inside the mailer:
class UserMailer < ApplicationMailer
def welcome_email
mail(to: '[email protected]', subject: 'Welcome!')
end
end
And the template:
<!-- app/views/user_mailer/welcome_email.html.erb -->
<h1>Welcome!</h1>
<p>Thanks for joining!</p>
That’s enough to render and send a simple email. Next we’ll look at how sending actually works.
Sending Emails with Action Mailer
Sending emails is a three step process:
- Instantiate a new mailer object This creates an instance of your mailer class that encapsulates the email you want to send:
mailer = UserMailer.with(user: @user).welcome_email
Any data passed to .with()
becomes available as params
in your mailer action and templates.
- Call
#deliver_later
to enqueue the email Under the hood, this hands the email off to Active Job for asynchronous delivery:
mailer.deliver_later
#deliver_now
will send the email inline instead of enqueueing.
- The Active Job worker delivers the email At this point, Active Job takes over and delivers the email in the background via Action Mailer.
Now let’s walk through a simple end-to-end example…
Walkthrough – Sending Emails with Action Mailer
To see Action Mailer in action, let’s build a simple workflow for sending a welcome email when a new user signs up.
Generating a Mailer
First, we’ll generate our mailer using Rails generators:
$ rails g mailer UserMailer
This creates app/mailers/user_mailer.rb
and a view folder with layouts and preview code.
Adding an Email Action
Next, let’s add a welcome_email
action:
class UserMailer < ApplicationMailer
def welcome_email
@user = params[:user]
mail(to: @user.email, subject: "Welcome to MyAwesomeSite!")
end
end
We can access the User
model that was passed in via params
here.
Creating the Template
Then we’ll make the template app/views/user_mailer/welcome_email.html.erb
:
<h1>Welcome <%= @user.name %>!</h1>
<p>Thanks for joining!</p>
Calling the Mailer
Now we can call the mailer from a controller, like the UsersController
:
class UsersController < ApplicationController
# POST /users
def create
@user = User.create(user_params)
UserMailer.with(user: @user).welcome_email.deliver_later
redirect_to @user
end
end
This will render the templates and email the user after creating their account.
And that’s it! Within a few lines of code, we’ve set up a complete mailer to send emails from our app.
Action Mailer Configuration
Action Mailer offers flexible configuration options that are easily customized within config/environments/
.
The main settings available include:
default_options
– Default values for headers, reply_to etc. applied to all mailers and emails.smtp_settings
– Configures Action Mailer to deliver via SMTP. Allows setting address, port, user_name, password etc.sendmail_settings
– Likewise configures delivery via sendmail instead of SMTP.delivery_job
– Sets the Active Job class used for delivery. Defaults toActionMailer::MailDeliveryJob
.interceptors
– Register email interceptors that inspect emails before delivery.observers
– Register observers that get notified after emails are sent.preview_paths
– Where to mount the mail previews used in development.
For example:
“`ruby
config.action_mailer.smtp_settings = {
address: ‘smtp.sendgrid.net’,
user_name: ENV[‘SENDGRID_USERNAME’],
password: ENV[‘SENDGRID_PASSWORD’]
}
This allows easily switching between different delivery methods like SMTP, sendmail, and even testing mode.
Summing Up
The key takeaways are:
– Action Mailer integrates tightly with MVC
– Generator makes it easy to spin up new mailers
– Mailer actions work like controller actions
– Templates build email content just like views
– `#deliver_later` enqueues delivery via Active Job
– Flexible configuration options This covers the basic mechanics of how Action Mailer operates.
Next we’ll look at details of templating, testing, and best practices. Let me know if any part of this overview needs more explanation or expansion!
ruby
class MyMailer < ApplicationMailer
layout ‘awesome_layout’
Will render app/views/layouts/awesome_layout.{text,html}.erb
end
For the email body, it will render the template matching the action name – like `welcome_email.html.erb` for the `welcome_email` action. This gives you full access to partials, helpers, asset linking, and more as you build your email templates.
A few important notes:
– Any instance variables from the mailer action are available in templates
– You can inline styles using `<style>` tags rather than external CSS
– Linked assets must use absolute URLs
Inline Templates and Text Body
For ultimate flexibility, you can also directly specify text content inline:
ruby
mail(body: “Hello World”) # Defaults to text/plain
mail(body: “html”.html_safe)
Or skip templates entirely:
ruby
mail do |format|
format.text { render plain: “Render text” }
format.html { render inline: “inline” }
end
This allows rendering the text and HTML bodies directly without needing templates.
erb
<%= user_url(@user) %>
Configure `default_url_options` in `config/environments/`:
ruby
config.action_mailer.default_url_options = {
host: “example.com”
}
This lets you use the regular `_path` helpers:
erb
<%= user_path(@user) %>
With proper configuration, you can build robust email templates linking back to your application.
Adding Images and Attachments
Embedding images in emails is straightforward with Action Mailer. For images, use the `image_tag` helper as usual:
erb
<%= image_tag(“header.png”) %>
Action Mailer will automatically inline the image as an attachment. You can also manually attach files using `attachments.inline`:
ruby
attachments.inline[‘logo.png’] = File.read(‘logo.png’)
This attaches `logo.png` with a CID (Content ID) that can be referenced in templates with `cid:`:
For regular file attachments, use `attachments[]`:
ruby
attachments[‘attachment.zip’] = File.read(‘attachment.zip’)
The attachment will be included in the email with the given filename.
Previewing Emails
One of Action Mailer’s best features is previewing emails right within your app. The mailer generator creates a preview class: `test/mailers/previews/user_mailer_preview.rb` You can add methods to preview each email:
ruby
class UserMailerPreview < ActionMailer::Preview
def welcome_email
user = User.first
UserMailer.with(user: user).welcome_email
end
Now you can view the email at `/rails/mailers/user_mailer/welcome_email`. As you refine your templates, you can keep reloading to preview changes.
Testing Mailers
Action Mailer provides robust integration testing capabilities.
For example, you can test that:
– The email is delivered with `assert_emails`
– The right recipient, headers, subject etc. are set
– The body content matches what you expect Here’s an example mailer test:
ruby
class UserMailerTest < ActionMailer::TestCase
test “welcome email” do
user = users(:one)
email = UserMailer.with(user: user).welcome_email
assert_emails 1 do
email.deliver_now
end
assert_equal ['[email protected]'], email.from
assert_equal ['[email protected]'], email.to
assert_equal "Welcome!", email.subject
assert_match user.name, email.html_part.body.encoded
assert_match user.name, email.text_part.body.encoded
end
The Action Mailer testing guide has more examples.
Debugging and Troubleshooting
Here are some tips for debugging common email issues:
– Use MailView to preview the raw HTML message and headers
– Switch to a `test` mailer adapter to review `ActionMailer::Base.deliveries`
– Enable logging to diagnose delivery failures
– Use Mailtrap](https://mailtrap.io) or [Letter Opener to preview emails during development
– Add Observers to monitor email delivery With some diligent debugging, you can resolve most email quirks!
In short
Action Mailer provides powerful tools for flexible email templating and delivery. With layouts, templates, attachments, and previews, you have everything needed to craft professional emails right within Rails. Combined with rock solid testing and debugging options, Action Mailer enables building reliable and well-tested email functionality in your apps.
Best Practices for Using Action Mailer
Now that you understand how Action Mailer works, let’s go over some best practices for using it effectively. We’ll look at folder structure, naming, background delivery, error handling, and more.
Mailer Directory Structure*
The standard mailer folder structure looks like:
app/
mailers/
application_mailer.rb
order_mailer.rb
user_mailer.rb
views/
layouts/
mailer.text.erb
mailer.html.erb
user_mailer/
welcome_email.text.erb
welcome_email.html.erb
order_mailer/
receipt_email.text.erb
receipt_email.html.erb
Some guidelines:
– Put each mailer class in its own file under `app/mailers`
– Use the `application_mailer.rb` for default settings
– Mailer view templates live under `views/mailer_name/action_name`
– Layouts are in `views/layouts/mailer.(text|html).erb`
This structure keeps mailers neatly organized as the number of emails grows.
Naming Conventions
Aim for clear naming to keep things understandable:
– Mailer classes end in `Mailer` like `UserMailer`
– Action names describe the email like `welcome_email`
– Templates match the action name like `welcome_email.html.erb`
Double check default template locations if an email isn’t rendering.
Background Delivery
Use background jobs via `deliver_later` rather than `deliver_now` wherever possible:
ruby
UserMailer.welcome_email(user).deliver_later
This improves user experience by keeping response times fast.
Be sure to configure your queue adapter to actually send background emails. The default async queue drops emails in development/test modes.
Handling Errors
Email delivery sometimes fails. Make your app robust:
– Rescue and log delivery errors
– Retry transient failures with exponential backoff
– Alert developers of ongoing issues
– Gracefully handle invalid addresses
Monitoring for bounces and retries helps ensure nothing slips through the cracks.
Integrating with Frontend Forms
Frontend form submissions often trigger emails like receipts or admin notifications. Here’s one way to handle this:
1. Submit form data to a controller
For example, a contact form POSTs to a `ContactsController’:
ruby
def create
@contact = Contact.create!(contact_params)
end
2. Pass info to mailer as params
The controller can pass @contact as a param to the mailer:
ruby
ContactMailer.with(contact: @contact).contact_email.deliver_later
3. Notify the user of success
Show a flash message, redirect etc to confirm delivery:
ruby
flash[:notice] = “Message sent!”
redirect_to root_path
This keeps the frontend and email delivery separated nicely.
Other Tips Some additional best practices:
– Set global defaults in `application_mailer.rb` for DRY reuse
– Leverage mailer callbacks to apply shared logic
– Preview emails extensively during development
– Test rendering, delivery, and integration thoroughly
– Enforce authentication for admin-only emails
– Rate limit emails to avoid abuse
Following Ruby and Rails conventions will serve you well.
And don’t hesitate to open source your mailers for others!
In nutshell
While Action Mailer is flexible, following conventions helps avoid confusion down the line. Delivering asynchronously, handling errors gracefully, previewing frequently, and writing tests will all pay dividends for maintaining clean and robust mailers.
Action Mailer Alternatives and Add-Ons
One of Action Mailer’s strengths is its flexibility – it integrates seamlessly with many complementary tools. Here are some popular alternatives and addons that work great with Action Mailer.
Third Party Delivery Services
For high volume email delivery, using a dedicated service can be easier than managing your own SMTP server.
Some good options include:
- SendGrid – Optimized for deliverability with handy analytics.
- Amazon SES – Affordable and reliable delivery from AWS.
- Mailgun – Feature-packed delivery and routing.
- Postmark – Delivery API with excellent support.
You can switch to these services via configuration without changing any mailer code.
For example, to use SendGrid:
# config/environments/production.rb
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
user_name: ENV['SENDGRID_USERNAME'],
password: ENV['SENDGRID_PASSWORD'],
domain: 'yourdomain.com',
address: 'smtp.sendgrid.net',
port: 587,
authentication: :plain,
enable_starttls_auto: true
}
Be sure to enable delivery in development to preview emails from these services.
Preview Tools
Generating realistic test emails speeds up development. Some helpful tools:
- Mailtrap – Captures test emails and provides a UI to browse. Great for manual testing.
- Letter Opener – Previews emails right in the browser instead of sending.
- MailView – Displays HTML and plaintext email in the browser.
These make it fast and easy to iterate on email templates.
Migrating from Other Mailers
If you have an existing app using a different mailer, here are some tips for migrating:
- Introduce Action Mailer alongside the old mailer at first
- Convert one email template at a time, keeping the old one as a fallback
- Update calling code to deliver via Action Mailer while retaining the old path
- Only when all emails go through Action Mailer, remove the old mailer completely
This incremental approach minimizes risk and avoids breaking existing emails.
Some key areas to review when switching mailers:
- Template locations and naming conventions
- Delivery methods and adapter options
- Passing data from controllers to mailers
- Testing framework and integrations
- Monitoring and metrics collection
Leveraging Action Mailer’s similarities to Action Controller and Action View smooths the transition.
In short
While Action Mailer provides excellent default functionality, integrating third party providers and tools can take your email capabilities to the next level. And you can migrate to Action Mailer incrementally when the time is right.
Key Takeaways and Resources
Let’s wrap up with some key takeaways and helpful resources for continuing your Action Mailer journey.
Summary of Action Mailer Benefits
Here are some of the core strengths that make Action Mailer a game-changer:
- Productivity – Its MVC conventions eliminate so much boilerplate code compared to starting from scratch.
- Flexibility – Supports text, HTML, attachments, templates, and more out of the box.
- Deliverability – Built-in tools help optimize inbox delivery and avoid spam filters.
- Testability – Leverages Rails’ great testing support for mailers too.
- Maintainability – Keeping emails alongside app code in source control is tidy and sustainable.
- Reliability – Letting Rails manage sending and retries avoids many pitfalls.
- Familiarity – Uses concepts you already know like controllers, views and layouts.
- Scalability – Background delivery and services like SendGrid allow huge volumes.
The bottom line is that Action Mailer perfectly complements Rails’ philosophy while solving the unique challenges of email exceptionally well.
Additional Action Mailer Resources
Here are some references for learning more:
- Action Mailer Basics – Rails Guides deep dive
- API Docs – Complete technical reference
- Action Mailbox Basics – Inbound email handling
- Mail gem – Underlying library powering Action Mailer
- GOV.UK Email – Style guide for government emails
- Testing Rails Applications – Testing techniques
- Postmark Blog – Best practices using Postmark
- SendGrid Docs – Integrations and deliverability guide
The Rails community has a wealth of knowledge to share on effective email development patterns.
Putting Action Mailer to Work
Armed with a comprehensive overview, you now have all the building blocks to put Action Mailer to work in your apps.
A few ideas to get started:
- Add welcome and notification emails to your next project
- Build a newsletter signup feature on your website
- Implement password reset via mailed magic links
- Parse replies to customer service emails
The possibilities are endless! Action Mailer unlocks simple yet powerful email capabilities for your Rails apps.
I hope this guide illuminated how and why Action Mailer is an indispensable tool for any Rails developer. Please let me know if you have any other questions as you being working with Action Mailer.
Verdict
Action Mailer provides a robust yet simple way to add email capabilities to Ruby on Rails applications. Here are some key takeaways:
- It follows familiar MVC conventions for mailers and email templates. This aligns neatly with Rails best practices.
- The generator and naming conventions make it easy to start sending emails quickly.
- Mailer actions allow packaging common email logic into reusable methods like controllers.
- Leveraging Active Job for background delivery improves user experience.
- The templating system gives flexibility to craft text, HTML, and multipart messages.
- Built-in tools like interceptors, observers, and preview help optimize deliverability.
- Testing and debugging support ensures email reliability and correctness.
- Configuration options provide ample flexibility including SMTP, sendmail, and more.
- The approach promotes maintainable and sustainable email management alongside app code.
- Action Mailer streamlines what can often be an unwieldy aspect of application development.
Whether sending account notifications, marketing campaigns, or system alerts, Action Mailer has you covered. Its tight integration with Rails MVC patterns leads to productive development and healthy email practices.
Any quality web app needs reliable email capabilities. For Ruby on Rails developers, Action Mailer is an intuitive and robust solution for mastering this requirement with ease.
Frequently Asked Questions
Here are answers to some common questions about Action Mailer:
How do I add images and attachments?
Use image_tag
and attachments.inline
for embedding images. For attachments, use attachments[]
to specify files by name.
What delivery methods are available?
The default is SMTP but you can configure sendmail, Postmark, SendGrid, Amazon SES, or file based delivery easily.
How can I switch to a transactional email service?
Just update the SMTP settings in config/environments/production.rb
to use your service credentials and domain. No code changes needed.
What are the naming conventions?
Mailers are named XxxMailer
and located in app/mailers
. Templates match the method name like welcome_email.html.erb
.
How do I preview emails in development?
Add methods to test/mailers/previews/mailer_preview.rb
to see emails rendered live at /rails/mailer/url_path
.
How can I send emails in the background?
Use deliver_later
instead of deliver_now
to enqueue delivery via Active Job. Be sure to configure your queue adapter.
How do I handle invalid mail addresses and bounces?
Rescue Net::SMTPFatalError
and related exceptions. Log and retry transient errors. Disable bad addresses.
What debugging tools are available?
Use the MailView gem to inspect headers and HTML. Enable Rails logging for more visibility.
Can I transition gradually from another mailer?
Absolutely. Run both in parallel, migrate emails incrementally, then finally remove the old mailer.
Where can I find email templates to use?
Many open source templates are available on GitHub to start from.