GitHub - yolodex-ai/reachable: Node package and cli for verifying email addresses

3 min read Original article ↗

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 reachable
  • 1: 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

  1. Syntax Validation: Checks RFC-compliant email format
  2. MX Lookup: Discovers mail servers via DNS
  3. SMTP Connection: Connects to highest priority MX server
  4. HELO/EHLO: Initiates SMTP conversation
  5. MAIL FROM: Sets sender address
  6. RCPT TO: Tests if recipient is accepted
  7. 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