"TYPO3 4.0.1: typo3_src-4.0.1/t3lib/class.t3lib_readmail.php Source File", "datetime" => "Sat Dec 2 19:22:18 2006", "date" => "2 Dec 2006", "doxygenversion" => "1.4.6", "projectname" => "TYPO3 4.0.1", "projectnumber" => "4.0.1" ); get_header($doxygen_vars); ?>

class.t3lib_readmail.php

00001 <?php
00002 /***************************************************************
00003 *  Copyright notice
00004 *
00005 *  (c) 1999-2006 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 ***************************************************************/
00083 class t3lib_readmail {
00084         var $dateAbbrevs = array(
00085                 'JAN' => 1,
00086                 'FEB' => 2,
00087                 'MAR' => 3,
00088                 'APR' => 4,
00089                 'MAY' => 5,
00090                 'JUN' => 6,
00091                 'JUL' => 7,
00092                 'AUG' => 8,
00093                 'SEP' => 9,
00094                 'OCT' => 10,
00095                 'NOV' => 11,
00096                 'DEC' => 12
00097         );
00098         var $serverGMToffsetMinutes = 60;               // = +0100 (CET)
00099 
00100         /*******************************
00101          *
00102          * General
00103          *
00104          ********************************/
00105 
00113         function getMessage($mailParts) {
00114                 if ($mailParts['content-type']) {
00115                         $CType = $this->getCType($mailParts['content-type']);
00116                         if ($CType['boundary']) {
00117                                 $parts = $this->getMailBoundaryParts($CType['boundary'],$mailParts['CONTENT']);
00118                                 $c=$this->getTextContent($parts[0]);
00119                         } else {
00120                                 $c=$this->getTextContent(
00121                                         'Content-Type: '.$mailParts['content-type'].'
00122                                         '.$mailParts['CONTENT']
00123                                 );
00124                         }
00125                 } else {
00126                         $c = $mailParts['CONTENT'];
00127                 }
00128                 return $c;
00129         }
00130 
00138         function getTextContent($content)       {
00139                 $p=$this->extractMailHeader($content);
00140                 // Here some decoding might be needed...
00141                 // However we just return what is believed to be the proper notification:
00142                 return $p['CONTENT'];
00143         }
00144 
00153         function getMailBoundaryParts($boundary,$content)       {
00154                 $mParts = explode('--'.$boundary,$content);
00155                 unset($mParts[0]);
00156                 reset($mParts);
00157                 $new=array();
00158                 while(list(,$val)=each($mParts))        {
00159                         if (trim($val)=='--') break;
00160                         $new[] = ltrim($val);
00161                 }
00162                 return $new;
00163         }
00164 
00173         function getCType($str) {
00174                 $parts = explode(';',$str);
00175                 $cTypes=array();
00176                 $cTypes['ContentType']=$parts[0];
00177                 next($parts);
00178                 while(list(,$ppstr)=each($parts))       {
00179                         $mparts = explode('=',$ppstr,2);
00180                         if (count($mparts)>1)   {
00181                                 $cTypes[strtolower(trim($mparts[0]))]=ereg_replace('^"','',trim(ereg_replace('"$','',trim($mparts[1]))));
00182                         } else {
00183                                 $cTypes[]=$ppstr;
00184                         }
00185                 }
00186                 return $cTypes;
00187         }
00188 
00196         function analyseReturnError($c) {
00197                 $cp=array();
00198                 if (strstr($c,'--- Below this line is a copy of the message.')) {               // QMAIL
00199                         list($c)=explode('--- Below this line is a copy of the message.',$c);   // Splits by the QMAIL divider
00200                         $cp['content']=trim($c);
00201                         $parts = explode('>:',$c,2);
00202                         $cp['reason_text']=trim($parts[1]);
00203                         $cp['mailserver']='Qmail';
00204                         if (eregi('550|no mailbox|account does not exist',$cp['reason_text']))  {
00205                                 $cp['reason']=550;      // 550 Invalid recipient
00206                         } elseif (stristr($cp['reason_text'],'couldn\'t find any host named')) {
00207                                 $cp['reason']=2;        // Bad host
00208                         } elseif (eregi('Error in Header|invalid Message-ID header',$cp['reason_text'])) {
00209                                 $cp['reason']=554;
00210                         } else {
00211                                 $cp['reason']=-1;
00212                         }
00213                 } elseif (strstr($c,'The Postfix program'))     {               // Postfix
00214                         $cp['content']=trim($c);
00215                         $parts = explode('>:',$c,2);
00216                         $cp['reason_text']=trim($parts[1]);
00217                         $cp['mailserver']='Postfix';
00218                         if (stristr($cp['reason_text'],'550'))  {
00219                                 $cp['reason']=550;      // 550 Invalid recipient, User unknown
00220                         } elseif (stristr($cp['reason_text'],'553')) {
00221                                 $cp['reason']=553;      // No such user
00222                         } elseif (stristr($cp['reason_text'],'551')) {
00223                                 $cp['reason']=551;      // Mailbox full
00224                         } else {
00225                                 $cp['reason']=-1;
00226                         }
00227                 } else {        // No-named:
00228                         $cp['content']=trim($c);
00229                         $cp['reason_text']=trim(substr($c,0,1000));
00230                         $cp['mailserver']='unknown';
00231                         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']))   {
00232                                 $cp['reason']=550;      // 550 Invalid recipient, User unknown
00233                         } elseif (eregi('over quota|mailbox full',$cp['reason_text']))  {
00234                                 $cp['reason']=551;
00235                         } elseif (eregi('Error in Header',$cp['reason_text']))  {
00236                                 $cp['reason']=554;
00237                         } else {
00238                                 $cp['reason']=-1;
00239                         }
00240                 }
00241 
00242                 return $cp;
00243         }
00244 
00251         function decodeHeaderString($str)       {
00252                 $parts = explode('=?',$str,2);
00253                 if (count($parts)==2)   {
00254                         list($charset,$encType,$encContent)=explode('?',$parts[1],3);
00255                         $subparts =explode('?=',$encContent,2);
00256                         $encContent=$subparts[0];
00257 
00258                         switch(strtolower($encType))    {
00259                                 case 'q':
00260                                         $encContent = quoted_printable_decode($encContent);
00261                                         $encContent = str_replace('_',' ',$encContent);
00262                                 break;
00263                                 case 'b':
00264                                         $encContent=base64_decode($encContent);
00265                                 break;
00266                         }
00267 
00268                         $parts[1]=$encContent.$this->decodeHeaderString($subparts[1]);  // Calls decodeHeaderString recursively for any subsequent encoded section.
00269                 }
00270                 return implode('',$parts);
00271         }
00272 
00279         function extractNameEmail($str) {
00280                 $outArr=array();
00281 
00282                         // Email:
00283                 $reg='';
00284                 ereg('<([^>]*)>',$str,$reg);
00285                 if (t3lib_div::validEmail($str)) {
00286                         $outArr['email']=$str;
00287                 } elseif ($reg[1] && t3lib_div::validEmail($reg[1]))    {
00288                         $outArr['email']=$reg[1];
00289                                 // Find name:
00290                         list($namePart)=explode($reg[0],$str);
00291                         if (trim($namePart))    {
00292                                 $reg='';
00293                                 ereg('"([^"]*)"',$str,$reg);
00294                                 if (trim($reg[1]))      {
00295                                         $outArr['name']=trim($reg[1]);
00296                                 } else $outArr['name']=trim($namePart);
00297                         }
00298                 }
00299                 return $outArr;
00300         }
00301 
00308         function getContentTypeData($contentTypeStr)    {
00309                 $outValue=array();
00310                 $cTypeParts = t3lib_div::trimExplode(';',$contentTypeStr,1);
00311                 $outValue['_MIME_TYPE']=$cTypeParts[0]; // content type, first value is supposed to be the mime-type, whatever after the first is something else.
00312 
00313                 reset($cTypeParts);
00314                 next($cTypeParts);
00315                 while(list(,$v)=Each($cTypeParts))      {
00316                         $reg='';
00317                         eregi('([^=]*)="(.*)"',$v,$reg);
00318                         if (trim($reg[1]) && trim($reg[2]))     {
00319                                 $outValue[strtolower($reg[1])] = $reg[2];
00320                         }
00321                 }
00322                 return $outValue;
00323         }
00324 
00331         function makeUnixDate($dateStr) {
00332                 $dateParts=explode(',',$dateStr);
00333                 $dateStr=count($dateParts)>1 ? $dateParts[1] : $dateParts[0];
00334 
00335                 $spaceParts = t3lib_div::trimExplode(' ',$dateStr,1);
00336 
00337                 $spaceParts[1]=$this->dateAbbrevs[strtoupper($spaceParts[1])];
00338                 $timeParts = explode(':',$spaceParts[3]);
00339                 $timeStamp = mktime ($timeParts[0], $timeParts[1], $timeParts[2], $spaceParts[1], $spaceParts[0], $spaceParts[2]);
00340 
00341                 $offset = $this->getGMToffset($spaceParts[4]);
00342                 $timeStamp-=($offset*60);       // Compensates for GMT by subtracting the number of seconds which the date is offset from serverTime
00343 
00344                 return $timeStamp;
00345         }
00346 
00354         function getGMToffset($GMT)     {
00355                 $GMToffset=substr($GMT,1,2)*60+substr($GMT,3,2);
00356                 $GMToffset*=substr($GMT,0,1)=='+'?1:-1;
00357                 $GMToffset-=$this->serverGMToffsetMinutes;
00358                 return $GMToffset;
00359         }
00360 
00368         function extractMailHeader($content,$limit=0)   {
00369                 if ($limit)     $content = substr($content,0,$limit);
00370 
00371                 $lines=explode(chr(10),ltrim($content));
00372                 $headers=array();
00373                 $p='';
00374                 while(list($k,$str)=each($lines))               {
00375                         if (!trim($str))        break;  // header finished
00376                         $parts = explode(' ',$str,2);
00377                         if ($parts[0] && substr($parts[0],-1)==':')     {
00378                                 $p=strtolower(substr($parts[0],0,-1));
00379                                 if (isset($headers[$p]))        {
00380                                         $headers[$p.'.'][]=$headers[$p];
00381                                         $headers[$p]='';
00382                                 }
00383                                 $headers[$p]=trim($parts[1]);
00384                         } else {
00385                                 $headers[$p].=' '.trim($str);
00386                         }
00387                         unset($lines[$k]);
00388                 }
00389                 if (!$limit)    $headers['CONTENT']=ltrim(implode(chr(10),$lines));
00390                 return $headers;
00391         }
00392 
00399         function fullParse($content)    {
00400                         // *************************
00401                         // PROCESSING the HEADER part of the mail
00402                         // *************************
00403 
00404                         // Splitting header and body of mail:
00405                 $mailParts = $this->extractMailHeader($content);
00406 
00407                         // Decoding header values which potentially can be encoded by =?...?=
00408                 $list = explode(',','subject,thread-topic,from,to');
00409                 while(list(,$headerType)=each($list))   {
00410                         if (isset($mailParts[$headerType]))     $mailParts[$headerType]=$this->decodeHeaderString($mailParts[$headerType]);
00411                 }
00412                         // Separating email/names from header fields which can contain email addresses.
00413                 $list = explode(',','from,to,reply-to,sender,return-path');
00414                 while(list(,$headerType)=each($list))   {
00415                         if (isset($mailParts[$headerType]))     {
00416                                 $mailParts['_'.strtoupper($headerType)]=$this->extractNameEmail($mailParts[$headerType]);
00417                         }
00418                 }
00419                         // Decode date from human-readable format to unix-time (includes compensation for GMT CET)
00420                 $mailParts['_DATE']=$this->makeUnixDate($mailParts['date']);
00421 
00422                         // Transfer encodings of body content
00423                 switch(strtolower($mailParts['content-transfer-encoding']))     {
00424                         case 'quoted-printable':
00425                                 $mailParts['CONTENT']=quoted_printable_decode($mailParts['CONTENT']);
00426                         break;
00427                         case 'base64':
00428                                 $mailParts['CONTENT']=base64_decode($mailParts['CONTENT']);
00429                         break;
00430                 }
00431 
00432                         // Content types
00433                 $mailParts['_CONTENT_TYPE_DAT']=$this->getContentTypeData($mailParts['content-type']);
00434 
00435 
00436                         // *************************
00437                         // PROCESSING the CONTENT part of the mail (the body)
00438                         // *************************
00439                 $cType = strtolower($mailParts['_CONTENT_TYPE_DAT']['_MIME_TYPE']);
00440                 $cType = substr($cType,0,9);    // only looking for 'multipart' in string.
00441                 switch($cType)  {
00442 /*                      case 'multipart/mixed':
00443                         case 'multipart/related':
00444                         case 'multipart/alternative':
00445                         case 'multipart/signed':
00446 */
00447                         case 'multipart':
00448                                 if ($mailParts['_CONTENT_TYPE_DAT']['boundary'])        {
00449                                         $contentSectionParts = t3lib_div::trimExplode('--'.$mailParts['_CONTENT_TYPE_DAT']['boundary'],$mailParts['CONTENT'],1);
00450                                         $contentSectionParts_proc=array();
00451 
00452                                         reset($contentSectionParts);
00453                                         while(list($k,$v)=each($contentSectionParts))   {
00454                                                 if (substr($v,0,2)=='--')       break;
00455                                                 $contentSectionParts_proc[$k]=$this->fullParse($v);
00456                                         }
00457                                         $mailParts['CONTENT']=$contentSectionParts_proc;
00458                                 } else $mailParts['CONTENT'] = 'ERROR: No boundary found.';
00459                         break;
00460                         default:
00461                                 if (strtolower($mailParts['_CONTENT_TYPE_DAT']['charset'])=='utf-8')    {
00462                                         $mailParts['CONTENT']=utf8_decode($mailParts['CONTENT']);
00463                                 }
00464                         break;
00465                 }
00466                 return $mailParts;
00467         }
00468 }
00469 
00470 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_readmail.php'])  {
00471         include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_readmail.php']);
00472 }
00473 ?>