Email Verification Testing Guide
Master email verification testing with Mail7's comprehensive guide. Learn how to implement robust email validation, prevent invalid signups, and ensure high-quality user data in your applications.
Understanding Email Verification
Email verification is crucial for maintaining data quality and preventing fraud. Key aspects include:
- Syntax Validation: Ensure email addresses follow correct format
- Domain Verification: Validate email domain existence
- Mailbox Verification: Check if mailbox exists
- Anti-Fraud Measures: Detect disposable or suspicious emails
Mail7 Verification Features
- Real-time Verification: Instant email address validation
- Batch Processing: Verify multiple emails efficiently
- Detailed Reports: Get comprehensive verification results
- API Integration: Easy integration with your applications
Implementation Guide
1. Basic Email Verification
async function verifyEmail(email) {
try {
const response = await fetch('https://api.mail7.io/verify', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({ email })
});
const result = await response.json();
return {
isValid: result.valid,
reason: result.reason,
risk: result.risk_score
};
} catch (error) {
console.error('Verification failed:', error);
throw error;
}
}
2. Batch Verification
async function verifyEmailBatch(emails) {
try {
const response = await fetch('https://api.mail7.io/verify/batch', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({ emails })
});
return await response.json();
} catch (error) {
console.error('Batch verification failed:', error);
throw error;
}
}
3. Verification with Custom Rules
function createVerificationRules() {
return {
syntax: true,
dns: true,
mailbox: true,
disposable: false,
catchAll: false
};
}
async function verifyWithRules(email, rules) {
try {
const response = await fetch('https://api.mail7.io/verify/advanced', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({ email, rules })
});
return await response.json();
} catch (error) {
console.error('Advanced verification failed:', error);
throw error;
}
}
Testing Scenarios
1. Basic Validation
- Valid email formats
- Invalid syntax cases
- Special characters handling
- Case sensitivity tests
2. Domain Verification
- Valid domains
- Non-existent domains
- Temporary DNS issues
- International domains
3. Advanced Scenarios
- Disposable email detection
- Role-based email detection
- Catch-all domain handling
- High-risk pattern detection
Advanced Verification Patterns
1. Comprehensive Email Verification Service
// EmailVerificationService.js
class EmailVerificationService {
constructor(config) {
this.apiKey = config.apiKey;
this.baseUrl = config.baseUrl || 'https://api.mail7.io';
this.cache = new Map();
this.rateLimiter = new RateLimiter(config.rateLimit || 100);
}
async verify(email, options = {}) {
await this.rateLimiter.acquire();
if (options.useCache && this.cache.has(email)) {
return this.cache.get(email);
}
try {
const result = await this.performVerification(email);
if (options.useCache) {
this.cache.set(email, result);
setTimeout(() => this.cache.delete(email),
options.cacheDuration || 3600000);
}
return result;
} catch (error) {
throw new VerificationError(
`Failed to verify ${email}: ${error.message}`);
}
}
async performVerification(email) {
const response = await fetch(`${this.baseUrl}/verify`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${this.apiKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
email,
validateMX: true,
checkDisposable: true,
checkFree: true,
checkCatchAll: true
})
});
if (!response.ok) {
throw new Error(`API request failed: ${response.statusText}`);
}
const result = await response.json();
return this.enrichVerificationResult(result);
}
enrichVerificationResult(result) {
return {
...result,
riskLevel: this.calculateRiskLevel(result),
recommendations: this.generateRecommendations(result),
timestamp: new Date()
};
}
calculateRiskLevel(result) {
let risk = 0;
if (result.isDisposable) risk += 0.4;
if (result.isFree) risk += 0.2;
if (result.isCatchAll) risk += 0.3;
if (!result.hasMX) risk += 0.5;
return Math.min(risk, 1);
}
generateRecommendations(result) {
const recommendations = [];
if (result.isDisposable) {
recommendations.push('Consider blocking disposable email providers');
}
if (result.isCatchAll) {
recommendations.push('Implement additional verification steps');
}
if (result.riskLevel > 0.7) {
recommendations.push('Require additional user verification');
}
return recommendations;
}
}
2. Advanced Batch Processing
// BatchVerificationProcessor.js
class BatchVerificationProcessor {
constructor(config) {
this.verifier = new EmailVerificationService(config);
this.batchSize = config.batchSize || 100;
this.concurrency = config.concurrency || 5;
}
async processBatch(emails) {
const batches = this.splitIntoBatches(emails);
const results = new Map();
const errors = new Map();
await Promise.all(
batches.map(async batch => {
try {
const batchResults = await this.verifyBatch(batch);
batchResults.forEach((result, email) => {
results.set(email, result);
});
} catch (error) {
batch.forEach(email => {
errors.set(email, error.message);
});
}
})
);
return {
results: Object.fromEntries(results),
errors: Object.fromEntries(errors),
summary: this.generateSummary(results, errors)
};
}
splitIntoBatches(emails) {
const batches = [];
for (let i = 0; i < emails.length; i += this.batchSize) {
batches.push(emails.slice(i, i + this.batchSize));
}
return batches;
}
async verifyBatch(emails) {
const results = new Map();
const queue = new PQueue({ concurrency: this.concurrency });
await Promise.all(
emails.map(email =>
queue.add(async () => {
const result = await this.verifier.verify(email);
results.set(email, result);
})
)
);
return results;
}
generateSummary(results, errors) {
return {
total: results.size + errors.size,
verified: results.size,
failed: errors.size,
validEmails: Array.from(results.entries())
.filter(([_, result]) => result.isValid).length,
highRiskEmails: Array.from(results.entries())
.filter(([_, result]) => result.riskLevel > 0.7).length
};
}
}
3. Real-time Validation with Web Workers
// emailValidationWorker.js
self.onmessage = async function(e) {
const { email, config } = e.data;
const verifier = new EmailVerificationService(config);
try {
const result = await verifier.verify(email, {
useCache: true,
cacheDuration: 3600000
});
self.postMessage({
type: 'success',
email,
result
});
} catch (error) {
self.postMessage({
type: 'error',
email,
error: error.message
});
}
};
// Usage in main thread
class RealTimeValidator {
constructor() {
this.worker = new Worker('emailValidationWorker.js');
this.callbacks = new Map();
this.worker.onmessage = (e) => {
const { type, email, result, error } = e.data;
const callback = this.callbacks.get(email);
if (callback) {
callback(type === 'success' ? result : error);
this.callbacks.delete(email);
}
};
}
validate(email) {
return new Promise((resolve, reject) => {
this.callbacks.set(email, (resultOrError) => {
if (resultOrError instanceof Error) {
reject(resultOrError);
} else {
resolve(resultOrError);
}
});
this.worker.postMessage({
email,
config: {
apiKey: process.env.MAIL7_API_KEY,
rateLimit: 100
}
});
});
}
}
Security and Compliance
1. GDPR Compliance
// GDPRCompliantVerifier.js
class GDPRCompliantVerifier {
constructor(config) {
this.verifier = new EmailVerificationService(config);
this.dataRetentionPeriod = config.dataRetentionPeriod || 30 * 24 * 60 * 60 * 1000; // 30 days
this.verificationLog = new Map();
}
async verify(email, purpose) {
// Log verification attempt
this.logVerification(email, purpose);
// Perform verification
const result = await this.verifier.verify(email);
// Store minimal necessary data
const gdprCompliantResult = this.sanitizeResult(result);
// Schedule data deletion
this.scheduleDataDeletion(email);
return gdprCompliantResult;
}
logVerification(email, purpose) {
this.verificationLog.set(email, {
timestamp: new Date(),
purpose,
ipAddress: this.anonymizeIP(request.ip)
});
}
sanitizeResult(result) {
// Remove unnecessary personal data
const { isValid, riskLevel, recommendations } = result;
return { isValid, riskLevel, recommendations };
}
scheduleDataDeletion(email) {
setTimeout(() => {
this.verificationLog.delete(email);
}, this.dataRetentionPeriod);
}
anonymizeIP(ip) {
// Implement IP anonymization
return ip.replace(/\d+$/, '0');
}
async exportVerificationLog() {
// Export for data subject access requests
return Array.from(this.verificationLog.entries())
.map(([email, data]) => ({
email,
verificationDate: data.timestamp,
purpose: data.purpose
}));
}
}
2. Rate Limiting and Abuse Prevention
// RateLimiter.js
class RateLimiter {
constructor(config) {
this.windowMs = config.windowMs || 60000;
this.maxRequests = config.maxRequests || 100;
this.requests = new Map();
}
async checkLimit(identifier) {
const now = Date.now();
const windowStart = now - this.windowMs;
// Clean up old requests
this.requests.forEach((timestamps, key) => {
this.requests.set(key,
timestamps.filter(time => time > windowStart));
});
// Get or initialize request timestamps
const timestamps = this.requests.get(identifier) || [];
// Check if limit exceeded
if (timestamps.length >= this.maxRequests) {
throw new Error('Rate limit exceeded');
}
// Record new request
timestamps.push(now);
this.requests.set(identifier, timestamps);
return {
remaining: this.maxRequests - timestamps.length,
reset: Math.ceil((windowStart + this.windowMs - now) / 1000)
};
}
}
3. Audit Logging
// AuditLogger.js
class AuditLogger {
constructor(config) {
this.storage = config.storage;
this.retentionDays = config.retentionDays || 90;
}
async logVerification(data) {
const logEntry = {
timestamp: new Date(),
email: data.email,
result: data.result,
clientId: data.clientId,
ipAddress: this.anonymizeIP(data.ipAddress),
userAgent: data.userAgent
};
await this.storage.store(logEntry);
await this.cleanupOldLogs();
}
async searchLogs(criteria) {
return await this.storage.query(criteria);
}
async generateReport(startDate, endDate) {
const logs = await this.storage.query({
timestamp: {
$gte: startDate,
$lte: endDate
}
});
return {
totalVerifications: logs.length,
successRate: this.calculateSuccessRate(logs),
riskDistribution: this.analyzeRiskLevels(logs),
topDomains: this.getTopDomains(logs)
};
}
async cleanupOldLogs() {
const cutoff = new Date();
cutoff.setDate(cutoff.getDate() - this.retentionDays);
await this.storage.delete({
timestamp: { $lt: cutoff }
});
}
}
Best Practices and Guidelines
1. Verification Strategy
- Implement multi-level verification
- Use caching for frequently verified domains
- Implement proper error handling and retries
- Monitor verification performance and success rates
2. Security Measures
- Implement rate limiting per client/IP
- Use secure API endpoints (HTTPS)
- Rotate API keys regularly
- Monitor for abuse patterns
3. Data Privacy
- Comply with GDPR and other privacy regulations
- Implement data retention policies
- Provide transparency about data usage
- Support data subject access requests
4. Performance Optimization
- Use batch processing for large datasets
- Implement caching strategies
- Optimize network requests
- Monitor and optimize resource usage
Integration Examples
1. React Form Integration
// EmailVerificationField.jsx
const EmailVerificationField = ({ onChange }) => {
const [email, setEmail] = useState('');
const [status, setStatus] = useState('idle');
const [error, setError] = useState(null);
const validator = useRef(new RealTimeValidator());
const handleChange = async (e) => {
const newEmail = e.target.value;
setEmail(newEmail);
setStatus('validating');
try {
const result = await validator.current.validate(newEmail);
setStatus(result.isValid ? 'valid' : 'invalid');
setError(result.recommendations?.join(', '));
onChange(newEmail, result);
} catch (error) {
setStatus('error');
setError(error.message);
}
};
return (
{error && {error}}
);
};
2. Node.js API Integration
// verificationRouter.js
const router = express.Router();
const verifier = new EmailVerificationService(config);
const rateLimiter = new RateLimiter({
windowMs: 15 * 60 * 1000,
maxRequests: 100
});
router.post('/verify', async (req, res) => {
try {
// Check rate limit
await rateLimiter.checkLimit(req.ip);
const { email } = req.body;
const result = await verifier.verify(email, {
useCache: true,
cacheDuration: 3600000
});
res.json({
success: true,
result
});
} catch (error) {
res.status(error.status || 500).json({
success: false,
error: error.message
});
}
});
Common Use Cases
- User Registration: Validate emails during signup
- Data Cleaning: Verify existing email databases
- Marketing Lists: Clean email marketing lists
- Form Validation: Real-time email field validation
Debugging Tips
- Response Codes: Understand verification response codes
- Error Handling: Implement comprehensive error handling
- Logging: Enable detailed verification logs
- Testing: Use Mail7's verification test suite
Start Email Verification Testing
Implement robust email verification in your applications with Mail7's reliable verification platform.