Authenticate Users with Confirmation Emails using Devise & SendGrid
If you are building an application that has users, you might be interested in authenticating a user’s account with a confirmation email. I recently implemented this functionality into an application — using ActionMailer, SendGrid, and Devise — and found that while there were a number of great step-by-step guides on how to authenticate accounts and send emails, there was not much information on how/why these steps work. This article should help you better understand what’s going on in that code you just copy/pasted from your favorite Rails blogger.
Below, I’ll cover the tools used to authenticate new user accounts by sending confirmation emails from your application and will give a high-level overview of what code needs to go where to make it GO!
ActionMailer: ActionMailer is a built in Rails class that allows you to send emails from your application using mailer classes and views. Mailers are really just another way to render a view. By generating a Mailer and calling the ActionMailer method `mail`, you can send an email using the views you’ve defined.
SendGrid: You could absolutely send your emails solely using the ActionMailer mentioned above but there are a number of reasons why it is considered best practice to use a different server to send emails from your production environment — including security and reliability. SendGrid is a Simple Mail Transfer Protocol (SMTP) that helps ensure your emails are successfully delivered to your users and makes them less likely to be seen as spam. This is very important! Your users will be upset if they don’t receive the emails they need to activate their account or the notifications they request. With the process discussed in this post, ActionMailer is set up to hand off emails to SendGrid, then SendGrid ensures they are delivered to the users.
Figaro (Optional): Environment variables (like, API keys) usually need to be app-specific, private, and varied by environment. The Figaro gem provides a solution for handling this sensitive data. When using SendGrid, a username and password will be generated and you should consider storing those using Figaro.
Devise: This is where the authentication happens. Devise is a flexible authentication solution for Rails that allows you to build some really important functionality such as the ability to confirm new user’s accounts with an email confirmation (see more Devise features here). Once the user submits their registration form, Devise will pass the new user’s information to the User model (to be stored in the database) and to the ActionMailer class which will hand the email off to SendGrid to deliver to the user.
High-Level Explanation of What Happens:
- User accesses sign-up page and fills out the registration form.
- When the user clicks “Submit”, Devise sends the information the user provided to the User model (to be stored in the database).
- Then, Devise sends ActionMailer an email view (subject, body, email address).
- ActionMailer looks into the configuration information to see how it should send the email and sees that it is being pointed to SendGrid’s server.
- SendGrid delivers the email to the user.
Let’s take a look at how this functionality can be set up in your application. (This is a high-level guide. For step-by-step instructions, see the resources I’ve listed below.)
Start by setting up Devise to authenticate users:
- Add the Devise gem to your project.
- Then you’ll need to set up the default URL options for the Devise mailer in each environment (test, development, and production).
- Create your application’s User class with the Devise generator. This will create a model (if one does not exist) and configure it with the default Devise modules. The generator also configures your `config/routes.rb` file to point to the Devise controller.
- Next, check the User model for any of the additional Devise configuration options you might want to add, such as confirmable or lockable (there are a total of 10 that you can cherry pick). If you add an option, be sure to inspect the migration file and uncomment the appropriate section. For the example in this article where we’re authenticating user accounts by sending confirmation emails, we need to uncomment the Confirmable section in the migration. You will also need to add `:confirmable` to the Devise method in your user model.
- Migrate your database!
- Create your views. Because Devise was built to help you quickly build an application that uses authentication, you can invoke the Devise views generator to copy all necessary views to your project. In this very specific narrowly scoped example, we need the Devise views for the sign in page, sign up page (registration form), and the confirmation email Devise also offers other pre-made, customizable, views that will be very useful as this app continues to develop.
- We don’t want our users to be able to access any part of our app, besides the sign in/up views until they’ve authenticated their account via the confirmation email. To restrict access, we can add
before_action :authenticate_user!to our application controller.
Now get the emails rolling with ActionMailer and SendGrid:
- If you haven’t already, get your app on Heroku and install the SendGrid add-on from your command line.
- (Optional) If you’re going to use Figaro to store your SendGrid credentials, use the command line to get the automatically created username and password from Heroku.
- The code in `config/initialize` runs when our app starts. We use this when want to set config options or application settings. In this case we need to configure some special settings to send emails. This is where we can configure ActionMailer to use SendGrid by specifying the ActionMailer settings to point to SendGrid’s servers.’
- (Optional) If you’ve chosen to use Figaro, you’ll need to now add the gem, store your credentials in
config/application.yml. Then share what your hiding with collaborators by creating a a new file in your config directory named
application.example.yml. This file will not be ignored and so will show up on GitHub. It only exists to demonstrate to collaborators what variables are expected, and how they should be formatted.
That’s how it works! If you have other insight you think would be helpful for newbies to know, please share below so we can all continue learning together!