Skip to content

Instantly share code, notes, and snippets.

@fizz
Created December 11, 2017 21:04
Show Gist options
  • Save fizz/4355d5023d3e05fd7e5197a1fca8f292 to your computer and use it in GitHub Desktop.
Save fizz/4355d5023d3e05fd7e5197a1fca8f292 to your computer and use it in GitHub Desktop.
Clean up email address typos using kicksend/mailcheck + mailgun validator API
var prompt = require('prompt');
var mailgun = require('mailgun-validator')('YOUR_API_KEY');
var kicksend = require('mailcheck');
var mongo = require('mongoskin');
var db = mongo.db('localhost:27017/customers?autoreconnect');
var async = require('async');
var domains = [
/* Default domains included */
"aol.com", "att.net", "comcast.net", "facebook.com", "gmail.com", "gmx.com", "googlemail.com",
"google.com", "hotmail.com", "hotmail.co.uk", "mac.com", "me.com", "mail.com", "msn.com",
"live.com", "sbcglobal.net", "verizon.net", "yahoo.com", "yahoo.co.uk",
/* Other global domains */
"email.com", "games.com" /* AOL */, "gmx.net", "hush.com", "hushmail.com", "inbox.com",
"lavabit.com", "love.com" /* AOL */, "pobox.com", "rocketmail.com" /* Yahoo */,
"safe-mail.net", "wow.com" /* AOL */, "ygm.com" /* AOL */, "ymail.com" /* Yahoo */, "zoho.com",
/* United States ISP domains */
"bellsouth.net", "charter.net", "cox.net", "earthlink.net", "juno.com",
/* British ISP domains */
"btinternet.com", "virginmedia.com", "blueyonder.co.uk", "freeserve.co.uk", "live.co.uk",
"ntlworld.com", "o2.co.uk", "orange.net", "sky.com", "talktalk.co.uk", "tiscali.co.uk",
"virgin.net", "wanadoo.co.uk", "bt.com",
/* Chinese ISP domains */
"sina.com", "qq.com",
/* French ISP domains */
"hotmail.fr", "live.fr", "laposte.net", "yahoo.fr", "wanadoo.fr", "orange.fr", "gmx.fr", "sfr.fr", "neuf.fr", "free.fr",
/* German ISP domains */
"gmx.de", "hotmail.de", "live.de", "online.de", "t-online.de" /* T-Mobile */, "web.de", "yahoo.de",
/* Russian ISP domains */
"mail.ru", "rambler.ru", "yandex.ru",
/* Belgian ISP domains */
"hotmail.be", "live.be", "skynet.be", "voo.be", "tvcablenet.be",
/* Argentinian ISP domains */
"hotmail.com.ar", "live.com.ar", "yahoo.com.ar", "fibertel.com.ar", "speedy.com.ar", "arnet.com.ar",
/* Domains used in Mexico */
'hotmail.com', 'gmail.com', 'yahoo.com.mx', 'live.com.mx', 'yahoo.com', 'hotmail.es', 'live.com', 'hotmail.com.mx', 'prodigy.net.mx', 'msn.com',
'twc.com', 'gm.com', 'cs.com', 'q.com', 'aon.at', 'att.com', 'prodigy.net', 'wowway.com'
];
var tlds = ["co.uk", "com", "net", "org", "info", "edu", "gov", "mil", 'com.br', 'co.za', 'ie', 'us', 'cc', 'rr.com', 'com.au', 'ca', 'us.com', 'net.nz', 'nl', 'com.au', 'biz', 'co.nz', 'ms', 'com.my', 'dk', 'bm', 'ch', 'net.au', 'mn', 'com.ph', 'be', 'in.gov', 'es', 'com.bh', 'pt', 'on.ca', 'tw', 'com.vn', 'tv', 'co.sz', 'af.mil', 'com.mx', 'se'];
var query = {cache: true, cachetime: 600};
var kicksendSuggest = function(err, ret){
if(err) {
console.log(err);
process.exit();
}
ret.forEach(function(r){
if(bounce){
kicksend.run({
email: r.email,
domains: domains,
topLevelDomains: tlds,
suggested: function(s){
console.log(r.email + ' to ' + s.full);
prompt.get('OK?', function(err, ret){
if(!err){
if(ret==='y'){
r.email = s.full;
db.getresponse.insert(r);
} else {
prompt.get('Try Mailgun?', function(err, ret){
if(!err){
if(ret==='y'){
mailgun.validate(r.email, function(err, ret){
if(!err){
if(!ret.is_valid){
if(ret.did_you_mean){
console.log(ret.did_you_mean);
prompt.get('OK?', function(err, ret){
if(!err){
if(ret==='y'){
r.email = ret.did_you_mean;
db.getresponse.insert(r);
}
}
});
}
}
}
});
}
}
});
}
}
});
}
});
}
});
};
var okfine = function(r, cb) {
process.nextTick(cb);
};
var acceptSuggestion = function(s, r, cb) {
r.original_email = r.email;
r.email = s;
db.collection('unsafe_openers').removeById(r._id, function(e, item){
db.collection('rescued').insert(r, function(e, item){
okfine(r, cb);
});
});
};
var ignore = function(r, cb) {
db.collection('unsafe_openers').removeById(r._id, function(e, item) {
db.collection('ignored').insert(r, function(e, item){
okfine(r, cb);
});
});
};
var tryMailgun = function(r, cb) {
okfine(r, cb);
};
var suggestMailgun = function(r, cb) {
ignore(r, cb);
};
var tryKicksend = function(r, cb){
kicksend.run({
email: r.email,
domains: domains,
topLevelDomains: tlds,
suggested: function(s){
console.log('Kicksend suggests: ' + s.full + ' accept? (y/n)');
ask('yesno', r, function(r, cb){acceptSuggestion(s.full,r,cb);}, suggestMailgun, cb);
},
empty: function() {
console.log('Kicksend came up empty.');
suggestMailgun(r, cb);
}
});
};
var checkContacts = function(e, r) {
async.eachSeries(r, function(r, cb){
bounce = 0;
r.actions.forEach(function(a){
if(a.actionType==='Bounce'){
bounce += 1;
}
});
if(bounce>0){
console.log(r.email + ' has bounced ' + bounce + ' times.' );
tryKicksend(r, cb);
} else {
ignore(r, cb);
}
});
};
prompt.start();
var ask = function(q, r, yes, no, cb){
prompt.get(q, function(e, resp){
if(e){
process.exit();
}
if(resp.yesno==='y'){
yes(r, cb);
} else if(resp.yesno==='n') {
no(r, cb);
} else if(resp.yesno==='q') {
process.exit();
} else {
no(r, cb);
}
});
};
db.collection('unsafe_openers').find().toArray(function(e, contacts){
checkContacts(null, contacts);
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment