...

View Full Version : Email Address Validation



MRushton
08-29-2010, 11:01 PM
To be used in PHP versions which do not have the native function filter_var().


/*
* Copyright Michael Rushton 2009-10
* http://squiloople.com/
* Feel free to use and redistribute this code. But please keep this copyright notice.
*/

final class EmailAddressValidator {

private $email_address;

private $dot_atom = true;
private $strict_atom = true;
private $quoted_string = false;
private $obsolete_syntax = false;
private $domain_name = true;
private $strict_domain = true;
private $international = false;
private $domain_literal = false;

private function __construct($email_address, $strict) {

$this->email_address = $email_address;

if (!$strict) {
$this->SetStrict(false);
}

}

public static function SetEmailAddress($email_address, $strict = true) {
return new self($email_address, $strict);
}

public function SetStrict($strict = true) {

$this->SetStrictAtom($strict);
$this->SetQuotedString(!$strict);
$this->SetObsoleteSyntax(!$strict);
$this->SetStrictDomain($strict);
$this->SetInternational(!$strict);
$this->SetDomainLiteral(!$strict);

return $this;

}

public function SetDotAtom($allow = true) {

$this->dot_atom = $allow;

return $this;

}

public function SetStrictAtom($allow = true) {

$this->strict_atom = $allow;

return $this;

}

public function SetQuotedString($allow = true) {

$this->quoted_string = $allow;

return $this;

}

public function SetObsoleteSyntax($allow = true) {

$this->obsolete_syntax = $allow;

return $this;

}

public function SetDomainName($allow = true) {

$this->domain_name = $allow;

return $this;

}

public function SetStrictDomain($allow = true) {

$this->strict_domain = $allow;

return $this;

}

public function SetInternational($allow = true) {

$this->international = $allow;

return $this;

}

public function SetDomainLiteral($allow = true) {

$this->domain_literal = $allow;

return $this;

}

public function Validate() {

$atom = $this->strict_atom ? 'a-z0-9_-' : '\x21\x23-\x27\x2A\x2B\x2D\x2F-\x39\x3D\x3F\x5E-\x7E';

$dot_atom = '(?!.{65,}@)[' . $atom . ']+(?:\.[' . $atom . ']+)*';

$quoted_content = $this->obsolete_syntax ? '\x01-\x08\x0B\x0C\x0E-\x1F\x21\x23-\x5B\x5D-\x7F' : '\x21\x23-\x5B\x5D-\x7E';

$quoted_pair = $this->obsolete_syntax ? '\x00-\x7F' : '\x09\x20-\x7E';

$quoted_string = '\x22(?:[' . $quoted_content . ']|(?:\x5C[' . $quoted_pair . '])){0,64}\x22';

$obsolete_syntax = '(?!(?:(?:\x22?\x5C[\x00-\x7E]\x22?)|(?:\x22?[^\x5C\x22]\x22?)){65,}@)(?:(?:[' . $atom . ']+)|(?:' . $quoted_string . '))(?:\.(?:(?:[' . $atom . ']+)|(?:' . $quoted_string . ')))*';

$minimum = $this->strict_domain ? 1 : 0;

$international = $this->international ? '(?:xn--)?' : '';

$domain_name = '(?!.*[^.]{64,})(?:' . $international . '[a-z0-9]+(?:-[a-z0-9]+)*\.){' . $minimum . ',126}' . $international . '[a-z0-9]+(?:-[a-z0-9]+)*';

$ipv6_full = '[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){7}';

$ipv6_comp = '(?!(?:.*[a-f0-9][:\]]){7,})(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,5})?::(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,5})?';

$ipv6 = '(?:(?:' . $ipv6_full . ')|(?:' . $ipv6_comp . '))';

$ipv6v4_full = '[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){5}:';

$ipv6v4_comp = '(?!(?:.*[a-f0-9]:){5,})(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,3})?::(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,3}:)?';

$ipv6v4 = '(?:(?:' . $ipv6v4_full . ')|(?:' . $ipv6v4_comp . '))';

$ipv4 = '(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(?:\.(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}';

$domain_literal = '\[(?:(?:IPv6:' . $ipv6 . ')|(?:(?:IPv6:' . $ipv6v4 . ')?' . $ipv4 . '))\]';

switch (true) {

case ($this->obsolete_syntax):
$local_part = $obsolete_syntax;
break;
case ($this->dot_atom && $this->quoted_string):
$local_part = '(?:(?:' . $dot_atom . ')|(?:' . $quoted_string . '))';
break;
case ($this->quoted_string):
$local_part = $quoted_string;
break;
default:
$local_part = $dot_atom;

}

switch (true) {

case ($this->domain_name && $this->domain_literal):
$domain = '(?:(?:' . $domain_name . ')|(?:' . $domain_literal . '))';
break;
case ($this->domain_literal):
$domain = $domain_literal;
break;
default:
$domain = $domain_name;

}

return preg_match('/^(?!(?:(?:\x22?\x5C[\x00-\x7E]\x22?)|(?:\x22?[^\x5C\x22]\x22?)){255,})' . $local_part . '@' . $domain . '$/i', $this->email_address);

}

}

Examples:




// Returns true

SetEmailAddress('michael@example.com')->Validate();

// Returns false

SetEmailAddress('"michael"@example.com')->Validate();

// Returns true

SetEmailAddress('"michael"@example.com')->SetQuotedString()->Validate();

// Returns true

SetEmailAddress('"michael"@[IPv6:FFFF:FFFF::255.255.255.255]', false)->Validate();

// Returns true

SetEmailAddress('"my".name."is".!!!@example.xn--fiqs8s')->SetObsoleteSyntax()->SetInternational()->Validate();

// Returns true

SetEmailAddress('a@b')->SetStrictDomain(false)->Validate();

saudzforum
09-01-2010, 05:56 AM
Very nice script.

wildreason
09-01-2010, 06:56 AM
Pretty hardcore dude. Why did you write it?

MRushton
09-01-2010, 08:10 AM
I wrote it initially because I was applying for a position as a trainee PHP developer (which I didn't get) and was asked in an online application-exam how I'd go about validating an email address using regular expressions. I'd never actually used regex before so had to teach myself in a few days. I thought it would be more genuine to start from scratch rather than to simply copy some other code someone had written (although it took me a few more weeks to get it to level it's at now).

And now it turns out that PHP's filter_var() function, as of 5.3.3, uses my regex as its email validation filter (with one minor change; not allowing for single-label domain names -- something which actually should be allowed).

So I guess sometimes it is better to reinvent the wheel, despite what a lot of people seem to say (which is why I'm also pushing for them to use my other regex to validate for IP addresses -- something the current native function doesn't quite do perfectly). ;)

MRushton
09-01-2010, 08:48 PM
So, I've optimized it slightly to reduce the length of the regular expression, but it appears I cannot edit my original post. You can get the newest version from my Email Address Validation (http://squiloople.com/2009/12/20/email-address-validation/) article (which also breaks down piece-by-piece how to validate an email address).



EZ Archive Ads Plugin for vBulletin Copyright 2006 Computer Help Forum