Skip to content

Instantly share code, notes, and snippets.

@antonpirker
Created October 26, 2016 10:12
Show Gist options
  • Save antonpirker/56a9aaca2321d8fec78886ad186e742f to your computer and use it in GitHub Desktop.
Save antonpirker/56a9aaca2321d8fec78886ad186e742f to your computer and use it in GitHub Desktop.
<html>
<head>
<script>
// Based on RFC 2822 section 3.2.4 / RFC 5322 section 3.2.3, these
// characters are permitted in email addresses (not taking into
// account internationalization):
var ATEXT = "a-zA-Z0-9_!#\\$%&\\'\\*\\+\\-\/=\\?\\^`\\{\\|\\}~";
// A "dot atom text", per RFC 2822 3.2.4:
var DOT_ATOM_TEXT = '[' + ATEXT + ']+(?:\\.[' + ATEXT + ']+)*';
// RFC 6531 section 3.3 extends the allowed characters in internationalized
// addresses to also include three specific ranges of UTF8 defined in
// RFC3629 section 4, which appear to be the Unicode code points from
// U+0080 to U+10FFFF.
var ATEXT_UTF8 = ATEXT + '\u{0080}-\u{0010FFFF}';
var DOT_ATOM_TEXT_UTF8 = '[' + ATEXT_UTF8 + ']+(?:\\.[' + ATEXT_UTF8 + ']+)*';
// The domain part of the email address, after IDNA (ASCII) encoding,
// must also satisfy the requirements of RFC 952/RFC 1123 which restrict
// the allowed characters of hostnames further. The hyphen cannot be at
// the beginning or end of a *dot-atom component* of a hostname either.
var ATEXT_HOSTNAME = '(?:(?:[a-zA-Z0-9][a-zA-Z0-9\\-]*)?[a-zA-Z0-9])';
function validateEmailLocalPart(localPart) {
if(!localPart || localPart.length == 0) {
throw 'There must be something before the @-sign.';
}
// RFC 5321 4.5.3.1.1
if(localPart.length > 64) {
throw 'The email address is too long before the @-sign.';
}
// Check the local part against the regular expression for the older ASCII requirements.
var re = new RegExp('^' + DOT_ATOM_TEXT + '$');
var found = null;
found = localPart.match(re);
if(!found) {
var re = new RegExp('^' + DOT_ATOM_TEXT_UTF8 + '$');
var found1 = null;
found1 = localPart.match(re);
if(!found1) {
var badChars = '';
var re1 = new RegExp('^['+ATEXT_UTF8+']');
for(var i=0; i<localPart.length; i++) {
var c = localPart[i];
var found2 = null;
found2 = c.match(re1);
if(!found2) {
badChars += c;
}
}
throw 'The email address contains invalid characters before the @-sign: "' + badChars + '"';
}
}
return localPart;
}
function validateEmailDomainPart(domainPart) {
if(!domainPart || domainPart.length == 0) {
throw 'There must be something after the @-sign.';
}
if(domainPart.endsWith('.')) {
throw 'An email address cannot end with a period.';
}
if(domainPart.startsWith('.')) {
throw 'An email address cannot have a period immediately after the @-sign.';
}
if(domainPart.indexOf('..') != -1) {
throw 'An email address cannot have two periods in a row.';
}
if(domainPart.length > 255) {
throw 'The email address is too long after the @-sign.';
}
// A "dot atom text", per RFC 2822 3.2.4, but using the restricted
// characters allowed in a hostname (see ATEXT_HOSTNAME above).
DOT_ATOM_TEXT_2 = ATEXT_HOSTNAME + '(?:\.' + ATEXT_HOSTNAME + ')*'
// Check the regular expression. This is probably entirely redundant
// with idna.decode, which also checks this format.
var re = new RegExp('^' + DOT_ATOM_TEXT_2 + '$');
var found = domainPart.match(re);
if(!found) {
throw 'The email address contains invalid characters after the @-sign.';
}
// All publicly deliverable addresses have domain named with at least
// one period. We also know that all TLDs end with a letter.
if(domainPart.indexOf('.') == -1) {
throw 'The domain name ' + domainPart + ' is not valid. It should have a period.';
}
var re = new RegExp('[A-Za-z]$');
var found = domainPart.search(re);
if(!found) {
throw 'The domain name ' + domainPart + ' is not valid. It is not within a valid top-level domain.';
}
return domainPart;
}
function isValidEmail(email) {
if(!email) {
return false;
}
var isValid = true;
var error = '';
var parts = email.split('@');
if(parts.length != 2) {
isValid = false;
error = 'The email address is not valid. It must have exactly one @-sign.';
return isValid;
}
var ret = [];
ret['local'] = validateEmailLocalPart(parts[0]);
ret['domain'] = validateEmailDomainPart(parts[1]);
return isValid;
}
function testEmails() {
var emails = [
'anton pirker@bla.com',
'nijole.s@hotmail.de',
'anton@ignaz.at',
'ööö@bbb.com',
'bbb@ööö.com',
'anton pirker@bla.com',
'anton@@anton.com',
'bla.@bla.com',
'adsf',
'.@.',
'.@.com',
'bla@.com',
'..@bla.com',
'bla@bla..com',
'',
' ',
'_!#$%&\'*+-/=?^`{|}~@bla.com',
'@bla.com',
]
for(var i=0; i<emails.length; i++) {
console.log('"' + emails[i] + '"');
var res = '';
try {
res = isValidEmail(emails[i]);
if(res) {
res = '[true]';
}
} catch(ex) {
res = '[false] ' + ex;
}
console.log('---> ', res);
}
}
testEmails();
</script>
</head>
<body>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment