PHP头条
热点:

用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 Shedhttp://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;

一个比较好的解决方案来自IloveJackDanielhttp://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;
}


www.phpzy.comtrue/php/19078.htmlTechArticle用PHP校验EMAIL地址的正确方法(1) 由John Klensin编写的互联网任务工程组IETF)文档RFC 3696 “应用程序技术检查和命名转换”给出了多个真实有效的EMAIL地址,但很不幸的是这些地址却被大多...

相关文章

PHP之友评论

今天推荐