2013-10-07 12 views
13

Sto usando PHP 5.3.10. Questo è il codice:PHP FILTER_VALIDATE_EMAIL non funziona correttamente

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

Torna: "Email: [email protected] corretto.

Penso che un dominio di primo livello con un solo carattere non sia corretto (non sono a conoscenza di un TLD di lunghezza di un carattere in base a questo elenco: http://data.iana.org/TLD/tlds-alpha-by-domain.txt).

Quindi, il filtro FILTER_VALIDATE_EMAIL funziona correttamente o no?

+1

La prima parte prima che la @ non può essere più lungo di 64 caratteri ... nel mio caso questo ha causato un paio d'ore di debugging, ma 'FILTER_VALIDATE_EMAIL' aveva ragione. .. –

risposta

38

La convalida degli indirizzi di posta elettronica è un po 'complicata. Date un'occhiata a questa lista:

indirizzi e-mail validi

  1. [email protected]
  2. [email protected]
  3. [email protected] .example.com
  4. [email protected]
  5. user @ [IPv6: 2001: DB8: 1ss :: A0B: DBD0]
  6. "much.more insolito "@ example.com
  7. "[email protected]"@example.com
  8. " molto.(),:; <> [] \ "MOLTO. \ "Molto @ \ \" molto \". Inusuale "@ strange.example.com
  9. casella postale @ com (domini di primo livello sono i nomi host validi)
  10. admin @ serverposta1 (nome di dominio locale senza TLD)
  11. # $% &'*+-/=?^_`{}|[email protected]
  12. "() <> []:!,; @ \\ "# $% & '* + -/=^_` {} |!? ~ .a "@ example.org
  13. " "@ example.org (spazio tra le virgolette)
  14. üñîçøðé@example.com (Caratteri Unicode nella parte locale)

indirizzi email non validi

  1. Abc.example.com (un carattere @ deve separare le parti locali e di dominio)
  2. A @ B @ c @ example.com (solo uno è @ consentito virgolette esterne)
  3. a "b (c) d, e: f; gi [j \ k] [email protected] (nessuno dei caratteri speciali in questa parte locale è consentito tra virgolette)
  4. solo "non" [email protected] (quotato str ings deve essere separato da punti, oppure l'unico elemento che compone la parte locale)
  5. questo è "not \ [email protected] (spazi, virgolette e barre retroverse potrebbero esistere solo quando all'interno di stringhe quotate e precedute da un backslash)
  6. questo \ still \ "non \ consentito @ esempio.com (anche se sfuggito (preceduto da un backslash), spazi, virgolette e backslash devono essere ancora contenuta tra virgolette)

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

Allmost tutte le implementazioni di validazione e-mail sono "spiati" ma l'implementazione php va bene per lavorare con perché accetta tutta la posta elettronica comune Indirizzi

UPDATE:

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

Per gli indirizzi "parziali" con n. nella parte del dominio, un commento nel codice sorgente (in ext/filtro/logical_filters.c) giustifica questo rifiuto così:

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

Ed ecco un link per la classe da Michael Rushton (link non funzionante fonte vedi sotto) che supporta sia 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; 
    } 
    } 

Edit 2016: In PHP 7.1 beta che ho notato quanto segue:

  • Implementazione della convalida della posta elettronica come da RFC 6531. (Leo Feyer, Anatol).

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

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

e alcuni bei esempi aggiuntivi

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

Sì, perché è possibile utilizzare un nome di dominio locale, ecc. È complicato convalidare il TLD e la maggior parte delle implementazioni accetta solo (anche un indirizzo non valido). Le implementazioni di convalida della posta elettronica non sono così rigide –

+1

Si dice: 9. postbox @ com (i domini di primo livello sono nomi di host validi), ma il filtro FILTER_VALIDATE_EMAIL su questo indirizzo restituisce false! Quindi, il filtro accetta come validi solo alcuni indirizzi email (inclusi "[email protected]") ma non altri (comunque validi come "postbox @ com")? Questo è un comportamento strano! –

+0

@RosarioRusso: è ora di presentare una segnalazione di bug, perché hai ragione: restituisce false, e non dovrebbe! –

-1

uso di questo codice

<?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

Non accetta '" molto.(),:; <> [] \ ". MOLTO. \ "very @ \\ \" very \ ". insolito" @ strange.example.com', che (come mostrano entrambe le risposte qui) è un indirizzo valido. Inoltre, '.coop' è un TLD valido, inoltre, la tua espressione regolare non consente' my.name @ bonafidehost.coop' o ... _non usarlo_. [ci sono più TLD con 3+ caratteri, come 'aero'. Controlla l'elenco] (http://data.iana.org/TLD/tlds-alpha-by-domain.txt) –

+0

verifica ora codice aggiornato –

+5

Ancora non ok: '.museum' è valido, anche, ed è 6 caratteri lungo. La tua espressione regolare è anche _case sensitive_ e _still_ non accetta segni, virgolette e simili. È _too restrittivo_ [ecco una regex che è in realtà _close_ ad essere conforme a RFC] (http://www.ex-parrot.com/pdw/Mail-RFC822-Address.html)! Guardalo, è un casino: email + regex = disaster –

2

FILTER_VALIDATE_EMAIL non è suppor ting PHP 5.2.14

+0

L'ho notato perché funzionava localmente sulla mia macchina, ma non quando ho caricato il mio codice sul server di hosting. – CodeGodie

-2

ho scelto di usare:

<?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); } 
?> 

nel mio software forum https://github.com/neofutur/MyBestBB/blob/master/include/email.php#L39

ma ufficialmente è: http://www.ex-parrot.com/pdw/Mail-RFC822-Address.html (più troppo)

2

C'è una Classe PHP su codice google per la convalida degli indirizzi email:

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

Si può usare come

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

È deprecato ... Attenersi al http://php.net/manual/en/filter.filters.validate.php di PHP che copre quasi tutti i casi d'uso come da RFC 822 – MarcoZen