Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
456 views
in Technique[技术] by (71.8m points)

email validation - PHP FILTER_VALIDATE_EMAIL does not work correctly

I'm using PHP 5.3.10. This is the code:

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

It returns: "Email: test@example.c correct.

I think that a top level domain with only one character is not correct (I'm not aware of one-character-length TLD according to this list: http://data.iana.org/TLD/tlds-alpha-by-domain.txt).

So, FILTER_VALIDATE_EMAIL filter is working correctly or not?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Validating e-mail adresses is kinda complicated. Take a look at this list:

Valid email addresses

  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. user@[IPv6:2001:db8:1ff::a0b:dbd0]
  6. "much.more unusual"@example.com
  7. "very.unusual.@.unusual.com"@example.com
  8. "very.(),:;<>[]".VERY."very@ "very".unusual"@strange.example.com
  9. postbox@com (top-level domains are valid hostnames)
  10. admin@mailserver1 (local domain name with no TLD)
  11. !#$%&'*+-/=?^_`{}|~@example.org
  12. "()<>[]:,;@"!#$%&'*+-/=?^_`{}| ~.a"@example.org
  13. " "@example.org (space between the quotes)
  14. ü????eé@example.com (Unicode characters in local part)

Invalid email addresses

  1. Abc.example.com (an @ character must separate the local and domain parts)
  2. A@b@c@example.com (only one @ is allowed outside quotation marks)
  3. a"b(c)d,e:f;gi[jk]l@example.com (none of the special characters in this local part are allowed outside quotation marks)
  4. just"not"right@example.com (quoted strings must be dot separated, or the only element making up the local-part)
  5. this is"notallowed@example.com (spaces, quotes, and backslashes may only exist when within quoted strings and preceded by a backslash)
  6. this still"notallowed@example.com (even if escaped (preceded by a backslash), spaces, quotes, and backslashes must still be contained by quotes)

Source http://en.wikipedia.org/wiki/Email_address

Allmost all e-mail validation implementations are "bugged" but the php implementation is fine to work with because it accepts all common e-mail adresses

UPDATE:

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

Regarding "partial" addresses with no . in the domain part, a comment in the source code (in ext/filter/logical_filters.c) justifies this rejection thus:

 * 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.

And here is a link to the class from Michael Rushton (link broken see source below) Which supports both 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-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 the basic domain name format if required
      if ($this->_basic_domain_name)
      {
        return '(?>' . $this-

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

1.4m articles

1.4m replys

5 comments

56.9k users

...