我有一个类,可以在将每个输入发送到数据库层之前对其进行验证。请注意,我的问题不是关于逃跑或任何事情。我的数据库层将处理SQL注入问题。我要做的就是验证电子邮件是否有效,因为稍后该电子邮件可能会被用作"发送到"。例如,用户将通过发送到电子邮件的链接恢复对其帐户的访问权限。我读了很多关于filter_var
的文章,有一群人反对它,而其他人则赞成。将重点放在"我只想验证电子邮件,而不是过滤数据库或html或XSS或其他任何东西"上,使用filter_var
有问题吗?
是的,你应该这样做。
使用标准库验证而不是自制库验证具有多种好处:
- 许多眼球已经看到了您将使用的代码(嗯,至少两个),希望在合并到版本中之前就具有电子邮件验证的经验。
- 它经过单元测试。
- 其他人将使用相同的检查和报告错误,您可以在 php 更新中免费获得这些修复程序。
但是,检查电子邮件地址的格式只是第一道防线,如果您真的想知道它是真实的还是假的,则必须向其发送消息。
是的,你应该使用filter_var
,这就是你如何合并它:
if( filter_var( $email ,FILTER_VALIDATE_EMAIL ) )
{
/*
* Rest of your code
*/
}
是的。但checkdnsrr()
在这里可能也值得一提。
filter_var()
将批准看似不完整的域,因为它在本地上下文中可能有效(例如someone@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()
非常即时(根据我的经验),我还没有找到它不起作用的环境。
不幸的是,filter_var
不支持地址本地部分(@ 之前)的 UTF8,要支持国际域名,您需要单独通过idn_to_ascii
运行域名(这很麻烦且不明显)。
在我看来,这使得filter_var
相当无用:Unicode电子邮件地址在野外出现的越多,合法的电子邮件地址就越失败,对于中国或巴西等国家来说尤其如此,这些国家对这些地址有明显的需求。 filter_var
也不允许像root@localhost
这样的电子邮件地址,这些地址是有效的,并且在服务器上下文中可能有用。
如果存在一个电子邮件库来根据特定说明进行验证,那将非常有用 - 是否只允许域名,还是也允许像 localhost 这样的任意主机,或者是否有应该有效的自定义域白名单?应该允许 unicode 吗?免费邮件域名(如@homail.com)的常见拼写错误也应该失败吗?
此外,以更具体的方式验证某些域名是明智的 - hotmail.com 目前不允许 unicode 字符,并且对可用字符有特定的限制。由于PHP应用程序中最常用的电子邮件地址集中在大约100个不同的域上,因此可以使用它以更好的方式验证这些域名。不幸的是,据我所知,目前还没有这样的库。
在 2021 年,没有。 filter_var
的验证实现(从 PHP 8 开始)不验证国际域名,我认为这足以成为放弃的理由。
Symfony自己的电子邮件验证也使用没有UTF-8支持的正则表达式。
使用 https://github.com/egulias/EmailValidator。它遵循电子邮件 RFC,还可以检查 MX 记录以进一步验证域是否存在。
我看到的一些评论与我的测试不符,所以我想指出我在 PHP 5.x 中找到的功能。如果您首先对电子邮件进行 SANITIZATION,它将删除您不需要的所有字符,然后您可以进行验证。 我有两个功能,以防有人只想做一个或另一个。
检查电子邮件是否有效:
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