Rails Mailer Tutorial

Intro

For a recent project, my group and I wanted to add a feature to automatically send an email to a user that would correspond with a specific action. Looking for the simplest, quickest way to accomplish this task, I avoided the Rails documentation, assuming that it would be overly detailed and complex. The tutorial that I found instead appeared to be simple, but didn’t actually link up with what I was trying to accomplish. I ended up going back to the documentation and taking the time to figure it out. It was very clear and easy to understand, but as expected, I had to sift through some of the details that were not relevant to our project. Here’s the tutorial I wished that I had read:


Tutorial

1. Create a New Gmail Account

You will need to have a working Gmail address to act as the sender, and for our purpose, we don’t want one that has ties to any sensitive information. This is because we’ll need to include the password in our environment file, and if you plan to push up to GitHub, it will be exposed. There are ways to encrypt it, but we won’t get into that now. Create a Gmail account related to your app, and continue to step 2.

2. Generate the Mailer

In your terminal, type rails g mailer UserMailer . (This assumes your app already exists. If not, create a new Rails app by typing rails new <appname> before generating the mailer.) This creates a few things:

  • a mailer controller
  • an HTML layout
  • a text-only layout
  • a directory for views

You also get a test file and a preview file, but we won’t worry about those for this tutorial. We also won’t be changing the layout files, but it’s important to know that they exist.

3. Set Up Your Default ‘From’ Address

Open app/mailers/application_mailer.rb and you should see the following:

class ApplicationMailer < ActionMailer::Base
default from: "from@example.com"
layout 'mailer'
end

Replace from@example.com with your newly created email address.

4. Define Mailer Method

Let’s assume you are using this to send a welcome email to a new user upon sign-up. Seems like a good place to start.

Open app/mailers/user_mailer.rb and add the following method:

class UserMailer < ApplicationMailer
  def welcome_email(user)
@user
= user
mail(to: @user.email, subject: 'Welcome to My Awesome Site')
end
end

Replace My Awesome Site with the name of your site… unless it is really awesome, in which case feel free to leave it as is.

4. Views

Create a file called welcome_email.html.erb in app/views/user_mailer/. This will contain the actual body of the email, formatted using HTML. Here is a bare-bones example of what you may want to add.

<h1>Welcome to example.com, <%= @user.nickname %></h1>
<p>
You have successfully signed up to example.com,
your username is: <%=
@user.usermane %>.<br>
</p>
<p>Thanks for joining and have a great day!</p>

Because not all clients prefer HTML emails, it is best practice to have a text-only version as well. Again in app/views/user_mailer/ , create a file called welcome_email.text.erb, and include something like the following:

Welcome to example.com, <%= @user.nickname %>
===============================================
You have successfully signed up to example.com,
your username is: <%=
@user.username %>.
Thanks for joining and have a great day!

5. Configuration for Gmail

Copy and paste the following into config/environments/development.rb , replacing no-reply@example.com with your newly created Gmail address:

config.action_mailer.delivery_method = :sendmail
# Defaults to:
# config.action_mailer.sendmail_settings = {
# location: '/usr/sbin/sendmail',
# arguments: '-i'
# }
config.action_mailer.perform_deliveries = true
config.action_mailer.raise_delivery_errors = true
config.action_mailer.default_options = {from: 'no-reply@example.com'}

Then copy and paste this next part, which is specific for Gmail:

config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
address: 'smtp.gmail.com',
port: 587,
domain: 'example.com',
user_name: '<username>',
password: '<password>',
authentication: 'plain',
enable_starttls_auto: true
}

Replace example.com with the domain of your app (if you have one). Replace <username> and <password> with your new Gmail username and password.

6. Calling the Mailer

We are now ready to tell the mailer to send emails! Here is the line of code that will execute the action of sending an email:

UserMailer.welcome_email(@user).deliver_now

Notice that it calls our welcome_email method on our UserMailer class and passes in an instance variable that contains the instance of the user. deliver_now is an Action Mailer method that, as you’d expect, delivers the email as soon as its called.

In our case, we want the email to be sent out when a new user signs up, so we will place it in our users controller.

def create
@user = User.new(user_params)
if @user.save
UserMailer.welcome_email(@user).deliver_now
    ...
    end
end

That’s it!

More Mailing

Now that you have a welcome email set up, it is easy to add more mailer functionality. For example, my project was a game that allowed one user to send a challenge invitation to another user, and we wanted the recipient of the invitation to get an email notifying them that they’ve been challenged. The email needed to include their own name, as well as the name of the user that challenged them. In mailers/user_mailer.rb , underneath the welcome_email method, I added an invitation_email method.

class UserMailer < ApplicationMailer
  def welcome_email(user)
@user = user
mail(to: @user.email, subject: 'Welcome to Flatiron Champions!')
end
  def invitation_email(challenger, opponent)
@challenger = challenger
@opponent = opponent
mail(to: @opponent.email, subject: "New Flatiron Champions Challenge!")
end
end

It takes in two arguments, one for the challenger (the user sending the email) and another for the opponent. Notice that we aren’t actually using the @challenger variable in the method. We need it defined there so we can call on it in the view file and include the name of the challenger in the body of the email.

In the views/user_mailer/ directory, I added invitation_email.html.erb and invitation_email.text.erb in which I included the content of the invitation email in HTML and text form, respectively. Because of our method’s arguments, I was able to call on @challenger.nickname and @opponent.nickname in the body of the email.

Even More Mailing

Once your head is wrapped around sending a simple email, check out the Rails documentation for everything else you can do with Action Mailer. They have a more detailed guide to getting set up, as well as info on all the advanced methods and options including sending attachments, etc.

Happy mailing!