[ Index ]

PHP Cross Reference of vtigercrm-6.1.0

title

Body

[close]

/modules/Settings/MailConverter/handlers/ -> MailRecord.php (source)

   1  <?php
   2  /*********************************************************************************
   3   ** The contents of this file are subject to the vtiger CRM Public License Version 1.0
   4   * ("License"); You may not use this file except in compliance with the License
   5   * The Original Code is:  vtiger CRM Open Source
   6   * The Initial Developer of the Original Code is vtiger.
   7   * Portions created by vtiger are Copyright (C) vtiger.
   8   * All Rights Reserved.
   9   *
  10   ********************************************************************************/
  11  
  12  /**
  13   * This class provides structured way of accessing details of email.
  14   */
  15  class Vtiger_MailRecord {
  16      // FROM address(es) list 
  17      var $_from;
  18      // TO address(es) list
  19      var $_to;
  20      //var $_replyto;
  21  
  22      // CC address(es) list
  23      var $_cc;
  24      // BCC address(es) list
  25      var $_bcc;
  26      // DATE
  27      var $_date;
  28      // SUBJECT
  29      var $_subject;
  30      // BODY (either HTML / PLAIN message)
  31      var $_body;
  32      // CHARSET of the body content
  33      var $_charset;
  34      // If HTML message was set as body content
  35      var $_isbodyhtml;
  36      // PLAIN message of the original email
  37      var $_plainmessage = false;
  38      // HTML message of the original email
  39      var $_htmlmessage = false;
  40      // ATTACHMENTS list of the email
  41      var $_attachments = false;
  42      // UNIQUEID associated with the email
  43      var $_uniqueid = false;
  44  
  45      // Flag to avoid re-parsing the email body.
  46      var $_bodyparsed = false;
  47  
  48      /** DEBUG Functionality. */
  49      var $debug = false;
  50  	function log($message=false) {
  51          if(!$message) $message = $this->__toString();
  52  
  53          global $log;
  54          if($log && $this->debug) { $log->debug($message); }
  55          else if($this->debug) {
  56              echo var_export($message, true) . "\n";
  57          }
  58      }
  59  
  60      /**
  61       * String representation of the object.
  62       */
  63  	function __toString() {
  64          $tostring = '';
  65          $tostring .= 'FROM: [' . implode(',', $this->_from) . ']';
  66          $tostring .= ',TO: [' . implode(',', $this->_to) . ']';
  67          if (!empty($this->_cc))
  68              $tostring .= ',CC: [' . implode(',', $this->_cc) . ']';
  69          if (!empty($this->_bcc))
  70              $tostring .= ',BCC: [' . implode(',', $this->_bcc) . ']';
  71          $tostring .= ',DATE: [' . $this->_date . ']';
  72          $tostring .= ',SUBJECT: [' . $this->_subject . ']';
  73          return $tostring;
  74      }
  75  
  76      /**
  77       * Constructor.
  78       */
  79  	function __construct($imap, $messageid, $fetchbody=true) {
  80          $this->__parseHeader($imap, $messageid);
  81          if($fetchbody) $this->__parseBody($imap, $messageid);
  82      }
  83  
  84      /**
  85       * Get body content as Text.
  86       */
  87  	function getBodyText($striptags=true) {
  88          $bodytext = $this->_body;
  89  
  90          if($this->_plainmessage) {
  91              $bodytext = $this->_plainmessage;
  92          } else if($this->_isbodyhtml) {
  93              // TODO This conversion can added multiple lines if 
  94              // content is displayed directly on HTML page
  95              $bodytext = preg_replace("/<br>/", "\n", $bodytext);
  96              $bodytext = strip_tags($bodytext);
  97          }
  98          return $bodytext;
  99      }
 100  
 101      /**
 102       * Get body content as HTML.
 103       */
 104  	function getBodyHTML() {
 105          $bodyhtml = $this->_body;
 106          if(!$this->_isbodyhtml) {
 107              $bodyhtml = preg_replace( Array("/\r\n/", "/\n/"), Array('<br>','<br>'), $bodyhtml );
 108          }
 109          return $bodyhtml;
 110      }        
 111  
 112      /**
 113       * Fetch the mail body from server.
 114       */
 115  	function fetchBody($imap, $messageid) {
 116          if(!$this->_bodyparsed) $this->__parseBody($imap, $messageid);
 117      }
 118  
 119      /**
 120       * Parse the email id from the mail header text.
 121       * @access private
 122       */
 123  	function __getEmailIdList($inarray) {
 124          if(empty($inarray)) return Array();
 125          $emails = Array();
 126          foreach($inarray as $emailinfo) {
 127              $emails[] = $emailinfo->mailbox . '@' . $emailinfo->host;
 128          }
 129          return $emails;
 130      }
 131      
 132      /**
 133       * Helper function to convert the encoding of input to target charset.
 134       */
 135  	static function __convert_encoding($input, $to, $from = false) {
 136          static $mb_function = NULL;
 137          static $iconv_function = NULL;
 138  
 139          if ($mb_function === NULL) $mb_function = function_exists('mb_convert_encoding');
 140          if ($iconv_function === NULL) $iconv_function = function_exists('iconv');
 141  
 142          if($mb_function) {
 143              if(!$from) $from = mb_detect_encoding($input);
 144  
 145              if(strtolower(trim($to)) == strtolower(trim($from))) {                         
 146                      return $input;
 147              } else {
 148                  return mb_convert_encoding($input, $to, $from);
 149              }
 150          }
 151          return $input;
 152      }
 153      
 154      /**
 155       * MIME decode function to parse IMAP header or mail information
 156       */
 157  	static function __mime_decode($input, &$words=null, $targetEncoding='UTF-8') {
 158          if(is_null($words)) $words = array();
 159          $returnvalue = $input;
 160          
 161          preg_match_all('/=\?([^\?]+)\?([^\?]+)\?([^\?]+)\?=/', $input, $matches);
 162                  array_filter($matches);
 163                  if(count($matches[0])>0){
 164                  $decodedArray=  imap_mime_header_decode($input);
 165                  foreach($decodedArray as $part=>$prop){
 166                              $decodevalue=$prop->text;
 167                              $charset=$prop->charset;
 168                  $value = self::__convert_encoding($decodevalue, $targetEncoding, $charset);                
 169                  array_push($words, $value);                
 170              }
 171          }
 172          if(!empty($words)) {
 173              $returnvalue = implode('', $words);
 174          }
 175          return $returnvalue;
 176      }
 177      
 178      /**
 179       * MIME encode function to prepare input to target charset supported by normal IMAP clients.
 180       */
 181  	static function __mime_encode($input, $encoding='Q', $charset='iso-8859-1') {
 182          $returnvalue = $input;        
 183          $encoded = false;
 184          
 185          if(strtoupper($encoding) == 'B' ) {
 186              $returnvalue = self::__convert_encoding($input, $charset);
 187              $returnvalue = base64_encode($returnvalue);
 188              $encoded = true;
 189          } else {
 190              $returnvalue = self::__convert_encoding($input, $charset);
 191              if(function_exists('imap_qprint')) {
 192                  $returnvalue = imap_qprint($returnvalue);
 193                  $encoded = true;
 194              } else {
 195                  // TODO: Handle case when imap_qprint is not available.
 196              }
 197          }
 198          if($encoded) {
 199              $returnvalue = "=?$charset?$encoding?$returnvalue?=";
 200          }
 201          return $returnvalue;
 202      }
 203  
 204      /**
 205       * Parse header of the email.
 206       * @access private
 207       */
 208  	function __parseHeader($imap, $messageid) {
 209          $this->_from = Array();
 210          $this->_to = Array();
 211  
 212          $mailheader = imap_headerinfo($imap, $messageid);
 213  
 214          $this->_uniqueid = $mailheader->message_id;
 215  
 216          $this->_from = $this->__getEmailIdList($mailheader->from);
 217          $this->_to   = $this->__getEmailIdList($mailheader->to);
 218          $this->_cc   = $this->__getEmailIdList($mailheader->cc);
 219          $this->_bcc  = $this->__getEmailIdList($mailheader->bcc);
 220  
 221          $this->_date = $mailheader->udate;
 222  
 223          $this->_subject = self::__mime_decode($mailheader->subject);
 224          if(!$this->_subject) $this->_subject = 'Untitled';
 225      }
 226      // Modified: http://in2.php.net/manual/en/function.imap-fetchstructure.php#85685
 227  	function __parseBody($imap, $messageid) {
 228          $structure = imap_fetchstructure($imap, $messageid);
 229  
 230          $this->_plainmessage = '';
 231          $this->_htmlmessage = '';
 232          $this->_body = '';
 233          $this->_isbodyhtml = false;
 234  
 235          if($structure->parts) { /* multipart */
 236              foreach($structure->parts as $partno0=>$p) {
 237                  $this->__getpart($imap, $messageid, $p, $partno0+1);
 238              }
 239          } else { /* not multipart */
 240              $this->__getpart($imap, $messageid, $structure, 0);
 241          }
 242  
 243          // Set the body (either plain or html content)
 244          if($this->_htmlmessage != '') {
 245              $this->_body = $this->_htmlmessage;
 246              $this->_isbodyhtml = true;
 247          } else {
 248              $this->_body = $this->_plainmessage;
 249          }
 250  
 251          if($this->_attachments) {
 252              $this->log("Attachments: ");
 253              $filename = array();
 254              $content = array();
 255              $attachmentKeys = array_keys($this->_attachments);
 256              for ($i = 0; $i < count($attachmentKeys); $i++) {
 257                  $filename[$i] = self::__mime_decode($attachmentKeys[$i]);
 258                  $content[$i] = $this->_attachments[$attachmentKeys[$i]];
 259              }
 260              unset($this->_attachments);
 261              for ($i = 0; $i < count($attachmentKeys); $i++) {
 262                  $this->_attachments[$filename[$i]] = $content[$i];
 263              }
 264              $this->log(array_keys($this->_attachments));
 265          }
 266  
 267          $this->_bodyparsed = true;
 268      }
 269      // Modified: http://in2.php.net/manual/en/function.imap-fetchstructure.php#85685    
 270  	function __getpart($imap, $messageid, $p, $partno) {
 271          // $partno = '1', '2', '2.1', '2.1.3', etc if multipart, 0 if not multipart
 272          
 273          // DECODE DATA
 274          $data = ($partno)? 
 275              imap_fetchbody($imap,$messageid,$partno):  // multipart
 276              imap_body($imap,$messageid);               // not multipart
 277      
 278          // Any part may be encoded, even plain text messages, so check everything.
 279          if ($p->encoding==4) $data = quoted_printable_decode($data);
 280          elseif ($p->encoding==3) $data = base64_decode($data);
 281          // no need to decode 7-bit, 8-bit, or binary
 282  
 283          // PARAMETERS
 284          // get all parameters, like charset, filenames of attachments, etc.
 285          $params = array();
 286          if ($p->parameters) {
 287              foreach ($p->parameters as $x) $params[ strtolower( $x->attribute ) ] = $x->value;
 288          }
 289          if ($p->dparameters) {
 290              foreach ($p->dparameters as $x) $params[ strtolower( $x->attribute ) ] = $x->value;
 291          }
 292  
 293          // ATTACHMENT
 294          // Any part with a filename is an attachment,
 295          // so an attached text file (type 0) is not mistaken as the message.
 296          if ($params['filename'] || $params['name']) {
 297              // filename may be given as 'Filename' or 'Name' or both
 298              $filename = ($params['filename'])? $params['filename'] : $params['name'];
 299              // filename may be encoded, so see imap_mime_header_decode()
 300              if(!$this->_attachments) $this->_attachments = Array();
 301              $this->_attachments[$filename] = $data;  // TODO: this is a problem if two files have same name
 302          }
 303  
 304          // TEXT
 305          elseif ($p->type==0 && $data) {            
 306              $this->_charset = $params['charset'];  // assume all parts are same charset
 307              $data = self::__convert_encoding($data, 'UTF-8', $this->_charset);
 308              
 309              // Messages may be split in different parts because of inline attachments,
 310              // so append parts together with blank row.
 311              if (strtolower($p->subtype)=='plain') $this->_plainmessage .= trim($data) ."\n\n";
 312              else $this->_htmlmessage .= $data ."<br><br>";            
 313          }
 314  
 315          // EMBEDDED MESSAGE
 316          // Many bounce notifications embed the original message as type 2,
 317          // but AOL uses type 1 (multipart), which is not handled here.
 318          // There are no PHP functions to parse embedded messages,
 319          // so this just appends the raw source to the main message.
 320          elseif ($p->type==2 && $data) {
 321              $this->_plainmessage .= trim($data) ."\n\n";
 322          }
 323  
 324          // SUBPART RECURSION
 325          if ($p->parts) {
 326              foreach ($p->parts as $partno0=>$p2)
 327                  $this->__getpart($imap,$messageid,$p2,$partno.'.'.($partno0+1));  // 1.2, 1.2.1, etc.
 328          }
 329      }
 330  }
 331  ?>


Generated: Fri Nov 28 20:08:37 2014 Cross-referenced by PHPXref 0.7.1