00001 <?php
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
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;
00099
00100
00101
00102
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
00141
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.')) {
00199 list($c)=explode('--- Below this line is a copy of the message.',$c);
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;
00206 } elseif (stristr($cp['reason_text'],'couldn\'t find any host named')) {
00207 $cp['reason']=2;
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')) {
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;
00220 } elseif (stristr($cp['reason_text'],'553')) {
00221 $cp['reason']=553;
00222 } elseif (stristr($cp['reason_text'],'551')) {
00223 $cp['reason']=551;
00224 } else {
00225 $cp['reason']=-1;
00226 }
00227 } else {
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;
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]);
00269 }
00270 return implode('',$parts);
00271 }
00272
00279 function extractNameEmail($str) {
00280 $outArr=array();
00281
00282
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
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 ?>