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')
endend
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!")
endend
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!