一、簡介
在本系列的第二篇中,我向你展示了所有構成整個POP3用戶端的JavaScript函數。為了檢索並在Web頁面上顯示電子郵件訊息以及建立負責把適當的行為添加到每一個使用者介面控制項的函數,我定義了負責發送和處理HTTP請求的函數。
在第二篇的最後,我們建立了一個具有完整功能的用戶端應用程式層。這個層能夠請求PHP檔案—它直接與一個指定POP3伺服器對話並且提取要被顯示的訊息以顯示於Web頁面中。儘管我在上一篇中所開發的使用者介面暴露了一些基本的控制項用於可視化和訊息之間導航,可能你想加入自己的新功能以建立一個更優秀的程式。為此,你可以在我提供的樣本基礎上加以改進,或者建立一種全新的介面,並提供更為複雜的導航控制項,或者一種真正專業化的外觀感覺。其實,如你所想象,這個程式中還存在大量可以擴充的地方。
在本文(最後一篇)中,我將把在上篇中建立的用戶端應用程式層串連到郵件伺服器並且執行POP3命令,從而檢索電子郵件訊息並把它顯示於相應的網頁上。為了實現這一目標,我將開發一個易於理解的PHP類,它提供了一些有用的方法來構建一個到POP3伺服器的串連並負責提取其中的電子郵件訊息。
下面,讓我們開始建立這個PHP POP3處理類。
二、使用POP3伺服器—定義POP3Processor類的基本架構
假定你已經正確理解了上一篇中定義的JavaScript函數,那麼現在我們將專註於開發一個PHP類。這個類負責串連到郵件伺服器,推入原始的POP3命令並且取回電子郵件訊息列表以備將來顯示之用。
為了實現以上任務,我開發的PHP類將暴露三個核心方法。第一個是構造器,它負責使用POP3認證命令建立一個到給定郵件伺服器的串連。第二個類方法fetch()負責傳送要求的命令以實現從收件匣中取回格式化的電子郵件訊息列表。最後,close()方法將關閉到伺服器的通訊端串連。
與上面描述的任務相應,該POP3Processor類的基本架構可以按下列方式定義:
class POP3Processor{
//串連到POP3伺服器
public function __construct(){
//串連到POP3伺服器的代碼在此
}
//取回電子郵件訊息
public function fetch(){
//檢索電子郵件訊息的代碼在此
}
// 關閉郵件伺服器串連
public function close(){
//關閉POP3郵件伺服器串連的代碼在此
}
} |
如你所見,上面這個類的結構遵循通常規則,因此它是比較易讀和易於理解的。當然,這也是這個類的唯一架構。接下來,我們必須定義每一個相關的類方法。首先,我們定義這個類的第一個方法。
三、串連到POP3伺服器—定義POP3Processor類構造器方法
為了處理所有與串連到POP3伺服器相關的操作,這個類使用了它的構造器方法。這個方法接受通常的串連到一個特定伺服器的輸入參數(也即它的名字或IP地址,以及名字/口令組合)。下面是這個方法的具體實現:
public function __construct($host,$user,$password){
if(!$this->fp=fsockopen($host,110,$errno,$errstr,30)){
throw new Exception('Failed to connect to POP3 server
'.$errstr.$errno);
}
stream_set_timeout($this->fp,2);
$this->output.=fgets($this->fp,128).'<br />';
fputs($this->fp,"USER $usern");//發送USER命令
$this->output.=fgets($this->fp,128).'<br />';
fputs($this->fp,"PASS $passwordn");//發送PASS命令
$this->output.=fgets($this->fp,128).'<br />';
$this->output.='||||';//發送限界字串
} |
如果你已經研究了上面的方法,那麼你會發現它的實現邏輯相當簡單。該方法實現的第一件事情是開啟一個到TCP連接埠110(預設的POP3伺服器連接埠號碼)的通訊端串連—通過利用輸入到這個方法的輸入參數實現。如你所見,這個操作相當直接,所以在此我們不再作分析。
在開啟一個到POP3伺服器的串連後,事情變得越來越有趣了。請注意,為了執行相應的存取控制過程並得到隨後由伺服器發送回用戶端的響應,這個方法先後發送“USER”和“PASS”命令。最後,該方法通過把四個管道字串定界符傳送到伺服器來結束它的操作。它們將用於把所有的伺服器響應(包括相關的電子郵件訊息列表)分解成塊。
至此,該構造器已經實現串連到POP3伺服器,發送使用者名稱/口令對並且接收在伺服器上產生的響應。然而,如我前面所提到的,這個類還必須取回電子郵件訊息列表以便於把這些訊息可視化顯示於客戶程式介面中。在下一節中,我將定義另一個負責檢索各個訊息的類方法fetch()。
四、取回電子郵件訊息—定義fetch()方法
如你在前面所見,與POP3伺服器進行互動其實只需要把伺服器能夠理解的適當的命令注入到通訊端中即可。遵循這一思路,fetch()類方法使用簡單的POP3命令得到現存訊息的完整列表。請看下面的定義:
public function fetch(){
fputs($this->fp,"STATn");//發送STAT命令
$ret=fgets($this->fp,128).'<br />';
if(substr($ret,0,5)!='-ERR '){
$messages=intval(substr($ret,4,1));
for($i=1;$i<=$messages;$i++){
fputs($this->fp,"RETR $in"); //發送RETR命令
$this->output.=stream_get_contents($this-
>fp).'<br /><br />';//取回電子郵件訊息
$this->output.='||||';//發送限界字串
}
}
$this->output=substr($this->output,0,strlen($this->output)-
4);
return $ret.$this->output;
} |
上面的方法首先使用一個“STAT”命令檢查伺服器的狀態,然後發送“RETR”命令,這個命令指示伺服器檢索儲存在收件匣中的訊息列表。如果在檢索過程中沒有任何錯誤發生,那麼這個方法將利用“stream_get_contents()”PHP內建函數來讀取每一條訊息的內容,並在每一條內容後添加上當我定義類構造器時向你展示的四個管道定界符。
最後,這個方法以字串形式返回完整的訊息列表,並把它們儲存在“$this->output”屬性中以備後面處理。如你所見,從POP3伺服器中取回電子郵件訊息可能比你想象的要容易得多。事實上,這僅是發送適當的POP3命令的事情,因為它們可以被伺服器正確解釋。
至此,我提供的這個PHP類已經能夠取回電子郵件訊息(以一個常規字串形式返回)。接下來,我需要定義另一個類方法close(),用於關閉到伺服器的串連。
五、關閉到POP3伺服器的串連—定義close()類方法
你可能已經猜出,這個close()類方法負責關閉到POP3伺服器的通訊端串連,而且這個方法的定義很短。實際上,它僅僅是PHP fclose()函數的一個簡單的封裝器,其具體實現代碼如下:
public function close(){
fputs($this->fp,"QUITn");
fclose($this->fp);
} |
上面的方法向POP3伺服器發出一個“QUIT”命令,這將導致該伺服器與用戶端程式的立即中斷。另外,該方法也關閉控制代碼$this->fp—這個控制代碼是第一次建立到伺服器的串連時建立的。
至此,我們定義了PHP類的所有方法。下面,讓我們看一下它們是如何聯合應用於一個類結構中的。很明顯,這將有助於你更容易地理解這個類的工作原理。下面是這個POP3Processor類的完整定義:
class POP3Processor{
//聲明資料成員
private $output='';
private $fp;
//構造器
public function __construct($host,$user,$password){
if(!$this->fp=fsockopen($host,110,$errno,$errstr,30)){
throw new Exception('Failed to connect to POP3 server
'.$errstr.$errno);
}
stream_set_timeout($this->fp,2);
$this->output.=fgets($this->fp,128).'<br />';
fputs($this->fp,"USER $usern");//發送USER命令
$this->output.=fgets($this->fp,128).'<br />';
fputs($this->fp,"PASS $passwordn");//發送PASS命令
$this->output.=fgets($this->fp,128).'<br />';
$this->output.='||||';//發送限界字串
}
//取回電子郵件訊息
public function fetch(){
fputs($this->fp,"STATn");//發送STAT命令
$ret=fgets($this->fp,128).'<br />';
if(substr($ret,0,5)!='-ERR '){
$messages=intval(substr($ret,4,1));
for($i=1;$i<=$messages;$i++){
fputs($this->fp,"RETR $in"); //發送RETR命令
$this->output.=stream_get_contents($this-
>fp).'<br /><br />';//取回電子郵件訊息
$this->output.='||||';//發送定界字串
}
}
$this->output=substr($this->output,0,strlen($this-
>output)-4);
return $ret.$this->output;
}
//關閉郵件伺服器串連
public function close(){
fputs($this->fp,"QUITn");
fclose($this->fp);
}
} 下面是這個類的一種可能的實現: try{
//執行個體化POP3處理器對象
$popProc=new POP3Processor('pop3hostname',username','password');
//從郵件伺服器取回訊息
echo $popProc->fetch();
//關閉郵件伺服器串連
$popProc->close();
}
catch(Exception $e){
echo $e->getMessage();
exit();
} |
如上例所示,一個POP3Processor對象被使用適當的輸入參數執行個體化,並且建立了一個到指定POP3伺服器的串連。然後,假定在串連處理過程中沒有錯誤發生,那麼接下來將檢索電子郵件訊息並將其顯示於Web頁面中,這是通過使用fetch()方法來實現的。在樣本最後,通過調用相應的close()方法關閉串連。
好,現在我已向你展示了如何使用POP3Processor類從一個POP3伺服器取回訊息,但是這個類是如何與我前面建立的使用者介面類進行互動的呢?為了展示AJAX應用程式是如何與POP 3處理類共同工作的,我將把所有的用戶端代碼放到一個pop_client.htm檔案中,而把PHP類放到另一個檔案pop_processor.php中,這樣你就可以很方便地看清完整的POP3用戶端是如何工作的。
六、組裝POP3端—把用戶端和伺服器端層聯合起來
如我在前面所提及,檔案pop_client.htm構成基於web的POP3用戶端,這個檔案與PHP3Processor類進行互動,以便串連到POP3伺服器並從中檢索郵件訊息列表。因這個檔案代碼較長,請參考所附源碼檔案(已加上詳細中文注釋)。
七、總結
現在,我們已經全部結束。在本系列文章中,我向你展示了AJAX技術的另一種應用—建立一個基於Web的POP3用戶端應用程式,它能夠實現從一個郵件伺服器中檢索電子郵件訊息並將其顯示於一個Web頁面中。當然,此程式僅是開發更複雜的工程的開始;但是通過這個程式,你應該能夠更為清晰地瞭解如何使用AJAX構建一個類似傳統型應用程式的Web程式。