Created
December 31, 2012 21:05
-
-
Save anonymous/4422742 to your computer and use it in GitHub Desktop.
Has a ton of jshint 1.0.0 RC errors (23), but none in jshint r12.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Mailcheck https://github.com/Kicksend/mailcheck | |
* Author | |
* Derrick Ko (@derrickko) | |
* | |
* License | |
* Copyright (c) 2012 Receivd, Inc. | |
* | |
* Licensed under the MIT License. | |
* | |
* v 1.1 | |
*/ | |
var Kicksend = { | |
mailcheck : { | |
threshold: 2, | |
defaultDomains: ["yahoo.com", "google.com", "hotmail.com", "gmail.com", "me.com", "aol.com", "mac.com", | |
"live.com", "comcast.net", "googlemail.com", "msn.com", "facebook.com", "verizon.net", "sbcglobal.net", | |
"att.net", "gmx.com", "mail.com", "ymail.com", "hotmail.co.uk", "yahoo.co.uk", "live.co.uk"], | |
defaultTopLevelDomains: ["co.uk", "com", "net", "org", "info", "edu", "gov", "mil"], | |
whitelistRegexes: [ | |
/ymail.com/, | |
/yahoo\.co\./, | |
/yahoo\.com\./, | |
/hotmail\.co\./, | |
/hotmail\.com\./ | |
], | |
run: function (opts) { | |
opts.domains = opts.domains || Kicksend.mailcheck.defaultDomains; | |
opts.topLevelDomains = opts.topLevelDomains || Kicksend.mailcheck.defaultTopLevelDomains; | |
opts.distanceFunction = opts.distanceFunction || Kicksend.sift3Distance; | |
opts.ignoreTLDs = opts.ignoreTLDs || false; | |
var result = Kicksend.mailcheck.suggest(encodeURI(opts.email), opts.domains, opts.topLevelDomains, opts.distanceFunction, opts.ignoreTLDs); | |
if (result) { | |
if (opts.suggested) { | |
opts.suggested(result); | |
} | |
} else { | |
if (opts.empty) { | |
opts.empty(); | |
} | |
} | |
}, | |
suggest: function (email, domains, topLevelDomains, distanceFunction, ignoreTLDs) { | |
email = email.toLowerCase(); | |
var emailParts = this.splitEmail(email), | |
closestDomain = this.findClosestDomain(emailParts.domain, domains, distanceFunction), | |
closestTopLevelDomain, | |
domain, | |
i, | |
r; | |
for (i = 0; i < this.whitelistRegexes.length; i += 1) { | |
r = this.whitelistRegexes[i]; | |
if (r.exec(emailParts.domain)) { | |
return false; | |
} | |
} | |
if (closestDomain) { | |
if (closestDomain !== emailParts.domain) { | |
// The email address closely matches one of the supplied domains; return a suggestion | |
return { address: emailParts.address, domain: closestDomain, full: emailParts.address + "@" + closestDomain }; | |
} | |
} else if (!ignoreTLDs) { | |
// The email address does not closely match one of the supplied domains | |
closestTopLevelDomain = this.findClosestDomain(emailParts.topLevelDomain, topLevelDomains); | |
if (emailParts.domain && closestTopLevelDomain && closestTopLevelDomain !== emailParts.topLevelDomain) { | |
// The email address may have a mispelled top-level domain; return a suggestion | |
domain = emailParts.domain; | |
closestDomain = domain.substring(0, domain.lastIndexOf(emailParts.topLevelDomain)) + closestTopLevelDomain; | |
return { address: emailParts.address, domain: closestDomain, full: emailParts.address + "@" + closestDomain }; | |
} | |
} | |
/* The email address exactly matches one of the supplied domains, does not closely | |
* match any domain and does not appear to simply have a mispelled top-level domain, | |
* or is an invalid email address; do not return a suggestion. | |
*/ | |
return false; | |
}, | |
findClosestDomain: function (domain, domains, distanceFunction) { | |
var dist, | |
minDist = 99, | |
closestDomain = null, | |
i; | |
if (!domain || !domains) { | |
return false; | |
} | |
if (!distanceFunction) { | |
distanceFunction = this.sift3Distance; | |
} | |
for (i = 0; i < domains.length; i += 1) { | |
if (domain === domains[i]) { | |
return domain; | |
} | |
dist = distanceFunction(domain, domains[i]); | |
if (dist < minDist) { | |
minDist = dist; | |
closestDomain = domains[i]; | |
} | |
} | |
if (minDist <= this.threshold && closestDomain !== null) { | |
return closestDomain; | |
} else { | |
return false; | |
} | |
}, | |
sift3Distance: function (s1, s2) { | |
var c = 0, | |
offset1 = 0, | |
offset2 = 0, | |
lcs = 0, | |
maxOffset = 5, | |
i; | |
// sift3: http://siderite.blogspot.com/2007/04/super-fast-and-accurate-string-distance.html | |
if (s1 === null || s1.length === 0) { | |
if (s2 === null || s2.length === 0) { | |
return 0; | |
} else { | |
return s2.length; | |
} | |
} | |
if (s2 === null || s2.length === 0) { | |
return s1.length; | |
} | |
while ((c + offset1 < s1.length) && (c + offset2 < s2.length)) { | |
if (s1.charAt(c + offset1) === s2.charAt(c + offset2)) { | |
lcs += 1; | |
} else { | |
offset1 = 0; | |
offset2 = 0; | |
for (i = 0; i < maxOffset; i += 1) { | |
if ((c + i < s1.length) && (s1.charAt(c + i) === s2.charAt(c))) { | |
offset1 = i; | |
break; | |
} | |
if ((c + i < s2.length) && (s1.charAt(c) === s2.charAt(c + i))) { | |
offset2 = i; | |
break; | |
} | |
} | |
} | |
c += 1; | |
} | |
return (s1.length + s2.length) / 2 - lcs; | |
}, | |
splitEmail: function (email) { | |
var parts = email.split('@'), | |
i, | |
domain, | |
domainParts, | |
tld = ''; | |
if (parts.length < 2) { | |
return false; | |
} | |
for (i = 0; i < parts.length; i += 1) { | |
if (parts[i] === '') { | |
return false; | |
} | |
} | |
domain = parts.pop(); | |
domainParts = domain.split('.'); | |
if (domainParts.length === 0) { | |
// The address does not have a top-level domain | |
return false; | |
} else if (domainParts.length === 1) { | |
// The address has only a top-level domain (valid under RFC) | |
tld = domainParts[0]; | |
} else { | |
// The address has a domain and a top-level domain | |
for (i = 1; i < domainParts.length; i += 1) { | |
tld += domainParts[i] + '.'; | |
} | |
if (domainParts.length >= 2) { | |
tld = tld.substring(0, tld.length - 1); | |
} | |
} | |
return { | |
topLevelDomain: tld, | |
domain: domain, | |
address: parts.join('@') | |
}; | |
} | |
} | |
}; | |
if (window.jQuery) { | |
(function ($) { | |
$.fn.mailcheck = function (opts) { | |
var self = this, | |
oldSuggested, | |
oldEmpty; | |
if (opts.suggested) { | |
oldSuggested = opts.suggested; | |
opts.suggested = function (result) { | |
oldSuggested(self, result); | |
}; | |
} | |
if (opts.empty) { | |
oldEmpty = opts.empty; | |
opts.empty = function () { | |
oldEmpty.call(null, self); | |
}; | |
} | |
opts.email = this.val(); | |
Kicksend.mailcheck.run(opts); | |
}; | |
}(jQuery)); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment