Skip
Arish's avatar

45. Sending Emails with Action Mailer


Action Mailer

Action Mailer allows you to send emails from your Rails application. It works like controllers but for emails instead of web responses.

Creating a Mailer

bash
1rails generate mailer UserMailer welcome password_reset

This creates:

  • app/mailers/user_mailer.rb
  • app/views/user_mailer/welcome.html.erb
  • app/views/user_mailer/welcome.text.erb
  • app/views/user_mailer/password_reset.html.erb
  • app/views/user_mailer/password_reset.text.erb

Basic Mailer

ruby
1# app/mailers/user_mailer.rb
2class UserMailer < ApplicationMailer
3  def welcome(user)
4    @user = user
5    @login_url = login_url
6    
7    mail(
8      to: @user.email,
9      subject: "Welcome to Our App!"
10    )
11  end
12  
13  def password_reset(user)
14    @user = user
15    @reset_url = password_reset_url(token: @user.reset_token)
16    
17    mail(
18      to: @user.email,
19      subject: "Password Reset Instructions"
20    )
21  end
22end

Email Templates

HTML Template

erb
1<!-- app/views/user_mailer/welcome.html.erb -->
2<!DOCTYPE html>
3<html>
4<head>
5  <style>
6    .container { max-width: 600px; margin: 0 auto; font-family: Arial, sans-serif; }
7    .header { background: #4F46E5; color: white; padding: 20px; text-align: center; }
8    .content { padding: 20px; }
9    .button { 
10      display: inline-block; 
11      background: #4F46E5; 
12      color: white; 
13      padding: 12px 24px; 
14      text-decoration: none; 
15      border-radius: 4px; 
16    }
17    .footer { padding: 20px; text-align: center; color: #666; font-size: 12px; }
18  </style>
19</head>
20<body>
21  <div class="container">
22    <div class="header">
23      <h1>Welcome to Our App!</h1>
24    </div>
25    <div class="content">
26      <p>Hi <%= @user.name %>,</p>
27      <p>Thanks for signing up! We're excited to have you on board.</p>
28      <p>Click the button below to get started:</p>
29      <p>
30        <a href="<%= @login_url %>" class="button">Log In Now</a>
31      </p>
32      <p>If you have any questions, just reply to this email.</p>
33      <p>Cheers,<br>The Team</p>
34    </div>
35    <div class="footer">
36      <p>© <%= Date.current.year %> Our App. All rights reserved.</p>
37    </div>
38  </div>
39</body>
40</html>

Text Template

erb
1<!-- app/views/user_mailer/welcome.text.erb -->
2Welcome to Our App!
3==================
4
5Hi <%= @user.name %>,
6
7Thanks for signing up! We're excited to have you on board.
8
9Get started by logging in:
10<%= @login_url %>
11
12If you have any questions, just reply to this email.
13
14Cheers,
15The Team
16
17--
18© <%= Date.current.year %> Our App. All rights reserved.

Sending Emails

Send Immediately

ruby
1# Sends synchronously (blocks the request)
2UserMailer.welcome(@user).deliver_now
ruby
1# Queues for background processing
2UserMailer.welcome(@user).deliver_later
3
4# With delay
5UserMailer.welcome(@user).deliver_later(wait: 1.hour)
6
7# At specific time
8UserMailer.welcome(@user).deliver_later(wait_until: Date.tomorrow.noon)

Mail Options

ruby
1class UserMailer < ApplicationMailer
2  def notification(user, subject:, body:)
3    @user = user
4    @body = body
5    
6    mail(
7      to: @user.email,
8      from: "notifications@example.com",
9      cc: "admin@example.com",
10      bcc: "logs@example.com",
11      reply_to: "support@example.com",
12      subject: subject
13    )
14  end
15  
16  def with_attachment(user, document)
17    @user = user
18    
19    # Attach file
20    attachments['document.pdf'] = File.read(document.path)
21    
22    # Attach with options
23    attachments['report.csv'] = {
24      mime_type: 'text/csv',
25      content: generate_csv
26    }
27    
28    # Inline attachment (for images in HTML)
29    attachments.inline['logo.png'] = File.read('app/assets/images/logo.png')
30    
31    mail(to: @user.email, subject: 'Your Document')
32  end
33end

Using inline attachments in HTML:

erb
1<%= image_tag attachments['logo.png'].url %>

Configuration

Development (Letter Opener)

ruby
1# Gemfile
2gem 'letter_opener', group: :development
3
4# config/environments/development.rb
5config.action_mailer.delivery_method = :letter_opener
6config.action_mailer.perform_deliveries = true

Production (SMTP)

ruby
1# config/environments/production.rb
2config.action_mailer.delivery_method = :smtp
3config.action_mailer.smtp_settings = {
4  address: 'smtp.example.com',
5  port: 587,
6  domain: 'example.com',
7  user_name: ENV['SMTP_USERNAME'],
8  password: ENV['SMTP_PASSWORD'],
9  authentication: 'plain',
10  enable_starttls_auto: true
11}

SendGrid

ruby
1config.action_mailer.smtp_settings = {
2  address: 'smtp.sendgrid.net',
3  port: 587,
4  domain: 'yourdomain.com',
5  user_name: 'apikey',
6  password: ENV['SENDGRID_API_KEY'],
7  authentication: :plain,
8  enable_starttls_auto: true
9}

Postmark

ruby
1# Gemfile
2gem 'postmark-rails'
3
4# config/environments/production.rb
5config.action_mailer.delivery_method = :postmark
6config.action_mailer.postmark_settings = {
7  api_token: ENV['POSTMARK_API_TOKEN']
8}

Application Mailer

Set defaults for all mailers:

ruby
1# app/mailers/application_mailer.rb
2class ApplicationMailer < ActionMailer::Base
3  default from: 'notifications@example.com',
4          reply_to: 'support@example.com'
5          
6  layout 'mailer'
7  
8  # Helper methods available to all mailers
9  helper :application
10  
11  private
12  
13  def user_email(user)
14    mail(to: email_address_with_name(user.email, user.name))
15  end
16end

Email Layout

erb
1<!-- app/views/layouts/mailer.html.erb -->
2<!DOCTYPE html>
3<html>
4<head>
5  <meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
6  <style>
7    /* Global email styles */
8    body { font-family: Arial, sans-serif; line-height: 1.6; }
9  </style>
10</head>
11<body>
12  <%= yield %>
13</body>
14</html>

Callbacks

ruby
1class UserMailer < ApplicationMailer
2  before_action :set_user
3  after_action :log_delivery
4  
5  def welcome
6    mail(to: @user.email, subject: 'Welcome!')
7  end
8  
9  private
10  
11  def set_user
12    @user = params[:user]
13  end
14  
15  def log_delivery
16    Rails.logger.info "Sending #{action_name} email to #{@user.email}"
17  end
18end
19
20# Using with params
21UserMailer.with(user: @user).welcome.deliver_later

Preview Emails

ruby
1# test/mailers/previews/user_mailer_preview.rb
2class UserMailerPreview < ActionMailer::Preview
3  def welcome
4    user = User.first || User.new(name: 'Test', email: 'test@example.com')
5    UserMailer.welcome(user)
6  end
7  
8  def password_reset
9    user = User.first
10    UserMailer.password_reset(user)
11  end
12end

View at: http://localhost:3000/rails/mailers/user_mailer/welcome

Action Mailer makes sending beautiful emails from Rails straightforward!