查看 POP3/SMTP 協議的時候想嘗試一下自己寫一個操作類,核心沒啥,就是使用 fsockopen ,然後寫入/接收數據,只實現了最核心的部分功能,當作是學習 Socket 操作的練手。其中參考了 RFC 2449和一個國外的簡單Web郵件系統 Uebimiau 的部分代碼,不過絕對沒有抄他滴,HOHO,絕對原創。復制代碼 代碼如下:
<?php
class SocketPOPClient
{
var $strMessage = '';
var $intErrorNum = 0;
var $bolDebug = false;
var $strEmail = '';
var $strPasswd = '';
var $strHost = '';
var $intPort = 110;
var $intConnSecond = 30;
var $intBuffSize = 8192;
var $resHandler = NULL;
var $bolIsLogin = false;
var $strRequest = '';
var $strResponse = '';
var $arrRequest = array();
var $arrResponse = array();
//---------------
// 基礎操作
//---------------
//構造函數
function SocketPOP3Client($strLoginEmail, $strLoginPasswd, $strPopHost='', $intPort='')
{
$this->strEmail = trim(strtolower($strLoginEmail));
$this->strPasswd = trim($strLoginPasswd);
$this->strHost = trim(strtolower($strPopHost));
if ($this->strEmail=='' || $this->strPasswd=='')
{
$this->setMessage('Email address or Passwd is empty', 1001);
return false;
}
if (!PReg_match("/^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$/i", $this->strEmail))
{
$this->setMessage('Email address invalid', 1002);
return false;
}
if ($this->strHost=='')
{
$this->strHost = substr(strrchr($this->strEmail, "@"), 1);
}
if ($intPort!='')
{
$this->intPort = $intPort;
}
$this->connectHost();
}
//連接服務器
function connectHost()
{
if ($this->bolDebug)
{
echo "Connection ".$this->strHost." ...\r\n";
}
if (!$this->getIsConnect())
{
if ($this->strHost=='' || $this->intPort=='')
{
$this->setMessage('POP3 host or Port is empty', 1003);
return false;
}
$this->resHandler = @fsockopen($this->strHost, $this->intPort, &$this->intErrorNum, &$this->strMessage, $this->intConnSecond);
if (!$this->resHandler)
{
$strErrMsg = 'Connection POP3 host: '.$this->strHost.' failed';
$intErrNum = 2001;
$this->setMessage($strErrMsg, $intErrNum);
return false;
}
$this->getLineResponse();
if (!$this->getRestIsSucceed())
{
return false;
}
}
return true;
}
//關閉連接
function closeHost()
{
if ($this->resHandler)
{
fclose($this->resHandler);
}
return true;
}
//發送指令
function sendCommand($strCommand)
{
if ($this->bolDebug)
{
if (!preg_match("/PASS/", $strCommand))
{
echo "Send Command: ".$strCommand."\r\n";
}
else
{
echo "Send Command: PASS ******\r\n";
}
}
if (!$this->getIsConnect())
{
return false;
}
if (trim($strCommand)=='')
{
$this->setMessage('Request command is empty', 1004);
return false;
}
$this->strRequest = $strCommand."\r\n";
$this->arrRequest[] = $strCommand;
fputs($this->resHandler, $this->strRequest);
return true;
}
//提取響應信息第一行
function getLineResponse()
{
if (!$this->getIsConnect())
{
return false;
}
$this->strResponse = fgets($this->resHandler, $this->intBuffSize);
$this->arrResponse[] = $this->strResponse;
return $this->strResponse;
}
//提取若干響應信息,$intReturnType是返回值類型, 1為字符串, 2為數組
function getRespMessage($intReturnType)
{
if (!$this->getIsConnect())
{
return false;
}
if ($intReturnType == 1)
{
$strAllResponse = '';
while(!feof($this->resHandler))
{
$strLineResponse = $this->getLineResponse();
if (preg_match("/^\+OK/", $strLineResponse))
{
continue;
}
if (trim($strLineResponse)=='.')
{
break;
}
$strAllResponse .= $strLineResponse;
}
return $strAllResponse;
}
else
{
$arrAllResponse = array();
while(!feof($this->resHandler))
{
$strLineResponse = $this->getLineResponse();
if (preg_match("/^\+OK/", $strLineResponse))
{
continue;
}
if (trim($strLineResponse)=='.')
{
break;
}
$arrAllResponse[] = $strLineResponse;
}
return $arrAllResponse;
}
}
//提取請求是否成功
function getRestIsSucceed($strRespMessage='')
{
if (trim($responseMessage)=='')
{
if ($this->strResponse=='')
{
$this->getLineResponse();
}
$strRespMessage = $this->strResponse;
}
if (trim($strRespMessage)=='')
{
$this->setMessage('Response message is empty', 2003);
return false;
}
if (!preg_match("/^\+OK/", $strRespMessage))
{
$this->setMessage($strRespMessage, 2000);
return false;
}
return true;
}
//獲取是否已連接
function getIsConnect()
{
if (!$this->resHandler)
{
$this->setMessage("Nonexistent availability connection handler", 2002);
return false;
}
return true;
}
//設置消息
function setMessage($strMessage, $intErrorNum)
{
if (trim($strMessage)=='' || $intErrorNum=='')
{
return false;
}
$this->strMessage = $strMessage;
$this->intErrorNum = $intErrorNum;
return true;
}
//獲取消息
function getMessage()
{
return $this->strMessage;
}
//獲取錯誤號
function getErrorNum()
{
return $this->intErrorNum;
}
//獲取請求信息
function getRequest()
{
return $this->strRequest;
}
//獲取響應信息
function getResponse()
{
return $this->strResponse;
}
//---------------
// 郵件原子操作
//---------------
//登錄郵箱
function popLogin()
{
if (!$this->getIsConnect())
{
return false;
}
$this->sendCommand("USER ".$this->strEmail);
$this->getLineResponse();
$bolUserRight = $this->getRestIsSucceed();
$this->sendCommand("PASS ".$this->strPasswd);
$this->getLineResponse();
$bolPassRight = $this->getRestIsSucceed();
if (!$bolUserRight || !$bolPassRight)
{
$this->setMessage($this->strResponse, 2004);
return false;
}
$this->bolIsLogin = true;
return true;
}
//退出登錄
function popLogout()
{
if (!$this->getIsConnect() && $this->bolIsLogin)
{
return false;
}
$this->sendCommand("QUIT");
$this->getLineResponse();
if (!$this->getRestIsSucceed())
{
return false;
}
return true;
}
//獲取是否在線
function getIsOnline()
{
if (!$this->getIsConnect() && $this->bolIsLogin)
{
return false;
}
$this->sendCommand("NOOP");
$this->getLineResponse();
if (!$this->getRestIsSucceed())
{
return false;
}
return true;
}
//獲取郵件數量和字節數(返回數組)
function getMailSum($intReturnType=2)
{
if (!$this->getIsConnect() && $this->bolIsLogin)
{
return false;
}
$this->sendCommand("STAT");
$strLineResponse = $this->getLineResponse();
if (!$this->getRestIsSucceed())
{
return false;
}
if ($intReturnType==1)
{
return $this->strResponse;
}
else
{
$arrResponse = explode(" ", $this->strResponse);
if (!is_array($arrResponse) || count($arrResponse)<=0)
{
$this->setMessage('STAT command response message is error', 2006);
return false;
}
return array($arrResponse[1], $arrResponse[2]);
}
}
//獲取指定郵件得session Id
function getMailSessId($intMailId, $intReturnType=2)
{
if (!$this->getIsConnect() && $this->bolIsLogin)
{
return false;
}
if (!$intMailId = intval($intMailId))
{
$this->setMessage('Mail message id invalid', 1005);
return false;
}
$this->sendCommand("UIDL ". $intMailId);
$this->getLineResponse();
if (!$this->getRestIsSucceed())
{
return false;
}
if ($intReturnType == 1)
{
return $this->strResponse;
}
else
{
$arrResponse = explode(" ", $this->strResponse);
if (!is_array($arrResponse) || count($arrResponse)<=0)
{
$this->setMessage('UIDL command response message is error', 2006);
return false;
}
return array($arrResponse[1], $arrResponse[2]);
}
}
//取得某個郵件的大小
function getMailSize($intMailId, $intReturnType=2)
{
if (!$this->getIsConnect() && $this->bolIsLogin)
{
return false;
}
$this->sendCommand("LIST ".$intMailId);
$this->getLineResponse();
if (!$this->getRestIsSucceed())
{
return false;
}
if ($intReturnType == 1)
{
return $this->strResponse;
}
else
{
$arrMessage = explode(' ', $this->strResponse);
return array($arrMessage[1], $arrMessage[2]);
}
}
//獲取郵件基本列表數組
function getMailBaseList($intReturnType=2)
{
if (!$this->getIsConnect() && $this->bolIsLogin)
{
return false;
}
$this->sendCommand("LIST");
$this->getLineResponse();
if (!$this->getRestIsSucceed())
{
return false;
}
return $this->getRespMessage($intReturnType);
}
//獲取指定郵件所有信息,intReturnType是返回值類型,1是字符串,2是數組
function getMailMessage($intMailId, $intReturnType=1)
{
if (!$this->getIsConnect() && $this->bolIsLogin)
{
return false;
}
if (!$intMailId = intval($intMailId))
{
$this->setMessage('Mail message id invalid', 1005);
return false;
}
$this->sendCommand("RETR ". $intMailId);
$this->getLineResponse();
if (!$this->getRestIsSucceed())
{
return false;
}
return $this->getRespMessage($intReturnType);
}
//獲取某郵件前指定行, $intReturnType 返回值類型,1是字符串,2是數組
function getMailTopMessage($intMailId, $intTopLines=10, $intReturnType=1)
{
if (!$this->getIsConnect() && $this->bolIsLogin)
{
return false;
}
if (!$intMailId=intval($intMailId) || !$intTopLines=int($intTopLines))
{
$this->setMessage('Mail message id or Top lines number invalid', 1005);
return false;
}
$this->sendCommand("TOP ". $intMailId ." ". $intTopLines);
$this->getLineResponse();
if (!$this->getRestIsSucceed())
{
return false;
}
return $this->getRespMessage($intReturnType);
}
//刪除郵件
function delMail($intMailId)
{
if (!$this->getIsConnect() && $this->bolIsLogin)
{
return false;
}
if (!$intMailId=intval($intMailId))
{
$this->setMessage('Mail message id invalid', 1005);
return false;
}
$this->sendCommand("DELE ".$intMailId);
$this->getLineResponse();
if (!$this->getRestIsSucceed())
{
return false;
}
return true;
}
//重置被刪除得郵件標記為未刪除
function resetDeleMail()
{
if (!$this->getIsConnect() && $this->bolIsLogin)
{
return false;
}
$this->sendCommand("RSET");
$this->getLineResponse();
if (!$this->getRestIsSucceed())
{
return false;
}
return true;
}
//---------------
// 調試操作
//---------------
//輸出對象信息
function printObject()
{
print_r($this);
exit;
}
//輸出錯誤信息
function printError()
{
echo "[Error Msg] : $strMessage <br>\n";
echo "[Error Num] : $intErrorNum <br>\n";
exit;
}
//輸出主機信息
function printHost()
{
echo "[Host] : $this->strHost <br>\n";
echo "[Port] : $this->intPort <br>\n";
echo "[Email] : $this->strEmail <br>\n";
echo "[Passwd] : ******** <br>\n";
exit;
}
//輸出連接信息
function printConnect()
{
echo "[Connect] : $this->resHandler <br>\n";
echo "[Request] : $this->strRequest <br>\n";
echo "[Response] : $this->strResponse <br>\n";
exit;
}
}
?>
<?
//測試代碼
//例如:$o = SocketPOP3Client('郵箱地址', '密碼', 'POP3服務器', 'POP3端口')
/*
set_time_limit(0);
$o = new SocketPOPClient('[email protected]', '123456', 'pop.126.com', '110');
$o->popLogin();
print_r($o->getMailBaseList());
print_r($o->getMailSum(1));
print_r($o->getMailTopMessage(2, 2, 2));
$o->popLogout();
$o->closeHost();
$o->printObject();
*/
?>