读取分析邮件(eml)内容的类。可读头/内容/附件
<?php
require_once('mailread.inc.php');
$mr = new MailRead();
print_r($mr->readfromfile('test.eml', true, true));
?>
<?php
/*
// @author : lael
// blog : http://www.ydtuiguang.com/
// http://www.ydtuiguang.com
// all right reserved.
*/
class MailRead {
function MailRead(){
//
}
/// $readtext 是否读邮件内容 $attachments 是否读附件
function readfromfile($file, $readtext = true, $attachments = false){
$fp = @fopen($file, 'r');
if(!$fp)return false;
$tempresult = array();
$result = array();
$result['temp']['_headereof'] = false;
$result['temp']['_bodyheadereof'] = false;
$result['temp']['_bodybof'] = false;
$result['header'] = array();
$result['header']['boundary'] = array();
$result['body'] = array();
$lastkey = '';
$tempkey = '';
while(!feof($fp)){
$line = fgets($fp, 4096);
$linesi = strtolower($line);
$templinesi = trim($linesi);
if(feof($fp) && ($templinesi == '.' || empty($templinesi))){
$result['body'][$tempkey]['text'] = rtrim($result['body'][$tempkey]['text'], " .\r\n\t");
break;
}
//判断头结束
if(!$result['temp']['_headereof'] && (strpos($linesi, "\r") === 0 || strpos($linesi, "\n") === 0 || $linesi === '')){
foreach($result['header'] as $k => $v){
switch($k){
case 'From':
case 'To':
$result['header'][$k] = $this->getheaderfromto($v);
break;
case 'Date':
$result['header'][$k] = $this->getheaderdate($v);
break;
case 'Subject':
$result['header'][$k] = $this->getheadersubject($v);
break;
case 'boundary':
$result['header'][$k] = $this->getheaderboundary($v);
break;
case 'Message-ID':
$result['header'][$k] = md5($v);
break;
case 'Content-Type':
$result['header'][$k] = $this->getheadercontenttype($v);
break;
case 'Content-Transfer-Encoding':
$result['header'][$k] = $this->getheadercontenttransferencoding($v);
}
}
$result['temp']['_headereof'] = true;
continue;//下一行
}
if(!$result['temp']['_headereof']){
if(strpos($linesi, ' ') === 0 || strpos($linesi, "\t") === 0){//换行数据
if(isset($result['header'][$lastkey])){
if($lastkey == 'boundary'){
$result['header'][$lastkey][count($result['header'][$lastkey]) - 1] .= str_replace(array(' ', "\t", "\r", "\n"), '', $line);
}else{
$result['header'][$lastkey] .= str_replace(array(' ', "\t", "\r", "\n"), '', $line);
}
}
}else{
$lastkey = '';
}
if(strpos($linesi, 'from:') === 0 && !isset($result['header']['From'])){
$lastkey = 'From';
$result['header']['From'] = trim($line);
}
if(strpos($linesi, 'to:') === 0 && !isset($result['header']['To'])){
$lastkey = 'To';
$result['header']['To'] = trim($line);
}
if(strpos($linesi, 'date:') === 0 && !isset($result['header']['Date'])){
$lastkey = 'Date';
$result['header']['Date'] = trim($line);
}
if(strpos($linesi, 'message-id:') === 0 && !isset($result['header']['Message-ID'])){
$lastkey = 'Message-ID';
$result['header']['Message-ID'] = trim($line);
}
if(strpos($linesi, 'subject:') === 0 && !isset($result['header']['Subject'])){
$lastkey = 'Subject';
$result['header']['Subject'] = trim($line);
}
if(strpos($linesi, 'boundary=') !== false){
$lastkey = 'boundary';
array_push($result['header']['boundary'], trim($line));
}
if(strpos($linesi, 'content-transfer-encoding:') === 0){
$lastkey = 'Content-Transfer-Encoding';
$result['header']['Content-Transfer-Encoding'] = trim($line);
}
if(strpos($linesi, 'content-type:') === 0){
$lastkey = 'Content-Type';
$result['header']['Content-Type'] = trim($line);
}
}else{
if(!$readtext && !$attachments)break;
//
if(empty($result['header']['boundary'])){//没有分隔符,剩余数据全是邮件内容
$result['body']['text/html']['header'] = $result['header'];
$result['body']['text/html']['text'] .= $line;
}else{
$templinesi = trim($linesi);
if(!empty($templinesi) && strpos(strtolower('--'.implode('--', $result['header']['boundary']).'--'), $templinesi) !== false){
//内容为text/html表示已经得到邮件内容
if($result['temp']['_bodybof'] && $result['temp']['_bodyheadereof'])
if(isset($result['body']['text/html']))
if(!$attachments)break;
$lastkey = '';
$result['temp']['_bodyheadereof'] = false;
$result['temp']['_bodybof'] = true;//开始
continue;
}
if($result['temp']['_bodybof']){
//判断头结束
if(!$result['temp']['_bodyheadereof'] && (strpos($linesi, "\r") === 0 || strpos($linesi, "\n") === 0 || $linesi === '')){
//分析头信息
$result['header']['boundary'] = $this->getheaderboundary($result['header']['boundary']);
unset($tempresult['boundary']);
foreach($tempresult as $k => $v){
switch($k){
case 'Content-Type':
$tempresult[$k] = $this->getheadercontenttype($v);
break;
case 'Content-Transfer-Encoding':
$tempresult[$k] = $this->getheadercontenttransferencoding($v);
break;
case 'Content-Disposition':
$tempresult[$k] = $this->getheadercontentdisposition($v);
break;
case 'Content-ID':
$tempresult[$k] = $this->getheadercontentid($v);
break;
}
}
$result['temp']['_bodyheadereof'] = true;
continue;//下一行
}
//读取内容头信息
if(!$result['temp']['_bodyheadereof']){
if(strpos($linesi, ' ') === 0 || strpos($linesi, "\t") === 0){//换行数据
if(isset($tempresult[$lastkey])){
if($lastkey == 'boundary'){
$result['header'][$lastkey][count($result['header'][$lastkey]) - 1] .= str_replace(array(' ', "\t", "\r", "\n"), '', $line);
}else{
$tempresult[$lastkey] .= str_replace(array(' ', "\t", "\r", "\n"), '', $line);
}
}
}else{
$lastkey = '';
}
if(strpos($linesi, 'content-transfer-encoding:') === 0){
$lastkey = 'Content-Transfer-Encoding';
$tempresult['Content-Transfer-Encoding'] = trim($line);
}
if(strpos($linesi, 'content-type:') === 0){
$lastkey = 'Content-Type';
$tempresult['Content-Type'] = trim($line);
}
if(strpos($linesi, 'content-id:') === 0){
$lastkey = 'Content-ID';
$tempresult['Content-ID'] = trim($line);
}
if(strpos($linesi, 'content-disposition:') === 0){
$lastkey = 'Content-Disposition';
$tempresult['Content-Disposition'] = trim($line);
}
if(strpos($linesi, 'boundary=') !== false){
$lastkey = 'boundary';
$tempresult['boundary'] = '';
array_push($result['header']['boundary'], trim($line));
}
}else{
$tempkey = $tempresult['Content-Type']['name'];
if(empty($tempkey))$tempkey = $tempresult['Content-Disposition']['filename'];
if(empty($tempkey))$tempkey = $tempresult['Content-ID'];
if(empty($tempkey))$tempkey = $tempresult['Content-Type']['type'];
if(empty($tempkey))$tempkey = $tempresult['Content-Disposition']['type'];
if(!empty($tempkey)){
$result['body'][$tempkey]['header'] = $tempresult;
$result['body'][$tempkey]['text'] .= $line;
}
}
}
}
}
}
@fclose($fp);
if($readtext){
if(empty($result['body']['text/html']))$result['body']['text/html'] = $result['body']['text/plain'];
unset($result['body']['text/plain']);
switch($result['body']['text/html']['header']['Content-Transfer-Encoding']){
case 'base64':
$result['body']['text/html']['text'] = base64_decode($result['body']['text/html']['text']);
break;
case 'quoted-printable':
$result['body']['text/html']['text'] = quoted_printable_decode($result['body']['text/html']['text']);
break;
}
if(!empty($result['body']['text/html']['header']['Content-Type']['charset']))$result['body']['text/html']['text'] = $this->striconv($result['body']['text/html']['text'], $result['body']['text/html']['header']['Content-Type']['charset'], 'UTF-8');
//文本换行
if($result['body']['text/html']['header']['Content-Type']['type'] == 'text/plain')$result['body']['text/html']['text'] = nl2br($result['body']['text/html']['text']);
//处理图片
//<IMG src="cid:BA07BBCA@99F98623.1570004E.jpg">
//<img src="data:image/gif;base64,......=" />
}
return $result;
}
function getdecode($encode){
$result = $encode;
preg_match_all('/=\?(.*?)\?b\?(.*?)\?=/i', $result, $match);
if(isset($match[2][0])){
for($i = 0; $i < count($match[2]); $i ++)
$result = str_replace($match[0][$i], $this->striconv(base64_decode($match[2][$i]), $match[1][$i], 'UTF-8'), $result);
}
preg_match_all('/=\?(.*?)\?q\?(.*?)\?=/i', $result, $match);
if(isset($match[2][0])){
for($i = 0; $i < count($match[2]); $i ++)
$result = str_replace($match[0][$i], $this->striconv(quoted_printable_decode($match[2][$i]), $match[1][$i], 'UTF-8'), $result);
}
return $result;
}
function getheaderfromto($fromto){
return trim(preg_replace('/from:|to:|"|\'/i', '', $this->getdecode($fromto)));
}
function getheaderdate($date){
return strtotime(trim(preg_replace('/date:/i', '', $date)));
}
function getheadersubject($subject){
return trim(preg_replace('/subject:/i', '', $this->getdecode($subject)));
}
function getheaderboundary($boundary){
$result = array();
if(!is_array($boundary))return $result;
foreach($boundary as $k => $v){
$temp = $v;
if(strpos($v, 'boundary=') !== false)$temp = substr($v, strpos($v, 'boundary=') + strlen('boundary='));
if(strpos($temp, ';') !== false)$temp = substr($temp, 0, strpos($temp, ';'));
array_push($result, trim(preg_replace('/"|\'/i', '', $temp)));
}
return $result;
}
function getheadercontenttype($contenttype){
if(is_array($contenttype))return $contenttype;
$result = array();
$temp = preg_replace('/content-type:|\s|\r|\n|\t|"|\'/i', '', $contenttype);
$result['type'] = strtok($temp, ';');
while(true){
$tempnext = strtok(';');
if(!$tempnext)break;
if(strpos($tempnext, 'charset=') !== false){
$result['charset'] = preg_replace('/charset=/i', '', $tempnext);
}elseif(strpos($tempnext, 'boundary=') !== false){
$result['boundary'] = preg_replace('/boundary=/i', '', $tempnext);
}elseif(strpos($tempnext, 'name=') !== false){
$result['name'] = $this->getdecode(preg_replace('/name=/i', '', $tempnext));
}
}
return $result;
}
function getheadercontenttransferencoding($contenttransferencoding){
return strtolower(preg_replace('/content-transfer-encoding:|\s|\r|\n|\t|"|\'/i', '', $contenttransferencoding));
}
function getheadercontentdisposition($contentdisposition){
if(is_array($contentdisposition))return $contentdisposition;
$result = array();
$temp = preg_replace('/content-disposition:|\s|\r|\n|\t|"|\'/i', '', $contentdisposition);
$result['type'] = strtok($temp, ';');
while(true){
$tempnext = strtok(';');
if(!$tempnext)break;
if(strpos($tempnext, 'filename=') !== false){
$result['filename'] = $this->getdecode(preg_replace('/filename=/i', '', $tempnext));
}
}
return $result;
}
function getheadercontentid($contentid){
$result = '';
$temp = preg_replace('/content-id:|\s|\r|\n|\t|"|\'/i', '', $contentid);
preg_match_all('/<(.*?)>/i', $temp, $match);
$result = $temp;
if(isset($match[1][0]))$result = $match[1][0];
return $result;
}
function striconv($str, $form = "GBK", $to = "UTF-8"){
if(strtolower($form) == strtolower($to))return $str;
$result = $str;
if(function_exists("mb_convert_encoding")){
$result = @mb_convert_encoding($str, $to, $form);
}else{
if(function_exists("iconv")){
$result = @iconv($form, $to."//IGNORE", $str);
}
}
return $result;
}
}
?>