How to Verify Emails Using Redis and Twilio

Often, applications must check whether a user’s email is valid or not. Systems must verify that a user is using their own email to protect against bad actors and malicious use.

The Twilio Sendgrid Email API allows you to programmatically send emails, and you can make use of the service to verify emails. Also, in these cases, you must store that data in memory instead of a relational database — this is where Redis comes in.

Below, we’ll outline a tutorial to help you create a system that’ll allow the users to verify their emails, and in doing so, enable your system to verify their emails.

Why Do You Even Need This System?

  • Many apps allow users to send a secret code to their emails to reset their password. You can use this tutorial to understand how the system works.
  • This will also allow the application to check whether the user has used a valid email, and more importantly, whether it’s their own email or not.
  • By sending a verification code, you can use this system to check whether the logged-in user is the account owner. This can help avoid divulging sensitive user information to unauthorized parties.

What Is Redis, and Why Use Redis?

Redis is an open-source tool that runs as a service in the background that allows you to store data in memory for high-performance data retrieval and storage purposes. Essentially, everything you put into Redis sits in memory for easy access. Redis can cache any data, whether a string, integer, or array. And although its role is as a cache, Redis can also work as full-fledged data storage if you want.

Redis is great for storing temporary data that’s quickly retrievable. For example, suppose you want to send a code that’ll expire five minutes after sending. Or, you may want to store some data that is being accessed more frequently than others. You can use Redis to achieve all those things.

In this tutorial, we’ll use Redis to store the OTP/code temporarily in memory.

Prerequisites

  • NodeJS
  • NPM
  • Twilio SendGrid account

Step 1: Install and Run Redis Server

In order to run the Redis service, you first need to install it. So, head over to their official website and follow the instructions for installation. To install Redis on MacOS, use the below command:

brew install redis

Once Redis has been installed, you can run it using the command:

redis-server

Now, keep the Redis server running.

Step 2: Get the SendGrid API Credentials

Now login to your Twilio SendGrid account and create a sender. You should see the below form:

Once you have filled out the form, you now need to generate an API key. Go to the API Key (Settings -> API Key) page and click on the button “Create API.” You should see the below page. When creating API Key, make sure to select “Full Access.”

Now copy and paste your API key into a safe place.

Step 3: Set up the Project and Install Dependencies

Once you have generated the API Key, create a folder redis-sendgrid on your computer and open it in VSCode (or your preferred code editor) and in a new terminal. Now run the below commands to install all the dependencies:

npm install --save @sendgrid/mail
npm install -g redis
npm install prompt-sync

In the above commands, we’re installing the official SendGrid mail library, Redis client, and prompt-sync for taking user input.

After installing the libraries, create two files: sendEmail.js and validateOTP.js. Your folder structure should look like this:

Step 4: Send an OTP Using SendGrid API

Once you have set the project up and installed all the dependencies, it’s time to write some code. Open the file sendEmail.js and paste the below code:

import { createClient } from 'redis';
import setApiKey from '@sendgrid/mail';
import send from '@sendgrid/mail';
import promptSync from 'prompt-sync';
import 'process';

const client = createClient();
client.on('error', (err) => console.log('Redis Client Error', err));
await client.connect();

var code = "";
var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";

for (var i = 0; i < 5; i++)
   code += possible.charAt(Math.floor(Math.random() * possible.length));

const prompt = promptSync();
const email = prompt('Please enter your email: ');

setApiKey.setApiKey('YOUR_API_KEY_HERE');
await client.set(email, code);
const msg = {
 to: email,
 from: 'YOUR EMAIL HERE',
 subject: 'Your Code for password reset',
 text: "Here's your code for password recovery: "+code
};

send.send(msg)
 .then((response) => {
   console.log(response[0].statusCode)
   console.log(response[0].headers)
   process.exit();
 })
 .catch((error) => {
   console.error(error)
   process.exit();
 })

Code Explanation

After importing all the dependencies, the above code creates the client for the Redis server to store and retrieve the data. Then it creates a variable called code that’ll store the random alphanumeric string of length = 5.

Once the code is generated, the prompt() function asks for the receiver’s email on the terminal. So when the user inputs the receiver’s email, it first stores the code in the Redis database and then sends the email with the subject Your Code for password reset.

Note: If you add the below line of code in the file, it’ll automatically delete the code after 24 hours. The second parameter is the timeout in the below function, so you increase or decrease the timeout by passing in the time in seconds.

client.expireat(key, parseInt((+new Date)/1000) + 86400); //OPTIONAL

Testing the Code

We’ll assume that the Redis server is still running on your computer in another terminal. If it’s not running, open a new terminal and run the command redis-server before proceeding.

Now let’s try to execute the code. Run the command node sendEmail.js. If everything works fine, then you should see the below output:

After you enter the receiver’s email, it’ll call the Twilio SendGrid API, and the user should receive an email with the specified subject and a code.

Troubleshooting

You may encounter the error: SyntaxError: Cannot use import statement outside a module. You can easily resolve the error by just adding "type": "module" in your package.json.

Step 5: Verify the OTP

In the above step, you sent the code using SendGrid API. In this step, you’ll validate the code/OTP. Open the file validateOTP.js and paste the below code:

import { createClient } from 'redis';
import promptSync from 'prompt-sync';
import 'process';
const client = createClient();
client.on('error', (err) => console.log('Redis Client Error', err));
await client.connect();

const prompt = promptSync();

const email = prompt('Please enter your email: ');
const code = await client.get(email);

if(code == null){
   console.log("Incorrect Email passed");
   process.exit();
}

const user_code = prompt('Please enter your code: ');

if (user_code == code){
   console.log("Validation Successfull");
   process.exit();
}else{
   console.log("Incorrect Code Passed");
   process.exit();
}

Code Explanation

After importing all the dependencies, the code tries to connect to the Redis server. Once connected, it asks for the email to start the verification. If the email doesn’t exist in the Redis database, it terminates the execution with the message Incorrect Email passed.

If the email exists in the Redis database, it asks for the code. If it matches the code with the one in the database, it prints the success/failure message.

Testing the Code

To execute the code, use the command: node validateOTP.js. You should see the below output:

Here are some example success and failure messages:

Troubleshooting

You may encounter the error: SyntaxError: Cannot use import statement outside a module. Again, you can easily resolve the error by just adding "type": "module" in your package.json.

Final Words

Since Redis is an open-source technology, it is widely used in many applications. The flexibility of Redis makes it easy for other developers to integrate into their applications. If you want to send multiple emails using Twilio, you can check out this other tutorial on sending emails in bulk. Twilio Sendgrid is a fine option for this use case, but there are also plenty of other email APIs on the market to keep in mind.