2010-09-16 30 views
31

Después de leer varias publicaciones, decidí no usar REGEX para verificar si un correo electrónico es válido y simplemente usar la función incorporada de filter_var de PHP. Parecía funcionar bien, hasta que comenzó a decirme que un correo electrónico no era válido porque tenía un número en él.¿Funciona realmente el filter_var FILTER_VALIDATE_EMAIL de PHP?

es decir, [email protected] funciona, mientras que [email protected] no.

¿Me falta algo o es el filter_var($email, FILTER_VALIDATE_EMAIL) realmente bastante ineficaz?

+0

probando la existencia de un punto en la dirección de correo electrónico también es necesario. http://www.electrictoolbox.com/php-email-validation-filter-var-updated/ –

+0

@willdanceforfun Su pregunta es inexacta. 'name2 @ domain.com' funciona bien en todas las versiones de PHP que admiten' filter_var() '. Prueba: http://3v4l.org/joLvm – Brad

Respuesta

33

La expresión regular utilizada en el código de filtro PHP 5.3.3 se basa en el blog de Michael Rushton sobre Email Address Validation. Parece que funciona para el caso que mencionas.

También puede consultar algunas de las opciones en Comparing E-mail Address Validating Regular Expressions (la expresión regular actualmente utilizada en PHP es una de esas pruebas).

Luego puede elegir una expresión regular que prefiera y utilizarla en una llamada al preg_match().

O bien podría tomar la expresión regular y reemplazar la que está en el archivo PHP/ext/filter/logical_filter.c, función php_filter_validate_email(), y reconstruir PHP.

+2

Eso lo cubre :) – Andy

+0

El enlace al blog de Michael Rushton ahora lo lleva a una página vacía :( – Matteo

+0

@Matteo, puede encontrar el mismo código en la fuente PHP o encontrar el blog de Michael Rushton en la máquina de retorno: https : //web.archive.org/web/20150910045413/http: //squiloople.com/2009/12/20/email-address-validation –

5

[email protected] parece funcionar bien: http://codepad.org/5HDgMW5i

Pero sin duda he visto a gente quejándose que tiene problemas, incluso en SO. Con toda probabilidad, tiene problemas, pero también lo hará una solución de expresiones regulares. Las especificaciones de la dirección de correo electrónico son muy, muy complicadas (RFC XXXX).

Es por eso que la única solución para verificar correos electrónicos en los que debe confiar es enviar un correo electrónico a la dirección y exigir acción (por ejemplo: si es un script de registro, pídales que hagan clic en un enlace de verificación).

+0

Gracias por eso. Enviaré un correo electrónico de validación. Sería bueno tener algo en su lugar para asegurarme de que la gente no arroje accidentalmente caracteres obviamente incorrectos. – willdanceforfun

+3

@Keen No estoy diciendo tirar la validación de expresiones regulares por la ventana; puede validarlo y, si falla, advertir al usuario (por ejemplo: "la computadora dice que su correo electrónico no es válido, pero no es muy inteligente. ¿Está seguro de que desea utilizar este correo electrónico?") – NullUserException

+0

¡Es una gran idea! – willdanceforfun

1
function isValidEmail($email, $checkDNS = false) 
{ 

    $valid = (
      /* Preference for native version of function */ 
      function_exists('filter_var') and filter_var($email, FILTER_VALIDATE_EMAIL) 
      ) || (
       /* The maximum length of an e-mail address is 320 octets, per RFC 2821. */ 
       strlen($email) <= 320 
       /* 
       * 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. 
       * 
       * This regex does not handle comments and folding whitespace. While 
       * this is technically valid in an email address, these parts aren't 
       * actually part of the address itself. 
       */ 
       and preg_match_all(
        '/^(?!(?:(?:\\x22?\\x5C[\\x00-\\x7E]\\x22?)|(?:\\x22?[^\\x5C\\x22]\\x22?))'. 
        '{255,})(?!(?:(?:\\x22?\\x5C[\\x00-\\x7E]\\x22?)|(?:\\x22?[^\\x5C\\x22]\\x22?))'. 
        '{65,}@)(?:(?:[\\x21\\x23-\\x27\\x2A\\x2B\\x2D\\x2F-\\x39\\x3D\\x3F\\x5E-\\x7E]+)|'. 
        '(?:\\x22(?:[\\x01-\\x08\\x0B\\x0C\\x0E-\\x1F\\x21\\x23-\\x5B\\x5D-\\x7F]|(?:\\x5C[\\x00-\\x7F]))*\\x22))'. 
        '(?:\\.(?:(?:[\\x21\\x23-\\x27\\x2A\\x2B\\x2D\\x2F-\\x39\\x3D\\x3F\\x5E-\\x7E]+)|'. 
        '(?:\\x22(?:[\\x01-\\x08\\x0B\\x0C\\x0E-\\x1F\\x21\\x23-\\x5B\\x5D-\\x7F]|'. 
        '(?:\\x5C[\\x00-\\x7F]))*\\x22)))*@(?:(?:(?!.*[^.]{64,})'. 
        '(?:(?:(?:xn--)?[a-z0-9]+(?:-+[a-z0-9]+)*\\.){1,126})'.'{1,}'. 
        '(?:(?:[a-z][a-z0-9]*)|(?:(?:xn--)[a-z0-9]+))(?:-+[a-z0-9]+)*)|'. 
        '(?:\\[(?:(?:IPv6:(?:(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){7})|'. 
        '(?:(?!(?:.*[a-f0-9][:\\]]){7,})(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,5})?::'. 
        '(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,5})?)))|'. 
        '(?:(?:IPv6:(?:(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){5}:)|'. 
        '(?:(?!(?:.*[a-f0-9]:){5,})'.'(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,3})?::'. 
        '(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,3}:)?)))?(?:(?:25[0-5])|'. 
        '(?:2[0-4][0-9])|(?:1[0-9]{2})|(?:[1-9]?[0-9]))(?:\\.(?:(?:25[0-5])|'. 
        '(?:2[0-4][0-9])|(?:1[0-9]{2})|(?:[1-9]?[0-9]))){3}))\\]))$/iD', 
        $email) 
      ); 

    if($valid) 
    { 
     if($checkDNS && ($domain = end(explode('@',$email, 2)))) 
     { 
      /* 
      Note: 
      Adding the dot enforces the root. 
      The dot is sometimes necessary if you are searching for a fully qualified domain 
      which has the same name as a host on your local domain. 
      Of course the dot does not alter results that were OK anyway. 
      */ 
      return checkdnsrr($domain . '.', 'MX'); 
     } 
     return true; 
    } 
    return false; 
} 


//----------------------------------------------------------------- 

    var_dump(isValidEmail('[email protected]', true)); 
    // bool(true) 
+6

No proporcione el código como respuesta. –

Cuestiones relacionadas