Chances are, if you’re developing a web application, you’re going to have it send e-mail to users at some point in the application. Be it a registration e-mail, a lost password notice, or any other notification that might come from your application.
While working in your development environment, you don’t want messages like these being delivered to your real users – but you still want to be able to test that these features work as planned. This is especially true if you have e-mail scheduled to be delivered based on something like a cron job, where no express action on your part is required for the messages to start flowing.
The method I’ve implemented in my client projects to avert this disaster is to hook into the wp_mail filter, and force every outgoing message from WordPress to be delivered to my e-mail address instead.
Step 1: Add a variable to your wp-config.php to determine which environment you’re in.
In my wp-config.php, I define a new constant that determines if I’m in my development, staging or production environment.
define('WP_ENV', 'dev'); /* define('WP_ENV', 'staging'); define('WP_ENV', 'production'); */
Uncomment the appropriate environment when setting up your configuration.
Step 2: Override the mail recipient
Add a new function to your site’s functionality plugin (or to your themes functions.php file if you’re not using a plugin for site functionality) that filters e-mail sent with wp_mail.
/*** * Override outgoing e-mail messages if in development environment. * Send messages to pre-defined e-mail addresses for testing. */ add_filter( 'wp_mail', 'override_mail_recipient'); function override_mail_recipient ( $args ) { $to = $args['to']; $html = $args['html']; $subject = $args['subject']; $message = $args['message']; switch (WP_ENV) { case "dev": $subject = '[DEV] ' . $subject; $to = get_option('admin_email'); $message = 'DEVELOPMENT ENVIRONMENT. THIS MESSAGE WOULD NORMALLY HAVE BEEN SENT TO: ' . $to . '\r\n' . $message; $html .= 'DEVELOPMENT ENVIRONMENT. THIS MESSAGE WOULD NORMALLY HAVE BEEN SENT TO: ' . $to . ''; break; case "staging": $subject = '[STAGING] ' . $subject; $to = get_option('admin_email'); $message = 'DEVELOPMENT ENVIRONMENT. THIS MESSAGE WOULD NORMALLY HAVE BEEN SENT TO: ' . $to . '\r\n' . $message; $html .= 'DEVELOPMENT ENVIRONMENT. THIS MESSAGE WOULD NORMALLY HAVE BEEN SENT TO: ' . $to . ''; break; } $new_wp_mail = array( 'to' => $to, 'subject' => $subject, 'message' => $message, 'html' => $html, 'headers' => $args['headers'], 'attachments' => $args['attachments'], ); return $new_wp_mail; }
Not only will this redirect all outgoing e-mail to the e-mail address of the blog administrator (presumably you), it will also add a prefix to the subject line of the e-mail so you can easily spot development/staging messages. Finally, it adds a footer to to the body content letting you know who the message would have been delivered to if you were in the production environment.
There is a typo in $subjet
Good catch! Fixed it.
Is the code incomplete?
Hi Toby – It looks like something went wrong with the formatting of the code. Thanks for letting me know. I’ve fixed it.
Thank you for this, but just noting that you get $to from $args, then change the value to the new $to and then use that new $to in the following messages (instead of the original $to value).
Also any reason why in the HTML version you add it to the end and the text version you add it to the beginning?