¿Debo usar filter_var para validar el correo electrónico?

8 minutos de lectura

Tengo una clase que valida cada entrada antes de enviarla a la capa de la base de datos. Tenga en cuenta que mi problema no se trata de escapar ni nada. Mi capa de base de datos manejará el problema de inyección de SQL. Todo lo que quiero hacer es validar si el correo electrónico es válido o no porque más tarde ese correo electrónico podría usarse como ‘enviar a’. Por ejemplo, el usuario recuperará el acceso a su cuenta a través de un enlace enviado al correo electrónico. leí mucho sobre filter_var y hay un montón de gente en contra y otro grupo a favor. Manteniendo el enfoque en ‘Solo quiero validar el correo electrónico y no filtrarlo para la base de datos o para html o XSS o lo que sea’, ¿hay algún problema al usar filter_var?

  • Si desea asegurarse de que el correo electrónico tenga el formato correcto, está bien para ese propósito. Si desea saber si es una dirección de correo electrónico real, lo más probable es que tenga que pagar por un servicio de validación de correo electrónico.

    –Jeremy Harris

    22/10/2013 a las 15:30

  • No necesita pagar por un servicio de validación. Simplemente envíe un correo electrónico con un enlace de verificación.

    – ComFreek

    22/10/2013 a las 15:32

  • SÍ, definitivamente deberías usar filter_var para verificar si esta es una dirección de correo electrónico válida, ya que esta es la única forma confiable en PHP para verificar una dirección de correo electrónico…

    – feeela

    22/10/2013 a las 15:35

Si deberías.

Usar la validación de la biblioteca estándar en lugar de una casera tiene múltiples beneficios:

  1. Muchos ojos ya han visto el código (bueno, al menos dos) que utilizará, con suerte con experiencia en la validación de correo electrónico incluso antes de que se fusione en un lanzamiento.
  2. Es unidad probada.
  3. Otras personas usarán el mismo cheque y reportar errores y obtiene estas correcciones de forma gratuita en las actualizaciones de php.

Sin embargo, verificar el formato de una dirección de correo electrónico es solo la primera línea de defensa, si realmente desea saber si es real o no, deberá enviarle un mensaje.

  • Desafortunadamente, esto solo es cierto si alguien realmente mantiene y mejora aún más dicha biblioteca de validación. En este caso utilizando filter_var tiene algunos peligros: no es compatible con UTF8 en la parte local a pesar de que esto ha sido válido durante bastante tiempo, y en realidad tienes que convertir el nombre de dominio con idn_to_ascii usted mismo para validar los nombres de dominio internacionales, lo cual no es obvio. Prepárese para muchas direcciones de correo electrónico fallidas que son realmente válidas si usa filter_vary esto solo empeorará mucho más cuando Unicode se use más ampliamente en las direcciones de correo electrónico.

    – iquito

    19 mayo 2016 a las 17:54

avatar de usuario
Absfrm

Sí, deberías usar filter_var y así es como puedes incorporarlo:

if( filter_var( $email ,FILTER_VALIDATE_EMAIL ) )
{
    /*
     * Rest of your code
     */
}

avatar de usuario
plano rico

Sí. Pero checkdnsrr() también puede ser digno de una mención aquí.

filter_var() aprobará dominios que parezcan estar incompletos porque podrían ser válidos en un contexto local (por ejemplo, [email protected]). Esto puede generar falsos positivos en los que las personas simplemente pierden el TLD o el punto en el nombre de dominio (p. ej., [email protected])

Captura estos haciendo un checkdnsrr() busque en el dominio: si puede encontrar un registro MX para el dominio y la dirección es válida, entonces ha hecho lo mejor que pudo.

Código de ejemplo:

if(filter_var($email, FILTER_VALIDATE_EMAIL)) 
{
    list($userName, $mailDomain) = explode("@", $email);
    if (!checkdnsrr($mailDomain, "MX"))
    {
        // Email is unreachable.
    }
}
else
{
    // Email is bad.
}

checkdnsrr() es bastante instantáneo (según mi experiencia) y aún no he encontrado un entorno en el que no funcione.

  • Lo comprobaré cuando tenga algo de tiempo, pero puedo asegurarte que el ejemplo que mencionaste @gmailcom NO es validado por filter_var.

    – Marco Aurelio Deleu

    11 de diciembre de 2014 a las 18:37

  • Suficientemente cierto. Lo cual es un problema en sí mismo, aunque solo en circunstancias bastante oscuras. Hay una Informe de errores de PHP enumerar fallas de FILTER_VALIDATE_EMAIL; hacer checkdnsrr() atraparía todos los falsos positivos dados en el ejemplo del teclado allí.

    – avión rico

    3 de noviembre de 2015 a las 11:00

  • Tenga en cuenta que checkdnsrr tiene un tiempo de espera de 20 segundos, que aparentemente no se puede cambiar (algunos dominios responden de una manera que hace que llegue a los 20 segundos, como tuve que experimentar en mi aplicación), y el nombre de dominio debe ser procesado por idn_to_ascii() primero en admitir dominios con caracteres especiales (como ö, é, etc.). cambié a llamar dig con passthru para que pueda especificar un tiempo de espera y qué servidores de nombres usar.

    – iquito

    16 mayo 2016 a las 23:23

  • filter_var falla en una dirección de correo electrónico como [email protected], aunque esta sería una dirección de correo electrónico válida en algunos contextos.

    – iquito

    19 mayo 2016 a las 17:48

Desafortunadamente, filter_var no admite UTF8 en la parte local (antes de la @) de la dirección, y para admitir nombres de dominio internacionales, deberá ejecutar el nombre de dominio a través de idn_to_ascii por separado (lo cual es una molestia y no es obvio).

Esto hace filter_var bastante inútil en mi opinión: cuantas más direcciones de correo electrónico unicode aparezcan, más direcciones de correo electrónico legítimas fallarán, lo que es especialmente el caso de países como China o Brasil, donde existe una demanda obvia de estas direcciones. filter_var tampoco permite direcciones de correo electrónico como [email protected]que son válidos y pueden ser útiles en un contexto de servidor.

Sería realmente útil si existiera una biblioteca de correo electrónico para validar de acuerdo con instrucciones específicas: ¿solo se permiten nombres de dominio, o también hosts arbitrarios como localhost, o hay una lista blanca para dominios personalizados que deberían ser válidos? ¿Debería permitirse Unicode? ¿Cuáles son los errores tipográficos comunes para los nombres de dominio de correo gratuito (como @homail.com) que también deberían fallar?

Además, sería sensato validar algunos nombres de dominio de una manera más específica: hotmail.com no permite caracteres Unicode por ahora y tiene limitaciones específicas sobre los caracteres utilizables. Como la mayoría de las direcciones de correo electrónico utilizadas en las aplicaciones PHP se concentran en quizás 100 dominios diferentes, esto podría usarse para validar estos nombres de dominio de una mejor manera. Desafortunadamente, tal biblioteca no existe todavía, que yo sepa.

Algunos de los comentarios que vi no coincidían con mis pruebas, así que quería señalar la funcionalidad que encontré con PHP 5.x. Si primero SANITIZA el correo electrónico, eliminará todos los caracteres que no desea, luego puede VALIDAR. Tengo dos funciones en caso de que alguien quisiera hacer solo una u otra.

Compruebe si el correo electrónico es válido:

function isValidEmailAddress($email="", $check_domain = false)
{
    if (empty($email)) {
        return false;
    } else {
        $success = true;
    }

    if (!filter_var((string) $email, FILTER_VALIDATE_EMAIL)) {
        $success = false;
    }
    if ($check_domain && $success) {
        list($name, $domain) = explode('@', trim($email) . "@");
        if (!checkdnsrr($domain, 'MX')) {
            $success = false;
        }
    }
    return array("success" => $success, "email" => $email);
}

Eliminar y UTF8, etc.:

function sanitizeEmailAddress($email="") {
    if (!empty($email)) {
        $email = filter_var(strtolower(trim($email)), FILTER_SANITIZE_EMAIL);
    }
    return $email;
}

Ejemplo de uso:

// test -- 
$list = array('goodÂ@bad.com', '[email protected]', '[email protected]', '[email protected]', '', '<[email protected]>', '[email protected]', '[email protected]', '[email protected]', '[email protected]', '[email protected]');

foreach($list as $email) {

    $ret = isValidEmailAddress( sanitizeEmailAddress($email), false );
    if ($ret['success']) {
        echo "GOOD " . $ret['email'];
    } else {
       echo "BAD  " .$email;
    }
        echo "\n";
    }

Resultados :

GOOD [email protected]
GOOD [email protected]
GOOD [email protected]
BAD  [email protected]
BAD  
GOOD [email protected]
GOOD [email protected]
GOOD [email protected]
GOOD [email protected]
GOOD [email protected]
GOOD [email protected]

si usa la opción de dominio: $ret = isValidEmailAddress( sanitizeEmailAddress($email), true );

GOOD [email protected]
GOOD [email protected]
GOOD [email protected]
BAD  [email protected]
BAD  
GOOD [email protected]
GOOD [email protected]
GOOD [email protected]
BAD  [email protected]
BAD  [email protected]
BAD  [email protected]

  • Es muy importante tener en cuenta que primero debe FILTER_SANITIZE_EMAIL. Esto permite que php lo limpie antes de ejecutarlo a través de su único proceso de validación.

    – Chris

    28 de diciembre de 2018 a las 19:11

En 2021, no. filter_varLa implementación de validación de (a partir de PHP 8) no verifica los nombres de dominio internacionales, lo que considero que es una razón lo suficientemente grande como para deshacerse.

propio de Symfony Validación de correo electrónico también usa un Regex que no tiene soporte para UTF-8.

Usar https://github.com/egulias/EmailValidator. Sigue el RFC del correo electrónico y también puede verificar los registros MX para verificar aún más que el dominio existe.

  • Es muy importante tener en cuenta que primero debe FILTER_SANITIZE_EMAIL. Esto permite que php lo limpie antes de ejecutarlo a través de su único proceso de validación.

    – Chris

    28 de diciembre de 2018 a las 19:11

¿Ha sido útil esta solución?