Ensuring email addresses are valid in Mongoose is fundamental for clean data. You can find three common ways to handle this validation, each with working code snippets. We'll also examine the shortcomings of these traditional methods and show how Abstract API helps overcome their limitations.
How to Implement Email Validation in Mongoose
Here are four common ways to validate email addresses in Mongoose. Each method includes a description of how it works and a corresponding code snippet for implementation.
Built-in Match Validator
A String path in a schema can take a match option. Mongoose then uses a regular expression to test the input each time the document validates. This method executes synchronously, so it does not require any promise or async setup.
The error message comes from Mongoose’s internal validator. This approach offers a straightforward way to enforce a specific format with zero runtime dependencies.
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 with a validator function and a message. This method provides full control and can be asynchronous if needed, which allows for more complex logic like external API calls.
It also offers a single place to normalize, trim, and compare domains before the document reaches the database. The custom message property allows for specific feedback when validation fails.
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
This approach integrates the popular third-party library, validator.js. The validator.isEmail() function handles complex validation rules, such as IDNA, UTF-8 local parts, and sub-addressing. This method delegates rule maintenance to the library's team.
It offers more nuance than a simple regular expression and can be easily swapped in or out because it uses the same validate hook.
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 "mongoose.SchemaTypes.Email" as a new schema type upon require-time. This approach keeps the schema definition clean, as you just select a different type instead of the addition of validators.
It includes built-in options like "allowBlank" and "correctTld" to reject bare domains. The plugin can be reused across many schemas without code duplication.
require('mongoose-type-email');
const userSchema = new mongoose.Schema({
email: {
type: mongoose.SchemaTypes.Email,
required: true,
correctTld: true,
allowBlank: false
}
});
Challenges of Implementing Email Validation in Mongoose
Traditional Mongoose validation methods primarily check for syntactic correctness. They often fail to confirm an email's actual deliverability or protect against common data quality issues that arise in production.
- The built-in match validator and other regex-based methods only confirm syntactic correctness. They accept dead mailboxes, disposable domains, and spam-trap addresses because they never verify the email's existence or deliverability.
- Static regexes in the match validator and custom functions quickly become outdated. They fail to account for new TLDs, Unicode characters, or IDNs, which leads to the rejection of valid emails or the acceptance of invalid ones.
- The unique: true option is not a validator but an index build process. During concurrent writes or before the index completes, duplicate emails can bypass the check and cause late-stage database errors that require manual translation.
- Async validators that perform real checks like MX lookups introduce network latency into the save pipeline. This approach adds complexity with retry logic and new failure modes that can stall or even abort document writes.
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 methods by perform comprehensive, real-time checks that go beyond simple format validation.
- It performs RFC-compliant syntax checks and suggests corrections for typos.
- It confirms a domain has valid MX records and performs a real-time SMTP handshake to ensure the mailbox accepts mail.
- It detects disposable, free, and role-based email addresses to support custom validation policies.
- It identifies spam-trap domains before they enter your database.
- It returns a high-level deliverability status and a quality score for an evidence-based decision.
How to Add Abstract API to Your Dev Environment
Once you know Abstract’s capabilities, to add its email validation API to your project is simple.
- Sign up at Abstract API, create an Email Verification project, and copy the API key.
- Install the necessary packages.
npm i axios dotenv
- Add your API key to a ".env" file.
ABSTRACT_KEY=your_key
- Create a helper function to call the API.
async function verifyEmail(email){
return axios.get('https://emailvalidation.abstractapi.com/v1/',{params:{api_key:process.env.ABSTRACT_KEY,email}}).then(r=>r.data);
}
Sample Email Validation Implementation with Abstract API
You can attach the helper function directly to a Mongoose schema as a custom validator. This code block demonstrates how to integrate the API call into your data model. The validator function checks the API response to ensure the email has a "DELIVERABLE" status and a valid SMTP record before it accepts the data.
const axios = require('axios');
require('dotenv').config();
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'
}
}
});
If the validation succeeds, the API returns a detailed JSON object. This output gives you an evidence-based decision instead of a simple regex guess. You can use the "quality_score" to gate sign-ups or flag accounts for review, while other flags identify disposable or role-based addresses.
{
"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"}
}
Final Thoughts
Traditional regex validation fails to detect invalid domains, disposable addresses, or spam traps, which allows bad data into your system. Abstract API offers a robust solution with real-time checks for deliverability and infrastructure. Consider an account to get your free API key and reliably validate user emails.
Validate Emails with Abstract API
Don't let bad emails compromise your data. Start validating user signups in your application.
Get started for free