C_Imap 邮件的imap

<?php
class C_Imap{
	public $Fosck = null;
	public $Server = '';
	public $Port = 143;
	public $Errno = null;
	public $Erron = null;
	public $TimeOut = 30;
	public $NextNum = 1;			//执行编号
	public $NumAnex = null;			//执行编号前缀
	public $ThisNum = null;			//当前的编号
	public $IsDeBug = 2;			//debug等级
	public $ThisMailBox = null;		//当前MailBox
	public $ExecMessage = array('code' => null, 'message' => null);	//执行结果
	public $AttachBaseUrl = './';
	
	public function __construct(){
		//打开socket连接
		$this -> Fosck = fsockopen($this -> Server, $this -> Port , $this -> Errno, $this -> Erron, $this -> TimeOut);
		if($this -> Fosck){
			$TmpString = trim($this -> ReceivCmd());
			$this -> DeBugPrint($TmpString, 0);
		}else{
			$this -> DeBugPrint($this -> Errno.$this -> Erron, 0);
		}
		$this -> NumAnex = chr(rand(65,90));	//产生一个A-Z的字符
	}
	
	public function __destruct(){
		//关闭socket连接
		if($this -> Fosck){
			fclose($this -> Fosck);
		}
	}
	
	//调试输出
	public function DeBugPrint($String, $IsSend=1){
		switch(true){
			case ($IsSend==0 && $this -> IsDeBug >=0) : {	//接收
				echo trim($String)."\n";
				break;
			}
			case ($IsSend==1 && $this -> IsDeBug >=1) : {	//发送
				echo trim($String)."\n";
				break;
			}
			case ($IsSend==2 && $this -> IsDeBug >=2) : {	//接收解析结果
				foreach($String as $Key => $Val){
					echo $Key.' => '.$Val."\n";
				}
				break;
			}
		}
		return true;
	}
	
	//字符串转码
	public function ConvertString($InCharct, $OutCharct, $String){
		$OutCharct=='' && $OutCharct = 'UTF8';
		$InCharct = strtoupper($InCharct);
		switch($InCharct){
			case 'UTF-8' : {
				return $String;
				break;
			}
			case 'GBK' : {
				return mb_convert_encoding($String, $OutCharct, $InCharct);
				break;
			}
			case 'GB2312' : {
				return mb_convert_encoding($String, $OutCharct, $InCharct);
				break;
			}
			case 'ISO-8859-1' : {
				return $String;
				break;
			}
			default : {
				return $String;
			}
		}
	}
	
	//获取下次执行编号
	public function GetNextNum(){
		$this -> ThisNum = $this -> NumAnex.$this -> NextNum++;
		return $this -> ThisNum;
	}
	
	//获取命令行
	public function GetCmdZdy($Cmd){
		$Return = strtoupper(trim($Cmd));
		$Return = $this -> GetNextNum().' '.$Return."\r\n";
		return $Return;
	}
	
	//获取命令行
	public function GetCmd($Cmd, $Args=array()){
		$CmdList = array(
			'LOGIN' 	=> 'LOGIN {USER} {PASS}',
			'LOGOUT' 	=> 'LOGOUT',
			'LIST' 		=> 'LIST "{BASE}" "{FILETER}"',					//列表MailBox
			'CREATE' 	=> 'CREATE "{FOLDER}"',							//创建MailBox
			'DELETE' 	=> 'DELETE "{FOLDER}"',							//删除MailBox
			'SELECT' 	=> 'SELECT "{MAILBOX}"',						//选择MailBox
			'RENAME' 	=> 'RENAME "{OLDFOLDER}" "{NEWFOLDER}"',		//重命名MailBox
			'NOOP' 		=> 'NOOP',										//肯定答复
			'SEARCH' 	=> 'SEARCH {TYPE}',								//搜索MailBox
			'EXPUNGE' 	=> 'EXPUNGE',									//执行标志
			'CLOSE' 	=> 'CLOSE',										//关闭MailBox且执行标志
			'STORE' 	=> 'UID STORE {UID} {ISADD}FLAGS.SILENT ({FLAGS})',	//执行标志
			'COPY' 		=> 'UID COPY {UID} "{MAILBOX}"',					//移动邮件
			
		);
		$Return = $CmdList[strtoupper($Cmd)];
		$Search = $Places = array();
		if(is_array($Args) && count($Args) > 0){
			foreach($Args as $Key => $Val){
				$Search[] = "'{".strtoupper($Key)."}'";
				$Places[] = $Val;
			}
			$Return = preg_replace($Search, $Places, $Return);
		}
		$Return = trim(preg_replace("'{([A-Za-z0-9]+)}'", "", $Return));
		$Return = $this -> GetNextNum().' '.$Return."\r\n";
		return $Return;
	}
	
	//检测MailBox
	public function ToFolder($Folder){
		$TmpArray = explode('.', $Folder);
		$Result = array();
		foreach($TmpArray as $Key => $Val){
			$Val = $this -> ConvertString('UTF7-IMAP', 'UTF8', $Val);
			if(trim($Val) == '') return false;
			$Result[] = trim($Val);
		}
		if(count($Result) < 1) return false;
		return implode('.', $Result);
	}
	
	//写入Socket数据
	public function SendCmd($CmdString){
		return fwrite($this -> Fosck, $CmdString);
	}
	
	//读取Socket数据
	public function ReceivCmd($SizeOf=0){
		if($SizeOf > 0){
			return fgets($this -> Fosck, $SizeOf);
		}else{
			return fgets($this -> Fosck);
		}
	}
	
	//是否接收结尾
	public function IsTag($String, $Tag=''){
		if($Tag == '') $Tag = $this -> ThisNum;
		$Length = strlen($String);
		if($Length < 1) return false;
		if(preg_match('/^([a-z0-9*]+) (OK|NO|BAD|BYE) (\[.*\]){0,1}(.*)$/i', $String, $Match)){
			if($Match[1] == $Tag){
				$this -> ExecMessage = array('code' => $Match[3]!='' ? $Match[3] : $Match[2], 'message' => $this -> ConvertString('UTF-8', 'UTF7-IMAP', $Match[4]));
				return $Match;
			}
        }
		return false;
	}
	
	//检测是否执行成功
	public function IsOK($Match){
		if(is_array($Match) && count($Match) > 1){
			switch(strtoupper($Match[2])){
				case 'OK' : return true;
				case 'NO' : return false;
				case 'BAD' : return false;
				case 'BYE' : return true;
			}
		}elseif($Match === true){
			return true;
		}
		return false;
	}
    
	//执行命令
	public function ToExec($CmdString, $IsBack=1){
		if($CmdString == '') return false;
		$this -> ExecMessage = array('code' => null, 'message' => null);	//清空消息
		stream_set_timeout($this -> Fosck, 10);			//设置超时时间
		$SendCmdResult = $this -> SendCmd($CmdString);
		$this -> DeBugPrint($CmdString, 1);
		if(!$SendCmdResult) return false;
		$BackString = '';
		$Match = false;
		do{
			if($Match) break;
			$TmpString = $this -> ReceivCmd();
			$this -> DeBugPrint($TmpString, 0);
			$BackString .= $TmpString;
			$Match = $this -> IsTag(trim($TmpString));
		}while($IsBack);
		$this -> DeBugPrint($this -> ExecMessage, 2);
		return $IsBack ? array($Match, $BackString) : array(true, $BackString);
	}
	
	//登录
	public function Login($User, $Pass){
		$CmdString = $this -> GetCmd('LOGIN', array('USER' => $User, 'PASS' => $Pass));
		$BackArray = $this -> ToExec($CmdString, 1);
		return $this -> IsOK($BackArray[0]);
	}
	
	//登出
	public function Logout(){
		$CmdString = $this -> GetCmd('LOGOUT');
		$BackArray = $this -> ToExec($CmdString, 1);
		return $this -> IsOK($BackArray[0]);
	}
	
	//获取MailBox
	public function GetMailBox($Base="", $Fileter="*"){
		$CmdString = $this -> GetCmd('LIST', array('BASE' => $Base, 'FILETER' => $Fileter));
		$BackArray = $this -> ToExec($CmdString, 1);
		$IsOk = $this -> IsOK($BackArray[0]);
		if($IsOk){
			$Return = array();
			$ListMailBox = explode("\n", trim($BackArray[1]));
			foreach($ListMailBox as $Key => $Val){
				$Val = trim($Val);
				if($Val == '')continue;
				if(preg_match('/^\* LIST (.*) \"(.*)\" \"(.*)\"$/i', $Val, $Match)){
					$KeyTo = $Match[3];
					$TmpArray = explode('.', $KeyTo);
					$Return[$KeyTo] = $this -> ConvertString('UTF-8', 'UTF7-IMAP', array_pop($TmpArray));
				}
			}
			ksort($Return);
			return $Return;
		}else{
			return false;
		}
	}
	
	//创建MailBox
	public function CreateMailBox($Folder){
		if(!($Folder = $this -> ToFolder($Folder))) return false;
		$CmdString = $this -> GetCmd('CREATE', array('FOLDER' => $Folder));
		$BackArray = $this -> ToExec($CmdString, 1);
		return $this -> IsOK($BackArray[0]);
	}
	
	//删除MailBox
	public function DeleteMailBox($Folder){
		if(!($Folder = $this -> ToFolder($Folder))) return false;
		if(strtoupper($Folder) == 'INBOX') return false;			//默认收件箱不能删除
		$CmdString = $this -> GetCmd('DELETE', array('FOLDER' => $Folder));
		$BackArray = $this -> ToExec($CmdString, 1);
		return $this -> IsOK($BackArray[0]);
	}
	
	//删除MailBox
	public function RenameMailBox($OldFolder, $NewFolder){
		if(!($OldFolder = $this -> ToFolder($OldFolder))) return false;
		if(!($NewFolder = $this -> ToFolder($NewFolder))) return false;
		$CmdString = $this -> GetCmd('RENAME', array('OLDFOLDER' => $OldFolder, 'NEWFOLDER' => $NewFolder));
		$BackArray = $this -> ToExec($CmdString, 1);
		return $this -> IsOK($BackArray[0]);
	}
	
	//选择Mailbox
	public function SelectMailBox($MailBox){
		if(!($MailBox = $this -> ToFolder($MailBox))) return false;
		if($this -> ThisMailBox) $this -> Close();		//关闭当前正在操作的MailBox
		$CmdString = $this -> GetCmd('SELECT', array('MAILBOX' => $MailBox));
		$BackArray = $this -> ToExec($CmdString, 1);
		if($this -> IsOK($BackArray[0])){
			$this -> ThisMailBox = $MailBox;
			return true;
		}else{
			return false;
		}
	}
	
	//肯定的答复
	public function GetOK(){
		$CmdString = $this -> GetCmd('NOOP');
		$BackArray = $this -> ToExec($CmdString, 1);
		return $this -> IsOK($BackArray[0]);
	}
	
	//获取MailboxUid
	public function SearchMailBox($Type='NEW'){
		if(!$this -> ThisMailBox)return false;
		$CmdString = $this -> GetCmd('SEARCH', array('TYPE' => $Type));
		$BackArray = $this -> ToExec($CmdString, 1);
		$IsOk = $this -> IsOK($BackArray[0]);
		if($IsOk){
			$ListMailUid = explode("\n", trim($BackArray[1]));
			foreach($ListMailUid as $Key => $Val){
				$Val = trim($Val);
				if($Val == '')continue;
				if(preg_match('/^\* SEARCH(.*)$/i', $Val, $Match)){
					$UidList = explode(' ', trim($Match[1]));
					return $UidList;
				}
			}
			return array();
		}else{
			return false;
		}
	}
	
	//执行删除\deleted标志的信件
	public function Expunge(){
		if(!$this -> ThisMailBox)return false;
		$CmdString = $this -> GetCmd('EXPUNGE');
		$BackArray = $this -> ToExec($CmdString, 1);
		return $this -> IsOK($BackArray[0]);
	}
	
	//关闭文件夹
	public function Close(){
		$CmdString = $this -> GetCmd('CLOSE');
		$BackArray = $this -> ToExec($CmdString, 1);
		if($this -> IsOK($BackArray[0])){
			$this -> ThisMailBox = null;
			return true;
		}else{
			return false;
		}
	}
	
	//执行删除\deleted标志的信件
	public function Store($Uid, $IsAdd, $Flags){
		if(!$this -> ThisMailBox)return false;
		if(!($Flags = $this -> ToFlags($Flags))) return false;
		if(!($Uid = $this -> ToUid($Uid))) return false;
		$CmdString = $this -> GetCmd('STORE', array('UID' => $Uid, 'ISADD' => ($IsAdd ? '+' : '-'), 'FLAGS' => $Flags));
		$BackArray = $this -> ToExec($CmdString, 1);
		return $this -> IsOK($BackArray[0]);
	}
	
	//检查FLAGS格式
	public function ToFlags($Flags){
		$FlagsArray = explode(',', $Flags);
		if(count($FlagsArray) > 0){
			$Flags = '';
			foreach($FlagsArray as $Val){
				$Val = strtoupper(trim($Val));
				if(!in_array($Val, array('SEEN','ANSWERED','FLAGGED','DELETED','DRAFT','RECENT'))){
					return false;
				}else{
					$Flags .= ($Flags==''?'':' ')."\\".$Val;
				}
			}
		}else{
			return false;
		}
		return $Flags;
	}
	
	//检查UID格式
	public function ToUid($Uid){
		if(strpos($Uid, ':')){	//1:5 in(1,2,3,4,5)
			$TmpArray = explode(':', $Uid);
			if(count($TmpArray) != 2)return false;
			if($TmpArray[0] > $TmpArray[1])return false;
			$Uid = $TmpArray[0].':'.$TmpArray[1];
		}else if(strpos($Uid, ',')){	//1,2,5 in(1,2,5)
			$Uid = '';
			$TmpArray = explode(',', $Uid);
			if(count($TmpArray) < 2)return false;
			foreach($TmpArray as $Val){
				$Val = intval(trim($Val));
				if($Val < 1) return false;
				$Uid .= ($Uid == '' ? '':',').$Val;
			}
		}else{	//单个id
			if($Uid < 1)return false;
		}
		return $Uid;
	}
	
	//复制邮件
	public function CopyMail($Uid, $MailBox){
		if(!$this -> ThisMailBox)return false;
		if($Uid < 1)return false;
		if(!($MailBox = $this -> ToFolder($MailBox))) return false;
		$CmdString = $this -> GetCmd('COPY', array('UID' => $Uid, 'MAILBOX' => $MailBox));
		$BackArray = $this -> ToExec($CmdString, 1);
		return $this -> IsOK($BackArray[0]);
	}
	
	//移动邮件
	public function MoveMail($Uid, $MailBox){
		if(!$this -> ThisMailBox)return false;
		if($this -> CopyMail($Uid, $MailBox)){
			if($this -> Store($Uid, 1, 'DELETED')){
				return $this -> Expunge();
			}
		}
		return false;
	}
	
	//格式化数据
	public function GetFormart($Type, $String){
		switch($Type){
			case 'DATE' : {			//时间
				$Date = date("Y-m-d H:i:s", strtotime($String));
				return $Date;
				break;
			}
			case 'MESSAGE-ID' : {	//消息Id
				return preg_replace(array("'<'", "'>'"), array('', ''), $String);
				break;
			}
			case 'SUBJECT' : {		//主体
				$StringArray = explode('?==?', trim($String));
				$Length = count($StringArray)-1;
				if($Length == 0) return $this -> GetString($String, 'UTF-8');
				$Return = '';
				foreach($StringArray as $Key => $Val){
					if($Key == 0){
						$Return .= $this -> GetString($Val.'?=', 'UTF-8');
					}elseif($Length == $Key){
						$Return .= $this -> GetString('=?'.$Val, 'UTF-8');
					}else{
						$Return .= $this -> GetString('=?'.$Val.'?=', 'UTF-8');
					}
				}
				return $Return;
				break;
			}
			case 'TO': {			//接受者
				if(preg_match("/(.*)(\<.*\>)(.*)/i", $String, $Match)){
					$ToNickName = $this -> GetString(trim(preg_replace(array("'<'", "'>'", "'\"'", "'\('", "'\)'"), array('', '', '', '', ''), $Match[1])), 'UTF-8');
					$To = trim(preg_replace(array("'<'", "'>'", "'\"'", "'\('", "'\)'"), array('', '', '', '', ''), $Match[2]));
				}elseif(preg_match("/([\S]* )([\S\s]*)/i", $String, $Match)){
					$ToNickName = $this -> GetString(trim(preg_replace(array("'<'", "'>'", "'\"'", "'\('", "'\)'"), array('', '', '', '', ''), $Match[2])), 'UTF-8');
					$To = trim(preg_replace(array("'<'", "'>'", "'\"'", "'\('", "'\)'"), array('', '', '', '', ''), $Match[1]));
				}else{
					$To = $String;
					$ToNickName = substr($String, 0, strpos($String, '@'));
				}
				return array(
						'TONICKNAME' => $ToNickName, 
						'TO' => $To
						);
				break;
			}
			case 'FROM' : {			//发信人
				if(preg_match("/(.*)(\<.*\>)(.*)/i", $String, $Match)){
					$FromNickName = $this -> GetString(trim(preg_replace(array("'<'", "'>'", "'\"'", "'\('", "'\)'"), array('', '', '', '', ''), $Match[1])), 'UTF-8');
					$From = trim(preg_replace(array("'<'", "'>'", "'\"'", "'\('", "'\)'"), array('', '', '', '', ''), $Match[2]));
				}elseif(preg_match("/([\S]* )([\S\s]*)/i", $String, $Match)){
					$FromNickName = $this -> GetString(trim(preg_replace(array("'<'", "'>'", "'\"'", "'\('", "'\)'"), array('', '', '', '', ''), $Match[2])), 'UTF-8');
					$From = trim(preg_replace(array("'<'", "'>'", "'\"'", "'\('", "'\)'"), array('', '', '', '', ''), $Match[1]));
				}else{
					$From = $String;
					$FromNickName = substr($String, 0, strpos($String, '@'));
				}
				return array(
						'FROMNICKNAME' => $FromNickName, 
						'FROM' => $From
						);
				break;
			}
			case 'RETURN-PATH' : {	//发信人地址
				return preg_replace(array("'<'", "'>'"), array('', ''), $String);
				break;
			}
			case 'CC': {			//抄送
				$CcList = array();
				$TmpArray = explode(',', $String);
				foreach($TmpArray as $Key => $Val){
					$Val = trim($Val);
					if($Val == '')continue;
					$Pos = strpos($Val, ' ');
					if($Pos){
						$CcNickName = $this -> GetString(trim(substr($Val, 0, $Pos)), 'UTF-8');
						$Cc = trim(substr($Val, $Pos+1));
					}else{
						$Cc = $String;
						$CcNickName = substr($Val, 0, strpos($String, '@'));
					}
					$CcList[] = array(
							'CCNICKNAME' => preg_replace(array("'<'", "'>'", "'\"'"), array('', '', ''), $CcNickName), 
							'CC' => preg_replace(array("'<'", "'>'", "'\"'"), array('', '', ''), $Cc)
							);
				}
				return $CcList;
				break;
			}
			case 'CONTENT-TRANSFER-ENCODING' : {	//内容编码
				return strtoupper(trim($String));
				break;
			}
			case 'MIME-VERSION' : {			//MIME版本
				return trim($String);
				break;
			}
			case 'CONTENT-TYPE' : {			//文档类型
				return trim($String);
				break;
			}
			case 'X-PRIORITY' : {			//文档类型
				return trim($String);
				break;
			}
		}
	}
	
	//转码内容
	public function GetString($String, $Charset="UTF-8", $Num=3){
		if(preg_match("/(=\?(.*?)\?B\?(.*?)\?=)/i", $String, $Match)){
			$StringToo = base64_decode($Match[3]);
			$String = $this -> ConvertString($Match[2], $Charset, $StringToo);
		}elseif(preg_match("/(=\?(.*?)\?Q\?(.*?)\?=)/i", $String, $Match)){
			$StringToo = quoted_printable_decode($Match[3]);
			$String = $this -> ConvertString($Match[2], $Charset, $StringToo);
		}else{
			return $String;
		}
		if(--$Num > 0){
			return $this -> GetString($String, $Charset, $Num);
		}else{
			return $String;
		}
	}
	
	//获取邮件列表
	public function GetUidHead($Uid){
		if(!$this -> ThisMailBox)return false;
		if($Uid < 1)return false;
		$CmdString = 'UID FETCH '.$Uid.' (UID, FLAGS, BODY.PEEK[HEADER.FIELDS (TO From Subject Message-Id Date Return-Path Cc Content-Transfer-Encoding Content-Type Mime-Version X-Priority)])';
		$CmdString = $this -> GetCmdZdy($CmdString);
		$BackArray = $this -> ToExec($CmdString, 1);
		$IsOk = $this -> IsOK($BackArray[0]);
		if($IsOk){
			$ListFlags = $ListUIds = $ListContent = array();
			$IsStart = false;
			$TmpString = '';
			foreach(explode("\n", $BackArray[1]) as $Val){
				$Val = trim($Val);
				if(isset($Val{0}) && $Val{0} == '*') $IsStart = true;
				if($IsStart){
					$TmpString .= ($TmpString!='' ? "\n" : '').$Val;
				}
				if(isset($Val{0}) && $Val{0} == ')'){
					$IsStart = false;
					if(preg_match("/\* (\d+) FETCH \(UID (\d+) FLAGS \(([\S\s]*)\) [\S\s]*}/U", $TmpString, $Match)){
						$ListUIds[] = $Match[2];
						$ListFlags[] = implode(',', explode(' ', preg_replace("'\\\\'", '', $Match[3])));
						$ListContent[] = $TmpString;
						$TmpString = '';
					}
				}
			}
			$ListHead = array();
			if(count($ListContent) > 0){
				foreach($ListContent as $Key => $Val){
					$TmpListArray = explode("\n", trim($Val));
					$TmpString = '';
					foreach($TmpListArray as $Vals){
						if(trim($Vals) == ')')continue;
						if($TmpString!='' && strpos($Vals, ':')){		//需要处理前一批数据
							$Pos = strpos($TmpString, ':');
							$Type = strtoupper(trim(substr($TmpString, 0, $Pos)));
							if($Type != ''){
								$ListHead[$ListUIds[$Key]][$Type] = $this -> GetFormart($Type, trim(substr($TmpString, $Pos+1)));
							}
							$TmpString = '';
						}
						$TmpString .= trim($Vals);
					}
					if($TmpString != ''){
						$Pos = strpos($TmpString, ':');
						$Type = strtoupper(trim(substr($TmpString, 0, $Pos)));
						if($Type != ''){
							$ListHead[$ListUIds[$Key]][$Type] = $this -> GetFormart($Type, trim(substr($TmpString, $Pos+1)));
						}
						$TmpString = '';
					}
					$ListHead[$ListUIds[$Key]]['FLAGS'] = $ListFlags[$Key];
					ksort($ListHead[$ListUIds[$Key]]);
				}
			}
			return $ListHead;
		}else{
			return false;
		}
	}
	
	//获取邮件列表
	public function GetMailBoxList($Ids='1:*'){
		if(!$this -> ThisMailBox)return false;
		$CmdString = 'FETCH '.$Ids.' (UID, FLAGS, BODY.PEEK[HEADER.FIELDS (TO From Subject Message-Id Date Return-Path Cc Content-Transfer-Encoding Content-Type Mime-Version X-Priority)])';
		$CmdString = $this -> GetCmdZdy($CmdString);
		$BackArray = $this -> ToExec($CmdString, 1);
		$IsOk = $this -> IsOK($BackArray[0]);
		if($IsOk){
			$ListFlags = $ListUIds = $ListContent = array();
			$IsStart = false;
			$TmpString = '';
			foreach(explode("\n", $BackArray[1]) as $Val){
				$Val = trim($Val);
				if(isset($Val{0}) && $Val{0} == '*') $IsStart = true;
				if($IsStart){
					$TmpString .= ($TmpString!='' ? "\n" : '').$Val;
				}
				if(isset($Val{0}) && $Val{0} == ')'){
					$IsStart = false;
					if(preg_match("/\* (\d+) FETCH \(UID (\d+) FLAGS \(([\S\s]*)\) [\S\s]*}/U", $TmpString, $Match)){
						$ListUIds[] = $Match[2];
						$ListFlags[] = implode(',', explode(' ', preg_replace("'\\\\'", '', $Match[3])));
						$ListContent[] = $TmpString;
						$TmpString = '';
					}
				}
			}
			$ListHead = array();
			if(count($ListContent) > 0){
				foreach($ListContent as $Key => $Val){
					$TmpListArray = explode("\n", trim($Val));
					$TmpString = '';
					foreach($TmpListArray as $Vals){
						if(trim($Vals) == ')')continue;
						if($TmpString!='' && strpos($Vals, ':')){		//需要处理前一批数据
							$Pos = strpos($TmpString, ':');
							$Type = strtoupper(trim(substr($TmpString, 0, $Pos)));
							if($Type != ''){
								$ListHead[$ListUIds[$Key]][$Type] = $this -> GetFormart($Type, trim(substr($TmpString, $Pos+1)));
							}
							$TmpString = '';
						}
						$TmpString .= trim($Vals);
					}
					if($TmpString != ''){
						$Pos = strpos($TmpString, ':');
						$Type = strtoupper(trim(substr($TmpString, 0, $Pos)));
						if($Type != ''){
							$ListHead[$ListUIds[$Key]][$Type] = $this -> GetFormart($Type, trim(substr($TmpString, $Pos+1)));
						}
						$TmpString = '';
					}
					$ListHead[$ListUIds[$Key]]['FLAGS'] = $ListFlags[$Key];
					ksort($ListHead[$ListUIds[$Key]]);
				}
			}
			return $ListHead;
		}else{
			return false;
		}
	}
	
	//解码字符串
	public function GetEnString($String, $Charset=''){
		if(!is_array($String))return false;
		switch(strtoupper($Charset)){
			case 'BASE64' : {
				$StringToo = '';
				foreach($String as $Val) $StringToo .= trim($Val);
				return base64_decode($StringToo);
				break;
			}
			case '7BIT' : {
				$StringToo = '';
				foreach($String as $Val) $StringToo .= trim($Val);
				return $StringToo;
				break;
			}
			case '8BIT' : {
				$StringToo = '';
				foreach($String as $Val) $StringToo .= trim($Val);
				return $StringToo;
				break;
			}
			case 'BINARY' : {
				$StringToo = '';
				foreach($String as $Val) $StringToo .= trim($Val);
				return $StringToo;
				break;
			}
			case 'QUOTED-PRINTABLE' : {
				$StringToo = '';
				foreach($String as $Val){
					$StringToo .= trim($Val)."\r\n";
				}
				return quoted_printable_decode($StringToo);
				break;
			}
			default : {
				$StringToo = '';
				foreach($String as $Val) $StringToo .= trim($Val);
				return $StringToo;
			}
		}
	}
	
	//格式化内容
	public function ParseMail($Content, $Charset=''){
		if($Content == '')return '';
		$Return = array();
		$Line = explode("\n", trim($Content));
		$LineLength = count($Line);
		$Is_Mail = preg_match("/^--[A-Za-z0-9_\-\=\.\@]+$/imU", $Line[0]);
		if(preg_match("/^This is a ([a-z0-9A-Z_-]*) message in MIME format[\S\s]*/imU", $Line[0], $Match) || $Is_Mail){
			$HeadString = '';
			$BodyString = null;
			$IsMark = false;
			$IsA = true;
			$IsDiff = true;
			$TmpData = $TmpSet = null;
			$TmpKey = $TmpKeyToo = '';
			$IsB = $Is_Mail ? false : true;
			foreach($Line as $Key => $Val){
				if($IsB && trim($Val) == ''){
					$IsB = false;
					continue;
				}
				if($IsB) continue;
				if(trim($Val) == ')' && $LineLength-1 == $Key)continue;
				if(preg_match("/^--[A-Za-z0-9_\-\=\.\@]+--$/imU", trim($Val), $Matchs)){	//结束
					$IsMark = true;
					$TmpKeyToo = '';
				}elseif(preg_match("/^--[A-Za-z0-9_\-\=\.\@]+$/imU", trim($Val), $Matchs)){	//开始
					$IsMark = true;
					$TmpKeyToo = substr(trim($Val), 2);
					if($TmpKey == '') $TmpKey = $TmpKeyToo;
					$IsA = true;
				}else{
					if($IsA && trim($Val) == ''){	//Head Body 切换
						$IsA = !$IsA;
					}
					if($IsA){
						$Pos = strpos(trim($Val), ':');
						if(!$Pos){
							$HeadString .= ($IsDiff ? '':';').$Val;
						}else{
							$HeadString .= ($HeadString!=''?"\n":"").$Val;
						}
						$IsDiff = substr(trim($Val), -1) == ';' ? true : false;
					}else{
						$BodyString[] = $Val;
					}
				}
				if($IsMark){
					$IsMark = false;
					if(trim($HeadString) != '' || (count($BodyString) > 0 && trim($BodyString[0]) != '')){
						if(is_null($TmpSet) && count($BodyString) == 1 && trim($BodyString[0]) == ''){
							if($HeadString == ''){
								$TmpSet = array();
							}else{
								$TmpSet = array('HEAD' => $HeadString, 'BODY' => $BodyString);
							}
						}else{
							$TmpData[$TmpKey][] = array('HEAD' => $HeadString, 'BODY' => $BodyString);
						}
						$BodyString = null;
						$HeadString = '';
						$TmpKey = $TmpKeyToo;
					}
					$IsA = true;
				}
			}
			//解析邮件正文
			$SetHead = $this -> GetToHead($TmpSet['HEAD']);
			if(isset($SetHead['CONTENT-TYPE']['BOUNDARY']) && isset($TmpData[$SetHead['CONTENT-TYPE']['BOUNDARY']])){
				foreach($TmpData[$SetHead['CONTENT-TYPE']['BOUNDARY']] as $Key => $Val){
					$TooHead = $this -> GetToHead($Val['HEAD']);
					isset($TooHead['CONTENT-TRANSFER-ENCODING']) && $TooHead['CONTENT-TRANSFER-ENCODING'][0] != '' && $Charset = $TooHead['CONTENT-TRANSFER-ENCODING'][0];
					$Encoding = strtoupper($TooHead['CONTENT-TYPE']['CHARSET']);
					if(strtoupper($TooHead['CONTENT-TYPE'][0]) == 'TEXT/PLAIN'){
						if($Encoding != ''){
							$Return['TEXT'] = array('BODY' => $this -> ConvertString($Encoding, '', $this -> GetEnString($Val['BODY'], $Charset)), 'CHARSET' => $Encoding);
						}else{
							$Return['TEXT'] = array('BODY' => $this -> GetEnString($Val['BODY'], $Charset), 'CHARSET' => $Encoding);
						}
					}else{
						if($Encoding != ''){
							$Return['HTML'] = array('BODY' => $this -> ConvertString($Encoding, '', $this -> GetEnString($Val['BODY'], $Charset)), 'CHARSET' => $Encoding);
						}else{
							$Return['HTML'] = array('BODY' => $this -> GetEnString($Val['BODY'], $Charset), 'CHARSET' => $Encoding);
						}
					}
				}
				unset($TmpData[$SetHead['CONTENT-TYPE']['BOUNDARY']]);
			}else{
				foreach(array_shift($TmpData) as $Key => $Val){
					$TooHead = $this -> GetToHead($Val['HEAD']);
					isset($TooHead['CONTENT-TRANSFER-ENCODING']) && $TooHead['CONTENT-TRANSFER-ENCODING'][0] != '' && $Charset = $TooHead['CONTENT-TRANSFER-ENCODING'][0];
					!isset($TooHead['CONTENT-TYPE']) && $TooHead['CONTENT-TYPE'] = array(0 => '', 'CHARSET' => '');
					isset($TooHead['CONTENT-TYPE']['CHARSET']) && $Encoding = strtoupper($TooHead['CONTENT-TYPE']['CHARSET']);
					if(strtoupper($TooHead['CONTENT-TYPE'][0]) == 'TEXT/PLAIN'){
						if($Encoding != ''){
							$Return['TEXT'] = array('BODY' => $this -> ConvertString($Encoding, '', $this -> GetEnString($Val['BODY'], $Charset)), 'CHARSET' => $Encoding);
						}else{
							$Return['TEXT'] = array('BODY' => $this -> GetEnString($Val['BODY'], $Charset), 'CHARSET' => $Encoding);
						}
					}else{
						if($Encoding != ''){
							$Return['HTML'] = array('BODY' => $this -> ConvertString($Encoding, '', $this -> GetEnString($Val['BODY'], $Charset)), 'CHARSET' => $Encoding);
						}else{
							$Return['HTML'] = array('BODY' => $this -> GetEnString($Val['BODY'], $Charset), 'CHARSET' => $Encoding);
						}
					}
				}
			}
			//解析邮件正文结束
			if(count($TmpData) > 0){	//含有附件
				foreach(array_shift($TmpData) as $Key => $Val){
					$TooHead = $this -> GetToHead($Val['HEAD']);
					isset($TooHead['CONTENT-TRANSFER-ENCODING']) && $TooHead['CONTENT-TRANSFER-ENCODING'][0] != '' && $Charset = $TooHead['CONTENT-TRANSFER-ENCODING'][0];
					$Encoding = '';
					isset($TooHead['CONTENT-TYPE']['CHARSET']) && $Encoding = strtoupper($TooHead['CONTENT-TYPE']['CHARSET']);
					$TmpBody = $this -> GetEnString($Val['BODY'], $Charset);
					$UrlExtension = $this -> SaveAttachment(array('BODY' => $TmpBody, 'BODYSIZE' => strlen($TmpBody), 'FILENAME' => $this -> GetString(($TooHead['CONTENT-DISPOSITION']['FILENAME']!='' ? $TooHead['CONTENT-DISPOSITION']['FILENAME'] : $TooHead['CONTENT-TYPE']['NAME']), $Encoding), 'TYPE' => $TooHead['CONTENT-TYPE'][0], 'CHARSET' => isset($TooHead['CONTENT-TYPE']['CHARSET']) ? $TooHead['CONTENT-TYPE']['CHARSET'] : ''));
					if($UrlExtension){
						if($Encoding != ''){
							$Return['ATTACHMENT'][] = array('URL' => $UrlExtension['URL'], 'EXTENSION' => $UrlExtension['EXTENSION'], 'BODYSIZE' => strlen($TmpBody), 'FILENAME' => $this -> ConvertString($Encoding, '', $this -> GetString(($TooHead['CONTENT-DISPOSITION']['FILENAME']!='' ? $TooHead['CONTENT-DISPOSITION']['FILENAME'] : $TooHead['CONTENT-TYPE']['NAME']), $Encoding)), 'TYPE' => $TooHead['CONTENT-TYPE'][0], 'CHARSET' => $TooHead['CONTENT-TYPE']['CHARSET']);
						}else{
							$Return['ATTACHMENT'][] = array('URL' => $UrlExtension['URL'], 'EXTENSION' => $UrlExtension['EXTENSION'], 'BODYSIZE' => strlen($TmpBody), 'FILENAME' => $this -> GetString(($TooHead['CONTENT-DISPOSITION']['FILENAME']!='' ? $TooHead['CONTENT-DISPOSITION']['FILENAME'] : $TooHead['CONTENT-TYPE']['NAME']), $Encoding), 'TYPE' => $TooHead['CONTENT-TYPE'][0], 'CHARSET' => isset($TooHead['CONTENT-TYPE']['CHARSET']) ? $TooHead['CONTENT-TYPE']['CHARSET'] :'');
						}
					}
				}
			}
		}else{	//简单邮件
			if(trim($Line[$LineLength-1]) == ')') unset($Line[$LineLength-1]);
			$Return['TEXT'] = array('BODY' => $this -> ConvertString('', '', $this -> GetEnString(array(implode("\n", $Line)), $Charset)), 'CHARSET' => '');
		}
		return $Return;
	}
	
	//处理头信息
	public function GetToHead($HeadString){
		$SetArray = array();
		$TmpSetArray = explode("\n", trim($HeadString));
		foreach($TmpSetArray as $Key => $Val){
			if(trim($Val) == '')continue;
			$Pos = strpos($Val, ':');
			if($Pos){
				$Keys = strtoupper(trim(substr($Val, 0, $Pos)));
				$Vals = trim(substr($Val, $Pos+1));
				if($Keys != ''){
					$TmpArray = explode(';', $Vals);
					$TmpDataArray = array();
					foreach($TmpArray as $Keyss => $Valss){
						$Valss = preg_replace(array("'<'", "'>'", "'\"'"), array('', '', ''), trim($Valss));
						if($Valss == '')continue;
						$Poss = strpos($Valss, '=');
						if($Poss){
							$KeysToo = strtoupper(trim(substr($Valss, 0, $Poss)));
							if($KeysToo == '')continue;
							$TmpDataArray[$KeysToo] = trim(substr($Valss, $Poss+1));
						}else{
							$TmpDataArray[] = trim($Valss);
						}
					}
					$SetArray[$Keys] = $TmpDataArray;
				}
			}
		}
		return $SetArray;
	}
	
	//获取邮件内容
	public function GetUidContent($Uid, $Charset=''){
		if(!$this -> ThisMailBox)return false;
		if($Uid < 1)return false;
		$CmdString = 'UID FETCH '.$Uid.' BODY.PEEK[TEXT]';
		$CmdString = $this -> GetCmdZdy($CmdString);
		$BackArray = $this -> ToExec($CmdString, 1);
		$IsOk = $this -> IsOK($BackArray[0]);
		if($IsOk){
			$Return = array();
			$IsStart = false;
			$TmpString = '';
			foreach(explode("\n", $BackArray[1]) as $Key => $Val){
				$Val = trim($Val);
				if(isset($Val{0}) && $Val{0} == '*') $IsStart = true;
				if($IsStart && $Key > 0){
					$TmpString .= ($TmpString!='' ? "\n" : '').$Val;
				}
				if(isset($Val{0}) && $Val{0} == ')'){
					$IsStart = false;
					$Return[$Uid] = $this -> ParseMail(trim($TmpString), $Charset);
					$TmpString = '';
					return $Return;
				}
			}
			return true;
		}else{
			return false;
		}
	}
	
	//保存附件
	public function SaveAttachment($Attachment){
		$Url = $this -> AttachBaseUrl;
		$Url .= date("Y_m").'/';
		if(!is_dir($Url)){
			if(!mkdir($Url, 0700)) return false;
		}
		$Url .= date("d").'/';
		if(!is_dir($Url)){
			if(!mkdir($Url, 0700)) return false;
		}
		$RPos = strrpos($Attachment['FILENAME'], '.');
		$Annx = strtolower(substr($Attachment['FILENAME'], $RPos+1));
		$Url .= md5(substr($Attachment['FILENAME'], 0, $RPos)).'.'.$Annx.'_attr';
		if(!$Fopen = fopen($Url, 'w')) return false;
		if(!fwrite($Fopen, $Attachment['BODY']));
		if($Fopen)fclose($Fopen);
		return array('URL' => $Url, 'EXTENSION' => $Annx);
	}	
}
/*
error_reporting(E_ALL);
$C_Imap = new C_Imap();
$C_Imap -> Login('xxx@xxx.cn', 'xxxxxxxx');
//print_r($C_Imap -> GetMailBox());
//var_dump($C_Imap -> DeleteMailBox('黄.a.Test'));
//var_dump($C_Imap -> RenameMailBox('黄.a.Test1', 'KKK-黄祥.向你'));
//var_dump($C_Imap -> CreateMailBox('黄.a.Test'));
//var_dump($C_Imap -> GetMailBox());
//var_dump($C_Imap -> GetOK());
$C_Imap -> SelectMailBox("INBOX");
//$C_Imap -> MoveMail(4, "KKK");

var_dump($C_Imap -> SearchMailBox('new'));
//var_dump($C_Imap -> SearchMailBox('ALL'));

//var_dump($C_Imap -> Store('2', 1, 'ANSWERED,SEEN,FLAGGED,DELETED,DRAFT,RECENT'));
echo '<pre>';
print_r($C_Imap -> GetMailBoxList());
echo '</pre>';
//var_dump($C_Imap -> Store('2', 0, 'SEEN,ANSWERED,FLAGGED,DELETED,DRAFT,RECENT'));

$Uid = isset($_GET['uid']) ? $_GET['uid'] : 0;
if($Uid < 1) $Uid = 19;
$Head = $C_Imap -> GetUidHead($Uid);
print_r($Head);
$Charset = '';
isset($Head[$Uid]['CONTENT-TRANSFER-ENCODING']) && $Charset = $Head[$Uid]['CONTENT-TRANSFER-ENCODING'];
$Body = $C_Imap -> GetUidContent($Uid, $Charset);
print_r($Body);
//($C_Imap -> GetUidContent(2));
//($C_Imap -> GetUidContent(17, 'base64'));
//($C_Imap -> GetUidContent(3));
//($C_Imap -> GetUidContent(15, '8Bit'));
$C_Imap -> Logout();
*/
?>

 

posted @ 2012-01-17 15:58  祥辉  阅读(294)  评论(0编辑  收藏  举报