422 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			PHP
		
	
	
	
		
		
			
		
	
	
			422 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			PHP
		
	
	
	
|  | <?php | ||
|  | /** | ||
|  |  * PHPMailer POP-Before-SMTP Authentication Class. | ||
|  |  * PHP Version 5.5. | ||
|  |  * | ||
|  |  * @see https://github.com/PHPMailer/PHPMailer/ The PHPMailer GitHub project | ||
|  |  * | ||
|  |  * @author    Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk> | ||
|  |  * @author    Jim Jagielski (jimjag) <jimjag@gmail.com> | ||
|  |  * @author    Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net> | ||
|  |  * @author    Brent R. Matzelle (original founder) | ||
|  |  * @copyright 2012 - 2019 Marcus Bointon | ||
|  |  * @copyright 2010 - 2012 Jim Jagielski | ||
|  |  * @copyright 2004 - 2009 Andy Prevost | ||
|  |  * @license   http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License | ||
|  |  * @note      This program is distributed in the hope that it will be useful - WITHOUT | ||
|  |  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
|  |  * FITNESS FOR A PARTICULAR PURPOSE. | ||
|  |  */ | ||
|  | 
 | ||
|  | namespace PHPMailer\PHPMailer; | ||
|  | 
 | ||
|  | /** | ||
|  |  * PHPMailer POP-Before-SMTP Authentication Class. | ||
|  |  * Specifically for PHPMailer to use for RFC1939 POP-before-SMTP authentication. | ||
|  |  * 1) This class does not support APOP authentication. | ||
|  |  * 2) Opening and closing lots of POP3 connections can be quite slow. If you need | ||
|  |  *   to send a batch of emails then just perform the authentication once at the start, | ||
|  |  *   and then loop through your mail sending script. Providing this process doesn't | ||
|  |  *   take longer than the verification period lasts on your POP3 server, you should be fine. | ||
|  |  * 3) This is really ancient technology; you should only need to use it to talk to very old systems. | ||
|  |  * 4) This POP3 class is deliberately lightweight and incomplete, implementing just | ||
|  |  *   enough to do authentication. | ||
|  |  *   If you want a more complete class there are other POP3 classes for PHP available. | ||
|  |  * | ||
|  |  * @author Richard Davey (original author) <rich@corephp.co.uk> | ||
|  |  * @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk> | ||
|  |  * @author Jim Jagielski (jimjag) <jimjag@gmail.com> | ||
|  |  * @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net> | ||
|  |  */ | ||
|  | class POP3 | ||
|  | { | ||
|  |     /** | ||
|  |      * The POP3 PHPMailer Version number. | ||
|  |      * | ||
|  |      * @var string | ||
|  |      */ | ||
|  |     const VERSION = '6.1.4'; | ||
|  | 
 | ||
|  |     /** | ||
|  |      * Default POP3 port number. | ||
|  |      * | ||
|  |      * @var int | ||
|  |      */ | ||
|  |     const DEFAULT_PORT = 110; | ||
|  | 
 | ||
|  |     /** | ||
|  |      * Default timeout in seconds. | ||
|  |      * | ||
|  |      * @var int | ||
|  |      */ | ||
|  |     const DEFAULT_TIMEOUT = 30; | ||
|  | 
 | ||
|  |     /** | ||
|  |      * Debug display level. | ||
|  |      * Options: 0 = no, 1+ = yes. | ||
|  |      * | ||
|  |      * @var int | ||
|  |      */ | ||
|  |     public $do_debug = 0; | ||
|  | 
 | ||
|  |     /** | ||
|  |      * POP3 mail server hostname. | ||
|  |      * | ||
|  |      * @var string | ||
|  |      */ | ||
|  |     public $host; | ||
|  | 
 | ||
|  |     /** | ||
|  |      * POP3 port number. | ||
|  |      * | ||
|  |      * @var int | ||
|  |      */ | ||
|  |     public $port; | ||
|  | 
 | ||
|  |     /** | ||
|  |      * POP3 Timeout Value in seconds. | ||
|  |      * | ||
|  |      * @var int | ||
|  |      */ | ||
|  |     public $tval; | ||
|  | 
 | ||
|  |     /** | ||
|  |      * POP3 username. | ||
|  |      * | ||
|  |      * @var string | ||
|  |      */ | ||
|  |     public $username; | ||
|  | 
 | ||
|  |     /** | ||
|  |      * POP3 password. | ||
|  |      * | ||
|  |      * @var string | ||
|  |      */ | ||
|  |     public $password; | ||
|  | 
 | ||
|  |     /** | ||
|  |      * Resource handle for the POP3 connection socket. | ||
|  |      * | ||
|  |      * @var resource | ||
|  |      */ | ||
|  |     protected $pop_conn; | ||
|  | 
 | ||
|  |     /** | ||
|  |      * Are we connected? | ||
|  |      * | ||
|  |      * @var bool | ||
|  |      */ | ||
|  |     protected $connected = false; | ||
|  | 
 | ||
|  |     /** | ||
|  |      * Error container. | ||
|  |      * | ||
|  |      * @var array | ||
|  |      */ | ||
|  |     protected $errors = []; | ||
|  | 
 | ||
|  |     /** | ||
|  |      * Line break constant. | ||
|  |      */ | ||
|  |     const LE = "\r\n"; | ||
|  | 
 | ||
|  |     /** | ||
|  |      * Simple static wrapper for all-in-one POP before SMTP. | ||
|  |      * | ||
|  |      * @param string   $host        The hostname to connect to | ||
|  |      * @param int|bool $port        The port number to connect to | ||
|  |      * @param int|bool $timeout     The timeout value | ||
|  |      * @param string   $username | ||
|  |      * @param string   $password | ||
|  |      * @param int      $debug_level | ||
|  |      * | ||
|  |      * @return bool | ||
|  |      */ | ||
|  |     public static function popBeforeSmtp( | ||
|  |         $host, | ||
|  |         $port = false, | ||
|  |         $timeout = false, | ||
|  |         $username = '', | ||
|  |         $password = '', | ||
|  |         $debug_level = 0 | ||
|  |     ) { | ||
|  |         $pop = new self(); | ||
|  | 
 | ||
|  |         return $pop->authorise($host, $port, $timeout, $username, $password, $debug_level); | ||
|  |     } | ||
|  | 
 | ||
|  |     /** | ||
|  |      * Authenticate with a POP3 server. | ||
|  |      * A connect, login, disconnect sequence | ||
|  |      * appropriate for POP-before SMTP authorisation. | ||
|  |      * | ||
|  |      * @param string   $host        The hostname to connect to | ||
|  |      * @param int|bool $port        The port number to connect to | ||
|  |      * @param int|bool $timeout     The timeout value | ||
|  |      * @param string   $username | ||
|  |      * @param string   $password | ||
|  |      * @param int      $debug_level | ||
|  |      * | ||
|  |      * @return bool | ||
|  |      */ | ||
|  |     public function authorise($host, $port = false, $timeout = false, $username = '', $password = '', $debug_level = 0) | ||
|  |     { | ||
|  |         $this->host = $host; | ||
|  |         // If no port value provided, use default
 | ||
|  |         if (false === $port) { | ||
|  |             $this->port = static::DEFAULT_PORT; | ||
|  |         } else { | ||
|  |             $this->port = (int) $port; | ||
|  |         } | ||
|  |         // If no timeout value provided, use default
 | ||
|  |         if (false === $timeout) { | ||
|  |             $this->tval = static::DEFAULT_TIMEOUT; | ||
|  |         } else { | ||
|  |             $this->tval = (int) $timeout; | ||
|  |         } | ||
|  |         $this->do_debug = $debug_level; | ||
|  |         $this->username = $username; | ||
|  |         $this->password = $password; | ||
|  |         //  Reset the error log
 | ||
|  |         $this->errors = []; | ||
|  |         //  connect
 | ||
|  |         $result = $this->connect($this->host, $this->port, $this->tval); | ||
|  |         if ($result) { | ||
|  |             $login_result = $this->login($this->username, $this->password); | ||
|  |             if ($login_result) { | ||
|  |                 $this->disconnect(); | ||
|  | 
 | ||
|  |                 return true; | ||
|  |             } | ||
|  |         } | ||
|  |         // We need to disconnect regardless of whether the login succeeded
 | ||
|  |         $this->disconnect(); | ||
|  | 
 | ||
|  |         return false; | ||
|  |     } | ||
|  | 
 | ||
|  |     /** | ||
|  |      * Connect to a POP3 server. | ||
|  |      * | ||
|  |      * @param string   $host | ||
|  |      * @param int|bool $port | ||
|  |      * @param int      $tval | ||
|  |      * | ||
|  |      * @return bool | ||
|  |      */ | ||
|  |     public function connect($host, $port = false, $tval = 30) | ||
|  |     { | ||
|  |         //  Are we already connected?
 | ||
|  |         if ($this->connected) { | ||
|  |             return true; | ||
|  |         } | ||
|  | 
 | ||
|  |         //On Windows this will raise a PHP Warning error if the hostname doesn't exist.
 | ||
|  |         //Rather than suppress it with @fsockopen, capture it cleanly instead
 | ||
|  |         set_error_handler([$this, 'catchWarning']); | ||
|  | 
 | ||
|  |         if (false === $port) { | ||
|  |             $port = static::DEFAULT_PORT; | ||
|  |         } | ||
|  | 
 | ||
|  |         //  connect to the POP3 server
 | ||
|  |         $errno = 0; | ||
|  |         $errstr = ''; | ||
|  |         $this->pop_conn = fsockopen( | ||
|  |             $host, //  POP3 Host
 | ||
|  |             $port, //  Port #
 | ||
|  |             $errno, //  Error Number
 | ||
|  |             $errstr, //  Error Message
 | ||
|  |             $tval | ||
|  |         ); //  Timeout (seconds)
 | ||
|  |         //  Restore the error handler
 | ||
|  |         restore_error_handler(); | ||
|  | 
 | ||
|  |         //  Did we connect?
 | ||
|  |         if (false === $this->pop_conn) { | ||
|  |             //  It would appear not...
 | ||
|  |             $this->setError( | ||
|  |                 "Failed to connect to server $host on port $port. errno: $errno; errstr: $errstr" | ||
|  |             ); | ||
|  | 
 | ||
|  |             return false; | ||
|  |         } | ||
|  | 
 | ||
|  |         //  Increase the stream time-out
 | ||
|  |         stream_set_timeout($this->pop_conn, $tval, 0); | ||
|  | 
 | ||
|  |         //  Get the POP3 server response
 | ||
|  |         $pop3_response = $this->getResponse(); | ||
|  |         //  Check for the +OK
 | ||
|  |         if ($this->checkResponse($pop3_response)) { | ||
|  |             //  The connection is established and the POP3 server is talking
 | ||
|  |             $this->connected = true; | ||
|  | 
 | ||
|  |             return true; | ||
|  |         } | ||
|  | 
 | ||
|  |         return false; | ||
|  |     } | ||
|  | 
 | ||
|  |     /** | ||
|  |      * Log in to the POP3 server. | ||
|  |      * Does not support APOP (RFC 2828, 4949). | ||
|  |      * | ||
|  |      * @param string $username | ||
|  |      * @param string $password | ||
|  |      * | ||
|  |      * @return bool | ||
|  |      */ | ||
|  |     public function login($username = '', $password = '') | ||
|  |     { | ||
|  |         if (!$this->connected) { | ||
|  |             $this->setError('Not connected to POP3 server'); | ||
|  |         } | ||
|  |         if (empty($username)) { | ||
|  |             $username = $this->username; | ||
|  |         } | ||
|  |         if (empty($password)) { | ||
|  |             $password = $this->password; | ||
|  |         } | ||
|  | 
 | ||
|  |         // Send the Username
 | ||
|  |         $this->sendString("USER $username" . static::LE); | ||
|  |         $pop3_response = $this->getResponse(); | ||
|  |         if ($this->checkResponse($pop3_response)) { | ||
|  |             // Send the Password
 | ||
|  |             $this->sendString("PASS $password" . static::LE); | ||
|  |             $pop3_response = $this->getResponse(); | ||
|  |             if ($this->checkResponse($pop3_response)) { | ||
|  |                 return true; | ||
|  |             } | ||
|  |         } | ||
|  | 
 | ||
|  |         return false; | ||
|  |     } | ||
|  | 
 | ||
|  |     /** | ||
|  |      * Disconnect from the POP3 server. | ||
|  |      */ | ||
|  |     public function disconnect() | ||
|  |     { | ||
|  |         $this->sendString('QUIT'); | ||
|  |         //The QUIT command may cause the daemon to exit, which will kill our connection
 | ||
|  |         //So ignore errors here
 | ||
|  |         try { | ||
|  |             @fclose($this->pop_conn); | ||
|  |         } catch (Exception $e) { | ||
|  |             //Do nothing
 | ||
|  |         } | ||
|  |     } | ||
|  | 
 | ||
|  |     /** | ||
|  |      * Get a response from the POP3 server. | ||
|  |      * | ||
|  |      * @param int $size The maximum number of bytes to retrieve | ||
|  |      * | ||
|  |      * @return string | ||
|  |      */ | ||
|  |     protected function getResponse($size = 128) | ||
|  |     { | ||
|  |         $response = fgets($this->pop_conn, $size); | ||
|  |         if ($this->do_debug >= 1) { | ||
|  |             echo 'Server -> Client: ', $response; | ||
|  |         } | ||
|  | 
 | ||
|  |         return $response; | ||
|  |     } | ||
|  | 
 | ||
|  |     /** | ||
|  |      * Send raw data to the POP3 server. | ||
|  |      * | ||
|  |      * @param string $string | ||
|  |      * | ||
|  |      * @return int | ||
|  |      */ | ||
|  |     protected function sendString($string) | ||
|  |     { | ||
|  |         if ($this->pop_conn) { | ||
|  |             if ($this->do_debug >= 2) { //Show client messages when debug >= 2
 | ||
|  |                 echo 'Client -> Server: ', $string; | ||
|  |             } | ||
|  | 
 | ||
|  |             return fwrite($this->pop_conn, $string, strlen($string)); | ||
|  |         } | ||
|  | 
 | ||
|  |         return 0; | ||
|  |     } | ||
|  | 
 | ||
|  |     /** | ||
|  |      * Checks the POP3 server response. | ||
|  |      * Looks for for +OK or -ERR. | ||
|  |      * | ||
|  |      * @param string $string | ||
|  |      * | ||
|  |      * @return bool | ||
|  |      */ | ||
|  |     protected function checkResponse($string) | ||
|  |     { | ||
|  |         if (strpos($string, '+OK') !== 0) { | ||
|  |             $this->setError("Server reported an error: $string"); | ||
|  | 
 | ||
|  |             return false; | ||
|  |         } | ||
|  | 
 | ||
|  |         return true; | ||
|  |     } | ||
|  | 
 | ||
|  |     /** | ||
|  |      * Add an error to the internal error store. | ||
|  |      * Also display debug output if it's enabled. | ||
|  |      * | ||
|  |      * @param string $error | ||
|  |      */ | ||
|  |     protected function setError($error) | ||
|  |     { | ||
|  |         $this->errors[] = $error; | ||
|  |         if ($this->do_debug >= 1) { | ||
|  |             echo '<pre>'; | ||
|  |             foreach ($this->errors as $e) { | ||
|  |                 print_r($e); | ||
|  |             } | ||
|  |             echo '</pre>'; | ||
|  |         } | ||
|  |     } | ||
|  | 
 | ||
|  |     /** | ||
|  |      * Get an array of error messages, if any. | ||
|  |      * | ||
|  |      * @return array | ||
|  |      */ | ||
|  |     public function getErrors() | ||
|  |     { | ||
|  |         return $this->errors; | ||
|  |     } | ||
|  | 
 | ||
|  |     /** | ||
|  |      * POP3 connection error handler. | ||
|  |      * | ||
|  |      * @param int    $errno | ||
|  |      * @param string $errstr | ||
|  |      * @param string $errfile | ||
|  |      * @param int    $errline | ||
|  |      */ | ||
|  |     protected function catchWarning($errno, $errstr, $errfile, $errline) | ||
|  |     { | ||
|  |         $this->setError( | ||
|  |             'Connecting to the POP3 server raised a PHP warning:' . | ||
|  |             "errno: $errno errstr: $errstr; errfile: $errfile; errline: $errline" | ||
|  |         ); | ||
|  |     } | ||
|  | } |