Heim >php教程 >php手册 >一个邮件解码类

一个邮件解码类

WBOY
WBOYOriginal
2016-06-21 09:05:51822Durchsuche

 
    /**这个是改自pear中的解码类,增加了多种解码方式,修正了源码的系列bug.将解出的邮件分正文和附件存储,提高了解码效率。
    * Mime decode class
    *
    * this class used at undecode Mime Files
    * useage:
    *
    *    $message=GetMessage($filename,$read_type,$read_size);    
    *    $structure=RdMail($message);
    *    $from=$structure->headers['from'];
    *    $to=$structure->headers['to'];
    *
    * @copyright (c) 2004, richard,bjcctv. All rights reserved.
    * @author richard,bjcctv
    * @date:2004-11-24 last modified at:2005-06-01
    * @package MimeDecode
    * @version $Id$
    */
 
class Decode_Mimemail
{
 
    /**
     * Mime File
     * @var    string
     */
    var $_input;
 
    /**
     * header string
     * @var    string
     */
    var $_header;
 
    /**
     * body string
     * @var    string
     */
    var $_body;
 
    /**
     * err info
     * @var    string
     */
    var $_error;
 
    /**
     * whether include body object
     * @var    boolean
     */
    var $_include_bodies;
 
    /**
     * whether include body object
     * @var    boolean
     */
    var $_decode_bodies;
 
    /**
     * whether decode headers object
     * @var    boolean
     */
    var $_decode_headers;
 
    /**
     * crlf variable
     * @var    string
     */
    var $_crlf;
 
    /**
     * body parts
     * @var object
     */
    var $parts;
    var $mid;
    var $maildir;
 
    /**
     * Constructor.
     *
     * Sets up the object, initialise the variables, and splits and
     * stores the header and body of the input.
     *
     * @param string The input to decode
     * @access public
     */
     
    function Decode_Mimemail($input, $mid, $maildir, $crlf = "\n")
    {
        $this->_crlf   = "\n";
        list($header, $body)    = $this->splitBodyHeader($input); //拆分信头和信体两块
        $this->_input            = $input;
        $this->_header            = $header;
        $this->_body            = $body;
        $this->mid                = $mid;
        $this->maildir            = $maildir;
        $this->_decode_bodies    = false;
        $this->_include_bodies    = true;
    }
 
    /**
     * Begins the decoding process. If called statically
     * it will create an object and call the decode() method
     * of it.
     *
     * @param array An array of various parameters that determine
     *              various things:
     *              include_bodies - Whether to include the body in the returned
     *                               object.
     *              decode_bodies  - Whether to decode the bodies
     *                               of the parts. (Transfer encoding)
     *              decode_headers - Whether to decode headers
     *              input          - If called statically, this will be treated
     *                               as the input
     * @return object Decoded results
     * @access public
     */
    
    function decode($params = null)
    {
        // Have we been called statically?
        // If so, create an object and pass details to that.
        if (!isset($this) AND isset($params['input']))
        {
            if (isset($params['crlf']))
            {
                $obj = new Decode_Mimemail($params['input'],$params['mid'],$params['maildir'],$params['crlf']);
            }
            else
            {
                $obj = new Decode_Mimemail($params['input'],$params['mid'],$params['maildir']);
            }
            $structure = $obj->decode($params);
 
        // Called statically but no input
        }
        elseif (!isset($this))
        {
            return $this->_error="Called statically and no input given";
 
        // Called via an object
        }
        else
        {
            $this->_include_bodies = isset($params['include_bodies'])
                                        ? $params['include_bodies']
                                        : false;
            $this->_decode_bodies  = isset($params['decode_bodies'])
                                        ? $params['decode_bodies']
                                        : false;
            $this->_decode_headers = isset($params['decode_headers'])
                                        ? $params['decode_headers']
                                        : false;
            if (is_null($this->_header) || is_null($this->_body)
                || is_null($this->mid) || is_null($this->maildir))
            {
                    $structure = false;
            }
            else
            {
                $structure = $this->_decode($this->_header, $this->_body, $this->mid, $this->maildir);
            }
            if($structure === false)
            {
                $structure = $this->_error;
            }
        }
        return $structure;
    }
 
    /**
     * Performs the decoding. Decodes the body string passed to it
     * If it finds certain content-types it will call itself in a
     * recursive fashion
     *
     * @param string Header section
     * @param string Body section
     * @param string mid mime filename
     * @return object Results of decoding process
     * @access private
     */
 
    function _decode($headers, $body, $mid, $maildir, $default_ctype = 'text/plain')
    {
        $return = new stdClass;
        if(!is_null($headers))
        {
            $headers = $this->parseHeaders($headers);
        }
        else{
            $this->_error="the mime headers is null.";
            return $this->_error;
        }
 
        foreach ($headers as $value)
        {
            if (isset($return->headers[$value['name']]) AND !is_array($return->headers[$value['name']]))
            {
                $return->headers[$value['name']]   = array($return->headers[$value['name']]);
                $return->headers[$value['name']][] = $value['value'];
            }
            elseif (isset($return->headers[$value['name']]))
            {
                $return->headers[$value['name']][] = $value['value'];
            }
            else
            {
                $return->headers[$value['name']] = $value['value'];
            }
        }
        reset($headers); 
        //rewinds array's internal pointer to the first element and returns the value of the first array element. 
        while (list($key, $value) = each($headers))
        {
            $headers[$key]['name'] = strtolower($headers[$key]['name']); 
            switch ($headers[$key]['name'])
            {
                case 'content-type':
                    $content_type = $this->parseHeaderValue($headers[$key]['value']); 
                    if (preg_match('/([0-9a-z+.-]+)/([0-9a-z+.-]+)/i', $content_type['value'], $regs))
                    {
                        $return->ctype_primary   = $regs[1];
                        $return->ctype_secondary = $regs[2];
                    }
                    if (isset($content_type['other']))
                    {
                        while (list($p_name, $p_value) = each($content_type['other']))
                        {
                            $return->ctype_parameters[$p_name] = $p_value;
                        }
                    }
                    break;
 
                case 'content-disposition':
                    $content_disposition = $this->parseHeaderValue($headers[$key]['value']);
                    $return->disposition   = $content_disposition['value'];
                    if (isset($content_disposition['other']))
                    {
                        while (list($p_name, $p_value) = each($content_disposition['other'])) 
                        {
                            $return->d_parameters[$p_name] = $p_value;
                        }
                    }
                    break;
                case 'content-transfer-encoding':
                    if(!is_null($this->parseHeaderValue($headers[$key]['value'])))
                    {
                        $content_transfer_encoding = $this->parseHeaderValue($headers[$key]['value']);
                    }
                    else{
                        $content_transfer_encoding = "";
                    }
                    break;
            }
        }
        if (isset($content_type))
        {
            $content_type['value'] = strtolower($content_type['value']);
            switch ($content_type['value'])
            {
                case 'text':
                case 'text/plain':
                    if($this->_include_bodies)
                    {
                        if($this->_decode_bodies)
                        {
                            $return->body = isset($content_transfer_encoding['value'])
                                        ?$this->decodeBody($body,$content_transfer_encoding['value'])
                                        : $body;
                        }
                        else{
                            $return->body = $body;
                        }
                        
                        if(!isset($content_type['other']['charset']))
                        {
                            $content_type['other']['charset']="gb2312";
                        }
                        if($content_type['other']['charset'] != "")
                        {
                            $orim_str = "----- Original Message -----";
                            $orim_startpos = strpos($return->body,$orim_str);
                            if(is_int($orim_startpos))
                            {
                                $return->body = $return->body;
                            }
                            else{
                                $return->body    = str_replace("body);
                                $return->body    = str_replace(">",">",$return->body);
                                $return->body    = str_replace("\n","
",$return->body);
                                $return->body    = str_replace(" ","   ",$return->body);
                            }
                        }
                    }
                    $return->body = $this->ConverUrltoLink($return->body);
                     $return->body    = str_replace("
","
",$return->body);
                     $return->body    = str_replace("   "," ",$return->body);
                    if(strtolower($return->ctype_parameters['charset'])=="utf-8")
                    {
                        $return->body=iconv("utf-8", "gb2312", $return->body);
                    }                 
                    break;
    
                case 'text/html':
                    if($this->_include_bodies)
                    {
                        if($this->_decode_bodies)
                        {
                            $return->body = isset($content_transfer_encoding['value'])
                                        ? $this->decodeBody($body,$content_transfer_encoding['value'])
                                        : $body;
                        }
                        else{
                            $return->body = $body;
                        }
                    }
                    $return->body = $this->ConverUrltoLink($return->body);                
                    if(strtolower($return->ctype_parameters['charset'])=="utf-8")
                    {
                        $return->body=iconv("utf-8", "gb2312", $return->body);
                    }
                    break;
                case 'multipart/mixed':
                case 'multipart/alternative':
                case 'multipart/digest':
                case 'multipart/parallel':
                case 'multipart/report': // RFC1892
                case 'multipart/signed': // PGP
                case 'multipart/related':
                case 'application/x-pkcs7-mime':
                    if(!isset($content_type['other']['boundary']))
                    {
                        $this->_error = 'No boundary found for '.$content_type['value'].' part';
                        return false;
                    }
                    $default_ctype = (strtolower($content_type['value']) === 'multipart/digest')
                                        ? 'message/rfc822'
                                        : 'text/plain';
                    $parts = $this->boundarySplit($body, $content_type['other']['boundary']);
                    
                    if(!isset($return->attlist))
                    {
                        $return->attlist="";
                    }
                    for ($i = 0; $i                     {
                        list($part_header, $part_body) = $this->splitBodyHeader($parts[$i]);
                        if (is_null($part_header) || is_null($part_body))
                        {
                            $part = false;
                        }
                        else
                        {
                            $part = $this->_decode($part_header, $part_body, $mid, $maildir, $default_ctype);
                        }
                           if($part === false)
                        {
                               $part =$this->_error;   
                        }
                        if(!is_null($part->ctype_primary) AND !is_null($part->ctype_secondary))
                        {
                            $part_content_type=$part->ctype_primary."/".$part->ctype_secondary;
                        }
                        else{
                            $part_content_type="";
                        }
 
                        if(isset($part->body))
                        {
                            if(isset($part->headers['content-transfer-encoding']) AND !is_null($part->headers['content-transfer-encoding']))
                            {
                                $part->body    = $this->decodeBody($part->body,$part->headers['content-transfer-encoding']);
                            }
                            else{
                                $part->body    = $part->body;
                            }
                        }
                        /**
                         * if part exists with filename/name,save to disk.
                         */
                        if(!isset($part->body))
                        {
                            $part->body = $this->decodeBody($part_body, "base64");
                        } 
                        
                        if((($part->ctype_primary."/".$part->ctype_secondary=="message/rfc822") OR ($part->ctype_parameters['name']!="") OR ($part->headers['content-id']!="") OR (isset($part->d_parameters['filename']) AND isset($part->disposition))) AND isset($part->body))
                        {                    
                            $att_savename= $mid.".att".$i;    //attachment save name.
                            $user_cache=$this->maildir;
                            if(!empty($user_cache) AND !empty($att_savename))
                            {
                                $att_file=$user_cache."/".$att_savename;
                            }
                            else
                            {
                                $att_file="";
                                $return->parts[] = $part;
                                break;
                            }
                            $att_filename    = $part->ctype_parameters['name'];
                            if($att_filename=="")
                            {
                                $att_filename = $part->d_parameters['filename']==""
                                                ? $att_filename = "autofile".$i
                                                : $part->d_parameters['filename'];
                                //if the attachment is the type of rfc/822,and filename is null
                                //rename to autofile with ".eml"
                                if(($part->ctype_primary."/".$part->ctype_secondary=="message/rfc822") and $att_filename=="autofile".$i)
                                {
                                    $att_filename = $att_filename.".eml";  
                                }
                            }
                            $this->createAttfiles($att_file,$part->body);
     ,                        $attfile_size=filesize($att_file);
                            $return->attlist.=$att_filename."|".$attfile_size."|".$att_savename."|".$part_content_type."\n";
                            $logName=$user_cache."/.attlog";
                            $LogContent = $att_savename."\n";
                            $this->CreateLog($logName,$LogContent);
                            $part->body = ""; //released the used memory
                        }
                        else
                        {
                            if(isset($part->body))
                            {
                                $return->body=$part->body;
                            }
                        }
                        $return->parts[] = $part;
                    }
                    break;
                  case 'image/gif':
                  case 'image/jpeg':
                    break;
                default:
                    if($this->_include_bodies)
                    {
                        if($this->_decode_bodies)
                        {
                            $return->body = isset($content_transfer_encoding['value'])
                                        ?$this->decodeBody($body,$content_transfer_encoding['value'])
                                        :$body;
                        }
                        else{
                            $return->body = $body;
                        }
                    }
                    break;
            } // end switch
 
        }
        else {
            //process if content-type isn't exist.
            $ctype = explode('/', $default_ctype);
            $return->ctype_primary   = $ctype[0];
            $return->ctype_secondary = $ctype[1];
            $this->_include_bodies
                ? $return->body = ($this->_decode_bodies
                                    ? $this->decodeBody($body)
                                    : $body)
                : null;
                if($this->_include_bodies)
                {
                    $orim_str = "----- Original Message -----";
                    $orim_startpos = strpos($return->body,$orim_str);
                    if(is_int($orim_startpos))
                    {
                        $return->body = $return->body;
                    }
                    else{
                        $return->body    = str_replace("\n","
",$return->body);
                        $return->body    = str_replace(" ","   ",$return->body);
                    }
                }
                $return->body    = $this->ConverUrltoLink($return->body);
                 $return->body    = str_replace("
","
",$return->body);
                 $return->body    = str_replace("   "," ",$return->body);
                if(strtolower($return->ctype_parameters['charset'])=="utf-8")
                {
                      $return->body=iconv("utf-8", "gb2312", $return->body);
                }                 
        } //end else
       if(0attlist))
       {        
               $return->attlist  = substr($return->attlist,0,(strlen($return->attlist)-1)); 
       }   
       return $return;
    }
 
    /**
     * Given a string containing a header and body
     * section, this function will split them (at the first blank line) and return them.
     *
     * @param string Input to split apart
     * @return array Contains header and body section
     * @access private
     */
 
    function splitBodyHeader($input)
    {
        $pos = strpos($input, $this->_crlf.$this->_crlf);
        if ($pos === false)
        {
            $this->_error = 'Could not split header and body';
            return false;
        }
 
        $header = substr($input, 0, $pos);
        $body   = substr($input, $pos+(2*strlen($this->_crlf)));
        return array($header, $body);
    }
 
    /**
     * Parse headers given in $input and return as assoc array.
     *
     * @param string Headers to parse
     * @return array Contains parsed headers
     * @access private
     */
 
    function parseHeaders($input)
    {
        if ($input !== '')
        {
            // Unfold the input
            $input   = preg_replace('/' . $this->_crlf . "(\t| )/", ' ', $input);
            $headers = explode($this->_crlf, trim($input));
 
            foreach ($headers as $value)
            {
                $hdr_name = strtolower(substr($value, 0, $pos = strpos($value, ':')));
                $hdr_value = substr($value, $pos+1);
                $return[] = array(
                                  'name'  => $hdr_name,
                                  'value' => $this->_decode_headers
                                                ? $this->decodeHeader($hdr_value)
                                             &nbs

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Vorheriger Artikel:制作中文(繁简)的PDFNächster Artikel:PHP学习笔记-SESSION的使用