我有一个类,在将每个输入发送到数据库层之前验证它们。请注意,我的问题不是逃避或任何事情。我的数据库层将处理SQL注入问题。我想要做的就是验证电子邮件是否有效,因为稍后该电子邮件可能被用作“发送到”。例如,用户将通过发送到电子邮件的链接恢复对其帐户的访问。我读了很多关于filter_var
的内容,并且有很多人反对它,其他人也赞成。将注意力集中在“我只想验证电子邮件而不是为数据库或html或XSS或其他任何内容过滤”,使用filter_var
时是否存在问题?
答案 0 :(得分:23)
是的,你应该。
使用标准库验证而不是家庭酿造有一个好处:
但是,检查电子邮件地址的格式只是第一道防线,如果你真的想知道它是否真实,你必须向它发送信息。
答案 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 记录以进一步验证域是否存在。