Main Page | Directories | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | File Members | Related Pages | Examples

class.t3lib_readmail.php

Go to the documentation of this file.
00001 <?php
00002 /***************************************************************
00003 *  Copyright notice
00004 *
00005 *  (c) 1999-2004 Kasper Skaarhoj (kasperYYYY@typo3.com)
00006 *  All rights reserved
00007 *
00008 *  This script is part of the TYPO3 project. The TYPO3 project is
00009 *  free software; you can redistribute it and/or modify
00010 *  it under the terms of the GNU General Public License as published by
00011 *  the Free Software Foundation; either version 2 of the License, or
00012 *  (at your option) any later version.
00013 *
00014 *  The GNU General Public License can be found at
00015 *  http://www.gnu.org/copyleft/gpl.html.
00016 *  A copy is found in the textfile GPL.txt and important notices to the license
00017 *  from the author is found in LICENSE.txt distributed with these scripts.
00018 *
00019 *
00020 *  This script is distributed in the hope that it will be useful,
00021 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00022 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00023 *  GNU General Public License for more details.
00024 *
00025 *  This copyright notice MUST APPEAR in all copies of the script!
00026 ***************************************************************/
00087 class t3lib_readmail {
00088    var $dateAbbrevs = array(
00089       'JAN' => 1,
00090       'FEB' => 2,
00091       'MAR' => 3,
00092       'APR' => 4,
00093       'MAY' => 5,
00094       'JUN' => 6,
00095       'JUL' => 7,
00096       'AUG' => 8,
00097       'SEP' => 9,
00098       'OCT' => 10,
00099       'NOV' => 11,
00100       'DEC' => 12
00101    );
00102    var $serverGMToffsetMinutes = 60;      // = +0100 (CET)
00103 
00104 
00105 
00106 
00107 
00108 
00109    /*******************************
00110     *
00111     * FUNCTIONS for the Dmailer
00112     *
00113     ********************************/
00114 
00122    function find_MIDfromReturnPath($to)   {
00123       $parts = explode('mid',strtolower($to));
00124       $moreParts=explode('_',$parts[1]);
00125       $out=array(
00126          'mid' => $moreParts[0],
00127          'rtbl' => substr($moreParts[1],0,1),
00128          'rid' => intval(substr($moreParts[1],1))
00129       );
00130       if ($out['rtbl']=='p')     $out['rtbl']='P';
00131 
00132       return($out);
00133    }
00134 
00142    function find_XTypo3MID($content)   {
00143       if (strstr($content,'X-Typo3MID:')) {
00144          $p=explode('X-Typo3MID:',$content,2);
00145          $l=explode(chr(10),$p[1],2);
00146          list($mid,$hash)=t3lib_div::trimExplode('-',$l[0]);
00147          if (md5($mid)==$hash)   {
00148             $moreParts=explode('_',substr($mid,3));
00149             $out=array(
00150                'mid' => $moreParts[0],
00151                'rtbl' => substr($moreParts[1],0,1),
00152                'rid' => substr($moreParts[1],1)
00153             );
00154             return($out);
00155          }
00156       }
00157    }
00158 
00159 
00160 
00161 
00162 
00163 
00164 
00165 
00166 
00167 
00168 
00169 
00170 
00171 
00172 
00173 
00174 
00175    /*******************************
00176     *
00177     * General
00178     *
00179     ********************************/
00180 
00188    function getMessage($mailParts)  {
00189       if ($mailParts['content-type'])  {
00190          $CType = $this->getCType($mailParts['content-type']);
00191          if ($CType['boundary']) {
00192             $parts = $this->getMailBoundaryParts($CType['boundary'],$mailParts['CONTENT']);
00193             $c=$this->getTextContent($parts[0]);
00194          } else {
00195             $c=$this->getTextContent(
00196                'Content-Type: '.$mailParts['content-type'].'
00197                '.$mailParts['CONTENT']
00198             );
00199          }
00200       } else {
00201          $c = $mailParts['CONTENT'];
00202       }
00203       return $c;
00204    }
00205 
00213    function getTextContent($content)   {
00214       $p=$this->extractMailHeader($content);
00215       // Here some decoding might be needed...
00216       // However we just return what is believed to be the proper notification:
00217       return $p['CONTENT'];
00218    }
00219 
00228    function getMailBoundaryParts($boundary,$content)  {
00229       $mParts = explode('--'.$boundary,$content);
00230       unset($mParts[0]);
00231       reset($mParts);
00232       $new=array();
00233       while(list(,$val)=each($mParts)) {
00234          if (trim($val)=='--') break;
00235          $new[] = ltrim($val);
00236       }
00237       return $new;
00238    }
00239 
00248    function getCType($str) {
00249       $parts = explode(';',$str);
00250       $cTypes=array();
00251       $cTypes['ContentType']=$parts[0];
00252       next($parts);
00253       while(list(,$ppstr)=each($parts))   {
00254          $mparts = explode('=',$ppstr,2);
00255          if (count($mparts)>1)   {
00256             $cTypes[strtolower(trim($mparts[0]))]=ereg_replace('^"','',trim(ereg_replace('"$','',trim($mparts[1]))));
00257          } else {
00258             $cTypes[]=$ppstr;
00259          }
00260       }
00261       return $cTypes;
00262    }
00263 
00271    function analyseReturnError($c)  {
00272       $cp=array();
00273       if (strstr($c,'--- Below this line is a copy of the message.'))   {     // QMAIL
00274          list($c)=explode('--- Below this line is a copy of the message.',$c);   // Splits by the QMAIL divider
00275          $cp['content']=trim($c);
00276          $parts = explode('>:',$c,2);
00277          $cp['reason_text']=trim($parts[1]);
00278          $cp['mailserver']='Qmail';
00279          if (eregi('550|no mailbox|account does not exist',$cp['reason_text']))  {
00280             $cp['reason']=550;   // 550 Invalid recipient
00281          } elseif (stristr($cp['reason_text'],'couldn\'t find any host named')) {
00282             $cp['reason']=2;  // Bad host
00283          } elseif (eregi('Error in Header|invalid Message-ID header',$cp['reason_text'])) {
00284             $cp['reason']=554;
00285          } else {
00286             $cp['reason']=-1;
00287          }
00288       } elseif (strstr($c,'The Postfix program'))  {     // Postfix
00289          $cp['content']=trim($c);
00290          $parts = explode('>:',$c,2);
00291          $cp['reason_text']=trim($parts[1]);
00292          $cp['mailserver']='Postfix';
00293          if (stristr($cp['reason_text'],'550')) {
00294             $cp['reason']=550;   // 550 Invalid recipient, User unknown
00295          } elseif (stristr($cp['reason_text'],'553')) {
00296             $cp['reason']=553;   // No such user
00297          } elseif (stristr($cp['reason_text'],'551')) {
00298             $cp['reason']=551;   // Mailbox full
00299          } else {
00300             $cp['reason']=-1;
00301          }
00302       } else { // No-named:
00303          $cp['content']=trim($c);
00304          $cp['reason_text']=trim(substr($c,0,1000));
00305          $cp['mailserver']='unknown';
00306          if (eregi('Unknown Recipient|Delivery failed 550|Receiver not found|User not listed|recipient problem|Delivery to the following recipients failed|User unknown|recipient name is not recognized',$cp['reason_text']))   {
00307             $cp['reason']=550;   // 550 Invalid recipient, User unknown
00308          } elseif (eregi('over quota|mailbox full',$cp['reason_text'])) {
00309             $cp['reason']=551;
00310          } elseif (eregi('Error in Header',$cp['reason_text']))   {
00311             $cp['reason']=554;
00312          } else {
00313             $cp['reason']=-1;
00314          }
00315       }
00316 
00317       return $cp;
00318    }
00319 
00326    function decodeHeaderString($str)   {
00327       $parts = explode('=?',$str,2);
00328       if (count($parts)==2)   {
00329          list($charset,$encType,$encContent)=explode('?',$parts[1],3);
00330          $subparts =explode('?=',$encContent,2);
00331          $encContent=$subparts[0];
00332 
00333          switch(strtolower($encType))  {
00334             case 'q':
00335                $encContent = quoted_printable_decode($encContent);
00336                $encContent = str_replace('_',' ',$encContent);
00337             break;
00338             case 'b':
00339                $encContent=base64_decode($encContent);
00340             break;
00341          }
00342 
00343          $parts[1]=$encContent.$this->decodeHeaderString($subparts[1]); // Calls decodeHeaderString recursively for any subsequent encoded section.
00344       }
00345       return implode('',$parts);
00346    }
00347 
00354    function extractNameEmail($str)  {
00355       $outArr=array();
00356 
00357          // Email:
00358       $reg='';
00359       ereg('<([^>]*)>',$str,$reg);
00360       if (t3lib_div::validEmail($str)) {
00361          $outArr['email']=$str;
00362       } elseif ($reg[1] && t3lib_div::validEmail($reg[1]))  {
00363          $outArr['email']=$reg[1];
00364             // Find name:
00365          list($namePart)=explode($reg[0],$str);
00366          if (trim($namePart)) {
00367             $reg='';
00368             ereg('"([^"]*)"',$str,$reg);
00369             if (trim($reg[1]))   {
00370                $outArr['name']=trim($reg[1]);
00371             } else $outArr['name']=trim($namePart);
00372          }
00373       }
00374       return $outArr;
00375    }
00376 
00383    function getContentTypeData($contentTypeStr) {
00384       $outValue=array();
00385       $cTypeParts = t3lib_div::trimExplode(';',$contentTypeStr,1);
00386       $outValue['_MIME_TYPE']=$cTypeParts[0];   // content type, first value is supposed to be the mime-type, whatever after the first is something else.
00387 
00388       reset($cTypeParts);
00389       next($cTypeParts);
00390       while(list(,$v)=Each($cTypeParts))  {
00391          $reg='';
00392          eregi('([^=]*)="(.*)"',$v,$reg);
00393          if (trim($reg[1]) && trim($reg[2])) {
00394             $outValue[strtolower($reg[1])] = $reg[2];
00395          }
00396       }
00397       return $outValue;
00398    }
00399 
00406    function makeUnixDate($dateStr)  {
00407       $dateParts=explode(',',$dateStr);
00408       $dateStr=count($dateParts)>1 ? $dateParts[1] : $dateParts[0];
00409 
00410       $spaceParts = t3lib_div::trimExplode(' ',$dateStr,1);
00411 
00412       $spaceParts[1]=$this->dateAbbrevs[strtoupper($spaceParts[1])];
00413       $timeParts = explode(':',$spaceParts[3]);
00414       $timeStamp = mktime ($timeParts[0], $timeParts[1], $timeParts[2], $spaceParts[1], $spaceParts[0], $spaceParts[2]);
00415 
00416       $offset = $this->getGMToffset($spaceParts[4]);
00417       $timeStamp-=($offset*60);  // Compensates for GMT by subtracting the number of seconds which the date is offset from serverTime
00418 
00419       return $timeStamp;
00420    }
00421 
00429    function getGMToffset($GMT)   {
00430       $GMToffset=substr($GMT,1,2)*60+substr($GMT,3,2);
00431       $GMToffset*=substr($GMT,0,1)=='+'?1:-1;
00432       $GMToffset-=$this->serverGMToffsetMinutes;
00433       return $GMToffset;
00434    }
00435 
00443    function extractMailHeader($content,$limit=0)   {
00444       if ($limit) $content = substr($content,0,$limit);
00445 
00446       $lines=explode(chr(10),ltrim($content));
00447       $headers=array();
00448       $p='';
00449       while(list($k,$str)=each($lines))      {
00450          if (!trim($str))  break;   // header finished
00451          $parts = explode(' ',$str,2);
00452          if ($parts[0] && substr($parts[0],-1)==':')  {
00453             $p=strtolower(substr($parts[0],0,-1));
00454             if (isset($headers[$p]))   {
00455                $headers[$p.'.'][]=$headers[$p];
00456                $headers[$p]='';
00457             }
00458             $headers[$p]=trim($parts[1]);
00459          } else {
00460             $headers[$p].=' '.trim($str);
00461          }
00462          unset($lines[$k]);
00463       }
00464       if (!$limit)   $headers['CONTENT']=ltrim(implode(chr(10),$lines));
00465       return $headers;
00466    }
00467 
00474    function fullParse($content)  {
00475          // *************************
00476          // PROCESSING the HEADER part of the mail
00477          // *************************
00478 
00479          // Splitting header and body of mail:
00480       $mailParts = $this->extractMailHeader($content);
00481 
00482          // Decoding header values which potentially can be encoded by =?...?=
00483       $list = explode(',','subject,thread-topic,from,to');
00484       while(list(,$headerType)=each($list))  {
00485          if (isset($mailParts[$headerType])) $mailParts[$headerType]=$this->decodeHeaderString($mailParts[$headerType]);
00486       }
00487          // Separating email/names from header fields which can contain email addresses.
00488       $list = explode(',','from,to,reply-to,sender,return-path');
00489       while(list(,$headerType)=each($list))  {
00490          if (isset($mailParts[$headerType])) {
00491             $mailParts['_'.strtoupper($headerType)]=$this->extractNameEmail($mailParts[$headerType]);
00492          }
00493       }
00494          // Decode date from human-readable format to unix-time (includes compensation for GMT CET)
00495       $mailParts['_DATE']=$this->makeUnixDate($mailParts['date']);
00496 
00497          // Transfer encodings of body content
00498       switch(strtolower($mailParts['content-transfer-encoding'])) {
00499          case 'quoted-printable':
00500             $mailParts['CONTENT']=quoted_printable_decode($mailParts['CONTENT']);
00501          break;
00502          case 'base64':
00503             $mailParts['CONTENT']=base64_decode($mailParts['CONTENT']);
00504          break;
00505       }
00506 
00507          // Content types
00508       $mailParts['_CONTENT_TYPE_DAT']=$this->getContentTypeData($mailParts['content-type']);
00509 
00510 
00511          // *************************
00512          // PROCESSING the CONTENT part of the mail (the body)
00513          // *************************
00514       $cType = strtolower($mailParts['_CONTENT_TYPE_DAT']['_MIME_TYPE']);
00515       $cType = substr($cType,0,9);  // only looking for 'multipart' in string.
00516       switch($cType) {
00517 /*       case 'multipart/mixed':
00518          case 'multipart/related':
00519          case 'multipart/alternative':
00520          case 'multipart/signed':
00521 */
00522          case 'multipart':
00523             if ($mailParts['_CONTENT_TYPE_DAT']['boundary'])   {
00524                $contentSectionParts = t3lib_div::trimExplode('--'.$mailParts['_CONTENT_TYPE_DAT']['boundary'],$mailParts['CONTENT'],1);
00525                $contentSectionParts_proc=array();
00526 
00527                reset($contentSectionParts);
00528                while(list($k,$v)=each($contentSectionParts))   {
00529                   if (substr($v,0,2)=='--')  break;
00530                   $contentSectionParts_proc[$k]=$this->fullParse($v);
00531                }
00532                $mailParts['CONTENT']=$contentSectionParts_proc;
00533             } else $mailParts['CONTENT'] = 'ERROR: No boundary found.';
00534          break;
00535          default:
00536             if (strtolower($mailParts['_CONTENT_TYPE_DAT']['charset'])=='utf-8') {
00537                $mailParts['CONTENT']=utf8_decode($mailParts['CONTENT']);
00538             }
00539          break;
00540       }
00541       return $mailParts;
00542    }
00543 }
00544 
00545 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_readmail.php'])   {
00546    include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_readmail.php']);
00547 }
00548 ?>

Generated on Sun Oct 3 01:05:49 2004 for TYPO3core 3.7.0 dev by  doxygen 1.3.8-20040913