Zend Framework - Zend_Mail
Current view: /usr/local/lib/zend/trunk/incubator/library/Zend/Mail/Transport/Pop3.php
Date: Tue Feb 6 18:30:06 CET 2007 Executable lines: 126
Code covered: 76.98% Executed lines: 97
Legend: executed not executed dead code


       1                 : <?php                                                                                                    
       2                 : /**                                                                                                      
       3                 :  * Zend Framework                                                                                        
       4                 :  *                                                                                                       
       5                 :  * LICENSE                                                                                               
       6                 :  *                                                                                                       
       7                 :  * This source file is subject to version 1.0 of the Zend Framework                                      
       8                 :  * license, that is bundled with this package in the file LICENSE, and                                   
       9                 :  * is available through the world-wide-web at the following URL:                                         
      10                 :  * http://www.zend.com/license/framework/1_0.txt. If you did not receive                                 
      11                 :  * a copy of the Zend Framework license and are unable to obtain it                                      
      12                 :  * through the world-wide-web, please send a note to license@zend.com                                    
      13                 :  * so we can mail you a copy immediately.                                                                
      14                 :  *                                                                                                       
      15                 :  * @package    Zend_Mail                                                                                 
      16                 :  * @copyright  Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)                  
      17                 :  * @license    http://www.zend.com/license/framework/1_0.txt Zend Framework License version 1.0          
      18                 :  */                                                                                                      
      19                 :                                                                                                          
      20                 : /**                                                                                                      
      21                 :  * Zend_Mail_Transport_Exception                                                                         
      22                 :  */                                                                                                      
      23                 : require_once 'Zend/Mail/Transport/Exception.php';                                                        
      24                 :                                                                                                          
      25                 :                                                                                                          
      26                 : /**                                                                                                      
      27                 :  * @package    Zend_Mail                                                                                 
      28                 :  * @copyright  Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)                  
      29                 :  * @license    http://www.zend.com/license/framework/1_0.txt Zend Framework License version 1.0          
      30                 :  */                                                                                                      
      31                 : class Zend_Mail_Transport_Pop3                                                                           
      32                 : {                                                                                                        
      33                 :     /**                                                                                                  
      34                 :      * saves if server supports top                                                                      
      35                 :      */                                                                                                  
      36                 :     public $hasTop = null;                                                                               
      37                 :                                                                                                          
      38                 :     /**                                                                                                  
      39                 :      * socket to pop3                                                                                    
      40                 :      */                                                                                                  
      41                 :     private $_socket;                                                                                    
      42                 :                                                                                                          
      43                 :     /**                                                                                                  
      44                 :      * greeting timestamp for apop                                                                       
      45                 :      */                                                                                                  
      46                 :     private $_timestamp;                                                                                 
      47                 :                                                                                                          
      48                 :                                                                                                          
      49                 :     /**                                                                                                  
      50                 :      * Public constructor                                                                                
      51                 :      *                                                                                                   
      52                 :      * @param string $host  hostname of IP address of POP3 server, if given connect() is called          
      53                 :      * @param int    $port  port of POP3 server, default is 110 (995 for ssl)                            
      54                 :      * @param bool   $ssl   use ssl?                                                                     
      55                 :      */                                                                                                  
      56                 :     public function __construct($host = '', $port = null, $ssl = false)                                  
      57                 :     {                                                                                                    
      58              18 :         if ($host) {                                                                                     
      59               1 :             $this->connect($host, $port, $ssl);                                                          
      60               1 :         }                                                                                                
      61              18 :     }                                                                                                    
      62                 :                                                                                                          
      63                 :                                                                                                          
      64                 :     /**                                                                                                  
      65                 :      * Public destructor                                                                                 
      66                 :      */                                                                                                  
      67                 :     public function __destruct()                                                                         
      68                 :     {                                                                                                    
      69              18 :         $this->logout();                                                                                 
      70              18 :     }                                                                                                    
      71                 :                                                                                                          
      72                 :                                                                                                          
      73                 :     /**                                                                                                  
      74                 :      * Open connection to POP3 server                                                                    
      75                 :      *                                                                                                   
      76                 :      * @param  string $host  hostname of IP address of POP3 server                                       
      77                 :      * @param  int    $port  of POP3 server, default is 110 (995 for ssl)                                
      78                 :      * @param  string $ssl   use 'SSL' or 'TLS'                                                          
      79                 :      * @throws Zend_Mail_Transport_Exception                                                             
      80                 :      * @return string welcome message                                                                    
      81                 :      */                                                                                                  
      82                 :     public function connect($host, $port = null, $ssl = false)                                           
      83                 :     {                                                                                                    
      84              18 :         if ($ssl == 'SSL') {                                                                             
      85               1 :             $host = 'ssl://' . $host;                                                                    
      86               1 :         }                                                                                                
      87                 :                                                                                                          
      88              18 :         if ($port === null) {                                                                            
      89              16 :             $port = $ssl == 'SSL' ? 995 : 110;                                                           
      90              16 :         }                                                                                                
      91                 :                                                                                                          
      92              18 :         $this->_socket = @fsockopen($host, $port);                                                       
      93              18 :         if (!$this->_socket) {                                                                           
      94               2 :             throw new Zend_Mail_Transport_Exception('cannot connect to host');                           
      95                 :         }                                                                                                
      96                 :                                                                                                          
      97              16 :         $welcome = $this->readResponse();                                                                
      98                 :                                                                                                          
      99              15 :         strtok($welcome, '<');                                                                           
     100              15 :         $this->_timestamp = strtok('>');                                                                 
     101              15 :         if (!strpos($this->_timestamp, '@')) {                                                           
     102              15 :             $this->_timestamp = null;                                                                    
     103              15 :         } else {                                                                                         
     104               0 :             $this->_timestamp = '<' . $this->_timestamp . '>';                                           
     105                 :         }                                                                                                
     106                 :                                                                                                          
     107              15 :         if($ssl === 'TLS') {                                                                             
     108               1 :             $this->request('STLS');                                                                      
     109               1 :             $result = stream_socket_enable_crypto($this->_socket, true, STREAM_CRYPTO_METHOD_TLS_CLIENT);
     110               1 :             if(!$result) {                                                                               
     111               0 :                 throw new Zend_Mail_Transport_Exception('cannot enable TLS');                            
     112                 :             }                                                                                            
     113               1 :         }                                                                                                
     114                 :                                                                                                          
     115              15 :         return $welcome;                                                                                 
     116                 :     }                                                                                                    
     117                 :                                                                                                          
     118                 :                                                                                                          
     119                 :     /**                                                                                                  
     120                 :      * Send a request                                                                                    
     121                 :      *                                                                                                   
     122                 :      * @param string $request  your request without newline                                              
     123                 :      */                                                                                                  
     124                 :     public function sendRequest($request)                                                                
     125                 :     {                                                                                                    
     126              16 :         $result = @fputs($this->_socket, $request."\n");                                                 
     127              16 :         if (!$result) {                                                                                  
     128               1 :             throw new Zend_Mail_Transport_Exception('send failed - connection closed?');                 
     129                 :         }                                                                                                
     130              16 :     }                                                                                                    
     131                 :                                                                                                          
     132                 :                                                                                                          
     133                 :     /**                                                                                                  
     134                 :      *                                                                                                   
     135                 :      * read a response                                                                                   
     136                 :      *                                                                                                   
     137                 :      * @param  boolean response has multiple lines and should be read until "<nl>.<nl>"                  
     138                 :      * @throws Zend_Mail_Transport_Exception                                                             
     139                 :      * @return string response                                                                           
     140                 :      */                                                                                                  
     141                 :     public function readResponse($multiline = false)                                                     
     142                 :     {                                                                                                    
     143              16 :         $result = fgets($this->_socket);                                                                 
     144              16 :         if (!is_string($result)) {                                                                       
     145               0 :             throw new Zend_Mail_Transport_Exception('read failed - connection closed?');                 
     146                 :         }                                                                                                
     147                 :                                                                                                          
     148              16 :         $result = trim($result);                                                                         
     149              16 :         if (strpos($result, ' ')) {                                                                      
     150              16 :             list($status, $message) = explode(' ', $result, 2);                                          
     151              16 :         } else {                                                                                         
     152              15 :             $status = $result;                                                                           
     153              15 :             $message = '';                                                                               
     154                 :         }                                                                                                
     155                 :                                                                                                          
     156              16 :         if ($status != '+OK') {                                                                          
     157               2 :             throw new Zend_Mail_Transport_Exception('last request failed');                              
     158                 :         }                                                                                                
     159                 :                                                                                                          
     160              15 :         if ($multiline) {                                                                                
     161               5 :             $message = '';                                                                               
     162               5 :             $line = fgets($this->_socket);                                                               
     163               5 :             while ($line && trim($line) != '.') {                                                        
     164               5 :                 $message .= $line;                                                                       
     165               5 :                 $line = fgets($this->_socket);                                                           
     166               5 :             };                                                                                           
     167               5 :         }                                                                                                
     168                 :                                                                                                          
     169              15 :         return $message;                                                                                 
     170                 :     }                                                                                                    
     171                 :                                                                                                          
     172                 :                                                                                                          
     173                 :     /**                                                                                                  
     174                 :      * Send request and get resposne                                                                     
     175                 :      * @see sendRequest(), readResponse()                                                                
     176                 :      *                                                                                                   
     177                 :      * @param  string $request    request                                                                
     178                 :      * @param  bool   $multiline  multiline response?                                                    
     179                 :      * @return string             result from readResponse()                                             
     180                 :      */                                                                                                  
     181                 :     public function request($request, $multiline = false)                                                
     182                 :     {                                                                                                    
     183              16 :         $this->sendRequest($request);                                                                    
     184              16 :         return $this->readResponse($multiline);                                                          
     185                 :     }                                                                                                    
     186                 :                                                                                                          
     187                 :                                                                                                          
     188                 :     /**                                                                                                  
     189                 :      * End communication with POP3 server (also closes socket)                                           
     190                 :      */                                                                                                  
     191                 :     public function logout()                                                                             
     192                 :     {                                                                                                    
     193              18 :         if(!$this->_socket) {                                                                            
     194              17 :             return;                                                                                      
     195                 :         }                                                                                                
     196                 :                                                                                                          
     197                 :         try {                                                                                            
     198              16 :             $this->request('QUIT');                                                                      
     199              16 :         } catch (Zend_Mail_Transport_Exception $e) {                                                     
     200                 :             // ignore error - we're closing the socket anyway                                            
     201                 :         }                                                                                                
     202                 :                                                                                                          
     203              16 :         fclose($this->_socket);                                                                          
     204              16 :         $this->_socket = null;                                                                           
     205              16 :     }                                                                                                    
     206                 :                                                                                                          
     207                 :                                                                                                          
     208                 :     /**                                                                                                  
     209                 :      * Get capabilities from POP3 server                                                                 
     210                 :      *                                                                                                   
     211                 :      * @return array list of capabilities                                                                
     212                 :      */                                                                                                  
     213                 :     public function capa()                                                                               
     214                 :     {                                                                                                    
     215               0 :         $result = $this->request('CAPA', true);                                                          
     216               0 :         return explode("\n", $result);                                                                   
     217                 :     }                                                                                                    
     218                 :                                                                                                          
     219                 :                                                                                                          
     220                 :     /**                                                                                                  
     221                 :      * Login to POP3 server. Can use APOP                                                                
     222                 :      *                                                                                                   
     223                 :      * @param  string $user      username                                                                
     224                 :      * @param  string $password  password                                                                
     225                 :      * @param  bool   $try_apop  should APOP be tried?                                                   
     226                 :      * @return void                                                                                      
     227                 :      */                                                                                                  
     228                 :     public function login($user, $password, $tryApop = true)                                             
     229                 :     {                                                                                                    
     230              14 :         if ($tryApop && $this->_timestamp) {                                                             
     231                 :             try {                                                                                        
     232               0 :                 $this->request("APOP $user " . md5($this->_timestamp . $password));                      
     233               0 :                 return;                                                                                  
     234                 :             } catch (Zend_Mail_Transport_Exception $e) {                                                 
     235                 :                 // ignore                                                                                
     236                 :             }                                                                                            
     237                 :         }                                                                                                
     238                 :                                                                                                          
     239              14 :         $result = $this->request("USER $user");                                                          
     240              14 :         $result = $this->request("PASS $password");                                                      
     241              14 :     }                                                                                                    
     242                 :                                                                                                          
     243                 :                                                                                                          
     244                 :     /**                                                                                                  
     245                 :      * Make STAT call for message count and size sum                                                     
     246                 :      *                                                                                                   
     247                 :      * @param  int $messages  out parameter with count of messages                                       
     248                 :      * @param  int $octets    out parameter with size in octects of messages                             
     249                 :      * @return void                                                                                      
     250                 :      */                                                                                                  
     251                 :     public function status(&$messages, &$octets)                                                         
     252                 :     {                                                                                                    
     253               1 :         $messages = 0;                                                                                   
     254               1 :         $octets = 0;                                                                                     
     255               1 :         $result = $this->request('STAT');                                                                
     256                 :                                                                                                          
     257               1 :         list($messages, $octets) = explode(' ', $result);                                                
     258               1 :     }                                                                                                    
     259                 :                                                                                                          
     260                 :                                                                                                          
     261                 :     /**                                                                                                  
     262                 :      * Make LIST call for size of message(s)                                                             
     263                 :      *                                                                                                   
     264                 :      * @param  int $msgno  number of message                                                             
     265                 :      * @return int|array   size of given message or list with array(num => size)                         
     266                 :      */                                                                                                  
     267                 :     public function getList($msgno = null)                                                               
     268                 :     {                                                                                                    
     269               2 :         if ($msgno !== null) {                                                                           
     270               1 :             $result = $this->request("LIST $msgno");                                                     
     271                 :                                                                                                          
     272               1 :             list(, $result) = explode(' ', $result);                                                     
     273               1 :             return (int)$result;                                                                         
     274                 :         }                                                                                                
     275                 :                                                                                                          
     276               1 :         $result = $this->request('LIST', true);                                                          
     277               1 :         $messages = array();                                                                             
     278               1 :         $line = strtok($result, "\n");                                                                   
     279               1 :         while($line) {                                                                                   
     280               1 :             list($no, $size) = explode(' ', trim($line));                                                
     281               1 :             $messages[(int)$no] = (int)$size;                                                            
     282               1 :             $line = strtok("\n");                                                                        
     283               1 :         }                                                                                                
     284                 :                                                                                                          
     285               1 :         return $messages;                                                                                
     286                 :     }                                                                                                    
     287                 :                                                                                                          
     288                 :                                                                                                          
     289                 :     /**                                                                                                  
     290                 :      * Make UIDL call for getting a uniqueid                                                             
     291                 :      *                                                                                                   
     292                 :      * @param  int $msgno    number of message                                                           
     293                 :      * @return string|array  uniqueid of message or list with array(num => uniqueid)                     
     294                 :      */                                                                                                  
     295                 :     public function uniqueid($msgno = null)                                                              
     296                 :     {                                                                                                    
     297               0 :         if ($msgno !== null) {                                                                           
     298               0 :             $result = $this->request("UIDL $msgno");                                                     
     299                 :                                                                                                          
     300               0 :             list(, $result) = explode(' ', $result);                                                     
     301               0 :             return $result;                                                                              
     302                 :         }                                                                                                
     303                 :                                                                                                          
     304               0 :         $result = $this->request('UIDL', true);                                                          
     305                 :                                                                                                          
     306               0 :         $result = explode("\n", $result);                                                                
     307               0 :         $messages = array();                                                                             
     308               0 :         foreach ($result as $line) {                                                                     
     309               0 :             list($no, $id) = explode(' ', $line);                                                        
     310               0 :             $messages[(int)$no] = $id;                                                                   
     311               0 :         }                                                                                                
     312                 :                                                                                                          
     313               0 :         return $messages;                                                                                
     314                 :                                                                                                          
     315                 :     }                                                                                                    
     316                 :                                                                                                          
     317                 :                                                                                                          
     318                 :     /**                                                                                                  
     319                 :      * Make TOP call for getting headers and maybe some body lines                                       
     320                 :      * This method also sets hasTop - before it it's not known if top is supported                       
     321                 :      *                                                                                                   
     322                 :      * The fallback makes normale RETR call, which retrieves the whole message. Additional               
     323                 :      * lines are not removed.                                                                            
     324                 :      *                                                                                                   
     325                 :      * @param int  $msgno     number of message                                                          
     326                 :      * @param int  $lines     number of wanted body lines (empty line is inserted after header lines)    
     327                 :      * @param bool $fallback  fallback with full retrieve if top is not supported                        
     328                 :      * @return string message headers with wanted body lines                                             
     329                 :      */                                                                                                  
     330                 :     public function top($msgno, $lines = 0, $fallback = false)                                           
     331                 :     {                                                                                                    
     332               6 :         if ($this->hasTop === false) {                                                                   
     333               0 :             if ($fallback) {                                                                             
     334               0 :                 return $this->retrive($msgno);                                                           
     335                 :             } else {                                                                                     
     336               0 :                 throw new Zend_Mail_Transport_Exception('top not supported and no fallback wanted');     
     337                 :             }                                                                                            
     338                 :         }                                                                                                
     339               6 :         $this->hasTop = true;                                                                            
     340                 :                                                                                                          
     341               6 :         if (!$lines || (int)$lines < 1) {                                                                
     342               6 :             $request = "TOP $msgno";                                                                     
     343               6 :         } else {                                                                                         
     344               0 :             $request = "TOP $msgno $lines";                                                              
     345                 :         }                                                                                                
     346                 :                                                                                                          
     347                 :         try {                                                                                            
     348               6 :             $result = $this->request($request, true);                                                    
     349               6 :         } catch (Zend_Mail_Transport_Exception $e) {                                                     
     350               2 :             $this->hasTop = false;                                                                       
     351               2 :             if ($fallback) {                                                                             
     352               2 :                 $result = $this->retrive($msgno);                                                        
     353               0 :             } else {                                                                                     
     354               0 :                 throw $e;                                                                                
     355                 :             }                                                                                            
     356                 :         }                                                                                                
     357                 :                                                                                                          
     358               4 :         return $result;                                                                                  
     359                 :     }                                                                                                    
     360                 :                                                                                                          
     361                 :                                                                                                          
     362                 :     /**                                                                                                  
     363                 :      * Make a RETR call for retrieving a full message with headers and body                              
     364                 :      *                                                                                                   
     365                 :      * @param  int     $msgno  message number                                                            
     366                 :      * @return string          message                                                                   
     367                 :      */                                                                                                  
     368                 :     public function retrive($msgno)                                                                      
     369                 :     {                                                                                                    
     370               3 :         $result = $this->request("RETR $msgno", true);                                                   
     371               1 :         return $result;                                                                                  
     372                 :     }                                                                                                    
     373                 :                                                                                                          
     374                 :                                                                                                          
     375                 :     /**                                                                                                  
     376                 :      * Make a NOOP call, maybe needed for keeping the server happy                                       
     377                 :      */                                                                                                  
     378                 :     public function noop()                                                                               
     379                 :     {                                                                                                    
     380               1 :         $this->request('NOOP');                                                                          
     381               1 :     }                                                                                                    
     382                 :                                                                                                          
     383                 :                                                                                                          
     384                 :     /**                                                                                                  
     385                 :      * Make a DELE count to remove a message                                                             
     386                 :      */                                                                                                  
     387                 :     public function delete($msgno)                                                                       
     388                 :     {                                                                                                    
     389               0 :         $this->request("DELE $msgno");                                                                   
     390               0 :     }                                                                                                    
     391                 :                                                                                                          
     392                 :                                                                                                          
     393                 :     /**                                                                                                  
     394                 :      * Make RSET call, which rollbacks delete requests                                                   
     395                 :      */                                                                                                  
     396                 :     public function undelete()                                                                           
     397                 :     {                                                                                                    
     398               0 :         $this->request('RSET');                                                                          
     399               0 :     }                                                                                                    
     400                 : }                                                                                                        
     401                 : 

Generated by: PHPUnit 3.0.0 and Xdebug 2.0.0RC2-dev.