Outgoing email is sent using the Simple Mail Transfer Protocol (SMTP). Fortunately, PHP’s built-in mail()
function handles all SMTP socket-level protocols and handshaking for you. The mail()
function acts as your mail client, sending email messages just as Outlook or Thunderbird might.
Before you can use PHP as a mail client, you must edit PHP’s configuration file, php.ini, to point PHP to the mail server’s location. For example, the script in Example 15-1 shows the section of php.ini that configures PHP to work with sendmail, the Unix mail server on many networks.
Example 15-1. Configuring PHP’s mail()
function
[mail function] ; For Win32 only. SMTP = localhost ; For Win32 only. ;sendmail_from = me@example.com ; For Unix only. You may supply arguments as well (default: "sendmail -t -i"). sendmail_path = /usr/sbin/sendmail -t -i
Notice that the configuration differs slightly for Windows and Unix installations. For example, windows servers use php.ini to describe the network location of the mail server you want to use. In contrast, Unix installations need the file path to your local mail server. In either case, you must have access to a mail server (preferably in the same network domain) that allows you to send email.
Years ago, you could send email through almost any mail server on the Internet using relay host, which enables mail servers to relay messages from mail clients in one domain to a different domain. When using relay host, one can send nearly anonymous email, because these mail servers accept commands from any mail client without needing any form of authentication.
The relay host process has been largely abandoned by system administrators because spammers can use it to send millions of anonymous commercial emails. Today, almost every mail server will ignore commands that come from a different domain or from users that are not registered as valid clients.
An “open” mail server—one that allows relaying—is obviously a dangerous thing. I once worked for a company with two corporate mail servers, one of which mistakenly allowed mail relaying. Eventually, a spammer discovered it and commandeered it as a platform for dispatching thousands of anonymous commercial emails.[49] In addition to wasting our bandwidth, our domain was reported as one that belonged to a spammer and subsequently got placed on a watch list used by spam-detection companies. Once they identified our domain as a source of spam, many important corporate emails weren’t received because spam filters had rejected them. It took quite an effort to get our domain off of that list. For this reason, you will need a valid email account to send email from a webbot.
PHP provides a built-in function for sending email, as shown in Example 15-2.
Example 15-2. Sending an email with PHP’s built-in mail()
function
$email_address = "some.account@someserver.com"; $email_subject = "Webbot Notification Email"; $email_message = "Your webbot found something that needs you attention"; mail($email_address, $email_subject, $email_message);
In the simplest configuration, as shown in Example 15-2, you only need to specify the destination email address, the subject, and the message. For the reasons mentioned in the relay host discussion, however, you will need a valid account on the same server as the one specified in your php.ini file.
There are, of course, more options than those shown in Example 15-2. However, these options usually require that you build email headers, which tell a mail client how to format the email and how the email should be distributed. Since the syntax for email headers is very specific, it is easy to implement them incorrectly. Therefore, I’ve written a small email library called LIB_mail
with a function formatted_mail()
, which makes it easy to send emails that are more complex than what can easily be sent with the mail()
function alone. The script for LIB_mail
is shown in Example 15-3.
Example 15-3. Sending formatted email with LIB_mail
function formatted_mail($subject, $message, $address, $content_type) { # Set defaults if(!isset($address['cc'])) $address['cc'] = ""; if(!isset($address['bcc'])) $address['bcc'] = ""; # Ensure that there's a Reply-to address if(!isset($address['replyto'])) $address['replyto'] = $address['from']; # Create mail headers $headers = ""; $headers = $headers . "From: ".$address['from']."\r\n"; $headers = $headers . "Return-Path: ".$address['from']."\r\n"; $headers = $headers . "Reply-To: ".$address['replyto']."\r\n"; # Add Cc to header if needed if (strlen($address['cc'])< 1) $headers = $headers . "Cc: ".$address['cc']."\r\n"; # Add Bcc to header if needed if (strlen($address['bcc'])< 1) $headers = $headers . "Bcc: ".$address['bcc']."\r\n"; # Add content type $headers = $headers . "Content-Type: ".$content_type."\r\n"; # Send the email $result = mail($address['to'], $subject, $message, $headers); return $result; }
The main thing to take away from the script above is that the mail header is a very syntax-sensitive string that works better if it is a built-in function than if it is created repeatedly in your scripts. Also, up to six addresses are involved in sending email, and they are all passed to this routine in an array called $address
. These addresses are defined in Table 15-1.
Table 15-1. Email Addresses Used by LIB_mail
Function | Required or Optional | |
---|---|---|
To: | Defines the address of the main recipient of the email | Required |
Reply-to: | Defines the address where replies to the email are sent | Optional |
Return-path: | Indicates where notifications are sent if the email could not be delivered | Optional |
From: | Defines the email address of the party sending the email | Required |
Cc: | Refers to an address of another party, who receives a carbon copy of the email, but is not the primary recipient of the message | Optional |
Bcc: | Is similar to Cc: and stands for blind carbon copy; this address is hidden from the other parties receiving the same email | Optional |
Configuring the Reply-to address is also important because this address is used as the address where undeliverable email messages are sent. If this is not defined, undeliverable email messages will bounce back to your system admin, and you won’t know that an email wasn’t delivered. For this reason, the function automatically uses the From address if a Return-path address isn’t specified.