* the handle on the mail handler that we are using
* @var object
*/
- private static $_mail = NULL;
+ public static $_mail = NULL;
/**
* We only need one instance of this object. So we use the singleton
if ($mailingInfo['outBound_option'] == CRM_Mailing_Config::OUTBOUND_OPTION_REDIRECT_TO_DB ||
(defined('CIVICRM_MAILER_SPOOL') && CIVICRM_MAILER_SPOOL)
) {
- self::$_mail = new CRM_Mailing_BAO_Spool();
+ self::$_mail = self::_createMailer('CRM_Mailing_BAO_Spool', array());
}
elseif ($mailingInfo['outBound_option'] == CRM_Mailing_Config::OUTBOUND_OPTION_SMTP) {
if ($mailingInfo['smtpServer'] == '' || !$mailingInfo['smtpServer']) {
// CRM-9349
$params['persist'] = $persist;
- self::$_mail = Mail::factory('smtp', $params);
+ self::$_mail = self::_createMailer('smtp', $params);
}
elseif ($mailingInfo['outBound_option'] == CRM_Mailing_Config::OUTBOUND_OPTION_SENDMAIL) {
if ($mailingInfo['sendmail_path'] == '' ||
$params['sendmail_path'] = $mailingInfo['sendmail_path'];
$params['sendmail_args'] = $mailingInfo['sendmail_args'];
- self::$_mail = Mail::factory('sendmail', $params);
+ self::$_mail = self::_createMailer('sendmail', $params);
}
elseif ($mailingInfo['outBound_option'] == CRM_Mailing_Config::OUTBOUND_OPTION_MAIL) {
- $params = array();
- self::$_mail = Mail::factory('mail', $params);
+ self::$_mail = self::_createMailer('mail', array());
}
elseif ($mailingInfo['outBound_option'] == CRM_Mailing_Config::OUTBOUND_OPTION_MOCK) {
- self::$_mail = Mail::factory('mock', $params);
+ self::$_mail = self::_createMailer('mock', array());
}
- elseif ($mailingInfo['outBound_option'] == 2) {
+ elseif ($mailingInfo['outBound_option'] == CRM_Mailing_Config::OUTBOUND_OPTION_DISABLED) {
CRM_Core_Error::debug_log_message(ts('Outbound mail has been disabled. Click <a href=\'%1\'>Administer >> System Setting >> Outbound Email</a> to set the OutBound Email.', array(1 => CRM_Utils_System::url('civicrm/admin/setting/smtp', 'reset=1'))));
CRM_Core_Session::setStatus(ts('Outbound mail has been disabled. Click <a href=\'%1\'>Administer >> System Setting >> Outbound Email</a> to set the OutBound Email.', array(1 => CRM_Utils_System::url('civicrm/admin/setting/smtp', 'reset=1'))));
}
return self::$_mail;
}
+ /**
+ * @param string $driver 'CRM_Mailing_BAO_Spool' or a name suitable for Mail::factory()
+ * @param array $params
+ * @return Mail|NULL
+ */
+ public static function _createMailer($driver, $params) {
+ if ($driver == 'CRM_Mailing_BAO_Spool') {
+ $mailer = new CRM_Mailing_BAO_Spool($params);
+ } else {
+ $mailer = Mail::factory($driver, $params);
+ }
+ CRM_Utils_Hook::hook_civicrm_alterMailer($mailer, $driver, $params);
+ return $mailer;
+ }
+
/**
* delete the web server writable directories
*
--- /dev/null
+<?php
+
+/**
+ * This is a quick-and-dirty way to define a vaguely-class-ish structure. It's non-performant, abnormal,
+ * and not a complete OOP system. Only use for testing/mocking.
+ *
+ * @code
+ * $object = new CRM_Utils_FakeObject(array(
+ * 'doIt' => function() { print "It!\n"; }
+ * ));
+ * $object->doIt();
+ * @endcode
+ */
+class CRM_Utils_FakeObject {
+ function __construct($array) {
+ $this->array = $array;
+ }
+
+ function __call($name, $arguments) {
+ if (isset($this->array[$name]) && is_callable($this->array[$name])) {
+ return call_user_func_array($this->array[$name], $arguments);
+ } else {
+ throw new Exception("Call to unimplemented method: $name");
+ }
+ }
+}
\ No newline at end of file
self::$_nullObject, 'civicrm_alterBarcode');
}
+ /**
+ * Modify or replace the Mailer object used for outgoing mail.
+ *
+ * @param object $mailer
+ * The default mailer produced by normal configuration; a PEAR "Mail" class (like those returned by Mail::factory)
+ * @param string $driver
+ * The type of the default mailer (eg "smtp", "sendmail", "mock", "CRM_Mailing_BAO_Spool")
+ * @param array $params
+ * The default mailer config options
+ * @see Mail::factory
+ */
+ static function hook_civicrm_alterMailer(&$mailer, $driver, $params) {
+ return self::singleton()->invoke(3, $mailer, $driver, $params, self::$_nullObject, self::$_nullObject, 'civicrm_alterMailer');
+ }
+
/**
* This hook is called while building the core search query,
* so hook implementers can provide their own query objects which alters/extends core search.
--- /dev/null
+<?php
+
+require_once 'CiviTest/CiviUnitTestCase.php';
+
+class CRM_Core_Config_MailerTest extends CiviUnitTestCase {
+
+ /**
+ * @var array (string=>int) Keep count of the #times different functions are called
+ */
+ var $calls;
+
+ function setUp() {
+ $this->calls = array(
+ 'civicrm_alterMailer' => 0,
+ 'send' => 0,
+ );
+ parent::setUp();
+ }
+
+ function testHookAlterMailer() {
+ $test = $this;
+ $mockMailer = new CRM_Utils_FakeObject(array(
+ 'send' => function ($recipients, $headers, $body) use ($test) {
+ $test->calls['send']++;
+ $test->assertEquals(array('to@example.org'), $recipients);
+ $test->assertEquals('Subject Example', $headers['Subject']);
+ }
+ ));
+
+ CRM_Utils_Hook::singleton()->setHook('civicrm_alterMailer',
+ function (&$mailer, $driver, $params) use ($test, $mockMailer) {
+ $test->calls['civicrm_alterMailer']++;
+ $test->assertTrue(is_string($driver) && !empty($driver));
+ $test->assertTrue(is_array($params));
+ $test->assertTrue(is_callable(array($mailer, 'send')));
+ $mailer = $mockMailer;
+ }
+ );
+
+ $params = array();
+ $params['groupName'] = 'CRM_Core_Config_MailerTest';
+ $params['from'] = 'From Example <from@example.com>';
+ $params['toName'] = 'To Example';
+ $params['toEmail'] = 'to@example.org';
+ $params['subject'] = 'Subject Example';
+ $params['text'] = 'Example text';
+ $params['html'] = '<p>Example HTML</p>';
+ CRM_Utils_Mail::send($params);
+
+ $this->assertEquals(1, $this->calls['civicrm_alterMailer']);
+ $this->assertEquals(1, $this->calls['send']);
+
+ // once more, just to make sure the hooks are called right #times
+ CRM_Utils_Mail::send($params);
+ CRM_Utils_Mail::send($params);
+ $this->assertEquals(1, $this->calls['civicrm_alterMailer']);
+ $this->assertEquals(3, $this->calls['send']);
+ }
+
+}
// FIXME: look at it closer in second stage
// initialize the object once db is loaded
+ CRM_Core_Config::$_mail = NULL;
$config = CRM_Core_Config::singleton();
// when running unit tests, use mockup user framework