我有一个类可以在将每个输入发送到数据库层之前对其进行验证。请注意,我的问题与逃避或任何事情无关。我的数据库层将处理 SQL 注入问题。我要做的就是验证电子邮件是否有效,因为稍后该电子邮件可能会被用作“发送至”。例如,用户将通过发送到电子邮件的链接恢复对其帐户的访问。我读了很多关于它的内容filter_var
,有很多人反对它,而其他人则支持它。将重点放在“我只想验证电子邮件而不是针对数据库或 html 或 XSS 或其他任何内容进行过滤”,使用时有问题filter_var
吗?
6 回答
是的,你应该使用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 个不同的域上,因此这可以用来以更好的方式验证这些域名。不幸的是,据我所知,还没有这样的库。
我看到的一些评论与我的测试不匹配,所以我想指出我在 PHP 5.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";
}
结果 :
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
2021 年,No filter_var
. 的验证实现(从 PHP 8 开始)不验证国际域名,我认为这足以成为放弃的理由。
Symfony 自己的电子邮件验证也使用不支持 UTF-8 的 Regex。
使用https://github.com/egulias/EmailValidator。它遵循电子邮件 RFC,还可以检查 MX 记录以进一步验证域确实存在。