2

I would like postfix to run a external php script (a hook) every time there is a outgoing delivery error.

For example, my webserver sends out emails and sometimes the recipients mailbox is full or nonexistent:

(host mx2.seznam.cz[77.75.76.32] said: 450 5.1.1 Mailbox is currently disabled. (in reply to RCPT TO command))

I would like to capture those errors through a script and notify my user that he needs to update his email address in our system.

Is it possible to get postfix to dump all of this information (email address, SMTP error) into a external script as they happen?

Thank you.

  • 1
    That sounds like handling a bounce. There is an answer here for that: https://serverfault.com/questions/48326/how-to-collect-bounces-in-postfix/735721#735721 – Alexis Wilke Jan 10 '19 at 21:17
  • @AlexisWilke thank you for that link! It does work wonderfully for hard errors, however I still can't find a way of passing deferred emails to a script: `status=deferred (connect to email.bg[89.25.48.10]:25: Connection timed out)` – Arkadiy Bolotov Jan 11 '19 at 04:54
  • Well... the master.cf line uses `bulkbounce` in my example there. Did you look into using `defer` as well? (point 3 in my answer) I never tried that on a deferred message since that will either work later or fail with a bounce anyway. – Alexis Wilke Jan 11 '19 at 05:11
  • @AlexisWilke thank you for your inputs. I ended up doing another way (check my answer). – Arkadiy Bolotov Jan 11 '19 at 07:14

1 Answers1

1

I ended up rerouting rsyslog maillog notifications via UDP to a simple php daemon for processing and doing all the magic there.

The bounce-daemon.php is controlled by monit, so it's always up and running.

rsyslog.conf:

# Forward postfix logs via UDP 
mail.*                                                  @127.0.0.1:55515

bounce-daemon.php:

$socket = stream_socket_server("udp://127.0.0.1:55515", $errno, $errstr, STREAM_SERVER_BIND);
if (!$socket) {
    die("$errstr ($errno)");
}

do {

    //  echo "Waiting for data... ";
    $pkt = stream_socket_recvfrom($socket, 10000, 0, $peer);

    // do processing here
    echo "$pkt\n";

} while ($pkt !== false);