读取分析邮件(eml)内容的类。可读头/内容/附件

读取分析邮件(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;
	}
	
}
?>


 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值