About the Author

Chris Shiflett

Hi, I'm Chris, a web developer and a founding member of Analog. I live and work in Brooklyn, NY.


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 Events

Brooklyn Beta

21 - 22 Oct 2010

At The Invisible Dog, Brooklyn, New York.

New Comments

Chris Shiflett wrote:

Hi John, How do you avoid race conditions with this? The findandmodify() command is atomic,...

Posted in Auto Increment with MongoDB
John Judy wrote:

How do you avoid race conditions with this? Once you get to a certain traffic volume two or more ...

Posted in Auto Increment with MongoDB
Chris Shiflett wrote:

Hey Ivo, Andrei is best suited to give a full response, since he's the one who researched this...

Posted in Auto Increment with MongoDB
Ivo wrote:

Although you did mention that you werent going to discuss the why, I can't think of a single vali...

Posted in Auto Increment with MongoDB
Stikkyfinger wrote:

Jon Gibbins plays a mean guitar? I'd be interested to know what he plays and what type of guitar ...

Posted in Hello, Analog

Browse Comments


Work and Books

Analog Essential PHP Security HTTP Developer's Handbook