email-reachable
Verify email address reachability using SMTP protocol without sending emails.
Features
- SMTP Verification: Connects to mail servers and verifies mailbox existence
- Catch-All Detection: Identifies domains that accept all email addresses
- MX Record Lookup: Discovers and prioritizes mail servers
- Syntax Validation: RFC-compliant email syntax checking
- Disposable Domain Detection: Identifies temporary email providers
- No External Services: All verification done locally via SMTP
Installation
npm install email-reachable
CLI Usage
# Basic usage npx email-reachable user@example.com # JSON output npx email-reachable user@example.com --json # Debug mode npx email-reachable user@example.com --debug # Custom timeout npx email-reachable user@example.com --timeout=15000
CLI Output
✓ user@example.com
Reachable: true
Reason: valid
Syntax Valid: true
Disposable: false
Catch-All: false
MX Records: mx1.example.com, mx2.example.com
SMTP Response: 250 OK
Duration: 1234ms
Exit Codes
0: Email is reachable1: Email is not reachable or error occurred
Library Usage
import { verifyEmail } from 'email-reachable'; const result = await verifyEmail('user@example.com'); console.log(result); // { // email: 'user@example.com', // reachable: true, // reason: 'valid', // syntax: true, // disposable: false, // catchAll: false, // mxRecords: [{ exchange: 'mx1.example.com', priority: 10 }], // smtpResponse: { code: 250, message: 'OK', command: 'RCPT TO' }, // duration: 1234 // }
Options
import { verifyEmail } from 'email-reachable'; const result = await verifyEmail('user@example.com', { timeout: 15000, // Connection timeout in ms (default: 10000) senderDomain: 'mydomain.com', // HELO domain (default: 'verify.local') senderAddress: 'verify@mydomain.com', // MAIL FROM address port: 25, // SMTP port (default: 25) debug: true, // Enable debug output });
Utility Functions
import { getMxRecords, extractDomain, extractLocalPart, isValidSyntax, isDisposableDomain, } from 'email-reachable'; // Get MX records for a domain const mxRecords = await getMxRecords('example.com'); // [{ exchange: 'mx1.example.com', priority: 10 }] // Extract domain from email const domain = extractDomain('user@example.com'); // 'example.com' // Extract local part const localPart = extractLocalPart('user@example.com'); // 'user' // Validate syntax const isValid = isValidSyntax('user@example.com'); // true // Check for disposable domain const isDisposable = isDisposableDomain('mailinator.com'); // true
Verification Result
| Field | Type | Description |
|---|---|---|
email |
string |
The email address that was verified |
reachable |
boolean |
Whether the email appears reachable |
reason |
VerificationReason |
Reason for the result |
syntax |
boolean |
Whether email syntax is valid |
disposable |
boolean |
Whether domain is a known disposable provider |
catchAll |
boolean | null |
Whether domain accepts all addresses |
mxRecords |
MxRecord[] |
Discovered MX records |
smtpResponse |
SmtpResponse |
Last SMTP response received |
duration |
number |
Verification time in milliseconds |
Verification Reasons
| Reason | Description |
|---|---|
valid |
Email appears valid and reachable |
invalid_syntax |
Email address syntax is invalid |
no_mx_records |
Domain has no MX records |
smtp_connection_failed |
Could not connect to any mail server |
mailbox_not_found |
Mail server rejected the recipient |
catch_all_domain |
Domain accepts all addresses (can't verify) |
smtp_error |
SMTP protocol error |
timeout |
Connection or command timeout |
blocked |
Mail server blocked verification attempt |
How It Works
- Syntax Validation: Checks RFC-compliant email format
- MX Lookup: Discovers mail servers via DNS
- SMTP Connection: Connects to highest priority MX server
- HELO/EHLO: Initiates SMTP conversation
- MAIL FROM: Sets sender address
- RCPT TO: Tests if recipient is accepted
- Catch-All Detection: Tests random address to detect catch-all
Limitations
- Some mail servers may block verification attempts
- Catch-all domains can't have individual addresses verified
- Greylisting may cause false negatives
- Rate limiting may apply on some servers
- Port 25 may be blocked on some networks
Requirements
- Node.js >= 18.0.0
- Port 25 outbound access (SMTP)
License
MIT