DEV Community

Cover image for How To Implemented Email OTP Verification in Web Application
Prashant Patil
Prashant Patil

Posted on

How To Implemented Email OTP Verification in Web Application

Email verification has become a standard feature in modern web applications. Whether you're building an e-commerce platform, a social media application, or a job portal, verifying a user's email helps ensure that accounts belong to real users while reducing spam and fake registrations.

During one of my MERN stack projects, I wanted to implement email-based OTP verification. Initially, I had no idea where to start. I knew the feature was important, but I wasn't sure how production applications handled it. So, I spent time researching different approaches, reading documentation, and even asking AI how large companies implement email verification systems.

This article summarizes what I learned and explains the approach I found easiest to implement.

Different Ways to Send OTP Emails

There are several ways to send verification emails from your application.

1. Nodemailer (The Simplest for MERN Applications)

If you're using Node.js, Nodemailer is one of the easiest libraries to integrate. It allows your backend to send emails through providers like Gmail, Outlook, or SMTP servers with very little setup.

For personal projects, learning, or small-scale applications, this is an excellent choice because it requires minimal configuration.

2. Email Service Providers (Recommended for Production)

As I researched further, I found that most large companies don't send emails directly using Gmail. Instead, they use dedicated email delivery services such as:

  • Amazon SES
  • SendGrid
  • Mailgun
  • Postmark
  • Brevo (formerly Sendinblue)

These services provide:

  • Better email deliverability
  • Higher sending limits
  • Analytics
  • Bounce handling
  • Spam protection
  • Improved reliability

Many of these services also provide Node.js SDKs, making integration straightforward.

3. SMTP Servers

Another option is connecting your application directly to an SMTP server. Many hosting providers and organizations provide SMTP credentials that applications can use to send emails.

This approach offers more control but usually requires additional configuration.

Why I Chose Nodemailer

Since my project was built using the MERN stack, I found Nodemailer to be the simplest solution.

It integrates seamlessly with Express.js and only requires a few lines of code to send emails. The extensive documentation and large community also make troubleshooting much easier.

For learning purposes and personal projects, I believe this is one of the best ways to understand how email verification works before moving on to enterprise-grade services.

Creating a Google Account and Getting Credentials

To use Gmail with Nodemailer, you'll first need a Google account.

Instead of using your normal Gmail password, Google recommends creating an App Password.

The general process is:

  1. Create or use an existing Google account.
  2. Enable 2-Step Verification on the account.
  3. Navigate to your Google Account security settings.
  4. Generate an App Password.
  5. Use the generated email address and App Password inside your Node.js application.

These credentials allow Nodemailer to securely authenticate with Gmail without exposing your actual account password.

Database Design

While designing the User model, I added a simple field:

isEmailVerified: {
    type: Boolean,
    default: false
}
Enter fullscreen mode Exit fullscreen mode

This field determines whether the user has successfully verified their email address.

Whenever a new account is created, this value remains false until the OTP verification process is completed.

Login Flow

One thing I wanted to avoid was allowing unverified users to access the application.

The login flow works like this:

  1. User enters email and password.
  2. Validate the credentials.
  3. Check the isEmailVerified field.
  4. If the value is true, allow login.
  5. If the value is false, redirect the user to the OTP verification page.

On the OTP page, the user's email is already pre-filled, making the process faster and more user-friendly.

Sending the OTP

When the user clicks the Send OTP button:

  • Generate a random 6-digit OTP.
  • Set an expiration time (typically 5–10 minutes).
  • Send the OTP to the registered email using Nodemailer.

This creates a smooth experience while preventing unnecessary emails from being sent automatically.

Never Store OTPs in Plain Text

One important lesson I learned is that OTPs should never be stored directly in the database.

Instead:

  • Hash the OTP using a secure hashing algorithm such as bcrypt.
  • Store only the hashed version.
  • Keep an expiration timestamp.
  • Delete or invalidate the OTP after successful verification or expiry.

This ensures that even if someone gains database access, they cannot view users' OTPs.

Verifying the OTP

Once the user enters the OTP:

  1. Retrieve the stored hashed OTP.
  2. Compare the entered OTP with the hashed value.
  3. Verify that the OTP hasn't expired.
  4. If the OTP matches:
    • Update isEmailVerified to true.
    • Remove the stored OTP.
    • Allow the user to continue using the application.
  5. If the OTP is incorrect or expired, ask the user to request a new OTP.

Additional Best Practices

While implementing the feature, I also discovered several practices commonly used in production applications:

  • Limit the number of OTP requests within a certain time window.
  • Add a cooldown (for example, 30–60 seconds) before allowing another OTP request.
  • Set OTP expiration to 5–10 minutes.
  • Limit incorrect verification attempts.
  • Log verification events for auditing.
  • Use HTTPS to protect data during transmission.
  • Prevent brute-force attacks with rate limiting.

These measures improve both security and user experience.

What I Learned

Before implementing this feature, I assumed email verification would be difficult. After researching multiple approaches, I realized the overall concept is actually straightforward once you understand the authentication flow.

For my MERN stack application, Nodemailer turned out to be the easiest solution because it integrates naturally with Node.js and Express. Later, I also learned that larger companies usually rely on dedicated email services like Amazon SES or SendGrid for better scalability and reliability.

If you're building your first full-stack application, implementing email OTP verification is a great way to strengthen your understanding of authentication, backend development, database design, and application security. Once you understand the fundamentals, transitioning to enterprise-grade email providers becomes much easier.

Top comments (0)