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

Php 我应该使用filter_var验证电子邮件吗?,php,validation,Php,Validation,我有一个类,它在我将每个输入发送到数据库层之前验证它。请注意,我的问题不是逃跑什么的。我的数据库层将处理SQL注入问题。我想做的就是验证电子邮件是否有效,因为稍后该电子邮件可能会用作“发送到”。例如,用户将通过发送到电子邮件的链接恢复对其帐户的访问。我读了很多关于过滤变量的书,有一大群人反对,另一大群人赞成。将重点放在“我只是想验证电子邮件,而不是对其进行数据库、html或XSS等过滤”,使用filter\u var是否有问题?是的,您应该使用filter\u var,这就是您可以合并它的方式:

我有一个类,它在我将每个输入发送到数据库层之前验证它。请注意,我的问题不是逃跑什么的。我的数据库层将处理SQL注入问题。我想做的就是验证电子邮件是否有效,因为稍后该电子邮件可能会用作“发送到”。例如,用户将通过发送到电子邮件的链接恢复对其帐户的访问。我读了很多关于过滤变量的书,有一大群人反对,另一大群人赞成。将重点放在“我只是想验证电子邮件,而不是对其进行数据库、html或XSS等过滤”,使用
filter\u var
是否有问题?

是的,您应该使用
filter\u var
,这就是您可以合并它的方式:

if( filter_var( $email ,FILTER_VALIDATE_EMAIL ) )
{
    /*
     * Rest of your code
     */
}
是的,你应该

使用标准库验证而不是自制验证有多种好处:

  • 许多眼球已经看到了您将要使用的代码(至少有两个),希望在电子邮件验证方面有经验,甚至在它被合并到发行版之前
  • 是的
  • 其他人将使用相同的检查,您可以在php更新中免费获得这些修复
  • 然而,检查电子邮件地址的格式只是第一道防线,如果你真的想知道它是真的还是假的,你必须向它发送一条消息

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

    filter\u var()
    将批准似乎不完整的域,因为它可能在本地上下文中有效(例如。someone@localhost). 这可能导致误报,人们只是错过了域名中的TLD或点(例如hattie)。jacques@gmailcom)

    通过在域上查找来捕获这些信息-如果您可以找到域的MX记录并且地址有效,那么您已经尽了最大努力

    示例代码:

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

    checkdnsr()
    是非常即时的(以我的经验),我还没有找到一个它不工作的环境。

    不幸的是,
    filter\u var
    在地址的本地部分(在@之前)不支持UTF8,为了支持国际域名,您需要分别通过
    idn\u to\u ascii
    运行域名(这很麻烦,也不明显)

    这使得
    filter\u var
    在我看来毫无用处:在野外出现的unicode电子邮件地址越多,合法的电子邮件地址就越会失败,尤其是像中国或巴西这样对这些地址有明显需求的国家
    filter\u var
    也不允许像
    root@localhost
    ,在服务器环境中有效且可能有用

    如果存在一个电子邮件库来根据特定的说明进行验证,这将非常有用-是否只允许使用域名,或者是否也允许使用任意主机(如localhost),或者是否有一个自定义域的白名单,该白名单应该是有效的?应该允许使用unicode吗?免费邮件域名(如@homail.com)有哪些常见的打字错误也会失败


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

    我看到的一些评论与我的测试不匹配,因此我想指出我在PHP5.x中发现的功能。如果您首先清理电子邮件,它将删除所有您不想要的字符,然后您可以验证。我有两个功能,以防有人只想做其中一个

    检查电子邮件是否有效:

    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";
        }
    
    如果使用域选项:$ret=isValidEmailAddress(sanitizeEmailAddress($email),true)


    <强> 2021,No.<强> >代码> FieldValue/Cuth>的验证实现(如PHP 8)不验证国际域名,我认为这是足够大的理由放弃。< /P> Symfony自己也使用不支持UTF-8的正则表达式


    使用。它遵循电子邮件RFC,还可以检查MX记录,以进一步验证该域是否存在。

    如果您想确保电子邮件格式正确,可以这样做。如果你想知道它是否是一个真实的电子邮件地址,那么你很可能需要支付电子邮件验证服务的费用。你不需要支付验证服务的费用。只需发送一封带有验证链接的电子邮件。是的,你一定要使用
    filter\u var
    来检查这是否是一个有效的电子邮件地址,因为这是PHP中唯一可靠的检查电子邮件地址的方法…我会在有时间时进行检查,但是我可以马上向你保证,你提到的@gmailcom的例子没有得到filter\u var.True的验证。这本身就是一个问题,尽管只是在相当模糊的情况下。有一个列表列出了过滤、验证和电子邮件的失败;执行checkdnsrr()将捕获代码板示例中给出的所有误报。请注意,checkdnsrr的超时时间为20秒,这显然是无法更改的(一些域的响应方式使其达到20秒,正如我在应用程序中所经历的那样),域名应通过
    idn_to_ascii()处理
    首先支持具有特殊字符的域(如ö、é等)。我切换到使用
    passthru
    调用
    dig
    ,这样我就可以指定超时时间和要使用的名称服务器。
    filter\u var
    在这样的电子邮件地址上失败someone@localhost-即使在某些情况下这是一个有效的电子邮件地址。不幸的是,只有当有人真的维护并进一步改进了这样一个系统时,这才是正确的
    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
    
    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