Chinaunix首页 | 论坛 | 博客
  • 博客访问: 567534
  • 博文数量: 84
  • 博客积分: 1529
  • 博客等级: 上尉
  • 技术积分: 1482
  • 用 户 组: 普通用户
  • 注册时间: 2011-01-27 17:57
文章分类

全部博文(84)

文章存档

2014年(7)

2013年(9)

2012年(20)

2011年(48)

分类: 系统运维

2011-08-24 17:07:03

   对于普通的邮件地址,一般都只是做命名合法的有效性,但是对于邮件地址是否存在等无法做有效的验证。通过网上的资料查看以下方式可以进行较完整的验证,但是在测试过程中发现还是不够那么完善,但是此方式是我看到用代码层面去确定的最好方式了:
  1. <?php

  2.  /**
  3.  * Validate Email Addresses Via SMTP
  4.  * This queries the SMTP server to see if the email address isaccepted.
  5.  * @copyright -Please keep this comment intact
  6.  * @author gabe@fijiwebdesign.com
  7.  * @contributers adnan@barakatdesigns.net
  8.  * @version 0.1a
  9.  */
  10. class SMTP_validateEmail {

  11.       /**
  12.        * PHP Socket resource to remote MTA
  13.        * @var resource $sock
  14.        */
  15.       var $sock;
  16.      
  17.       /**
  18.        * Current User being validated
  19.        */
  20.       var $user;
  21.       /**
  22.        * Current domain where user is being validated
  23.        */
  24.       var $domain;
  25.       /**
  26.        * List of domains to validate users on
  27.        */
  28.       var $domains;
  29.       /**
  30.        * SMTP Port
  31.        */
  32.       var $port = 25;
  33.       /**
  34.        * Maximum Connection Time to wait for connectionestablishment per MTA
  35.        */
  36.       var $max_conn_time = 30;
  37.       /**
  38.        * Maximum time to read from socket before giving up
  39.        */
  40.       var $max_read_time = 5;
  41.      
  42.       /**
  43.        * username of sender
  44.        */
  45.       var $from_user = 'user';
  46.       /**
  47.        * Host Name of sender
  48.        */
  49.       var $from_domain = 'localhost';
  50.      
  51.       /**
  52.        * Nameservers to use when make DNS query for MX entries
  53.        * @var Array $nameservers
  54.        */
  55.       var $nameservers = array(
  56.           '192.168.0.1'
  57.       );
  58.      
  59.       var $debug = false;
  60.      
  61.       /**
  62.        * Initializes the Class
  63.        * @return SMTP_validateEmail Instance
  64.        * @param $email Array[optional] List of Emails toValidate
  65.        * @param $sender String[optional] Email of validator
  66.        */
  67.       function SMTP_validateEmail($emails = false, $sender =false)
  68.       {
  69.           if ($emails) {
  70.                $this->setEmails($emails);
  71.           }
  72.           if ($sender) {
  73.                $this->setSenderEmail($sender);
  74.           }
  75.       }
  76.      
  77.       function _parseEmail($email)
  78.       {
  79.           $parts = explode('@', $email);
  80.           $domain = array_pop($parts);
  81.           $user= implode('@', $parts);
  82.           return array($user, $domain);
  83.       }
  84.      
  85.       /**
  86.        * Set the Emails to validate
  87.        * @param $emails Array List of Emails
  88.        */
  89.       function setEmails($emails)
  90.       {
  91.           foreach ($emails as $email) {
  92.               list($user, $domain) = $this->_parseEmail($email);
  93.               if (!isset($this->domains[$domain])) {
  94.                     $this->domains[$domain] = array();
  95.               }
  96.               $this->domains[$domain][] = $user;
  97.           }
  98.       }
  99.      
  100.       /**
  101.        * Set the Email of the sender/validator
  102.        * @param $email String
  103.        */
  104.       function setSenderEmail($email)
  105.       {
  106.           $parts = $this->_parseEmail($email);
  107.           $this->from_user = $parts[0];
  108.           $this->from_domain = $parts[1];
  109.       }
  110.      
  111.       /**
  112.       * Validate Email Addresses
  113.       * @param String $emails Emails to validate (recipientemails)
  114.       * @param String $sender Sender's Email
  115.       * @return Array Associative List of Emails and theirvalidation results
  116.       */
  117.       function validate($emails = false, $sender = false)
  118.       {
  119.           
  120.           $results = array();
  121.      
  122.           if ($emails) {
  123.                $this->setEmails($emails);
  124.           }
  125.           if ($sender) {
  126.                $this->setSenderEmail($sender);
  127.           }
  128.      
  129.           // query the MTAs on each Domain

  130.           foreach($this->domains as $domain=>$users) {
  131.      
  132.           $mxs = array();
  133.      
  134.           // current domain being queried

  135.           $this->domain = $domain;
  136.       
  137.           // retrieve SMTP Server via MX query on domain

  138.           list($hosts, $mxweights) = $this->queryMX($domain);
  139.      
  140.           // retrieve MX priorities

  141.           for($n = 0; $n < count($hosts); $n++){
  142.               $mxs[$hosts[$n]] = $mxweights[$n];
  143.           }
  144.           asort($mxs);
  145.      
  146.           // last fallback is the original domain

  147.           $mxs[$this->domain] = 0;
  148.       
  149.           $this->debug(print_r($mxs, 1));
  150.       
  151.           $timeout = $this->max_conn_time;
  152.        
  153.           // try each host

  154.           while(list($host) = each($mxs)) {
  155.               // connect to SMTP server

  156.               $this->debug("try $host:$this->port\n");
  157.               if ($this->sock = fsockopen($host, $this->port, $errno, $errstr, (float) $timeout)) {
  158.                   stream_set_timeout($this->sock, $this->max_read_time);
  159.                    break;
  160.               }
  161.           }
  162.      
  163.           //did we get a TCP socket

  164.           if ($this->sock) {
  165.               $reply = fread($this->sock, 2082);
  166.               $this->debug("<<<\n$reply");
  167.             
  168.               preg_match('/^([0-9]{3}) /ims', $reply,$matches);
  169.               $code = isset($matches[1]) ? $matches[1] : '';
  170.           
  171.               if($code != '220') {
  172.                   // MTA gave an error...

  173.                   foreach($users as $user) {
  174.                    $results[$user.'@'.$domain] = false;
  175.                    }
  176.                    continue;
  177.               }
  178.               
  179.               // say helo

  180.               $this->send("HELO ".$this->from_domain);
  181.               // tell of sender

  182.               $this->send("MAIL FROM: <".$this->from_user.'@'.$this->from_domain.">");
  183.             
  184.               // ask for each recepient on this domain

  185.               foreach($users as $user) {
  186.             
  187.                    // ask of recepient

  188.                    $reply = $this->send("RCPT TO: <".$user.'@'.$domain.">");
  189.                 
  190.                   // get code and msg from response

  191.                    preg_match('/^([0-9]{3}) /ims', $reply,$matches);
  192.                    $code = isset($matches[1]) ? $matches[1] : '';
  193.               
  194.                    if ($code == '250') {
  195.                    // you received 250 so the email address was accepted

  196.                         $results[$user.'@'.$domain] =true;
  197.                    }
  198.                    elseif ($code == '451' || $code == '452') {
  199.                         // you received 451 so the email address was greylisted (or some temporary error occured on the MTA) - so assume is ok

  200.                         $results[$user.'@'.$domain] =true;
  201.                    }
  202.                    else {
  203.                         $results[$user.'@'.$domain] =false;
  204.                    }
  205.             
  206.              }
  207.             
  208.               // reset before quit

  209.               $this->send("RSET");
  210.             
  211.               // quit

  212.               $this->send("quit");
  213.               // close socket

  214.               fclose($this->sock);
  215.               }
  216.           }
  217.           return $results;
  218.       }
  219.      
  220.      
  221.      function send($msg) {
  222.           fwrite($this->sock, $msg."\r\n");
  223.      
  224.           $reply = fread($this->sock, 2082);
  225.      
  226.           $this->debug(">>>\n$msg\n");
  227.           $this->debug("<<<\n$reply");
  228.       
  229.           return $reply;
  230.      }
  231.      
  232.       /**
  233.        * Query DNS server for MX entries
  234.        * @return
  235.        */
  236.      function queryMX($domain) {
  237.           $hosts = array();
  238.           $mxweights = array();
  239.           if (function_exists('getmxrr')) {
  240.           getmxrr($domain, $hosts, $mxweights);
  241.      }
  242.      else {
  243.           // windows, we need Net_DNS

  244.           require_once 'Net/DNS.php';
  245.      
  246.           $resolver = new Net_DNS_Resolver();
  247.           $resolver->debug = $this->debug;
  248.           // nameservers to query

  249.           $resolver->nameservers = $this->nameservers;
  250.           $resp = $resolver->query($domain, 'MX');
  251.               if ($resp) {
  252.                    foreach($resp->answer as $answer) {
  253.                         $hosts[] = $answer->exchange;
  254.                         $mxweights[] = $answer->preference;
  255.                    }
  256.               }
  257.               
  258.           }
  259.           return array($hosts, $mxweights);
  260.       }
  261.      
  262.       /**
  263.        * Simple function to replicate PHP 5 behaviour.
  264.        */
  265.      function microtime_float()
  266.      {
  267.        list($usec, $sec) = explode(" ", microtime());
  268.        return ((float)$usec + (float)$sec);
  269.      }
  270.      
  271.      function debug($str)
  272.      {
  273.           if ($this->debug) {
  274.               echo '
    '.htmlentities($str).'
    '
    ;
  275.           }
  276.      }
  277. }
  278. ?>

  279. //调用例子
  280. <?php

  281. // include SMTP Email Validation Class

  282. require_once('testEmailVaild.php');

  283. // the email to validate

  284. $email = '163chenweicai@163.com';
  285. // an optional sender

  286. $sender = 'glb0@chinanetcenter.com';
  287. // instantiate the class

  288. $SMTP_Validator = new SMTP_validateEmail();
  289. // turn on debugging if you want to view the SMTP transaction

  290. $SMTP_Validator->debug = true;
  291. // do the validation

  292. $results = $SMTP_Validator->validate(array($email),$sender);
  293. // view results

  294. echo $email.' is '.($results[$email] ? 'valid' :'invalid')."\n";

  295. // send email?

  296. if ($results[$email]) {
  297.   //mail($email, 'Confirm Email', 'Please reply to this email to confirm', 'From:'.$sender."\r\n"); // send email

  298. }
  299. else {
  300.   echo 'The email addresses you entered is not valid';
  301. }


  302. ?>

以上代码来源于其它地方,由于是上次保持到本地的,已经找不到。若代码所属者看到此代码要求删除可以留言。

    后来在多次的测试中发现,其实sendmail本身对于发送失败的地址会有相关的返回值,此信息可以从$mail->ErrorInfo函数中获取,在failed to load: recipients_字符串后面会有发送失败的地址。我们可以对发送的邮件地址进行多次发送,第一次发送就可以获取失败的地址,然后进行记录并通知,以后的发送读取发送的失败的地址进行过滤。从而可以解决这个问题。相比于上述第一种方法,会多一次发送的时间,但是在准确性方面却有很好的保证。

阅读(5591) | 评论(0) | 转发(0) |
0

上一篇:php并发处理

下一篇:VC++中文件类型小结

给主人留下些什么吧!~~