用PHP校验EMAIL地址的正确方法(1)


由John Klensin编写的互联网任务工程组(IETF)文档RFC 3696 “应用程序技术检查和命名转换”给出了多个真实有效的EMAIL地址,但很不幸的是这些地址却被大多数PHP校验程序给拒绝了,地址Abc\@def@example.com,customer/department=shipping@example.com 和!def!xyz%abc@example.com都是有效的,下面是在有关文献中给出的一个非常流行正则表达式,但它拒绝了前面给出的所有EMAIL地址:





^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,3})$


这个正则表达式只允许下划线(_)和连字符(-),数字和大小写字母。即使在此之前先对字母做了大小写转换,也会拒绝那些包含斜线(/),等号(=),惊叹号(!)和百分号(%)的地址。这个表达式也要求最高级的域组件至少要有2个或3个字符,因此也会拒绝有效的域,如.museum。


另一个受人喜欢的正则表达式是:





^[a-zA-Z0-9_.-]+@[a-zA-Z0-9-]+.[a-zA-Z0-9-.]+$


这个正则表达式也会拒绝前面段落给出的有效示例地址,它优雅地解决了大写字母问题,并且当最高级域名只有2个或3个字符也不会报错了,但它又允许无效的域名,如example..com。


清单1显示了一个来自PHP Dev Shed(http://www.devshed.com/c/a/PHP/Email-Address-Verification-with-PHP/2)的示例,这个代码包括(至少)三个错误:


首先,它不能识别出许多有效的email地址字符,如百分号(%)。


第二,它将email地址在@符合处分成用户名和域两部分,如果email地址在符号处包括一个引用,如Abc\@def@example.com,将会中断这个代码。


第三,它不能检查主机地址DNS记录,有DNS A记录的主机会接受email地址,不一定非得要MX记录,我没有在PHP Dev Shed上找作者的岔,至少有100位浏览者做了4-5星的评分。


清单1.一个错误的email校验程序





function checkEmail($email) {

if(preg_match("/^([a-zA-Z0-9])+([a-zA-Z0-9\._-])*@([a-zA-Z0-9_-])+([a-zA-Z0-9\._-]+)+$/",
$email)){
list($username,$domain)=split('@',$email);
if(!checkdnsrr($domain,'MX')) {
return false;
}
return true;
}
return false;

一个比较好的解决方案来自IloveJackDaniel(http://ilovejackdaniels.com/)的Dave Child的博客,显示在清单2中(http://www.ilovejackdaniels.com/php/email-address-validation)。


Dave不仅喜欢陈年的美国威士忌,而且它也有一个副业,就是阅读RFC 2822,找出在一个email地址用户名有效的字符范围,至少有50人对这个解决方案做了评论,包括一些已经被合并到最初的方案中的纠正,不过这个由大家共同开发的代码仍然有缺陷,主要是它不能允许在用户名中出现转移字符,如\@,并且当不止一个地址符号时也会拒绝,因此就不能使用@来将用户名与域进行划分,个人认为这会扩大检查域名中每个组件影响的范围。


清单2:IloveJackDaniel提供的更好的示例





function check_email_address($email) {

//首先,我们检查这里的@符号,然后看其长度是否正确。
if (!ereg("^[^@]{1,64}@[^@]{1,255}$", $email)) {
// email无效,因为某个小段中的字符数量错误或@符号的数量错误
return false;
}
//将其分割成小段
$email_array = explode("@", $email);
$local_array = explode(".", $email_array[0]);
for ($i = 0; $i < sizeof($local_array); $i++) {
if
(!ereg("^(([A-Za-z0-9!#$%&'*+/=?^_`{|}~-][A-Za-z0-9!#$%&
↪'*+/=?^_`{|}~\.-]{0,63})|(\"[^(\\|\")]{0,62}\"))$",
$local_array[$i])) {
return false;
}
}
//检查域是否是一个IP地址,如果不是,它应该是一个有效的域
if (!ereg("^\[?[0-9\.]+\]?$", $email_array[1])) {
$domain_array = explode(".", $email_array[1]);
if (sizeof($domain_array) < 2) {
return false; // 域长度不够
}
for ($i = 0; $i < sizeof($domain_array); $i++) {
if
(!ereg("^(([A-Za-z0-9][A-Za-z0-9-]{0,61}[A-Za-z0-9])|
↪([A-Za-z0-9]+))$",
$domain_array[$i])) {
return false;
}
}
}
return true;
}





标签:

友情链接
轻松育儿世界奇观
苏ICP备16066217号-2