A script that sends e-mail is one of the most common scripts found on a Web site, yet in its simplicity, a mail script sometimes causes the most frustration for programmers. There’s a function in PHP called mail() that needs just the recipient and the message body in order to send a message, but there are a few tweaks that you have to work through in order to make mail() do just what you want.

For mail() to work at all, you must have an SMTP server that PHP can connect to. Despite how essential this server is to mail programs, most people don’t have the foggiest idea of how it functions. In this tutorial, we’ll shed some light on the mysteries of SMTP as well as address some of the common questions about sending mail with PHP. Some highlights include methods of looping through a list of addresses and sending individual messages to recipients in both text and HTML formats.

Knowing your SMTP server
SMTP is the acronym for Simple Mail Transfer Protocol, and an SMTP server is the machine that runs this protocol and sends out the mail. Running the protocol essentially means running a program such as Sendmail or Qmail if you’re on a non-Windows machine. On Windows, the SMTP Service that is part of the Windows NT Service Pack or built in to the Windows 2000 operating system is typically the one running.

This is not to say those are the only SMTP software packages out there, but they are the most common. If your Web site is part of an Internet Service Provider’s virtual hosting package, the SMTP server should already be installed on that machine. If you are the systems administrator responsible for a dedicated machine located at an ISP or in-house, chances are quite good that you installed an SMTP daemon of some sort on that machine, specifically to handle sending e-mail from the Web server.

However, if you are a single user who has only a development Web server running on your personal machine, you may not have SMTP running locally. Here’s a very simple, yet accurate, rule of thumb: If you are a Windows user who has never run across the phrase SMTP server, you’re not running one. If that’s the case, you have two choices: install, configure, and maintain an SMTP server (not recommended if you don’t know what it is) or use one that’s already available to you.

“How can a server be available if it’s not currently being run?” you might ask. Well, if that machine is connected to the Internet via a dial-up connection (or DSL or cable), you can use your ISP’s outgoing mail server. For example, if your development machine is a Windows 98 box with a 56Kbps modem connected to the Internet via EarthLink, then you can use mail.earthlink.net as your SMTP server. Whatever e-mail client you use (Eudora, Outlook, Netscape Mail, and so on) as your outgoing mail server will also function within your PHP code as your SMTP server. The trick is making PHP aware of this little fact.

In the php.ini master configuration file, there are a few directives that need to be set up so that the mail() function works properly. Before changing them, check to see what they are. Use the phpinfo() function to show the current configuration of your system, by creating a file containing:
<? phpinfo() ?>

Save the file, place it somewhere in the document root of your Web server, and access it via your browser. You should see a nicely formatted display of your configuration. The options you want to check are:

  • ·        SMTP
  • ·        sendmail_from
  • ·        sendmail_path

If you are not using Windows, the sendmail_path directive is all you need to worry about. If you’re using Windows, you should look at the last two directives.

If you’re on Linux or a Unix variant, sendmail_path should be something like:
sendmail_path = /usr/sbin/sendmail

Or, if you’re using Qmail:
sendmail_path = /var/qmail/bin/sendmail

In this directive, you can also set configuration flags to specify queuing options or to explicitly set the Return-Path header, such as:
sendmail_path = /usr/sbin/sendmail -t -fyou@yourdomain.com

As a non-Windows user, that’s all you have to do. If you are using Windows, you have a little more work to do. You’ll want to look at the values for SMTP and sendmail_from. Don’t get confused by the use of sendmail in the name of the sendmail_from directive. Although you’re not using the program called Sendmail on Windows, it’s just the name of the directive. Don’t sweat it.

In your phpinfo() results, look at the default values for SMTP and sendmail_from–they should be either blank or contain dummy values. You’ll want to change these to be meaningful for your system.

If you are indeed running an SMTP server on that machine, your entry in php.ini will look like this:
SMTP = localhost

However, if you are going to use the outgoing mail server of your ISP (in this example, EarthLink), the entry in php.ini would look like this:
SMTP = mail.earthlink.net

You can also use an IP address instead of the name, since the machine cannot differentiate between these two entries.

The second configuration directive is sendmail_from, and this is the e-mail address used in the From header. It can be overwritten in the mail script itself but normally operates as the default value. Here’s what the configuration would look like with youraddress@yourdomain.com obviously standing in for your own address.
sendmail_from = youraddress@yourdomain.com

After making these configuration changes, restart the Web server and use the phpinfo() function to verify that the changes have been made. When that’s done, you’re ready to send some e-mail using PHP.

Sending a simple e-mail
The mail() function is quite simple: there are only five parameters, and two of them are optional. These are:

  • ·        Recipient address
  • ·        Subject
  • ·        Message
  • ·        Any other headers (optional)
  • ·        Other configuration options for your SMTP server (optional)

The additional headers parameter controls mail functions such as CC, BCC, Reply-To fields, or anything else that is compliant with the SMTP protocol. In this example, I’m just using From and Reply-To headers.

If you want to send mail to me and you’re using a non-Windows system, it would look something like:
$to = “julie@thickbook.com”;
$subject = “ZDNet Developer article”;
$msg = “I completely understand SMTP servers now!”;
$headers = “From: me@mycompany.com\nReply-To: someoneelse@mycompany.com”;
$config = “-fwebmaster@mycompany.com”;
mail(“$to”, “$subject”, “$msg”, “$headers”, “$config”);
echo “finished!”;

If you’re using a Windows-based SMTP service, it is likely you that won’t need the fifth parameter, and in the additional headers (fourth) parameter, you’ll need to separate them differently–use \r\n instead of \n. So, the same mail sent through a Windows-based SMTP service would be:
$to = “julie@thickbook.com”;
$subject = “ZDNet Developer article”;
$msg = “I completely understand SMTP servers now!”;
$headers = “From: me@mycompany.com\r\nReply-To: someoneelse@mycompany.com”;
mail(“$to”, “$subject”, “$msg”, “$headers”);
echo “finished!”;

That echo statement in the script enables your Web browser to return a message to you when the script is finished. If it were left out, you would just get a “Document contains no data” dialog box, since no output was sent to the browser.

The mail() function will return true as long as it connects to the specified SMTP server. This does not mean that the mail successfully reached its intended recipient. The mail() function does not wait for or report success/error codes from the SMTP server.

The mail() function will return false, and give you a warning such as “Couldn’t connect in line x” or “Unknown error in line x.” If either of these messages show up, check the values of SMTP in php.ini. Two possibilities provoke this message: the SMTP server is down, or PHP can’t connect to it. Either way, your mail will not be sent.

This script uses hard-coded values for all of the parameters. With a simple HTML form, you can plug values into these parameters and have yourself a fine feedback form.

Looping through a distribution list
Once you know how to send mail to one person, you’ll probably want to get all crazy and send the same message to many recipients–like a newsletter. All this entails is a nice little loop to run through your list of names and send the mail to them.

The format of the mail function is the same:
mail([recipient], [subject], [message], [any headers]);

You’ll simply want to replace [recipient] with the next name in your list. Suppose you have an array of e-mail addresses:
$addresses = array(“me@mycompany.com”, “you@yourcompany.com”, “someone@otherplace.com”);

All you do is loop through the array, get the new address, and send the mail.

If you have a list of e-mail addresses in a database, the same principle applies: loop through them.

There you have it. Obviously, the same concept applies to your specific database type and table structure, though the code will need to be modified.

Here’s the little gem that everyone seems to be missing when it comes to looping through a list of addresses: if you have more than 50 or so addresses, your script will probably time out before it finishes the list, because PHP has a default time limit of 30 seconds per script. You can modify this time limit but be careful when doing so. Try to limit this modification to particular scripts, such as looping through a list and sending mail. Otherwise, you could have runaway server processes on your hands, your machine will come crashing to a halt, and the world will end.

To set a time limit within a script, you use the set_time_limit() function. You can specify the limit, such as 60 seconds (set_time_limit(60)), or you can allow it to run until it’s absolutely done (set_time_limit(0)).

Place this in your script, and your mail-sending loop will happily continue until mail has been sent to every address in the list.

Sending HTML-formatted e-mail
Sending HTML-formatted e-mail is another of those simple things that seems more challenging than it really is. Once you learn how to do it, you’ll probably kick yourself for thinking it was harder than it is!

We need to make two modifications to the basic mail script that we’ve already used:

  • ·        Your message should be in HTML.
  • ·        You must add the content-type header.

That is all there is to it. Recipients who have a mail client that reads HTML-formatted e-mail will see their message in big, bold letters. If you are sending HTML-formatted e-mail that includes image tags, remember to use the full URL in the src attribute, for example: <img src=”http://www.yourdomain.com/images/image.gif”>.

Remember that not everyone can read HTML-formatted e-mail and that those who can’t will see only the code itself. This is annoying, so use this knowledge wisely.

You can use PHP to send mail in just about every way, shape, or form imaginable. This tutorial touches only on the basics: configuring your server and sending some simple mail. You can also send attachments along with your mail()-generated e-mail, modify a ton of different headers, and generally do just about anything that an actual e-mail client or mailing-list program can do.