email validation - PHP FILTER_VALIDATE_EMAIL does not work correctly -


i'm using php 5.3.10. 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 top level domain 1 character not correct (i'm not aware of one-character-length tld according list: http://data.iana.org/tld/tlds-alpha-by-domain.txt).

so, filter_validate_email filter working correctly or not?

validating e-mail adresses kinda complicated. take @ 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 valid hostnames)
  10. admin@mailserver1 (local domain name no tld)
  11. !#$%&'*+-/=?^_`{}|~@example.org
  12. "()<>[]:,;@\\"!#$%&'*+-/=?^_`{}| ~.a"@example.org
  13. " "@example.org (space between quotes)
  14. üñîçøðé@example.com (unicode characters in local part)

invalid email addresses

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

source http://en.wikipedia.org/wiki/email_address

allmost e-mail validation implementations "bugged" php implementation fine work because accepts common e-mail adresses

update:

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

regarding "partial" addresses no . in domain part, comment in source code (in ext/filter/logical_filters.c) justifies rejection thus:

 * regex below based on regex michael rushton.  * however, not identical.  changed consider routeable  * addresses valid.  michael's regex considers a@b valid address  * conflicts section 2.3.5 of rfc 5321 states that:  *  *   resolvable, fully-qualified domain names (fqdns) permitted  *   when domain names used in smtp.  in other words, names can  *   resolved mx rrs or address (i.e., or aaaa) rrs (as discussed  *   in section 5) permitted, cname rrs targets can  *   resolved, in turn, mx or address rrs.  local nicknames or  *   unqualified names must not used. 

and here link class michael rushton (link broken see source below) supports both rfc 5321/5322

<?php   /**    * squiloople framework    *    * license: feel free use , redistribute 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 relevant standards    */   final class emailaddressvalidator   {     // rfc 5321 constant     const rfc_5321 = 5321;     // rfc 5322 constant     const rfc_5322 = 5322;     /**      * email address      *      * @access private      * @var string $_email_address      */     private $_email_address;     /**      * quoted string local part either allowed (true) or not (false)      *      * @access private      * @var boolean $_quoted_string      */     private $_quoted_string = false;     /**      * obsolete local part either allowed (true) or not (false)      *      * @access private      * @var boolean $_obsolete      */     private $_obsolete = false;     /**      * basic domain name either required (true) or not (false)      *      * @access private      * @var boolean $_basic_domain_name      */     private $_basic_domain_name = true;     /**      * domain literal domain either allowed (true) or not (false)      *      * @access private      * @var boolean $_domain_literal      */     private $_domain_literal = false;    /**      * comments , folding white spaces either allowed (true) or not (false)      *      * @access private      * @var boolean $_cfws      */     private $_cfws = false;     /**      * set email address , turn on relevant standard if required      *      * @access public      * @param string $email_address      * @param null|integer $standard      */     public function __construct($email_address, $standard = null)     {       // set email address       $this->_email_address = $email_address;       // set relevant standard or throw exception if unknown requested       switch ($standard)       {         // 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 exception         default:           throw new exception('unknown rfc standard email address validation.');       }     }     /**      * call 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 email address using basic standard      *      * @access public      * @return emailaddressvalidator      */     public function setstandardbasic()     {       // quoted string local part not allowed       $this->_quoted_string = false;       // obsolete local part not allowed       $this->_obsolete = false;       // basic domain name required       $this->_basic_domain_name = true;       // domain literal domain not allowed       $this->_domain_literal = false;       // comments , folding white spaces not allowed       $this->_cfws = false;       // return emailaddressvalidator object       return $this;     }     /**      * validate email address using rfc 5321      *      * @access public      * @return emailaddressvalidator      */     public function setstandard5321()     {       // quoted string local part allowed       $this->_quoted_string = true;       // obsolete local part not allowed       $this->_obsolete = false;       // basic domain name not required       $this->_basic_domain_name = false;       // domain literal domain allowed       $this->_domain_literal = true;       // comments , folding white spaces not allowed       $this->_cfws = false;       // return emailaddressvalidator object       return $this;     }     /**      * validate email address using rfc 5322      *      * @access public      * @return emailaddressvalidator      */     public function setstandard5322()     {       // quoted string local part disallowed       $this->_quoted_string = false;       // obsolete local part allowed       $this->_obsolete = true;       // basic domain name not required       $this->_basic_domain_name = false;       // domain literal domain allowed       $this->_domain_literal = true;       // comments , folding white spaces allowed       $this->_cfws = true;       // return emailaddressvalidator object       return $this;     }     /**      * either allow (true) or not allow (false) quoted string local part      *      * @access public      * @param boolean $allow      * @return emailaddressvalidator      */     public function setquotedstring($allow = true)     {       // either allow (true) or not allow (false) quoted string local part       $this->_quoted_string = $allow;       // return emailaddressvalidator object       return $this;     }     /**      * either allow (true) or not allow (false) obsolete local part      *      * @access public      * @param boolean $allow      * @return emailaddressvalidator      */     public function setobsolete($allow = true)     {       // either allow (true) or not allow (false) obsolete local part       $this->_obsolete = $allow;       // return emailaddressvalidator object       return $this;     }     /**      * either require (true) or not require (false) basic domain name      *      * @access public      * @param boolean $allow      * @return emailaddressvalidator      */     public function setbasicdomainname($allow = true)     {       // either require (true) or not require (false) basic domain name       $this->_basic_domain_name = $allow;       // return emailaddressvalidator object       return $this;     }     /**      * either allow (true) or not allow (false) domain literal domain      *      * @access public      * @param boolean $allow      * @return emailaddressvalidator      */     public function setdomainliteral($allow = true)     {       // either allow (true) or not allow (false) domain literal domain       $this->_domain_literal = $allow;       // return emailaddressvalidator object       return $this;     }     /**      * either allow (true) or not allow (false) comments , folding white spaces      *      * @access public      * @param boolean $allow      * @return emailaddressvalidator      */     public function setcfws($allow = true)     {       // either allow (true) or not allow (false) comments , folding white spaces       $this->_cfws = $allow;       // return emailaddressvalidator object       return $this;     }     /**      * return regular expression dot atom local part      *      * @access private      * @return string      */     private function _getdotatom()     {       return "([!#-'*+\/-9=?^-~-]+)(?>\.(?1))*";     }     /**      * return regular expression quoted string local part      *      * @access private      * @return string      */     private function _getquotedstring()     {       return '"(?>[ !#-\[\]-~]|\\\[ -~])*"';     }     /**      * return regular expression 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 regular expression domain name domain      *      * @access private      * @return string      */     private function _getdomainname()     {       // return 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 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 regular expression 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 regular expression 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 regular expression 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 regular expression domain literal domain      *      * @access private      * @return string      */     private function _getdomainliteral()     {       return '\[(?:(?>ipv6:(?>'         . $this->_getipv6()         . '))|(?>(?>ipv6:(?>'         . $this->_getipv4mappedipv6()         . '))?'         . $this->_getipv4()         . '))\]';     }     /**      * return either regular expression folding white spaces or backreference      *      * @access private      * @param boolean $define      * @return string      */     private function _getfws($define = false)     {       // return backreference if $define set false otherwise return regular expression       if ($this->_cfws)       {         return !$define ? '(?p>fws)' : '(?<fws>(?>(?>(?>\x0d\x0a)?[\t ])+|(?>[\t ]*\x0d\x0a)?[\t ]+)?)';       }     }     /**      * return regular expression 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 regular expression comments , folding white spaces or backreference      *      * @access private      * @param boolean $define      * @return string      */     private function _getcfws($define = false)     {       // return backreference if $define set false       if ($this->_cfws && !$define)       {         return '(?p>cfws)';       }       // otherwise return regular expression       if ($this->_cfws)       {         return '(?<cfws>(?>(?>(?>'           . $this->_getfws(true)           . $this->_getcomments()           . ')+'           . $this->_getfws()           . ')|'           . $this->_getfws()           . ')?)';       }     }     /**      * establish , return valid format local part      *      * @access private      * @return string      */     private function _getlocalpart()     {       // local part may obsolete if allowed       if ($this->_obsolete)       {         return $this->_getobsolete();       }       // otherwise local part must either dot atom or quoted string if latter allowed       if ($this->_quoted_string)       {         return '(?>' . $this->_getdotatom() . '|' . $this->_getquotedstring() . ')';       }       // otherwise local part must dot atom       return $this->_getdotatom();     }     /**      * establish , return valid format domain      *      * @access private      * @return string      */     private function _getdomain()     {       // domain must either domain name or domain literal if latter allowed       if ($this->_domain_literal)       {         return '(?>' . $this->_getdomainname() . '|' . $this->_getdomainliteral() . ')';       }       // otherwise domain must domain name       return $this->_getdomainname();     }     /**      * return email address length limit      *      * @access private      * @return string      */     private function _getemailaddresslengthlimit()     {       return '(?!(?>' . $this->_getcfws() . '"?(?>\\\[ -~]|[^"])"?' . $this->_getcfws() . '){255,})';     }     /**      * return local part length limit      *      * @access private      * @return string      */     private function _getlocalpartlengthlimit()     {       return '(?!(?>' . $this->_getcfws() . '"?(?>\\\[ -~]|[^"])"?' . $this->_getcfws() . '){65,}@)';     }     /**      * establish , return domain name length limit      *      * @access private      * @return string      */     private function _getdomainnamelengthlimit()     {       return '(?!' . $this->_getcfws() . '[a-z\d-]{64,})';     }     /**      * check see if domain can resolved mx rrs      *      * @access private      * @param array $domain      * @return integer|boolean      */     private function _verifydomain($domain)     {       // return 0 if domain cannot resolved mx rrs       if (!checkdnsrr(end($domain), 'mx'))       {         return 0;       }       // otherwise return true       return true;     }     /**      * perform validation check on 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 email address has 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 see if domain can resolved mx rrs if required       if ($verify)       {         return $this->_verifydomain(explode('@', $this->_email_address));       }       // otherwise return 1       return 1;     }   } 

edit 2016: in php 7.1 beta noticed following:

  • implemented email validation per rfc 6531. (leo feyer, anatol).

see section 3.3 https://tools.ietf.org/html/rfc6531#section-3.3

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

and nice examples

用户@例子.广告                 (chinese, unicode) उपयोगकर्ता@उदाहरण.कॉम           (hindi, unicode) юзер@екзампл.ком             (ukrainian, unicode) θσερ@εχαμπλε.ψομ             (greek, unicode) dörte@sörensen.example.com   (german, unicode) 

Comments

Popular posts from this blog

java.util.scanner - How to read and add only numbers to array from a text file -

rewrite - Trouble with Wordpress multiple custom querystrings -

php - Accessing static methods using newly created $obj or using class Name -