我应该使用filter_var来验证电子邮件吗?

时间:2013-10-22 15:27:32

标签: php validation

我有一个类,在将每个输入发送到数据库层之前验证它们。请注意,我的问题不是逃避或任何事情。我的数据库层将处理SQL注入问题。我想要做的就是验证电子邮件是否有效,因为稍后该电子邮件可能被用作“发送到”。例如,用户将通过发送到电子邮件的链接恢复对其帐户的访问。我读了很多关于filter_var的内容,并且有很多人反对它,其他人也赞成。将注意力集中在“我只想验证电子邮件而不是为数据库或html或XSS或其他任何内容过滤”,使用filter_var时是否存在问题?

6 个答案:

答案 0 :(得分:23)

是的,你应该。

使用标准库验证而不是家庭酿造有一个好处:

  1. 许多眼球已经看到了你将要使用的代码(好吧,至少有两个),希望在将它合并到一个版本之前就具有电子邮件验证方面的经验。
  2. 这是unit tested
  3. 其他人会使用相同的支票和report bugs,您可以在php更新时免费获得这些修补程序。
  4. 但是,检查电子邮件地址的格式只是第一道防线,如果你真的想知道它是否真实,你必须向它发送信息。

答案 1 :(得分:8)

是的,您应该使用filter_var,这就是您可以合并它的方式:

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

答案 2 :(得分:7)

是。但checkdnsrr()在这里也值得一提。

filter_var()会批准看似不完整的域名,因为它可能在本地环境中有效(例如某人@ localhost)。如果人们错过TLD或域名中的点(例如hattie.jacques@gmailcom),这可能导致误报。

通过对域进行checkdnsrr()查找来捕获这些内容 - 如果您可以找到该域的MX记录并且该地址有效,那么您已经完成了最多的工作。

示例代码:

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

checkdnsrr()非常即时(根据我的经验),我还没有找到一个不起作用的环境。

答案 3 :(得分:2)

不幸的是,filter_var在地址的本地部分(@之前)不支持UTF8,为了支持国际域名,您需要分别通过idn_to_ascii运行域名(是一件麻烦但并不明显的事。)

这使得filter_var在我看来相当无用:越来越多的unicode电子邮件地址出现,更合法的电子邮件地址将会失败,尤其是中国或巴西等国家的情况。对这些地址的明显需求。 filter_var也不允许使用root@localhost等电子邮件地址,这些地址有效且可能在服务器上下文中有用。

如果存在根据特定说明进行验证的电子邮件库 - 仅允许域名,或者是localhost之类的任意主机,或者是否应该有效的自定义域白名单,那将非常有用?应该允许unicode吗?免费邮箱域名(如@ homail.com)的常见拼写错误也应该失败?

此外,以更具体的方式验证某些域名是明智的 - hotmail.com目前不允许使用unicode字符,并且对可用字符有特定限制。由于PHP应用程序中大多数使用的电子邮件地址都集中在100个不同的域上,因此可以用更好的方式验证这些域名。不幸的是,据我所知,还没有这样的图书馆存在。

答案 4 :(得分:1)

我看到的一些评论与我的测试不符,所以我想指出我在PHP 5.x中找到的功能。如果您首先对电子邮件进行SANITIZE,它将删除您不想要的所有字符,那么您可以进行验证。我有两个功能,以防有人想要做一个或另一个。

检查电子邮件是否有效:

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

删除<>和UTF8等:

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

样本用法:

// test -- 
$list = array('goodÂ@bad.com', 'mikeq@google.com', 'puser@porsche.us', 'quick@us', '', '<yo@marist.edu>', 'hello@us.edu', 'rgil@yahoo.com', 'abc@2r.edu', 'one2@e3.edu', 'key@gen.us');

foreach($list as $email) {

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

结果:

GOOD good@bad.com
GOOD mikeq@google.com
GOOD puser@porsche.us
BAD  quick@us
BAD  
GOOD yo@marist.edu
GOOD hello@us.edu
GOOD rgil@yahoo.com
GOOD abc@2r.edu
GOOD one2@e3.edu
GOOD key@gen.us

如果您使用域选项:$ ret = isValidEmailAddress(sanitizeEmailAddress($ email),true);

GOOD good@bad.com
GOOD mikeq@google.com
GOOD puser@porsche.us
BAD  quick@us
BAD  
GOOD yo@marist.edu
GOOD hello@us.edu
GOOD rgil@yahoo.com
BAD  abc@2r.edu
BAD  one2@e3.edu
BAD  key@gen.us

答案 5 :(得分:0)

在 2021 年,不会。.then() 的验证实现(自 PHP 8 起)不会验证国际域名,我认为这是放弃的充分理由。< /p>

Symfony 自己的 Email Validation 也使用不支持 UTF-8 的正则表达式。

使用https://github.com/egulias/EmailValidator。它遵循电子邮件 RFC,还可以检查 MX 记录以进一步验证域是否存在。