For qmail users, I have written a function that talks directly to qmail-queue, rather than going through the sendmail wrapper used by mail(). Thus it allows more direct control over the message (for example, you can adapt the function to display "undisclosed recipients" in to the To: header). It also performs careful validation of the e-mail addresses passed to it, making it more difficult for spammers to exploit your scripts.
Please note that this function differs from the mail() function in that the from address must be passed as a _separate_ argument. It is automatically put into the message headers and _does not_ need to be included in $additional_headers.
$to can either be an array or a single address contained in a string.
$message should not contain any carriage return characters - only linefeeds.
No validation is performed on $additional_headers. This is mostly unnecessary because qmail will ignore any additional To: headers injected by a malicious user. However if you have some strange mail setup it might be a problem.
The function returns false if the message fails validation or is rejected by qmail-queue, and returns true on success.
<?php
function qmail_queue($to, $from, $subject, $message, $additional_headers = "")
{
$cmd = "/var/qmail/bin/qmail-queue";
$hostname = trim(file_get_contents("/var/qmail/control/me"));
if(is_scalar($to))
$to = array($to);
$e = "/^[-+\\.0-9=a-z_]+@([-0-9a-z]+\\.)+([0-9a-z]){2,4}$/i";
if(!preg_match($e, $from)) return false;
foreach($to as $rcpt)
{
if(!preg_match($e, $rcpt)) return false;
}
if(!preg_match("/^[\\040-\\176]+$/", $subject)) return false;
$dspec = array
(
array("pipe", "r"), array("pipe", "r") );
$pipes = array();
$proc = proc_open($cmd, $dspec, $pipes);
if(!is_resource($proc)) return false;
if(!empty($additional_headers))
{
fwrite($pipes[0], $additional_headers . "\n");
}
fwrite($pipes[0], "To: " . $to[0]); for($i = 1; $i < sizeof($to); $i++) {
fwrite($pipes[0], ", " . $to[$i]);
}
fwrite($pipes[0], "\nSubject: " . $subject . "\n");
fwrite($pipes[0], "From: " . $from . "\n");
fwrite($pipes[0], "Message-Id: <" . md5(uniqid(microtime())) . "@" . $hostname . ">\n");
fwrite($pipes[0], "Date: " . date("r") . "\n\n");
fwrite($pipes[0], $message);
fwrite($pipes[0], "\n");
fclose($pipes[0]);
fwrite($pipes[1], "F" . $from . "\0");
foreach($to as $rcpt)
{
fwrite($pipes[1], "T" . $rcpt . "\0");
}
fwrite($pipes[1], "\0");
fclose($pipes[1]);
return proc_close($proc) == 0;
}
?>