Master real-time email validation with SMTP verification. Learn advanced protocols, handle complex scenarios like greylisting, and achieve 99.9% accuracy with our comprehensive technical guide.
SMTP (Simple Mail Transfer Protocol) verification is the most accurate method for validating email addresses. It connects directly to the recipient's mail server to verify if an email address exists and can receive messages, all without sending an actual email.
Instantly verify email existence by communicating with actual mail servers
Verification happens without sending messages, protecting your reputation
Achieve 99.9% accuracy by validating directly with mail servers
Direct verification with actual mail servers provides the most reliable results
Get immediate feedback on email validity in under 500ms
Identify domains that accept all emails regardless of validity
Prevent hard bounces and protect your sender reputation
Avoid wasted sends to non-existent email addresses
Maintain clean email lists for better engagement rates
Query DNS for mail server records
Connect to mail server on port 25
Verify email without sending
Query DNS to find Mail Exchange (MX) records for the domain. These records specify which servers handle email for the domain and their priority levels.
# Example MX lookup for gmail.com $ dig MX gmail.com gmail.com. 3600 IN MX 5 gmail-smtp-in.l.google.com. gmail.com. 3600 IN MX 10 alt1.gmail-smtp-in.l.google.com. gmail.com. 3600 IN MX 20 alt2.gmail-smtp-in.l.google.com. gmail.com. 3600 IN MX 30 alt3.gmail-smtp-in.l.google.com. gmail.com. 3600 IN MX 40 alt4.gmail-smtp-in.l.google.com.
Establish a TCP connection to the highest priority MX server on port 25 and perform the SMTP protocol handshake to verify the email address.
# SMTP conversation example C: HELO email-check.app S: 250 Hello email-check.app C: MAIL FROM:<noreply@email-check.app> S: 250 2.1.0 Ok C: RCPT TO:<user@example.com> S: 250 2.1.5 Ok # ✓ Email exists # OR S: 550 5.1.1 No such user # ✗ Email doesn't exist C: QUIT S: 221 2.0.0 Bye
Analyze the SMTP response codes to determine the email address validity and handle various scenarios like temporary failures or verification issues.
Email address exists and can receive mail
Email address doesn't exist on this server
Temporary failure, retry later
| Code | Category | Meaning | Action Required | Status |
|---|---|---|---|---|
| 250 | Success | Requested mail action OK, completed | Mark as valid | Valid |
| 421 | Temporary | Service not available, closing connection | Retry later with backoff | Retry |
| 450 | Temporary | Mailbox unavailable (e.g., greylisting) | Retry after delay | Retry |
| 550 | Permanent | No such user here / Mailbox not found | Mark as invalid | Invalid |
| 551 | Permanent | User not local; please try forward-path | Mark as invalid | Invalid |
| 553 | Permanent | Mailbox name syntax incorrect | Mark as invalid | Invalid |
Servers temporarily reject connections from unknown senders as an anti-spam measure.
450 4.7.1 Greylisted, please try again laterDomains configured to accept all email addresses, making individual validation impossible.
250 OK (for any@domain.com)Aggressive spam protection can block legitimate verification attempts.
Connection refused (port 25)Use our REST API for easy SMTP verification integration. Perfect for web applications and batch processing.
// Single email verification with SMTP
const params = new URLSearchParams({
email: 'user@example.com',
verifyMx: true,
verifySmtp: true,
detectName: true
});
const response = await fetch('https://api.email-check.app/v1-get-email-details?' + params, {
headers: {
'accept': 'application/json',
'x-api-key': 'YOUR_API_KEY'
}
});
const result = await response.json();
console.log(result);
// {
// "email": "user@example.com",
// "validMx": true,
// "validSmtp": true,
// "validFormat": true,
// "isDisposable": false,
// "isFree": true,
// "detectedName": {"firstName": "John", "lastName": "Doe", "confidence": 0.85},
// "domainAge": {"domain": "example.com", "ageInDays": 3650},
// "domainRegistration": {"isRegistered": true, "registrar": "Example Inc."}
// }import requests
import json
# SMTP verification with Python
params = {
"email": "user@example.com",
"verifyMx": True,
"verifySmtp": True,
"detectName": True
}
headers = {
"accept": "application/json",
"x-api-key": "YOUR_API_KEY"
}
response = requests.get("https://api.email-check.app/v1-get-email-details", params=params, headers=headers)
result = response.json()
print(f"Email: {result['email']}")
print(f"Valid Format: {result['validFormat']}")
print(f"Valid MX: {result['validMx']}")
print(f"Valid SMTP: {result['validSmtp']}")
print(f"Disposable: {result['isDisposable']}")
print(f"Free Email: {result['isFree']}")Process multiple emails efficiently by making parallel API calls for optimal performance.
// Multiple email verification example
const emails = [
'user1@example.com',
'user2@gmail.com',
'invalid@nonexistent.domain'
];
const verifyEmail = async (email) => {
const params = new URLSearchParams({
email: email,
verifyMx: true,
verifySmtp: true,
detectName: true
});
const response = await fetch('https://api.email-check.app/v1-get-email-details?' + params, {
headers: {
'accept': 'application/json',
'x-api-key': 'YOUR_API_KEY'
}
});
return await response.json();
};
// Process emails in parallel
const results = await Promise.all(
emails.map(email => verifyEmail(email))
);
console.log('Verification results:', results);
// [
// {
// "email": "user1@example.com",
// "validMx": true,
// "validSmtp": true,
// "validFormat": true
// },
// ...
// ];
// Filter results based on validation status
const validEmails = results.filter(result => result.validFormat && result.validMx && result.validSmtp);
const invalidEmails = results.filter(result => !result.validFormat || !result.validMx || !result.validSmtp);
console.log(`Valid emails: ${validEmails.length}`);
console.log(`Invalid emails: ${invalidEmails.length}`);Implement proper error handling for production-ready email verification.
async function verifyEmailWithRetry(email, maxRetries = 3) {
const params = new URLSearchParams({
email: email,
verifyMx: true,
verifySmtp: true,
detectName: true
});
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
const response = await fetch('https://api.email-check.app/v1-get-email-details?' + params, {
headers: {
'accept': 'application/json',
'x-api-key': 'YOUR_API_KEY'
}
});
if (!response.ok) {
if (response.status === 429) {
// Rate limited - exponential backoff
const delay = Math.pow(2, attempt) * 1000;
await new Promise(resolve => setTimeout(resolve, delay));
continue;
}
if (response.status >= 500) {
// Server error - retry
if (attempt < maxRetries) continue;
}
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
const result = await response.json();
// Handle different validation results
if (result.validFormat && result.validMx && result.validSmtp) {
return { ...result, status: 'deliverable' };
} else if (!result.validFormat) {
return { ...result, status: 'undeliverable' };
} else if (!result.validMx) {
return { ...result, status: 'risky' };
} else if (!result.validSmtp) {
return { ...result, status: 'unknown' };
} else {
return { ...result, status: 'unknown' };
}
} catch (error) {
console.error(`Attempt ${attempt} failed:`, error.message);
if (attempt === maxRetries) {
return {
email,
valid: false,
error: error.message,
status: 'error'
};
}
// Wait before retry
await new Promise(resolve => setTimeout(resolve, 1000 * attempt));
}
}
}For debugging and learning purposes, you can manually test SMTP verification using telnet or netcat.
# Step 1: Find MX record $ dig MX gmail.com +short 5 gmail-smtp-in.l.google.com. 10 alt1.gmail-smtp-in.l.google.com. # Step 2: Connect to mail server $ telnet gmail-smtp-in.l.google.com 25 Trying 173.194.76.26... Connected to gmail-smtp-in.l.google.com. Escape character is '^]'. 220 mx.google.com ESMTP h8-20020a17090a460800b00274b19a3882si12345678pjj.123 - gsmtp # Step 3: SMTP handshake HELO email-check.app 250 mx.google.com at your service # Step 4: Set sender MAIL FROM:<test@email-check.app> 250 2.1.0 OK h8-20020a17090a460800b00274b19a3882si12345678pjj.123 - gsmtp # Step 5: Test recipient (replace with actual email) RCPT TO:<existing.user@gmail.com> 250 2.1.5 OK h8-20020a17090a460800b00274b19a3882si12345678pjj.123 - gsmtp # OR for non-existent user: RCPT TO:<nonexistent.user.12345@gmail.com> 550-5.1.1 The email account that you tried to reach does not exist. # Step 6: Close connection QUIT 221 2.0.0 closing connection h8-20020a17090a460800b00274b19a3882si12345678pjj.123 - gsmtp Connection closed by foreign host.
Manual testing is great for learning but not suitable for production. Many mail servers have rate limits and may block frequent manual connections. Always use proper API services for production applications.
Get started with our powerful email verification API. Achieve 99.9% accuracy with real-time SMTP checking, disposable email detection, and enterprise-grade infrastructure.