How to send emails with Rails 5

October 10, 2018

This tutorial will show you how to send a customized email when the user takes a specific action. We’ll also customize the email to deliver in either HTML or plain text. For the purposes of this tutorial, I’ll send users a welcome email when they sign up.

1. Since we’re sending emails to new users, let’s generate a mailer called UserMailer.

rails g mailer UserMailer

2. We want to create an action inside the mailer that maps to the email we want to send. Let’s send users a welcome email:

# app/mailers/user_mailer.rb
class UserMailer < ApplicationMailer
  default from: ""

  def welcome
    @user = params[:user]
    mail(to:, subject: "Welcome!")

3. Let’s create the corresponding email in app/views/user_mailer/welcome.html.erb. The title of this new file, welcome.html.erb, should match the name of our welcome action from Step 2.

<!DOCTYPE html>
    <meta content='text/html; charset=UTF-8' http-equiv='Content-Type' />
    <h1>Welcome, <%= %>!</h1>

4. Since some users default to plain text emails, let’s make an alternative version inside app/views/user_mailer/welcome.text.erb.

Welcome, <%= %>!

5. Now, just tell Rails when to send this email. If you wanted to email a user when they signed up, you could call UserMailer from inside your create method:

class UsersController < ApplicationController
  def create
    # ...
    UserMailer.with(user: @user).welcome.deliver_later
    # ...

We call deliver_later to make the email send asynchronously. You can keep reading to learn more about passing variables into your mailer.

Passing variables into your mailer

Notice that we’re passing some variables into UserMailer with .with(). These can be accessed via params[:xxx] like we did in Step 2. For instance, you could pass in the @user and a @story:

  user: @user,
  story: "Whether we wanted it or not, we've stepped into a war with the \
  Cabal on Mars. So let's get to taking out their command, one by one.   \
  Valus Ta'aurc. From what I can gather, he commands the Siege Dancers   \
  from an Imperial Land Tank just outside of Rubicon. He's well          \
  protected, but with the right team, we can punch through those         \
  defenses, take this beast out, and break their grip on Freehold."

Then, add it to user_mailer.rb’s welcome method:

def welcome
  @user  = params[:user]
  @story = params[:story]

And finally, reference it inside your views like:

Dear <%= %>,

<%= @story %>

This just cracks the surface of Action Mailer. For more information, read the docs.