<?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();
*/
?>