1

Emails are being successfully piped into a PHP script through cPanel email user filtering, but the PHP script have a execution time limit (to prevent DoS). When the time limit error occurs, the email bounces.

Althought it is a PHP error what is producing the bouncing, the error virtually cannot be fixed, that is why there is a time limit.

A sample of the bounce message is:

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 |/usr/bin/php -q /home/foo/bar/script.php
generated by moo@beer.cl
local delivery failed

------ This is a copy of the message, including all the headers. ------
------ The body of the messa[...]

The first thing one might think, is that the execution time limit error is printing a message (that would automatically cause a bounce) but this is not the case, because ini_set('display_errors', false); is set. The proof that nothing is being printed is the lack of "The following text was generated during the delivery attempt: ..." in the message quoted above.

A small test:

#!/usr/bin/php -q
<?php
    set_time_limit(1);
    ini_set('display_errors', false);
    $fh_stdin = fopen('php://stdin', 'rb');
    while (true) rand();
?>
mikl
  • 1,067
  • 1
  • 20
  • 34

1 Answers1

1

Not sure if there is a question here, but the mail processor bounces the message because when the PHP script terminates abnormally due to an error, the PHP process returns a non-zero value (255 in this case) to the shell.

When your MTA that piped the email to your script sees that it fails based on its return value being > 0, it considers it a failure and bounces the message (potentially including any script output in the bounce message).

If you can't (or don't want to) change the max execution time for these piped processes, one solution would be to queue the message for processing by some other script where you can break down the processing into pieces or increase the time limit.

Using register_shutdown_function() and set_error_handler() I was unable to override PHP's return value for a timeout using exit(0) so that probably won't be a workaround.

You should be able to increase the time with set_time_limit unless your PHP is running in safe mode preventing it from doing so. But if the processes are really long running it may be better to queue the messages for processing instead of trying to handle messages as they come in since this could lead to bottlenecks or server overloads.

drew010
  • 68,777
  • 11
  • 134
  • 162
  • Ok, I accept it is beyond PHP and I considered the alternatives given, but I prefer to reject emails greater than 1MB, and register a detailed log without backup. I do still put a time limit only to detect design deficiencies that could eventually produce loops or overhead. Despite the email bounce, it can be debugged/optimized/tunned to never occur. This saves extra complexity and resource usage. Please add my alternative to your answer. However I accept your answer because the technical information given is the base of my decision. – mikl Sep 28 '15 at 13:54
  • An option, althought it might sound contradictory, is to just utilize the email bounce to suggest the sender that the email sent might be bigger than expected. Using register_shutdown_function(); you can output/print a customized message like "The email could not be processed because it might be bigger than expected" inside the bounce. – mikl Sep 28 '15 at 14:21
  • @drew010 - If the script is failing the MTA process, where are errors written to so we can debug whats those errors are? I am using cPanel Email Filters to pipe bounced emails (for a specific email account) to a PHP script. The script works from CLI when I pipe a saved email to the script, but the filter piping never executes...or if it does and is erroring out its not giving me any errors. I even specified a specific error log file: `ini_set("error_log", "bouncedEmails.log");` – rolinger Jun 24 '20 at 12:28
  • @rolinger Try explicitly setting error_reporting to E_ALL and display_errors to 0 in your mail script, and try an absolute path for error_log and be 100% sure the process executing can write to it. Otherwise, check the Exim logs `/var/log/exim_mainlog` for cpanel/whm maybe. If the message is bouncing it should be returned to the sender. Feel free to find my contact info in my profile. – drew010 Jul 14 '20 at 15:59