1<?php 2 3/** 4 * Extends the mailer class to expose internal variables for testing 5 */ 6class TestMailer extends Mailer { 7 public function prop($name){ 8 return $this->$name; 9 } 10 11 public function &propRef($name) { 12 return $this->$name; 13 } 14 15 public function prepareHeaders() { 16 return parent::prepareHeaders(); 17 } 18 19 public function cleanHeaders() { 20 parent::cleanHeaders(); 21 } 22 23} 24 25/** 26 * @group mailer_class 27 */ 28class mailer_test extends DokuWikiTest { 29 30 31 function test_userheader(){ 32 $mail = new TestMailer(); 33 $headers = $mail->prop('headers'); 34 $this->assertArrayNotHasKey('X-Dokuwiki-User',$headers); 35 36 $_SERVER['REMOTE_USER'] = 'andi'; 37 $mail = new TestMailer(); 38 $headers = $mail->prop('headers'); 39 $this->assertArrayHasKey('X-Dokuwiki-User',$headers); 40 } 41 42 function test_setHeader(){ 43 $mail = new TestMailer(); 44 45 // check existance of default headers 46 $headers = $mail->prop('headers'); 47 $this->assertArrayHasKey('X-Mailer',$headers); 48 $this->assertArrayHasKey('X-Dokuwiki-Title',$headers); 49 $this->assertArrayHasKey('X-Dokuwiki-Server',$headers); 50 $this->assertArrayHasKey('X-Auto-Response-Suppress',$headers); 51 $this->assertArrayHasKey('List-Id',$headers); 52 53 // set a bunch of test headers 54 $mail->setHeader('test-header','bla'); 55 $mail->setHeader('to','A valid ASCII name <test@example.com>'); 56 $mail->setHeader('from',"Thös ne\needs\x00serious cleaning\$§%."); 57 $mail->setHeader('bad',"Thös ne\needs\x00serious cleaning\$§%.",false); 58 $mail->setHeader("weird\n*+\x00foo.-_@bar?",'now clean'); 59 60 // are they set? 61 $headers = $mail->prop('headers'); 62 $this->assertArrayHasKey('Test-Header',$headers); 63 $this->assertEquals('bla',$headers['Test-Header']); 64 $this->assertArrayHasKey('To',$headers); 65 $this->assertEquals('A valid ASCII name <test@example.com>',$headers['To']); 66 $this->assertArrayHasKey('From',$headers); 67 $this->assertEquals('Ths neeedsserious cleaning.',$headers['From']); 68 $this->assertArrayHasKey('Bad',$headers); 69 $this->assertEquals("Thös ne\needs\x00serious cleaning\$§%.",$headers['Bad']); 70 $this->assertArrayHasKey('Weird+foo.-_@bar',$headers); 71 72 // unset a header again 73 $mail->setHeader('test-header',''); 74 $headers = $mail->prop('headers'); 75 $this->assertArrayNotHasKey('Test-Header',$headers); 76 } 77 78 function test_addresses(){ 79 if (isWindows()) { 80 $this->markTestSkipped(); 81 } 82 83 $mail = new TestMailer(); 84 85 $mail->to('andi@splitbrain.org'); 86 $mail->cleanHeaders(); 87 $headers = $mail->prop('headers'); 88 $this->assertEquals('andi@splitbrain.org', $headers['To']); 89 90 $mail->to('<andi@splitbrain.org>'); 91 $mail->cleanHeaders(); 92 $headers = $mail->prop('headers'); 93 $this->assertEquals('andi@splitbrain.org', $headers['To']); 94 95 $mail->to('Andreas Gohr <andi@splitbrain.org>'); 96 $mail->cleanHeaders(); 97 $headers = $mail->prop('headers'); 98 $this->assertEquals('Andreas Gohr <andi@splitbrain.org>', $headers['To']); 99 100 $mail->to('"Andreas Gohr" <andi@splitbrain.org>'); 101 $mail->cleanHeaders(); 102 $headers = $mail->prop('headers'); 103 $this->assertEquals('"Andreas Gohr" <andi@splitbrain.org>', $headers['To']); 104 105 $mail->to('Andreas Gohr <andi@splitbrain.org> , foo <foo@example.com>'); 106 $mail->cleanHeaders(); 107 $headers = $mail->prop('headers'); 108 $this->assertEquals('Andreas Gohr <andi@splitbrain.org>, foo <foo@example.com>', $headers['To']); 109 110 $mail->to('"Foo, Dr." <foo@example.com> , foo <foo@example.com>'); 111 $mail->cleanHeaders(); 112 $headers = $mail->prop('headers'); 113 $this->assertEquals('=?UTF-8?B?IkZvbywgRHIuIg==?= <foo@example.com>, foo <foo@example.com>', $headers['To']); 114 115 $mail->to('Möp <moep@example.com> , foo <foo@example.com>'); 116 $mail->cleanHeaders(); 117 $headers = $mail->prop('headers'); 118 $this->assertEquals('=?UTF-8?B?TcO2cA==?= <moep@example.com>, foo <foo@example.com>', $headers['To']); 119 120 $mail->to(array('Möp <moep@example.com> ',' foo <foo@example.com>')); 121 $mail->cleanHeaders(); 122 $headers = $mail->prop('headers'); 123 $this->assertEquals('=?UTF-8?B?TcO2cA==?= <moep@example.com>, foo <foo@example.com>', $headers['To']); 124 125 $mail->to(array('Beet, L van <lvb@example.com>',' foo <foo@example.com>')); 126 $mail->cleanHeaders(); 127 $headers = $mail->prop('headers'); 128 $this->assertEquals('=?UTF-8?B?QmVldCwgTCB2YW4=?= <lvb@example.com>, foo <foo@example.com>', $headers['To']); 129 130 131 } 132 133 function test_simplemail(){ 134 global $conf; 135 $conf['htmlmail'] = 0; 136 137 $mailbody = 'A test mail in ASCII'; 138 $mail = new TestMailer(); 139 $mail->to('test@example.com'); 140 $mail->setBody($mailbody); 141 142 $dump = $mail->dump(); 143 144 // construct the expected mail body text - include the expected dokuwiki signature 145 $replacements = $mail->prop('replacements'); 146 $expected_mail_body = chunk_split(base64_encode($mailbody.$replacements['text']['EMAILSIGNATURE']),72,MAILHEADER_EOL); 147 148 $this->assertNotRegexp('/Content-Type: multipart/',$dump); 149 $this->assertRegexp('#Content-Type: text/plain; charset=UTF-8#',$dump); 150 $this->assertRegexp('/'.preg_quote($expected_mail_body,'/').'/',$dump); 151 152 $conf['htmlmail'] = 1; 153 } 154 155 function test_replacements(){ 156 $mail = new TestMailer(); 157 158 $replacements = array( '@DATE@','@BROWSER@','@IPADDRESS@','@HOSTNAME@','@EMAILSIGNATURE@', 159 '@TITLE@','@DOKUWIKIURL@','@USER@','@NAME@','@MAIL@'); 160 $mail->setBody('A test mail in with replacements '.join(' ',$replacements)); 161 162 $text = $mail->prop('text'); 163 $html = $mail->prop('html'); 164 165 foreach($replacements as $repl){ 166 $this->assertNotRegexp("/$repl/",$text,"$repl replacement still in text"); 167 $this->assertNotRegexp("/$repl/",$html,"$repl replacement still in html"); 168 } 169 } 170 171 /** 172 * @see https://forum.dokuwiki.org/post/35822 173 */ 174 function test_emptyBCCorCC() { 175 $mail = new TestMailer(); 176 $headers = &$mail->propRef('headers'); 177 $headers['Bcc'] = ''; 178 $headers['Cc'] = ''; 179 $header = $mail->prepareHeaders(); 180 $this->assertEquals(0, preg_match('/(^|\n)Bcc: (\n|$)/', $header), 'Bcc found in headers.'); 181 $this->assertEquals(0, preg_match('/(^|\n)Cc: (\n|$)/', $header), 'Cc found in headers.'); 182 } 183 184 function test_nullTOorCCorBCC() { 185 $mail = new TestMailer(); 186 $headers = &$mail->propRef('headers'); 187 $headers['Bcc'] = NULL; 188 $headers['Cc'] = NULL; 189 $headers['To'] = NULL; 190 $header = $mail->prepareHeaders(); 191 $this->assertEquals(0, preg_match('/(^|\n)Bcc: (\n|$)/', $header), 'Bcc found in headers.'); 192 $this->assertEquals(0, preg_match('/(^|\n)Cc: (\n|$)/', $header), 'Cc found in headers.'); 193 $this->assertEquals(0, preg_match('/(^|\n)To: (\n|$)/', $header), 'To found in headers.'); 194 } 195 196 /** 197 * @group internet 198 */ 199 function test_lint(){ 200 // prepare a simple multipart message 201 $mail = new TestMailer(); 202 $mail->to(array('Möp <moep@example.com> ',' foo <foo@example.com>')); 203 $mail->from('Me <test@example.com>'); 204 $mail->subject('This is a töst'); 205 $mail->setBody('Hello Wörld, 206 207 please don\'t burn, okay? 208 '); 209 $mail->attachContent('some test data', 'text/plain', 'a text.txt'); 210 $msg = $mail->dump(); 211 $msglines = explode("\n", $msg); 212 213 //echo $msg; 214 215 // ask message lint if it is okay 216 $html = new HTTPClient(); 217 $results = $html->post('https://tools.ietf.org/tools/msglint/msglint', array('msg'=>$msg)); 218 if($results === false) { 219 $this->markTestSkipped('no response from validator'); 220 return; 221 } 222 223 // parse the result lines 224 $lines = explode("\n", $results); 225 $rows = count($lines); 226 $i=0; 227 while(trim($lines[$i]) != '-----------' && $i<$rows) $i++; //skip preamble 228 for($i=$i+1; $i<$rows; $i++){ 229 $line = trim($lines[$i]); 230 if($line == '-----------') break; //skip appendix 231 232 // get possible continuation of the line 233 while($lines[$i+1][0] == ' '){ 234 $line .= ' '.trim($lines[$i+1]); 235 $i++; 236 } 237 238 // check the line for errors 239 if(substr($line,0,5) == 'ERROR' || substr($line,0,7) == 'WARNING'){ 240 // ignore some errors 241 if(strpos($line, "missing mandatory header 'return-path'")) continue; #set by MDA 242 if(strpos($line, "bare newline in text body decoded")) continue; #we don't send mail bodies as CRLF, yet 243 if(strpos($line, "last decoded line too long")) continue; #we don't send mail bodies as CRLF, yet 244 245 // get the context in which the error occured 246 $errorin = ''; 247 if(preg_match('/line (\d+)$/', $line, $m)){ 248 $errorin .= "\n".$msglines[$m[1] - 1]; 249 } 250 if(preg_match('/lines (\d+)-(\d+)$/', $line, $m)){ 251 for($x=$m[1]-1; $x<$m[2]; $x++){ 252 $errorin .= "\n".$msglines[$x]; 253 } 254 } 255 256 // raise the error 257 throw new Exception($line.$errorin); 258 } 259 } 260 261 $this->assertTrue(true); // avoid being marked as risky for having no assertion 262 } 263 264 function test_simplemailsignature() { 265 global $conf; 266 $conf['htmlmail'] = 0; 267 268 $mailbody = 'A test mail in ASCII'; 269 $signature = "\n-- \n" . 'This mail was generated by DokuWiki at' . "\n" . DOKU_URL . "\n"; 270 $mail = new TestMailer(); 271 $mail->to('test@example.com'); 272 $mail->setBody($mailbody); 273 274 $dump = $mail->dump(); 275 276 // construct the expected mail body text - include the expected dokuwiki signature 277 $expected_mail_body = chunk_split(base64_encode($mailbody . $signature), 72, MAILHEADER_EOL); 278 $this->assertRegexp('/' . preg_quote($expected_mail_body, '/') . '/', $dump); 279 280 $conf['htmlmail'] = 1; 281 } 282 283 function test_htmlmailsignature() { 284 $mailbody_text = 'A test mail in ASCII :)'; 285 $mailbody_html = 'A test mail in <strong>html</strong>'; 286 $htmlmsg_expected = '<html> 287<head> 288 <title>My Test Wiki</title> 289 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> 290</head> 291<body> 292 293A test mail in <strong>html</strong> 294 295<br /><hr /> 296<small>This mail was generated by DokuWiki at<br /><a href="' . DOKU_URL . '">' . DOKU_URL . '</a></small> 297</body> 298</html> 299'; 300 301 $mail = new TestMailer(); 302 $mail->to('test@example.com'); 303 $mail->setBody($mailbody_text, null, null, $mailbody_html); 304 305 $dump = $mail->dump(); 306 307 // construct the expected mail body text - include the expected dokuwiki signature 308 $expected_mail_body = chunk_split(base64_encode($htmlmsg_expected), 72, MAILHEADER_EOL); 309 310 $this->assertRegexp('/Content-Type: multipart/', $dump); 311 $this->assertRegexp('#Content-Type: text/plain; charset=UTF-8#', $dump); 312 $this->assertRegexp('/' . preg_quote($expected_mail_body, '/') . '/', $dump); 313 314 } 315 316 function test_htmlmailsignaturecustom() { 317 global $lang; 318 $lang['email_signature_html'] = 'Official message from your DokuWiki @DOKUWIKIURL@<br />Created by wonderful mail class <a href="https://www.dokuwiki.org/devel:mail">https://www.dokuwiki.org/devel:mail</a>'; 319 320 $mailbody_text = 'A test mail in ASCII :)'; 321 $mailbody_html = 'A test mail in <strong>html</strong>'; 322 $htmlmsg_expected = '<html> 323<head> 324 <title>My Test Wiki</title> 325 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> 326</head> 327<body> 328 329A test mail in <strong>html</strong> 330 331<br /><hr /> 332<small>Official message from your DokuWiki <a href="' . DOKU_URL . '">' . DOKU_URL . '</a><br />Created by wonderful mail class <a href="https://www.dokuwiki.org/devel:mail">https://www.dokuwiki.org/devel:mail</a></small> 333</body> 334</html> 335'; 336 337 $mail = new TestMailer(); 338 $mail->to('test@example.com'); 339 $mail->setBody($mailbody_text, null, null, $mailbody_html); 340 341 $dump = $mail->dump(); 342 343 // construct the expected mail body text - include the expected dokuwiki signature 344 $replacements = $mail->prop('replacements'); 345 $expected_mail_body = chunk_split(base64_encode($htmlmsg_expected), 72, MAILHEADER_EOL); 346 347 $this->assertRegexp('/' . preg_quote($expected_mail_body, '/') . '/', $dump); 348 349 } 350 351 function test_getCleanName() { 352 $mail = new TestMailer(); 353 $name = $mail->getCleanName('Foo Bar'); 354 $this->assertEquals('Foo Bar', $name); 355 $name = $mail->getCleanName('Foo, Bar'); 356 $this->assertEquals('"Foo, Bar"', $name); 357 $name = $mail->getCleanName('Foo" Bar'); 358 $this->assertEquals('"Foo\" Bar"', $name); 359 } 360} 361//Setup VIM: ex: et ts=4 : 362