action mailerrb
ActionMailer RB: The Complete Playbook for Rails Email Development
Rails applications almost universally need to send emails—password resets, transactional receipts, marketing campaigns, and system alerts. ActionMailer is Rails’s built-in framework for handling these use cases, and it remains one of the most powerful yet underutilized features in the Rails ecosystem. This playbook covers everything from basic setup through production-grade architecture.
Key Takeaways
- ActionMailer classes inherit from
ApplicationMailerorMail::Messageand use dedicated view templates for each email variant. - Always delegate actual delivery to Active Job — never call
deliver_nowin request-response cycles. - Use
delivery_methodconfiguration to switch between SMTP, API-based providers (SendGrid, AWS SES, Mailgun), and test/adapters during development. - Write focused test cases with
deliver_laterverification, fixture-based assertions, and delivery counter mocks. - Leverage inline layouts, text/HTML multipart bodies, and ActionMailer preview routes for a professional workflow.
- Handle bounces, unsubscribes, and spam complaints through webhook receivers and proper list hygiene to protect sender reputation.
What Is ActionMailer?
ActionMailer is Rails’s mail delivery subsystem. It follows the same conventions as Action Controller: each mailer class contains methods that map to individual email templates, and Rails renders those templates using the familiar ERB or HAML tooling you already use in views.
Unlike a typical controller action, ActionMailer operates entirely outside the HTTP request cycle. It builds a Mail::Message object, renders templates asynchronously (when properly configured), and hands off the message to a delivery adapter. Understanding this separation is critical for writing performant, non-blocking applications.
Core Components
- Mailer Class — Inherits from
ApplicationMailer; defines email methods and default headers. - Email Templates — View files located under
app/views/{mailer_name}supporting HTML, text, and attachments. - Delivery Adapter — Configured per environment (SMTP, SendGrid, AWS SES, test, file, logger).
- Job Integration —
deliver_laterqueues emails through Active Job for background processing. - Preview Route —
/rails/mailersallows visual inspection of email templates during development.
Setting Up ActionMailer in Your Rails Application
Step 1 — Create the Mailer
rails generate mailer UserMailer welcome_password_reset
This generator creates four artifacts:
app/mailers/user_mailer.rb— The mailer classapp/views/user_mailer/— Template directorytest/mailers/user_mailer_test.rb — Test skeletontest/mailers/previews/user_mailer_preview.rb— Preview class
Step 2 — Configure the Mailer Base Class
class ApplicationMailer < ActionMailer::Base
default from: "noreply@yourapp.com"
default reply_to: "support@yourapp.com"
default template_path: "emails"
layout "email"
end
Step 3 — Set Delivery Configuration
Configure config/action_mailer in config/environments/production.rb:
config.action_mailer.delivery_method = :smtp
config.action_mailer.perform_deliveries = true
config.action_mailer.raise_delivery_errors = true
config.action_mailer.default_options = {from: "noreply@yourapp.com"}
config.action_mailer.smtp_settings = {
address: "smtp.sendgrid.net",
port: 587,
domain: "yourapp.com",
user_name: ENV["SENDGRID_USERNAME"],
password: ENV["SENDGRID_PASSWORD"],
authentication: "plain",
enable_starttls_auto: true
}
Step 4 — Enable Action Mailer Preview Routes
# config/routes.rb
Rails.application.routes.draw do
# ...
mount Rails::MailersController => "/rails/mailers"
end
Pre-Launch Checklist
- [ ] Verify
config.action_mailer.perform_deliveriesistruein production - [ ] Confirm all
ENVvariables for credentials are set in deployment - [ ] Add
config.action_mailer.default_url_optionsfor URL generation in links - [ ] Set up SPF, DKIM, and DMARC records for your sending domain
- [ ] Configure a webhook endpoint for bounce and complaint handling
- [ ] Add a staging delivery rule (e.g., deliver to a catch-all address)
- [ ] Test
deliver_nowmanually against the preview route before launch
Writing Effective Mailer Methods
Basic Mailer Method
class UserMailer < ApplicationMailer
def welcome(user)
@user = user
mail(
to: user.email,
subject: "Welcome to Acme, #{@user.first_name}",
cc: "onboarding@yourapp.com"
)
end
end
Multipart Emails
Production applications should always send both HTML and plain-text variants. Rails handles this automatically when both .html.erb and .text.erb templates exist in the same directory.
# app/views/user_mailer/welcome.html.erb
<h1>Welcome, <%= @user.first_name %>!</h1>
<p>Get started by <%= link_to "setting up your profile", signup_url(@user.signup_token) %>.</p>
# app/views/user_mailer/welcome.text.erb
Welcome, <%= @user.first_name %>!
Get started by signing up at: <%= signup_url(@user.signup_token) %>
Attachment Handling
def monthly_report(user, report)
@user = user
@report = report
attachments["report.pdf"] = File.read(report.path)
mail(
to: @user.email,
subject: "Your monthly report is ready"
)
end
Inline Images
def onboarding_email(user)
@user = user
attachments.inline["logo.png"] = File.read(Rails.root.join("app/assets/images/logo.png"))
mail(to: @user.email, subject: "Welcome aboard")
end
Then reference in the HTML template:
<%= image_tag attachments["logo.png"].url, alt: "Logo" %>
Integrating ActionMailer with Active Job
Why Use deliver_later Instead of deliver_now
Calling deliver_now inside a controller blocks the request thread until the email is sent. In production with external SMTP providers, this introduces unpredictable latency and risks timeout errors. The recommended pattern is to enqueue the mailer via deliver_later, which delegates to Active Job.
Standard Enqueue Pattern
# In a controller or service object
UserMailer.welcome(user).deliver_later
# or with explicit queue
UserMailer.welcome(user).set(queue: "email_high_priority").