Interested in sending advanced email using PHP's mail() function, or even by piping output directly to sendmail? If so, make sure you take a look at Steve's comprehensive tutorial on sending email with PHP.
Getting Intimate With PHP's Mail() Function - Talking to Sendmail (Page 3 of 5 )
Of course, PHP let's you call the system mail program directly. You might want to do this in order to use a special feature only available in a certain mail program. Another reason to talk directly to sendmail is to create a From: header or other custom header in a more readable manner.
Talking to the mail program is like writing to a file. (Perl programmers will be familiar with this technique). Instead of opening a file, the popen() function specifies a program to pipe (communicate in a standard Unix way) your message to. This makes a connection to the mail program. The puts() function is used to "print" the message headers and message body out to the mail program, connected through the file descriptor already opened with the popen() function.
Because you may want to use a different mail program than sendmail, it's a good idea to store this path in a variable. You can store the recipient address in a variable to make it easy to change. Here is a simple script to send a message by talking directly to the sendmail program:
<?php $fd = popen("/usr/sbin/sendmail -t","w"); fputs($fd, "To: firstname.lastname@example.org\n"); fputs($fd, "From: Me \n"); fputs($fd, "Subject: Test message from my web site\n"); fputs($fd, "X-Mailer: PHP3\n"); fputs($fd, "Testing.\n"); pclose($fd); ?>
The popen() function opens a pipe to the mail program. To open the pipe, you must give the function the name of the program to pipe to and set the type of communication to make. The "w" standing for "write," which tells the open function to pipe the information from PHP to sendmail. If we used "r" instead then it would open the pipe in the opposite direction, sending information to PHP from the application.
The fputs() function then writes out each line of the message to sendmail. This function requires that we give it a file descriptor and the string we want to output. The file descriptor, which we obtained when the file (in Unix, devices masquerade as files) was opened, tells PHP where to send the message. The message itself is contained in a string. When we are done, the pipe is closed with the pclose() function.
Specify the -t option when working directly with sendmail to reduce the chance of abuse. From the sendmail documentation:
The `-t’ option to `sendmail’ instructs `sendmail’ to parse the headers of the message, and use all the recipient-type headers (i.e. `To:’, `Cc:’ and `Bcc:’) to construct the list of envelope recipients. This has the advantage of simplifying the `sendmail’ command line, but makes it impossible to specify recipients other than those listed in the headers.
One reason to access the mail program directly is to set the envelope email address. If you operate a mailing hosted at another provider, you may find that when you send mail using the simple mail() function that the messages are rejected for not having a matching envelope address. This happens because the address you are sending from and the envelope address do not match.
By directly accessing sendmail, we can alleviate this problem. Use the -f switch to tell sendmail to set the envelope address:
Sendmail Security When calling the system mail program, we must be careful of what characters we are sending to it. Because we are opening a Unix pipe, it is possible for malicious users to enter shell meta characters into form inputs that later are passed to sendmail. The results can be disastrous.
When creating a form handling script that eventually hands off user-entered data to the mail program, you must screen user input carefully. Treat all user input as if it were hostile. Start by removing shell meta-characters from any input used by sendmail, such as To: and From: inputs, or even the Subject: input of a feedback form.
Characters that must be removed are the period, for example, if you have an input for the user name. I usually use a system of inclusion rather than exclusion when sanitizing input data. That is, instead of saying "give me the string that results after taking out these specific characters", I say "give me the string that results after taking out any characters that are *not* these specific characters". It seems safer and easier, I feel, to identify what I know I want rather than attempt to identify every possible bad scenario that could happen. So, I use something like this regular expression in Perl: