@mailtester/core
v1.1.2
Published
Modern, high-performance email validation with RFC 5322 compliance, typo detection, disposable email blocking, MX verification, and SMTP validation
Maintainers
Readme
@mailtester/core
Modern, high-performance email validation for Node.js
A comprehensive email validation library with RFC 5322 compliance, typo detection, disposable email blocking, MX record verification, and SMTP validation.
📚 Documentation • Installation • Quick Start • API Reference • Configuration • License
Features
- RFC 5322 Compliant — Full regex validation with strict and loose modes
- Typo Detection — Suggests corrections for common domain typos (gmaill.com → gmail.com)
- Disposable Email Blocking — Detects 40,000+ temporary email services
- MX Record Validation — Verifies domain has valid mail servers
- SMTP Verification — Checks if mailbox actually exists
- Bulk Validation — Process thousands of emails concurrently
- Rate Limiting — Built-in protection against API abuse
- TypeScript First — Full type safety with strict mode
- Zero Config — Sensible defaults, works out of the box
- Lightweight — ~25KB gzipped, minimal dependencies
Requirements
- Node.js 16.0.0 or higher
- TypeScript 5.3+ (for TypeScript users)
Installation
# npm
npm install @mailtester/core
# yarn
yarn add @mailtester/core
# pnpm
pnpm add @mailtester/coreQuick Start
Basic Validation
import { validate } from '@mailtester/core';
const result = await validate('[email protected]');
console.log(result.valid); // true
console.log(result.score); // 85 (0-100 reputation score)With Configuration
import { validate } from '@mailtester/core';
const result = await validate('[email protected]', {
preset: 'balanced', // Skip SMTP for faster validation
earlyExit: true // Stop on first failure
});
if (!result.valid) {
console.log(`Invalid: ${result.reason}`);
// e.g., "Invalid: disposable"
}Bulk Validation
import { validateBulk } from '@mailtester/core';
const emails = [
'[email protected]',
'[email protected]',
'[email protected]'
];
const result = await validateBulk(emails, {
concurrency: 10,
onProgress: (completed, total) => {
console.log(`Progress: ${completed}/${total}`);
}
});
console.log(`Valid: ${result.valid}/${result.total}`);
// Valid: 2/3Custom Validator Instance
import { createValidator } from '@mailtester/core';
// Create a reusable validator with custom config
const validator = createValidator({
validators: {
regex: { enabled: true },
typo: { enabled: true },
disposable: { enabled: true },
mx: { enabled: true },
smtp: { enabled: false } // Disable SMTP for speed
},
earlyExit: true
});
// Validate multiple emails with same config
const result1 = await validator.validate('[email protected]');
const result2 = await validator.validate('[email protected]');API Reference
validate(email, options?)
Validates a single email address.
const result = await validate('[email protected]');Parameters:
email(string) — Email address to validateoptions(Config, optional) — Validation configuration
Returns: Promise<ValidationResult>
interface ValidationResult {
valid: boolean; // Overall validity
email: string; // Email that was validated
score: number; // Reputation score (0-100)
reason?: string; // Which validator failed (if invalid)
validators: { // Individual validator results
regex?: ValidatorResult;
typo?: ValidatorResult;
disposable?: ValidatorResult;
mx?: ValidatorResult;
smtp?: ValidatorResult;
};
metadata?: {
timestamp?: string; // ISO 8601 timestamp
duration?: number; // Validation duration in ms
};
}validateBulk(emails, options?)
Validates multiple email addresses concurrently.
const result = await validateBulk(emails, {
concurrency: 10,
onProgress: (completed, total) => console.log(`${completed}/${total}`)
});Parameters:
emails(string[]) — Array of email addressesoptions(BulkValidationOptions, optional) — Bulk validation options
Options:
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| concurrency | number | 10 | Max concurrent validations |
| continueOnError | boolean | true | Continue if individual validation fails |
| onProgress | function | — | Progress callback (completed, total) => void |
| config | Config | — | Validation config for all emails |
| rateLimit | object | — | Rate limiting configuration |
Returns: Promise<BulkValidationResult>
interface BulkValidationResult {
results: ValidationResult[]; // Individual results
total: number; // Total emails processed
valid: number; // Count of valid emails
invalid: number; // Count of invalid emails
errors: number; // Count of errors
duration: number; // Total duration in ms
}createValidator(config?)
Creates a reusable validator instance with custom configuration.
const validator = createValidator({ preset: 'strict' });
const result = await validator.validate('[email protected]');Parameters:
config(Config, optional) — Validator configuration
Returns: ValidatorInstance
interface ValidatorInstance {
validate(email: string): Promise<ValidationResult>;
getConfig(): MergedConfig;
}Configuration
Presets
Three built-in presets for common use cases:
| Preset | Validators | Early Exit | Use Case |
|--------|------------|------------|----------|
| strict | All enabled | Yes | Maximum validation (default) |
| balanced | SMTP disabled | No | Fast validation with good coverage |
| permissive | Regex only | Yes | Quick format check |
// Use strict preset (default)
await validate('[email protected]', { preset: 'strict' });
// Use balanced preset (no SMTP)
await validate('[email protected]', { preset: 'balanced' });
// Use permissive preset (regex only)
await validate('[email protected]', { preset: 'permissive' });Custom Configuration
await validate('[email protected]', {
validators: {
regex: { enabled: true },
typo: { enabled: true },
disposable: { enabled: true },
mx: { enabled: true },
smtp: { enabled: false }
},
earlyExit: true, // Stop on first failure
timeout: 30000 // 30 second timeout
});Configuration Options
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| preset | string | — | Use preset config: 'strict', 'balanced', 'permissive' |
| validators | object | — | Enable/disable individual validators |
| earlyExit | boolean | true | Stop validation on first failure |
| timeout | number | — | Overall timeout in milliseconds |
Validators
Regex Validator
Validates email format according to RFC 5322 standards.
// Enabled by default
{ regex: { enabled: true } }Checks:
- Valid email format (local@domain)
- Proper character usage
- Domain structure
- Internationalized domain names (IDN)
Typo Validator
Detects common domain typos and suggests corrections.
// Enabled by default
{ typo: { enabled: true } }Examples:
gmaill.com→ suggestsgmail.comyahooo.com→ suggestsyahoo.comhotmal.com→ suggestshotmail.com
Disposable Validator
Blocks temporary/disposable email services.
// Enabled by default
{ disposable: { enabled: true } }Blocks:
- 40,000+ known disposable domains
- Pattern-based detection
- Temporary email services
MX Validator
Verifies domain has valid mail exchange servers.
// Enabled by default
{ mx: { enabled: true } }Checks:
- MX records exist
- DNS resolution works
- Fallback to A records
SMTP Validator
Verifies mailbox exists by connecting to mail server.
// Enabled by default (disable for speed)
{ smtp: { enabled: true } }Checks:
- SMTP connection
- RCPT TO verification
- Mailbox existence
Note: SMTP validation may be blocked by some mail servers or firewalls. Consider using
balancedpreset if you experience timeouts.
Rate Limiting
Built-in rate limiting for bulk validation:
await validateBulk(emails, {
rateLimit: {
global: {
requests: 100, // Max requests
window: 60 // Per 60 seconds
},
perDomain: {
requests: 10, // Max per domain
window: 60 // Per 60 seconds
}
}
});Error Handling
import { validate, ValidationError } from '@mailtester/core';
try {
const result = await validate('[email protected]');
if (!result.valid) {
console.log(`Invalid email: ${result.reason}`);
// Check specific validator errors
if (result.validators.disposable?.error) {
console.log('Disposable email detected');
}
}
} catch (error) {
if (error instanceof ValidationError) {
console.log(`Validation error: ${error.code}`);
}
}TypeScript Support
Full TypeScript support with strict mode:
import type {
ValidationResult,
ValidatorResult,
Config,
BulkValidationOptions,
BulkValidationResult
} from '@mailtester/core';
// All types are exported
const config: Config = {
preset: 'strict',
earlyExit: true
};
const result: ValidationResult = await validate('[email protected]', config);Performance
- Single validation: < 150ms (without SMTP)
- Bulk 100 emails: < 5 seconds
- Package size: ~25KB gzipped
Tips for Better Performance
Disable SMTP for faster validation:
await validate(email, { preset: 'balanced' });Use bulk validation for multiple emails:
await validateBulk(emails, { concurrency: 20 });Enable early exit to stop on first failure:
await validate(email, { earlyExit: true });
Examples
Express.js Integration
import express from 'express';
import { validate } from '@mailtester/core';
const app = express();
app.use(express.json());
app.post('/api/validate-email', async (req, res) => {
const { email } = req.body;
const result = await validate(email, { preset: 'balanced' });
res.json({
valid: result.valid,
score: result.score,
reason: result.reason
});
});User Registration
import { validate } from '@mailtester/core';
async function registerUser(email: string, password: string) {
// Validate email first
const validation = await validate(email, {
validators: {
regex: { enabled: true },
typo: { enabled: true },
disposable: { enabled: true },
mx: { enabled: true },
smtp: { enabled: false } // Skip for speed
}
});
if (!validation.valid) {
throw new Error(`Invalid email: ${validation.reason}`);
}
// Check for typo suggestions
if (validation.validators.typo?.details?.suggestion) {
// Optionally warn user about potential typo
console.log(`Did you mean: ${validation.validators.typo.details.suggestion}?`);
}
// Proceed with registration...
}Email List Cleaning
import { validateBulk } from '@mailtester/core';
async function cleanEmailList(emails: string[]) {
const result = await validateBulk(emails, {
concurrency: 20,
config: { preset: 'balanced' },
onProgress: (completed, total) => {
const percent = Math.round((completed / total) * 100);
console.log(`Cleaning: ${percent}%`);
}
});
const validEmails = result.results
.filter(r => r.valid)
.map(r => r.email);
console.log(`Cleaned: ${validEmails.length}/${emails.length} valid`);
return validEmails;
}Contributing
Contributions are welcome! Please read our Contributing Guide for details.
# Clone the repository
git clone https://github.com/kazmiali/mailtester.git
# Install dependencies
yarn install
# Run tests
yarn test
# Build
yarn buildLicense
MIT © Ali Kazmi
