php验证邮件地址的有效性

			SMTP和STMP命令
具体SMTP指令问题不做深究 有兴趣者可参考http://www.magicwinmail.com/technic_smtp.php
Smtp(Simple Mail Transfer 
Protocol)协议是为保证电子邮件的可靠和高效传输,TCP/IP协议的应用层中包含有SMTP协议,但是事实上其与传输系统和机制无关,只要一个
可靠的数据流通道,该协议可以工作在TCP上,也可以工作在NCP,NITS等协议上,在TCP上,其使用端口25进行传输。STMP的重要特点是可以交
互的通信系统中传发邮件。
    SMTP提供了一种邮件传输的机制,当接受方和发送方都种子 一 
个网络上时,可以把邮件直接传给对方,当双方不在同一网络上时,需要通过一个或几个中间服务器转发。STMP首先由发送方提供声请,要求与控接方SMTP
建立双向通道,接收方可以是最后接件人也可以是中间转发的服务器,接收服务器确认可以建立连接后,双发就可以开始通信。
    发送方SMTP向接受方发出Mail命令,告知发送方的身份,如果回答OK。发送方再发出RCPT命令,告知收件人的身份,接收方SMTP确认是否接收或转发,如果同意就回答OK,接下来几可以进程数据传输拉。
    那SMTP 的命令是什么拉?STMP中定义15个命令,其中SMTP工作的基本的命令有7个,HELO,MAILFROM,RCPT TO,DATA,REST,NOOP和QUIT;
下面我们介绍一下这几个命令:
    HELO:发送方问候接收方,后面是发件人的服务器地址或标志;
    MAILFROM:开始发送邮件,起后面跟随发送邮件发送方 的地址;
    RCPT TO:接受方收件人的邮箱
    DATA:接收方把把该命令之后的数据作为发送数据;
    REST:接收方复位;
    NOOP:这个命令不影响任何参数,只是要求接收回答OK,不会影响缓冲区的数据;
    OUIT;SMTP要求接受方需要回答OK;然后中断传输在接到这个命令并回答OK前,接受方不得中断连接,即使传输出现错误。 
<?php
/**
 * Validate Email Addresses Via SMTP
 * This queries the SMTP server to see if the email address isaccepted.
 * @author [email protected]
 * @version 0.1a
 */
header("Content-type: text/html; charset=utf-8");
class SMTP_validateEmail {

      /**
       * PHP Socket resource to remote MTA
       * @var resource $sock
       */
      var $sock;
     
      /**
       * Current User being validated
       */
      var $user;
      /**
       * Current domain where user is being validated
       */
      var $domain;
      /**
       * List of domains to validate users on
       */
      var $domains;
      /**
       * SMTP Port
       */
      var $port = 25;
      /**
       * Maximum Connection Time to wait for connectionestablishment per MTA
       */
      var $max_conn_time = 30;
      /**
       * Maximum time to read from socket before giving up
       */
      var $max_read_time = 5;
     
      /**
       * username of sender
       */
      var $from_user = 'user';
      /**
       * Host Name of sender
       */
      var $from_domain = 'localhost';
     
      /**
       * Nameservers to use when make DNS query for MX entries
       * @var Array $nameservers
       */
      var $nameservers = array(
          '192.168.0.1'
      );
     
      var $debug = false;
     
      /**
       * Initializes the Class
       * @return SMTP_validateEmail Instance
       * @param $email Array[optional] List of Emails toValidate
       * @param $sender String[optional] Email of validator
       */
      function SMTP_validateEmail($emails = false, $sender =false)
      {
          if ($emails) {
               $this->setEmails($emails);
          }
          if ($sender) {
               $this->setSenderEmail($sender);
          }
      }
     //解析邮箱地址
      function _parseEmail($email)
      {
          $parts = explode('@', $email);
          $domain = array_pop($parts);
          $user= implode('@', $parts);
          return array($user, $domain);
      }
     
      /**
       * 设置受事邮件地址
       * @param $emails Array List of Emails
       */
      function setEmails($emails)
      {
          foreach ($emails as $email) {
              list($user, $domain) = $this->_parseEmail($email);
              if (!isset($this->domains[$domain])) {
                    $this->domains[$domain] = array();
              }
              $this->domains[$domain][] = $user;
          }
      }
     
      /**
       * Set the Email of the sender/validator
       * @param $email String
       */
      function setSenderEmail($email)
      {
          $parts = $this->_parseEmail($email);
          $this->from_user = $parts[0];//邮箱地址
          $this->from_domain = $parts[1];//邮箱域名
      }
     
      /**
      * Validate Email Addresses
      * @param String $emails Emails to validate (recipientemails)
      * @param String $sender Sender's Email
      * @return Array Associative List of Emails and theirvalidation results
      */
      function validate($emails = false, $sender = false)
      {
          
          $results = array();
     
          if ($emails) {
                  //设置受事邮件地址
               $this->setEmails($emails);
          }
          if ($sender) {
          //设置发信人
               $this->setSenderEmail($sender);
          }
     
          // query the MTAs on each Domain

          foreach($this->domains as $domain=>$users) {
     
          $mxs = array();
     
          // current domain being queried

          $this->domain = $domain;
      
          // retrieve SMTP Server via MX query on domain

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

          for($n = 0; $n < count($hosts); $n++){
              $mxs[$hosts[$n]] = $mxweights[$n];
          }
          asort($mxs);
     
          // last fallback is the original domain

          $mxs[$this->domain] = 0;
      
          $this->debug(print_r($mxs, 1));
      
          $timeout = $this->max_conn_time;
       
          // try each host

          while(list($host) = each($mxs)) {
              // 用fsockopen链接受事地址STMP服务器
                
              $this->debug("try $host:$this->port\n");
              if ($this->sock = fsockopen($host, $this->port, $errno, $errstr, (float) $timeout)) {
                  stream_set_timeout($this->sock, $this->max_read_time);
                   break;
              }
          }

     
          //did we get a TCP socket

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

                  foreach($users as $user) {
                   $results[$user.'@'.$domain] = false;
                   }
                   continue;
              }
              
              // say helo

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

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

              foreach($users as $user) {
            
                   // ask of recepient 请求受事邮件地址
                   $reply = $this->send("RCPT TO: <".$user.'@'.$domain.">");
                
                  // get code and msg from response 获得返回码

                   preg_match('/^([0-9]{3}) /ims', $reply,$matches);
                   $code = isset($matches[1]) ? $matches[1] : '';
              
                   if ($code == '250') {
                   // you received 250 so the email address was accepted 250表示已收信

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

                        $results[$user.'@'.$domain] =true;
                   }
                   else {
                        $results[$user.'@'.$domain] =false;
                   }
            
             }
            
              // reset before quit

              $this->send("RSET");
            
              // quit

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

              fclose($this->sock);
              }
          }
          return $results;
      }
     
     //向受事服务器发送指令
     function send($msg) {
          fwrite($this->sock, $msg."\r\n");
     
          $reply = fread($this->sock, 2082);
     
          $this->debug("END\n$msg\n");
          $this->debug("START\n$reply");
      
          return $reply;
     }
     
      /**
       * Query DNS server for MX entries  getmxrr()函数取得指定网址 DNS 记录之 MX 字段。
       * @return
       */
     function queryMX($domain) {
          $hosts = array();
          $mxweights = array();
          if (function_exists('getmxrr')) {
          getmxrr($domain, $hosts, $mxweights);
     }
     else {
          // windows, we need Net_DNS

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

          $resolver->nameservers = $this->nameservers;
          $resp = $resolver->query($domain, 'MX');
              if ($resp) {
                   foreach($resp->answer as $answer) {
                        $hosts[] = $answer->exchange;
                        $mxweights[] = $answer->preference;
                   }
              }
              
          }
          return array($hosts, $mxweights);
      }
     
      /**
       * Simple function to replicate PHP 5 behaviour.http://php.net/microtime
       */
     function microtime_float()
     {
       list($usec, $sec) = explode(" ", microtime());
       return ((float)$usec + (float)$sec);
     }
     
     function debug($str)
     {
          if ($this->debug) {
              echo '<pre>'.htmlentities($str).'</pre>';
          }
     }
}

set_time_limit(0);
 
//清空并关闭输出缓存
ob_end_clean();
flush(); //将输出发送给客户端浏览器 
$mail_list = "add.txt";
$fp = fopen($mail_list,'r');
while(!feof($fp)){
  $list[] = trim(fgets($fp));
}


//$email = '[email protected]';
// an optional sender

$sender = '[email protected]';
// instantiate the class

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

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

foreach($list as $k=>$who){
  if($who != ''){
      $results = $SMTP_Validator->validate(array($who),$sender);
      // view results
      //echo 'ok';
      echo $who.' 是'.($results[$who] ? '有效的' :'无效的')."\n";
      if($results[$who]){
        file_put_contents('result.txt',$who. "\r\n", FILE_APPEND);
      }
      // send email?

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

      }
      else {
        //file_put_contents('result.txt',$who. "\r\n", FILE_APPEND);
        //echo 'The email addresses you entered is not valid';
      }
  }
}

本文出自 “长长技术博客” 博客,谢绝转载!

你可能感兴趣的:(PHP,验证,邮件真实性)