Browse Source

Merge remote-tracking branch 'ceeram/2.0-email' into 2.0

Conflicts:
	lib/Cake/Network/Email/AbstractTransport.php
	lib/Cake/Network/Email/CakeEmail.php
	lib/Cake/Network/Email/DebugTransport.php
	lib/Cake/Network/Email/MailTransport.php
	lib/Cake/Network/Email/SmtpTransport.php
Jose Lorenzo Rodriguez 14 years ago
parent
commit
b9b7516945

+ 6 - 5
lib/Cake/Network/Email/AbstractTransport.php

@@ -34,8 +34,8 @@ abstract class AbstractTransport {
 /**
  * Send mail
  *
- * @param CakeEmail $email CakeEmail
- * @return boolean
+ * @params CakeEmail $email
+ * @return array
  */
 	abstract public function send(CakeEmail $email);
 
@@ -43,12 +43,13 @@ abstract class AbstractTransport {
  * Set the config
  *
  * @param array $config
- * @return void
+ * @return array Returns configs
  */
-	public function config($config = array()) {
-		if (!empty($config)) {
+	public function config($config = null) {
+		if (is_array($config)) {
 			$this->_config = $config;
 		}
+		return $this->_config;
 	}
 
 /**

+ 50 - 78
lib/Cake/Network/Email/CakeEmail.php

@@ -266,17 +266,21 @@ class CakeEmail {
  *
  * @var mixed
  */
-	protected $_config = 'default';
+	protected $_config = array();
 
 /**
  * Constructor
+ * @param mixed $config Array of configs, or string to load configs from email.php
  *
  */
-	public function __construct() {
+	public function __construct($config = null) {
 		$charset = Configure::read('App.encoding');
 		if ($charset !== null) {
 			$this->charset = $charset;
 		}
+		if ($config) {
+			$this->config($config);
+		}
 	}
 
 /**
@@ -550,7 +554,7 @@ class CakeEmail {
  * Add header for the message
  *
  * @param array $headers
- * @return mixed $this
+ * @return object $this
  * @throws SocketException
  */
 	public function addHeaders($headers) {
@@ -579,17 +583,10 @@ class CakeEmail {
  * @return array
  */
 	public function getHeaders($include = array()) {
-		$defaults = array(
-			'from' => false,
-			'sender' => false,
-			'replyTo' => false,
-			'readReceipt' => false,
-			'returnPath' => false,
-			'to' => false,
-			'cc' => false,
-			'bcc' => false,
-			'subject' => false
-		);
+		if ($include == array_values($include)) {
+			$include = array_fill_keys($include, true);
+		}
+		$defaults = array_fill_keys(array('from', 'sender', 'replyTo', 'readReceipt', 'returnPath', 'to', 'cc', 'bcc', 'subject'), false);
 		$include += $defaults;
 
 		$headers = array();
@@ -890,50 +887,23 @@ class CakeEmail {
 		if ($config === null) {
 			return $this->_config;
 		}
-
-		if (is_array($config)) {
-			$this->_config = $config;
-		} else {
-			$this->_config = (string)$config;
-		}
-
-		if ($this->_transportClass) {
-			$this->_transportClass->config($this->_config);
+		if (!is_array($config)) {
+			$config = (string)$config;
 		}
 
+		$this->_applyConfig($config);
 		return $this;
 	}
 
 /**
  * Send an email using the specified content, template and layout
  *
- * @param string|array $content
- * @return boolean Success
+ * @return array
  * @throws SocketException
  */
 	public function send($content = null) {
-		if (is_string($this->_config)) {
-			if (!config('email')) {
-				throw new SocketException(__d('cake', '%s not found.', APP . 'Config' . DS . 'email.php'));
-			}
-			$configs = new EmailConfig();
-			if (!isset($configs->{$this->_config})) {
-				throw new SocketException(__d('cake', 'Unknown email configuration "%s".', $this->_config));
-			}
-			$config = $configs->{$this->_config};
-			if (isset($config['transport'])) {
-				$this->transport($config['transport']);
-			}
-		} else {
-			$config = $this->_config;
-		}
-
 		if (empty($this->_from)) {
-			if (!empty($config['from'])) {
-				$this->from($config['from']);
-			} else {
-				throw new SocketException(__d('cake', 'From is not specified.'));
-			}
+			throw new SocketException(__d('cake', 'From is not specified.'));
 		}
 		if (empty($this->_to) && empty($this->_cc) && empty($this->_bcc)) {
 			throw new SocketException(__d('cake', 'You need specify one destination on to, cc or bcc.'));
@@ -972,11 +942,15 @@ class CakeEmail {
 			$this->_message[] = '--' . $this->_boundary . '--';
 			$this->_message[] = '';
 		}
-
-		$transport = $this->transportClass();
-		$transport->config($config);
-
-		return $transport->send($this);
+		$contents = $this->transportClass()->send($this);
+		if (!empty($this->_config['log'])) {
+			$level = LOG_DEBUG;
+			if ($this->_config['log'] !== true) {
+				$level = $this->_config['log'];
+			}
+			CakeLog::write($level, PHP_EOL . $contents['headers'] . PHP_EOL . $contents['message']);
+		}
+		return $contents;
 	}
 
 /**
@@ -992,20 +966,7 @@ class CakeEmail {
  */
 	public static function deliver($to = null, $subject = null, $message = null, $transportConfig = 'fast', $send = true) {
 		$class = __CLASS__;
-		$instance = new $class();
-
-		if (is_string($transportConfig)) {
-			if (!config('email')) {
-				throw new SocketException(__d('cake', '%s not found.', APP . 'Config' . DS . 'email.php'));
-			}
-			$configs = new EmailConfig();
-			if (!isset($configs->{$transportConfig})) {
-				throw new SocketException(__d('cake', 'Unknown email configuration "%s".', $transportConfig));
-			}
-			$transportConfig = $configs->{$transportConfig};
-		}
-		self::_applyConfig($instance, $transportConfig);
-
+		$instance = new $class($transportConfig);
 		if ($to !== null) {
 			$instance->to($to);
 		}
@@ -1015,7 +976,7 @@ class CakeEmail {
 		if (is_array($message)) {
 			$instance->viewVars($message);
 			$message = null;
-		} elseif ($message === null && isset($config['message'])) {
+		} elseif ($message === null && array_key_exists('message', $config = $instance->config())) {
 			$message = $config['message'];
 		}
 
@@ -1033,7 +994,18 @@ class CakeEmail {
  * @param array $config
  * @return void
  */
-	protected static function _applyConfig(CakeEmail $obj, $config) {
+	protected function _applyConfig($config) {
+		if (is_string($config)) {
+			if (!class_exists('EmailConfig') && !config('email')) {
+				throw new SocketException(__d('cake', '%s not found.', APP . 'Config' . DS . 'email.php'));
+			}
+			$configs = new EmailConfig();
+			if (!isset($configs->{$config})) {
+				throw new SocketException(__d('cake', 'Unknown email configuration "%s".', $config));
+			}
+			$config = $configs->{$config};
+		}
+		$this->_config += $config;
 		$simpleMethods = array(
 			'from', 'sender', 'to', 'replyTo', 'readReceipt', 'returnPath', 'cc', 'bcc',
 			'messageId', 'subject', 'viewRender', 'viewVars', 'attachments',
@@ -1041,12 +1013,12 @@ class CakeEmail {
 		);
 		foreach ($simpleMethods as $method) {
 			if (isset($config[$method])) {
-				$obj->$method($config[$method]);
+				$this->$method($config[$method]);
 				unset($config[$method]);
 			}
 		}
 		if (isset($config['headers'])) {
-			$obj->setHeaders($config['headers']);
+			$this->setHeaders($config['headers']);
 			unset($config['headers']);
 		}
 		if (array_key_exists('template', $config)) {
@@ -1055,10 +1027,10 @@ class CakeEmail {
 				$layout = $config['layout'];
 				unset($config['layout']);
 			}
-			$obj->template($config['template'], $layout);
+			$this->template($config['template'], $layout);
 			unset($config['template']);
 		}
-		$obj->config($config);
+		$this->transportClass()->config($config);
 	}
 
 /**
@@ -1090,7 +1062,7 @@ class CakeEmail {
 		$this->_transportName = 'Mail';
 		$this->_transportClass = null;
 		$this->_attachments = array();
-		$this->_config = 'default';
+		$this->_config = array();
 		return $this;
 	}
 
@@ -1288,12 +1260,12 @@ class CakeEmail {
 		$View->helpers = $this->_helpers;
 		$msg = array();
 
-		list($templatePlugin, $template) = pluginSplit($this->_template, true);
-		list($layoutPlugin, $layout) = pluginSplit($this->_layout, true);
-		if (!empty($templatePlugin)) {
-			$View->plugin = rtrim($templatePlugin, '.');
-		} elseif (!empty($layoutPlugin)) {
-			$View->plugin = rtrim($layoutPlugin, '.');
+		list($templatePlugin, $template) = pluginSplit($this->_template);
+		list($layoutPlugin, $layout) = pluginSplit($this->_layout);
+		if ($templatePlugin) {
+			$View->plugin = $templatePlugin;
+		} elseif ($layoutPlugin) {
+			$View->plugin = $layoutPlugin;
 		}
 
 		$content = implode("\n", $content);

+ 4 - 13
lib/Cake/Network/Email/DebugTransport.php

@@ -29,22 +29,13 @@ class DebugTransport extends AbstractTransport {
  * Send mail
  *
  * @param CakeEmail $email CakeEmail
- * @return boolean
+ * @return array
  */
 	public function send(CakeEmail $email) {
-		$headers = $email->getHeaders(array(
-			'from' => true,
-			'sender' => true,
-			'replyTo' => true,
-			'readReceipt' => true,
-			'returnPath' => true,
-			'to' => true,
-			'cc' => true,
-			'bcc' => true,
-			'subject' => true
-		));
+		$headers = $email->getHeaders(array('from', 'sender', 'replyTo', 'readReceipt', 'returnPath', 'to', 'cc', 'bcc', 'subject'));
 		$headers = $this->_headersToString($headers);
-		return $headers . "\n\n" . implode((array)$email->message(), "\n");
+		$message = implode("\r\n", (array)$email->message());
+		return array('headers' => $headers, 'message' => $message);
 	}
 
 }

+ 10 - 5
lib/Cake/Network/Email/MailTransport.php

@@ -28,22 +28,27 @@ class MailTransport extends AbstractTransport {
  * Send mail
  *
  * @param CakeEmail $email CakeEmail
- * @return boolean
+ * @return array
  */
 	public function send(CakeEmail $email) {
 		$eol = PHP_EOL;
 		if (isset($this->_config['eol'])) {
 			$eol = $this->_config['eol'];
 		}
-		$headers = $email->getHeaders(array_fill_keys(array('from', 'sender', 'replyTo', 'readReceipt', 'returnPath', 'to', 'cc', 'bcc'), true));
+		$headers = $email->getHeaders(array('from', 'sender', 'replyTo', 'readReceipt', 'returnPath', 'to', 'cc', 'bcc'));
 		$to = $headers['To'];
 		unset($headers['To']);
-		$header = $this->_headersToString($headers, $eol);
+		$headers = $this->_headersToString($headers, $eol);
 		$message = implode($eol, $email->message());
 		if (ini_get('safe_mode') || !isset($this->_config['additionalParameters'])) {
-			return @mail($to, $email->subject(), $message, $header);
+			if (!@mail($to, $email->subject(), $message, $headers)) {
+				throw new SocketException(__d('cake', 'Could not send email.'));
+			}
 		}
-		return @mail($to, $email->subject(), $message, $header, $this->_config['additionalParameters']);
+		if(!@mail($to, $email->subject(), $message, $headers, $this->_config['additionalParameters'])) {
+			throw new SocketException(__d('cake', 'Could not send email.'));
+		}
+		return array('headers' => $headers, 'message' => $message);
 	}
 
 }

+ 11 - 3
lib/Cake/Network/Email/SmtpTransport.php

@@ -40,10 +40,17 @@ class SmtpTransport extends AbstractTransport {
 	protected $_cakeEmail;
 
 /**
+ * Content of email to return
+ *
+ * @var string
+ */
+	protected $_content;
+
+/**
  * Send mail
  *
  * @param CakeEmail $email CakeEmail
- * @return boolean
+ * @return array
  * @throws SocketException
  */
 	public function send(CakeEmail $email) {
@@ -55,7 +62,7 @@ class SmtpTransport extends AbstractTransport {
 		$this->_sendData();
 		$this->_disconnect();
 
-		return true;
+		return $this->_content;
 	}
 
 /**
@@ -158,10 +165,11 @@ class SmtpTransport extends AbstractTransport {
 	protected function _sendData() {
 		$this->_smtpSend('DATA', '354');
 
-		$headers = $this->_cakeEmail->getHeaders(array_fill_keys(array('from', 'sender', 'replyTo', 'readReceipt', 'returnPath', 'to', 'cc', 'bcc', 'subject'), true));
+		$headers = $this->_cakeEmail->getHeaders(array('from', 'sender', 'replyTo', 'readReceipt', 'returnPath', 'to', 'cc', 'bcc', 'subject'));
 		$headers = $this->_headersToString($headers);
 		$message = implode("\r\n", $this->_cakeEmail->message());
 		$this->_smtpSend($headers . "\r\n\r\n" . $message . "\r\n\r\n\r\n.");
+		$this->_content = array('headers' => $headers, 'message' => $message);
 	}
 
 /**

+ 338 - 106
lib/Cake/Test/Case/Network/Email/CakeEmailTest.php

@@ -57,65 +57,32 @@ class TestCakeEmail extends CakeEmail {
 
 }
 
-/**
- * Debug transport email
- *
- */
-class DebugTransport extends AbstractTransport {
-
-/**
- * Last email body
+/*
+ * EmailConfig class
  *
- * @var string
  */
-	public static $lastEmail = '';
+class EmailConfig {
 
 /**
- * Last email header
+ * test config
  *
  * @var string
  */
-	public static $lastHeader = '';
+	public $test = array(
+		'from' => array('some@example.com' => 'My website'),
+		'to' => array('test@example.com' => 'Testname'),
+		'subject' => 'Test mail subject',
+		'transport' => 'Debug',
+	);
 
-/**
- * Include addresses in header
- *
- * @var boolean
- */
-	public static $includeAddresses = false;
-
-/**
- * Config
- *
- * @var array
- */
-	public static $config = array();
+}
 
-/**
- * Config
+/*
+ * ExtendTransport class
+ * test class to ensure the class has send() method
  *
- * @param mixed $config
- * @return mixed
  */
-	public function config($config) {
-		self::$config = $config;
-	}
-
-/**
- * Send
- *
- * @param object $email CakeEmail
- * @return boolean
- */
-	public function send(CakeEmail $email) {
-		self::$lastEmail = implode("\r\n", $email->message());
-		$options = array();
-		if (self::$includeAddresses) {
-			$options = array_fill_keys(array('from', 'replyTo', 'readReceipt', 'returnPath', 'to', 'cc', 'bcc'), true);
-		}
-		self::$lastHeader = $this->_headersToString($email->getHeaders($options));
-		return true;
-	}
+class ExtendTransport {
 
 }
 
@@ -172,6 +139,9 @@ class CakeEmailTest extends CakeTestCase {
 		$result = $this->CakeEmail->from(array('cake@cakephp.org' => 'CakePHP'));
 		$this->assertIdentical($this->CakeEmail->from(), $expected);
 		$this->assertIdentical($this->CakeEmail, $result);
+
+		$this->setExpectedException('SocketException');
+		$result = $this->CakeEmail->from(array('cake@cakephp.org' => 'CakePHP', 'fail@cakephp.org' => 'From can only be one address'));
 	}
 
 /**
@@ -255,6 +225,7 @@ class CakeEmailTest extends CakeTestCase {
 			array('string'),
 			array('<tag>'),
 			array('some@one.whereis'),
+			array('wrong@key' => 'Name'),
 			array(array('ok@cakephp.org', 1.0, '', 'string'))
 		);
 	}
@@ -271,6 +242,17 @@ class CakeEmailTest extends CakeTestCase {
 	}
 
 /**
+ * testBuildInvalidData
+ *
+ * @dataProvider invalidEmails
+ * @expectedException SocketException
+ * @return void
+ */
+	public function testInvalidEmailAdd($value) {
+		$this->CakeEmail->addTo($value);
+	}
+
+/**
  * testFormatAddress method
  *
  * @return void
@@ -347,6 +329,9 @@ class CakeEmailTest extends CakeTestCase {
 		$this->assertIdentical($this->CakeEmail, $result);
 		$result = $this->CakeEmail->getHeaders();
 		$this->assertIdentical($result['Message-ID'], '<my-email@localhost>');
+
+		$result = $this->CakeEmail->messageId();
+		$this->assertIdentical($result, '<my-email@localhost>');
 	}
 
 /**
@@ -442,6 +427,46 @@ class CakeEmailTest extends CakeTestCase {
 			'Content-Transfer-Encoding' => '7bit'
 		);
 		$this->assertIdentical($this->CakeEmail->getHeaders(array('from' => true, 'to' => true)), $expected);
+
+		$result = $this->CakeEmail->setHeaders(array());
+		$this->assertIsA($result, 'CakeEmail');
+	}
+
+/**
+ * Data provider function for testInvalidHeaders
+ *
+ * @return array
+ */
+	public static function invalidHeaders() {
+		return array(
+			array(10),
+			array(''),
+			array('string'),
+			array(false),
+			array(null)
+		);
+	}
+
+/**
+ * testInvalidHeaders
+ *
+ * @dataProvider invalidHeaders
+ * @expectedException SocketException
+ * @return void
+ */
+	public function testInvalidHeaders($value) {
+		$this->CakeEmail->setHeaders($value);
+	}
+
+/**
+ * testInvalidAddHeaders
+ *
+ * @dataProvider invalidHeaders
+ * @expectedException SocketException
+ * @return void
+ */
+	public function testInvalidAddHeaders($value) {
+		$this->CakeEmail->addHeaders($value);
 	}
 
 /**
@@ -509,6 +534,9 @@ class CakeEmailTest extends CakeTestCase {
 			'license' => array('file' => CAKE . 'LICENSE.txt', 'mimetype' => 'application/octet-stream')
 		);
 		$this->assertIdentical($this->CakeEmail->attachments(), $expected);
+
+		$this->setExpectedException('SocketException');
+		$this->CakeEmail->attachments(array(array('nofile' => CAKE . 'basics.php', 'mimetype' => 'text/plain')));
 	}
 
 /**
@@ -517,12 +545,27 @@ class CakeEmailTest extends CakeTestCase {
  * @return void
  */
 	public function testTransport() {
-		$result = $this->CakeEmail->transport('debug');
+		$result = $this->CakeEmail->transport('Debug');
 		$this->assertIdentical($this->CakeEmail, $result);
-		$this->assertIdentical($this->CakeEmail->transport(), 'debug');
+		$this->assertIdentical($this->CakeEmail->transport(), 'Debug');
 
 		$result = $this->CakeEmail->transportClass();
 		$this->assertIsA($result, 'DebugTransport');
+
+		$this->setExpectedException('SocketException');
+		$this->CakeEmail->transport('Invalid');
+		$result = $this->CakeEmail->transportClass();
+	}
+
+/**
+ * testExtendTransport method
+ *
+ * @return void
+ */
+	public function testExtendTransport() {
+		$this->setExpectedException('SocketException');
+		$this->CakeEmail->transport('Extend');
+		$result = $this->CakeEmail->transportClass();
 	}
 
 /**
@@ -531,46 +574,136 @@ class CakeEmailTest extends CakeTestCase {
  * @return void
  */
 	public function testConfig() {
-		$this->CakeEmail->transport('debug')->transportClass();
-		DebugTransport::$config = array();
+		$transportClass = $this->CakeEmail->transport('debug')->transportClass();
 
 		$config = array('test' => 'ok', 'test2' => true);
 		$this->CakeEmail->config($config);
-		$this->assertIdentical(DebugTransport::$config, $config);
+		$this->assertIdentical($transportClass->config(), $config);
 		$this->assertIdentical($this->CakeEmail->config(), $config);
 
 		$this->CakeEmail->config(array());
-		$this->assertIdentical(DebugTransport::$config, array());
+		$this->assertIdentical($transportClass->config(), array());
+
 	}
 
 /**
+ * testConfigString method
+ *
+ * @return void
+ */
+	public function testConfigString() {
+		$configs = new EmailConfig();
+		$this->CakeEmail->config('test');
+
+		$result = $this->CakeEmail->to();
+		$this->assertEquals($configs->test['to'], $result);
+
+		$result = $this->CakeEmail->from();
+		$this->assertEquals($configs->test['from'], $result);
+
+		$result = $this->CakeEmail->subject();
+		$this->assertEquals($configs->test['subject'], $result);
+
+		$result = $this->CakeEmail->transport();
+		$this->assertEquals($configs->test['transport'], $result);
+
+		$result = $this->CakeEmail->transportClass();
+		$this->assertIsA($result, 'DebugTransport');
+	}
+/**
  * testSendWithContent method
  *
  * @return void
  */
 	public function testSendWithContent() {
 		$this->CakeEmail->reset();
-		$this->CakeEmail->transport('debug');
-		DebugTransport::$includeAddresses = false;
-
+		$this->CakeEmail->transport('Debug');
 		$this->CakeEmail->from('cake@cakephp.org');
 		$this->CakeEmail->to(array('you@cakephp.org' => 'You'));
 		$this->CakeEmail->subject('My title');
 		$this->CakeEmail->config(array('empty'));
-		$result = $this->CakeEmail->send("Here is my body, with multi lines.\nThis is the second line.\r\n\r\nAnd the last.");
 
-		$this->assertTrue($result);
+		$result = $this->CakeEmail->send("Here is my body, with multi lines.\nThis is the second line.\r\n\r\nAnd the last.");
+		$expected = array('headers', 'message');
+		$this->assertEquals($expected, array_keys($result));
 		$expected = "Here is my body, with multi lines.\r\nThis is the second line.\r\n\r\nAnd the last.\r\n\r\n";
-		$this->assertIdentical(DebugTransport::$lastEmail, $expected);
-		$this->assertTrue((bool)strpos(DebugTransport::$lastHeader, 'Date: '));
-		$this->assertTrue((bool)strpos(DebugTransport::$lastHeader, 'Message-ID: '));
-		$this->assertFalse(strpos(DebugTransport::$lastHeader, 'To: '));
 
-		DebugTransport::$includeAddresses = true;
-		$this->CakeEmail->send("Other body");
-		$this->assertIdentical(DebugTransport::$lastEmail, "Other body\r\n\r\n");
-		$this->assertTrue((bool)strpos(DebugTransport::$lastHeader, 'Message-ID: '));
-		$this->assertTrue((bool)strpos(DebugTransport::$lastHeader, 'To: '));
+		$this->assertEquals($expected, $result['message']);
+		$this->assertTrue((bool)strpos($result['headers'], 'Date: '));
+		$this->assertTrue((bool)strpos($result['headers'], 'Message-ID: '));
+		$this->assertTrue((bool)strpos($result['headers'], 'To: '));
+
+		$result = $this->CakeEmail->send("Other body");
+		$expected = "Other body\r\n\r\n";
+		$this->assertIdentical($result['message'], $expected);
+		$this->assertTrue((bool)strpos($result['headers'], 'Message-ID: '));
+		$this->assertTrue((bool)strpos($result['headers'], 'To: '));
+
+		$this->CakeEmail->reset();
+		$this->CakeEmail->transport('Debug');
+		$this->CakeEmail->from('cake@cakephp.org');
+		$this->CakeEmail->to(array('you@cakephp.org' => 'You'));
+		$this->CakeEmail->subject('My title');
+		$this->CakeEmail->config(array('empty'));
+		$result = $this->CakeEmail->send(array('Sending content', 'As array'));
+		$expected = "Sending content\r\nAs array\r\n\r\n\r\n";
+		$this->assertIdentical($result['message'], $expected);
+	}
+
+/**
+ * testSendWithoutFrom method
+ *
+ * @return void
+ */
+	public function testSendWithoutFrom() {
+		$this->CakeEmail->transport('Debug');
+		$this->CakeEmail->to('cake@cakephp.org');
+		$this->CakeEmail->subject('My title');
+		$this->CakeEmail->config(array('empty'));
+		$this->setExpectedException('SocketException');
+		$this->CakeEmail->send("Forgot to set From");
+	}
+
+/**
+ * testSendWithoutTo method
+ *
+ * @return void
+ */
+	public function testSendWithoutTo() {
+		$this->CakeEmail->transport('Debug');
+		$this->CakeEmail->from('cake@cakephp.org');
+		$this->CakeEmail->subject('My title');
+		$this->CakeEmail->config(array('empty'));
+		$this->setExpectedException('SocketException');
+		$this->CakeEmail->send("Forgot to set To");
+	}
+
+/**
+ * testSendWithLog method
+ *
+ * @return void
+ */
+	public function testSendWithLog() {
+		$path = CAKE . 'Test' . DS . 'test_app' . DS . 'tmp' . DS;
+		CakeLog::config('email', array(
+			'engine' => 'FileLog',
+			'path' => CAKE . 'Test' . DS . 'test_app' . DS . 'tmp' . DS
+		));
+		CakeLog::drop('default');
+		$this->CakeEmail->transport('Debug');
+		$this->CakeEmail->to('me@cakephp.org');
+		$this->CakeEmail->from('cake@cakephp.org');
+		$this->CakeEmail->subject('My title');
+		$this->CakeEmail->config(array('log' => 'emails'));
+		$result = $this->CakeEmail->send("Logging This");
+
+		App::uses('File', 'Utility');
+		$File = new File(CAKE . 'Test' . DS . 'test_app' . DS . 'tmp' . DS . 'emails.log');
+		$log = $File->read();
+		$this->assertTrue(strpos($log, $result['headers']) !== false);
+		$this->assertTrue(strpos($log, $result['message']) !== false);
+		$File->delete();
+		CakeLog::drop('email');
 	}
 
 /**
@@ -581,7 +714,6 @@ class CakeEmailTest extends CakeTestCase {
 	public function testSendRender() {
 		$this->CakeEmail->reset();
 		$this->CakeEmail->transport('debug');
-		DebugTransport::$includeAddresses = true;
 
 		$this->CakeEmail->from('cake@cakephp.org');
 		$this->CakeEmail->to(array('you@cakephp.org' => 'You'));
@@ -590,9 +722,9 @@ class CakeEmailTest extends CakeTestCase {
 		$this->CakeEmail->template('default', 'default');
 		$result = $this->CakeEmail->send();
 
-		$this->assertTrue((bool)strpos(DebugTransport::$lastEmail, 'This email was sent using the CakePHP Framework'));
-		$this->assertTrue((bool)strpos(DebugTransport::$lastHeader, 'Message-ID: '));
-		$this->assertTrue((bool)strpos(DebugTransport::$lastHeader, 'To: '));
+		$this->assertTrue((bool)strpos($result['message'], 'This email was sent using the CakePHP Framework'));
+		$this->assertTrue((bool)strpos($result['headers'], 'Message-ID: '));
+		$this->assertTrue((bool)strpos($result['headers'], 'To: '));
 	}
 
 /**
@@ -603,7 +735,6 @@ class CakeEmailTest extends CakeTestCase {
 	public function testSendRenderWithVars() {
 		$this->CakeEmail->reset();
 		$this->CakeEmail->transport('debug');
-		DebugTransport::$includeAddresses = true;
 
 		$this->CakeEmail->from('cake@cakephp.org');
 		$this->CakeEmail->to(array('you@cakephp.org' => 'You'));
@@ -613,7 +744,7 @@ class CakeEmailTest extends CakeTestCase {
 		$this->CakeEmail->viewVars(array('value' => 12345));
 		$result = $this->CakeEmail->send();
 
-		$this->assertTrue((bool)strpos(DebugTransport::$lastEmail, 'Here is your value: 12345'));
+		$this->assertTrue((bool)strpos($result['message'], 'Here is your value: 12345'));
 	}
 
 /**
@@ -624,7 +755,6 @@ class CakeEmailTest extends CakeTestCase {
 	public function testSendRenderWithHelpers() {
 		$this->CakeEmail->reset();
 		$this->CakeEmail->transport('debug');
-		DebugTransport::$includeAddresses = true;
 
 		$timestamp = time();
 		$this->CakeEmail->from('cake@cakephp.org');
@@ -633,10 +763,15 @@ class CakeEmailTest extends CakeTestCase {
 		$this->CakeEmail->config(array('empty'));
 		$this->CakeEmail->template('custom_helper', 'default');
 		$this->CakeEmail->viewVars(array('time' => $timestamp));
-		$this->CakeEmail->helpers(array('Time'));
+
+		$result = $this->CakeEmail->helpers(array('Time'));
+		$this->assertIsA($result, 'CakeEmail');
+
 		$result = $this->CakeEmail->send();
+		$this->assertTrue((bool)strpos($result['message'], 'Right now: ' . date('Y-m-d\TH:i:s\Z', $timestamp)));
 
-		$this->assertTrue((bool)strpos(DebugTransport::$lastEmail, 'Right now: ' . date('Y-m-d\TH:i:s\Z', $timestamp)));
+		$result = $this->CakeEmail->helpers();
+		$this->assertEquals(array('Time'), $result);
 	}
 
 /**
@@ -652,31 +787,29 @@ class CakeEmailTest extends CakeTestCase {
 
 		$this->CakeEmail->reset();
 		$this->CakeEmail->transport('debug');
-		DebugTransport::$includeAddresses = true;
 		$this->CakeEmail->from('cake@cakephp.org');
 		$this->CakeEmail->to(array('you@cakephp.org' => 'You'));
 		$this->CakeEmail->subject('My title');
 		$this->CakeEmail->config(array('empty'));
 
-		$this->CakeEmail->template('TestPlugin.test_plugin_tpl', 'default')->send();
-		$this->assertTrue((bool)strpos(DebugTransport::$lastEmail, 'Into TestPlugin.'));
-		$this->assertTrue((bool)strpos(DebugTransport::$lastEmail, 'This email was sent using the CakePHP Framework'));
+		$result = $this->CakeEmail->template('TestPlugin.test_plugin_tpl', 'default')->send();
+		$this->assertTrue((bool)strpos($result['message'], 'Into TestPlugin.'));
+		$this->assertTrue((bool)strpos($result['message'], 'This email was sent using the CakePHP Framework'));
 
-		$this->CakeEmail->template('TestPlugin.test_plugin_tpl', 'TestPlugin.plug_default')->send();
-		$this->assertTrue((bool)strpos(DebugTransport::$lastEmail, 'Into TestPlugin.'));
-		$this->assertTrue((bool)strpos(DebugTransport::$lastEmail, 'This email was sent using the TestPlugin.'));
+		$result = $this->CakeEmail->template('TestPlugin.test_plugin_tpl', 'TestPlugin.plug_default')->send();
+		$this->assertTrue((bool)strpos($result['message'], 'Into TestPlugin.'));
+		$this->assertTrue((bool)strpos($result['message'], 'This email was sent using the TestPlugin.'));
 
-		DebugTransport::$lastEmail = '';
-		$this->CakeEmail->template('TestPlugin.test_plugin_tpl', 'plug_default')->send();
-		$this->assertTrue((bool)strpos(DebugTransport::$lastEmail, 'Into TestPlugin.'));
-		$this->assertTrue((bool)strpos(DebugTransport::$lastEmail, 'This email was sent using the TestPlugin.'));
+		$result = $this->CakeEmail->template('TestPlugin.test_plugin_tpl', 'plug_default')->send();
+		$this->assertTrue((bool)strpos($result['message'], 'Into TestPlugin.'));
+		$this->assertTrue((bool)strpos($result['message'], 'This email was sent using the TestPlugin.'));
 
 		$this->CakeEmail->viewVars(array('value' => 12345));
-		$this->CakeEmail->template('custom', 'TestPlugin.plug_default')->send();
-		$this->assertTrue((bool)strpos(DebugTransport::$lastEmail, 'Here is your value: 12345'));
-		$this->assertTrue((bool)strpos(DebugTransport::$lastEmail, 'This email was sent using the TestPlugin.'));
+		$result = $this->CakeEmail->template('custom', 'TestPlugin.plug_default')->send();
+		$this->assertTrue((bool)strpos($result['message'], 'Here is your value: 12345'));
+		$this->assertTrue((bool)strpos($result['message'], 'This email was sent using the TestPlugin.'));
 
-		$this->expectException();
+		$this->setExpectedException('MissingViewException');
 		$this->CakeEmail->template('test_plugin_tpl', 'plug_default')->send();
 	}
 
@@ -688,7 +821,6 @@ class CakeEmailTest extends CakeTestCase {
 	public function testSendMultipleMIME() {
 		$this->CakeEmail->reset();
 		$this->CakeEmail->transport('debug');
-		DebugTransport::$includeAddresses = true;
 
 		$this->CakeEmail->from('cake@cakephp.org');
 		$this->CakeEmail->to(array('you@cakephp.org' => 'You'));
@@ -727,27 +859,25 @@ class CakeEmailTest extends CakeTestCase {
 	public function testSendAttachment() {
 		$this->CakeEmail->reset();
 		$this->CakeEmail->transport('debug');
-		DebugTransport::$includeAddresses = false;
-
 		$this->CakeEmail->from('cake@cakephp.org');
 		$this->CakeEmail->to(array('you@cakephp.org' => 'You'));
 		$this->CakeEmail->subject('My title');
 		$this->CakeEmail->config(array());
 		$this->CakeEmail->attachments(array(CAKE . 'basics.php'));
-		$this->CakeEmail->send('body');
-		$this->assertTrue((bool)strpos(DebugTransport::$lastEmail, "Content-Type: application/octet-stream\r\nContent-Transfer-Encoding: base64\r\nContent-Disposition: attachment; filename=\"basics.php\""));
+		$result = $this->CakeEmail->send('body');
+		$this->assertTrue((bool)strpos($result['message'], "Content-Type: application/octet-stream\r\nContent-Transfer-Encoding: base64\r\nContent-Disposition: attachment; filename=\"basics.php\""));
 
 		$this->CakeEmail->attachments(array('my.file.txt' => CAKE . 'basics.php'));
-		$this->CakeEmail->send('body');
-		$this->assertTrue((bool)strpos(DebugTransport::$lastEmail, "Content-Type: application/octet-stream\r\nContent-Transfer-Encoding: base64\r\nContent-Disposition: attachment; filename=\"my.file.txt\""));
+		$result = $this->CakeEmail->send('body');
+		$this->assertTrue((bool)strpos($result['message'], "Content-Type: application/octet-stream\r\nContent-Transfer-Encoding: base64\r\nContent-Disposition: attachment; filename=\"my.file.txt\""));
 
 		$this->CakeEmail->attachments(array('file.txt' => array('file' => CAKE . 'basics.php', 'mimetype' => 'text/plain')));
-		$this->CakeEmail->send('body');
-		$this->assertTrue((bool)strpos(DebugTransport::$lastEmail, "Content-Type: text/plain\r\nContent-Transfer-Encoding: base64\r\nContent-Disposition: attachment; filename=\"file.txt\""));
+		$result = $this->CakeEmail->send('body');
+		$this->assertTrue((bool)strpos($result['message'], "Content-Type: text/plain\r\nContent-Transfer-Encoding: base64\r\nContent-Disposition: attachment; filename=\"file.txt\""));
 
-		$this->CakeEmail->attachments(array('file.txt' => array('file' => CAKE . 'basics.php', 'mimetype' => 'text/plain', 'contentId' => 'a1b1c1')));
-		$this->CakeEmail->send('body');
-		$this->assertTrue((bool)strpos(DebugTransport::$lastEmail, "Content-Type: text/plain\r\nContent-Transfer-Encoding: base64\r\nContent-ID: <a1b1c1>\r\nContent-Disposition: inline; filename=\"file.txt\""));
+		$this->CakeEmail->attachments(array('file2.txt' => array('file' => CAKE . 'basics.php', 'mimetype' => 'text/plain', 'contentId' => 'a1b1c1')));
+		$result = $this->CakeEmail->send('body');
+		$this->assertTrue((bool)strpos($result['message'], "Content-Type: text/plain\r\nContent-Transfer-Encoding: base64\r\nContent-ID: <a1b1c1>\r\nContent-Disposition: inline; filename=\"file2.txt\""));
 	}
 
 /**
@@ -778,6 +908,11 @@ class CakeEmailTest extends CakeTestCase {
 		$this->assertIdentical($instance->template(), array('template' => 'custom', 'layout' => 'custom_layout'));
 		$this->assertIdentical($instance->viewVars(), array('value' => 123, 'name' => 'CakePHP'));
 		$this->assertIdentical($instance->cc(), array('cake@cakephp.org' => 'Myself'));
+
+		$configs = array('from' => 'root@cakephp.org', 'message' => 'Message from configs', 'transport' => 'Debug');
+		$instance = CakeEmail::deliver('all@cakephp.org', 'About', null, $configs, true);
+		$message = $instance->message();
+		$this->assertEquals($configs['message'], $message[0]);
 	}
 
 /**
@@ -788,8 +923,6 @@ class CakeEmailTest extends CakeTestCase {
 	public function testMessage() {
 		$this->CakeEmail->reset();
 		$this->CakeEmail->transport('debug');
-		DebugTransport::$includeAddresses = true;
-
 		$this->CakeEmail->from('cake@cakephp.org');
 		$this->CakeEmail->to(array('you@cakephp.org' => 'You'));
 		$this->CakeEmail->subject('My title');
@@ -888,4 +1021,103 @@ class CakeEmailTest extends CakeTestCase {
 		$this->assertIdentical($expected, $result);
 	}
 
+/**
+ * testConstructWithConfigArray method
+ *
+ * @return void
+ */
+	public function testConstructWithConfigArray() {
+		$configs = array(
+			'from' => array('some@example.com' => 'My website'),
+			'to' => 'test@example.com',
+			'subject' => 'Test mail subject',
+			'transport' => 'Debug',
+		);
+		$this->CakeEmail = new CakeEmail($configs);
+
+		$result = $this->CakeEmail->to();
+		$this->assertEquals(array($configs['to'] => $configs['to']), $result);
+
+		$result = $this->CakeEmail->from();
+		$this->assertEquals($configs['from'], $result);
+
+		$result = $this->CakeEmail->subject();
+		$this->assertEquals($configs['subject'], $result);
+
+		$result = $this->CakeEmail->transport();
+		$this->assertEquals($configs['transport'], $result);
+
+		$result = $this->CakeEmail->transportClass();
+		$this->assertTrue($result instanceof DebugTransport);
+
+		$result = $this->CakeEmail->send('This is the message');
+
+		$this->assertTrue((bool)strpos($result['headers'], 'Message-ID: '));
+		$this->assertTrue((bool)strpos($result['headers'], 'To: '));
+	}
+
+/**
+ * testConstructWithConfigString method
+ *
+ * @return void
+ */
+	public function testConstructWithConfigString() {
+		$configs = new EmailConfig();
+		$this->CakeEmail = new CakeEmail('test');
+
+		$result = $this->CakeEmail->to();
+		$this->assertEquals($configs->test['to'], $result);
+
+		$result = $this->CakeEmail->from();
+		$this->assertEquals($configs->test['from'], $result);
+
+		$result = $this->CakeEmail->subject();
+		$this->assertEquals($configs->test['subject'], $result);
+
+		$result = $this->CakeEmail->transport();
+		$this->assertEquals($configs->test['transport'], $result);
+
+		$result = $this->CakeEmail->transportClass();
+		$this->assertTrue($result instanceof DebugTransport);
+
+		$result = $this->CakeEmail->send('This is the message');
+
+		$this->assertTrue((bool)strpos($result['headers'], 'Message-ID: '));
+		$this->assertTrue((bool)strpos($result['headers'], 'To: '));
+	}
+/**
+ * testViewRender method
+ *
+ * @return void
+ */
+	public function testViewRender() {
+		$result = $this->CakeEmail->viewRender();
+		$this->assertEquals('View', $result);
+
+		$result = $this->CakeEmail->viewRender('Theme');
+		$this->assertIsA($result, 'CakeEmail');
+
+		$result = $this->CakeEmail->viewRender();
+		$this->assertEquals('Theme', $result);
+	}
+
+/**
+ * testEmailFormat method
+ *
+ * @return void
+ */
+	public function testEmailFormat() {
+		$result = $this->CakeEmail->emailFormat();
+		$this->assertEquals('text', $result);
+
+		$result = $this->CakeEmail->emailFormat('html');
+		$this->assertIsA($result, 'CakeEmail');
+
+		$result = $this->CakeEmail->emailFormat();
+		$this->assertEquals('html', $result);
+
+		$this->setExpectedException('SocketException');
+		$result = $this->CakeEmail->emailFormat('invalid');
+	}
+
 }

+ 17 - 15
lib/Cake/Test/Case/Network/Email/DebugTransportTest.php

@@ -51,23 +51,25 @@ class DebugTransportTest extends CakeTestCase {
 		$email->subject('Testing Message');
 		$email->expects($this->any())->method('message')->will($this->returnValue(array('First Line', 'Second Line', '')));
 
-		$data = "From: CakePHP Test <noreply@cakephp.org>\r\n";
-		$data .= "To: CakePHP <cake@cakephp.org>\r\n";
-		$data .= "Cc: Mark Story <mark@cakephp.org>, Juan Basso <juan@cakephp.org>\r\n";
-		$data .= "Bcc: phpnut@cakephp.org\r\n";
-		$data .= "X-Mailer: CakePHP Email\r\n";
-		$data .= "Date: " . date(DATE_RFC2822) . "\r\n";
-		$data .= "Message-ID: <4d9946cf-0a44-4907-88fe-1d0ccbdd56cb@localhost>\r\n";
-		$data .= "Subject: Testing Message\r\n";
-		$data .= "MIME-Version: 1.0\r\n";
-		$data .= "Content-Type: text/plain; charset=UTF-8\r\n";
-		$data .= "Content-Transfer-Encoding: 7bit";
-		$data .= "\n\n";
-		$data .= "First Line\n";
-		$data .= "Second Line\n";
+		$headers = "From: CakePHP Test <noreply@cakephp.org>\r\n";
+		$headers .= "To: CakePHP <cake@cakephp.org>\r\n";
+		$headers .= "Cc: Mark Story <mark@cakephp.org>, Juan Basso <juan@cakephp.org>\r\n";
+		$headers .= "Bcc: phpnut@cakephp.org\r\n";
+		$headers .= "X-Mailer: CakePHP Email\r\n";
+		$headers .= "Date: " . date(DATE_RFC2822) . "\r\n";
+		$headers .= "Message-ID: <4d9946cf-0a44-4907-88fe-1d0ccbdd56cb@localhost>\r\n";
+		$headers .= "Subject: Testing Message\r\n";
+		$headers .= "MIME-Version: 1.0\r\n";
+		$headers .= "Content-Type: text/plain; charset=UTF-8\r\n";
+		$headers .= "Content-Transfer-Encoding: 7bit";
+
+		$data = "First Line\r\n";
+		$data .= "Second Line\r\n";
 
 		$result = $this->DebugTransport->send($email);
-		$this->assertEquals($data, $result);
+
+		$this->assertEquals($headers, $result['headers']);
+		$this->assertEquals($data, $result['message']);
 	}
 
 }

+ 3 - 3
lib/Cake/Test/Case/Network/Email/SmtpTransportTest.php

@@ -61,7 +61,7 @@ class SmtpTestTransport extends SmtpTransport {
  * @param string $method
  * @param string $args
  * @return mixed
- */ 
+ */
 	public function __call($method, $args) {
 		$method = '_' . $method;
 		return $this->$method();
@@ -73,7 +73,7 @@ class SmtpTestTransport extends SmtpTransport {
  * Test case
  *
  */
-class StmpProtocolTest extends CakeTestCase {
+class SmtpTransportTest extends CakeTestCase {
 
 /**
  * Setup
@@ -130,7 +130,7 @@ class StmpProtocolTest extends CakeTestCase {
  * @expectedException Exception
  * @return void
  */
-	public function testConnetFail() {
+	public function testConnectFail() {
 		$this->socket->expects($this->any())->method('connect')->will($this->returnValue(true));
 		$this->socket->expects($this->at(0))->method('read')->will($this->returnValue(false));
 		$this->socket->expects($this->at(1))->method('read')->will($this->returnValue("220 Welcome message\r\n"));