email-validation
Version:
Email validation that follows the specs.
74 lines (69 loc) • 4.26 kB
JavaScript
var util = require('util');
var email = module.exports = function() {};
var strToObj = function(str) {
var obj = {};
for(var i = 0; i < str.length; i++) {
obj[str[i]] = str.charCodeAt(i);
}
return obj;
};
var chars = strToObj("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!#$%&'*+-/=?^_`{|}~.");
var specialchars = strToObj("\\\"(),:;<>@[\] ");
var escapers = strToObj('\\"');
var hostchars = strToObj("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-");
email.parse = function(address, dothrow, callback) {
callback = (typeof callback == 'undefined' && typeof dothrow == 'function') ? dothrow : null;
var userland = true;
var quotation = false;
var escaped = false;
var _user = "", _domain = "";
var hostisip = false;
var hoststartpos = 0;
try {
if(address.length >= 254) throw util.format("[Error parsing email address: address is longer than 253, actual]", address.length);
for(var i = 0; i < address.length; i++) {
//console.log(i, address[i])
if(userland) {
if(address[i] == '"' && i == 0) { quotation = true; _user += address[i]; continue; }
if(typeof chars[address[i]] != 'undefined') { //needed I'm sure.
_user += address[i]; continue;
} else if(typeof specialchars[address[i]] != 'undefined') {
if(quotation) {
if(!escaped && address[i] == "\\") { escaped = true; _user += address[i]; continue; }
if(!escaped && address[i] == '"' && address[i+1] == "@") { userland = false; hoststartpos = i+2; _user += address[i]; i+=1; continue; }
if(escaped && typeof escapers[address[i]] != 'undefined') { escaped = false; _user += address[i]; continue; }
if(!escaped && typeof escapers[address[i]] != 'undefined') throw util.format("[Error parsing email address: invalid use of %s (pos: %s)]", address[i], i, address);
} else if(address[i] == "@" && !quotation) {
userland = false;
hoststartpos = i+1;
continue;
} else {
throw util.format("[Error parsing email address: special character '%s' (pos: %s) used without quotation marks]", address[i], i);
}
} else {
throw util.format("[Error parsing email address: character '%s' (pos: %s) is not allowed in an email address user space.]", address[i], i, address);
}
_user += address[i];
} else { //parsing hostname. Probably could be done with regex.
if(i == hoststartpos && address[i] == '[') { hostisip = true; hostchars['['] = '['; hostchars[']'] = ']'; hostchars[':'] = ':'; _domain += address[i]; continue; }
if(typeof hostchars[address[i]] == 'undefined') throw util.format("[Error parsing email address: character '%s' (pos: %s) is not allowed in the hostname section]", address[i], i);
if(i >= hoststartpos && /[@\.]/.test(address[i - 1]) && !/[a-z0-9]/i.test(address[i])) throw util.format("[Error parsing email address: All domain segments must start with a letter or number, never a symbol like '%s'.")
_domain += address[i];
}
}
if(_domain === '') throw util.format("[Error parseing email address: no domain part]", address);
if(hostisip && !require('net').isIP(address.substring(hoststartpos+1,address.length-1))) throw util.format("[Error parsing email address: invalid IP address]");
if(hostisip && address[address.length-1] != "]") throw util.format("[Error parsing email address: IP address notation must end with a ']']");
if(!hostisip && (/^.+@([a-z0-9]{64,}(|\.))/i).test(address)) throw util.format("[Error parsing email address: hostname has elements greater than 63 characters]");
if(userland) throw util.format("[Error parsing email address: quotation mark not closed]" , address);
} catch (err) {
if(callback) callback(err);
if(typeof dothrow != 'undefined' && typeof dothrow != 'function') throw err;
return false; //redundant?
}
if(callback) callback(null, {user: _user, domain: _domain});
else return {user: _user, domain: _domain};
}
email.valid = function(address, dothrow, callback) {
return !!email.parse(address, dothrow, callback);
}