Merge pull request #462 from splitbrain/mail_headers_ex

Updates to mailer and subscription classes to improve testability
This commit is contained in:
Andreas Gohr 2013-12-15 12:44:50 -08:00
commit 00fe8cd9e0
3 changed files with 191 additions and 13 deletions

View File

@ -4,6 +4,9 @@
* Extends the mailer class to expose internal variables for testing
*/
class TestMailer extends Mailer {
public $use_mock_mail = true;
public $msgs = array();
public function prop($name){
return $this->$name;
}
@ -20,6 +23,15 @@ class TestMailer extends Mailer {
parent::cleanHeaders();
}
protected function _mail($to, $subject, $body, $headers, $sendparam=null){
if ($this->use_mock_mail) {
$this->msgs[] = compact('to','subject','body','headers','sendparam');
return true;
} else {
return parent::_mail($to, $subject, $body, $headers, $sendparam);
}
}
}
class mailer_test extends DokuWikiTest {
@ -169,6 +181,37 @@ class mailer_test extends DokuWikiTest {
$this->assertEquals(0, preg_match('/(^|\n)To: (\n|$)/', $header), 'To found in headers.');
}
function test_MultipleHeaderInstances() {
$mail = new TestMailer();
$mail->setHeader('X-Count',array("1","2"));
$mail->cleanHeaders();
$header = $mail->prepareHeaders();
$this->assertEquals(2, preg_match_all('/(^|\n)X-Count: \d/', $header), "X-Count header count incorrect.");
}
function test_ZeroHeaders() {
$mail = new TestMailer();
$mail->setHeader('X-Zero-String',array("0"));
$mail->setHeader('X-Zero-Int',array(0));
$mail->setHeader('X-Zero-Float',array(0.0));
$mail->cleanHeaders();
$header = $mail->prepareHeaders();
$this->assertEquals(1, preg_match_all('/(^|\n)X-Zero-String: \d/', $header), "X-ZeroString header count incorrect.");
$this->assertEquals(1, preg_match_all('/(^|\n)X-Zero-Int: \d/', $header), "X-ZeroInt header count incorrect.");
$this->assertEquals(1, preg_match_all('/(^|\n)X-Zero-Float: [\d.]+/', $header), "X-ZeroFloat header count incorrect.");
}
/**
* only one subject should end up in the cleaned & prep'd headers
*/
function test_multipleSubjects() {
$mail = new TestMailer();
$mail->subject(array("foo","bar"));
$mail->cleanHeaders();
$header = $mail->prepareHeaders();
$this->assertEquals(1, preg_match_all('/(^|\n)Subject: /', $header), "multiple Subject: headers found.");
}
/**
* @group internet
*/
@ -229,7 +272,103 @@ class mailer_test extends DokuWikiTest {
throw new Exception($line.$errorin);
}
}
}
/**
* check that Mailer is handing off the correct parameters to php's mail()
*/
function test_send() {
global $conf, $EVENT_HANDLER;
$old_conf = $conf;
$to = 'foo <foo@example.com>';
$from = 'Me <test@example.com>';
$subject = 'Subject';
$body = 'Hello Wörld';
$conf['title'] = 'MailTest';
global $EVENT_HANDLER;
$before = 0;
$after = 0;
$EVENT_HANDLER->register_hook('MAIL_MESSAGE_SEND', 'BEFORE', null,
function() use (&$before) {
$before++;
}
);
$EVENT_HANDLER->register_hook('MAIL_MESSAGE_SEND', 'AFTER', null,
function() use (&$after) {
$after++;
}
);
$mail = new TestMailer();
$mail->to(array($to));
$mail->from($from);
$mail->subject($subject);
$mail->setHeader('X-Mailer','DokuWiki Mail Tester');
$mail->setBody($body);
$mail->attachContent('some test data', 'text/plain', 'test.txt');
$ok = $mail->send();
// One and only one call to mail()
$this->assertTrue($ok, 'send failed');
$this->assertCount(1, $mail->msgs, 'mail() called '.count($mail->msgs).' times, should be 1');
// To: handling...
$this->assertEquals($to, $mail->msgs[0]['to'], '$to param not set correctly');
$this->assertEquals(0,preg_match('/(^|\n)To: /',$mail->msgs[0]['headers']), 'To: found in headers');
// Subject handling...
$this->assertEquals('[MailTest] '.$subject, $mail->msgs[0]['subject'], '$subject param not set correctly');
$this->assertEquals(0,preg_match('/(^|\n)Subject: /', $mail->msgs[0]['headers']), 'Subject: found in headers');
// headers present, just check "From: " & our "X-Mailer:"
$this->assertEquals(1, preg_match_all('/(^|\n)From: '.$from.'(\n|$)/', $mail->msgs[0]['headers']), 'From: missing from headers');
$this->assertEquals(1, preg_match_all('/(^|\n)X-Mailer: DokuWiki Mail Tester(\n|$)/', $mail->msgs[0]['headers']),'X-Mailer: header incorrect');
// body is present, contains our string and an attachment
$this->assertEquals(1, preg_match_all('/'.preg_quote(base64_encode($body),'/').'/', $mail->msgs[0]['body']),'expected content not found in $body param');
$this->assertEquals(1, preg_match_all('/Content-Disposition: attachment; filename=test.txt/', $mail->msgs[0]['body']),'expected attachment header not found in $body param');
// MAIL_MESSAGE_SEND triggered correctly
$this->assertEquals(1, $before, 'MAIL_MESSAGE_SEND.BEFORE event triggered '.$before.' times, should be 1');
$this->assertEquals(1, $after, 'MAIL_MESSAGE_SEND.AFTER event triggered '.$after.' times, should be 1');
$conf = $old_conf;
}
function test_dontsend_norecipients() {
$to = 'foo <foo@example.com>';
$from = 'Me <test@example.com>';
$subject = 'Subject';
$body = 'Hello Wörld';
$mail = new TestMailer();
$mail->from($from);
$mail->subject($subject);
$mail->setBody($body);
$ok = $mail->send();
$this->assertFalse($ok, 'Attempted send with no recipients');
}
function test_dontsend_nobody() {
$to = 'foo <foo@example.com>';
$from = 'Me <test@example.com>';
$subject = 'Subject';
$body = 'Hello Wörld';
$mail = new TestMailer();
$mail->to($to);
$mail->from($from);
$mail->subject($subject);
$ok = $mail->send();
$this->assertFalse($ok, 'Attempted send with no body');
}
}
//Setup VIM: ex: et ts=4 :

View File

@ -141,15 +141,15 @@ class Mailer {
// empty value deletes
if(is_array($value)){
$value = array_map('trim', $value);
$value = array_filter($value);
$value = array_filter($value, array($this, '_notEmpty'));
if(!$value) $value = '';
}else{
$value = trim($value);
}
if($value === '') {
if(isset($this->headers[$header])) unset($this->headers[$header]);
} else {
if($this->_notEmpty($value)) {
$this->headers[$header] = $value;
} else {
unset($this->headers[$header]);
}
}
@ -323,7 +323,7 @@ class Mailer {
* @param string $subject the mail subject
*/
public function subject($subject) {
$this->headers['Subject'] = $subject;
$this->setHeader('Subject', $subject, false);
}
/**
@ -530,6 +530,9 @@ class Mailer {
}
if(isset($this->headers['Subject'])) {
if (is_array($this->headers['Subject'])) {
$this->headers['Subject'] = reset($this->headers['Subject']);
}
// add prefix to subject
if(empty($conf['mailprefix'])) {
if(utf8_strlen($conf['title']) < 20) {
@ -576,8 +579,15 @@ class Mailer {
protected function prepareHeaders() {
$headers = '';
foreach($this->headers as $key => $val) {
if ($val === '' || is_null($val)) continue;
$headers .= $this->wrappedHeaderLine($key, $val);
if (is_array($val)) {
foreach ($val as $v) {
if ($this->_notEmpty($v)) {
$headers .= $this->wrappedHeaderLine($key, $v);
}
}
} else if ($this->_notEmpty($val)) {
$headers .= $this->wrappedHeaderLine($key, $val);
}
}
return $headers;
}
@ -667,14 +677,34 @@ class Mailer {
}
// send the thing
if(is_null($this->sendparam)) {
$success = @mail($to, $subject, $body, $headers);
} else {
$success = @mail($to, $subject, $body, $headers, $this->sendparam);
}
$success = $this->_mail($to, $subject, $body, $headers, $this->sendparam);
}
// any AFTER actions?
$evt->advise_after();
return $success;
}
/**
* wrapper for php mail() to support overriding in test suite
*/
protected function _mail($to, $subject, $body, $headers, $sendparam=null){
if (is_null($sendparam)){
$success = @mail($to, $subject, $body, $headers);
} else {
$success = @mail($to, $subject, $body, $headers, $this->sendparam);
}
return $success;
}
/**
* Test to see if header value is not empty. Empty values are:
* - an empty string, ''
* - null
*
* 0, 0.0 and "0" are not empty headers
*/
protected function _notEmpty($val) {
return !($val === '' || is_null($val));
}
}

View File

@ -17,6 +17,15 @@ class Subscription {
return actionOK('subscribe');
}
/**
* return a Mailer object
*
* used to support overriding in test suite
*/
protected function getMailer(){
return new Mailer();
}
/**
* Return the subscription meta file for the given ID
*
@ -593,7 +602,7 @@ class Subscription {
$text = rawLocale($template);
$subject = $lang['mail_'.$subject].' '.$context;
$mail = new Mailer();
$mail = $this->getMailer();
$mail->bcc($subscriber_mail);
$mail->subject($subject);
$mail->setBody($text, $trep, $hrep);