分享一个email验证类,代码如下:
<?php
/**
* EMail地址验证类
* 根据RFC5321,RFC5322,验证电子邮件地址
*/
final class EmailAddressValidator
{
/**
* 电子邮件地址验证
*
* @access private
* @var string $_emailAddress
*/
private $_emailAddress;
/**
* 是否允许带引号的字符串本地部分
*
* @access private
* @var bool $_quotedString
*/
private $_quotedString = false;
/**
* An obsolete local part
*
* @access private
* @var bool $_obsolete
*/
private $_obsolete = false;
/**
* A domain literal domain
*
* @access private
* @var bool $_domainLiteral
*/
private $_domainLiteral = false;
/**
* Comments and folding white spaces
*
* @access private
* @var bool $_cfws
*/
private $_cfws = false;
/**
* Set the email address and turn on the relevant standard if required
*
* @access public
* @param string $emailAddress
* @param integer $standard
*/
public function __construct($emailAddress, $standard = null)
{
// Set the email address
$this->_emailAddress = $emailAddress;
// Turn on the RFC 5321 standard if requested
if ($standard == 5321)
{
$this->setStandard5321();
}
// Otherwise turn on the RFC 5322 standard if requested
elseif ($standard == 5322)
{
$this->setStandard5322();
}
}
/**
* Call the constructor fluently
*
* @access public
* @static
* @param string $emailAddress
* @param null|integer $standard
* @return EmailAddressValidator
*/
public static function setEmailAddress($emailAddress, $standard = null)
{
return new self($emailAddress, $standard);
}
/**
* Validate the email address according to RFC 5321 and return itself
*
* @access public
* @param bool $allow
* @return EmailAddressValidator
*/
public function setStandard5321($allow = true)
{
// A quoted string local part is either allowed (true) or not (false)
$this->_quotedString = $allow;
// A domain literal domain is either allowed (true) or not (false)
$this->_domainLiteral = $allow;
// Return itself
return $this;
}
/**
* Validate the email address according to RFC 5322 and return itself
*
* @access public
* @param bool $allow
* @return EmailAddressValidator
*/
public function setStandard5322($allow = true)
{
// An obsolete local part is either allowed (true) or not (false)
$this->_obsolete = $allow;
// A domain literal domain is either allowed (true) or not (false)
$this->_domainLiteral = $allow;
// Comments and folding white spaces are either allowed (true) or not (false)
$this->_cfws = $allow;
// Return itself
return $this;
}
/**
* Either allow (true) or disallow (false) a quoted string local part and return itself
*
* @access public
* @param bool $allow
* @return EmailAddressValidator
*/
public function setQuotedString($allow = true)
{
// Either allow (true) or disallow (false) a quoted string local part
$this->_quotedString = $allow;
// Return itself
return $this;
}
/**
* Either allow (true) or disallow (false) an obsolete local part and return itself
*
* @access public
* @param bool $allow
* @return EmailAddressValidator
*/
public function setObsolete($allow = true)
{
// Either allow (true) or disallow (false) an obsolete local part
$this->_obsolete = $allow;
// Return itself
return $this;
}
/**
* Either allow (true) or disallow (false) a domain literal domain and return itself
*
* @access public
* @param bool $allow
* @return EmailAddressValidator
*/
public function setDomainLiteral($allow = true)
{
// Either allow (true) or disallow (false) a domain literal domain
$this->_domainLiteral = $allow;
// Return itself
return $this;
}
/**
* Either allow (true) or disallow (false) comments and folding white spaces and return itself
*
* @access public
* @param bool $allow
* @return EmailAddressValidator
*/
public function setCFWS($allow = true)
{
// Either allow (true) or disallow (false) comments and folding white spaces
$this->_cfws = $allow;
// Return itself
return $this;
}
/**
* Return the regular expression for a dot atom local part
*
* @access private
* @return string
*/
private function _getDotAtom()
{
return "([!#-'*+/-9=?^-~-]+)(?>.(?1))*";
}
/**
* Return the regular expression for a quoted string local part
*
* @access private
* @return string
*/
private function _getQuotedString()
{
return '"(?>[ !#-[]-~]|[ -~])*"';
}
/**
* Return the regular expression for an obsolete local part
*
* @access private
* @return string
*/
private function _getObsolete()
{
return '([!#-'*+/-9=?^-~-]+|"(?>'
. $this->_getFWS()
. '(?>[x01-x08x0Bx0Cx0E-!#-[]-x7F]|[x00-xFF]))*'
. $this->_getFWS()
. '")(?>'
. $this->_getCFWS()
. '.'
. $this->_getCFWS()
. '(?1))*';
}
/**
* Return the regular expression for a domain name domain
*
* @access private
* @return string
*/
private function _getDomainName()
{
return '([a-z0-9](?>[a-z0-9-]*[a-z0-9])?)(?>'
. $this->_getCFWS()
. '.'
. $this->_getCFWS()
. '(?2)){0,126}';
}
/**
* Return the regular expression for an IPv6 address
*
* @access private
* @return string
*/
private function _getIPv6()
{
return '([a-f0-9]{1,4})(?>:(?3)){7}|(?!(?:.*[a-f0-9][:]]){8,})((?3)(?>:(?3)){0,6})?::(?4)?';
}
/**
* Return the regular expression for an IPv4-mapped IPv6 address
*
* @access private
* @return string
*/
private function _getIPv6v4()
{
return '(?3)(?>:(?3)){5}:|(?!(?:.*[a-f0-9]:){6,})(?5)?::(?>((?3)(?>:(?3)){0,4}):)?';
}
/**
* Return the regular expression for an IPv4 address
*
* @access private
* @return string
*/
private function _getIPv4()
{
return '(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(?>.(?6)){3}';
}
/**
* Return the regular expression for a domain literal domain
*
* @access private
* @return string
*/
private function _getDomainLiteral()
{
return '[(?:(?>IPv6:(?>'
. $this->_getIPv6()
. '))|(?>(?>IPv6:(?>'
. $this->_getIPv6v4()
. '))?'
. $this->_getIPv4()
. '))]';
}
/**
* Return either the regular expression for folding white spaces or its backreference if allowed
*
* @access private
* @var bool $define
* @return string
*/
private function _getFWS($define = false)
{
// Return the backreference if $define is set to false otherwise return the regular expression
if ($this->_cfws)
{
return !$define ? '(?P>fws)' : '(?<fws>(?>[ ]+(?>x0Dx0A[ ]+)*)?)';
}
}
/**
* Return the regular expression for comments
*
* @access private
* @return string
*/
private function _getComments()
{
return '(?<comment>((?>'
. $this->_getFWS()
. '(?>[x01-x08x0Bx0Cx0E-'*-[]-x7F]|[x00-x7F]|(?P>comment)))*'
. $this->_getFWS()
. '))';
}
/**
* Return either the regular expression for comments and folding white spaces or its backreference if allowed
*
* @access private
* @var bool $define
* @return string
*/
private function _getCFWS($define = false)
{
// Return the backreference if $define is set to false
if ($this->_cfws && !$define)
{
return '(?P>cfws)';
}
// Otherwise return the regular expression
if ($this->_cfws)
{
return '(?<cfws>(?>(?>(?>'
. $this->_getFWS(true)
. $this->_getComments()
. ')+'
. $this->_getFWS()
. ')|'
. $this->_getFWS()
. ')?)';
}
}
/**
* Establish, and return, the valid format for the local part
*
* @access private
* @return string
*/
private function _getLocalPart()
{
// The local part may be obsolete if allowed
if ($this->_obsolete)
{
return $this->_getObsolete();
}
// Or the local part may be either a dot atom or a quoted string if the latter is allowed
if ($this->_quotedString)
{
return '(?>' . $this->_getDotAtom() . '|' . $this->_getQuotedString() . ')';
}
// Otherwise the local part may only be a dot atom
return $this->_getDotAtom();
}
/**
* Establish, and return, the valid format for the domain
*
* @access private
* @return string
*/
private function _getDomain()
{
// The domain may be either a domain name or a domain literal if the latter is allowed
if ($this->_domainLiteral)
{
return '(?>' . $this->_getDomainName() . '|' . $this->_getDomainLiteral() . ')';
}
// Otherwise the domain must be a domain name
return $this->_getDomainName();
}
/**
* Check to see if the domain can be resolved to MX RRs
*
* @access private
* @param array $domain
* @return bool
*/
private function _verifyDomain($domain)
{
// Return false if the domain cannot be resolved to MX RRs
if (!checkdnsrr(end($domain), 'MX'))
{
return false;
}
// Otherwise return true
return true;
}
/**
* Perform the validation check on the email address's syntax and, if required, call _verifyDomain()
*
* @access public
* @param bool $verify
* @return bool|integer
*/
public function isValid($verify = false)
{
// Return false if the email address has an incorrect syntax
if (!preg_match(
'/^'
. $this->_getCFWS()
. $this->_getLocalPart()
. $this->_getCFWS()
. '@'
. $this->_getCFWS()
. $this->_getDomain()
. $this->_getCFWS(true)
. '$/isD'
, $this->_emailAddress
))
{
return false;
}
// Otherwise check to see if the domain can be resolved to MX RRs if required
if ($verify)
{
// Return 0 if the domain cannot be resolved to MX RRs
if (!$this->_verifyDomain(explode('@', $this->_emailAddress)))
{
return 0;
}
// Otherwise return true
return true;
}
// Otherwise return 1
return 1;
}
}
email验证类的调用示例:
<?php
$valid = array(
1 => 'test@example.com',
2 => 'test@example.co.uk',
3 => 'test@example.museum',
4 => 'test@example',
5 => 'test@xn--example.com',
6 => 'test@example.xn--com',
7 => 'test.test@example.com',
8 => "!#$%&'*+-/=?^_`{|}~@example.com",
9 => 'test@123.com',
10 => 'test@example.123',
10 => 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkl@example.com',
11 => 'test@abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijk.com',
11 => 'test@example.abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijk',
12 => 'a@a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.a.b.c.d.e.f.g.h.i.j.k.l
.m.n.o.p.q.r.s.t.u.v.w.x.y.z.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v',
13 => '"test"@example.com',
14 => '"test@test"@example.com',
15 => '"test".test@example.com',
16 => 'test@[255.255.255.255]',
17 => 'test@[IPv6:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF]',
18 => 'test@[IPv6:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF::FFFF]',
19 => 'test@[IPv6:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:255.255.255.255]',
20 => 'test@[IPv6:FFFF:FFFF:FFFF:FFFF:FFFF::255.255.255.255]',
21 => ' test @ example . com ',
22 => '(comment)test@example.com',
23 => '((nested)comment)test@example.com',
24 => 'test@(comment)[255.255.255.255]',
25 => '"My name".is."Michael" (and I am (really) awesome) @ ("That's what she said") example . com',
);
$invalid = array(
1 => 'test',
2 => 'test@',
3 => '@example.com',
4 => 'test.@example.com',
5 => '.test@example.com',
6 => 'test..test@example.com',
7 => 'test@example..com',
8 => "tést@example.com",
9 => '"test@example.com',
10 => 'test"@example.com',
10 => '""@example.com',
11 => '"test"account"@example.com',
12 => 'a@a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.a.b.c.d.e.f.g.h.i.j
.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x',
13 => '"test"test@example.com',
14 => 'test@test@example.com',
15 => 'test@exam!ple.com',
16 => 'test@[255.255.255.256]',
17 => 'test@[IPv6:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF]',
18 => 'test@[IPv6:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF::FFFF:FFFF]',
19 => 'test@[IPv6:FFFF:FFFF:FFFF:FFFF:FFFF:255.255.255.255]',
20 => 'test@[IPv6:FFFF:FFFF:FFFF:FFFF:FFFF::FFFF:255.255.255.255]',
21 => 'test test@example.com',
22 => '(commenttest@example.com',
23 => '((nestedcomment)test@example.com',
24 => 'test@[255(comment).255.255.255]',
25 => ' @ ',
);
include 'EmailAddressValidator.php';
foreach ($valid as $address)
{
if (!EmailAddressValidator::setEmailAddress($address, 5322)->isValid())
{
echo 'Incorrect result: ' . $address . ' is a <strong>valid</strong> address.<br />';
}
}
foreach ($invalid as $address)
{
if (EmailAddressValidator::setEmailAddress($address, 5322)->isValid())
{
echo 'Incorrect result: ' . $address . ' is an <strong>invalid</strong> address.<br />';
}
}