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