Author: as
Date: Fri Jul  6 10:27:24 2007
New Revision: 5706

Log:
- Put the transport classes in the correct files.

Modified:
    trunk/Mail/design/class_diagram.png
    trunk/Mail/src/mail_autoload.php
    trunk/Mail/src/transports/mta/mta_transport.php
    trunk/Mail/src/transports/mta/transport_mta.php
    trunk/Mail/src/transports/smtp/smtp_transport.php
    trunk/Mail/src/transports/smtp/transport_smtp.php

Modified: trunk/Mail/design/class_diagram.png
==============================================================================
Binary files - no diff available.

Modified: trunk/Mail/src/mail_autoload.php
==============================================================================
--- trunk/Mail/src/mail_autoload.php [iso-8859-1] (original)
+++ trunk/Mail/src/mail_autoload.php [iso-8859-1] Fri Jul  6 10:27:24 2007
@@ -21,11 +21,11 @@
     'ezcMailTransport'                  => 'Mail/interfaces/transport.php',
     'ezcMail'                           => 'Mail/mail.php',
     'ezcMailFilePart'                   => 'Mail/parts/file.php',
-    'ezcMailMtaTransport'               => 
'Mail/transports/mta/transport_mta.php',
+    'ezcMailMtaTransport'               => 
'Mail/transports/mta/mta_transport.php',
     'ezcMailMultipart'                  => 'Mail/parts/multipart.php',
     'ezcMailMultipartParser'            => 
'Mail/parser/parts/multipart_parser.php',
     'ezcMailParserSet'                  => 
'Mail/parser/interfaces/parser_set.php',
-    'ezcMailSmtpTransport'              => 
'Mail/transports/smtp/transport_smtp.php',
+    'ezcMailSmtpTransport'              => 
'Mail/transports/smtp/smtp_transport.php',
     'ezcMailTransportOptions'           => 
'Mail/options/transport_options.php',
     'ezcMailAddress'                    => 'Mail/structs/mail_address.php',
     'ezcMailCharsetConverter'           => 'Mail/internal/charset_convert.php',
@@ -72,8 +72,8 @@
     'ezcMailTextParser'                 => 'Mail/parser/parts/text_parser.php',
     'ezcMailTools'                      => 'Mail/tools.php',
     'ezcMailTransportConnection'        => 
'Mail/transports/transport_connection.php',
-    'ezcMailTransportMta'               => 
'Mail/transports/mta/mta_transport.php',
-    'ezcMailTransportSmtp'              => 
'Mail/transports/smtp/smtp_transport.php',
+    'ezcMailTransportMta'               => 
'Mail/transports/mta/transport_mta.php',
+    'ezcMailTransportSmtp'              => 
'Mail/transports/smtp/transport_smtp.php',
     'ezcMailVariableSet'                => 
'Mail/transports/variable/var_set.php',
     'ezcMailVirtualFile'                => 
'Mail/parts/fileparts/virtual_file.php',
 );

Modified: trunk/Mail/src/transports/mta/mta_transport.php
==============================================================================
--- trunk/Mail/src/transports/mta/mta_transport.php [iso-8859-1] (original)
+++ trunk/Mail/src/transports/mta/mta_transport.php [iso-8859-1] Fri Jul  6 
10:27:24 2007
@@ -1,6 +1,6 @@
 <?php
 /**
- * File containing the ezcMailTransportMta class
+ * File containing the ezcMailMtaTransport class
  *
  * @package Mail
  * @version //autogen//
@@ -9,13 +9,57 @@
  */
 
 /**
- * This class is deprecated. Use ezcMailMtaTransport instead.
+ * Implementation of the mail transport interface using the system MTA.
+ *
+ * The system MTA translates to sendmail on most Linux distributions.
+ *
+ * Qmail insists it should only have "\n" linebreaks and will send
+ * garbled messages with the default "\r\n" setting.
+ * Use ezcMailTools::setLineBreak( "\n" ) before sending mail to fix this 
issue.
  *
  * @package Mail
  * @version //autogen//
- * @ignore
+ * @mainclass
  */
-class ezcMailTransportMta extends ezcMailMtaTransport
+class ezcMailMtaTransport implements ezcMailTransport
 {
+    /**
+     * Constructs a new ezcMailMtaTransport.
+     */
+    public function __construct(  )
+    {
+    }
+
+    /**
+     * Sends the mail $mail using the PHP mail method.
+     *
+     * Note that a message may not arrive at the destination even though
+     * it was accepted for delivery.
+     *
+     * @throws ezcMailTransportException
+     *         if the mail was not accepted for delivery by the MTA.
+     * @param ezcMail $mail
+     */
+    public function send( ezcMail $mail )
+    {
+        $mail->appendExcludeHeaders( array( 'to', 'subject' ) );
+        $headers = rtrim( $mail->generateHeaders() ); // rtrim removes the 
linebreak at the end, mail doesn't want it.
+
+        if ( ( count( $mail->to ) + count( $mail->cc ) + count( $mail->bcc ) ) 
< 1 )
+        {
+            throw new ezcMailTransportException( 'No recipient addresses found 
in message header.' );
+        }
+        $additionalParameters = "";
+        if ( isset( $mail->returnPath ) )
+        {
+            $additionalParameters = "-f{$mail->returnPath->email}";
+        }
+        $success = mail( ezcMailTools::composeEmailAddresses( $mail->to ),
+                         $mail->getHeader( 'Subject' ), $mail->generateBody(), 
$headers, $additionalParameters );
+        if ( $success === false )
+        {
+            throw new ezcMailTransportException( 'The email could not be sent 
by sendmail' );
+        }
+    }
 }
 ?>

Modified: trunk/Mail/src/transports/mta/transport_mta.php
==============================================================================
--- trunk/Mail/src/transports/mta/transport_mta.php [iso-8859-1] (original)
+++ trunk/Mail/src/transports/mta/transport_mta.php [iso-8859-1] Fri Jul  6 
10:27:24 2007
@@ -1,6 +1,6 @@
 <?php
 /**
- * File containing the ezcMailMtaTransport class
+ * File containing the ezcMailTransportMta class
  *
  * @package Mail
  * @version //autogen//
@@ -9,57 +9,13 @@
  */
 
 /**
- * Implementation of the mail transport interface using the system MTA.
- *
- * The system MTA translates to sendmail on most Linux distributions.
- *
- * Qmail insists it should only have "\n" linebreaks and will send
- * garbled messages with the default "\r\n" setting.
- * Use ezcMailTools::setLineBreak( "\n" ) before sending mail to fix this 
issue.
+ * This class is deprecated. Use ezcMailMtaTransport instead.
  *
  * @package Mail
  * @version //autogen//
- * @mainclass
+ * @ignore
  */
-class ezcMailMtaTransport implements ezcMailTransport
+class ezcMailTransportMta extends ezcMailMtaTransport
 {
-    /**
-     * Constructs a new ezcMailMtaTransport.
-     */
-    public function __construct(  )
-    {
-    }
-
-    /**
-     * Sends the mail $mail using the PHP mail method.
-     *
-     * Note that a message may not arrive at the destination even though
-     * it was accepted for delivery.
-     *
-     * @throws ezcMailTransportException
-     *         if the mail was not accepted for delivery by the MTA.
-     * @param ezcMail $mail
-     */
-    public function send( ezcMail $mail )
-    {
-        $mail->appendExcludeHeaders( array( 'to', 'subject' ) );
-        $headers = rtrim( $mail->generateHeaders() ); // rtrim removes the 
linebreak at the end, mail doesn't want it.
-
-        if ( ( count( $mail->to ) + count( $mail->cc ) + count( $mail->bcc ) ) 
< 1 )
-        {
-            throw new ezcMailTransportException( 'No recipient addresses found 
in message header.' );
-        }
-        $additionalParameters = "";
-        if ( isset( $mail->returnPath ) )
-        {
-            $additionalParameters = "-f{$mail->returnPath->email}";
-        }
-        $success = mail( ezcMailTools::composeEmailAddresses( $mail->to ),
-                         $mail->getHeader( 'Subject' ), $mail->generateBody(), 
$headers, $additionalParameters );
-        if ( $success === false )
-        {
-            throw new ezcMailTransportException( 'The email could not be sent 
by sendmail' );
-        }
-    }
 }
 ?>

Modified: trunk/Mail/src/transports/smtp/smtp_transport.php
==============================================================================
--- trunk/Mail/src/transports/smtp/smtp_transport.php [iso-8859-1] (original)
+++ trunk/Mail/src/transports/smtp/smtp_transport.php [iso-8859-1] Fri Jul  6 
10:27:24 2007
@@ -1,6 +1,6 @@
 <?php
 /**
- * File containing the ezcMailTransportSmtp class
+ * File containing the ezcMailSmtpTransport class.
  *
  * @package Mail
  * @version //autogen//
@@ -9,13 +9,672 @@
  */
 
 /**
- * This class is deprecated. Use ezcMailSmtpTransport instead.
+ * This class implements the Simple Mail Transfer Protocol (SMTP)
+ * with authentication support.
+ *
+ * The implementation supports most of the commands specified in:
+ *  - [EMAIL PROTECTED] http://www.faqs.org/rfcs/rfc821.html} (SMTP)
+ *  - [EMAIL PROTECTED] http://www.faqs.org/rfcs/rfc2554.html} (SMTP 
Authentication)
+ *
+ * @property string $serverHost
+ *           The SMTP server host to connect to.
+ * @property int $serverPort
+ *           The port of the SMTP server. Defaults to 25.
+ * @property string $username
+ *           The username used for authentication. The default is blank which
+ *           means no authentication.
+ * @property string $password
+ *           The password used for authentication.
+ * @property int $timeout
+ *           The timeout value of the connection in seconds. The default is
+ *           5 seconds. When setting/getting this option, the timeout option
+ *           from $this->options [EMAIL PROTECTED] ezcMailTransportOptions} 
will be set instead.
+ * @property string $senderHost
+ *           The hostname of the computer that sends the mail. The default is
+ *           'localhost'.
+ * @property ezcMailSmtpTransportOptions $options
+ *           Holds the options you can set to the SMTP transport.
  *
  * @package Mail
  * @version //autogen//
- * @ignore
+ * @mainclass
  */
-class ezcMailTransportSmtp extends ezcMailSmtpTransport
+class ezcMailSmtpTransport implements ezcMailTransport
 {
+    /**
+     * Plain connection.
+     */
+    const CONNECTION_PLAIN = 'tcp';
+
+    /**
+     * SSL connection.
+     */
+    const CONNECTION_SSL = 'ssl';
+
+    /**
+     * SSLv2 connection.
+     */
+    const CONNECTION_SSLV2 = 'sslv2';
+
+    /**
+     * SSLv3 connection.
+     */
+    const CONNECTION_SSLV3 = 'sslv3';
+
+    /**
+     * TLS connection.
+     */
+    const CONNECTION_TLS = 'tls';
+
+    /**
+     * The line-break characters to use.
+     *
+     * @access private
+     */
+    const CRLF = "\r\n";
+
+    /**
+     * We are not connected to a server.
+     *
+     * @access private
+     */
+    const STATUS_NOT_CONNECTED = 1;
+
+    /**
+     * We are connected to the server, but not authenticated.
+     *
+     * @access private
+     */
+    const STATUS_CONNECTED = 2;
+
+    /**
+     * We are connected to the server and authenticated.
+     *
+     * @access private
+     */
+    const STATUS_AUTHENTICATED = 3;
+
+    /**
+     * The connection to the SMTP server.
+     *
+     * @var resource
+     */
+    protected $connection;
+
+    /**
+     * Holds the connection status.
+     *
+     * $var int [EMAIL PROTECTED] STATUS_NOT_CONNECTED},
+     *          [EMAIL PROTECTED] STATUS_CONNECTED} or
+     *          [EMAIL PROTECTED] STATUS_AUTHENTICATED}.
+     */
+    protected $status;
+
+    /**
+     * True if authentication should be performed; otherwise false.
+     *
+     * This variable is set to true if a username is provided for login.
+     *
+     * @var bool
+     */
+    protected $doAuthenticate;
+
+    /**
+     * Holds if the connection should be kept open after sending a mail.
+     *
+     * @var bool
+     */
+    protected $keepConnection = false;
+
+    /**
+     * Holds the properties of this class.
+     *
+     * @var array(string=>mixed)
+     */
+    protected $properties = array();
+
+    /**
+     * Holds the options of this class.
+     *
+     * @var ezcMailSmtpTransportOptions
+     */
+    protected $options;
+
+    /**
+     * Constructs a new ezcMailSmtpTransport.
+     *
+     * The constructor expects, at least, the hostname $host of the SMTP 
server.
+     *
+     * The username $user will be used for authentication if provided.
+     * If it is left blank no authentication will be performed.
+     *
+     * The password $password will be used for authentication
+     * if provided. Use this parameter always in combination with the $user
+     * parameter.
+     *
+     * The value $port specifies on which port to connect to $host. By default
+     * it is 25 for plain connections and 465 for TLS/SSL/SSLv2/SSLv3.
+     *
+     * Note: The ssl option from [EMAIL PROTECTED] ezcMailTransportOptions} 
doesn't apply to SMTP.
+     * If you want to connect to SMTP using TLS/SSL/SSLv2/SSLv3 use the 
connectionType
+     * option in [EMAIL PROTECTED] ezcMailSmtpTransportOptions}.
+     *
+     * For options you can specify for SMTP see [EMAIL PROTECTED] 
ezcMailSmtpTransportOptions}.
+     *
+     * @throws ezcBasePropertyNotFoundException
+     *         if $options contains a property not defined
+     * @throws ezcBaseValueException
+     *         if $options contains a property with a value not allowed
+     * @param string $host
+     * @param string $user
+     * @param string $password
+     * @param int $port
+     * @param array(string=>mixed) $options
+     */
+    public function __construct( $host, $user = '', $password = '', $port = 
null, array $options = array() )
+    {
+        $this->options = new ezcMailSmtpTransportOptions( $options );
+        $this->serverHost = $host;
+        if ( $port === null )
+        {
+            $port = ( $this->options->connectionType === 
self::CONNECTION_PLAIN ) ? 25 : 465;
+        }
+        $this->serverPort = $port;
+        $this->user = $user;
+        $this->password = $password;
+        $this->doAuthenticate = $user != '' ? true : false;
+
+        $this->status = self::STATUS_NOT_CONNECTED;
+        $this->senderHost = 'localhost';
+    }
+
+    /**
+     * Destructs this object.
+     *
+     * Closes the connection if it is still open.
+     */
+    public function __destruct()
+    {
+        if ( $this->status != self::STATUS_NOT_CONNECTED )
+        {
+            $this->sendData( 'QUIT' );
+            fclose( $this->connection );
+        }
+    }
+
+    /**
+     * Sets the property $name to $value.
+     *
+     * @throws ezcBasePropertyNotFoundException
+     *         if the property $name does not exist
+     * @throws ezcBaseValueException
+     *         if $value is not accepted for the property $name
+     * @param string $name
+     * @param mixed $value
+     * @ignore
+     */
+    public function __set( $name, $value )
+    {
+        switch ( $name )
+        {
+            case 'user':
+            case 'password':
+            case 'senderHost':
+            case 'serverHost':
+            case 'serverPort':
+                $this->properties[$name] = $value;
+                break;
+
+            case 'timeout':
+                // the timeout option from $this->options is used instead of
+                // the timeout option of this class
+                $this->options->timeout = $value;
+                break;
+
+            case 'options':
+                if ( !( $value instanceof ezcMailSmtpTransportOptions ) )
+                {
+                    throw new ezcBaseValueException( 'options', $value, 
'instanceof ezcMailSmtpTransportOptions' );
+                }
+                $this->options = $value;
+                break;
+
+            default:
+                throw new ezcBasePropertyNotFoundException( $name );
+        }
+    }
+
+    /**
+     * Returns the value of the property $name.
+     *
+     * @throws ezcBasePropertyNotFoundException
+     *         if the property $name does not exist
+     * @param string $name
+     * @return mixed
+     * @ignore
+     */
+    public function __get( $name )
+    {
+        switch ( $name )
+        {
+            case 'user':
+            case 'password':
+            case 'senderHost':
+            case 'serverHost':
+            case 'serverPort':
+                return $this->properties[$name];
+
+            case 'timeout':
+                return $this->options->timeout;
+
+            case 'options':
+                return $this->options;
+
+            default:
+                throw new ezcBasePropertyNotFoundException( $name );
+        }
+    }
+
+    /**
+     * Returns true if the property $name is set, otherwise false.
+     *
+     * @param string $name
+     * @return bool
+     * @ignore
+     */
+    public function __isset( $name )
+    {
+        switch ( $name )
+        {
+            case 'user':
+            case 'password':
+            case 'senderHost':
+            case 'serverHost':
+            case 'serverPort':
+                return isset( $this->properties[$name] );
+
+            case 'timeout':
+            case 'options':
+                return true;
+
+            default:
+                return false;
+        }
+    }
+
+    /**
+     * Sets if the connection should be kept open after sending an email.
+     *
+     * This method should be called prior to the first call to send().
+     *
+     * Keeping the connection open is useful if you are sending a lot of mail.
+     * It removes the overhead of opening the connection after each mail is
+     * sent.
+     *
+     * Use disconnect() to close the connection if you have requested to keep
+     * it open.
+     */
+    public function keepConnection()
+    {
+        $this->keepConnection = true;
+    }
+
+    /**
+     * Sends the ezcMail $mail using the SMTP protocol.
+     *
+     * If you want to send several emails use keepConnection() to leave the
+     * connection to the server open between each mail.
+     *
+     * @throws ezcMailTransportException
+     *         if the mail could not be sent
+     * @throws ezcBaseFeatureNotFoundException
+     *         if trying to use SSL and the openssl extension is not installed
+     * @param ezcMail $mail
+     */
+    public function send( ezcMail $mail )
+    {
+        // sanity check the e-mail
+        // need at least one recepient
+        if ( ( count( $mail->to ) + count( $mail->cc ) + count( $mail->bcc ) ) 
< 1 )
+        {
+            throw new ezcMailTransportException( "Can not send e-mail with no 
'to' recipients." );
+        }
+
+        try
+        {
+            // open connection unless we are connected already.
+            if ( $this->status != self::STATUS_AUTHENTICATED )
+            {
+                $this->connect();
+            }
+
+            if ( isset( $mail->returnPath ) )
+            {
+                $this->cmdMail( $mail->returnPath->email );
+            }
+            else
+            {
+                $this->cmdMail( $mail->from->email );
+            }
+
+            // each recepient must be listed here.
+            // this controls where the mail is actually sent as SMTP does not
+            // read the headers itself
+            foreach ( $mail->to as $address )
+            {
+                $this->cmdRcpt( $address->email );
+            }
+            foreach ( $mail->cc as $address )
+            {
+                $this->cmdRcpt( $address->email );
+            }
+            foreach ( $mail->bcc as $address )
+            {
+                $this->cmdRcpt( $address->email );
+            }
+            // done with the from and recipients, lets send the mail itself
+            $this->cmdData();
+
+            // A '.' on a line ends the mail. Make sure this does not happen in
+            // the data we want to send.  also called transparancy in the RFC,
+            // section 4.5.2
+            $data = $mail->generate();
+            $data = str_replace( self::CRLF . '.', self::CRLF . '..', $data );
+            if ( $data[0] == '.' )
+            {
+                $data = '.' . $data;
+            }
+
+            $this->sendData( $data );
+            $this->sendData( '.' );
+
+            if ( $this->getReplyCode( $error ) !== '250' )
+            {
+                throw new ezcMailTransportSmtpException( "Error: {$error}" );
+            }
+        }
+        catch ( ezcMailTransportSmtpException $e )
+        {
+            throw new ezcMailTransportException( $e->getMessage() );
+            // TODO: reset connection here.pin
+        }
+
+        // close connection unless we should keep it
+        if ( $this->keepConnection === false )
+        {
+            try
+            {
+                $this->disconnect();
+            }
+            catch ( Exception $e )
+            {
+                // Eat! We don't care anyway since we are aborting the 
connection
+            }
+        }
+    }
+
+    /**
+     * Creates a connection to the SMTP server and initiates the login
+     * procedure.
+     *
+     * @todo The @ should be removed when PHP doesn't throw warnings for 
connect problems
+     *
+     * @throws ezcMailTransportSmtpException
+     *         if no connection could be made
+     *         or if the login failed
+     * @throws ezcBaseExtensionNotFoundException
+     *         if trying to use SSL and the openssl extension is not installed
+     */
+    protected function connect()
+    {
+        $errno = null;
+        $errstr = null;
+        if ( $this->options->connectionType !== self::CONNECTION_PLAIN &&
+             !ezcBaseFeatures::hasExtensionSupport( 'openssl' ) )
+        {
+            throw new ezcBaseExtensionNotFoundException( 'openssl', null, "PHP 
not configured --with-openssl." );
+        }
+        if ( count( $this->options->connectionOptions ) > 0 )
+        {
+            $context = stream_context_create( 
$this->options->connectionOptions );
+            $this->connection = @stream_socket_client( 
"{$this->options->connectionType}://{$this->serverHost}:{$this->serverPort}",
+                                                       $errno, $errstr, 
$this->options->timeout, STREAM_CLIENT_CONNECT, $context );
+        }
+        else
+        {
+            $this->connection = @stream_socket_client( 
"{$this->options->connectionType}://{$this->serverHost}:{$this->serverPort}",
+                                                       $errno, $errstr, 
$this->options->timeout );
+        }
+
+        if ( is_resource( $this->connection ) )
+        {
+            stream_set_timeout( $this->connection, $this->options->timeout );
+            $this->status = self::STATUS_CONNECTED;
+            $greeting = $this->getData();
+            $this->login();
+        }
+        else
+        {
+            throw new ezcMailTransportSmtpException( "Failed to connect to the 
smtp server: {$this->serverHost}:{$this->serverPort}." );
+        }
+    }
+
+    /**
+     * Performs the initial handshake with the SMTP server and
+     * authenticates the user, if login data is provided to the
+     * constructor.
+     *
+     * @throws ezcMailTransportSmtpException
+     *         if the HELO/EHLO command or authentication fails
+     */
+    protected function login()
+    {
+        if ( $this->doAuthenticate )
+        {
+            $this->sendData( 'EHLO ' . $this->senderHost );
+        }
+        else
+        {
+            $this->sendData( 'HELO ' . $this->senderHost );
+        }
+        if ( $this->getReplyCode( $error ) !== '250' )
+        {
+                throw new ezcMailTransportSmtpException( "HELO/EHLO failed 
with error: $error." );
+        }
+
+        // do authentication
+        if ( $this->doAuthenticate )
+        {
+            $this->sendData( 'AUTH LOGIN' );
+            if ( $this->getReplyCode( $error ) !== '334' )
+            {
+                throw new ezcMailTransportSmtpException( 'SMTP server does not 
accept AUTH LOGIN.' );
+            }
+
+            $this->sendData( base64_encode( $this->user ) );
+            if ( $this->getReplyCode( $error ) !== '334' )
+            {
+                throw new ezcMailTransportSmtpException( "SMTP server does not 
accept login: {$this->user}." );
+            }
+
+            $this->sendData( base64_encode( $this->password ) );
+            if ( $this->getReplyCode( $error ) !== '235' )
+            {
+                throw new ezcMailTransportSmtpException( 'SMTP server does not 
accept the password.' );
+            }
+        }
+        $this->status = self::STATUS_AUTHENTICATED;
+    }
+
+    /**
+     * Sends the QUIT command to the server and breaks the connection.
+     *
+     * @throws ezcMailTransportSmtpException
+     *         if the QUIT command failed
+     */
+    public function disconnect()
+    {
+        if ( $this->status != self::STATUS_NOT_CONNECTED )
+        {
+            $this->sendData( 'QUIT' );
+            $replyCode = $this->getReplyCode( $error ) !== '221';
+            fclose( $this->connection );
+            $this->status = self::STATUS_NOT_CONNECTED;
+            if ( $replyCode )
+            {
+                throw new ezcMailTransportSmtpException( "QUIT failed with 
error: $error." );
+            }
+        }
+    }
+
+    /**
+     * Returns the $email enclosed within '< >'.
+     *
+     * If $email is already enclosed within '< >' it is returned unmodified.
+     *
+     * @param string $email
+     * $return string
+     */
+    protected function composeSmtpMailAddress( $email )
+    {
+        if ( !preg_match( "/<.+>/", $email ) )
+        {
+            $email = "<{$email}>";
+        }
+        return $email;
+    }
+
+    /**
+     * Sends the MAIL FROM command, with the sender's mail address $from.
+     *
+     * This method must be called once to tell the server the sender address.
+     *
+     * The sender's mail address $from may be enclosed in angle brackets.
+     *
+     * @throws ezcMailTransportSmtpException
+     *         if there is no valid connection
+     *         or if the MAIL FROM command failed
+     * @param string $from
+     */
+    protected function cmdMail( $from )
+    {
+        if ( $this->status === self::STATUS_AUTHENTICATED )
+        {
+            $this->sendData( 'MAIL FROM:' . $this->composeSmtpMailAddress( 
$from ) . '' );
+            if ( $this->getReplyCode( $error ) !== '250' )
+            {
+                throw new ezcMailTransportSmtpException( "MAIL FROM failed 
with error: $error." );
+            }
+        }
+    }
+
+    /**
+     * Sends the 'RCTP TO' to the server with the address $email.
+     *
+     * This method must be called once for each recipient of the mail
+     * including cc and bcc recipients. The RCPT TO commands control
+     * where the mail is actually sent. It does not affect the headers
+     * of the email.
+     *
+     * The recipient mail address $email may be enclosed in angle brackets.
+     *
+     * @throws ezcMailTransportSmtpException
+     *         if there is no valid connection
+     *         or if the RCPT TO command failed
+     * @param string $email
+     */
+    protected function cmdRcpt( $email )
+    {
+        if ( $this->status === self::STATUS_AUTHENTICATED )
+        {
+            $this->sendData( 'RCPT TO:' . $this->composeSmtpMailAddress( 
$email ) );
+            if ( $this->getReplyCode( $error ) !== '250' )
+            {
+                throw new ezcMailTransportSmtpException( "RCPT TO failed with 
error: $error." );
+            }
+        }
+    }
+
+    /**
+     * Sends the DATA command to the SMTP server.
+     *
+     * @throws ezcMailTransportSmtpException
+     *         if there is no valid connection
+     *         or if the DATA command failed
+     */
+    protected function cmdData()
+    {
+        if ( $this->status === self::STATUS_AUTHENTICATED )
+        {
+            $this->sendData( 'DATA' );
+            if ( $this->getReplyCode( $error ) !== '354' )
+            {
+                throw new ezcMailTransportSmtpException( "DATA failed with 
error: $error." );
+            }
+        }
+    }
+
+    /**
+     * Sends $data to the SMTP server through the connection.
+     *
+     * This method appends one line-break at the end of $data.
+     *
+     * @throws ezcMailTransportSmtpException
+     *         if there is no valid connection
+     * @param string $data
+     */
+    protected function sendData( $data )
+    {
+        if ( is_resource( $this->connection ) )
+        {
+            if ( fwrite( $this->connection, $data . self::CRLF,
+                        strlen( $data ) + strlen( self::CRLF  ) ) === false )
+            {
+                throw new ezcMailTransportSmtpException( 'Could not write to 
SMTP stream. It was probably terminated by the host.' );
+            }
+        }
+    }
+
+    /**
+     * Returns data received from the connection stream.
+     *
+     * @throws ezcMailTransportSmtpException
+     *         if there is no valid connection
+     * @return string
+     */
+    protected function getData()
+    {
+        $data = '';
+        $line   = '';
+        $loops  = 0;
+
+        if ( is_resource( $this->connection ) )
+        {
+            while ( ( strpos( $data, self::CRLF ) === false || (string) 
substr( $line, 3, 1 ) !== ' ' ) && $loops < 100 )
+            {
+                $line = fgets( $this->connection, 512 );
+                $data .= $line;
+                $loops++;
+            }
+            return $data;
+        }
+        throw new ezcMailTransportSmtpException( 'Could not read from SMTP 
stream. It was probably terminated by the host.' );
+    }
+
+    /**
+     * Returns the reply code of the last message from the server.
+     *
+     * $line contains the complete data retrieved from the stream. This can be 
used to retrieve
+     * the error message in case of an error.
+     *
+     * @throws ezcMailTransportSmtpException
+     *         if it could not fetch data from the stream
+     * @param string &$line
+     * @return string
+     */
+    protected function getReplyCode( &$line )
+    {
+        return substr( trim( $line = $this->getData() ), 0, 3 );
+    }
 }
 ?>

Modified: trunk/Mail/src/transports/smtp/transport_smtp.php
==============================================================================
--- trunk/Mail/src/transports/smtp/transport_smtp.php [iso-8859-1] (original)
+++ trunk/Mail/src/transports/smtp/transport_smtp.php [iso-8859-1] Fri Jul  6 
10:27:24 2007
@@ -1,6 +1,6 @@
 <?php
 /**
- * File containing the ezcMailSmtpTransport class
+ * File containing the ezcMailTransportSmtp class
  *
  * @package Mail
  * @version //autogen//
@@ -9,672 +9,13 @@
  */
 
 /**
- * This class implements the Simple Mail Transfer Protocol (SMTP)
- * with authentication support.
- *
- * See for further information the RFCs:
- * - [EMAIL PROTECTED] http://www.faqs.org/rfcs/rfc821.html}
- * - [EMAIL PROTECTED] http://www.faqs.org/rfcs/rfc2554.html}
- *
- * @property string $serverHost
- *           The SMTP server host to connect to.
- * @property int $serverPort
- *           The port of the SMTP server. Defaults to 25.
- * @property string $username
- *           The username used for authentication. The default is blank which
- *           means no authentication.
- * @property string $password
- *           The password used for authentication.
- * @property int $timeout
- *           The timeout value of the connection in seconds. The default is
- *           5 seconds. When setting/getting this option, the timeout option
- *           from $this->options will be set instead [EMAIL PROTECTED] 
ezcMailTransportOptions}.
- * @property string $senderHost
- *           The hostname of the computer that sends the mail. The default is
- *           'localhost'.
- * @property ezcMailSmtpTransportOptions $options
- *           Holds the options you can set to the SMTP transport.
+ * This class is deprecated. Use ezcMailSmtpTransport instead.
  *
  * @package Mail
  * @version //autogen//
- * @mainclass
+ * @ignore
  */
-class ezcMailSmtpTransport implements ezcMailTransport
+class ezcMailTransportSmtp extends ezcMailSmtpTransport
 {
-    /**
-     * Plain connection.
-     */
-    const CONNECTION_PLAIN = 'tcp';
-
-    /**
-     * SSL connection.
-     */
-    const CONNECTION_SSL = 'ssl';
-
-    /**
-     * SSLv2 connection.
-     */
-    const CONNECTION_SSLV2 = 'sslv2';
-
-    /**
-     * SSLv3 connection.
-     */
-    const CONNECTION_SSLV3 = 'sslv3';
-
-    /**
-     * TLS connection.
-     */
-    const CONNECTION_TLS = 'tls';
-
-    /**
-     * The line-break characters to use.
-     *
-     * @access private
-     */
-    const CRLF = "\r\n";
-
-    /**
-     * We are not connected to a server.
-     *
-     * @access private
-     */
-    const STATUS_NOT_CONNECTED = 1;
-
-    /**
-     * We are connected to the server, but not authenticated.
-     *
-     * @access private
-     */
-    const STATUS_CONNECTED = 2;
-
-    /**
-     * We are connected to the server and authenticated.
-     *
-     * @access private
-     */
-    const STATUS_AUTHENTICATED = 3;
-
-    /**
-     * The connection to the SMTP server.
-     *
-     * @var resource
-     */
-    protected $connection;
-
-    /**
-     * Holds the connection status.
-     *
-     * $var int [EMAIL PROTECTED] STATUS_NOT_CONNECTED},
-     *          [EMAIL PROTECTED] STATUS_CONNECTED} or
-     *          [EMAIL PROTECTED] STATUS_AUTHENTICATED}.
-     */
-    protected $status;
-
-    /**
-     * True if authentication should be performed; otherwise false.
-     *
-     * This variable is set to true if a username is provided for login.
-     *
-     * @var bool
-     */
-    protected $doAuthenticate;
-
-    /**
-     * Holds if the connection should be kept open after sending a mail.
-     *
-     * @var bool
-     */
-    protected $keepConnection = false;
-
-    /**
-     * Holds the properties of this class.
-     *
-     * @var array(string=>mixed)
-     */
-    protected $properties = array();
-
-    /**
-     * Holds the options of this class.
-     *
-     * @var ezcMailSmtpTransportOptions
-     */
-    protected $options;
-
-    /**
-     * Constructs a new ezcMailSmtpTransport.
-     *
-     * The constructor expects, at least, the hostname $host of the SMTP 
server.
-     *
-     * The username $user will be used for authentication if provided.
-     * If it is left blank no authentication will be performed.
-     *
-     * The password $password will be used for authentication
-     * if provided. Use this parameter always in combination with the $user
-     * parameter.
-     *
-     * The value $port specifies on which port to connect to $host. By default
-     * it is 25 for plain connections and 465 for TLS/SSL/SSLv2/SSLv3.
-     *
-     * Note: The ssl option from ezcMailTransportOptions doesn't apply to SMTP.
-     * If you want to connect to SMTP using TLS/SSL/SSLv2/SSLv3 use the 
connectionType
-     * option in ezcMailSmtpTransportOptions.
-     *
-     * For options you can specify for SMTP see: [EMAIL PROTECTED] 
ezcMailSmtpTransportOptions}
-     *
-     * @throws ezcBasePropertyNotFoundException
-     *         if $options contains a property not defined
-     * @throws ezcBaseValueException
-     *         if $options contains a property with a value not allowed
-     * @param string $host
-     * @param string $user
-     * @param string $password
-     * @param int $port
-     * @param array(string=>mixed) $options
-     */
-    public function __construct( $host, $user = '', $password = '', $port = 
null, array $options = array() )
-    {
-        $this->options = new ezcMailSmtpTransportOptions( $options );
-        $this->serverHost = $host;
-        if ( $port === null )
-        {
-            $port = ( $this->options->connectionType === 
self::CONNECTION_PLAIN ) ? 25 : 465;
-        }
-        $this->serverPort = $port;
-        $this->user = $user;
-        $this->password = $password;
-        $this->doAuthenticate = $user != '' ? true : false;
-
-        $this->status = self::STATUS_NOT_CONNECTED;
-        $this->senderHost = 'localhost';
-    }
-
-    /**
-     * Destructs this object.
-     *
-     * Closes the connection if it is still open.
-     */
-    public function __destruct()
-    {
-        if ( $this->status != self::STATUS_NOT_CONNECTED )
-        {
-            $this->sendData( 'QUIT' );
-            fclose( $this->connection );
-        }
-    }
-
-    /**
-     * Sets the property $name to $value.
-     *
-     * @throws ezcBasePropertyNotFoundException
-     *         if the property $name does not exist
-     * @throws ezcBaseValueException
-     *         if $value is not accepted for the property $name
-     * @param string $name
-     * @param mixed $value
-     * @ignore
-     */
-    public function __set( $name, $value )
-    {
-        switch ( $name )
-        {
-            case 'user':
-            case 'password':
-            case 'senderHost':
-            case 'serverHost':
-            case 'serverPort':
-                $this->properties[$name] = $value;
-                break;
-
-            case 'timeout':
-                // the timeout option from $this->options is used instead of
-                // the timeout option of this class
-                $this->options->timeout = $value;
-                break;
-
-            case 'options':
-                if ( !( $value instanceof ezcMailSmtpTransportOptions ) )
-                {
-                    throw new ezcBaseValueException( 'options', $value, 
'instanceof ezcMailSmtpTransportOptions' );
-                }
-                $this->options = $value;
-                break;
-
-            default:
-                throw new ezcBasePropertyNotFoundException( $name );
-        }
-    }
-
-    /**
-     * Returns the value of the property $name.
-     *
-     * @throws ezcBasePropertyNotFoundException
-     *         if the property $name does not exist
-     * @param string $name
-     * @return mixed
-     * @ignore
-     */
-    public function __get( $name )
-    {
-        switch ( $name )
-        {
-            case 'user':
-            case 'password':
-            case 'senderHost':
-            case 'serverHost':
-            case 'serverPort':
-                return $this->properties[$name];
-
-            case 'timeout':
-                return $this->options->timeout;
-
-            case 'options':
-                return $this->options;
-
-            default:
-                throw new ezcBasePropertyNotFoundException( $name );
-        }
-    }
-
-    /**
-     * Returns true if the property $name is set, otherwise false.
-     *
-     * @param string $name
-     * @return bool
-     * @ignore
-     */
-    public function __isset( $name )
-    {
-        switch ( $name )
-        {
-            case 'user':
-            case 'password':
-            case 'senderHost':
-            case 'serverHost':
-            case 'serverPort':
-                return isset( $this->properties[$name] );
-
-            case 'timeout':
-            case 'options':
-                return true;
-
-            default:
-                return false;
-        }
-    }
-
-    /**
-     * Sets if the connection should be kept open after sending an email.
-     *
-     * This method should be called prior to the first call to send().
-     *
-     * Keeping the connection open is useful if you are sending a lot of mail.
-     * It removes the overhead of opening the connection after each mail is
-     * sent.
-     *
-     * Use disconnect() to close the connection if you have requested to keep
-     * it open.
-     */
-    public function keepConnection()
-    {
-        $this->keepConnection = true;
-    }
-
-    /**
-     * Sends the ezcMail $mail using the SMTP protocol.
-     *
-     * If you want to send several emails use keepConnection() to leave the
-     * connection to the server open between each mail.
-     *
-     * @throws ezcMailTransportException
-     *         if the mail could not be sent
-     * @throws ezcBaseFeatureNotFoundException
-     *         if trying to use SSL and the openssl extension is not installed
-     * @param ezcMail $mail
-     */
-    public function send( ezcMail $mail )
-    {
-        // sanity check the e-mail
-        // need at least one recepient
-        if ( ( count( $mail->to ) + count( $mail->cc ) + count( $mail->bcc ) ) 
< 1 )
-        {
-            throw new ezcMailTransportException( "Can not send e-mail with no 
'to' recipients." );
-        }
-
-        try
-        {
-            // open connection unless we are connected already.
-            if ( $this->status != self::STATUS_AUTHENTICATED )
-            {
-                $this->connect();
-            }
-
-            if ( isset( $mail->returnPath ) )
-            {
-                $this->cmdMail( $mail->returnPath->email );
-            }
-            else
-            {
-                $this->cmdMail( $mail->from->email );
-            }
-
-            // each recepient must be listed here.
-            // this controls where the mail is actually sent as SMTP does not
-            // read the headers itself
-            foreach ( $mail->to as $address )
-            {
-                $this->cmdRcpt( $address->email );
-            }
-            foreach ( $mail->cc as $address )
-            {
-                $this->cmdRcpt( $address->email );
-            }
-            foreach ( $mail->bcc as $address )
-            {
-                $this->cmdRcpt( $address->email );
-            }
-            // done with the from and recipients, lets send the mail itself
-            $this->cmdData();
-
-            // A '.' on a line ends the mail. Make sure this does not happen in
-            // the data we want to send.  also called transparancy in the RFC,
-            // section 4.5.2
-            $data = $mail->generate();
-            $data = str_replace( self::CRLF . '.', self::CRLF . '..', $data );
-            if ( $data[0] == '.' )
-            {
-                $data = '.' . $data;
-            }
-
-            $this->sendData( $data );
-            $this->sendData( '.' );
-
-            if ( $this->getReplyCode( $error ) !== '250' )
-            {
-                throw new ezcMailTransportSmtpException( "Error: {$error}" );
-            }
-        }
-        catch ( ezcMailTransportSmtpException $e )
-        {
-            throw new ezcMailTransportException( $e->getMessage() );
-            // TODO: reset connection here.pin
-        }
-
-        // close connection unless we should keep it
-        if ( $this->keepConnection === false )
-        {
-            try
-            {
-                $this->disconnect();
-            }
-            catch ( Exception $e )
-            {
-                // Eat! We don't care anyway since we are aborting the 
connection
-            }
-        }
-    }
-
-    /**
-     * Creates a connection to the SMTP server and initiates the login
-     * procedure.
-     *
-     * @todo The @ should be removed when PHP doesn't throw warnings for 
connect problems
-     *
-     * @throws ezcMailTransportSmtpException
-     *         if no connection could be made
-     *         or if the login failed
-     * @throws ezcBaseExtensionNotFoundException
-     *         if trying to use SSL and the openssl extension is not installed
-     */
-    protected function connect()
-    {
-        $errno = null;
-        $errstr = null;
-        if ( $this->options->connectionType !== self::CONNECTION_PLAIN &&
-             !ezcBaseFeatures::hasExtensionSupport( 'openssl' ) )
-        {
-            throw new ezcBaseExtensionNotFoundException( 'openssl', null, "PHP 
not configured --with-openssl." );
-        }
-        if ( count( $this->options->connectionOptions ) > 0 )
-        {
-            $context = stream_context_create( 
$this->options->connectionOptions );
-            $this->connection = @stream_socket_client( 
"{$this->options->connectionType}://{$this->serverHost}:{$this->serverPort}",
-                                                       $errno, $errstr, 
$this->options->timeout, STREAM_CLIENT_CONNECT, $context );
-        }
-        else
-        {
-            $this->connection = @stream_socket_client( 
"{$this->options->connectionType}://{$this->serverHost}:{$this->serverPort}",
-                                                       $errno, $errstr, 
$this->options->timeout );
-        }
-
-        if ( is_resource( $this->connection ) )
-        {
-            stream_set_timeout( $this->connection, $this->options->timeout );
-            $this->status = self::STATUS_CONNECTED;
-            $greeting = $this->getData();
-            $this->login();
-        }
-        else
-        {
-            throw new ezcMailTransportSmtpException( "Failed to connect to the 
smtp server: {$this->serverHost}:{$this->serverPort}." );
-        }
-    }
-
-    /**
-     * Performs the initial handshake with the SMTP server and
-     * authenticates the user, if login data is provided to the
-     * constructor.
-     *
-     * @throws ezcMailTransportSmtpException
-     *         if the HELO/EHLO command or authentication fails
-     */
-    protected function login()
-    {
-        if ( $this->doAuthenticate )
-        {
-            $this->sendData( 'EHLO ' . $this->senderHost );
-        }
-        else
-        {
-            $this->sendData( 'HELO ' . $this->senderHost );
-        }
-        if ( $this->getReplyCode( $error ) !== '250' )
-        {
-                throw new ezcMailTransportSmtpException( "HELO/EHLO failed 
with error: $error." );
-        }
-
-        // do authentication
-        if ( $this->doAuthenticate )
-        {
-            $this->sendData( 'AUTH LOGIN' );
-            if ( $this->getReplyCode( $error ) !== '334' )
-            {
-                throw new ezcMailTransportSmtpException( 'SMTP server does not 
accept AUTH LOGIN.' );
-            }
-
-            $this->sendData( base64_encode( $this->user ) );
-            if ( $this->getReplyCode( $error ) !== '334' )
-            {
-                throw new ezcMailTransportSmtpException( "SMTP server does not 
accept login: {$this->user}." );
-            }
-
-            $this->sendData( base64_encode( $this->password ) );
-            if ( $this->getReplyCode( $error ) !== '235' )
-            {
-                throw new ezcMailTransportSmtpException( 'SMTP server does not 
accept the password.' );
-            }
-        }
-        $this->status = self::STATUS_AUTHENTICATED;
-    }
-
-    /**
-     * Sends the QUIT command to the server and breaks the connection.
-     *
-     * @throws ezcMailTransportSmtpException
-     *         if the QUIT command failed
-     */
-    public function disconnect()
-    {
-        if ( $this->status != self::STATUS_NOT_CONNECTED )
-        {
-            $this->sendData( 'QUIT' );
-            $replyCode = $this->getReplyCode( $error ) !== '221';
-            fclose( $this->connection );
-            $this->status = self::STATUS_NOT_CONNECTED;
-            if ( $replyCode )
-            {
-                throw new ezcMailTransportSmtpException( "QUIT failed with 
error: $error." );
-            }
-        }
-    }
-
-    /**
-     * Returns the $email enclosed within '< >'.
-     *
-     * If $email is already enclosed within '< >' it is returned unmodified.
-     *
-     * @param string $email
-     * $return string
-     */
-    protected function composeSmtpMailAddress( $email )
-    {
-        if ( !preg_match( "/<.+>/", $email ) )
-        {
-            $email = "<{$email}>";
-        }
-        return $email;
-    }
-
-    /**
-     * Sends the MAIL FROM command, with the sender's mail address $from.
-     *
-     * This method must be called once to tell the server the sender address.
-     *
-     * The sender's mail address $from may be enclosed in angle brackets.
-     *
-     * @throws ezcMailTransportSmtpException
-     *         if there is no valid connection
-     *         or if the MAIL FROM command failed
-     * @param string $from
-     */
-    protected function cmdMail( $from )
-    {
-        if ( $this->status === self::STATUS_AUTHENTICATED )
-        {
-            $this->sendData( 'MAIL FROM:' . $this->composeSmtpMailAddress( 
$from ) . '' );
-            if ( $this->getReplyCode( $error ) !== '250' )
-            {
-                throw new ezcMailTransportSmtpException( "MAIL FROM failed 
with error: $error." );
-            }
-        }
-    }
-
-    /**
-     * Sends the 'RCTP TO' to the server with the address $email.
-     *
-     * This method must be called once for each recipient of the mail
-     * including cc and bcc recipients. The RCPT TO commands control
-     * where the mail is actually sent. It does not affect the headers
-     * of the email.
-     *
-     * The recipient mail address $email may be enclosed in angle brackets.
-     *
-     * @throws ezcMailTransportSmtpException
-     *         if there is no valid connection
-     *         or if the RCPT TO command failed
-     * @param string $email
-     */
-    protected function cmdRcpt( $email )
-    {
-        if ( $this->status === self::STATUS_AUTHENTICATED )
-        {
-            $this->sendData( 'RCPT TO:' . $this->composeSmtpMailAddress( 
$email ) );
-            if ( $this->getReplyCode( $error ) !== '250' )
-            {
-                throw new ezcMailTransportSmtpException( "RCPT TO failed with 
error: $error." );
-            }
-        }
-    }
-
-    /**
-     * Sends the DATA command to the SMTP server.
-     *
-     * @throws ezcMailTransportSmtpException
-     *         if there is no valid connection
-     *         or if the DATA command failed
-     */
-    protected function cmdData()
-    {
-        if ( $this->status === self::STATUS_AUTHENTICATED )
-        {
-            $this->sendData( 'DATA' );
-            if ( $this->getReplyCode( $error ) !== '354' )
-            {
-                throw new ezcMailTransportSmtpException( "DATA failed with 
error: $error." );
-            }
-        }
-    }
-
-    /**
-     * Sends $data to the SMTP server through the connection.
-     *
-     * This method appends one line-break at the end of $data.
-     *
-     * @throws ezcMailTransportSmtpException
-     *         if there is no valid connection
-     * @param string $data
-     */
-    protected function sendData( $data )
-    {
-        if ( is_resource( $this->connection ) )
-        {
-            if ( fwrite( $this->connection, $data . self::CRLF,
-                        strlen( $data ) + strlen( self::CRLF  ) ) === false )
-            {
-                throw new ezcMailTransportSmtpException( 'Could not write to 
SMTP stream. It was probably terminated by the host.' );
-            }
-        }
-    }
-
-    /**
-     * Returns data received from the connection stream.
-     *
-     * @throws ezcMailTransportSmtpException
-     *         if there is no valid connection
-     * @return string
-     */
-    protected function getData()
-    {
-        $data = '';
-        $line   = '';
-        $loops  = 0;
-
-        if ( is_resource( $this->connection ) )
-        {
-            while ( ( strpos( $data, self::CRLF ) === false || (string) 
substr( $line, 3, 1 ) !== ' ' ) && $loops < 100 )
-            {
-                $line = fgets( $this->connection, 512 );
-                $data .= $line;
-                $loops++;
-            }
-            return $data;
-        }
-        throw new ezcMailTransportSmtpException( 'Could not read from SMTP 
stream. It was probably terminated by the host.' );
-    }
-
-    /**
-     * Returns the reply code of the last message from the server.
-     *
-     * $line contains the complete data retrieved from the stream. This can be 
used to retrieve
-     * the error message in case of an error.
-     *
-     * @throws ezcMailTransportSmtpException
-     *         if it could not fetch data from the stream
-     * @param string &$line
-     * @return string
-     */
-    protected function getReplyCode( &$line )
-    {
-        return substr( trim( $line = $this->getData() ), 0, 3 );
-    }
 }
 ?>


-- 
svn-components mailing list
[email protected]
http://lists.ez.no/mailman/listinfo/svn-components

Reply via email to