Skip to content

Sendmail Wrapper

We had some spam problems last week, one of them caused by a form that wasn’t properly escaped. While that problem was fixed, the real problem was that it was hard to figure out what script had the issue.

To solve this, I wrote a sendmail wrapper for use by PHP (though really it could be used by anything) that logs the message along with the date, a message id (also inserted in th e headers) and the current directory (which gives the location of the original script).

It also extracts out the domain name from the current directory, but this is server specific so you’ll need to change the pattern to match your file system.

Eventually I’d like to include support to check for a maximum number of recipients, and maybe some other heuristics to check for spam.

You can get the script at:
http://gregmaclellan.com/php/sendmail.phps 

You should save this file as /usr/local/sbin/sendmail_logged.

The reporting script is at:
http://gregmaclellan.com/php/mailreporting.sh

There are instructions in this file for how to add it to cron.

Let me know if you have any comments, suggestions, do any improvements, or find any bugs.

 

Be Sociable, Share!
    • Harold Paulson

      Hey,

      Are you using CGI-PHP? I ask because I’m using mod_php and I don’t get the same stuff in the environment passed to my mail script.

      I used a little different approach to accoumplish a similar effect:

      I have an auto-prepended script set in my php.ini with stuff like:

      putenv(‘HTTP_HOST=’. $_SERVER['HTTP_HOST']);
      putenv(‘SCRIPT_NAME=’ . $_SERVER['SCRIPT_NAME']);
      putenv(‘REMOTE_ADDR=’ . $_SERVER['REMOTE_ADDR']);

      That kicks some useful info down to the sendmail wrapper environment. Apache senenv directives don’t make it through for me, unfortunately.

      Then I went low-tech with my wrapper script:

      #!/bin/sh

      logger -p mail.info vhostmail: site=${HTTP_HOST}, client=${REMOTE_ADDR}, script=${SCRIPT_NAME}
      /usr/sbin/sendmail -t -i $*

      Trying this on my production box now.

    • http://www.gregmaclellan.com groogs

      This is using CLI-PHP (as opposed to CGI). The difference is in the environment variables that get passed, and the output of error messages (text vs html).

      I wanted to avoid using auto-prepend, espessially since a user could change thoses values if they wanted to. Putting the information into syslog is a good idea though.

    • http://www.adsa.com.br Joao Pedro

      Hi,

      I have a server with host some web page using php.

      Some day ago this server is used for spam by php mail function in some email form.

      I used your script with some hoppes to identifier that script, but the log that generated show me SCRIPT_NAME = the name of your script (sendmail_logger) and don’t the script used in form to send the mail…..

      Do you know how can I log or make a way to find it?

      Tkz for your attention,
      Joao Pedro

    • http://www.gregmaclellan.com groogs

      There’s really not an easy way to get the actual executing script’s name, because it’s not something that’s normally passed to sendmail. You can try the method Harold Paulson uses above. For the most part, getting the working directory (`pwd`) should usually be enough to figure out what script it is, unless you have hundreds of scripts that send mail all in the same directory.

    • Pingback: groogsblog » Blog Archive » PHP mail() logging

    • http://www.voicemeup.com Technophreak

      Has anyone other than me notice a long delay when using ths wrapper ?

      It seems as everything works as expected, but the php scripts takes more than 30 seconds before it returns the output to the browser when executing the mail command.

      It hangs when its doing the popen to the sendmail.

    • http://www.voicemeup.com Technophreak

      To be more precise, it is exactly when doing the pclose() at the end that it takes a while to return.

    • Francesco

      Hi all,
      I’ve made this change to the script:

      19a20,26
      > if($argc > 1)
      > {
      > for($i = 1; $i {
      > $sendmail .= ” ” . $argv[$i];
      > }
      > }

      This allows it to preserve command line arguments passed with the mail() function (like “-f sender”).

    • Francesco

      Sorry, the right code is:

      19a20,26
      > if($argc > 1)
      > {
      > for($i = 1; $i {
      > $sendmail .= " " . $argv[$i];
      > }
      > }

    • Francesco

      Sorry again. ;)
      19a20,26
      > if($argc > 1)
      > {
      > for($i = 1; $i < $argc; $i++)
      > {
      > $sendmail .= ” ” . $argv[$i];
      > }
      > }

    • Ed Bellamy

      My installation (PHP4, FC3) delays form processing confirmation, but doesn’t log to the folder /var/log/phpmail

      Any ideas?

    • http://www.salsa.de Martin

      Cool script. I have trouble running it under Suse 10.1 (PHP5) Maybe its the safemode=on. I will investigate…
      Two lines drop warnings; $ENV["PWD"] and $data are not initialized.(line 25 and 35 or so)

    • Ed Bellamy

      Also – every time I submit a form, I get 500Mb in my error log. I’ve tried with register_globals =On and Off

    • http://www.salsa.de Martin

      I have trouble running this script; maybe because phpinfo() shows php is compiled with –disable-cli

      Is there a useful alternative using Perl?

      I found a simple shellscript that (should) drop number of params and all parameters given to a logfile and pipe to sendmail:

      #!/bin/sh
      logfile=/var/log/wrapperlog
      (date; echo ” | $# | $@”) >> $logfile
      exec /usr/lib/sendmail “$@”

    • http://www.salsa.de Martin

      update – with $PWD

      #!/bin/sh
      logfile=/var/log/wrapperlog
      (date; echo ” | $# | $PWD | $@”) >> $logfile
      exec /usr/lib/sendmail “$@”

    • http://www.rackaid.com/ Jeffrey Huckaby

      I’ve attempted to use various wrapper scripts to help with tracking down spam, but have found most too slow or cpu intensive to implement in busy environments.

      Does any one have performance notes on this wrapper?

      What I would like to see is a way to override the mail function in PHP and auto-include some additional headers. On many shared hosting environments, such as Plesk, Ensim or cPanel based systems, you can add some settings within apache on a per site basis. Perhaps some way to use php admin flags or apache’s own environment variables could be useful.

      For example, if I were to set an apache env variable to have the site’s admin user name could this be logged or otherwise inserted into the email using your script?

    • Murz

      Without additions with “$argv” this script broke “return-path” in all sending mail!

      So will be good to add this in the script.

    Subscribe