PHP 的 filter_var FILTER_VALIDATE_EMAIL 真的有效吗?
Posted
技术标签:
【中文标题】PHP 的 filter_var FILTER_VALIDATE_EMAIL 真的有效吗?【英文标题】:Does PHP's filter_var FILTER_VALIDATE_EMAIL actually work? 【发布时间】:2011-04-12 23:27:26 【问题描述】:在阅读了各种帖子后,我决定不使用 REGEX 来检查电子邮件是否有效,而只使用 php 的内置 filter_var 函数。它似乎工作正常,直到它开始告诉我一封电子邮件无效,因为我有一个号码。
即 name@domain.com 有效,而 name2@domain.com 无效。
是我遗漏了什么还是filter_var($email, FILTER_VALIDATE_EMAIL)
真的很无效?
【问题讨论】:
测试电子邮件地址中是否存在点也是必要的。 electrictoolbox.com/php-email-validation-filter-var-updated @willdanceforfun 您的问题不准确。name2@domain.com
在所有支持 filter_var()
的 PHP 版本上都能正常工作。证明:3v4l.org/joLvm
【参考方案1】:
PHP 5.3.3 过滤器代码中使用的正则表达式基于 Michael Rushton 关于Email Address Validation 的博客。它似乎确实适用于您提到的情况。
您还可以查看Comparing E-mail Address Validating Regular Expressions 中的一些选项(PHP 中当前使用的正则表达式是经过测试的其中之一)。
然后你可以选择一个你更喜欢的正则表达式,并在调用preg_match()
时使用它。
或者你可以使用正则表达式并替换文件 PHP/ext/filter/logical_filter.c 中的那个,函数php_filter_validate_email()
,然后重建 PHP。
【讨论】:
Michael Rushton 博客的链接现在将您带到一个空白页面:( @Matteo,您可以在 PHP 源代码中找到相同的代码。或者在 Wayback 机器中找到 Michael Rushton 的博客:web.archive.org/web/20150910045413/http://squiloople.com/2009/…【参考方案2】:name2@domain.com 似乎工作正常: http://codepad.org/5HDgMW5i
但我确实看到有人抱怨它有问题,即使在 SO 上也是如此。很可能,它确实有问题,但正则表达式解决方案也会有问题。电子邮件地址规范非常非常复杂 (RFC XXXX)。
这就是为什么您应该依赖的唯一验证电子邮件的解决方案是将电子邮件发送到地址并要求操作(例如:如果它是注册脚本,请他们点击验证链接)。
【讨论】:
谢谢。我将发送一封验证电子邮件,如果有一些东西可以确保人们不会不小心输入明显错误的字符,那就太好了。 @Keen 我不是说把正则表达式验证扔到窗外;您可以对其进行验证,如果失败则警告用户(例如:“计算机说您的电子邮件无效,但它不是很聪明。您确定要使用此电子邮件吗?”)【参考方案3】:该过滤器最近进行了改进。 http://codepad.org/Lz5m2S2N - 在键盘使用的版本中,您的案例似乎被正确过滤了
您还可以查看 http://bugs.php.net/49576 和 http://svn.php.net/viewvc/php/php-src/trunk/ext/filter/logical_filters.c 。正则表达式很可怕。
【讨论】:
【参考方案4】:function isValidEmail($email, $checkDNS = false)
$valid = (
/* Preference for native version of function */
function_exists('filter_var') and filter_var($email, FILTER_VALIDATE_EMAIL)
) || (
/* The maximum length of an e-mail address is 320 octets, per RFC 2821. */
strlen($email) <= 320
/*
* The regex below is based on a regex by Michael Rushton.
* However, it is not identical. I changed it to only consider routeable
* addresses as valid. Michael's regex considers a@b a valid address
* which conflicts with section 2.3.5 of RFC 5321 which states that:
*
* Only resolvable, fully-qualified domain names (FQDNs) are permitted
* when domain names are used in SMTP. In other words, names that can
* be resolved to MX RRs or address (i.e., A or AAAA) RRs (as discussed
* in Section 5) are permitted, as are CNAME RRs whose targets can be
* resolved, in turn, to MX or address RRs. Local nicknames or
* unqualified names MUST NOT be used.
*
* This regex does not handle comments and folding whitespace. While
* this is technically valid in an email address, these parts aren't
* actually part of the address itself.
*/
and preg_match_all(
'/^(?!(?:(?:\\x22?\\x5C[\\x00-\\x7E]\\x22?)|(?:\\x22?[^\\x5C\\x22]\\x22?))'.
'255,)(?!(?:(?:\\x22?\\x5C[\\x00-\\x7E]\\x22?)|(?:\\x22?[^\\x5C\\x22]\\x22?))'.
'65,@)(?:(?:[\\x21\\x23-\\x27\\x2A\\x2B\\x2D\\x2F-\\x39\\x3D\\x3F\\x5E-\\x7E]+)|'.
'(?:\\x22(?:[\\x01-\\x08\\x0B\\x0C\\x0E-\\x1F\\x21\\x23-\\x5B\\x5D-\\x7F]|(?:\\x5C[\\x00-\\x7F]))*\\x22))'.
'(?:\\.(?:(?:[\\x21\\x23-\\x27\\x2A\\x2B\\x2D\\x2F-\\x39\\x3D\\x3F\\x5E-\\x7E]+)|'.
'(?:\\x22(?:[\\x01-\\x08\\x0B\\x0C\\x0E-\\x1F\\x21\\x23-\\x5B\\x5D-\\x7F]|'.
'(?:\\x5C[\\x00-\\x7F]))*\\x22)))*@(?:(?:(?!.*[^.]64,)'.
'(?:(?:(?:xn--)?[a-z0-9]+(?:-+[a-z0-9]+)*\\.)1,126)'.'1,'.
'(?:(?:[a-z][a-z0-9]*)|(?:(?:xn--)[a-z0-9]+))(?:-+[a-z0-9]+)*)|'.
'(?:\\[(?:(?:IPv6:(?:(?:[a-f0-9]1,4(?::[a-f0-9]1,4)7)|'.
'(?:(?!(?:.*[a-f0-9][:\\]])7,)(?:[a-f0-9]1,4(?::[a-f0-9]1,4)0,5)?::'.
'(?:[a-f0-9]1,4(?::[a-f0-9]1,4)0,5)?)))|'.
'(?:(?:IPv6:(?:(?:[a-f0-9]1,4(?::[a-f0-9]1,4)5:)|'.
'(?:(?!(?:.*[a-f0-9]:)5,)'.'(?:[a-f0-9]1,4(?::[a-f0-9]1,4)0,3)?::'.
'(?:[a-f0-9]1,4(?::[a-f0-9]1,4)0,3:)?)))?(?:(?:25[0-5])|'.
'(?:2[0-4][0-9])|(?:1[0-9]2)|(?:[1-9]?[0-9]))(?:\\.(?:(?:25[0-5])|'.
'(?:2[0-4][0-9])|(?:1[0-9]2)|(?:[1-9]?[0-9])))3))\\]))$/iD',
$email)
);
if( $valid )
if( $checkDNS && ($domain = end(explode('@',$email, 2))) )
/*
Note:
Adding the dot enforces the root.
The dot is sometimes necessary if you are searching for a fully qualified domain
which has the same name as a host on your local domain.
Of course the dot does not alter results that were OK anyway.
*/
return checkdnsrr($domain . '.', 'MX');
return true;
return false;
//-----------------------------------------------------------------
var_dump(isValidEmail('nechtan@tagon8inc.com', true));
// bool(true)
【讨论】:
以上是关于PHP 的 filter_var FILTER_VALIDATE_EMAIL 真的有效吗?的主要内容,如果未能解决你的问题,请参考以下文章