├── index.js ├── package.json └── readme.md /index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const dns = require('dns'); 4 | const net = require('net'); 5 | 6 | const email = process.argv[2]; 7 | const domain = email && email.split('@', 2)[1]; 8 | 9 | if (!domain) { 10 | console.error(`Invalid email: ${email}`); 11 | process.exit(1); 12 | } 13 | 14 | promisify(dns.resolveMx)(domain) 15 | .then(addresses => 16 | addresses.reduce((best, next) => best.priority > next.priority ? best : next).exchange 17 | ) 18 | .then(mx => net.connect(25, mx)) 19 | .then(socket => new Promise((resolve, reject) => { 20 | socket.setEncoding('utf-8'); 21 | socket.on('error', reject); 22 | 23 | socket.once('data', data => { 24 | expect(data, 220, `Invalid response: ${data}`); 25 | 26 | resolve(send(socket, `helo hi`) 27 | .then(() => send(socket, `mail from: <${email}>`)) 28 | .then(() => send(socket, `rcpt to: <${email}>`)) 29 | .then(data => expect(data, 250, `Unknown email: ${email}`)) 30 | .then(() => send(socket, 'quit')) 31 | ); 32 | }); 33 | })) 34 | .then(() => console.log(`Valid email: ${email}`)) 35 | .catch(error => { 36 | console.error(error.message); 37 | process.exit(1); 38 | }); 39 | 40 | function promisify(callback, context) { 41 | return function(...args) { 42 | return new Promise((resolve, reject) => { 43 | const func = context ? callback.bind(context) : callback; 44 | 45 | func(...args, (err, ...results) => { 46 | if (err) { 47 | return reject(err); 48 | } 49 | 50 | if (results.length <= 1) { 51 | return resolve(results[0]); 52 | } 53 | 54 | resolve(results); 55 | }); 56 | }); 57 | }; 58 | } 59 | 60 | function expect(data, code, message) { 61 | if (!data.startsWith(code)) { 62 | throw new Error(message); 63 | } 64 | } 65 | 66 | function send(socket, message) { 67 | return new Promise(resolve => { 68 | socket.once('data', resolve); 69 | socket.write(`${message}\r\n`); 70 | }); 71 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "verify-email", 3 | "version": "1.0.0", 4 | "description": "Verify that an email address actually exist using SMTP.", 5 | "main": "index.js", 6 | "bin": "index.js", 7 | "scripts": { 8 | "test": "echo \"Error: no test specified\" && exit 1" 9 | }, 10 | "author": "Jean Dupouy ", 11 | "repository": "izeau/verify-email", 12 | "license": "MIT" 13 | } 14 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # verify-email 2 | 3 | Verify that an email address actually exist using SMTP. 4 | 5 | ## Purpose 6 | 7 | An email address like `foo@example.com` is valid but doesn’t actually exist. This tool is used to check against the SMTP server if an address is not only valid, but also exists. It doesn’t use any external dependency. 8 | 9 | ## Usage 10 | 11 | ``` 12 | npm i -g verify-email 13 | verify-email foo@example.com 14 | ``` 15 | 16 | The exit code will be `0` if the email exists, and `1` if an error happens. 17 | 18 | ## TODO 19 | 20 | * Unit tests 21 | * Fast invalid email detection using custom rules for major email providers (Gmail, Yahoo, etc.) 22 | * Library 23 | --------------------------------------------------------------------------------