Process email bounces with PHP

This is a quick script to process email bounces, for example from a mailing list so that users can be flagged up or unsubscribed when they have too many failures.

The actual bounce identification will be done by Chris Fortune’s Bounce Handler, which you can download from:
http://anti-spam-man.com/php_bouncehandler/

We require 3 files from that package:
bounce_driver.class.php
bounce_responses.php
rfc1893.error.codes.php

What this script does is get the bounced emails from a specified mailbox and counts up how many failed emails there are per email address – if the number is at least as many as your threshold value (called $delete), then (you insert your code to unsubscribe the email address or whatever etc. and) the bounced emails are then deleted. You can run the script as a cronjob or call from your mailing list script to tidy up subscriptions.

<?php

# define variables
$mail_box = '{mail.domain.com:143/novalidate-cert}'; //imap example
$mail_user = 'username'; //mail username
$mail_pass = 'password'; //mail password
$delete = '5'; //deletes emails with at least this number of failures

# connect to mailbox
$conn = imap_open ($mail_box, $mail_user, $mail_pass) or die(imap_last_error());
$num_msgs = imap_num_msg($conn);

# start bounce class
require_once('bounce_driver.class.php');
$bouncehandler = new Bouncehandler();

# get the failures
$email_addresses = array();
$delete_addresses = array();
  for ($n=1;$n<=$num_msgs;$n++) {
  $bounce = imap_fetchheader($conn, $n).imap_body($conn, $n); //entire message
  $multiArray = $bouncehandler->get_the_facts($bounce);
    if (!empty($multiArray[0]['action']) && !empty($multiArray[0]['status']) && !empty($multiArray[0]['recipient']) ) {
      if ($multiArray[0]['action']=='failed') {
      $email_addresses[$multiArray[0]['recipient']]++; //increment number of failures
      $delete_addresses[$multiArray[0]['recipient']][] = $n; //add message to delete array
      } //if delivery failed
    } //if passed parsing as bounce
  } //for loop

# process the failures
  foreach ($email_addresses as $key => $value) { //trim($key) is email address, $value is number of failures
    if ($value>=$delete) {
    /*
    do whatever you need to do here, e.g. unsubscribe email address
    */
    # mark for deletion
      foreach ($delete_addresses[$key] as $delnum) imap_delete($conn, $delnum);
    } //if failed more than $delete times
  } //foreach

# delete messages
imap_expunge($conn);

# close
imap_close($conn);

?>

Tagged , , , , , , , . Bookmark the permalink.

24 Responses to Process email bounces with PHP

  1. Oscar says:

    Works, thanks.
    Regards from México.

  2. NECAnGeL says:

    Works fine, I look for a script like this.
    Thanks

    Regards from Holland

  3. António Campos says:

    This line saved my life:

    $bounce = imap_fetchheader($conn, $n).imap_body($conn, $n); //entire message

    Thanks for your good work

  4. Michael Greene says:

    Your bounce checker works great, but I’ve come up stuck on one thing. If I send out a bulk mailing with multiple people on a BCC (as opposed to separate emails), I get a single reply back with all of the failed addresses, and the class doesn’t parse them. Any ideas on how I’d go about pulling the multiple addresses out? The answer may be to move away from BCC’ing multiple recipients to ensure a single address per bounce notification, but I figured it was worth throwing the question out there.

    Here’s an example:

    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:

    dsaflh@mydomain.com
    (generated from dsaflh@mydomain.com)
    No such person at this address
    347234jsldfkj@mydomain.com
    (generated from 347234jsldfkj@mydomain.com)
    No such person at this address
    sljsdkf@mydomain.com
    No such person at this address
    aasdlkj2@mydomain.com
    No such person at this address

    • cheesefather says:

      Hi, I didn’t write the class myself, but you could explode() the recipient section using carriage returns and then parse each exploded line as a potential email into a separate iteration of the handler… make sense? 🙂

  5. Jeff says:

    Dude, *exactly* what l needed! Thank you so much!

  6. Jeff says:

    Worked perfectly for me just as written. Thanks!!

  7. Pingback: PHP - dealing with bounced mails » Wegeberg

  8. Andrew says:

    Works perfectly, thanks. Any idea how I can extend this to get additional headers out of the email – I need to get ‘Return-Path’ for example.

    • cheesefather says:

      The plugin is written specifically to identify bounces – your best bet would be to parse the email for a return-path header after the entire message is read into the $bounce variable – so do a preg_match(‘/return-path.+\n|\r/’, $bounce) or something (that expression’s totally untested!).

  9. Phil says:

    Ah! so this is how to check for the bounces!
    been looking for this script.. been wondering for a long time how those software do it.

    Thanks!

  10. John says:

    Will it work for POP

  11. Johan says:

    Really a lifesaver! The spam can continue

  12. Dave says:

    I get the following error:

    Warning: iconv_mime_decode() [function.iconv-mime-decode]: Malformed string in xxx/xxx/xxx/bounce_driver.class.php on line 454

    Line 454 is:
    $hash[‘Subject’] = iconv_mime_decode($hash[‘Subject’], 0, “ISO-8859-1”);

    I have played around with it but can’t seem to fix the problem. Has anyone else ran into this error or know how to fix it?

  13. Sergio N Hernandez says:

    Great Code, would like to know, what is the optimal value used to eliminate email bounce.

    $ delete = ‘5 ‘

    I have read this article
    https://www.mailjet.com/support/what-is-an-acceptable-bounce-rate, 76.htm

    And I believe that maximum 3 emails bounce is the best. What do you think?

    Thanks for sharing

  14. Mark says:

    Thanks dude! After 2 days of searching how to get the list of problem mails. Saves me!

  15. Andree Ochoa says:

    Hi, does anyone have the required files?
    bounce_driver.class.php
    bounce_responses.php
    rfc1893.error.codes.php

    The link is dead. =(

  16. Pingback: Answer for Bounce inactive emails from php newsletter - Tech Magazine

Leave a Reply to Phil Cancel reply

Your email address will not be published. Required fields are marked *