LoggerAppenderMail: added dependency injection

The Mailer object can be injected, this makes the class testable and
should fix problems with TravisCI.

Signed-off-by: Ivan Habunek <ihabunek@apache.org>
diff --git a/src/main/php/LoggerAutoloader.php b/src/main/php/LoggerAutoloader.php
index d633562..29da2e9 100644
--- a/src/main/php/LoggerAutoloader.php
+++ b/src/main/php/LoggerAutoloader.php
@@ -1,144 +1,146 @@
-<?php

-/**

- * Licensed to the Apache Software Foundation (ASF) under one or more

- * contributor license agreements. See the NOTICE file distributed with

- * this work for additional information regarding copyright ownership.

- * The ASF licenses this file to You under the Apache License, Version 2.0

- * (the "License"); you may not use this file except in compliance with

- * the License. You may obtain a copy of the License at

- * 

- *		http://www.apache.org/licenses/LICENSE-2.0

- * 

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- * 

- * @package log4php

- */

-

-if (function_exists('__autoload')) {

-	trigger_error("log4php: It looks like your code is using an __autoload() function. log4php uses spl_autoload_register() which will bypass your __autoload() function and may break autoloading.", E_USER_WARNING);

-}

-

-spl_autoload_register(array('LoggerAutoloader', 'autoload'));

-

-/**

- * Class autoloader.

- * 

- * @package log4php

- * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0

- */

-class LoggerAutoloader {

-	

-	/** Maps classnames to files containing the class. */

-	private static $classes = array(

-	

-		// Base

-		'LoggerAppender' => '/LoggerAppender.php',

-		'LoggerAppenderPool' => '/LoggerAppenderPool.php',

-		'LoggerConfigurable' => '/LoggerConfigurable.php',

-		'LoggerConfigurator' => '/LoggerConfigurator.php',

-		'LoggerException' => '/LoggerException.php',

-		'LoggerFilter' => '/LoggerFilter.php',

-		'LoggerHierarchy' => '/LoggerHierarchy.php',

-		'LoggerLevel' => '/LoggerLevel.php',

-		'LoggerLocationInfo' => '/LoggerLocationInfo.php',

-		'LoggerLoggingEvent' => '/LoggerLoggingEvent.php',

-		'LoggerMDC' => '/LoggerMDC.php',

-		'LoggerNDC' => '/LoggerNDC.php',

-		'LoggerLayout' => '/LoggerLayout.php',

-		'LoggerReflectionUtils' => '/LoggerReflectionUtils.php',

-		'LoggerRoot' => '/LoggerRoot.php',

-		'LoggerThrowableInformation' => '/LoggerThrowableInformation.php',

-		

-		// Appenders

+<?php
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *		http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * @package log4php
+ */
+
+if (function_exists('__autoload')) {
+	trigger_error("log4php: It looks like your code is using an __autoload() function. log4php uses spl_autoload_register() which will bypass your __autoload() function and may break autoloading.", E_USER_WARNING);
+}
+
+spl_autoload_register(array('LoggerAutoloader', 'autoload'));
+
+/**
+ * Class autoloader.
+ *
+ * @package log4php
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
+ */
+class LoggerAutoloader {
+
+	/** Maps classnames to files containing the class. */
+	private static $classes = array(
+
+		// Base
+		'LoggerAppender' => '/LoggerAppender.php',
+		'LoggerAppenderPool' => '/LoggerAppenderPool.php',
+		'LoggerConfigurable' => '/LoggerConfigurable.php',
+		'LoggerConfigurator' => '/LoggerConfigurator.php',
+		'LoggerException' => '/LoggerException.php',
+		'LoggerFilter' => '/LoggerFilter.php',
+		'LoggerHierarchy' => '/LoggerHierarchy.php',
+		'LoggerLevel' => '/LoggerLevel.php',
+		'LoggerLocationInfo' => '/LoggerLocationInfo.php',
+		'LoggerLoggingEvent' => '/LoggerLoggingEvent.php',
+		'LoggerMDC' => '/LoggerMDC.php',
+		'LoggerNDC' => '/LoggerNDC.php',
+		'LoggerLayout' => '/LoggerLayout.php',
+		'LoggerReflectionUtils' => '/LoggerReflectionUtils.php',
+		'LoggerRoot' => '/LoggerRoot.php',
+		'LoggerThrowableInformation' => '/LoggerThrowableInformation.php',
+
+		// Appenders
 		'LoggerAppenderAMQP' => '/appenders/LoggerAppenderAMQP.php',
-		'LoggerAppenderConsole' => '/appenders/LoggerAppenderConsole.php',

-		'LoggerAppenderDailyFile' => '/appenders/LoggerAppenderDailyFile.php',

-		'LoggerAppenderEcho' => '/appenders/LoggerAppenderEcho.php',

-		'LoggerAppenderFile' => '/appenders/LoggerAppenderFile.php',

+		'LoggerAppenderConsole' => '/appenders/LoggerAppenderConsole.php',
+		'LoggerAppenderDailyFile' => '/appenders/LoggerAppenderDailyFile.php',
+		'LoggerAppenderEcho' => '/appenders/LoggerAppenderEcho.php',
+		'LoggerAppenderFile' => '/appenders/LoggerAppenderFile.php',
 		'LoggerAppenderGraylog2' => '/appenders/LoggerAppenderGraylog2.php',
-		'LoggerAppenderMail' => '/appenders/LoggerAppenderMail.php',

-		'LoggerAppenderMailEvent' => '/appenders/LoggerAppenderMailEvent.php',

-		'LoggerAppenderMongoDB' => '/appenders/LoggerAppenderMongoDB.php',

-		'LoggerAppenderNull' => '/appenders/LoggerAppenderNull.php',

-		'LoggerAppenderFirePHP' => '/appenders/LoggerAppenderFirePHP.php',

-		'LoggerAppenderPDO' => '/appenders/LoggerAppenderPDO.php',

-		'LoggerAppenderPhp' => '/appenders/LoggerAppenderPhp.php',

-		'LoggerAppenderRollingFile' => '/appenders/LoggerAppenderRollingFile.php',

-		'LoggerAppenderSocket' => '/appenders/LoggerAppenderSocket.php',

-		'LoggerAppenderSyslog' => '/appenders/LoggerAppenderSyslog.php',

-		

-		// Configurators

-		'LoggerConfigurationAdapter' => '/configurators/LoggerConfigurationAdapter.php',

-		'LoggerConfigurationAdapterINI' => '/configurators/LoggerConfigurationAdapterINI.php',

-		'LoggerConfigurationAdapterPHP' => '/configurators/LoggerConfigurationAdapterPHP.php',

-		'LoggerConfigurationAdapterXML' => '/configurators/LoggerConfigurationAdapterXML.php',

-		'LoggerConfiguratorDefault' => '/configurators/LoggerConfiguratorDefault.php',

-

-		// Filters

-		'LoggerFilterDenyAll' => '/filters/LoggerFilterDenyAll.php',

-		'LoggerFilterLevelMatch' => '/filters/LoggerFilterLevelMatch.php',

-		'LoggerFilterLevelRange' => '/filters/LoggerFilterLevelRange.php',

-		'LoggerFilterStringMatch' => '/filters/LoggerFilterStringMatch.php',

-

-		// Helpers

-		'LoggerFormattingInfo' => '/helpers/LoggerFormattingInfo.php',

-		'LoggerOptionConverter' => '/helpers/LoggerOptionConverter.php',

-		'LoggerPatternParser' => '/helpers/LoggerPatternParser.php',

-		'LoggerUtils' => '/helpers/LoggerUtils.php',

-	

-		// Pattern converters

-		'LoggerPatternConverter' => '/pattern/LoggerPatternConverter.php',

-		'LoggerPatternConverterClass' => '/pattern/LoggerPatternConverterClass.php',

-		'LoggerPatternConverterCookie' => '/pattern/LoggerPatternConverterCookie.php',

-		'LoggerPatternConverterDate' => '/pattern/LoggerPatternConverterDate.php',

-		'LoggerPatternConverterEnvironment' => '/pattern/LoggerPatternConverterEnvironment.php',

-		'LoggerPatternConverterFile' => '/pattern/LoggerPatternConverterFile.php',

-		'LoggerPatternConverterLevel' => '/pattern/LoggerPatternConverterLevel.php',

-		'LoggerPatternConverterLine' => '/pattern/LoggerPatternConverterLine.php',

-		'LoggerPatternConverterLiteral' => '/pattern/LoggerPatternConverterLiteral.php',

-		'LoggerPatternConverterLocation' => '/pattern/LoggerPatternConverterLocation.php',

-		'LoggerPatternConverterLogger' => '/pattern/LoggerPatternConverterLogger.php',

-		'LoggerPatternConverterMDC' => '/pattern/LoggerPatternConverterMDC.php',

-		'LoggerPatternConverterMessage' => '/pattern/LoggerPatternConverterMessage.php',

-		'LoggerPatternConverterMethod' => '/pattern/LoggerPatternConverterMethod.php',

-		'LoggerPatternConverterNDC' => '/pattern/LoggerPatternConverterNDC.php',

-		'LoggerPatternConverterNewLine' => '/pattern/LoggerPatternConverterNewLine.php',

-		'LoggerPatternConverterProcess' => '/pattern/LoggerPatternConverterProcess.php',

-		'LoggerPatternConverterRelative' => '/pattern/LoggerPatternConverterRelative.php',

-		'LoggerPatternConverterRequest' => '/pattern/LoggerPatternConverterRequest.php',

-		'LoggerPatternConverterServer' => '/pattern/LoggerPatternConverterServer.php',

-		'LoggerPatternConverterSession' => '/pattern/LoggerPatternConverterSession.php',

-		'LoggerPatternConverterSessionID' => '/pattern/LoggerPatternConverterSessionID.php',

-		'LoggerPatternConverterSuperglobal' => '/pattern/LoggerPatternConverterSuperglobal.php',

-		'LoggerPatternConverterThrowable' => '/pattern/LoggerPatternConverterThrowable.php',

-		

-		// Layouts

+		'LoggerAppenderMail' => '/appenders/LoggerAppenderMail.php',
+		'LoggerAppenderMailEvent' => '/appenders/LoggerAppenderMailEvent.php',
+		'LoggerAppenderMongoDB' => '/appenders/LoggerAppenderMongoDB.php',
+		'LoggerAppenderNull' => '/appenders/LoggerAppenderNull.php',
+		'LoggerAppenderFirePHP' => '/appenders/LoggerAppenderFirePHP.php',
+		'LoggerAppenderPDO' => '/appenders/LoggerAppenderPDO.php',
+		'LoggerAppenderPhp' => '/appenders/LoggerAppenderPhp.php',
+		'LoggerAppenderRollingFile' => '/appenders/LoggerAppenderRollingFile.php',
+		'LoggerAppenderSocket' => '/appenders/LoggerAppenderSocket.php',
+		'LoggerAppenderSyslog' => '/appenders/LoggerAppenderSyslog.php',
+
+		// Configurators
+		'LoggerConfigurationAdapter' => '/configurators/LoggerConfigurationAdapter.php',
+		'LoggerConfigurationAdapterINI' => '/configurators/LoggerConfigurationAdapterINI.php',
+		'LoggerConfigurationAdapterPHP' => '/configurators/LoggerConfigurationAdapterPHP.php',
+		'LoggerConfigurationAdapterXML' => '/configurators/LoggerConfigurationAdapterXML.php',
+		'LoggerConfiguratorDefault' => '/configurators/LoggerConfiguratorDefault.php',
+
+		// Filters
+		'LoggerFilterDenyAll' => '/filters/LoggerFilterDenyAll.php',
+		'LoggerFilterLevelMatch' => '/filters/LoggerFilterLevelMatch.php',
+		'LoggerFilterLevelRange' => '/filters/LoggerFilterLevelRange.php',
+		'LoggerFilterStringMatch' => '/filters/LoggerFilterStringMatch.php',
+
+		// Helpers
+		'LoggerFormattingInfo' => '/helpers/LoggerFormattingInfo.php',
+		'LoggerMailerInterface' => '/helpers/LoggerMailerInterface.php',
+		'LoggerMailerPHP' => '/helpers/LoggerMailerPHP.php',
+		'LoggerOptionConverter' => '/helpers/LoggerOptionConverter.php',
+		'LoggerPatternParser' => '/helpers/LoggerPatternParser.php',
+		'LoggerUtils' => '/helpers/LoggerUtils.php',
+
+		// Pattern converters
+		'LoggerPatternConverter' => '/pattern/LoggerPatternConverter.php',
+		'LoggerPatternConverterClass' => '/pattern/LoggerPatternConverterClass.php',
+		'LoggerPatternConverterCookie' => '/pattern/LoggerPatternConverterCookie.php',
+		'LoggerPatternConverterDate' => '/pattern/LoggerPatternConverterDate.php',
+		'LoggerPatternConverterEnvironment' => '/pattern/LoggerPatternConverterEnvironment.php',
+		'LoggerPatternConverterFile' => '/pattern/LoggerPatternConverterFile.php',
+		'LoggerPatternConverterLevel' => '/pattern/LoggerPatternConverterLevel.php',
+		'LoggerPatternConverterLine' => '/pattern/LoggerPatternConverterLine.php',
+		'LoggerPatternConverterLiteral' => '/pattern/LoggerPatternConverterLiteral.php',
+		'LoggerPatternConverterLocation' => '/pattern/LoggerPatternConverterLocation.php',
+		'LoggerPatternConverterLogger' => '/pattern/LoggerPatternConverterLogger.php',
+		'LoggerPatternConverterMDC' => '/pattern/LoggerPatternConverterMDC.php',
+		'LoggerPatternConverterMessage' => '/pattern/LoggerPatternConverterMessage.php',
+		'LoggerPatternConverterMethod' => '/pattern/LoggerPatternConverterMethod.php',
+		'LoggerPatternConverterNDC' => '/pattern/LoggerPatternConverterNDC.php',
+		'LoggerPatternConverterNewLine' => '/pattern/LoggerPatternConverterNewLine.php',
+		'LoggerPatternConverterProcess' => '/pattern/LoggerPatternConverterProcess.php',
+		'LoggerPatternConverterRelative' => '/pattern/LoggerPatternConverterRelative.php',
+		'LoggerPatternConverterRequest' => '/pattern/LoggerPatternConverterRequest.php',
+		'LoggerPatternConverterServer' => '/pattern/LoggerPatternConverterServer.php',
+		'LoggerPatternConverterSession' => '/pattern/LoggerPatternConverterSession.php',
+		'LoggerPatternConverterSessionID' => '/pattern/LoggerPatternConverterSessionID.php',
+		'LoggerPatternConverterSuperglobal' => '/pattern/LoggerPatternConverterSuperglobal.php',
+		'LoggerPatternConverterThrowable' => '/pattern/LoggerPatternConverterThrowable.php',
+
+		// Layouts
 		'LoggerLayoutGelf' => '/layouts/LoggerLayoutGelf.php',
-		'LoggerLayoutHtml' => '/layouts/LoggerLayoutHtml.php',

-		'LoggerLayoutPattern' => '/layouts/LoggerLayoutPattern.php',

-		'LoggerLayoutSerialized' => '/layouts/LoggerLayoutSerialized.php',

-		'LoggerLayoutSimple' => '/layouts/LoggerLayoutSimple.php',

-		'LoggerLayoutTTCC' => '/layouts/LoggerLayoutTTCC.php',

-		'LoggerLayoutXml' => '/layouts/LoggerLayoutXml.php',

-		

-		// Renderers

-		'LoggerRendererDefault' => '/renderers/LoggerRendererDefault.php',

-		'LoggerRendererException' => '/renderers/LoggerRendererException.php',

-		'LoggerRendererMap' => '/renderers/LoggerRendererMap.php',

-		'LoggerRenderer' => '/renderers/LoggerRenderer.php',

-	);

-	

-	/**

-	 * Loads a class.

-	 * @param string $className The name of the class to load.

-	 */

-	public static function autoload($className) {

-		if(isset(self::$classes[$className])) {

-			include dirname(__FILE__) . self::$classes[$className];

-		}

-	}

-}

+		'LoggerLayoutHtml' => '/layouts/LoggerLayoutHtml.php',
+		'LoggerLayoutPattern' => '/layouts/LoggerLayoutPattern.php',
+		'LoggerLayoutSerialized' => '/layouts/LoggerLayoutSerialized.php',
+		'LoggerLayoutSimple' => '/layouts/LoggerLayoutSimple.php',
+		'LoggerLayoutTTCC' => '/layouts/LoggerLayoutTTCC.php',
+		'LoggerLayoutXml' => '/layouts/LoggerLayoutXml.php',
+
+		// Renderers
+		'LoggerRendererDefault' => '/renderers/LoggerRendererDefault.php',
+		'LoggerRendererException' => '/renderers/LoggerRendererException.php',
+		'LoggerRendererMap' => '/renderers/LoggerRendererMap.php',
+		'LoggerRenderer' => '/renderers/LoggerRenderer.php',
+	);
+
+	/**
+	 * Loads a class.
+	 * @param string $className The name of the class to load.
+	 */
+	public static function autoload($className) {
+		if(isset(self::$classes[$className])) {
+			include dirname(__FILE__) . self::$classes[$className];
+		}
+	}
+}
diff --git a/src/main/php/appenders/LoggerAppenderMail.php b/src/main/php/appenders/LoggerAppenderMail.php
index c93f518..00ec22e 100644
--- a/src/main/php/appenders/LoggerAppenderMail.php
+++ b/src/main/php/appenders/LoggerAppenderMail.php
@@ -19,22 +19,22 @@
 /**
  * LoggerAppenderMail appends log events via email.
  *
- * This appender does not send individual emails for each logging requests but 
- * will collect them in a buffer and send them all in a single email once the 
- * appender is closed (i.e. when the script exists). Because of this, it may 
- * not appropriate for long running scripts, in which case 
+ * This appender does not send individual emails for each logging requests but
+ * will collect them in a buffer and send them all in a single email once the
+ * appender is closed (i.e. when the script exists). Because of this, it may
+ * not appropriate for long running scripts, in which case
  * LoggerAppenderMailEvent might be a better choice.
- * 
+ *
  * This appender uses a layout.
- * 
+ *
  * ## Configurable parameters: ##
- * 
- * - **to** - Email address(es) to which the log will be sent. Multiple email 
+ *
+ * - **to** - Email address(es) to which the log will be sent. Multiple email
  *     addresses may be specified by separating them with a comma.
  * - **from** - Email address which will be used in the From field.
  * - **subject** - Subject of the email message.
  * - **bufferSize** - Output buffer size. Number of messages sent together.
- * 
+ *
  * @package log4php
  * @subpackage appenders
  * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
@@ -42,30 +42,30 @@
  */
 class LoggerAppenderMail extends LoggerAppender {
 
-	/** 
+	/**
 	 * Email address to put in From field of the email.
 	 * @var string
 	 */
 	protected $from;
 
-	/** 
+	/**
 	 * The subject of the email.
 	 * @var string
 	 */
 	protected $subject = 'Log4php Report';
-	
+
 	/**
-	 * One or more comma separated email addresses to which to send the email. 
+	 * One or more comma separated email addresses to which to send the email.
 	 * @var string
 	 */
 	protected $to;
 
-	/** 
-	 * Buffer which holds the email contents before it is sent. 
-	 * @var string  
+	/**
+	 * Buffer which holds the email contents before it is sent.
+	 * @var string
 	 */
 	protected $body = '';
-	
+
 	/**
 	 * Output buffer size. Number of meessages kept in buffer before sending.
 	 * @var integer
@@ -78,6 +78,12 @@
 	 */
 	protected $bufferCount = 0;
 
+	/**
+	 * Class used to send emails.
+	 * @var LoggerMailerInterface
+	 */
+	protected $mailer;
+
 	public function append(LoggerLoggingEvent $event) {
 		$this->body .= $this->layout->format($event);
 		$this->bufferCount += 1;
@@ -97,8 +103,11 @@
 			$this->closed = true;
 			return;
 		}
+		if (empty($this->mailer)) {
+			$this->mailer = new LoggerMailerPHP();
+		}
 	}
-	
+
 	public function close() {
 		if(!$this->closed) {
 			if(!empty($this->body)) {
@@ -115,7 +124,7 @@
 		$headers = "From: {$this->from}\r\n";
 		$headers .= "Content-Type: {$contentType}\r\n";
 
-		$success = mail($this->to, $this->subject, $message, $headers);
+		$success = $this->mailer->send($this->to, $this->subject, $message, $headers);
 		if ($success === false) {
 			$this->warn("Failed sending email. Please check your php.ini settings. Closing appender.");
 			$this->closed = true;
@@ -124,22 +133,22 @@
 		$this->bufferCount = 0;
 		$this->body = '';
 	}
-	
+
 	/** Sets the 'subject' parameter. */
 	public function setSubject($subject) {
 		$this->setString('subject', $subject);
 	}
-	
+
 	/** Returns the 'subject' parameter. */
 	public function getSubject() {
 		return $this->subject;
 	}
-	
+
 	/** Sets the 'to' parameter. */
 	public function setTo($to) {
 		$this->setString('to', $to);
 	}
-	
+
 	/** Returns the 'to' parameter. */
 	public function getTo() {
 		return $this->to;
@@ -149,7 +158,7 @@
 	public function setFrom($from) {
 		$this->setString('from', $from);
 	}
-	
+
 	/** Returns the 'from' parameter. */
 	public function getFrom() {
 		return $this->from;
@@ -164,4 +173,14 @@
 	public function getBufferSize() {
 		return $this->bufferSize;
 	}
+
+	/** Sets the 'bufferSize' parameter. */
+	public function setMailer(LoggerMailerInterface $mailer) {
+		$this->mailer = $mailer;
+	}
+
+	/** Returns the 'mailer' parameter. */
+	public function getMailer() {
+		return $this->mailer;
+	}
 }
diff --git a/src/main/php/helpers/LoggerMailerInterface.php b/src/main/php/helpers/LoggerMailerInterface.php
new file mode 100644
index 0000000..b5bb002
--- /dev/null
+++ b/src/main/php/helpers/LoggerMailerInterface.php
@@ -0,0 +1,32 @@
+<?php
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * @package log4php
+ */
+
+/**
+ * Interface for a mail sending class.
+ *
+ * @package log4php
+ * @subpackage helpers
+ * @since 2.4.0
+ */
+interface LoggerMailerInterface {
+
+    public function send($to, $subject, $message, $headers = "");
+
+}
diff --git a/src/main/php/helpers/LoggerMailerPHP.php b/src/main/php/helpers/LoggerMailerPHP.php
new file mode 100644
index 0000000..1d35587
--- /dev/null
+++ b/src/main/php/helpers/LoggerMailerPHP.php
@@ -0,0 +1,34 @@
+<?php
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * @package log4php
+ */
+
+/**
+ * A mailer which uses mail() to dispatch emails.
+ *
+ * @package log4php
+ * @subpackage helpers
+ * @since 2.4.0
+ */
+class LoggerMailerPHP implements LoggerMailerInterface {
+
+    public function send($to, $subject, $message, $headers = "") {
+
+        return mail($to, $subject, $message, $headers);
+    }
+}
diff --git a/src/test/php/appenders/LoggerAppenderMailTest.php b/src/test/php/appenders/LoggerAppenderMailTest.php
index a949258..bcdfcec 100644
--- a/src/test/php/appenders/LoggerAppenderMailTest.php
+++ b/src/test/php/appenders/LoggerAppenderMailTest.php
@@ -22,6 +22,26 @@
  * @link       http://logging.apache.org/log4php
  */
 
+/** A mock mailer class which always reports success. */
+class LoggerMailerMockSuccess implements LoggerMailerInterface {
+
+	/** Counts how many times send was called. */
+	public $count = 0;
+
+	public function send($to, $subject, $message, $headers = "") {
+		$this->count++;
+		return true;
+	}
+}
+
+/** A mock mailer class which always reports failure. */
+class LoggerMailerMockFailure implements LoggerMailerInterface {
+
+	public function send($to, $subject, $message, $headers = "") {
+		return false;
+	}
+}
+
 /**
  * @group appenders
  */
@@ -32,11 +52,109 @@
 		self::assertTrue($appender->requiresLayout());
 	}
 
+	/** For greater coverge! */
+	public function testAccessors() {
+
+		$buffer = 10;
+		$from = 'log4php@localhost';
+		$mailer = new LoggerMailerPHP();
+		$subject = "Subject";
+		$to = 'log4php@target';
+
+		$appender = new LoggerAppenderMail("testAppender");
+		$appender->setBufferSize($buffer);
+		$appender->setFrom($from);
+		$appender->setMailer($mailer);
+		$appender->setSubject($subject);
+		$appender->setTo($to);
+		$appender->activateOptions();
+
+		$this->assertSame($buffer, $appender->getBufferSize());
+		$this->assertSame($from, $appender->getFrom());
+		$this->assertSame($mailer, $appender->getMailer());
+		$this->assertSame($subject, $appender->getSubject());
+		$this->assertSame($to, $appender->getTo());
+	}
+
+	public function testDefaultMailer() {
+
+		$appender = new LoggerAppenderMail("testAppender");
+		$appender->setTo('log4php@gmail.com');
+		$appender->setFrom('log4php@localhost');
+		$appender->activateOptions();
+
+		$this->assertInstanceOf('LoggerMailerInterface', $appender->getMailer());
+	}
+
 	public function testMail() {
+		$mockMailer = new LoggerMailerMockSuccess();
+
+		$this->assertSame(0, $mockMailer->count);
+
 		$appender = new LoggerAppenderMail("testAppender");
 		$appender->setTo('log4php@gmail.com');
 		$appender->setFrom('log4php@localhost');
 		$appender->setSubject("Testing text/plain " . date('Y-m-d H:i:s'));
+		$appender->setMailer($mockMailer);
+		$appender->activateOptions();
+
+		$appender->append(LoggerTestHelper::getTraceEvent('tracing'));
+		$appender->append(LoggerTestHelper::getDebugEvent('debugging'));
+		$appender->append(LoggerTestHelper::getInfoEvent('informing'));
+		$appender->append(LoggerTestHelper::getWarnEvent('warning'));
+		$appender->append(LoggerTestHelper::getErrorEvent('erring'));
+		$appender->append(LoggerTestHelper::getFatalEvent('fatality!'));
+
+		$this->assertSame(0, $mockMailer->count);
+		$appender->close();
+		$this->assertSame(1, $mockMailer->count);
+	}
+
+	public function testMailBuffered() {
+		$mockMailer = new LoggerMailerMockSuccess();
+
+		$appender = new LoggerAppenderMail("testAppender");
+		$appender->setTo('log4php@gmail.com');
+		$appender->setFrom('log4php@localhost');
+		$appender->setSubject("Testing text/plain " . date('Y-m-d H:i:s'));
+		$appender->setBufferSize(4);
+		$appender->setMailer($mockMailer);
+		$appender->activateOptions();
+
+		// Buffer should be cleared after 4 log messages
+
+		$this->assertSame(0, $mockMailer->count);
+
+		$appender->append(LoggerTestHelper::getTraceEvent('tracing'));
+		$appender->append(LoggerTestHelper::getDebugEvent('debugging'));
+		$appender->append(LoggerTestHelper::getInfoEvent('informing'));
+
+		$this->assertSame(0, $mockMailer->count);
+
+		$appender->append(LoggerTestHelper::getWarnEvent('warning'));
+		$appender->append(LoggerTestHelper::getErrorEvent('erring'));
+
+		$this->assertSame(1, $mockMailer->count);
+
+		$appender->append(LoggerTestHelper::getFatalEvent('fatality!'));
+
+		$this->assertSame(1, $mockMailer->count);
+
+		// Close should send the remaining messages in buffer
+		$appender->close();
+
+		$this->assertSame(2, $mockMailer->count);
+	}
+
+	public function testMailHTML() {
+		$mockMailer = new LoggerMailerMockSuccess();
+
+		$appender = new LoggerAppenderMail("testAppender");
+		$appender->setLayout(new LoggerLayoutHtml());
+		$appender->setTo('log4php@gmail.com');
+		$appender->setFrom('log4php@localhost');
+		$appender->setSubject("Testing text/html " . date('Y-m-d H:i:s'));
+		$appender->setMailer($mockMailer);
 		$appender->activateOptions();
 
 		$appender->append(LoggerTestHelper::getTraceEvent('tracing'));
@@ -48,21 +166,22 @@
 		$appender->close();
 	}
 
-	public function testMailHTML() {
+	/**
+	 * @expectedException PHPUnit_Framework_Error
+	 * @expectedExceptionMessage Failed sending email. Please check your php.ini settings. Closing appender.
+	 */
+	public function testMailerError() {
+		$mockMailer = new LoggerMailerMockFailure();
+
 		$appender = new LoggerAppenderMail("testAppender");
 		$appender->setLayout(new LoggerLayoutHtml());
 		$appender->setTo('log4php@gmail.com');
 		$appender->setFrom('log4php@localhost');
 		$appender->setSubject("Testing text/html " . date('Y-m-d H:i:s'));
+		$appender->setMailer($mockMailer);
 		$appender->activateOptions();
 
 		$appender->append(LoggerTestHelper::getTraceEvent('tracing'));
-		$appender->append(LoggerTestHelper::getDebugEvent('debugging'));
-		$appender->append(LoggerTestHelper::getInfoEvent('informing'));
-		$appender->append(LoggerTestHelper::getWarnEvent('warning'));
-		$appender->append(LoggerTestHelper::getErrorEvent('erring'));
-		$appender->append(LoggerTestHelper::getFatalEvent('fatality!'));
-		$appender->close();
 	}
 
 	/**