TYPO3 API  SVNRelease
PopBeforeSmtpPlugin.php
Go to the documentation of this file.
00001 <?php
00002 
00003 /*
00004  * This file is part of SwiftMailer.
00005  * (c) 2004-2009 Chris Corbyn
00006  *
00007  * For the full copyright and license information, please view the LICENSE
00008  * file that was distributed with this source code.
00009  */
00010 
00011 //@require 'Swift/Events/TransportChangeListener.php';
00012 //@require 'Swift/Events/TransportChangeEvent.php';
00013 
00014 /**
00015  * Makes sure a connection to a POP3 host has been established prior to connecting to SMTP.
00016  *
00017  * @package Swift
00018  * @subpackage Plugins
00019  *
00020  * @author Chris Corbyn
00021  */
00022 class Swift_Plugins_PopBeforeSmtpPlugin
00023   implements Swift_Events_TransportChangeListener, Swift_Plugins_Pop_Pop3Connection
00024 {
00025 
00026   /** A delegate connection to use (mostly a test hook) */
00027   private $_connection;
00028 
00029   /** Hostname of the POP3 server */
00030   private $_host;
00031 
00032   /** Port number to connect on */
00033   private $_port;
00034 
00035   /** Encryption type to use (if any) */
00036   private $_crypto;
00037 
00038   /** Username to use (if any) */
00039   private $_username;
00040 
00041   /** Password to use (if any) */
00042   private $_password;
00043 
00044   /** Established connection via TCP socket */
00045   private $_socket;
00046 
00047   /** Connect timeout in seconds */
00048   private $_timeout = 10;
00049 
00050   /** SMTP Transport to bind to */
00051   private $_transport;
00052 
00053   /**
00054    * Create a new PopBeforeSmtpPlugin for $host and $port.
00055    *
00056    * @param string $host
00057    * @param int $port
00058    * @param string $cypto as "tls" or "ssl"
00059    */
00060   public function __construct($host, $port = 110, $crypto = null)
00061   {
00062     $this->_host = $host;
00063     $this->_port = $port;
00064     $this->_crypto = $crypto;
00065   }
00066 
00067   /**
00068    * Create a new PopBeforeSmtpPlugin for $host and $port.
00069    *
00070    * @param string $host
00071    * @param int $port
00072    * @param string $cypto as "tls" or "ssl"
00073    *
00074    * @return Swift_Plugins_PopBeforeSmtpPlugin
00075    */
00076   public static function newInstance($host, $port = 110, $crypto = null)
00077   {
00078     return new self($host, $port, $crypto);
00079   }
00080 
00081   /**
00082    * Set a Pop3Connection to delegate to instead of connecting directly.
00083    *
00084    * @param Swift_Plugins_Pop_Pop3Connection $connection
00085    */
00086   public function setConnection(Swift_Plugins_Pop_Pop3Connection $connection)
00087   {
00088     $this->_connection = $connection;
00089     return $this;
00090   }
00091 
00092   /**
00093    * Bind this plugin to a specific SMTP transport instance.
00094    *
00095    * @param Swift_Transport
00096    */
00097   public function bindSmtp(Swift_Transport $smtp)
00098   {
00099     $this->_transport = $smtp;
00100   }
00101 
00102   /**
00103    * Set the connection timeout in seconds (default 10).
00104    *
00105    * @param int $timeout
00106    */
00107   public function setTimeout($timeout)
00108   {
00109     $this->_timeout = (int) $timeout;
00110     return $this;
00111   }
00112 
00113   /**
00114    * Set the username to use when connecting (if needed).
00115    *
00116    * @param string $username
00117    */
00118   public function setUsername($username)
00119   {
00120     $this->_username = $username;
00121     return $this;
00122   }
00123 
00124   /**
00125    * Set the password to use when connecting (if needed).
00126    *
00127    * @param string $password
00128    */
00129   public function setPassword($password)
00130   {
00131     $this->_password = $password;
00132     return $this;
00133   }
00134 
00135   /**
00136    * Connect to the POP3 host and authenticate.
00137    *
00138    * @throws Swift_Plugins_Pop_Pop3Exception if connection fails
00139    */
00140   public function connect()
00141   {
00142     if (isset($this->_connection))
00143     {
00144       $this->_connection->connect();
00145     }
00146     else
00147     {
00148       if (!isset($this->_socket))
00149       {
00150         if (!$socket = fsockopen(
00151           $this->_getHostString(), $this->_port, $errno, $errstr, $this->_timeout))
00152         {
00153           throw new Swift_Plugins_Pop_Pop3Exception(
00154             sprintf('Failed to connect to POP3 host [%s]: %s', $this->_host, $errstr)
00155           );
00156         }
00157         $this->_socket = $socket;
00158 
00159         if (false === $greeting = fgets($this->_socket))
00160         {
00161           throw new Swift_Plugins_Pop_Pop3Exception(
00162             sprintf('Failed to connect to POP3 host [%s]', trim($greeting))
00163           );
00164         }
00165 
00166         $this->_assertOk($greeting);
00167 
00168         if ($this->_username)
00169         {
00170           $this->_command(sprintf("USER %s\r\n", $this->_username));
00171           $this->_command(sprintf("PASS %s\r\n", $this->_password));
00172         }
00173       }
00174     }
00175   }
00176 
00177   /**
00178    * Disconnect from the POP3 host.
00179    */
00180   public function disconnect()
00181   {
00182     if (isset($this->_connection))
00183     {
00184       $this->_connection->disconnect();
00185     }
00186     else
00187     {
00188       $this->_command("QUIT\r\n");
00189       if (!fclose($this->_socket))
00190       {
00191         throw new Swift_Plugins_Pop_Pop3Exception(
00192           sprintf('POP3 host [%s] connection could not be stopped', $this->_host)
00193         );
00194       }
00195       $this->_socket = null;
00196     }
00197   }
00198 
00199   /**
00200    * Invoked just before a Transport is started.
00201    *
00202    * @param Swift_Events_TransportChangeEvent $evt
00203    */
00204   public function beforeTransportStarted(Swift_Events_TransportChangeEvent $evt)
00205   {
00206     if (isset($this->_transport))
00207     {
00208       if ($this->_transport !== $evt->getTransport())
00209       {
00210         return;
00211       }
00212     }
00213 
00214     $this->connect();
00215     $this->disconnect();
00216   }
00217 
00218   /**
00219    * Not used.
00220    */
00221   public function transportStarted(Swift_Events_TransportChangeEvent $evt)
00222   {
00223   }
00224 
00225   /**
00226    * Not used.
00227    */
00228   public function beforeTransportStopped(Swift_Events_TransportChangeEvent $evt)
00229   {
00230   }
00231 
00232   /**
00233    * Not used.
00234    */
00235   public function transportStopped(Swift_Events_TransportChangeEvent $evt)
00236   {
00237   }
00238 
00239   // -- Private Methods
00240 
00241   private function _command($command)
00242   {
00243     if (!fwrite($this->_socket, $command))
00244     {
00245       throw new Swift_Plugins_Pop_Pop3Exception(
00246         sprintf('Failed to write command [%s] to POP3 host', trim($command))
00247       );
00248     }
00249 
00250     if (false === $response = fgets($this->_socket))
00251     {
00252       throw new Swift_Plugins_Pop_Pop3Exception(
00253         sprintf('Failed to read from POP3 host after command [%s]', trim($command))
00254       );
00255     }
00256 
00257     $this->_assertOk($response);
00258 
00259     return $response;
00260   }
00261 
00262   private function _assertOk($response)
00263   {
00264     if (substr($response, 0, 3) != '+OK')
00265     {
00266       throw new Swift_Plugins_Pop_Pop3Exception(
00267         sprintf('POP3 command failed [%s]', trim($response))
00268       );
00269     }
00270   }
00271 
00272   private function _getHostString()
00273   {
00274     $host = $this->_host;
00275     switch (strtolower($this->_crypto))
00276     {
00277       case 'ssl':
00278         $host = 'ssl://' . $host;
00279         break;
00280 
00281       case 'tls':
00282         $host = 'tls://' . $host;
00283         break;
00284     }
00285     return $host;
00286   }
00287 
00288 }