About the Author

Chris Shiflett

Chris Shiflett is an author and speaker who leads the web application security practice at OmniTI.


PHP Advent Calendar Day 1

Welcome to the PHP Advent Calendar. If you are unfamiliar with the format of an Advent calendar, Wikipedia has a pretty good description. The PHP Advent Calendar is similar in spirit to the Perl Advent Calendar, a tradition the Perl community has sustained for several years.

Each day, starting today and ending on Christmas Day, a member of the PHP community will be sharing a PHP-related tip or trick. Today's entry is provided by Sean Coates.

Sean Coates

Name
Sean Coates
Blog
blog.phpdoc.info
Biography
Sean Coates a PHP developer who works primarily on keeping things together over at php|a by developing their software and organizing their conferences. He was formerly the Editor-in-Chief of php|architect Magazine, is the co-host of the Pro::PHP Podcast and contributes to the PHP documentation team.
Location
Montréal, Canada

If you've ever developed a script that sends batch email to customers, you know that dreaded feeling of "what have I done?!" that hits seconds after you've launched the script, and the precise moment you remember that you forgot to turn the debug flag on, and hundreds of customers have been mailed your unfinished test template. It's an amateur mistake, but it's an easy one to make. With a little bit of clever configuration, you can mitigate the risk of stray email going to real customers from your development/staging environment.

When it comes to mail() (as well as many other things), PHP (on non-Windows, and by default) prefers to delegate the heavy lifting to another piece of software: sendmail (or a sendmail compatible command-line mail transport agent). By default, PHP will call your sendmail binary, and pass it the entire message, after composing it from the headers and body supplied by the developer.

One of the side-benefits to this system is the ability to override PHP's default, and seamlessly hook in your own sendmail-workalike binary or script. By setting the sendmail_path directive in php.ini, you can easily override the actual sending of email, and instead log it for easy review.

Here's an example from one of my development environments:

$ cat /path/to/php/ini | grep sendmail_path
sendmail_path=/usr/local/bin/logmail
$ cat /usr/local/bin/logmail
cat >> /tmp/logmail.log

This little bit of config code is extremely useful in a non-production environment. In the scenario above, you don't have to worry about flipping any flags or accidentally reading the "real" customer database when you meant to read the "fake" repository that contains only your own email address. Disaster avoided.

Left alone, that log file will get pretty big over time, quickly becoming unmanageable. With a little additional hackery, and with the help of the common formail app, an alternative might look like this:

$ cat /path/to/php/ini | grep sendmail_path
sendmail_path=/usr/local/bin/trapmail
$ cat /usr/local/bin/trapmail
formail -R cc X-original-cc \
  -R to X-original-to \
  -R bcc X-original-bcc \
  -f -A"To: devteam@example.com" \
| /usr/sbin/sendmail -t -i

This script traps all mail that would normally go out (say, to a customer), and instead, delivers it to devteam@example.com (with the original fields renamed for debugging purposes).

Sure, you could override this in your own framework (if you have a centralized mail object/function, for example), but the true beauty of this method is that it works for all calls to the mail() function, even those in third-party libraries. You do, however, still need to watch out for direct SMTP calls.

About This Post

PHP Advent Calendar Day 1 was posted on Sat, 01 Dec 2007 at 23:07:30 GMT.

3 Comments

1. David Rodger's GravatarDavid Rodger said:

Are you aware of fakemail?

http://www.lastcraft.com/fakemail.php

Sun, 02 Dec 2007 at 05:24:20 GMT Link


2. Brenda's GravatarBrenda said:

also i want that tshirt

Sun, 02 Dec 2007 at 10:10:54 GMT Link


3. Chris Shiflett's GravatarChris Shiflett said:

Sean has set up a friendly interface for the calendar:

http://phpdoc.info/advent/

Sun, 02 Dec 2007 at 20:56:13 GMT Link


Post A Comment

Personal Details and Comment

Style Guide

Line breaks are converted to paragraphs. Also use:

  • <a href="" title="">text</a>1
  • <em>text</em>
  • <blockquote><p>text</p></blockquote>
  • <code>2  <?php  if ($foo) {      $foo = TRUE;  }  ?></code>
  1. Note: <code> can be used inline (e.g. in paragraphs) or in a block as shown. Include whitespace and newlines in blocks.

Please enter Chris (my first name) below. This is a primitive spam prevention technique, and I apologize for the inconvenience.

Preview and Submit

Upcoming Talks

php|tek

21 - 23 May 2008

At Sheraton Gateway Suites Chicago O'Hare, Chicago, Illinois.

DC PHP Conference

02 - 04 Jun 2008

At Cafritz Conference Center, Washington, District of Columbia.

O'Reilly Open Source Convention

21 - 25 Jul 2008

At Oregon Convention Center, Portland, Oregon.

ZendCon

15 - 18 Sep 2008

In Santa Clara, California.

PHP Appalachia

11 - 14 Oct 2008

At Big Bear Lodge, Gatlinburg, Tennessee.

New Comments

Joseph Crawford wrote:

404 not found :( What's with this OpenID thing, you know how long it took me to figure out I h...

Posted in Zend Framework Tutorial
Laurent Cottereau wrote:

I am very interested in the possibilities of this service. However, I am wondering about what is ...

Posted in OpenID with myVidoop
Zac wrote:

Awesome code! Thanks!

Posted in Convert Smart Quotes with PHP
Muttley wrote:

Thanks for this, Shiffers. I've been working on a similar thing, using a similar method, so it's ...

Posted in Allowing HTML and Preventing XSS
hossein wrote:

Hi! May you give me an example how to use mcrypt_encrypt() in order to save passwrod in databa...

Posted in OpenID with myVidoop

Browse Comments