How To Log Emails Sent With PHP's mail() Function To Detect Form Spam

Version 1.0
Author: Till Brehm <t [dot] brehm [at] ispconfig [dot] com>
Last edited 07/10/2009

If you are running a webserver you might have faced the problem already: somewhere on your server is a vulnerable contact form or CMS system written in PHP that gets abused by spammers to send emails trough your server. If you have more than a few websites, it is a pain to detect which of the sites is vulnerable and sends the spam emails. This tutorial explains the installation of a small wrapper script which logs email messages sent trough the PHP mail() function.

I'm using Debian Linux here for this tutorial but the script should work on any Linux distribution.


1 Installing the wrapper script

Open a new file /usr/local/bin/phpsendmail...

vi /usr/local/bin/phpsendmail

... and insert the following script code:


  This script is a sendmail wrapper for php to log calls of the php mail() function.
  Author: Till Brehm,
  (Hopefully) secured by David Goodwin <david @>

$sendmail_bin = '/usr/sbin/sendmail';
$logfile = '/tmp/mail_php.log';

//* Get the email content
$logline = '';
$pointer = fopen('php://stdin', 'r');

while ($line = fgets($pointer)) {
        if(preg_match('/^to:/i', $line) || preg_match('/^from:/i', $line)) {
                $logline .= trim($line).' ';
        $mail .= $line;
$logline .= "\n";

//* compose the sendmail command
$command = 'echo ' . escapeshellarg($mail) . ' | '.$sendmail_bin.' -t -i';
for ($i = 1; $i < $_SERVER['argc']; $i++) {
        $command .= escapeshellarg($_SERVER['argv'][$i]).' ';

//* Write the log
file_put_contents($logfile, date('Y-m-d H:i:s') . ' ' . $_ENV['PWD'] . ' ' . $logline, FILE_APPEND);
//* Execute the command
return shell_exec($command);

If you use a different Linux distribution than Debian, the sendmail binary might be in a different location than /usr/sbin/sendmail and you have to change the sendmail path in the line $sendmail_bin = '/usr/sbin/sendmail'; of the script.

Now make the script executable...

chmod +x /usr/local/bin/phpsendmail

... and create the logfile and make it writable:

touch /tmp/mail_php.log
chmod 777 /tmp/mail_php.log


2 Modifying the php.ini

Now we reconfigure PHP so that it uses our wrapper script to send the emails.

Open the php.ini file...

vi /etc/php5/apache2/php.ini

... and change the lines...

[mail function]
; For Win32 only.
SMTP = localhost
smtp_port = 25

; For Win32 only.
;sendmail_from =

; For Unix only.  You may supply arguments as well (default: "sendmail -t -i").
;sendmail_path =

... to:

[mail function]
; For Win32 only.
;SMTP = localhost
;smtp_port = 25

; For Win32 only.
;sendmail_from =

; For Unix only.  You may supply arguments as well (default: "sendmail -t -i").
sendmail_path = /usr/local/bin/phpsendmail

If you use php as cgi, with suphp or as fcgi, then change the same lines in the file /etc/php5/cgi/php.ini, too.

Restart the Apache webserver to apply the changes.

/etc/init.d/apache2 restart


3 Test the setup

To test this setup, create a new php file with the name mailtest.php in one of your websites with the content:

mail('','This is a test message subject','This is a test message body');
echo 'Mail sent.'; 

Then open the file in a webbrowser to execute it. The test message should be logged now into the logfile. Check this with the command:

cat /tmp/mail_php.log