Mail Filter pipe to PHP script (works but doesn't!)

Saiing

Registered
Nov 27, 2006
2
0
151
Oh boy, this is my last resort.

I have a mail filter set up through CPanel:

$header_to: is "[email protected]"+++++++| /home/myaccount/mailmgr/process.php

So I want any email sent to [email protected] to be processed by process.php which reads as below (right now it's just a dummy script which writes the email out to a file, just so I can see if it's working - there's no error trapping or anything else going on.)

#!/usr/bin/php -q

<?php

$outfilename = "mailout";
$email = "";

$infile = fopen("php://stdin", "r");
while (!feof($infile)) {
$email .= fread($infile, 1024);
}
fclose($infile);

$fout=fopen("./$outfilename","w");
fwrite($fout, $email);
fclose($fout);

php?>


The thing is, it works (almost) perfectly. The email comes in, gets filtered, piped to the script which reads it and dumps it to a file. However, the person sending the email gets the following message by return.

"This message was created automatically by mail delivery software.

A message that you sent could not be delivered to one or more of its
recipients. This is a permanent error. The following address(es) failed:

pipe to | /home/myaccount/mailmgr/process.php
generated by [email protected]

The following text was generated during the delivery attempt:

------ pipe to | /home/myaccount/mailmgr/process.php
generated by [email protected] ------"


So basically, it's working, but the person sending still gets an error back. Anyone have any ideas? Is it my PHP? Is it CPanel? Is it something else?

I've torn most of my hair out already. Any help would be appreciated before I lose what little I have left. PS. Apologies for the slightly messy PHP.


EDIT: For the record, after my own attempt (described above) failed, I followed the how-to at http://forums.cpanel.net/showthread.php?t=50985&highlight=mail+filter+php in case I missed something. It results in EXACTLY the same error.

I've also checked both attempts using CPanel's "Filter Test" tool, and it seems to think everything is fine. Is there anything else anyone can think of?
 
Last edited:

Rafaelfpviana

Well-Known Member
Mar 12, 2004
141
0
166
Brazil
I know what is happening.

The thing is that Exim and Exim's Sendmail simply deny sending e-mails as nobody through shell.

Try this, ssh your servre as root and then:

first create a text file like this:

Code:
To: [email protected]
Subject: Test
From: [email protected]
MIME-Version: 1.0
Content-Type: text/html; charset=utf-8
Content-Transfer-Encoding: 8bit

<b>yo</b>, whassup?
save it in /tmp as email_thing, so you will be able to find it as /tmp/email_thing

now do this as root

Code:
[email protected][~]# su nobody -s /bin/bash
bash-2.05b$cat /tmp/email_thing|/usr/sbin/sendmail -t -i
doing that it will result in this:

Code:
sendmail: sendmail cannot be called directly from a shell with the current user id
sendmail: sendmail cannot be called directly from a shell with the current user id
so this is good in a way, this is a protection from spammers and this is also the reason why those famous "stop nobody spammers" perl scripts don't work.

And it's the same for your script.

I was doing a research on this, I was able to create a script that works, but it's a doble-edge sword. It can log the spammers that use the mail() function but sometimes, if it's a badly written e-mail it wont go through.

Enougth talk, here is the code:

PHP:
#!/usr/bin/php -c /usr/local/cpanel/3rdparty/etc/php.ini
<?php
// notice that this script uses a diferent php.ini, thats to be sure that this script don't get any problems with safe mode or disabled functions
$get='';
$in="1";
$arg='';
$i=1;
$j=1;
error_reporting(0);
$fp = fopen("php://stdin", "r");
function readline($fp){
	$in = fgets($fp,1094);
	return $in;
}
while(!feof($fp)){
	$in=readline($fp);
	$get .=$in;
}
while(array_key_exists($i,$args) && $argv[$i])
        {
        $arg .=' '.$argv[$i];
        $i++;
        }
### AntiAbuse
$chd=$_SERVER['PWD'];
$lines=explode("\n",$get);
$messageid=date('ymdHis');
$email=$lines[0];
//Acha a linha do from

while (!(eregi("from: ",$lines[$j])) && ($lines[$j]))
        $j++;
if (eregi("from: ",$lines[$j]))
        {
        if (eregi("[<,>]",$lines[$j]))
                {
                $lines=split("[<,>]",$lines[$j]);
                $from=$lines[1];
                }
        else
                $from=$lines[$j];
        }
$date=date("Y-m-d");
$time=date("H:i:s");
$log="$date - $time - $chd - $email - $from - $messageid \n";

$smtp_server = fsockopen("localhost", 25, $errno, $errstr, 30);

if(!$server_smtp && empty($from)){
	// We have an error, do something
	exit;
}
#envia a mensagem
fwrite($smtp_server, "HELO localhost\r\n");
fwrite($smtp_server, "MAIL FROM:<".eregi_replace('from:[ ]?','',$from).">\r\n");
fwrite($smtp_server, "RCPT TO:<".eregi_replace('to:[ ]?','',$email).">\r\n");
fwrite($smtp_server, "DATA\r\n");
fwrite($smtp_server, $get);
fwrite($smtp_server, ".\r\nQUIT\r\n");
fclose($smtp_server);

$file=fopen("/var/log/spam_log","a");
fwrite($file,$log);
fclose($file);
?>
Save this code as /usr/sbin/sendmail.php

and set these permissions:
Code:
[email protected][~]# chown root.root /usr/sbin/sendmail.php
[email protected][~]# chmod 715 /usr/sbin/sendmail.php
How to set it up:

Login the server as root and do this

Code:
[email protected][~]# touch /var/log/spam_log
[email protected][~]# chmod 777 /var/log/spam_log
Ok, log file created.

Ususaly what is done is edit the php.ini file to use that sendmail instead of the standard one, but to try it out, I sugest that you change it only for one account, by adding this in httpd.conf, but remember to find the domiain first, it should look like this:

Code:
<VirtualHost 11.111.111.11>
ServerAlias www.domain.com domain.com
ServerAdmin [email protected]
...
...
...
...
php_admin_value sendmail_path "/usr/sbin/sendmail.php"
</VirtualHost>
When your are ready to go just edit your php.ini file to use that sendmail_path.

ok??!?!

I think that explains it, any questions?