reroute_email.test 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434
  1. <?php
  2. /**
  3. * @file
  4. * Test the Reroute Email module.
  5. */
  6. /**
  7. * Provides common functionality for the Reroute Email test classes.
  8. */
  9. class RerouteEmailTestCase extends DrupalWebTestCase {
  10. /**
  11. * User object to perform site browsing
  12. * @var object
  13. */
  14. protected $adminUser;
  15. /**
  16. * Reroute email destination address used for the tests.
  17. * @var string
  18. */
  19. protected $rerouteDestination = "rerouted@example.com";
  20. /**
  21. * Original email address used for the tests.
  22. * @var string
  23. */
  24. protected $originalDestination = "original@example.com";
  25. /**
  26. * Permissions required by the user to perform the tests.
  27. * @var array
  28. */
  29. protected $permissions = array(
  30. 'administer reroute email',
  31. );
  32. /**
  33. * Enable modules and create user with specific permissions.
  34. */
  35. public function setUp() {
  36. // Merge inherited classes modules, see FieldUITestCase for an example.
  37. $modules = func_get_args();
  38. if (isset($modules[0]) && is_array($modules[0])) {
  39. $modules = $modules[0];
  40. }
  41. $modules[] = 'reroute_email';
  42. parent::setUp($modules);
  43. // Authenticate test user.
  44. $this->admin_user = $this->drupalCreateUser($this->permissions);
  45. $this->drupalLogin($this->admin_user);
  46. }
  47. /**
  48. * Helper function to configure Reroute Email Settings.
  49. *
  50. * @param string $reroute_destination
  51. * (optional) The email address to which emails should be rerouted.
  52. * Defaults to $this->rerouteDestination if set to NULL.
  53. * @param bool $reroute_email_enable
  54. * (optional) Set to TRUE to enable email Rerouting, defaults to TRUE.
  55. * @param bool $reroute_email_enable_message
  56. * (optional) Set to TRUE to show rerouting description, defaults to TRUE.
  57. */
  58. public function configureRerouteEmail($reroute_destination = NULL, $reroute_email_enable = TRUE, $reroute_email_enable_message = TRUE) {
  59. // Initialize $reroute_destination by default if no value is provided.
  60. if (!isset($reroute_destination)) {
  61. $reroute_destination = $this->rerouteDestination;
  62. }
  63. // Configure to Reroute Email settings form.
  64. $post = array(
  65. 'reroute_email_address' => $reroute_destination,
  66. 'reroute_email_enable' => $reroute_email_enable,
  67. 'reroute_email_enable_message' => $reroute_email_enable_message,
  68. );
  69. // Submit Reroute Email Settings form and check if it was successful.
  70. $this->drupalPost("admin/config/development/reroute_email", $post, t('Save configuration'));
  71. $this->assertText(t("The configuration options have been saved."));
  72. }
  73. /**
  74. * Assert whether the text "Originally to: @to_email" is found in email body.
  75. *
  76. * @param string $mail_body
  77. * The email body in which the line of text should be searched for.
  78. * @param bool $message
  79. * Message to display in test case results.
  80. * @param bool $original_destination
  81. * (optional) The original email address to be found in rerouted email
  82. * body. Defaults to $this->originalDestination if set to NULL.
  83. */
  84. public function assertOriginallyTo($mail_body, $message, $original_destination = NULL) {
  85. // Initialize $original_destination by default if no value is provided.
  86. if (!isset($original_destination)) {
  87. $original_destination = $this->originalDestination;
  88. }
  89. // Search in $mailbody for "Originally to: $original_destination".
  90. $search_for = t("Originally to: @to", array('@to' => $original_destination));
  91. $has_info = preg_match("/$search_for/", $mail_body);
  92. // Asserts whether searched text was found.
  93. $this->assertTrue($has_info, $message);
  94. $this->verbose(t('Email body was: <pre>@mail_body</pre>', array('@mail_body' => $mail_body)));
  95. }
  96. }
  97. /**
  98. * Tests email rerouting for the site-wide Core Contact form.
  99. */
  100. class RerouteEmailContactTestCase extends RerouteEmailTestCase {
  101. /**
  102. * Implements DrupalWebTestCase::getInfo().
  103. */
  104. public static function getInfo() {
  105. return array(
  106. 'name' => 'Site-wide Core Contact form email rerouting',
  107. 'description' => "Test Reroute Email module's ability to reroute mail sent from the Core Contact module forms.",
  108. 'group' => 'Reroute Email',
  109. );
  110. }
  111. /**
  112. * Enable modules and create user with specific permissions.
  113. */
  114. public function setUp() {
  115. // Add more permissions to be able to manipulate the contact forms.
  116. $this->permissions[] = 'administer contact forms';
  117. $this->permissions[] = 'access site-wide contact form';
  118. // Include Core Contact module.
  119. parent::setUp('contact');
  120. }
  121. /**
  122. * Basic tests of email rerouting for emails sent through the Contact forms.
  123. *
  124. * The Core Contact email form is submitted several times with different
  125. * Email Rerouting settings: Rerouting enabled or disabled, Body injection
  126. * enabled or disabled, several recipients with or without whitelist.
  127. */
  128. public function testBasicNotification() {
  129. // Additional destination email address used for testing the whitelist.
  130. $additional_destination = "additional@example.com";
  131. // Configure to reroute normally to rerouted@example.com.
  132. $this->configureRerouteEmail();
  133. // Configure the contact settings to send to $original_destination.
  134. $this->drupalPost('admin/structure/contact/edit/1', array('recipients' => $this->originalDestination), t('Save'));
  135. // Go to the contact page and send an email.
  136. $post = array('subject' => "Test test test", 'message' => 'This is a test');
  137. $this->drupalPost("contact", $post, t("Send message"));
  138. $this->assertText(t("Your message has been sent"));
  139. $mails = $this->drupalGetMails();
  140. $mail = end($mails);
  141. $this->assertMail('to', $this->rerouteDestination, format_string("Email was rerouted to @address", array('@address' => $this->rerouteDestination)));
  142. // Check if original destination email address is in rerouted email body.
  143. $this->assertOriginallyTo($mail['body'], 'Found the correct "Originally to" line in the body');
  144. $this->assertTrue(strpos($mail['body'], 'Originally to') !== FALSE, 'Body does contain "Originally to"');
  145. // Now try sending to one of the additional email addresses that should
  146. // not be rerouted. Configure two email addresses in reroute form.
  147. // Body injection is still turned on.
  148. $this->configureRerouteEmail("{$this->rerouteDestination}, $additional_destination");
  149. // Configure the contact settings to point to the additional recipient.
  150. $this->drupalPost('admin/structure/contact/edit/1', array('recipients' => $additional_destination), t('Save'));
  151. // Go to the contact page and send an email.
  152. $post = array('subject' => "Test test test", 'message' => 'This is a test');
  153. $this->drupalPost("contact", $post, t("Send message"));
  154. $this->assertText(t("Your message has been sent"));
  155. $mails = $this->drupalGetMails();
  156. $mail = end($mails);;
  157. $this->assertMail('to', $additional_destination, 'Email was not rerouted because destination was in whitelist');
  158. // Now change the configuration to disable reroute and set the original
  159. // email recipients.
  160. $this->configureRerouteEmail(NULL, FALSE);
  161. // Set the contact form to send to original_destination.
  162. $this->drupalPost('admin/structure/contact/edit/1', array('recipients' => $this->originalDestination), t('Save'));
  163. // Go to the contact page and send an email.
  164. $post = array('subject' => "Test test test", 'message' => 'This is a test');
  165. $this->drupalPost("contact", $post, t("Send message"));
  166. $this->assertText(t("Your message has been sent"));
  167. $mails = $this->drupalGetMails();
  168. $mail = end($mails);
  169. // Mail should not be rerouted - should go to $original_destination.
  170. $this->assertMail('to', $this->originalDestination, 'Mail not rerouted - sent to original destination.');
  171. $this->verbose(t("Email 'to' was: <pre>@mail_to</pre>", array('@mail_to' => $mail['to'])));
  172. // Configure to reroute without body injection.
  173. $this->configureRerouteEmail(NULL, TRUE, FALSE);
  174. // Go to the contact page and send an email.
  175. $post = array('subject' => "Test test test", 'message' => 'This is a test');
  176. $this->drupalPost("contact", $post, t("Send message"));
  177. $this->assertText(t("Your message has been sent"));
  178. $mails = $this->drupalGetMails();
  179. $mail = end($mails);
  180. // There should be nothing in the body except the contact message - no
  181. // body injection like 'Originally to'.
  182. $this->assertTrue(strpos($mail['body'], 'Originally to') === FALSE, 'Body does not contain "Originally to"');
  183. $this->assertTrue($mail['headers']['X-Rerouted-Original-To'] == $this->originalDestination, 'X-Rerouted-Original-To is correctly set to the original destination email');
  184. }
  185. }
  186. /**
  187. * Tests email rerouting for the Test Email form.
  188. */
  189. class RerouteEmailTestEmailTestCase extends RerouteEmailTestCase {
  190. /**
  191. * Implements DrupalWebTestCase::getInfo().
  192. */
  193. public static function getInfo() {
  194. return array(
  195. 'name' => 'Test Email form',
  196. 'description' => "Test Reroute Email's form for sending a test email.",
  197. 'group' => 'Reroute Email',
  198. );
  199. }
  200. /**
  201. * Basic tests for reroute_email Test Email form.
  202. *
  203. * Check if submitted form values are properly submitted and rerouted.
  204. * Test Subject, To, Cc, Bcc and Body submitted values, form validation,
  205. * default values, and submission with invalid email addresses.
  206. */
  207. public function testFormTestEmail() {
  208. // Configure to reroute normally to rerouted@example.com.
  209. $this->configureRerouteEmail();
  210. // Check Subject field default value.
  211. $this->drupalGet("admin/config/development/reroute_email/test");
  212. $this->assertFieldByName('subject', t("Reroute Email Test"), 'The expected default value was found for the Subject field.');
  213. // Submit the Test Email form to send an email to be rerouted.
  214. $post = array(
  215. 'to' => "to@example.com",
  216. 'cc' => "cc@example.com",
  217. 'bcc' => "bcc@example.com",
  218. 'subject' => "Test Reroute Email Test Email Form",
  219. 'body' => 'Testing email rerouting and the Test Email form',
  220. );
  221. $this->drupalPost("admin/config/development/reroute_email/test", $post, t("Send email"));
  222. $this->assertText(t("Test email submitted for delivery."));
  223. $mails = $this->drupalGetMails();
  224. $mail = end($mails);
  225. // Check rerouted email to.
  226. $this->assertMail('to', $this->rerouteDestination, format_string('To email address was rerouted to @address.', array('@address' => $this->rerouteDestination)));
  227. // Check the To passed through the Test Email Form.
  228. $this->assertOriginallyTo($mail['body'], 'Found submitted "To" email address in the body', $post['to']);
  229. // Check the Cc and Bcc headers are the ones submitted through the form.
  230. $this->assertTrue($mail['headers']['X-Rerouted-Original-Cc'] == $post['cc'], format_string('X-Rerouted-Original-Cc is correctly set to submitted value: @address', array('@address' => $post['cc'])));
  231. $this->assertTrue($mail['headers']['X-Rerouted-Original-Bcc'] == $post['bcc'], format_string('X-Rerouted-Original-Cc is correctly set to submitted value: @address', array('@address' => $post['bcc'])));
  232. // Check the Subject and Body field values can be found in rerouted email.
  233. $this->assertMail('subject', $post['subject'], format_string('Subject is correctly set to submitted value: @subject', array('@subject' => $post['subject'])));
  234. $this->assertFalse(strpos($mail['body'], $post['body']) === FALSE, 'Body contains the value submitted through the form');
  235. // Check required To field.
  236. $this->drupalPost("admin/config/development/reroute_email/test", array('to' => ''), t("Send email"));
  237. $this->assertText(t("To field is required."));
  238. // Test form submission with email rerouting and invalid email addresses.
  239. $post = array(
  240. 'to' => "To address invalid format",
  241. 'cc' => "Cc address invalid format",
  242. 'bcc' => "Bcc address invalid format",
  243. );
  244. $this->drupalPost("admin/config/development/reroute_email/test", $post, t("Send email"));
  245. // Successful submission with email rerouting enabled.
  246. $this->assertText(t("Test email submitted for delivery."));
  247. $mails = $this->drupalGetMails();
  248. $mail = end($mails);
  249. // Check rerouted email to.
  250. $this->assertMail('to', $this->rerouteDestination, format_string('To email address was rerouted to @address.', array('@address' => $this->rerouteDestination)));
  251. // Check the To passed through the Test Email Form.
  252. $this->assertOriginallyTo($mail['body'], 'Found submitted "To" email address in the body', $post['to']);
  253. // Check the Cc and Bcc headers are the ones submitted through the form.
  254. $this->assertTrue($mail['headers']['X-Rerouted-Original-Cc'] == $post['cc'], format_string('X-Rerouted-Original-Cc is correctly set to submitted value: @address', array('@address' => $post['cc'])));
  255. $this->assertTrue($mail['headers']['X-Rerouted-Original-Bcc'] == $post['bcc'], format_string('X-Rerouted-Original-Cc is correctly set to submitted value: @address', array('@address' => $post['bcc'])));
  256. // Now change the configuration to disable reroute and submit the Test
  257. // Email form with the same invalid email address values.
  258. $this->configureRerouteEmail(NULL, FALSE);
  259. // Submit the test email form again with previously used invalid addresses.
  260. $this->drupalPost("admin/config/development/reroute_email/test", $post, t("Send email"));
  261. // Check invalid email addresses are still passed to the mail system.
  262. $mails = $this->drupalGetMails();
  263. $mail = end($mails);
  264. // Check rerouted email to.
  265. $this->assertMail('to', $post['to'], format_string('To email address is correctly set to submitted value: @address.', array('@address' => $post['to'])));
  266. $this->verbose(t('Sent email values: <pre>@mail</pre>', array('@mail' => var_export($mail, TRUE))));
  267. // Check the Cc and Bcc headers are the ones submitted through the form.
  268. $this->assertTrue($mail['headers']['Cc'] == $post['cc'], format_string('Cc is correctly set to submitted value: @address', array('@address' => $post['cc'])));
  269. $this->assertTrue($mail['headers']['Bcc'] == $post['bcc'], format_string('Bcc is correctly set to submitted value: @address', array('@address' => $post['bcc'])));
  270. }
  271. }
  272. /**
  273. * Test handling of special cases for body as a string and Cc/Bcc robustness.
  274. */
  275. class RerouteEmailSpecialTestCase extends RerouteEmailTestCase {
  276. /**
  277. * Implements DrupalWebTestCase::getInfo().
  278. */
  279. public static function getInfo() {
  280. return array(
  281. 'name' => 'Body as a string and robust headers',
  282. 'description' => "Support message's body passed as a string and Cc/Bcc header keys with an unexpected case.",
  283. 'group' => 'Reroute Email',
  284. );
  285. }
  286. /**
  287. * Enable modules and create user with specific permissions.
  288. */
  289. public function setUp() {
  290. // Add more permissions to access recent log messages in test.
  291. $this->permissions[] = 'access site reports';
  292. // Include hidden test helper sub-module.
  293. parent::setUp('reroute_email_test');
  294. }
  295. /**
  296. * Test handling of message body as a string and header keys' robustness.
  297. *
  298. * A test email is sent by the reroute_email_test module with a string for
  299. * the body of the email message and Cc/Bcc header keys with an unexpected
  300. * case. Test if Reroute Email handles message's body properly when it is a
  301. * string and captures all Cc/Bcc header keys independently of the case.
  302. */
  303. public function testBodyStringRobustHeaders() {
  304. // Initialize Cc and Bcc keys with a special case.
  305. $test_cc_key = 'cC';
  306. $test_bcc_key = 'bCc';
  307. // Configure to reroute normally to rerouted@example.com.
  308. $this->configureRerouteEmail();
  309. // Print test email values for comparing values on test results page.
  310. $test_message = array(
  311. 'to' => $this->originalDestination,
  312. 'params' => array(
  313. 'body' => "Test Message body is a string.",
  314. 'headers' => array(
  315. 'test_cc_key' => $test_cc_key,
  316. 'test_bcc_key' => $test_bcc_key,
  317. $test_cc_key => "test_cc_key@example.com",
  318. $test_bcc_key => "test_bcc_key@example.com",
  319. ),
  320. ),
  321. );
  322. // Send test helper sub-module's email.
  323. drupal_mail('reroute_email_test', 'test_reroute_email', $test_message['to'], language_default(), $test_message['params']);
  324. $this->verbose(t('Test email message values: <pre>@test_message</pre>', array('@test_message' => var_export($test_message, TRUE))));
  325. $mails = $this->drupalGetMails();
  326. $mail = end($mails);
  327. // Check rerouted email to.
  328. $this->assertMail('to', $this->rerouteDestination, format_string('To email address was rerouted to @address.', array('@address' => $this->rerouteDestination)));
  329. // Check if original destination email address is in rerouted email body.
  330. $this->assertOriginallyTo($mail['body'], 'Found the correct "Originally to" line in the body');
  331. // Check if test message body is found although provided as a string.
  332. $this->assertTrue(strpos($mail['body'], $test_message['params']['body']) !== FALSE, 'Email body contains original message body although it was provided as a string.');
  333. // Check the watchdog entry logged by reroute_email_test_mail_alter.
  334. $this->drupalGet('admin/reports/dblog');
  335. $this->assertRaw(t('A String was detected in the body'), 'Recorded in recent log messages: a String was detected in the body.');
  336. // Test the robustness of the CC and BCC keys in headers.
  337. $this->assertTrue($mail['headers']['X-Rerouted-Original-Cc'] == $test_message['params']['headers'][$test_cc_key], format_string('X-Rerouted-Original-Cc is correctly set to @test_cc_address, although Cc header message key provided was: @test_cc_key', array('@test_cc_address' => $test_message['params']['headers'][$test_cc_key], '@test_cc_key' => $test_cc_key)));
  338. $this->assertTrue($mail['headers']['X-Rerouted-Original-Bcc'] == $test_message['params']['headers'][$test_bcc_key], format_string('X-Rerouted-Original-Bcc is correctly set to @test_bcc_address, although Bcc header message key provided was: @test_bcc_key', array('@test_bcc_address' => $test_message['params']['headers'][$test_bcc_key], '@test_bcc_key' => $test_bcc_key)));
  339. }
  340. }
  341. /**
  342. * Test default reroute destination email address when it is not configured.
  343. */
  344. class RerouteEmailDefaultAddressTestCase extends RerouteEmailTestCase {
  345. /**
  346. * Implements DrupalWebTestCase::getInfo().
  347. */
  348. public static function getInfo() {
  349. return array(
  350. 'name' => 'Default reroute destination email address',
  351. 'description' => "When reroute email addresses field is not configured, attempt to use the site email address, otherwise use sendmail_from system variable.",
  352. 'group' => 'Reroute Email',
  353. );
  354. }
  355. /**
  356. * Test default destination address is set to site_mail or sendmail_from.
  357. *
  358. * When reroute email addresses field is not configured and settings haven't
  359. * been configured yet, check if the site email address or the sendmail_from
  360. * system variable are properly used a fallbacks.
  361. */
  362. public function testRerouteDefaultAddress() {
  363. // Check default value for reroute_email_address when not configured.
  364. // If Site email is not empty, it should be the default value.
  365. $default_destination = variable_get('site_mail', NULL);
  366. $this->assertTrue(isset($default_destination), format_string('Site mail is not empty: @default_destination', array('@default_destination' => $default_destination)));
  367. // Load the Reroute Email Settings form page.
  368. $this->drupalGet("admin/config/development/reroute_email/reroute_email");
  369. // Check Email addresses field default value.
  370. $this->assertFieldByName(REROUTE_EMAIL_ADDRESS, $default_destination, format_string('Site email address is configured and is the default value of the Email addresses field: @default_destination', array('@default_destination' => $default_destination)));
  371. // Now unset site_mail to check if system sendmail_from is properly used.
  372. variable_del('site_mail');
  373. $default_destination = ini_get('sendmail_from');
  374. // Reload the Reroute Email Settings form page.
  375. $this->drupalGet("admin/config/development/reroute_email/reroute_email");
  376. // Check Email addresses field default value.
  377. $this->assertFieldByName('reroute_email_address', $default_destination, format_string('Site email address is not configured, Email addresses field defaults to system sendmail_from: @default_destination', array('@default_destination' => $default_destination)));
  378. }
  379. }