本类参考了网上关于PHP的MIME  MAIL和SMTP发送协议的文章,本类可以在*NUX或WIN平台下并且无需SMTP服务器,直接通过邮件专递方式送到邮件接收方的邮件服务器中。

      需要注意的是在发送大尺寸邮件时,建议在服务器允许MAIL()发送的情况下,尽量开启'usemail'=>true,因为用PHP的SOCKE 方式发送效率相对于MAIL()函数来说要低;另外要说明的是由于采用邮件专递的方式邮件没有本地暂存发送,为了可靠性和避免长时间等待的过时问题,所以 在没有启用PHP的MAIL函数时,本类没有添加支持用通过分号分隔的多帐号同时发送的功能。

     本类在nease.net的Linux+php5虚拟主机空间(该空间不能使用PHP自带的MAIL函数发邮件,写此类当时就是为了在这个空间下发送邮件)及win2003+IIS6+php4.3上测试成功。

简单范例:

mConfig['mailform']="xxx@21cn.com";    $isended=$mailer->mail("nobody@example.com","the  subject","hello","From: webmaster@example.com");    if($isended)    {         echo "true";    }    else    {        echo "false";    }?>

类文件: mailer.class.php

"202.96.104.16",                //设置解域MX记录的域名服务器          'mailform'    =>"yourname@yourdomain.com",//发送邮件的帐号          'charset'    =>"utf-8",                    //HTML附件编码          'usemail'    =>false                        //是否使用PHP中的MAIL函数     );      var $dns_repl_domain="";     var $arrMX    =array();     var  $error    ="";    var $aattach    =array();     var $xheaders    =array();     var  $ctencoding    = "7bit";     var $priorities = array( '1 (Highest)', '2  (High)', '3 (Normal)', '4 (Low)', '5 (Lowest)' );     var $content_type='';           function mailer()     {              }           //兼容的mail函数     function  mail($to,$subject,$message,$additional_headers='')     {          if($this->mConfig['usemail'])         {             return  mail($to,$subject,$message,$additional_headers);         }         else          {             if($this->queryMailStmp($to))             {                  $this->error="2 收件人邮箱地址非法";                 return  false;             }             //连接服务器              $is_sockopen=false;             $hostname="";              foreach($this->arrMX as $value)             {                 if($fp  = fsockopen ($value, 25, $errno, $errstr, 60))                 {                      $hostname=$value;                      $is_sockopen=true;                     break;                 }              }             if (!$is_sockopen){$this->error="3  联接服务器失败";return false;}            //HELO             fputs($fp,"HELO {$hostname}\r\n");              $lastmessage = fgets($fp,1024);              if(substr($lastmessage,0,3) != 220 ){$this->error="4 错误信息$lastmessage";return  false;}             //FROM:             fputs( $fp,"MAIL  FROM:<{$this->mConfig['mailform']}>"."\r\n");              $lastmessage = fgets ($fp,1024);             if (substr($lastmessage,0,3) !=  250){$this->error="5 错误信息$lastmessage";return false;}             //TO:              fputs( $fp,"RCPT TO:<$to>"."\r\n");              $lastmessage = fgets ($fp,1024);             if (substr($lastmessage,0,3) !=  250){$this->error="6 错误信息$lastmessage";return false;}              while(true){                 $lastmessage = fgets($fp,512);                  if((substr($lastmessage,3,1) !=  "-")||(empty($lastmessage)))break;             }             //DATA              fputs($fp,"DATA\r\n");             $lastmessage = fgets  ($fp,1024);             if (substr($lastmessage,0,3) !=  354){$this->error="7 错误信息$lastmessage";return false;}              $message="\n".$message;             if($additional_headers!='')              {                 $message =  $additional_headers."\r\n".$message;             }             //处理To头              $head="To: $to\r\n";             $message = $head.$message;              //处理Subject头             $head="Subject: $subject\r\n";              $message = $head.$message;             //加上结束串              $message .= "\r\n.\r\n";             //发送信息              fputs($fp, $message);             fputs($fp,"QUIT\r\n");              fclose($fp);             return true;         }     }    //邮址初步校验     function is_valid_email ($email = "")     {          return preg_match('/^[.\w-]+@([\w-]+\.)+[a-zA-Z]{2,6}$/',$email);      }    function queryMailStmp($mailaddr)     {          if($this->is_valid_email($mailaddr))         {              $this->mxlookup(substr(strstr($mailaddr,'@'),1));         }          else         {             return false;         }     }      //取得MX记录     function mxlookup($domain)     {          if(function_exists('getmxrr'))         {              getmxrr($domain,$this->arrMX);         }         else         {              ##########################             $dot_pos = 0; $temp =  "";             $QNAME="";              while($dot_pos=strpos($domain,"."))             {                  $temp   = substr($domain,0,$dot_pos);                 $domain =  substr($domain,$dot_pos+1);                 $QNAME .=  chr(strlen($temp)).$temp;             }             $QNAME .=  chr(strlen($domain)).$domain.chr(0);             ###########################              $dns_packet =  chr(0).chr(1).chr(1).chr(0).chr(0).chr(1).chr(0).chr(0).chr(0).chr(0).chr(0).chr(0).$QNAME.chr(0).chr(15).chr(0).chr(1);              $dns_socket = fsockopen("udp://{$this->mConfig['dns']}", 53);              fwrite($dns_socket,$dns_packet,strlen($dns_packet));              $this->dns_reply = fread($dns_socket,1);              $bytes = stream_get_meta_data($dns_socket);             $this->dns_reply  .= fread($dns_socket,$bytes['unread_bytes']);              fclose($dns_socket);             $this->cIx=6;              $this->Total_Accounts="";             for($i=0;$i<2;$i++){                   $this->Total_Accounts.=ord(substr($this->dns_reply,$this->cIx,1));                  $this->cIx++;             }              $this->cIx+=4;              $this->parse_data($this->dns_repl_domain);              $this->cIx+=7;              for($ic=1;$ic<=$this->Total_Accounts;$ic++) {                 $QTYPE =  ord($this->gdi($this->cIx));                 if($QTYPE!==15){                      print("
[No MX Records returned]");                      die();                 }                  $this->cIx+=9;                 $mxPref =  ord($this->gdi($this->cIx));                  $this->parse_data($curmx);                 $this->arrMX[] =$curmx;                  $this->cIx+=3;             }         }     }      function gdi(&$cIx,$bytes=1) {         $this->cIx++;          return(substr($this->dns_reply, $this->cIx-1, $bytes));      }     function parse_data(&$retval) {         $arName =  array();         $byte = ord($this->gdi($this->cIx));          while($byte!==0) {             if($byte==192) { //compressed                     $tmpIx = $this->cIx;                 $this->cIx =  ord($this->gdi($cIx));                 $tmpName = $retval;                  $this->parse_data($tmpName);                 $retval  = $retval.".".$tmpName;                 $this->cIx = $tmpIx+1;                  return;             }             $retval="";              $bCount = $byte;             for($b=0;$b<$bCount;$b++) {                  $retval .= $this->gdi($this->cIx);             }              $arName[]=$retval;             $byte =  ord($this->gdi($this->cIx));         }          $retval=join(".",$arName);     }           ############################################     # MIME MAIL CODE      ############################################     function From( $from="")      {         if($from=='')         {              $this->xheaders['From']=$this->mConfig['mailform'];         }          else         {             $this->xheaders['From'] =  $from;         }     }    function mimemail($to,$subject,$message)     {          $this->boundary= "--" . md5( uniqid("myboundary") );         if(  $this->mConfig['charset'] != "us-ascii" )         {              $this->ctencoding = "8bit";         }         $headers = "";          if( $this->mConfig['charset'] != "") {             //global  $contenttype;             $this->xheaders["Mime-Version"] = "1.0";              $this->xheaders["Content-Type"] = "{$this->content_type};  charset={$this->mConfig['charset']}";              $this->xheaders["Content-Transfer-Encoding"] = $this->ctencoding;          }         $this->xheaders["X-Mailer"] = "Dowebs.net Mailer";          if( count( $this->aattach ) > 0 )         {              $this->xheaders["Content-Type"] = "multipart/mixed;\n  boundary=\"{$this->boundary}\"";             $fullBody="This is a  multi-part message in MIME format.\n--{$this->boundary}\n";              $fullBody.= "Content-Type: text/html;  charset={$this->mConfig['charset']}\nContent-Transfer-Encoding:{$this->ctencoding}\n\n".message."\n";              $sep= chr(13) . chr(10);             $ata= array();              $k=0;             for( $i=0; $i < count(  $this->aattach); $i++ ) {                 $filename =  $this->aattach[$i];                 $basename = basename($filename);                  $ctype = $this->actype[$i];        // content-type                  $disposition = $this->adispo[$i];                  if(!file_exists( $filename)){$this->error="1 Class Mail, method attach : file  {$filename} can't be found";return false;}                 $subhdr=  "--{$this->boundary}\nContent-Type: {$ctype};\n  name=\"{$basename}\";\nContent-Transfer-Encoding: base64\nContent-Disposition:  {$disposition};\n filename=\"{$basename}\"\n";                 $ata[$k++] =  $subhdr;                 $linesz= filesize( $filename)+1;                  $fp= fopen( $filename, 'r' );                 $ata[$k++]  = chunk_split(base64_encode(fread( $fp, $linesz)));                  fclose($fp);             }             $fullBody .= implode($sep, $ata);          }         else         {             $fullBody =  $message;         }         reset($this->xheaders);          while( list( $hdr,$value ) = each( $this->xheaders)) {              $headers .= "$hdr: $value\n";         }                  return  $this->mail($to,$subject,$fullBody,$headers);     }     function  Attach($filename,$filetype = "",$disposition = "inline")     {              if( $filetype == "" )             {                  $filetype = "application/x-unknown-content-type";             }              $this->aattach[] = $filename;              $this->actype[] = $filetype;             $this->adispo[] =  $disposition;     }    function Content_type($contenttype)     {          $this->content_type=$contenttype;     }          function  Priority($priority)     {         if(!intval($priority))return false;          if(!isset($this->priorities[$priority-1]))return false;          $this->xheaders["X-Priority"] =  $this->priorities[$priority-1];         return true;     }} ?>