2013-10-07 6 views
13

J'utilise PHP 5.3.10. Ceci est le code:PHP FILTER_VALIDATE_EMAIL ne fonctionne pas correctement

<?php 
$email = "[email protected]"; 
if (filter_var($email, FILTER_VALIDATE_EMAIL)) 
     echo "Email: ".$email." correct"; 
else 
     echo "email not correct"; 
?> 

Il renvoie: "Email: [email protected] correct.

Je pense qu'un domaine de premier niveau avec un seul caractère n'est pas correct (je ne connais pas de TLD d'une longueur de caractère selon cette liste: http://data.iana.org/TLD/tlds-alpha-by-domain.txt).

Alors, FILTER_VALIDATE_EMAIL Le filtre fonctionne correctement ou non?

+1

La première partie avant le signe @ ne peut pas être plus de 64 caractères ... Dans mon cas, cela a causé quelques heures de débogage, mais 'FILTER_VALIDATE_EMAIL' avait droit. –

Répondre

38

La validation des adresses e-mail est un peu compliquée. Jetez un oeil à cette liste:

adresses e-mail valides

  1. [email protected]
  2. [email protected]
  3. [email protected] .example.com
  4. [email protected]
  5. utilisateur @ [IPv6: 2001: db8 1sq :: a0b: DBD0]
  6. « much.more inhabituelle "@ example.com
  7. "[email protected]"@example.com
  8. " très.(),:; <> [] \ "très. \ "Très @ \ \" très \". Inhabituel "@ strange.example.com
  9. Postbox @ com (domaines de premier niveau sont valides hostname)
  10. admin @ serveurmessagerie1 (nom de domaine local sans TLD)
  11. # $% &'*+-/=?^_`{}|[email protected]
  12. «() <> []:,; @ \\ « # $% & « * + -/=^_ `{} |! ~ .a "@ example.org
  13. " « @ example.org (espace entre les guillemets)
  14. üñîçøðé@example.com (Caractères Unicode dans la partie locale)

adresses e-mail non valides

  1. Abc.example.com (un caractère @ doit séparer les locaux et de domaine parties)
  2. A @ b @ c @ example.com (dont un seul [email protected] guillemets externes autorisés)
  3. a "b (c) d, e: f; gi [j \ k] [email protected] (aucun des caractères spéciaux dans cette partie locale ne doit être laissé entre guillemets)
  4. juste "pas" [email protected] (cité str les éléments doivent être séparés par des points, ou le seul élément constituant la partie locale)
  5. Ceci est "not \ [email protected] (les espaces, les guillemets et les barres obliques inverses peuvent uniquement exister dans les chaînes entre guillemets et être précédés d'un barre oblique inverse)
  6. cet exemple \ still \ "not \ allowed @.com (même si échappé (précédé par une barre oblique inverse), des espaces, des citations et antislashs doivent encore être contenue par des guillemets)

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

Allmost toutes les implémentations de validation de courrier électronique sont « mis sur écoute » mais la mise en œuvre de php est bien de travailler avec, car il accepte tous les e-mail commun adresses

MISE à JOUR:

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

trouvé

En ce qui concerne les adresses "partielles" avec no. dans la partie de domaine, un commentaire dans le code source (dans ext/filtre/logical_filters.c) justifie ce rejet ainsi:

* 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 [email protected] 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. 

Et voici un lien vers la classe de Michael Rushton (lien cassé source de voir ci-dessous) qui prend en charge les RFC 5321/5322

<?php 
    /** 
    * Squiloople Framework 
    * 
    * LICENSE: Feel free to use and redistribute this code. 
    * 
    * @author Michael Rushton <[email protected]> 
    * @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; 
    } 
    } 

Edition 2016: En PHP 7.1 beta i remarqué ce qui suit:

  • Implémentation de la validation par email selon RFC 6531. (Leo Feyer, Anatol).

Voir la section 3,3 https://tools.ietf.org/html/rfc6531#section-3.3

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

Et quelques beaux exemples supplémentaires

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

Oui c'est le cas, parce que vous pouvez utiliser un nom de domaine local, etc Il est compliqué de valider le TLD et la plupart des implémentations acceptent simplement (même adresse invalide). Les implémentations de validation par e-mail ne sont pas si strictes –

+1

Vous dites: 9. postbox @ com (les domaines de premier niveau sont des noms d'hôtes valides), mais le filtre FILTER_VALIDATE_EMAIL sur cette adresse renvoie false! Donc, le filtre n'accepte-t-il comme valide que quelques adresses email (incluses "[email protected]") mais pas d'autres (de toute façon, valables comme "postbox @ com")? C'est un comportement étrange! –

+0

@RosarioRusso: il est temps de déposer un rapport de bug, car vous avez raison: il renvoie false, et il ne devrait pas! –

-1

utiliser ce code

<?php 
$email = "[email protected]"; 
$regex = '/^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,4})$/'; 
if (preg_match($regex, $email)) { 
    echo "Email: ".$email." correct"; 
} else { 
    echo "email not correct"; 
} 
//OUTPUT: email not correct 

?> 
+1

N'accepte pas "" très.(),:; <> [] \ ". TRÈS. \ "very @ \\ \" very \ ". inhabituel" @ strange.example.com', qui (comme l'indiquent les deux réponses ici) est une adresse valide. De plus, '.coop' est aussi un TLD valide, votre regex n'autorise pas non plus' my.name @ bonafidehost.coop' ... _n'utilise pas_. [il y a plus de TLD avec 3+ caractères, comme 'aero'. Vérifiez la liste] (http://data.iana.org/TLD/tlds-alpha-by-domain.txt) –

+0

Vérifiez maintenant le code mis à jour –

+5

Toujours pas ok: '.museum' est également valide, et contient 6 caractères longue. Votre regex est également sensible à la casse, et _still_ n'accepte pas les signes, les guillemets et similaires. C'est trop restrictif. [Voici une regex qui est en fait _close_ à être conforme RFC] (http://www.ex-parrot.com/pdw/Mail-RFC822-Address.html)! Regardez-le, c'est un gâchis: email + regex = catastrophe –

2

FILTER_VALIDATE_EMAIL n'est pas suppor ting PHP 5.2.14

+0

Je l'ai remarqué car il fonctionnait localement sur ma machine, mais pas quand j'ai téléchargé mon code sur le serveur d'hébergement. – CodeGodie

-2

Je choisi d'utiliser:

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

dans mon logiciel forum https://github.com/neofutur/MyBestBB/blob/master/include/email.php#L39

mais il est officielement: http://www.ex-parrot.com/pdw/Mail-RFC822-Address.html (plus trop)

2

Il y a un Cours PHP sur google code pour la validation des adresses e-mail:

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

Vous pouvez l'utiliser comme

include('EmailAddressValidator.php'); 
$validator = new EmailAddressValidator; 
if ($validator->check_email_address('[email protected]')) { 
    // Email address is technically valid 
} else { 
    // Email not valid 
} 
+1

Est obsolète ... Stick à PHP http://php.net/manual/fr/filter.filters.validate.php qui couvre presque tous les cas d'utilisation selon la RFC 822 – MarcoZen

Questions connexes