Capturing e-mails on a Drupal development site

Capturing e-mails on a Drupal development site

Gergely Lekli's picture

We often set up staging sites for clients, and deploy all enhancements to that staging site first so that the client has an opportunity to test and validate new features before they go live. These staging sites occasionally contain production data to make testing easier and more realistic, which also means that even real user e-mail addresses can make their way to it. This potentially implies the risk of sending out unwanted e-mails to those addresses.

E-mail sending is one feature that developers need to be mindful of when testing Drupal sites. In certain settings, e-mails can be sent out without the person working on the site even realizing it. If you, for instance, have a module like Notifications or Subscriptions installed, an accidental cron run can send out a myriad of emails. For this reason it is better to not even allow arbitrary e-mail sending on staging sites.

Disabling e-mail sending on the staging site does not necessarily mean that the e-mails the site tries to send are thrown away. They can be redirected to a central storage of some sort where the developers have access to it, should they need to retrieve any of those e-mails. In order to achieve this, I have been mainly using two methods:

Reroute Email

Reroute Email module, as the name suggests, allows you to define one collecting e-mail address to which all the outgoing e-mails will be redirected. The module employs hook_mail_alter() to modify the recipient of each e-mail. It is noteworthy to mention that this can potentially interfere with other custom or contrib modules that alter outgoing mails the same way. Practically this means that after Reroute Email module has rerouted the e-mail, some other module can re-reroute it, rendering Reroute Email useless. Nevertheless, I have not encountered any situations where this might be an issue.


Reroute Email configuration

The module has just one configuration option besides the destination e-mail address: “Show rerouting description in mail body”. If this options is checked, you will see the original recipient’s e-mail address in the mail body, which is only included in the e-mail header otherwise.

Drupal’s TestingMailSystem

The other method is using Drupal’s build in testing mail system. Core provides this additional mail system, TestingMailSystem, besides the default one that is at work on any regular Drupal site. Unfortunately though, there is no way to switch over to it on core’s user interface. You will need to install Mail System module to make use of this system. After installing the module, you can go to Configuration > System > Mail System, and change the site-wide mail system to be used.


Mail System configuration

When the TestingMailSystem is activated, Drupal does not send out any actual e-mails. Instead, e-mails get logged to a system variable, namely drupal_test_email_collector. Another inconvenience when using this method is that there is no user interface to display the captured e-mails either. One needs to either go directly to the database and look up the value in the variable table, or write custom code to display the e-mails. I myself decided to implement a callback to list the captured e-mails on a page. Below is the implementation:

/**
 *  Callback to display captured test emails.
 */
function mymodule_captured_mails_page() {
  $captured_emails = variable_get('drupal_test_email_collector', array());

  $output = '';
  foreach ($captured_emails as $mail) {
    $output .= '<div>';
    $output .= 'To: <b>' . $mail['to'] . '</b><br>';
    $output .= 'Subject: <b>' . check_plain($mail['subject']) . '</b><br><br>';
    $output .= '<pre>' . check_plain($mail['body']) . '</pre>';

    $output .= '<hr></div>';
  }

  if (!count($captured_emails)) {
    $output = 'No mails.';
  }
  return $output;
}

To make this accessible from the web, one needs to define a menu item in hook_menu, and assign this function as the page callback, as illustrated below:

/**
 * Implements hook_menu().
 */
function mymodule_menu() {
  $items = array();
  $items['captured-mails'] = array(
    'title' => 'Captured mails',
    'page callback' => 'mymodule_captured_mails_page',
    'access arguments' => array('access administration pages'),
    'type' => MENU_CALLBACK,
   );
  return $items;
}

From then on, one can visit /captured-mails on their site, and see all the e-mails that have been sent out.

Comments

DevelMailLog creates a directory on the filesystem in "/tmp/devel_mail" and dumps each email out to a separate text file. I find this much preferable to TestingMailSystem - no need to build an interface, for one.

Gergely Lekli's picture

Thanks for adding this.
One thing to note here is that it uses a preset directory outside the Drupal root. So if you have multiple sites running on the same server, every site's mail will be dumped into one place. To prevent this, one can set the 'devel_debug_mail_directory' variable either in settings.php or in a custom module.

Thanks for sharing your module. It's handy and quick.

I noticed it doesn't appear that Drupal 6 supports TestingMailSystem (at least I can't seem to find it in the docs for 6, but I can in 7), though our D6 site MailSystem module has a setting for TestingMailSystem. when I set it, the system still tries to connect to sendmail (I see errors for this), and nothing is put into the captured emails variable (I added the menu URL code and the module code for viewing the variable contents).

Does this work in D6?

Post new comment

About Urban Insight

We create elegant, mobile-friendly websites.

We solve complex problems using Drupal and open source software.

Learn More

Snippet

To redirect all requests to HTTPS, place the following code into the vhost configuration file.

<IfModule mod_rewrite.c>
  RewriteEngine on
        RewriteCond %{SERVER_PORT} 80
        RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R,L]
        php_value session.cookie_secure 1
</IfModule>