<?php
/*~ phpmailer-bmh_rules.php
.---------------------------------------------------------------------------.
|  Software: PHPMailer-BMH (Bounce Mail Handler)                            |
|   Version: 5.0.0rc1                                                       |
|   Contact: codeworxtech@users.sourceforge.net                             |
|      Info: http://phpmailer.codeworxtech.com                              |
| ------------------------------------------------------------------------- |
|    Author: Andy Prevost andy.prevost@worxteam.com (admin)                 |
| Copyright (c) 2002-2009, Andy Prevost. All Rights Reserved.               |
| ------------------------------------------------------------------------- |
|   License: Distributed under the General Public License (GPL)             |
|            (http://www.gnu.org/licenses/gpl.html)                         |
| This program is distributed in the hope that it will be useful - WITHOUT  |
| ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or     |
| FITNESS FOR A PARTICULAR PURPOSE.                                         |
| ------------------------------------------------------------------------- |
| This is a update of the original Bounce Mail Handler script               |
| http://sourceforge.net/projects/bmh/                                      |
| The script has been renamed from Bounce Mail Handler to PHPMailer-BMH     |
| ------------------------------------------------------------------------- |
| We offer a number of paid services:                                       |
| - Web Hosting on highly optimized fast and secure servers                 |
| - Technology Consulting                                                   |
| - Oursourcing (highly qualified programmers and graphic designers)        |
'---------------------------------------------------------------------------'
Last updated: January 21 2009 13:49 EST

/**
* next rule number (BODY): 0238 <br />
* default category:        unrecognized: <br />
* default rule no.:        0000 <br />
*/

global $rule_categories;
$rule_categories = array(
   'antispam'       => array('remove'=>0,'bounce_type'=>'blocked'  )
  ,'autoreply'      => array('remove'=>0,'bounce_type'=>'autoreply')
  ,'concurrent'     => array('remove'=>0,'bounce_type'=>'soft'     )
  ,'content_reject' => array('remove'=>0,'bounce_type'=>'soft'     )
  ,'command_reject' => array('remove'=>1,'bounce_type'=>'hard'     )
  ,'internal_error' => array('remove'=>0,'bounce_type'=>'temporary')
  ,'defer'          => array('remove'=>0,'bounce_type'=>'soft'     )
  ,'delayed'        => array('remove'=>0,'bounce_type'=>'temporary')
  ,'dns_loop'       => array('remove'=>1,'bounce_type'=>'hard'     )
  ,'dns_unknown'    => array('remove'=>1,'bounce_type'=>'hard'     )
  ,'full'           => array('remove'=>0,'bounce_type'=>'soft'     )
  ,'inactive'       => array('remove'=>1,'bounce_type'=>'hard'     )
  ,'latin_only'     => array('remove'=>0,'bounce_type'=>'soft'     )
  ,'other'          => array('remove'=>1,'bounce_type'=>'generic'  )
  ,'oversize'       => array('remove'=>0,'bounce_type'=>'soft'     )
  ,'outofoffice'    => array('remove'=>0,'bounce_type'=>'soft'     )
  ,'unknown'        => array('remove'=>1,'bounce_type'=>'hard'     )
  ,'unrecognized'   => array('remove'=>0,'bounce_type'=>false,     )
  ,'user_reject'    => array('remove'=>1,'bounce_type'=>'hard'     )
  ,'warning'        => array('remove'=>0,'bounce_type'=>'soft'     )
);

/*
 * var for new line ending
 */
 $bmh_newline = "<br />\n";

/**
 * Defined bounce parsing rules for non-standard DSN
 * @param string $body               body of the email
 * @param string $structure          message structure
 * @param boolean $debug_mode        show debug info. or not
 * @return array    $result an array include the following fields: 'email', 'bounce_type','remove','rule_no','rule_cat'
 *                      if we could NOT detect the type of bounce, return rule_no = '0000'
 */
function bmhBodyRules($body,$structure,$debug_mode=false) {
  // initialize the result array
  $result = array(
     'email'       => ''
    ,'bounce_type' => false
    ,'remove'      => 0
    ,'rule_cat'    => 'unrecognized'
    ,'rule_no'     => '0000'
  );

  // ======== rule =========
  if (false) {
  }

  /*
   * rule: mailbox unknown;
   * sample:
   * xxxxx@yourdomain.com
   * no such address here
   */
  elseif (preg_match ("/(\S+@\S+\w).*\n?.*no such address here/i",$body,$match)) {
    $result['rule_cat']    = 'unknown';
    $result['rule_no']     = '0237';
    $result['email']       = $match[1];
  }

  /*
   * <xxxxx@yourdomain.com>:
   * 111.111.111.111 does not like recipient.
   * Remote host said: 550 User unknown
   */
  elseif (preg_match ("/<(\S+@\S+\w)>.*\n?.*\n?.*user unknown/i",$body,$match)) {
    $result['rule_cat']    = 'unknown';
    $result['rule_no']     = '0236';
    $result['email']       = $match[1];
  }

  /*
   * rule: mailbox unknown;
   * sample:
   * <xxxxx@yourdomain.com>:
   * Sorry, no mailbox here by that name. vpopmail (#5.1.1)
   */
  elseif (preg_match ("/<(\S+@\S+\w)>.*\n?.*no mailbox/i",$body,$match)) {
    $result['rule_cat']    = 'unknown';
    $result['rule_no']     = '0157';
    $result['email']       = $match[1];
  }

  /*
   * rule: mailbox unknown;
   * sample:
   * xxxxx@yourdomain.com<br>
   * local: Sorry, can't find user's mailbox. (#5.1.1)<br />
   */
  elseif (preg_match ("/(\S+@\S+\w)<br />.*\n?.*\n?.*can't find.*mailbox/i",$body,$match)) {
    $result['rule_cat']    = 'unknown';
    $result['rule_no']     = '0164';
    $result['email']       = $match[1];
  }

  /*
   * rule: mailbox unknown;
   * sample:
   *     ##########################################################
   *     #  This is an automated response from a mail delivery    #
   *     #  program.  Your message could not be delivered to      #
   *     #  the following address:                                #
   *     #                                                        #
   *     #      "|/usr/local/bin/mailfilt -u #dkms"               #
   *     #        (reason: Can't create output)                   #
   *     #        (expanded from: <xxxxx@yourdomain.com>)         #
   *     #                                                        #
   */
  elseif (preg_match ("/Can't create output.*\n?.*<(\S+@\S+\w)>/i",$body,$match)) {
    $result['rule_cat']    = 'unknown';
    $result['rule_no']     = '0169';
    $result['email']       = $match[1];
  }

  /*
   * rule: mailbox unknown;
   * sample:
   * ????????????????:
   * xxxxx@yourdomain.com : ????, ?????.
   */
  elseif (preg_match ("/(\S+@\S+\w).*=D5=CA=BA=C5=B2=BB=B4=E6=D4=DA/i",$body,$match)) {
    $result['rule_cat']    = 'unknown';
    $result['rule_no']     = '0174';
    $result['email']       = $match[1];
  }

  /*
   * rule: mailbox unknown;
   * sample:
   * xxxxx@yourdomain.com
   * Unrouteable address
   */
  elseif (preg_match ("/(\S+@\S+\w).*\n?.*Unrouteable address/i",$body,$match)) {
    $result['rule_cat']    = 'unknown';
    $result['rule_no']     = '0179';
    $result['email']       = $match[1];
  }

  /*
   * rule: mailbox unknow;
   * sample:
   * Delivery to the following recipients failed.
   * xxxxx@yourdomain.com
   */
  elseif (preg_match ("/delivery[^\n\r]+failed\S*\s+(\S+@\S+\w)\s/is",$body,$match)) {
    $result['rule_cat']    = 'unknown';
    $result['rule_no']     = '0013';
    $result['email']       = $match[1];
  }

  /*
   * rule: mailbox unknow;
   * sample:
   * A message that you sent could not be delivered to one or more of its^M
   * recipients. This is a permanent error. The following address(es) failed:^M
   * ^M
   * xxxxx@yourdomain.com^M
   * unknown local-part "xxxxx" in domain "yourdomain.com"^M
   */
  elseif (preg_match ("/(\S+@\S+\w).*\n?.*unknown local-part/i",$body,$match)) {
    $result['rule_cat']    = 'unknown';
    $result['rule_no']     = '0232';
    $result['email']       = $match[1];
  }

  /*
   * rule: mailbox unknow;
   * sample:
   * <xxxxx@yourdomain.com>:^M
   * 111.111.111.11 does not like recipient.^M
   * Remote host said: 550 Invalid recipient: <xxxxx@yourdomain.com>^M
   */
  elseif (preg_match ("/Invalid.*(?:alias|account|recipient|address|email|mailbox|user).*<(\S+@\S+\w)>/i",$body,$match)) {
    $result['rule_cat']    = 'unknown';
    $result['rule_no']     = '0233';
    $result['email']       = $match[1];
  }

  /*
   * rule: mailbox unknow;
   * sample:
   * Sent >>> RCPT TO: <xxxxx@yourdomain.com>^M
   * Received <<< 550 xxxxx@yourdomain.com... No such user^M
   * ^M
   * Could not deliver mail to this user.^M
   * xxxxx@yourdomain.com^M
   * *****************     End of message     ***************^M
   */
  elseif (preg_match ("/\s(\S+@\S+\w).*No such.*(?:alias|account|recipient|address|email|mailbox|user)>/i",$body,$match)) {
    $result['rule_cat']    = 'unknown';
    $result['rule_no']     = '0234';
    $result['email']       = $match[1];
  }

  /*
   * rule: mailbox unknow;
   * sample:
   * <xxxxx@yourdomain.com>:^M
   * This address no longer accepts mail.
   */
  elseif (preg_match ("/<(\S+@\S+\w)>.*\n?.*(?:alias|account|recipient|address|email|mailbox|user).*no.*accept.*mail>/i",$body,$match)) {
    $result['rule_cat']    = 'unknown';
    $result['rule_no']     = '0235';
    $result['email']       = $match[1];
  }

  /*
   * rule: full
   * sample 1:
   * <xxxxx@yourdomain.com>:
   * This account is over quota and unable to receive mail.
   * sample 2:
   * <xxxxx@yourdomain.com>:
   * Warning: undefined mail delivery mode: normal (ignored).
   * The users mailfolder is over the allowed quota (size). (#5.2.2)
   */
  elseif (preg_match ("/<(\S+@\S+\w)>.*\n?.*\n?.*over.*quota/i",$body,$match)) {
    $result['rule_cat']    = 'full';
    $result['rule_no']     = '0182';
    $result['email']       = $match[1];
  }

  /*
   * rule: mailbox full;
   * sample:
   *   ----- Transcript of session follows -----
   * mail.local: /var/mail/2b/10/kellen.lee: Disc quota exceeded
   * 554 <xxxxx@yourdomain.com>... Service unavailable
   */
  elseif (preg_match ("/quota exceeded.*\n?.*<(\S+@\S+\w)>/i",$body,$match)) {
    $result['rule_cat']    = 'full';
    $result['rule_no']     = '0126';
    $result['email']       = $match[1];
  }

  /*
   * rule: mailbox full;
   * sample:
   * Hi. This is the qmail-send program at 263.domain.com.
   * <xxxxx@yourdomain.com>:
   * - User disk quota exceeded. (#4.3.0)
   */
  elseif (preg_match ("/<(\S+@\S+\w)>.*\n?.*quota exceeded/i",$body,$match)) {
    $result['rule_cat']    = 'full';
    $result['rule_no']     = '0158';
    $result['email']       = $match[1];
  }

  /*
   * rule: mailbox full;
   * sample:
   * xxxxx@yourdomain.com
   * mailbox is full (MTA-imposed quota exceeded while writing to file /mbx201/mbx011/A100/09/35/A1000935772/mail/.inbox):
   */
  elseif (preg_match ("/\s(\S+@\S+\w)\s.*\n?.*mailbox.*full/i",$body,$match)) {
    $result['rule_cat']    = 'full';
    $result['rule_no']     = '0166';
    $result['email']       = $match[1];
  }

  /*
   * rule: mailbox full;
   * sample:
   * The message to xxxxx@yourdomain.com is bounced because : Quota exceed the hard limit
   */
  elseif (preg_match ("/The message to (\S+@\S+\w)\s.*bounce.*Quota exceed/i",$body,$match)) {
    $result['rule_cat']    = 'full';
    $result['rule_no']     = '0168';
    $result['email']       = $match[1];
  }

  /*
   * rule: inactive
   * sample:
   * xxxxx@yourdomain.com<br>
   * 553 user is inactive (eyou mta)
   */
  elseif (preg_match ("/(\S+@\S+\w)<br />.*\n?.*\n?.*user is inactive/i",$body,$match)) {
    $result['rule_cat']    = 'inactive';
    $result['rule_no']     = '0171';
    $result['email']       = $match[1];
  }

  /*
   * rule: inactive
   * sample:
   * xxxxx@yourdomain.com [Inactive account]
   */
  elseif (preg_match ("/(\S+@\S+\w).*inactive account/i",$body,$match)) {
    $result['rule_cat']    = 'inactive';
    $result['rule_no']     = '0181';
    $result['email']       = $match[1];
  }

  /*
   * rule: internal_error
   * sample:
   * <xxxxx@yourdomain.com>:
   * Unable to switch to /var/vpopmail/domains/domain.com: input/output error. (#4.3.0)
   */
  elseif (preg_match ("/<(\S+@\S+\w)>.*\n?.*input\/output error/i",$body,$match)) {
    $result['rule_cat']    = 'internal_error';
    $result['rule_no']     = '0172';
    $result['bounce_type'] = 'hard';
    $result['remove']      = 1;
    $result['email']       = $match[1];
  }

  /*
   * rule: internal_error
   * sample:
   * <xxxxx@yourdomain.com>:
   * can not open new email file errno=13 file=/home/vpopmail/domains/fromc.com/0/domain/Maildir/tmp/1155254417.28358.mx05,S=212350
   */
  elseif (preg_match ("/<(\S+@\S+\w)>.*\n?.*can not open new email file/i",$body,$match)) {
    $result['rule_cat']    = 'internal_error';
    $result['rule_no']     = '0173';
    $result['bounce_type'] = 'hard';
    $result['remove']      = 1;
    $result['email']       = $match[1];
  }

  /*
   * rule: defer
   * sample:
   * <xxxxx@yourdomain.com>:
   * 111.111.111.111 failed after I sent the message.
   * Remote host said: 451 mta283.mail.scd.yahoo.com Resources temporarily unavailable. Please try again later [#4.16.5].
   */
  elseif (preg_match ("/<(\S+@\S+\w)>.*\n?.*\n?.*Resources temporarily unavailable/i",$body,$match)) {
    $result['rule_cat']    = 'defer';
    $result['rule_no']     = '0163';
    $result['email']       = $match[1];
  }

  /*
   * rule: autoreply
   * sample:
   * AutoReply message from xxxxx@yourdomain.com
   */
  elseif (preg_match ("/^AutoReply message from (\S+@\S+\w)/i",$body,$match)) {
    $result['rule_cat']    = 'autoreply';
    $result['rule_no']     = '0167';
    $result['email']       = $match[1];
  }

  /*
   * rule: western chars only
   * sample:
   * <xxxxx@yourdomain.com>:
   * The user does not accept email in non-Western (non-Latin) character sets.
   */
  elseif (preg_match ("/<(\S+@\S+\w)>.*\n?.*does not accept[^\r\n]*non-Western/i",$body,$match)) {
    $result['rule_cat']    = 'latin_only';
    $result['rule_no']     = '0043';
    $result['email']       = $match[1];
  }

  global $rule_categories, $bmh_newline;
  if ($result['rule_no'] == '0000') {
    if ($debug_mode) {
      echo 'Body:' . $bmh_newline . $body . $bmh_newline;
      echo $bmh_newline;
    }
  } else {
    if ($result['bounce_type'] === false) {
      $result['bounce_type'] = $rule_categories[$result['rule_cat']]['bounce_type'];
      $result['remove']      = $rule_categories[$result['rule_cat']]['remove'];
    }
  }
  return $result;
}

/**
 * Defined bounce parsing rules for standard DSN (Delivery Status Notification)
 *
 * @param string  $dsn_msg           human-readable explanation
 * @param string  $dsn_report        delivery-status report
 * @param boolean $debug_mode        show debug info. or not
 * @return array    $result an array include the following fields: 'email', 'bounce_type','remove','rule_no','rule_cat'
 *                      if we could NOT detect the type of bounce, return rule_no = '0000'
 */
function bmhDSNRules($dsn_msg,$dsn_report,$debug_mode=false) {
  // initialize the result array
  $result = array(
    'email'        => ''
    ,'bounce_type' => false
    ,'remove'      => 0
    ,'rule_cat'    => 'unrecognized'
    ,'rule_no'     => '0000'
  );
  $action      = false;
  $status_code = false;
  $diag_code   = false;

  // ======= parse $dsn_report ======
  // get the recipient email
  if (preg_match ("/Original-Recipient: rfc822;(.*)/i",$dsn_report,$match)) {
    $email_arr = imap_rfc822_parse_adrlist($match[1],'default.domain.name');
    if (isset($email_arr[0]->host) && $email_arr[0]->host != '.SYNTAX-ERROR.' && $email_arr[0]->host != 'default.domain.name' ) {
      $result['email']       = $email_arr[0]->mailbox.'@'.$email_arr[0]->host;
    }
  } else if (preg_match ("/Final-Recipient: rfc822;(.*)/i",$dsn_report,$match)) {
    $email_arr = imap_rfc822_parse_adrlist($match[1],'default.domain.name');
    if (isset($email_arr[0]->host) && $email_arr[0]->host != '.SYNTAX-ERROR.' && $email_arr[0]->host != 'default.domain.name' ) {
      $result['email']       = $email_arr[0]->mailbox.'@'.$email_arr[0]->host;
    }
  }

  if (preg_match ("/Action: (.+)/i",$dsn_report,$match)) {
    $action = strtolower(trim($match[1]));
  }

  if (preg_match ("/Status: ([0-9\.]+)/i",$dsn_report,$match)) {
    $status_code = $match[1];
  }

  // Could be multi-line , if the new line is beginning with SPACE or HTAB
  if (preg_match ("/Diagnostic-Code:((?:[^\n]|\n[\t ])+)(?:\n[^\t ]|$)/is",$dsn_report,$match)) {
      $diag_code = $match[1];
  }
  // ======= rules ======
  if (empty($result['email'])) {
    /* email address is empty
     * rule: full
     * sample:   DSN Message only
     * User quota exceeded: SMTP <xxxxx@yourdomain.com>
     */
    if (preg_match ("/quota exceed.*<(\S+@\S+\w)>/is",$dsn_msg,$match)) {
      $result['rule_cat']    = 'full';
      $result['rule_no']     = '0161';
      $result['email']       = $match[1];
    }
  } else {
    /* action could be one of them as RFC:1894
     * "failed" / "delayed" / "delivered" / "relayed" / "expanded"
     */
    switch ($action) {
      case 'failed':
        /* rule: full
         * sample:
         * Diagnostic-Code: X-Postfix; me.domain.com platform: said: 552 5.2.2 Over
         *   quota (in reply to RCPT TO command)
         */
        if (preg_match ("/over.*quota/is",$diag_code)) {
          $result['rule_cat']    = 'full';
          $result['rule_no']     = '0105';
        }
        /* rule: full
         * sample:
         * Diagnostic-Code: SMTP; 552 Requested mailbox exceeds quota.
         */
        elseif (preg_match ("/exceed.*quota/is",$diag_code)) {
          $result['rule_cat']    = 'full';
          $result['rule_no']     = '0129';
        }
        /* rule: full
         * sample 1:
         * Diagnostic-Code: smtp;552 5.2.2 This message is larger than the current system limit or the recipient's mailbox is full. Create a shorter message body or remove attachments and try sending it again.
         * sample 2:
         * Diagnostic-Code: X-Postfix; host mta5.us4.domain.com.int[111.111.111.111] said:
         *   552 recipient storage full, try again later (in reply to RCPT TO command)
         * sample 3:
         * Diagnostic-Code: X-HERMES; host 127.0.0.1[127.0.0.1] said: 551 bounce as<the
         *   destination mailbox <xxxxx@yourdomain.com> is full> queue as
         *   100.1.ZmxEL.720k.1140313037.xxxxx@yourdomain.com (in reply to end of
         *   DATA command)
         */
        elseif (preg_match ("/(?:alias|account|recipient|address|email|mailbox|user).*full/is",$diag_code)) {
          $result['rule_cat']    = 'full';
          $result['rule_no']     = '0145';
        }
        /* rule: full
         * sample:
         * Diagnostic-Code: SMTP; 452 Insufficient system storage
         */
        elseif (preg_match ("/Insufficient system storage/is",$diag_code)) {
          $result['rule_cat']    = 'full';
          $result['rule_no']     = '0134';
        }
        /* rule: full
         * sample 1:
         * Diagnostic-Code: X-Postfix; cannot append message to destination file^M
         *   /var/mail/dale.me89g: error writing message: File too large^M
         * sample 2:
         * Diagnostic-Code: X-Postfix; cannot access mailbox /var/spool/mail/b8843022 for^M
         *   user xxxxx. error writing message: File too large
         */
        elseif (preg_match ("/File too large/is",$diag_code)) {
          $result['rule_cat']    = 'full';
          $result['rule_no']     = '0192';
        }
        /* rule: oversize
         * sample:
         * Diagnostic-Code: smtp;552 5.2.2 This message is larger than the current system limit or the recipient's mailbox is full. Create a shorter message body or remove attachments and try sending it again.
         */
        elseif (preg_match ("/larger than.*limit/is",$diag_code)) {
          $result['rule_cat']    = 'oversize';
          $result['rule_no']     = '0146';
        }
        /* rule: unknown
         * sample:
         * Diagnostic-Code: X-Notes; User xxxxx (xxxxx@yourdomain.com) not listed in public Name & Address Book
         */
        elseif (preg_match ("/(?:alias|account|recipient|address|email|mailbox|user)(.*)not(.*)list/is",$diag_code)) {
          $result['rule_cat']    = 'unknown';
          $result['rule_no']     = '0103';
        }
        /* rule: unknown
         * sample:
         * Diagnostic-Code: smtp; 450 user path no exist
         */
        elseif (preg_match ("/user path no exist/is",$diag_code)) {
          $result['rule_cat']    = 'unknown';
          $result['rule_no']     = '0106';
        }
        /* rule: unknown
         * sample 1:
         * Diagnostic-Code: SMTP; 550 Relaying denied.
         * sample 2:
         * Diagnostic-Code: SMTP; 554 <xxxxx@yourdomain.com>: Relay access denied
         * sample 3:
         * Diagnostic-Code: SMTP; 550 relaying to <xxxxx@yourdomain.com> prohibited by administrator
         */
        elseif (preg_match ("/Relay.*(?:denied|prohibited)/is",$diag_code)) {
          $result['rule_cat']    = 'unknown';
          $result['rule_no']     = '0108';
        }
        /* rule: unknown
         * sample:
         * Diagnostic-Code: SMTP; 554 qq Sorry, no valid recipients (#5.1.3)
         */
        elseif (preg_match ("/no.*valid.*(?:alias|account|recipient|address|email|mailbox|user)/is",$diag_code)) {
          $result['rule_cat']    = 'unknown';
          $result['rule_no']     = '0185';
        }
        /* rule: unknown
         * sample 1:
         * Diagnostic-Code: SMTP; 550 «Dªk¦a§} - invalid address (#5.5.0)
         * sample 2:
         * Diagnostic-Code: SMTP; 550 Invalid recipient: <xxxxx@yourdomain.com>
         * sample 3:
         * Diagnostic-Code: SMTP; 550 <xxxxx@yourdomain.com>: Invalid User
         */
        elseif (preg_match ("/Invalid.*(?:alias|account|recipient|address|email|mailbox|user)/is",$diag_code)) {
          $result['rule_cat']    = 'unknown';
          $result['rule_no']     = '0111';
        }
        /* rule: unknown
         * sample:
         * Diagnostic-Code: SMTP; 554 delivery error: dd Sorry your message to xxxxx@yourdomain.com cannot be delivered. This account has been disabled or discontinued [#102]. - mta173.mail.tpe.domain.com
         */
        elseif (preg_match ("/(?:alias|account|recipient|address|email|mailbox|user).*(?:disabled|discontinued)/is",$diag_code)) {
          $result['rule_cat']    = 'unknown';
          $result['rule_no']     = '0114';
        }
        /* rule: unknown
         * sample:
         * Diagnostic-Code: SMTP; 554 delivery error: dd This user doesn't have a domain.com account (www.xxxxx@yourdomain.com) [0] - mta134.mail.tpe.domain.com
         */
        elseif (preg_match ("/user doesn't have.*account/is",$diag_code)) {
          $result['rule_cat']    = 'unknown';
          $result['rule_no']     = '0127';
        }
        /* rule: unknown
         * sample:
         * Diagnostic-Code: SMTP; 550 5.1.1 unknown or illegal alias: xxxxx@yourdomain.com
         */
        elseif (preg_match ("/(?:unknown|illegal).*(?:alias|account|recipient|address|email|mailbox|user)/is",$diag_code)) {
          $result['rule_cat']    = 'unknown';
          $result['rule_no']     = '0128';
        }
        /* rule: unknown
         * sample 1:
         * Diagnostic-Code: SMTP; 450 mailbox unavailable.
         * sample 2:
         * Diagnostic-Code: SMTP; 550 5.7.1 Requested action not taken: mailbox not available
         */
        elseif (preg_match ("/(?:alias|account|recipient|address|email|mailbox|user).*(?:un|not\s+)available/is",$diag_code)) {
          $result['rule_cat']    = 'unknown';
          $result['rule_no']     = '0122';
        }
        /* rule: unknown
         * sample:
         * Diagnostic-Code: SMTP; 553 sorry, no mailbox here by that name (#5.7.1)
         */
        elseif (preg_match ("/no (?:alias|account|recipient|address|email|mailbox|user)/is",$diag_code)) {
          $result['rule_cat']    = 'unknown';
          $result['rule_no']     = '0123';
        }
        /* rule: unknown
         * sample 1:
         * Diagnostic-Code: SMTP; 550 User (xxxxx@yourdomain.com) unknown.
         * sample 2:
         * Diagnostic-Code: SMTP; 553 5.3.0 <xxxxx@yourdomain.com>... Addressee unknown, relay=[111.111.111.000]
         */
        elseif (preg_match ("/(?:alias|account|recipient|address|email|mailbox|user).*unknown/is",$diag_code)) {
          $result['rule_cat']    = 'unknown';
          $result['rule_no']     = '0125';
        }
        /* rule: unknown
         * sample 1:
         * Diagnostic-Code: SMTP; 550 user disabled
         * sample 2:
         * Diagnostic-Code: SMTP; 452 4.2.1 mailbox temporarily disabled: xxxxx@yourdomain.com
         */
        elseif (preg_match ("/(?:alias|account|recipient|address|email|mailbox|user).*disabled/is",$diag_code)) {
          $result['rule_cat']    = 'unknown';
          $result['rule_no']     = '0133';
        }
        /* rule: unknown
         * sample:
         * Diagnostic-Code: SMTP; 550 <xxxxx@yourdomain.com>: Recipient address rejected: No such user (xxxxx@yourdomain.com)
         */
        elseif (preg_match ("/No such (?:alias|account|recipient|address|email|mailbox|user)/is",$diag_code)) {
          $result['rule_cat']    = 'unknown';
          $result['rule_no']     = '0143';
        }
        /* rule: unknown
         * sample 1:
         * Diagnostic-Code: SMTP; 550 MAILBOX NOT FOUND
         * sample 2:
         * Diagnostic-Code: SMTP; 550 Mailbox ( xxxxx@yourdomain.com ) not found or inactivated
         */
        elseif (preg_match ("/(?:alias|account|recipient|address|email|mailbox|user).*NOT FOUND/is",$diag_code)) {
          $result['rule_cat']    = 'unknown';
          $result['rule_no']     = '0136';
        }
        /* rule: unknown
         * sample:
         * Diagnostic-Code: X-Postfix; host m2w-in1.domain.com[111.111.111.000] said: 551
         * <xxxxx@yourdomain.com> is a deactivated mailbox (in reply to RCPT TO
         * command)
         */
        elseif (preg_match ("/deactivated (?:alias|account|recipient|address|email|mailbox|user)/is",$diag_code)) {
          $result['rule_cat']    = 'unknown';
          $result['rule_no']     = '0138';
        }
        /* rule: unknown
         * sample:
         * Diagnostic-Code: SMTP; 550 <xxxxx@yourdomain.com> recipient rejected
         * ...
         * <<< 550 <xxxxx@yourdomain.com> recipient rejected
         * 550 5.1.1 xxxxx@yourdomain.com... User unknown
         */
        elseif (preg_match ("/(?:alias|account|recipient|address|email|mailbox|user).*reject/is",$diag_code)) {
          $result['rule_cat']    = 'unknown';
          $result['rule_no']     = '0148';
        }
        /* rule: unknown
         * sample:
         * Diagnostic-Code: smtp; 5.x.0 - Message bounced by administrator  (delivery attempts: 0)
         */
        elseif (preg_match ("/bounce.*administrator/is",$diag_code)) {
          $result['rule_cat']    = 'unknown';
          $result['rule_no']     = '0151';
        }
        /* rule: unknown
         * sample:
         * Diagnostic-Code: SMTP; 550 <maxqin> is now disabled with MTA service.
         */
        elseif (preg_match ("/<.*>.*disabled/is",$diag_code)) {
          $result['rule_cat']    = 'unknown';
          $result['rule_no']     = '0152';
        }
        /* rule: unknown
         * sample:
         * Diagnostic-Code: SMTP; 551 not our customer
         */
        elseif (preg_match ("/not our customer/is",$diag_code)) {
          $result['rule_cat']    = 'unknown';
          $result['rule_no']     = '0154';
        }
        /* rule: unknown
         * sample:
         * Diagnostic-Code: smtp; 5.1.0 - Unknown address error 540-'Error: Wrong recipients' (delivery attempts: 0)
         */
        elseif (preg_match ("/Wrong (?:alias|account|recipient|address|email|mailbox|user)/is",$diag_code)) {
          $result['rule_cat']    = 'unknown';
          $result['rule_no']     = '0159';
        }
        /* rule: unknown
         * sample:
         * Diagnostic-Code: smtp; 5.1.0 - Unknown address error 540-'Error: Wrong recipients' (delivery attempts: 0)
         * sample 2:
         * Diagnostic-Code: SMTP; 501 #5.1.1 bad address xxxxx@yourdomain.com
         */
        elseif (preg_match ("/(?:unknown|bad).*(?:alias|account|recipient|address|email|mailbox|user)/is",$diag_code)) {
          $result['rule_cat']    = 'unknown';
          $result['rule_no']     = '0160';
        }
        /* rule: unknown
         * sample:
         * Diagnostic-Code: SMTP; 550 Command RCPT User <xxxxx@yourdomain.com> not OK
         */
        elseif (preg_match ("/(?:alias|account|recipient|address|email|mailbox|user).*not OK/is",$diag_code)) {
          $result['rule_cat']    = 'unknown';
          $result['rule_no']     = '0186';
        }
        /* rule: unknown
         * sample:
         * Diagnostic-Code: SMTP; 550 5.7.1 Access-Denied-XM.SSR-001
         */
        elseif (preg_match ("/Access.*Denied/is",$diag_code)) {
          $result['rule_cat']    = 'unknown';
          $result['rule_no']     = '0189';
        }
        /* rule: unknown
         * sample:
         * Diagnostic-Code: SMTP; 550 5.1.1 <xxxxx@yourdomain.com>... email address lookup in domain map failed^M
         */
        elseif (preg_match ("/(?:alias|account|recipient|address|email|mailbox|user).*lookup.*fail/is",$diag_code)) {
          $result['rule_cat']    = 'unknown';
          $result['rule_no']     = '0195';
        }
        /* rule: unknown
         * sample:
         * Diagnostic-Code: SMTP; 550 User not a member of domain: <xxxxx@yourdomain.com>^M
         */
        elseif (preg_match ("/(?:recipient|address|email|mailbox|user).*not.*member of domain/is",$diag_code)) {
          $result['rule_cat']    = 'unknown';
          $result['rule_no']     = '0198';
        }
        /* rule: unknown
         * sample:
         * Diagnostic-Code: SMTP; 550-"The recipient cannot be verified.  Please check all recipients of this^M
         */
        elseif (preg_match ("/(?:alias|account|recipient|address|email|mailbox|user).*cannot be verified/is",$diag_code)) {
          $result['rule_cat']    = 'unknown';
          $result['rule_no']     = '0202';
        }
        /* rule: unknown
         * sample:
         * Diagnostic-Code: SMTP; 550 Unable to relay for xxxxx@yourdomain.com
         */
        elseif (preg_match ("/Unable to relay/is",$diag_code)) {
          $result['rule_cat']    = 'unknown';
          $result['rule_no']     = '0203';
        }
        /* rule: unknown
         * sample 1:
         * Diagnostic-Code: SMTP; 550 xxxxx@yourdomain.com:user not exist
         * sample 2:
         * Diagnostic-Code: SMTP; 550 sorry, that recipient doesn't exist (#5.7.1)
         */
        elseif (preg_match ("/(?:alias|account|recipient|address|email|mailbox|user).*(?:n't|not) exist/is",$diag_code)) {
          $result['rule_cat']    = 'unknown';
          $result['rule_no']     = '0205';
        }
        /* rule: unknown
         * sample:
         * Diagnostic-Code: SMTP; 550-I'm sorry but xxxxx@yourdomain.com does not have an account here. I will not
         */
        elseif (preg_match ("/not have an account/is",$diag_code)) {
          $result['rule_cat']    = 'unknown';
          $result['rule_no']     = '0207';
        }
        /* rule: unknown
         * sample:
         * Diagnostic-Code: SMTP; 550 This account is not allowed...xxxxx@yourdomain.com
         */
        elseif (preg_match ("/(?:alias|account|recipient|address|email|mailbox|user).*is not allowed/is",$diag_code)) {
          $result['rule_cat']    = 'unknown';
          $result['rule_no']     = '0220';
        }
        /* rule: inactive
         * sample:
         * Diagnostic-Code: SMTP; 550 <xxxxx@yourdomain.com>: inactive user
         */
        elseif (preg_match ("/inactive.*(?:alias|account|recipient|address|email|mailbox|user)/is",$diag_code)) {
          $result['rule_cat']    = 'inactive';
          $result['rule_no']     = '0135';
        }
        /* rule: inactive
         * sample:
         * Diagnostic-Code: SMTP; 550 xxxxx@yourdomain.com Account Inactive
         */
        elseif (preg_match ("/(?:alias|account|recipient|address|email|mailbox|user).*Inactive/is",$diag_code)) {
          $result['rule_cat']    = 'inactive';
          $result['rule_no']     = '0155';
        }
        /* rule: inactive
         * sample:
         * Diagnostic-Code: SMTP; 550 <xxxxx@yourdomain.com>: Recipient address rejected: Account closed due to inactivity. No forwarding information is available.
         */
        elseif (preg_match ("/(?:alias|account|recipient|address|email|mailbox|user) closed due to inactivity/is",$diag_code)) {
          $result['rule_cat']    = 'inactive';
          $result['rule_no']     = '0170';
        }
        /* rule: inactive
         * sample:
         * Diagnostic-Code: SMTP; 550 <xxxxx@yourdomain.com>... User account not activated
         */
        elseif (preg_match ("/(?:alias|account|recipient|address|email|mailbox|user) not activated/is",$diag_code)) {
          $result['rule_cat']    = 'inactive';
          $result['rule_no']     = '0177';
        }
        /* rule: inactive
         * sample 1:
         * Diagnostic-Code: SMTP; 550 User suspended
         * sample 2:
         * Diagnostic-Code: SMTP; 550 account expired
         */
        elseif (preg_match ("/(?:alias|account|recipient|address|email|mailbox|user).*(?:suspend|expire)/is",$diag_code)) {
          $result['rule_cat']    = 'inactive';
          $result['rule_no']     = '0183';
        }
        /* rule: inactive
         * sample:
         * Diagnostic-Code: SMTP; 553 5.3.0 <xxxxx@yourdomain.com>... Recipient address no longer exists
         */
        elseif (preg_match ("/(?:alias|account|recipient|address|email|mailbox|user).*no longer exist/is",$diag_code)) {
          $result['rule_cat']    = 'inactive';
          $result['rule_no']     = '0184';
        }
        /* rule: inactive
         * sample:
         * Diagnostic-Code: SMTP; 553 VS10-RT Possible forgery or deactivated due to abuse (#5.1.1) 111.111.111.211^M
         */
        elseif (preg_match ("/(?:forgery|abuse)/is",$diag_code)) {
          $result['rule_cat']    = 'inactive';
          $result['rule_no']     = '0196';
        }
        /* rule: inactive
         * sample:
         * Diagnostic-Code: SMTP; 553 mailbox xxxxx@yourdomain.com is restricted
         */
        elseif (preg_match ("/(?:alias|account|recipient|address|email|mailbox|user).*restrict/is",$diag_code)) {
          $result['rule_cat']    = 'inactive';
          $result['rule_no']     = '0209';
        }
        /* rule: inactive
         * sample:
         * Diagnostic-Code: SMTP; 550 <xxxxx@yourdomain.com>: User status is locked.
         */
        elseif (preg_match ("/(?:alias|account|recipient|address|email|mailbox|user).*locked/is",$diag_code)) {
          $result['rule_cat']    = 'inactive';
          $result['rule_no']     = '0228';
        }
        /* rule: user_reject
         * sample:
         * Diagnostic-Code: SMTP; 553 User refused to receive this mail.
         */
        elseif (preg_match ("/(?:alias|account|recipient|address|email|mailbox|user) refused/is",$diag_code)) {
          $result['rule_cat']    = 'user_reject';
          $result['rule_no']     = '0156';
        }
        /* rule: user_reject
         * sample:
         * Diagnostic-Code: SMTP; 501 xxxxx@yourdomain.com Sender email is not in my domain
         */
        elseif (preg_match ("/sender.*not/is",$diag_code)) {
          $result['rule_cat']    = 'user_reject';
          $result['rule_no']     = '0206';
        }
        /* rule: command_reject
         * sample:
         * Diagnostic-Code: SMTP; 554 Message refused
         */
        elseif (preg_match ("/Message refused/is",$diag_code)) {
          $result['rule_cat']    = 'command_reject';
          $result['rule_no']     = '0175';
        }
        /* rule: command_reject
         * sample:
         * Diagnostic-Code: SMTP; 550 5.0.0 <xxxxx@yourdomain.com>... No permit
         */
        elseif (preg_match ("/No permit/is",$diag_code)) {
          $result['rule_cat']    = 'command_reject';
          $result['rule_no']     = '0190';
        }
        /* rule: command_reject
         * sample:
         * Diagnostic-Code: SMTP; 553 sorry, that domain isn't in my list of allowed rcpthosts (#5.5.3 - chkuser)
         */
        elseif (preg_match ("/domain isn't in.*allowed rcpthost/is",$diag_code)) {
          $result['rule_cat']    = 'command_reject';
          $result['rule_no']     = '0191';
        }
        /* rule: command_reject
         * sample:
         * Diagnostic-Code: SMTP; 553 AUTH FAILED - xxxxx@yourdomain.com^M
         */
        elseif (preg_match ("/AUTH FAILED/is",$diag_code)) {
          $result['rule_cat']    = 'command_reject';
          $result['rule_no']     = '0197';
        }
        /* rule: command_reject
         * sample 1:
         * Diagnostic-Code: SMTP; 550 relay not permitted^M
         * sample 2:
         * Diagnostic-Code: SMTP; 530 5.7.1 Relaying not allowed: xxxxx@yourdomain.com
         */
        elseif (preg_match ("/relay.*not.*(?:permit|allow)/is",$diag_code)) {
          $result['rule_cat']    = 'command_reject';
          $result['rule_no']     = '0201';
        }
        /* rule: command_reject
         * sample:
         *
         * Diagnostic-Code: SMTP; 550 not local host domain.com, not a gateway
         */
        elseif (preg_match ("/not local host/is",$diag_code)) {
          $result['rule_cat']    = 'command_reject';
          $result['rule_no']     = '0204';
        }
        /* rule: command_reject
         * sample:
         * Diagnostic-Code: SMTP; 500 Unauthorized relay msg rejected
         */
        elseif (preg_match ("/Unauthorized relay/is",$diag_code)) {
          $result['rule_cat']    = 'command_reject';
          $result['rule_no']     = '0215';
        }
        /* rule: command_reject
         * sample:
         * Diagnostic-Code: SMTP; 554 Transaction failed
         */
        elseif (preg_match ("/Transaction.*fail/is",$diag_code)) {
          $result['rule_cat']    = 'command_reject';
          $result['rule_no']     = '0221';
        }
        /* rule: command_reject
         * sample:
         * Diagnostic-Code: smtp;554 5.5.2 Invalid data in message
         */
        elseif (preg_match ("/Invalid data/is",$diag_code)) {
          $result['rule_cat']    = 'command_reject';
          $result['rule_no']     = '0223';
        }
        /* rule: command_reject
         * sample:
         * Diagnostic-Code: SMTP; 550 Local user only or Authentication mechanism
         */
        elseif (preg_match ("/Local user only/is",$diag_code)) {
          $result['rule_cat']    = 'command_reject';
          $result['rule_no']     = '0224';
        }
        /* rule: command_reject
         * sample:
         * Diagnostic-Code: SMTP; 550-ds176.domain.com [111.111.111.211] is currently not permitted to
         * relay through this server. Perhaps you have not logged into the pop/imap
         * server in the last 30 minutes or do not have SMTP Authentication turned on
         * in your email client.
         */
        elseif (preg_match ("/not.*permit.*to/is",$diag_code)) {
          $result['rule_cat']    = 'command_reject';
          $result['rule_no']     = '0225';
        }
        /* rule: content_reject
         * sample:
         * Diagnostic-Code: SMTP; 550 Content reject. FAAAANsG60M9BmDT.1
         */
        elseif (preg_match ("/Content reject/is",$diag_code)) {
          $result['rule_cat']    = 'content_reject';
          $result['rule_no']     = '0165';
        }
        /* rule: content_reject
         * sample:
         * Diagnostic-Code: SMTP; 552 MessageWall: MIME/REJECT: Invalid structure
         */
        elseif (preg_match ("/MIME\/REJECT/is",$diag_code)) {
          $result['rule_cat']    = 'content_reject';
          $result['rule_no']     = '0212';
        }
        /* rule: content_reject
         * sample:
         * Diagnostic-Code: smtp; 554 5.6.0 Message with invalid header rejected, id=13462-01 - MIME error: error: UnexpectedBound: part didn't end with expected boundary [in multipart message]; EOSToken: EOF; EOSType: EOF
         */
        elseif (preg_match ("/MIME error/is",$diag_code)) {
          $result['rule_cat']    = 'content_reject';
          $result['rule_no']     = '0217';
        }
        /* rule: content_reject
         * sample:
         * Diagnostic-Code: SMTP; 553 Mail data refused by AISP, rule [169648].
         */
        elseif (preg_match ("/Mail data refused.*AISP/is",$diag_code)) {
          $result['rule_cat']    = 'content_reject';
          $result['rule_no']     = '0218';
        }
        /* rule: dns_unknown
         * sample:
         * Diagnostic-Code: SMTP; 550 Host unknown
         */
        elseif (preg_match ("/Host unknown/is",$diag_code)) {
          $result['rule_cat']    = 'dns_unknown';
          $result['rule_no']     = '0130';
        }
        /* rule: dns_unknown
         * sample:
         * Diagnostic-Code: SMTP; 553 Specified domain is not allowed.
         */
        elseif (preg_match ("/Specified domain.*not.*allow/is",$diag_code)) {
          $result['rule_cat']    = 'dns_unknown';
          $result['rule_no']     = '0180';
        }
        /* rule: dns_unknown
         * sample:
         * Diagnostic-Code: X-Postfix; delivery temporarily suspended: connect to
         * 111.111.11.112[111.111.11.112]: No route to host
         */
        elseif (preg_match ("/No route to host/is",$diag_code)) {
          $result['rule_cat']    = 'dns_unknown';
          $result['rule_no']     = '0188';
        }
        /* rule: dns_unknown
         * sample:
         * Diagnostic-Code: SMTP; 550 unrouteable address
         */
        elseif (preg_match ("/unrouteable address/is",$diag_code)) {
          $result['rule_cat']    = 'dns_unknown';
          $result['rule_no']     = '0208';
        }
        /* rule: defer
         * sample:
         * Diagnostic-Code: SMTP; 451 System(u) busy, try again later.
         */
        elseif (preg_match ("/System.*busy/is",$diag_code)) {
          $result['rule_cat']    = 'defer';
          $result['rule_no']     = '0112';
        }
        /* rule: defer
         * sample:
         * Diagnostic-Code: SMTP; 451 mta172.mail.tpe.domain.com Resources temporarily unavailable. Please try again later.  [#4.16.4:70].
         */
        elseif (preg_match ("/Resources temporarily unavailable/is",$diag_code)) {
          $result['rule_cat']    = 'defer';
          $result['rule_no']     = '0116';
        }
        /* rule: antispam, deny ip
         * sample:
         * Diagnostic-Code: SMTP; 554 sender is rejected: 0,mx20,wKjR5bDrnoM2yNtEZVAkBg==.32467S2
         */
        elseif (preg_match ("/sender is rejected/is",$diag_code)) {
          $result['rule_cat']    = 'antispam';
          $result['rule_no']     = '0101';
        }
        /* rule: antispam, deny ip
         * sample:
         * Diagnostic-Code: SMTP; 554 <unknown[111.111.111.000]>: Client host rejected: Access denied
         */
        elseif (preg_match ("/Client host rejected/is",$diag_code)) {
          $result['rule_cat']    = 'antispam';
          $result['rule_no']     = '0102';
        }
        /* rule: antispam, mismatch ip
         * sample:
         * Diagnostic-Code: SMTP; 554 Connection refused(mx). MAIL FROM [xxxxx@yourdomain.com] mismatches client IP [111.111.111.000].
         */
        elseif (preg_match ("/MAIL FROM(.*)mismatches client IP/is",$diag_code)) {
          $result['rule_cat']    = 'antispam';
          $result['rule_no']     = '0104';
        }
        /* rule: antispam, deny ip
         * sample:
         * Diagnostic-Code: SMTP; 554 Please visit http:// antispam.domain.com/denyip.php?IP=111.111.111.000 (#5.7.1)
         */
        elseif (preg_match ("/denyip/is",$diag_code)) {
          $result['rule_cat']    = 'antispam';
          $result['rule_no']     = '0144';
        }
        /* rule: antispam, deny ip
         * sample:
         * Diagnostic-Code: SMTP; 554 Service unavailable; Client host [111.111.111.211] blocked using dynablock.domain.com; Your message could not be delivered due to complaints we received regarding the IP address you're using or your ISP. See http:// blackholes.domain.com/ Error: WS-02^M
         */
        elseif (preg_match ("/client host.*blocked/is",$diag_code)) {
          $result['rule_cat']    = 'antispam';
          $result['rule_no']     = '0201';
        }
        /* rule: antispam, reject
         * sample:
         * Diagnostic-Code: SMTP; 550 Requested action not taken: mail IsCNAPF76kMDARUY.56621S2 is rejected,mx3,BM
         */
        elseif (preg_match ("/mail.*reject/is",$diag_code)) {
          $result['rule_cat']    = 'antispam';
          $result['rule_no']     = '0147';
        }
        /* rule: antispam
         * sample:
         * Diagnostic-Code: SMTP; 552 sorry, the spam message is detected (#5.6.0)
         */
        elseif (preg_match ("/spam.*detect/is",$diag_code)) {
          $result['rule_cat']    = 'antispam';
          $result['rule_no']     = '0162';
        }
        /* rule: antispam
         * sample:
         * Diagnostic-Code: SMTP; 554 5.7.1 Rejected as Spam see: http:// rejected.domain.com/help/spam/rejected.html
         */
        elseif (preg_match ("/reject.*spam/is",$diag_code)) {
          $result['rule_cat']    = 'antispam';
          $result['rule_no']     = '0216';
        }
        /* rule: antispam
         * sample:
         * Diagnostic-Code: SMTP; 553 5.7.1 <xxxxx@yourdomain.com>... SpamTrap=reject mode, dsn=5.7.1, Message blocked by BOX Solutions (www.domain.com) SpamTrap Technology, please contact the domain.com site manager for help: (ctlusr8012).^M
         */
        elseif (preg_match ("/SpamTrap/is",$diag_code)) {
          $result['rule_cat']    = 'antispam';
          $result['rule_no']     = '0200';
        }
        /* rule: antispam, mailfrom mismatch
         * sample:
         * Diagnostic-Code: SMTP; 550 Verify mailfrom failed,blocked
         */
        elseif (preg_match ("/Verify mailfrom failed/is",$diag_code)) {
          $result['rule_cat']    = 'antispam';
          $result['rule_no']     = '0210';
        }
        /* rule: antispam, mailfrom mismatch
         * sample:
         * Diagnostic-Code: SMTP; 550 Error: MAIL FROM is mismatched with message header from address!
         */
        elseif (preg_match ("/MAIL.*FROM.*mismatch/is",$diag_code)) {
          $result['rule_cat']    = 'antispam';
          $result['rule_no']     = '0226';
        }
        /* rule: antispam
         * sample:
         * Diagnostic-Code: SMTP; 554 5.7.1 Message scored too high on spam scale.  For help, please quote incident ID 22492290.
         */
        elseif (preg_match ("/spam scale/is",$diag_code)) {
          $result['rule_cat']    = 'antispam';
          $result['rule_no']     = '0211';
        }
        /* rule: antispam
         * sample:
         * Diagnostic-Code: SMTP; 554 5.7.1 reject: Client host bypassing service provider's mail relay: ds176.domain.com
         8?
        elseif (preg_match ("/Client host bypass/is",$diag_code)) {
          $result['rule_cat']    = 'antispam';
          $result['rule_no']     = '0229';
        }
        /* rule: antispam
         * sample:
         * Diagnostic-Code: SMTP; 550 sorry, it seems as a junk mail
         */
        elseif (preg_match ("/junk mail/is",$diag_code)) {
          $result['rule_cat']    = 'antispam';
          $result['rule_no']     = '0230';
        }
        /* rule: antispam
         * sample:
         * Diagnostic-Code: SMTP; 553-Message filtered. Please see the FAQs section on spam
         */
        elseif (preg_match ("/message filtered/is",$diag_code)) {
          $result['rule_cat']    = 'antispam';
          $result['rule_no']     = '0227';
        }
        /* rule: antispam, subject filter
         * sample:
         * Diagnostic-Code: SMTP; 554 5.7.1 The message from (<xxxxx@yourdomain.com>) with the subject of ( *(ca2639) 7|-{%2E* : {2"(%EJ;y} (SBI$#$@<K*:7s1!=l~) matches a profile the Internet community may consider spam. Please revise your message before resending.
         */
        elseif (preg_match ("/subject.*consider.*spam/is",$diag_code)) {
          $result['rule_cat']    = 'antispam';
          $result['rule_no']     = '0222';
        }
        /* rule: internal_error
         * sample:
         * Diagnostic-Code: SMTP; 451 Temporary local problem - please try later
         */
        elseif (preg_match ("/Temporary local problem/is",$diag_code)) {
          $result['rule_cat']    = 'internal_error';
          $result['rule_no']     = '0142';
        }
        /* rule: internal_error
         * sample:
         * Diagnostic-Code: SMTP; 553 5.3.5 system config error
         */
        elseif (preg_match ("/system config error/is",$diag_code)) {
          $result['rule_cat']    = 'internal_error';
          $result['rule_no']     = '0153';
        }
        /* rule: delayed
         * sample:
         * Diagnostic-Code: X-Postfix; delivery temporarily suspended: conversation with^M
         * 111.111.111.11[111.111.111.11] timed out while sending end of data -- message may be^M
         * sent more than once
         */
        elseif (preg_match ("/delivery.*suspend/is",$diag_code)) {
          $result['rule_cat']    = 'delayed';
          $result['rule_no']     = '0213';
        }

        // =========== rules based on the dsn_msg ===============
        /* rule: unknown
         * sample:
         * ----- The following addresses had permanent fatal errors -----
         * <xxxxx@yourdomain.com>
         * ----- Transcript of session follows -----
         * ... while talking to mta1.domain.com.:
         * >>> DATA
         * <<< 503 All recipients are invalid
         * 554 5.0.0 Service unavailable
         */
        elseif (preg_match ("/(?:alias|account|recipient|address|email|mailbox|user)(.*)invalid/i",$dsn_msg)) {
          $result['rule_cat']    = 'unknown';
          $result['rule_no']     = '0107';
        }
        /* rule: unknown
         * sample:
         * ----- Transcript of session follows -----
         * xxxxx@yourdomain.com... Deferred: No such file or directory
         */
        elseif (preg_match ("/Deferred.*No such.*(?:file|directory)/i",$dsn_msg)) {
          $result['rule_cat']    = 'unknown';
          $result['rule_no']     = '0141';
        }
        /* rule: unknown
         * sample:
         * Failed to deliver to '<xxxxx@yourdomain.com>'^M
         * LOCAL module(account xxxx) reports:^M
         * mail receiving disabled^M
         */
        elseif (preg_match ("/mail receiving disabled/i",$dsn_msg)) {
          $result['rule_cat']    = 'unknown';
          $result['rule_no']     = '0194';
        }
        /* rule: unknown
         * sample:
         * - These recipients of your message have been processed by the mail server:^M
         * xxxxx@yourdomain.com; Failed; 5.1.1 (bad destination mailbox address)
         */
        elseif (preg_match ("/bad.*(?:alias|account|recipient|address|email|mailbox|user)/i",$dsn_msg)) {
          $result['rule_cat']    = 'unknown';
          $result['rule_no']     = '227';
        }
        /* rule: full
         * sample 1:
         * This Message was undeliverable due to the following reason:
         * The user(s) account is temporarily over quota.
         * <xxxxx@yourdomain.com>
         * sample 2:
         *  Recipient address: xxxxx@yourdomain.com
         *  Reason: Over quota
         */
        elseif (preg_match ("/over.*quota/i",$dsn_msg)) {
          $result['rule_cat']    = 'full';
          $result['rule_no']     = '0131';
        }
        /* rule: full
         * sample:
         * Sorry the recipient quota limit is exceeded.
         * This message is returned as an error.
         */
        elseif (preg_match ("/quota.*exceeded/i",$dsn_msg)) {
          $result['rule_cat']    = 'full';
          $result['rule_no']     = '0150';
        }
        /* rule: full
         * sample:
         * The user to whom this message was addressed has exceeded the allowed mailbox
         * quota. Please resend the message at a later time.
         */
        elseif (preg_match ("/exceed.*\n?.*quota/i",$dsn_msg)) {
          $result['rule_cat']    = 'full';
          $result['rule_no']     = '0187';
        }
        /* rule: full
         * sample 1:
         * Failed to deliver to '<xxxxx@yourdomain.com>'
         * LOCAL module(account xxxxxx) reports:
         * account is full (quota exceeded)
         * sample 2:
         * Error in fabiomod_sql_glob_init: no data source specified - database access disabled
         * [Fri Feb 17 23:29:38 PST 2006] full error for caltsmy:
         * that member's mailbox is full
         * 550 5.0.0 <xxxxx@yourdomain.com>... Can't create output
         */
        elseif (preg_match ("/(?:alias|account|recipient|address|email|mailbox|user).*full/i",$dsn_msg)) {
          $result['rule_cat']    = 'full';
          $result['rule_no']     = '0132';
        }
        /* rule: full
         * sample:
         * gaosong "(0), ErrMsg=Mailbox space not enough (space limit is 10240KB)
         */
        elseif (preg_match ("/space.*not.*enough/i",$dsn_msg)) {
          $result['rule_cat']    = 'full';
          $result['rule_no']     = '0219';
        }
        /* rule: defer
         * sample 1:
         * ----- Transcript of session follows -----
         * xxxxx@yourdomain.com... Deferred: Connection refused by nomail.tpe.domain.com.
         * Message could not be delivered for 5 days
         * Message will be deleted from queue
         * sample 2:
         * 451 4.4.1 reply: read error from www.domain.com.
         * xxxxx@yourdomain.com... Deferred: Connection reset by www.domain.com.
         */
        elseif (preg_match ("/Deferred.*Connection (?:refused|reset)/i",$dsn_msg)) {
          $result['rule_cat']    = 'defer';
          $result['rule_no']     = '0115';
        }
        /* rule: dns_unknown
         * sample:
         * ----- The following addresses had permanent fatal errors -----
         * Tan XXXX SSSS <xxxxx@yourdomain..com>
         * ----- Transcript of session follows -----
         * 553 5.1.2 XXXX SSSS <xxxxx@yourdomain..com>... Invalid host name
         */
        elseif (preg_match ("/Invalid host name/i",$dsn_msg)) {
          $result['rule_cat']    = 'dns_unknown';
          $result['rule_no']     = '0109';
        }
        /* rule: dns_unknown
         * sample:
         * ----- Transcript of session follows -----
         * xxxxx@yourdomain.com... Deferred: mail.domain.com.: No route to host
         */
        elseif (preg_match ("/Deferred.*No route to host/i",$dsn_msg)) {
          $result['rule_cat']    = 'dns_unknown';
          $result['rule_no']     = '0109';
        }
        /* rule: dns_unknown
         * sample:
         * ----- Transcript of session follows -----
         * 550 5.1.2 xxxxx@yourdomain.com... Host unknown (Name server: .: no data known)
         */
        elseif (preg_match ("/Host unknown/i",$dsn_msg)) {
          $result['rule_cat']    = 'dns_unknown';
          $result['rule_no']     = '0140';
        }
        /* rule: dns_unknown
         * sample:
         * ----- Transcript of session follows -----
         * 451 HOTMAIL.com.tw: Name server timeout
         * Message could not be delivered for 5 days
         * Message will be deleted from queue
         */
        elseif (preg_match ("/Name server timeout/i",$dsn_msg)) {
          $result['rule_cat']    = 'dns_unknown';
          $result['rule_no']     = '0118';
        }
        /* rule: dns_unknown
         * sample:
         * ----- Transcript of session follows -----
         * xxxxx@yourdomain.com... Deferred: Connection timed out with hkfight.com.
         * Message could not be delivered for 5 days
         * Message will be deleted from queue
         */
        elseif (preg_match ("/Deferred.*Connection.*tim(?:e|ed).*out/i",$dsn_msg)) {
          $result['rule_cat']    = 'dns_unknown';
          $result['rule_no']     = '0119';
        }
        /* rule: dns_unknown
         * sample:
         * ----- Transcript of session follows -----
         * xxxxx@yourdomain.com... Deferred: Name server: domain.com.: host name lookup failure
         */
        elseif (preg_match ("/Deferred.*host name lookup failure/i",$dsn_msg)) {
          $result['rule_cat']    = 'dns_unknown';
          $result['rule_no']     = '0121';
        }
        /* rule: dns_loop
         * sample:
         * ----- Transcript of session follows -----^M
         * 554 5.0.0 MX list for znet.ws. points back to mail01.domain.com^M
         * 554 5.3.5 Local configuration error^M
         */
        elseif (preg_match ("/MX list.*point.*back/i",$dsn_msg)) {
          $result['rule_cat']    = 'dns_loop';
          $result['rule_no']     = '0199';
        }
        /* rule: internal_error
         * sample:
         * ----- Transcript of session follows -----
         * 451 4.0.0 I/O error
         */
        elseif (preg_match ("/I\/O error/i",$dsn_msg)) {
          $result['rule_cat']    = 'internal_error';
          $result['rule_no']     = '0120';
        }
        /* rule: internal_error
         * sample:
         * Failed to deliver to 'xxxxx@yourdomain.com'^M
         * SMTP module(domain domain.com) reports:^M
         * connection with mx1.mail.domain.com is broken^M
         */
        elseif (preg_match ("/connection.*broken/i",$dsn_msg)) {
          $result['rule_cat']    = 'internal_error';
          $result['rule_no']     = '0231';
        }
        /* rule: other
         * sample:
         * Delivery to the following recipients failed.
         * xxxxx@yourdomain.com
         */
        elseif (preg_match ("/Delivery to the following recipients failed.*\n.*\n.*".$result['email']."/i",$dsn_msg)) {
          $result['rule_cat']    = 'other';
          $result['rule_no']     = '0176';
        }

        // Followings are wind-up rule: must be the last one
        //   many other rules msg end up with "550 5.1.1 ... User unknown"
        //   many other rules msg end up with "554 5.0.0 Service unavailable"

        /* rule: unknown
         * sample 1:
         * ----- The following addresses had permanent fatal errors -----^M
         * <xxxxx@yourdomain.com>^M
         * (reason: User unknown)^M
         * sample 2:
         * 550 5.1.1 xxxxx@yourdomain.com... User unknown^M
         */
        elseif (preg_match ("/User unknown/i",$dsn_msg)) {
          $result['rule_cat']    = 'unknown';
          $result['rule_no']     = '0193';
        }
        /* rule: unknown
         * sample:
         * 554 5.0.0 Service unavailable
         */
        elseif (preg_match ("/Service unavailable/i",$dsn_msg)) {
          $result['rule_cat']    = 'unknown';
          $result['rule_no']     = '0214';
        }
        break;
      case 'delayed':
        $result['rule_cat']    = 'delayed';
        $result['rule_no']     = '0110';
        break;
      case 'delivered':
      case 'relayed':
      case 'expanded': // unhandled cases
        break;
      default :
        break;
    }
  }

  global $rule_categories, $bmh_newline;
  if ($result['rule_no'] == '0000') {
    if ($debug_mode) {
      echo 'email: ' . $result['email'] . $bmh_newline;
      echo 'Action: ' . $action . $bmh_newline;
      echo 'Status: ' . $status_code . $bmh_newline;
      echo 'Diagnostic-Code: ' . $diag_code . $bmh_newline;
      echo "DSN Message:<br />\n" . $dsn_msg . $bmh_newline;
      echo $bmh_newline;
    }
  } else {
    if ($result['bounce_type'] === false) {
      $result['bounce_type'] = $rule_categories[$result['rule_cat']]['bounce_type'];
      $result['remove']      = $rule_categories[$result['rule_cat']]['remove'];
    }
  }
  return $result;
}
?>