Author: Alexandru Stanoi Date: 2007-01-31 11:05:02 +0100 (Wed, 31 Jan 2007) New Revision: 4599
Log: - Implemented feature request #10091: added SSL/TLS support for the SMTP transport. Based on a patch from Christian Michel. Added: trunk/Mail/docs/tutorial_example_16.php Modified: trunk/Mail/ChangeLog trunk/Mail/docs/tutorial.txt trunk/Mail/src/options/smtp_options.php trunk/Mail/src/transports/smtp/transport_smtp.php trunk/Mail/tests/options/smtp_options_test.php trunk/Mail/tests/transports/transport_smtp_test.php Modified: trunk/Mail/ChangeLog =================================================================== --- trunk/Mail/ChangeLog 2007-01-30 10:19:42 UTC (rev 4598) +++ trunk/Mail/ChangeLog 2007-01-31 10:05:02 UTC (rev 4599) @@ -24,6 +24,8 @@ and deprecated second parameter of parseMail() in ezcMailParser. - Implemented feature request #9292: added SSL support for IMAP and POP3. Based on a patch from Mikko Koppanen. +- Implemented feature request #10091: added SSL/TLS support for the SMTP + transport. Based on a patch from Christian Michel. 1.2.1 - [RELEASEDATE] Modified: trunk/Mail/docs/tutorial.txt =================================================================== --- trunk/Mail/docs/tutorial.txt 2007-01-30 10:19:42 UTC (rev 4598) +++ trunk/Mail/docs/tutorial.txt 2007-01-31 10:05:02 UTC (rev 4599) @@ -66,7 +66,8 @@ For sending mail we support the following protocols: -- SMTP (ezcMailSmtpTransport) - uses an SMTP server to send mail +- SMTP (ezcMailSmtpTransport) - uses an SMTP server to send mail. Supports + plain and TLS/SSL/SSLv2/SSLv3 connections. - MTA (ezcMailMtaTransport) - wraps around the PHP mail() function For mail retrieval we currently support the following protocols: @@ -161,6 +162,15 @@ .. include:: tutorial_example_04.php :literal: +Send a mail using SMTP +---------------------- + +This example displays how to send a mail with SMTP, by using an SSLv3 +connection. + +.. include:: tutorial_example_16.php + :literal: + Character encoding ------------------ Added: trunk/Mail/docs/tutorial_example_16.php =================================================================== --- trunk/Mail/docs/tutorial_example_16.php 2007-01-30 10:19:42 UTC (rev 4598) +++ trunk/Mail/docs/tutorial_example_16.php 2007-01-31 10:05:02 UTC (rev 4599) @@ -0,0 +1,33 @@ +<?php +require_once 'tutorial_autoload.php'; + +// Create a new mail composer object +$mail = new ezcMailComposer(); + +// Specify the "from" mail address +$mail->from = new ezcMailAddress( '[EMAIL PROTECTED]', 'Adrian Ripburger' ); + +// Add one "to" mail address (multiple can be added) +$mail->addTo( new ezcMailAddress( '[EMAIL PROTECTED]', 'Maureen Corley' ) ); + +// Specify the subject of the mail +$mail->subject = "This is the subject of the example mail"; + +// Specify the body text of the mail +$mail->plainText = "This is the body of the example mail."; + +// Generate the mail +$mail->build(); + +// Create a new SMTP transport object with an SSLv3 connection. +// The port will be 465 by default, use the 4th argument to change it. +// Username and password (2nd and 3rd arguments) are left blank, which means +// the mail host does not need authentication. +// Omit the 5th parameter if you want to use a plain connection +// (or set connectionType to ezcMailSmtpTransport::CONNECTION_PLAIN). +$transport = new ezcMailSmtpTransport( 'mailhost.example.com', '', '', null, array( 'connectionType' => ezcMailSmtpTransport::CONNECTION_SSLV3 ) ); + +// Use the SMTP transport to send the created mail object +$transport->send( $mail ); + +?> Property changes on: trunk/Mail/docs/tutorial_example_16.php ___________________________________________________________________ Name: svn:eol-style + native Modified: trunk/Mail/src/options/smtp_options.php =================================================================== --- trunk/Mail/src/options/smtp_options.php 2007-01-30 10:19:42 UTC (rev 4598) +++ trunk/Mail/src/options/smtp_options.php 2007-01-31 10:05:02 UTC (rev 4599) @@ -13,6 +13,19 @@ * * The options from ezcMailTransportOptions are inherited. * + * @property string $connectionType + * Specifies the protocol used to connect to the SMTP server. See the + * CONNECTION_* constants in the ezcMailSmtpTransport class. + * @property array(mixed) $connectionOptions + * Specifies additional options for the connection. Must be in this format: + * array( 'wrapper_name' => array( 'option_name' => 'value' ) ). + * @property bool ssl + * This option belongs to ezcMailTransportOptions, but it is not used in SMTP. + * When trying to set this to true the connectionType option will be set to + * CONNECTION_SSL value from ezcMailSmtpTransport. + * When trying to set this to false the connectionType option will be set to + * CONNECTION_PLAIN value from ezcMailSmtpTransport. + * * @package Mail * @version //autogen// */ @@ -21,20 +34,27 @@ /** * Constructs an object with the specified values. * + * @throws ezcBasePropertyNotFoundException + * if $options contains a property not defined + * @throws ezcBaseValueException + * if $options contains a property with a value not allowed * @param array(string=>mixed) $options */ public function __construct( array $options = array() ) { + $this->connectionType = ezcMailSmtpTransport::CONNECTION_PLAIN; // default is plain connection + $this->connectionOptions = array(); // default is no extra connection options + parent::__construct( $options ); } /** * Sets the option $name to $value. * + * @throws ezcBasePropertyNotFoundException + * if the property $name is not defined * @throws ezcBaseValueException * if $value is not correct for the property $name - * @throws ezcBasePropertyNotFoundException - * if the propery $name is not defined * @param string $name * @param mixed $value * @ignore @@ -43,6 +63,26 @@ { switch ( $name ) { + case 'connectionType': + $this->properties[$name] = $value; + break; + + case 'connectionOptions': + if ( !is_array( $value ) ) + { + throw new ezcBaseValueException( $name, $value, 'array' ); + } + $this->properties[$name] = $value; + break; + + case 'ssl': + if ( !is_bool( $value ) ) + { + throw new ezcBaseValueException( $name, $value, 'bool' ); + } + $this->properties['connectionType'] = ( $value === true ) ? ezcMailSmtpTransport::CONNECTION_SSL : ezcMailSmtpTransport::CONNECTION_PLAIN; + break; + default: parent::__set( $name, $value ); } Modified: trunk/Mail/src/transports/smtp/transport_smtp.php =================================================================== --- trunk/Mail/src/transports/smtp/transport_smtp.php 2007-01-30 10:19:42 UTC (rev 4598) +++ trunk/Mail/src/transports/smtp/transport_smtp.php 2007-01-31 10:05:02 UTC (rev 4599) @@ -27,7 +27,8 @@ * The password used for authentication. * @property int $timeout * The timeout value of the connection in seconds. The default is - * 5 seconds [EMAIL PROTECTED] ezcMailTransportOptions}. + * 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'. @@ -41,7 +42,34 @@ 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"; @@ -115,8 +143,7 @@ /** * Constructs a new ezcMailSmtpTransport. * - * The constructor expects, at least, the hostname $host of the SMTP - * server. + * 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. @@ -125,29 +152,40 @@ * if provided. Use this parameter always in combination with the $user * parameter. * - * The portnumber $port, default the SMTP standard port, to which will - * be connected. + * 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. + * * @see ezcMailSmtpTransportOptions for options you can specify for SMTP. * + * @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 = 25, array $options = array() ) + 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->serverPort = $port; $this->doAuthenticate = $user != '' ? true : false; $this->status = self::STATUS_NOT_CONNECTED; $this->senderHost = 'localhost'; - $this->options = new ezcMailSmtpTransportOptions( $options ); - $this->timeout = $this->options->timeout; } /** @@ -184,10 +222,15 @@ case 'senderHost': case 'serverHost': case 'serverPort': - case 'timeout': $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 ) ) { @@ -219,9 +262,11 @@ case 'senderHost': case 'serverHost': case 'serverPort': - case 'timeout': return $this->properties[$name]; + case 'timeout': + return $this->options->timeout; + case 'options': return $this->options; @@ -246,9 +291,9 @@ case 'senderHost': case 'serverHost': case 'serverPort': - case 'timeout': return isset( $this->properties[$name] ); + case 'timeout': case 'options': return true; @@ -281,7 +326,9 @@ * connection to the server open between each mail. * * @throws ezcMailTransportException - * if the mail could not be sent. + * 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 ) @@ -370,19 +417,38 @@ * 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. + * or if the login failed + * @throws ezcBaseFeatureNotFoundException + * if trying to use SSL and the openssl extension is not installed */ private function connect() { - // FIXME: The @ should be removed when PHP doesn't throw warnings for connect problems - $this->connection = @stream_socket_client( "tcp://{$this->serverHost}:{$this->serverPort}", - $errno, $errstr, $this->timeout ); + $errno = null; + $errstr = null; + if ( $this->options->connectionType !== self::CONNECTION_PLAIN && + !ezcBaseFeatures::hasExtensionSupport( 'openssl' ) ) + { + throw new ezcBaseFeatureNotFoundException( "Failed to connect to the server: {$this->serverHost}:{$this->serverPort}. 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->timeout ); + stream_set_timeout( $this->connection, $this->options->timeout ); $this->status = self::STATUS_CONNECTED; $greeting = $this->getData(); $this->login(); @@ -399,7 +465,7 @@ * constructor. * * @throws ezcMailTransportSmtpException - * if the HELO/EHLO command or authentication fails. + * if the HELO/EHLO command or authentication fails */ private function login() { @@ -444,7 +510,7 @@ * Sends the QUIT command to the server and breaks the connection. * * @throws ezcMailTransportSmtpException - * if the QUIT command failed. + * if the QUIT command failed */ public function disconnect() { @@ -487,7 +553,7 @@ * * @throws ezcMailTransportSmtpException * if there is no valid connection - * or if the MAIL FROM command failed. + * or if the MAIL FROM command failed * @param string $from */ private function cmdMail( $from ) @@ -514,8 +580,8 @@ * * @throws ezcMailTransportSmtpException * if there is no valid connection - * or if the RCPT TO command failed. - * @param string $to + * or if the RCPT TO command failed + * @param string $email */ protected function cmdRcpt( $email ) { @@ -534,7 +600,7 @@ * * @throws ezcMailTransportSmtpException * if there is no valid connection - * or if the DATA command failed. + * or if the DATA command failed */ private function cmdData() { @@ -554,7 +620,7 @@ * This method appends one line-break at the end of $data. * * @throws ezcMailTransportSmtpException - * if there is no valid connection. + * if there is no valid connection * @param string $data */ private function sendData( $data ) @@ -573,7 +639,7 @@ * Returns data received from the connection stream. * * @throws ezcMailTransportSmtpException - * if there is no valid connection. + * if there is no valid connection * @return string */ private function getData() @@ -602,7 +668,7 @@ * the error message in case of an error. * * @throws ezcMailTransportSmtpException - * if it could not fetch data from the stream. + * if it could not fetch data from the stream * @param string &$line * @return string */ @@ -612,7 +678,6 @@ } } - /** * This class is deprecated. Use ezcMailSmtpTransport instead. * Modified: trunk/Mail/tests/options/smtp_options_test.php =================================================================== --- trunk/Mail/tests/options/smtp_options_test.php 2007-01-30 10:19:42 UTC (rev 4598) +++ trunk/Mail/tests/options/smtp_options_test.php 2007-01-31 10:05:02 UTC (rev 4599) @@ -14,31 +14,48 @@ */ class ezcMailSmtpTransportOptionsTest extends ezcTestCase { -/* // wait until SMTP has options to test public function testTransportOptionsDefault() { $options = new ezcMailSmtpTransportOptions(); - // ... + $this->assertEquals( ezcMailSmtpTransport::CONNECTION_PLAIN, $options->connectionType ); + $this->assertEquals( array(), $options->connectionOptions ); } public function testTransportOptionsSet() { $options = new ezcMailSmtpTransportOptions(); - // ... + $options->connectionType = ezcMailSmtpTransport::CONNECTION_TLS; + $options->connectionOptions = array( 'wrapper' => array( 'option' => 'value' ) ); + $this->assertEquals( ezcMailSmtpTransport::CONNECTION_TLS, $options->connectionType ); + $this->assertEquals( array( 'wrapper' => array( 'option' => 'value' ) ), $options->connectionOptions ); + $options->ssl = true; + $this->assertEquals( ezcMailSmtpTransport::CONNECTION_SSL, $options->connectionType ); + $options->ssl = false; + $this->assertEquals( ezcMailSmtpTransport::CONNECTION_PLAIN, $options->connectionType ); } + public function testTransportOptionsSetInvalid() { $options = new ezcMailSmtpTransportOptions(); try { - // ... + $options->connectionOptions = 'xxx'; $this->fail( "Expected exception was not thrown" ); } catch ( ezcBaseValueException $e ) { } + + try + { + $options->ssl = 'xxx'; + $this->fail( "Expected exception was not thrown" ); + } + catch ( ezcBaseValueException $e ) + { + } } -*/ + public function testTransportOptionsSetNotExistent() { $options = new ezcMailSmtpTransportOptions(); Modified: trunk/Mail/tests/transports/transport_smtp_test.php =================================================================== --- trunk/Mail/tests/transports/transport_smtp_test.php 2007-01-30 10:19:42 UTC (rev 4598) +++ trunk/Mail/tests/transports/transport_smtp_test.php 2007-01-31 10:05:02 UTC (rev 4599) @@ -234,6 +234,11 @@ $smtp->options = new ezcMailSmtpTransportOptions(); $this->assertEquals( $options, $smtp->options ); $this->assertEquals( 5, $smtp->options->timeout ); + $this->assertEquals( 5, $smtp->timeout ); + $smtp->timeout = 10; + $this->assertEquals( 10, $smtp->options->timeout ); + $this->assertEquals( ezcMailSmtpTransport::CONNECTION_PLAIN, $smtp->options->connectionType ); + $this->assertEquals( array(), $smtp->options->connectionOptions ); try { @@ -266,6 +271,184 @@ } } + public function testConnectionSSL() + { + try + { + $smtp = new ezcMailSmtpTransport( 'ezctest.ez.no', '', '', null, array( 'connectionType' => ezcMailSmtpTransport::CONNECTION_SSL ) ); + $mail = new ezcMail(); + $mail->from = new ezcMailAddress( '[EMAIL PROTECTED]', 'From' ); + $mail->addTo( new ezcMailAddress( '[EMAIL PROTECTED]', 'To' ) ); + $mail->subject = "SMTP SSL test"; + $mail->body = new ezcMailText( "It doesn't look as if it's ever used." ); + $mail->generate(); + $smtp->send( $mail ); + } + catch ( ezcMailTransportException $e ) + { + $this->fail( $e->getMessage() ); + } + } + + public function testConnectionSSLOptions() + { + try + { + $smtp = new ezcMailSmtpTransport( 'ezctest.ez.no', '', '', 465, + array( 'connectionType' => ezcMailSmtpTransport::CONNECTION_SSL, + 'connectionOptions' => array( 'wrapper_name' => array( 'option_name' => 'value' ) ) ) ); + $mail = new ezcMail(); + $mail->from = new ezcMailAddress( '[EMAIL PROTECTED]', 'From' ); + $mail->addTo( new ezcMailAddress( '[EMAIL PROTECTED]', 'To' ) ); + $mail->subject = "SMTP SSL test"; + $mail->body = new ezcMailText( "It doesn't look as if it's ever used." ); + $mail->generate(); + $smtp->send( $mail ); + } + catch ( ezcMailTransportException $e ) + { + $this->fail( $e->getMessage() ); + } + } + + public function testConnectionSSLv2() + { + try + { + $smtp = new ezcMailSmtpTransport( 'ezctest.ez.no', '', '', null, array( 'connectionType' => ezcMailSmtpTransport::CONNECTION_SSLV2 ) ); + $mail = new ezcMail(); + $mail->from = new ezcMailAddress( '[EMAIL PROTECTED]', 'From' ); + $mail->addTo( new ezcMailAddress( '[EMAIL PROTECTED]', 'To' ) ); + $mail->subject = "SMTP SSLv2 test"; + $mail->body = new ezcMailText( "It doesn't look as if it's ever used." ); + $mail->generate(); + $smtp->send( $mail ); + } + catch ( ezcMailTransportException $e ) + { + $this->fail( $e->getMessage() ); + } + } + + public function testConnectionSSLv3() + { + try + { + $smtp = new ezcMailSmtpTransport( 'ezctest.ez.no', '', '', 465, array( 'connectionType' => ezcMailSmtpTransport::CONNECTION_SSLV3 ) ); + $mail = new ezcMail(); + $mail->from = new ezcMailAddress( '[EMAIL PROTECTED]', 'From' ); + $mail->addTo( new ezcMailAddress( '[EMAIL PROTECTED]', 'To' ) ); + $mail->subject = "SMTP SSLv3 test"; + $mail->body = new ezcMailText( "It doesn't look as if it's ever used." ); + $mail->generate(); + $smtp->send( $mail ); + } + catch ( ezcMailTransportException $e ) + { + $this->fail( $e->getMessage() ); + } + } + + public function testConnectionTLS() + { + try + { + $smtp = new ezcMailSmtpTransport( 'ezctest.ez.no', '', '', null, array( 'connectionType' => ezcMailSmtpTransport::CONNECTION_TLS ) ); + $mail = new ezcMail(); + $mail->from = new ezcMailAddress( '[EMAIL PROTECTED]', 'From' ); + $mail->addTo( new ezcMailAddress( '[EMAIL PROTECTED]', 'To' ) ); + $mail->subject = "SMTP TLS test"; + $mail->body = new ezcMailText( "It doesn't look as if it's ever used." ); + $mail->generate(); + $smtp->send( $mail ); + } + catch ( ezcMailTransportException $e ) + { + $this->fail( $e->getMessage() ); + } + } + + public function testConnectionTLSWrongPort() + { + try + { + $smtp = new ezcMailSmtpTransport( 'ezctest.ez.no', '', '', 25, array( 'connectionType' => ezcMailSmtpTransport::CONNECTION_TLS ) ); + $mail = new ezcMail(); + $mail->from = new ezcMailAddress( '[EMAIL PROTECTED]', 'From' ); + $mail->addTo( new ezcMailAddress( '[EMAIL PROTECTED]', 'To' ) ); + $mail->subject = "SMTP TLS test"; + $mail->body = new ezcMailText( "It doesn't look as if it's ever used." ); + $mail->generate(); + $smtp->send( $mail ); + $this->fail( "Expected exception was not thrown" ); + } + catch ( ezcMailTransportException $e ) + { + + } + } + + public function testConnectionPlain() + { + try + { + $smtp = new ezcMailSmtpTransport( 'ezctest.ez.no', '', '', null, array( 'connectionType' => ezcMailSmtpTransport::CONNECTION_PLAIN ) ); + $mail = new ezcMail(); + $mail->from = new ezcMailAddress( '[EMAIL PROTECTED]', 'From' ); + $mail->addTo( new ezcMailAddress( '[EMAIL PROTECTED]', 'To' ) ); + $mail->subject = "SMTP TLS test"; + $mail->body = new ezcMailText( "It doesn't look as if it's ever used." ); + $mail->generate(); + $smtp->send( $mail ); + } + catch ( ezcMailTransportException $e ) + { + $this->fail( $e->getMessage() ); + } + } + + public function testConstructorPort() + { + $smtp = new ezcMailSmtpTransport( 'ezctest.ez.no', '', '', null, array( 'connectionType' => ezcMailSmtpTransport::CONNECTION_PLAIN ) ); + $this->assertEquals( 25, $smtp->serverPort ); + + $smtp = new ezcMailSmtpTransport( 'ezctest.ez.no', '', '', null, array( 'connectionType' => ezcMailSmtpTransport::CONNECTION_SSL ) ); + $this->assertEquals( 465, $smtp->serverPort ); + + $smtp = new ezcMailSmtpTransport( 'ezctest.ez.no', '', '', null, array( 'connectionType' => ezcMailSmtpTransport::CONNECTION_SSLV2 ) ); + $this->assertEquals( 465, $smtp->serverPort ); + + $smtp = new ezcMailSmtpTransport( 'ezctest.ez.no', '', '', null, array( 'connectionType' => ezcMailSmtpTransport::CONNECTION_SSLV3 ) ); + $this->assertEquals( 465, $smtp->serverPort ); + + $smtp = new ezcMailSmtpTransport( 'ezctest.ez.no', '', '', null, array( 'connectionType' => ezcMailSmtpTransport::CONNECTION_TLS ) ); + $this->assertEquals( 465, $smtp->serverPort ); + + $smtp = new ezcMailSmtpTransport( 'ezctest.ez.no', '', '', 465, array( 'connectionType' => ezcMailSmtpTransport::CONNECTION_PLAIN ) ); + $this->assertEquals( 465, $smtp->serverPort ); + } + + public function testConstructorOptions() + { + try + { + $smtp = new ezcMailSmtpTransport( 'ezctest.ez.no', '', '', 465, array( 'connection' => ezcMailSmtpTransport::CONNECTION_TLS ) ); + $this->fail( "Expected exception was not thrown" ); + } + catch ( ezcBasePropertyNotFoundException $e ) + { + } + + try + { + $smtp = new ezcMailSmtpTransport( 'ezctest.ez.no', '', '', 465, array( 'connectionOptions' => 'xxx' ) ); + $this->fail( "Expected exception was not thrown" ); + } + catch ( ezcBaseValueException $e ) + { + } + } + public static function suite() { return new PHPUnit_Framework_TestSuite( "ezcMailTransportSmtpTest" ); -- svn-components mailing list svn-components@lists.ez.no http://lists.ez.no/mailman/listinfo/svn-components