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
This commit is contained in:
mark_story 2011-01-06 23:08:54 -05:00
parent f45f2e4096
commit 8754d11aed
2 changed files with 87 additions and 32 deletions

View file

@ -837,6 +837,18 @@ class EmailComponent extends Object{
return @mail($to, $this->_encode($this->subject), $message, $header, $this->additionalParams); 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 * Sends out email via SMTP
* *
@ -853,7 +865,7 @@ class EmailComponent extends Object{
'timeout' => 30 'timeout' => 30
); );
$this->smtpOptions = array_merge($defaults, $this->smtpOptions); $this->smtpOptions = array_merge($defaults, $this->smtpOptions);
$this->__smtpConnection =& new CakeSocket($this->smtpOptions); $this->_getSocket($this->smtpOptions);
if (!$this->__smtpConnection->connect()) { if (!$this->__smtpConnection->connect()) {
$this->smtpError = $this->__smtpConnection->lastError(); $this->smtpError = $this->__smtpConnection->lastError();
@ -867,7 +879,7 @@ class EmailComponent extends Object{
if (isset($this->smtpOptions['client'])) { if (isset($this->smtpOptions['client'])) {
$host = $this->smtpOptions['client']; $host = $this->smtpOptions['client'];
} elseif (!empty($httpHost)) { } elseif (!empty($httpHost)) {
$host = $httpHost; list($host) = explode(':', $httpHost);
} else { } else {
$host = 'localhost'; $host = 'localhost';
} }

View file

@ -20,6 +20,9 @@
* @license http://www.opensource.org/licenses/opengroup.php The Open Group Test Suite License * @license http://www.opensource.org/licenses/opengroup.php The Open Group Test Suite License
*/ */
App::import('Component', 'Email'); App::import('Component', 'Email');
App::import('Core', 'CakeSocket');
Mock::generate('CakeSocket', 'MockEmailSocket');
/** /**
* EmailTestComponent class * EmailTestComponent class
@ -29,6 +32,7 @@ App::import('Component', 'Email');
*/ */
class EmailTestComponent extends EmailComponent { class EmailTestComponent extends EmailComponent {
var $smtpSend = '';
/** /**
* smtpSend method override for testing * smtpSend method override for testing
* *
@ -39,6 +43,19 @@ class EmailTestComponent extends EmailComponent {
return parent::_smtpSend($data, $code); 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. * Convenience setter method for testing.
* *
@ -49,6 +66,18 @@ class EmailTestComponent extends EmailComponent {
$this->__smtpConnection = $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. * Convenience getter method for testing.
* *
@ -408,46 +437,60 @@ TEMPDOC;
* @return void * @return void
*/ */
function testSmtpSendMultipleTo() { function testSmtpSendMultipleTo() {
if ($this->skipIf(!@fsockopen('localhost', 25), '%s No SMTP server running on localhost')) {
return;
}
$this->Controller->EmailTest->reset(); $this->Controller->EmailTest->reset();
$this->Controller->EmailTest->to = array('postmaster@localhost', 'root@localhost'); $this->Controller->EmailTest->to = array('postmaster@localhost', 'root@localhost');
$this->Controller->EmailTest->from = 'noreply@example.com'; $this->Controller->EmailTest->from = 'noreply@example.com';
$this->Controller->EmailTest->subject = 'Cake SMTP multiple To test'; $this->Controller->EmailTest->subject = 'Cake SMTP multiple To test';
$this->Controller->EmailTest->replyTo = 'noreply@example.com'; $this->Controller->EmailTest->replyTo = 'noreply@example.com';
$this->Controller->EmailTest->template = null; $this->Controller->EmailTest->template = null;
$this->Controller->EmailTest->delivery = 'smtp';
$this->assertTrue($this->Controller->EmailTest->send('This is the body of the message'));
$this->Controller->EmailTest->_debug = true; $this->Controller->EmailTest->_debug = true;
$this->Controller->EmailTest->sendAs = 'text'; $this->Controller->EmailTest->sendAs = 'text';
$expect = <<<TEMPDOC $this->Controller->EmailTest->delivery = 'smtp';
<pre>Host: localhost
Port: 25 $socket = new MockEmailSocket();
Timeout: 30 $socket->setReturnValue('connect', true);
To: postmaster@localhost, root@localhost $this->Controller->EmailTest->setConnectionSocket($socket);
From: noreply@example.com
Subject: Cake SMTP multiple To test
Header:
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:
Message:
This is the body of the message
</pre>
TEMPDOC;
$this->assertTrue($this->Controller->EmailTest->send('This is the body of the message')); $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);
$this->assertPattern('/MAIL FROM: <noreply@example\.com>\n/', $this->Controller->EmailTest->smtpSend);
$this->assertPattern('/RCPT TO: <postmaster@localhost>\n/', $this->Controller->EmailTest->smtpSend);
$this->assertPattern('/RCPT TO: <root@localhost>\n/', $this->Controller->EmailTest->smtpSend);
$this->assertPattern(
'/To: postmaster@localhost, root@localhost[\n\r]/',
$this->Controller->EmailTest->smtpSend
);
}
/**
* test sending smtp from a host using a port.
*
* @return void
*/
function testSmtpSendHostWithPort() {
$bkp = env('HTTP_HOST');
$_SERVER['HTTP_HOST'] = 'localhost:8080';
$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;
$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->assertPattern('/EHLO localhost\n/', $this->Controller->EmailTest->smtpSend);
$_SERVER['HTTP_HOST'] = $bkp;
} }
/** /**