Email Forward to PHP Script

cmdr_bond

Registered
May 15, 2005
2
0
151
Hello,

I was reading on a site (http://gvtulder.f2o.org/articles/incoming-mail/) that it's possible to instead of specify an email address to have your emails forwarded to, you can have cpanel send the email info to a php page.
I tried whath the site said, put a "|" followed by the path to the file but I think I'm doing something wrong as I'm getting my emails bounced back as undeliverable. How exactly do I do this and what kind of path am I supposed to write?

Thanks
 

webignition

Well-Known Member
Jan 22, 2005
1,880
0
166
I got stumped by this a bit when I first tried it and it took me a while to figure things out.

Assuming that the path to the PHP script is correct, what you also need to check is that:

1. You have #!/usr/local/bin/php as the first line in the PHP file

2. Check the permissions on the PHP script as it needs to be executable for whatever is piping data to it. Start with perms of 0777 and work down from there if you're not happy with these.

3. Make sure that the PHP script reads in the email from STDIN. I found that even with the correct setup from steps 1 and 2, the script also needs to read in the email for a bounceback not to occur.

A good way of troubleshooting is to get the script to email you - an easy way to spot that the script is executing and also a good way of checking the value of variables whilst debugging.

The PHP function I popped together for reading emails from STDIN is:

PHP:
function mailRead($i_klimit = "")
{
  // Reads piped mail from STDIN
  // Optional $i_klimit specifies after how many kilobytes the reading should stop
  // Default is 1024k. This is very generous for plain or formatted text.
  // Set to -1 for unlimited (i.e. read entire email)
  // This will prevent the script running into "out of memory" errors when dealing with large mails.

  if ($i_klimit == "") {
    $i_klimit = 1024;
  }
		
  $fp = fopen("php://stdin", "r");
  $email = "";
		
  if ($i_klimit == -1) {
    while (!feof($fp)) {
      $email .= fread($fp, 1024);
    }					
  } else {
    while (!feof($fp) && $i_limit < $i_klimit) {
      $email .= fread($fp, 1024);
      $i_limit++;
    }		
  }
		
  fclose($fp);
		
  return $email;
}
It may not be perfect but it does the trick and helps prevent"out of memory" errors if reading in huge emails (that was a fun thing to test!)

Another thing worth noting is that you can pick up a lot of useful info about the piped email through $_SERVER - the values are somewhat different to what you would expect when a script is executed via a browser.

Good luck!
 

trigger hippy

Member
Dec 2, 2005
16
0
151
Bristol, UK
Trouble piping e-mail to script

I am trying to pipe e-mail to script.
I have a file /home/tradein2/bounces/bounces.php both file and dir are CHOWN & CHGRP tradein2 CHMOD 0755 (was 0777, but that didn't work either)


File has contents as follows:
<?
#!/usr/local/bin/php

function mailRead($i_klimit = "")
// --- function copied from above post
}

$tdebug='Debug script ran at: '.date('r');
$tdebug.='\n\nThe e-mail was as follows:\n'.mailRead();

mail('[email protected]', 'debug script', $tdebug);

?>




cPanel has filter as follows:
$header_to: matches "[email protected]" | /home/tradein2/bounces/bounces.php

When I send a mail to [email protected], I get delivery failure message back and message is not delivered, and I get no test message from the script.

Anyone got any ideas?
 

webignition

Well-Known Member
Jan 22, 2005
1,880
0
166
You might also want to trim the script down first of all to ensure whilst troubleshooting permission-based issues.

PHP:
<?
#!/usr/local/bin/php

mail('[email protected]', 'test subject, 'test message');

?>
Would be about as simple as it could get.

If the script executes, you will definitely get sent the relevant email. If it doesn't, you won't. When you find it does, add back everything else and check if it still works.

By the way, the above cut-down script will result in a bounceback message returning to the sender as the message is not being read in from STDIN - worry about this later, get the script executing properly first.

Out of interest, are you running PHP as an Apache module or in CGI mode (i.e. with phpsuexec enabled)? I've never actually tried piping mail to PHP without phpsuexec enabled, so I can't say if it makes a difference, but you never know.
 

trigger hippy

Member
Dec 2, 2005
16
0
151
Bristol, UK
Tried that!....

I tried running the command from SSH and it worked, I got the message.
(/usr/local/bin/php /home/tradein2/bounces/bounces.php)

Still just get a bounce when I send e-mail to [email protected] though :mad:

(I am running phpsuexec)

Just a thought... SSH is running as root - is the script running as exim when the script is called, or is it as the user that the e-mail was sent to.
 
Last edited:

webignition

Well-Known Member
Jan 22, 2005
1,880
0
166
When testing from the command line, you should really be trying

Code:
/home/tradein2/bounces/bounces.php
instead of

Code:
/usr/local/bin/php /home/tradein2/bounces/bounces.php
You already have #!/usr/local/bin/php at the start of the script and so /usr/local/bin/php at the start of the command-line command is both unnecesary and doesn't test things correctly.

Mail will be being piped directly to '/home/tradein2/bounces/bounces.php' and not to the command '/usr/local/bin/php /home/tradein2/bounces/bounces.php' and so the former is a more accurate way of testing.

Saying that, if '/usr/local/bin/php /home/tradein2/bounces/bounces.php' works for you from the command line, you might want to adjust your filter so that you have

Code:
$header_to: matches "[email protected]" | /usr/local/bin/php /home/tradein2/bounces/bounces.php
instead of

Code:
$header_to: matches "[email protected]" | /home/tradein2/bounces/bounces.php
I've not tried this myself, but it's worth a shot.
 

trigger hippy

Member
Dec 2, 2005
16
0
151
Bristol, UK
Breakthrough

Yes, changing the filter worked - I now get the script running correctly from sending an e-mail.

I also tried running the file from SSH and got the following errors which I don't really understand as

[email protected] [~]# /home/tradein2/bounces/bounces.php
/home/tradein2/bounces/bounces.php: line 1: ?: No such file or directory
/home/tradein2/bounces/bounces.php: line 3: /aquota.user: Text file busy
/home/tradein2/bounces/bounces.php: line 4: syntax error near unexpected token `
$i_klimit'
/home/tradein2/bounces/bounces.php: line 4: `function mailRead($i_klimit = "") '

from file:

<? #!/usr/local/bin/php
/*
function mailRead($i_klimit = "")
{
// Reads piped mail from STDIN
// Optional $i_klimit specifies after how many kilobytes the reading should stop
// Default is 1024k. This is very generous for plain or formatted text.
// Set to -1 for unlimited (i.e. read entire email)
// This will prevent the script running into "out of memory" errors when dealing with large mails.

if ($i_klimit == "") {
$i_klimit = 1024;
}

$fp = fopen("php://stdin", "r");
$email = "";

if ($i_klimit == -1) {
while (!feof($fp)) {
$email .= fread($fp, 1024);
}
} else {
while (!feof($fp) && $i_limit < $i_klimit) {
$email .= fread($fp, 1024);
$i_limit++;
}
}

fclose($fp);

return $email;
}



$tdebug='Debug script ran at: '.date('r');
$tdebug.='\n\nThe e-mail was as follows:\n'.mailRead();

*/
mail('[email protected]', 'debug script', 'test');

?>


Is the file laid out correctly?
 

webignition

Well-Known Member
Jan 22, 2005
1,880
0
166
Your script should start as:

Code:
#!/usr/local/bin/php
<?
  // php code
?>
i.e. the shebang line should come before all PHP code - this tells the executing program what to handle the script with.

This was probably the issue all along - with the shebang line in the correct place, you should find that the previous filter works fine and that it will also run from the command line.