Documentation TYPO3 par Ameos |
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 ?>