Skip to content

Commit

Permalink
Adding EmailComponent::_getSocket() so EmailComponent + smtp is easie…
Browse files Browse the repository at this point in the history
…r 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
  • Loading branch information
markstory committed Jan 7, 2011
1 parent f45f2e4 commit 8754d11
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 28 deletions.
16 changes: 14 additions & 2 deletions cake/libs/controller/components/email.php
Expand Up @@ -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
*
Expand All @@ -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();
Expand All @@ -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';
}
Expand Down
95 changes: 69 additions & 26 deletions cake/tests/cases/libs/controller/components/email.test.php
Expand Up @@ -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
Expand All @@ -29,6 +32,7 @@
*/
class EmailTestComponent extends EmailComponent {

var $smtpSend = '';
/**
* smtpSend method override for testing
*
Expand All @@ -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.
*
Expand All @@ -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.
*
Expand Down Expand Up @@ -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 = <<<TEMPDOC
<pre>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: <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
);
}

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);

</pre>
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;
}

/**
Expand Down

0 comments on commit 8754d11

Please sign in to comment.