3 +--------------------------------------------------------------------+
4 | Copyright CiviCRM LLC. All rights reserved. |
6 | This work is published under the GNU AGPLv3 license with some |
7 | permitted exceptions and without any warranty. For full license |
8 | and copyright information, see https://civicrm.org/licensing |
9 +--------------------------------------------------------------------+
13 * Mail utils for use during unit testing to allow retrieval
14 * and examination of 'sent' emails.
18 * $mut = new CiviMailUtils( $this, true ); //true automatically starts spooling
20 * $msg = $mut->getMostRecentEmail( 'raw' ); // or 'ezc' to get an ezc mail object
21 * ... assert stuff about $msg ...
31 class CiviMailUtils
extends PHPUnit\Framework\TestCase
{
34 * Current outbound email option
37 protected $_outBound_option = NULL;
42 * @param CiviUnitTestCase $unit_test The currently running test
43 * @param bool $startImmediately
44 * Start writing to db now or wait until start() is called.
46 public function __construct(&$unit_test, $startImmediately = TRUE) {
47 $this->_ut
= $unit_test;
49 if ($startImmediately) {
55 * Clean up after test.
57 * @throws \CRM_Core_Exception
59 public function __destruct() {
61 $this->clearMessages();
65 * Start writing emails to db instead of current option.
67 public function start() {
68 // save current setting for outbound option, then change it
69 $mailingBackend = CRM_Core_BAO_Setting
::getItem(CRM_Core_BAO_Setting
::MAILING_PREFERENCES_NAME
,
73 $this->_outBound_option
= $mailingBackend['outBound_option'];
74 $mailingBackend['outBound_option'] = CRM_Mailing_Config
::OUTBOUND_OPTION_REDIRECT_TO_DB
;
76 Civi
::settings()->set('mailing_backend', $mailingBackend);
78 $mailingBackend = CRM_Core_BAO_Setting
::getItem(CRM_Core_BAO_Setting
::MAILING_PREFERENCES_NAME
,
83 public function stop() {
84 $mailingBackend = CRM_Core_BAO_Setting
::getItem(CRM_Core_BAO_Setting
::MAILING_PREFERENCES_NAME
,
88 $mailingBackend['outBound_option'] = $this->_outBound_option
;
90 Civi
::settings()->set('mailing_backend', $mailingBackend);
96 * @return ezcMail|string
98 public function getMostRecentEmail($type = 'raw') {
101 $dao = CRM_Core_DAO
::executeQuery('SELECT headers, body FROM civicrm_mailing_spool ORDER BY id DESC LIMIT 1');
103 $msg = $dao->headers
. "\n\n" . $dao->body
;
112 $msg = $this->convertToEzc($msg);
119 * @param string $type
122 * @throws CRM_Core_Exception
124 * @return array(ezcMail)|array(string)
126 public function getAllMessages($type = 'raw') {
129 $dao = CRM_Core_DAO
::executeQuery('SELECT headers, body FROM civicrm_mailing_spool ORDER BY id');
130 while ($dao->fetch()) {
131 $msgs[] = $dao->headers
. "\n\n" . $dao->body
;
140 foreach ($msgs as $i => $msg) {
141 $msgs[$i] = $this->convertToEzc($msg);
150 * Utility functions (previously part of CiviUnitTestCase)
151 * Included for backward compatibility with existing tests.
155 * Check contents of mail log.
157 * @param array $strings
158 * Strings that should be included.
159 * @param array $absentStrings
160 * Strings that should not be included.
161 * @param string $prefix
163 * @return \ezcMail|string
165 public function checkMailLog($strings, $absentStrings = [], $prefix = '') {
166 $mail = $this->getMostRecentEmail('raw');
167 return $this->checkMailForStrings($strings, $absentStrings, $prefix, $mail);
171 * Check contents of mail log.
173 * @param array $strings
174 * Strings that should be included.
175 * @param array $absentStrings
176 * Strings that should not be included.
177 * @param string $prefix
179 * @return \ezcMail|string
181 public function checkAllMailLog($strings, $absentStrings = [], $prefix = '') {
182 $mails = $this->getAllMessages('raw');
183 $mail = implode(',', $mails);
184 return $this->checkMailForStrings($strings, $absentStrings, $prefix, $mail);
188 * Check that mail log is empty.
189 * @param string $prefix
191 public function assertMailLogEmpty($prefix = '') {
192 $mail = $this->getMostRecentEmail('raw');
193 $this->_ut
->assertEmpty($mail, 'mail sent when it should not have been ' . $prefix);
197 * Assert that $expectedRecipients (and no else) have received emails
199 * @param array $expectedRecipients
200 * Array($msgPos => array($recipPos => $emailAddr)).
202 public function assertRecipients($expectedRecipients) {
204 foreach ($this->getAllMessages('ezc') as $message) {
205 $recipients[] = CRM_Utils_Array
::collect('email', $message->to
);
207 $cmp = function($a, $b) {
208 if ($a[0] == $b[0]) {
211 return ($a[0] < $b[0]) ?
1 : -1;
213 usort($recipients, $cmp);
214 usort($expectedRecipients, $cmp);
215 $this->_ut
->assertEquals(
218 "Incorrect recipients: " . print_r(array('expected' => $expectedRecipients, 'actual' => $recipients), TRUE)
223 * Assert that $expectedSubjects (and no other subjects) were sent.
225 * @param array $expectedSubjects
226 * Array(string $subj).
228 public function assertSubjects($expectedSubjects) {
230 foreach ($this->getAllMessages('ezc') as $message) {
231 /** @var ezcMail $message */
232 $subjects[] = $message->subject
;
235 sort($expectedSubjects);
236 $this->_ut
->assertEquals(
239 "Incorrect subjects: " . print_r(array('expected' => $expectedSubjects, 'actual' => $subjects), TRUE)
244 * Remove any sent messages from the log.
247 * How many recent messages to remove, defaults to 0 (all).
249 * @throws \CRM_Core_Exception
251 public function clearMessages($limit = 0) {
252 $sql = 'DELETE FROM civicrm_mailing_spool ORDER BY id DESC';
254 $sql .= ' LIMIT ' . $limit;
256 CRM_Core_DAO
::executeQuery($sql);
261 * Email header and body.
264 private function convertToEzc($msg) {
265 $set = new ezcMailVariableSet($msg);
266 $parser = new ezcMailParser();
267 $mail = $parser->parseMail($set);
268 $this->_ut
->assertNotEmpty($mail, 'Cannot parse mail');
273 * @param array $strings
274 * @param $absentStrings
279 public function checkMailForStrings(array $strings, $absentStrings, $prefix, $mail) {
280 foreach ($strings as $string) {
281 $this->_ut
->assertStringContainsString($string, $mail, "$string . not found in $mail $prefix");
283 foreach ($absentStrings as $string) {
284 $this->_ut
->assertEmpty(strstr($mail, $string), "$string incorrectly found in $mail $prefix");