From 8754d11aed8c5b88fb94dcd50db765cb4c0c46b5 Mon Sep 17 00:00:00 2001 From: mark_story Date: Thu, 6 Jan 2011 23:08:54 -0500 Subject: [PATCH] Adding EmailComponent::_getSocket() so EmailComponent + smtp is easier to test. Fixing issue where hosts with portnames could cause smtp emails to fail. Added tests, fixed an existing test to not depend on a local mailserver. Fixes #1433 --- cake/libs/controller/components/email.php | 16 +++- .../libs/controller/components/email.test.php | 95 ++++++++++++++----- 2 files changed, 83 insertions(+), 28 deletions(-) diff --git a/cake/libs/controller/components/email.php b/cake/libs/controller/components/email.php index c5ff866d5ab..78698b056d3 100755 --- a/cake/libs/controller/components/email.php +++ b/cake/libs/controller/components/email.php @@ -837,6 +837,18 @@ function _mail() { return @mail($to, $this->_encode($this->subject), $message, $header, $this->additionalParams); } + +/** + * Helper method to get socket, overridden in tests + * + * @param array $config Config data for the socket. + * @return void + * @access protected + */ + function _getSocket($config) { + $this->__smtpConnection =& new CakeSocket($config); + } + /** * Sends out email via SMTP * @@ -853,7 +865,7 @@ function _smtp() { 'timeout' => 30 ); $this->smtpOptions = array_merge($defaults, $this->smtpOptions); - $this->__smtpConnection =& new CakeSocket($this->smtpOptions); + $this->_getSocket($this->smtpOptions); if (!$this->__smtpConnection->connect()) { $this->smtpError = $this->__smtpConnection->lastError(); @@ -867,7 +879,7 @@ function _smtp() { if (isset($this->smtpOptions['client'])) { $host = $this->smtpOptions['client']; } elseif (!empty($httpHost)) { - $host = $httpHost; + list($host) = explode(':', $httpHost); } else { $host = 'localhost'; } diff --git a/cake/tests/cases/libs/controller/components/email.test.php b/cake/tests/cases/libs/controller/components/email.test.php index 72c14ace696..de1be084e11 100755 --- a/cake/tests/cases/libs/controller/components/email.test.php +++ b/cake/tests/cases/libs/controller/components/email.test.php @@ -20,6 +20,9 @@ * @license http://www.opensource.org/licenses/opengroup.php The Open Group Test Suite License */ App::import('Component', 'Email'); +App::import('Core', 'CakeSocket'); + +Mock::generate('CakeSocket', 'MockEmailSocket'); /** * EmailTestComponent class @@ -29,6 +32,7 @@ */ class EmailTestComponent extends EmailComponent { + var $smtpSend = ''; /** * smtpSend method override for testing * @@ -39,6 +43,19 @@ function smtpSend($data, $code = '250') { return parent::_smtpSend($data, $code); } +/** + * undocumented function + * + * @return void + */ + function _smtpSend($data, $code = '250') { + if ($this->_debug) { + $this->smtpSend .= $data . "\n"; + return true; + } + return parent::_smtpSend($data, $code); + } + /** * Convenience setter method for testing. * @@ -49,6 +66,18 @@ function setConnectionSocket(&$socket) { $this->__smtpConnection = $socket; } +/** + * Allows mocks to be used with tests. + * + * @param array $config + * @return void + */ + function _getSocket($config) { + if (empty($this->__smtpConnection)) { + parent::_getSocket($config); + } + } + /** * Convenience getter method for testing. * @@ -408,46 +437,60 @@ function testSmtpEhlo() { * @return void */ function testSmtpSendMultipleTo() { - if ($this->skipIf(!@fsockopen('localhost', 25), '%s No SMTP server running on localhost')) { - return; - } $this->Controller->EmailTest->reset(); $this->Controller->EmailTest->to = array('postmaster@localhost', 'root@localhost'); $this->Controller->EmailTest->from = 'noreply@example.com'; $this->Controller->EmailTest->subject = 'Cake SMTP multiple To test'; $this->Controller->EmailTest->replyTo = 'noreply@example.com'; $this->Controller->EmailTest->template = null; - + $this->Controller->EmailTest->_debug = true; + $this->Controller->EmailTest->sendAs = 'text'; $this->Controller->EmailTest->delivery = 'smtp'; + + $socket = new MockEmailSocket(); + $socket->setReturnValue('connect', true); + $this->Controller->EmailTest->setConnectionSocket($socket); + $this->assertTrue($this->Controller->EmailTest->send('This is the body of the message')); - $this->Controller->EmailTest->_debug = true; - $this->Controller->EmailTest->sendAs = 'text'; - $expect = <<Host: localhost -Port: 25 -Timeout: 30 -To: postmaster@localhost, root@localhost -From: noreply@example.com -Subject: Cake SMTP multiple To test -Header: + $this->assertPattern('/EHLO localhost\n/', $this->Controller->EmailTest->smtpSend); + $this->assertPattern('/MAIL FROM: \n/', $this->Controller->EmailTest->smtpSend); + $this->assertPattern('/RCPT TO: \n/', $this->Controller->EmailTest->smtpSend); + $this->assertPattern('/RCPT TO: \n/', $this->Controller->EmailTest->smtpSend); + $this->assertPattern( + '/To: postmaster@localhost, root@localhost[\n\r]/', + $this->Controller->EmailTest->smtpSend + ); + } -To: postmaster@localhost, root@localhost -From: noreply@example.com -Reply-To: noreply@example.com -Subject: Cake SMTP multiple To test -X-Mailer: CakePHP Email Component -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 7bitParameters: +/** + * test sending smtp from a host using a port. + * + * @return void + */ + function testSmtpSendHostWithPort() { + $bkp = env('HTTP_HOST'); + $_SERVER['HTTP_HOST'] = 'localhost:8080'; -Message: + $this->Controller->EmailTest->reset(); + $this->Controller->EmailTest->to = array('root@localhost'); + $this->Controller->EmailTest->from = 'noreply@example.com'; + $this->Controller->EmailTest->subject = 'Cake SMTP host test'; + $this->Controller->EmailTest->replyTo = 'noreply@example.com'; + $this->Controller->EmailTest->template = null; + $this->Controller->EmailTest->delivery = 'smtp'; + $this->Controller->EmailTest->sendAs = 'text'; + $this->Controller->EmailTest->_debug = true; -This is the body of the message + $socket = new MockEmailSocket(); + $socket->setReturnValue('connect', true); - -TEMPDOC; + $this->Controller->EmailTest->setConnectionSocket($socket); $this->assertTrue($this->Controller->EmailTest->send('This is the body of the message')); - $this->assertEqual($this->Controller->Session->read('Message.email.message'), $this->__osFix($expect)); + + $this->assertPattern('/EHLO localhost\n/', $this->Controller->EmailTest->smtpSend); + + $_SERVER['HTTP_HOST'] = $bkp; } /**