Validating emails in Mongoose is a key step for maintaining clean data and reliable user accounts. We will walk through five ways to implement validation using working code snippets, discuss the shortcomings of these traditional methods, and then show how Abstract API addresses these issues.
How to Implement Email Validation in Mongoose
Mongoose offers several ways to validate email formats directly within your schema definition. Here are four common approaches, each with its own implementation style and level of abstraction.
Built-in Match Validator
A String path in a Mongoose schema can take a match option. This option uses a regular expression to check the validity of the email format. Mongoose wraps the expression in RegExp.test()
and runs it each time the document undergoes validation.
const userSchema = new mongoose.Schema({
email: {
type: String,
required: true,
lowercase: true,
trim: true,
match: /^[^\s@]+@[^\s@]+\.[^\s@]+$/
}
});
Inline Custom Validator Function
The validate property accepts an object that contains a validator function and a message. This method provides full control over the validation logic and can even return a Promise for asynchronous operations.
You can branch on different conditions or perform complex checks before the document saves to MongoDB. The function receives the value to validate as an argument.
const EMAIL_RX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
const userSchema = new mongoose.Schema({
email: {
type: String,
required: true,
lowercase: true,
validate: {
validator: v => EMAIL_RX.test(v),
message: p => `${p.value} is not RFC-5322 compliant`
}
}
});
Validator.js Integration
You can integrate a third-party library like validator.js for more nuanced validation. This approach delegates rule maintenance to the library's team, so you do not need to track RFC updates yourself.
The library's isEmail
function handles complexities like Unicode characters and display-name strips. You use it inside the same validate hook as an inline custom validator.
const validator = require('validator');
const userSchema = new mongoose.Schema({
email: {
type: String,
required: true,
lowercase: true,
validate: {
validator: v => validator.isEmail(v, { allow_utf8_local_part: false }),
message: p => `${p.value} fails validator.js isEmail()`
}
}
});
Dedicated Schema-Type Plugin
The mongoose-type-email plugin registers a dedicated Email
type with Mongoose. This method keeps the schema definition clean, as you just select a different type instead of the addition of custom validators.
The plugin offers built-in options, such as correctTld
to reject bare domains and allowBlank
. This type can be reused across multiple schemas without the need to copy code.
require('mongoose-type-email');
const userSchema = new mongoose.Schema({
email: {
type: mongoose.SchemaTypes.Email,
required: true,
correctTld: true,
allowBlank: false
}
});
Challenges of Mongoose Email Validation
While these methods provide basic checks, they come with significant challenges. Their focus on syntax alone often fails to ensure data quality and can create maintenance overhead for your application.
- Regex-based approaches like the built-in match validator only confirm syntactic correctness. They cannot detect dead mailboxes or disposable domains because they perform no check on an email's existence or deliverability.
- Static regexes in built-in and custom validators quickly become outdated. They fail to handle new TLDs or Unicode local parts, which causes the rejection of valid emails or the acceptance of invalid ones.
- The common
unique: true
flag is not a validator but an asynchronous index operation. Duplicate emails can enter the database during concurrent writes, which surfaces later as a database error that requires manual translation. - A true validation, like an MX lookup, requires an async custom validator. This approach adds network latency and new failure modes to the save pipeline, which can stall or abort document writes entirely.
Validate Emails with Abstract API.
Add reliable email validation to your Mongoose schema to protect your application from bad data.
Get started for free
How Abstract API Handles Email Validation in Mongoose
Abstract API addresses the core weaknesses of traditional validation methods through real-time infrastructure checks and risk analysis.
- It performs RFC-compliant syntax checks, typo autocorrection, and MX record lookups to confirm the domain configuration.
- The API conducts a real-time SMTP handshake to verify a mailbox can accept mail, which prevents bounces from non-existent accounts.
- It detects disposable, free, and role-based addresses, which allows for policy controls over sign-ups.
- The service identifies known spam-trap and toxic domains to block malicious actors before they enter your database.
- Each check returns a simple deliverability status and a quality score for an evidence-based decision.
How to Bring Abstract API to Your Dev Environment
Once you understand the capabilities of Abstract API, the process to add its email validation API to your project is simple. First, sign up at Abstract, create an Email Verification project, and copy your API key. Next, install an HTTP client and environment loader like axios and dotenv.
npm i axios dotenv
After you install the packages, add your API key to a .env file. The code below shows how to create a helper function that calls the API and integrates it into a Mongoose schema as a custom validator. Failed validations will then surface as standard Mongoose ValidationError objects.
const axios = require('axios');
require('dotenv').config();
async function verifyEmail(email) {
return axios.get('https://emailvalidation.abstractapi.com/v1/', {
params: {
api_key: process.env.ABSTRACT_KEY,
email
}
}).then(r => r.data);
}
const emailSchema = new mongoose.Schema({
email:{
type:String,
required:true,
validate:{
validator:async v=>{
const r = await verifyEmail(v);
return r.deliverability==='DELIVERABLE' && r.is_smtp_valid.value;
},
message:'Email failed external validation'
}
}
});
Sample Email Validation Implementation with Abstract API
The custom validator in the schema calls the API for each new email. It checks the response to confirm the deliverability status is DELIVERABLE and the SMTP check is valid. If these conditions are not met, Mongoose rejects the email and returns the custom error message. This provides a robust, evidence-based decision instead of a simple regex guess.
A successful API call returns a detailed JSON object like this sample response:
{
"email":"johnsmith@gmail.com",
"autocorrect":"",
"deliverability":"DELIVERABLE",
"quality_score":0.9,
"is_valid_format":{"value":true,"text":"TRUE"},
"is_free_email":{"value":true,"text":"TRUE"},
"is_disposable_email":{"value":false,"text":"FALSE"},
"is_role_email":{"value":false,"text":"FALSE"},
"is_catchall_email":{"value":false,"text":"FALSE"},
"is_mx_found":{"value":true,"text":"TRUE"},
"is_smtp_valid":{"value":true,"text":"TRUE"}
}
The response fields give you precise control. The deliverability and quality_score fields let you gate sign-ups or flag accounts for manual review. The is_mx_found and is_smtp_valid flags confirm the mailbox can physically accept mail. Other flags for disposable, role, and free addresses enable specific policy controls.
Final Thoughts
Traditional regex methods only check an email's format. They cannot confirm if an address actually exists or accepts mail, which leads to bad data. Abstract API solves this with real-time infrastructure checks that confirm deliverability, domain validity, and mailbox status. For reliable user email validation, consider an account on Abstract API to get your free API key.
Validate Emails with Abstract API
Don't let bad emails compromise your data. Start validating user signups in your application.
Get started for free