PHP FILTER_VALIDATE_EMAIL无法正常工作

时间:2013-10-07 08:30:42

标签: php email-validation filter-var

我正在使用PHP 5.3.10。这是代码:

<?php
$email = "test@example.c";
if (filter_var($email, FILTER_VALIDATE_EMAIL))
        echo "Email: ".$email." correct";
else
        echo "email not correct";
?>

返回:"Email: test@example.c正确。

我认为只有一个字符的顶级域名不正确(根据此列表,我不知道单字符长度的TLD:http://data.iana.org/TLD/tlds-alpha-by-domain.txt)。

那么,FILTER_VALIDATE_EMAIL过滤器是否正常工作?

5 个答案:

答案 0 :(得分:42)

验证电子邮件地址有点复杂。 看一下这个清单:

有效的电子邮件地址

  1. niceandsimple@example.com
  2. very.common@example.com
  3. a.little.lengthy.but.fine@dept.example.com
  4. disposable.style.email.with+symbol@example.com
  5. 用户@ [IPv6的:2001:DB8:1FF :: A0B:DBD0]
  6. “很多。更不寻常”@ example.com
  7. “very.unusual。@。unusual.com” @ example.com
  8. 。 “很(),:;。&LT;&GT; [] \” VERY \“非常@ \ \ “非常\”。不寻常“@ strange.example.com
  9. 邮箱@ com(顶级域名是有效的主机名)
  10. admin @ mailserver1(没有TLD的本地域名)
  11. #$%&安培;'* + - / = ^ _`{} |~@example.org
  12. “()&LT;&GT; []:; @ \\”!?#$%&安培;'* + - / = ^ _`{} | 〜.A“@ example.org
  13. “”@ example.org(引号之间的空格)
  14. üñîçøðé​​@example.com(本地部分的Unicode字符)
  15. 电子邮件地址无效

    1. Abc.example.com(@字符必须分隔本地和域名 份)
    2. A @ b @ c @ example.com(只允许一个@在引号外)
    3. a“b(c)d,e:f; gi [j \ k] l@example.com(没有特殊字符 在本地部分允许在引号外)
    4. 只是“not”right@example.com(引用的字符串必须以点分隔,或者 构成本地部分的唯一元素)
    5. 这是“not \ allowed@example.com”(空格,引号和反斜杠可能 只有在带引号的字符串中且以反斜杠开头时才存在)
    6. 这个\ still \“not \ allowed@example.com(即使转义(前面是。) 必须仍然是反斜杠),空格,引号和反斜杠 包含在引号中)
    7. 来源http://en.wikipedia.org/wiki/Email_address

      所有电子邮件验证实现都被“窃听”但是php实现可以正常使用,因为它接受所有常见的电子邮件地址

      更新:

      http://www.php.net/manual/en/filter.filters.validate.php

      上找到

      关于没有的“部分”地址。在域部分中,源代码中的注释(在ext / filter / logical_filters.c中)证明了这种拒绝:

       * The regex below is based on a regex by Michael Rushton.
       * However, it is not identical.  I changed it to only consider routeable
       * addresses as valid.  Michael's regex considers a@b a valid address
       * which conflicts with section 2.3.5 of RFC 5321 which states that:
       *
       *   Only resolvable, fully-qualified domain names (FQDNs) are permitted
       *   when domain names are used in SMTP.  In other words, names that can
       *   be resolved to MX RRs or address (i.e., A or AAAA) RRs (as discussed
       *   in Section 5) are permitted, as are CNAME RRs whose targets can be
       *   resolved, in turn, to MX or address RRs.  Local nicknames or
       *   unqualified names MUST NOT be used.
      

      以下是来自Michael Rushton的课程链接(链接破碎见下文来源) 它支持RFC 5321/5322

      <?php
        /**
         * Squiloople Framework
         *
         * LICENSE: Feel free to use and redistribute this code.
         *
         * @author Michael Rushton <michael@squiloople.com>
         * @link http://squiloople.com/
         * @package Squiloople
         * @version 1.0
         * @copyright © 2012 Michael Rushton
         */
        /**
         * Email Address Validator
         *
         * Validate email addresses according to the relevant standards
         */
        final class EmailAddressValidator
        {
          // The RFC 5321 constant
          const RFC_5321 = 5321;
          // The RFC 5322 constant
          const RFC_5322 = 5322;
          /**
           * The email address
           *
           * @access private
           * @var string $_email_address
           */
          private $_email_address;
          /**
           * A quoted string local part is either allowed (true) or not (false)
           *
           * @access private
           * @var boolean $_quoted_string
           */
          private $_quoted_string = FALSE;
          /**
           * An obsolete local part is either allowed (true) or not (false)
           *
           * @access private
           * @var boolean $_obsolete
           */
          private $_obsolete = FALSE;
          /**
           * A basic domain name is either required (true) or not (false)
           *
           * @access private
           * @var boolean $_basic_domain_name
           */
          private $_basic_domain_name = TRUE;
          /**
           * A domain literal domain is either allowed (true) or not (false)
           *
           * @access private
           * @var boolean $_domain_literal
           */
          private $_domain_literal = FALSE;
         /**
           * Comments and folding white spaces are either allowed (true) or not (false)
           *
           * @access private
           * @var boolean $_cfws
           */
          private $_cfws = FALSE;
          /**
           * Set the email address and turn on the relevant standard if required
           *
           * @access public
           * @param string $email_address
           * @param null|integer $standard
           */
          public function __construct($email_address, $standard = NULL)
          {
            // Set the email address
            $this->_email_address = $email_address;
            // Set the relevant standard or throw an exception if an unknown is requested
            switch ($standard)
            {
              // Do nothing if no standard requested
              case NULL:
                break;
              // Otherwise if RFC 5321 requested
              case self::RFC_5321:
                $this->setStandard5321();
                break;
              // Otherwise if RFC 5322 requested
              case self::RFC_5322:
                $this->setStandard5322();
                break;
              // Otherwise throw an exception
              default:
                throw new Exception('Unknown RFC standard for email address validation.');
            }
          }
          /**
           * Call the constructor fluently
           *
           * @access public
           * @static
           * @param string $email_address
           * @param null|integer $standard
           * @return EmailAddressValidator
           */
          public static function setEmailAddress($email_address, $standard = NULL)
          {
            return new self($email_address, $standard);
          }
          /**
           * Validate the email address using a basic standard
           *
           * @access public
           * @return EmailAddressValidator
           */
          public function setStandardBasic()
          {
            // A quoted string local part is not allowed
            $this->_quoted_string = FALSE;
            // An obsolete local part is not allowed
            $this->_obsolete = FALSE;
            // A basic domain name is required
            $this->_basic_domain_name = TRUE;
            // A domain literal domain is not allowed
            $this->_domain_literal = FALSE;
            // Comments and folding white spaces are not allowed
            $this->_cfws = FALSE;
            // Return the EmailAddressValidator object
            return $this;
          }
          /**
           * Validate the email address using RFC 5321
           *
           * @access public
           * @return EmailAddressValidator
           */
          public function setStandard5321()
          {
            // A quoted string local part is allowed
            $this->_quoted_string = TRUE;
            // An obsolete local part is not allowed
            $this->_obsolete = FALSE;
            // Only a basic domain name is not required
            $this->_basic_domain_name = FALSE;
            // A domain literal domain is allowed
            $this->_domain_literal = TRUE;
            // Comments and folding white spaces are not allowed
            $this->_cfws = FALSE;
            // Return the EmailAddressValidator object
            return $this;
          }
          /**
           * Validate the email address using RFC 5322
           *
           * @access public
           * @return EmailAddressValidator
           */
          public function setStandard5322()
          {
            // A quoted string local part is disallowed
            $this->_quoted_string = FALSE;
            // An obsolete local part is allowed
            $this->_obsolete = TRUE;
            // Only a basic domain name is not required
            $this->_basic_domain_name = FALSE;
            // A domain literal domain is allowed
            $this->_domain_literal = TRUE;
            // Comments and folding white spaces are allowed
            $this->_cfws = TRUE;
            // Return the EmailAddressValidator object
            return $this;
          }
          /**
           * Either allow (true) or do not allow (false) a quoted string local part
           *
           * @access public
           * @param boolean $allow
           * @return EmailAddressValidator
           */
          public function setQuotedString($allow = TRUE)
          {
            // Either allow (true) or do not allow (false) a quoted string local part
            $this->_quoted_string = $allow;
            // Return the EmailAddressValidator object
            return $this;
          }
          /**
           * Either allow (true) or do not allow (false) an obsolete local part
           *
           * @access public
           * @param boolean $allow
           * @return EmailAddressValidator
           */
          public function setObsolete($allow = TRUE)
          {
            // Either allow (true) or do not allow (false) an obsolete local part
            $this->_obsolete = $allow;
            // Return the EmailAddressValidator object
            return $this;
          }
          /**
           * Either require (true) or do not require (false) a basic domain name
           *
           * @access public
           * @param boolean $allow
           * @return EmailAddressValidator
           */
          public function setBasicDomainName($allow = TRUE)
          {
            // Either require (true) or do not require (false) a basic domain name
            $this->_basic_domain_name = $allow;
            // Return the EmailAddressValidator object
            return $this;
          }
          /**
           * Either allow (true) or do not allow (false) a domain literal domain
           *
           * @access public
           * @param boolean $allow
           * @return EmailAddressValidator
           */
          public function setDomainLiteral($allow = TRUE)
          {
            // Either allow (true) or do not allow (false) a domain literal domain
            $this->_domain_literal = $allow;
            // Return the EmailAddressValidator object
            return $this;
          }
          /**
           * Either allow (true) or do not allow (false) comments and folding white spaces
           *
           * @access public
           * @param boolean $allow
           * @return EmailAddressValidator
           */
          public function setCFWS($allow = TRUE)
          {
            // Either allow (true) or do not allow (false) comments and folding white spaces
            $this->_cfws = $allow;
            // Return the EmailAddressValidator object
            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-\x08\x0B\x0C\x0E-!#-\[\]-\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 the basic domain name format if required
            if ($this->_basic_domain_name)
            {
              return '(?>' . $this->_getDomainNameLengthLimit()
                . '[a-z\d](?>[a-z\d-]*[a-z\d])?'
                . $this->_getCFWS()
                . '\.'
                . $this->_getCFWS()
                . '){1,126}[a-z]{2,6}';
            }
            // Otherwise return the full domain name format
            return $this->_getDomainNameLengthLimit()
              . '([a-z\d](?>[a-z\d-]*[a-z\d])?)(?>'
              . $this->_getCFWS()
              . '\.'
              . $this->_getDomainNameLengthLimit()
              . $this->_getCFWS()
              . '(?2)){0,126}';
          }
          /**
           * Return the regular expression for an IPv6 address
           *
           * @access private
           * @return string
           */
          private function _getIPv6()
          {
            return '([a-f\d]{1,4})(?>:(?3)){7}|(?!(?:.*[a-f\d][:\]]){8,})((?3)(?>:(?3)){0,6})?::(?4)?';
          }
          /**
           * Return the regular expression for an IPv4-mapped IPv6 address
           *
           * @access private
           * @return string
           */
          private function _getIPv4MappedIPv6()
          {
            return '(?3)(?>:(?3)){5}:|(?!(?:.*[a-f\d]:){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]\d|1\d{2}|[1-9]?\d)(?>\.(?6)){3}';
          }
          /**
           * Return the regular expression for a domain literal domain
           *
           * @access private
           * @return string
           */
          private function _getDomainLiteral()
          {
            return '\[(?:(?>IPv6:(?>'
              . $this->_getIPv6()
              . '))|(?>(?>IPv6:(?>'
              . $this->_getIPv4MappedIPv6()
              . '))?'
              . $this->_getIPv4()
              . '))\]';
          }
          /**
           * Return either the regular expression for folding white spaces or its backreference
           *
           * @access private
           * @param boolean $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>(?>(?>(?>\x0D\x0A)?[\t ])+|(?>[\t ]*\x0D\x0A)?[\t ]+)?)';
            }
          }
          /**
           * Return the regular expression for comments
           *
           * @access private
           * @return string
           */
          private function _getComments()
          {
            return '(?<comment>\((?>'
              . $this->_getFWS()
              . '(?>[\x01-\x08\x0B\x0C\x0E-\'*-\[\]-\x7F]|\\\[\x00-\x7F]|(?P>comment)))*'
              . $this->_getFWS()
              . '\))';
          }
          /**
           * Return either the regular expression for comments and folding white spaces or its backreference
           *
           * @access private
           * @param boolean $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();
            }
            // Otherwise the local part must be either a dot atom or a quoted string if the latter is allowed
            if ($this->_quoted_string)
            {
              return '(?>' . $this->_getDotAtom() . '|' . $this->_getQuotedString() . ')';
            }
            // Otherwise the local part must 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 must be either a domain name or a domain literal if the latter is allowed
            if ($this->_domain_literal)
            {
              return '(?>' . $this->_getDomainName() . '|' . $this->_getDomainLiteral() . ')';
            }
            // Otherwise the domain must be a domain name
            return $this->_getDomainName();
          }
          /**
           * Return the email address length limit
           *
           * @access private
           * @return string
           */
          private function _getEmailAddressLengthLimit()
          {
            return '(?!(?>' . $this->_getCFWS() . '"?(?>\\\[ -~]|[^"])"?' . $this->_getCFWS() . '){255,})';
          }
          /**
           * Return the local part length limit
           *
           * @access private
           * @return string
           */
          private function _getLocalPartLengthLimit()
          {
            return '(?!(?>' . $this->_getCFWS() . '"?(?>\\\[ -~]|[^"])"?' . $this->_getCFWS() . '){65,}@)';
          }
          /**
           * Establish and return the domain name length limit
           *
           * @access private
           * @return string
           */
          private function _getDomainNameLengthLimit()
          {
            return '(?!' . $this->_getCFWS() . '[a-z\d-]{64,})';
          }
          /**
           * Check to see if the domain can be resolved to MX RRs
           *
           * @access private
           * @param array $domain
           * @return integer|boolean
           */
          private function _verifyDomain($domain)
          {
            // Return 0 if the domain cannot be resolved to MX RRs
            if (!checkdnsrr(end($domain), 'MX'))
            {
              return 0;
            }
            // Otherwise return true
            return TRUE;
          }
          /**
           * Perform the validation check on the email address's syntax and, if required, call _verifyDomain()
           *
           * @access public
           * @param boolean $verify
           * @return boolean|integer
           */
          public function isValid($verify = FALSE)
          {
            // Return false if the email address has an incorrect syntax
            if (!preg_match(
                '/^'
              . $this->_getEmailAddressLengthLimit()
              . $this->_getLocalPartLengthLimit()
              . $this->_getCFWS()
              . $this->_getLocalPart()
              . $this->_getCFWS()
              . '@'
              . $this->_getCFWS()
              . $this->_getDomain()
              . $this->_getCFWS(TRUE)
              . '$/isD'
              , $this->_email_address
            ))
            {
              return FALSE;
            }
            // Otherwise check to see if the domain can be resolved to MX RRs if required
            if ($verify)
            {
              return $this->_verifyDomain(explode('@', $this->_email_address));
            }
            // Otherwise return 1
            return 1;
          }
        }
      

      编辑2016:在PHP 7.1 beta中,我注意到以下内容:

      • 根据RFC 6531实施电子邮件验证。(Leo Feyer,Anatol)。

      参见第3.3节https://tools.ietf.org/html/rfc6531#section-3.3

      https://en.wikipedia.org/wiki/International_email

      还有一些不错的额外例子

      用户@例子.广告                 (Chinese, Unicode)
      उपयोगकर्ता@उदाहरण.कॉम           (Hindi, Unicode)
      юзер@екзампл.ком             (Ukrainian, Unicode)
      θσερ@εχαμπλε.ψομ             (Greek, Unicode)
      Dörte@Sörensen.example.com   (German, Unicode)
      

答案 1 :(得分:2)

FILTER_VALIDATE_EMAIL不支持PHP 5.2.14

答案 2 :(得分:2)

Google代码上有一个用于验证电子邮件地址的PHP类:

http://code.google.com/p/php-email-address-validation

您可以像

一样使用它
include('EmailAddressValidator.php');
$validator = new EmailAddressValidator;
if ($validator->check_email_address('test@example.org')) { 
    // Email address is technically valid 
} else {
    // Email not valid
}

答案 3 :(得分:0)

FILTER_VALIDATE_EMAIL 只能告诉您地址格式是否正确。

考虑这些例子

// "not an email" is invalid so its false.
php > var_export(filter_var("not an email", FILTER_VALIDATE_EMAIL));
false
// "foo@a.com" looks like an email, so it passes even though its not real.
php > var_export(filter_var("foo@a.com", FILTER_VALIDATE_EMAIL));
'foo@a.com'
// "foo@gmail.com" passes, gmail is a valid email server,
//  but gmail require more than 3 letters for the address.
var_export(filter_var("foo@gmail.com", FILTER_VALIDATE_EMAIL));
'foo@gmail.com'

所以 FILTER_VALIDATE_EMAIL 只擅长在完全错误的时候告诉你,而不是在正确的时候。

您将需要使用 Real Email 之类的服务,它可以进行深入的电子邮件地址验证。

// foo@gmail.com is invalid because gmail require more than 3 letters for the address.
var_export(file_get_contents("https://isitarealemail.com/api/email/validate?email=foo@gmail.com"));
'{"status":"invalid"}'

// foobar@gmail.com is valid
var_export(file_get_contents("https://isitarealemail.com/api/email/validate?email=foobar@gmail.com"));
'{"status":"valid"}'

更多见https://docs.isitarealemail.com/how-to-validate-email-addresses-in-php

答案 4 :(得分:-2)

我选择使用:

<?php
$email =$argv[1];$result= is_valid_email($email); echo $result;
function is_valid_email($email) { return preg_match('/^(([^<>()[\]\\.,;:\s@"\']+(\.[^<>()[\]\\.,;:\s@"\']+)*)|("[^"\']+"))@((\[\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\])|(([a-zA-Z\d\-]+\.)+[a-zA-Z]{2,}))$/', $email); }
?>

在我的论坛软件中 https://github.com/neofutur/MyBestBB/blob/master/include/email.php#L39

但是官方说: http://www.ex-parrot.com/pdw/Mail-RFC822-Address.html (也更长)