本类参考了网上关于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上测试成功。

简单范例:

<?php
    require("mailer.class.php");
    $mailer=new  mailer();
    $mailer->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

<?php 
/** 
* Project:     Dowebs.Lib: the PHP compiling template  engine 
* File:        mailer.lib.php 
* 
* This library is opensource  software; 
* @link http://www.dowebs.net/ 
* @copyright  2004-2005 dowebs.net studio. 
* @author Xie Hengduo xiejuchen@21cn.com 
* @package System  
* @version 1.0.0.0 
*/ 
class mailer{ 
    var $mConfig=array(  
        'dns'    =>"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("<font color='red' size='4'  
face='verdana'><B>[No MX Records 
returned]</b></font>");  
                    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; 
    }

} 
?>