/**
 * Defined bounce parsing rules for non-standard DSN
 *
 * @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'
 * @author  Kevin : Wed Sep 06 15:22:22 PDT 2006
 */
function bmhBodyRules($body, $structure, $debug_mode = false)
{
    // initial the result array
    $result = array('email' => '', 'bounce_type' => false, 'remove' => 0, 'rule_cat' => 'unrecognized', 'rule_no' => '0000', 'body' => wrapmsg($body));
    /*if (isset($structure->parameters[0]->value) && $structure->parameters[0]->value=='CHARSET') {
    	$result['charset']=$structure->parameters[0]->value;
        }*/
    // ======== rule =========
    if (false) {
    } elseif (preg_match("/<(\\S+@\\S+\\w)>.*\n?.*no mailbox/i", $body, $match)) {
        $result['rule_cat'] = 'unknown';
        $result['rule_no'] = '0157';
        $result['email'] = $match[1];
    } 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];
    } 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];
    } 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];
    } elseif (preg_match("/(\\S+@\\S+\\w).*\n?.*Unrouteable address/i", $body, $match)) {
        $result['rule_cat'] = 'unknown';
        $result['rule_no'] = '0179';
        $result['email'] = $match[1];
    } 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];
    } 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];
    } 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];
    } 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];
    } 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];
    } 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];
    } elseif (preg_match("/quota exceeded.*\n?.*<(\\S+@\\S+\\w)>/i", $body, $match)) {
        $result['rule_cat'] = 'full';
        $result['rule_no'] = '0126';
        $result['email'] = $match[1];
    } elseif (preg_match("/<(\\S+@\\S+\\w)>.*\n?.*quota exceeded/i", $body, $match)) {
        $result['rule_cat'] = 'full';
        $result['rule_no'] = '0158';
        $result['email'] = $match[1];
    } 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];
    } 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];
    } 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];
    } elseif (preg_match("/(\\S+@\\S+\\w).*inactive account/i", $body, $match)) {
        $result['rule_cat'] = 'inactive';
        $result['rule_no'] = '0181';
        $result['email'] = $match[1];
    } 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];
    } 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];
    } 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];
    } elseif (preg_match("/^AutoReply message from (\\S+@\\S+\\w)/i", $body, $match)) {
        $result['rule_cat'] = 'autoreply';
        $result['rule_no'] = '0167';
        $result['email'] = $match[1];
    } 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];
    } elseif (preg_match('/Hi\\. This is the/', $body) && preg_match("/<(\\S+@\\S+\\w)>:/", $body, $match)) {
        // QMAIL
        $result['email'] = $match[1];
        $result['rule_cat'] = 'qmail_bounce';
        $result['rule_no'] = '0237';
        // rule : mailbox unknown;
        // sample:
        //
        // Hi. This is the qmail-send program at a.mx.domainoo.fr.
        // I'm afraid I wasn't able to deliver your message to the following addresses.
        // This is a permanent error; I've given up. Sorry it didn't work out.
        //
        // <*****@*****.**>:
        // 193.51.16.153 does not like recipient.
        // Remote host said: 550 5.1.1 <*****@*****.**>: Recipient address rejected: User unknown in relay recipient table
        // Giving up on 193.51.16.153.
        if (preg_match("/(?:User|Recipient) unknown/i", $body)) {
            $result['rule_cat'] = 'unknown';
            $result['rule_no'] = '0238';
        } else {
            if (preg_match('/mailbox is full/i', $body)) {
                $result['rule_cat'] = 'full';
                $result['rule_no'] = '0239';
            } else {
                if (preg_match('/exceed.*quotas?/i', $body)) {
                    $result['rule_cat'] = 'full';
                    $result['rule_no'] = '0240';
                } else {
                    if (preg_match('/user does not exist/i', $body)) {
                        $result['rule_cat'] = 'unknown';
                        $result['rule_no'] = '0241';
                    }
                }
            }
        }
    }
    global $rule_categories;
    if ($result['rule_no'] == '0000') {
        if ($debug_mode) {
            echo "Body :\n{$body}\n";
            echo "\n";
        }
    } 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'
 * @author  Kevin : Wed Sep 06 15:22:22 PDT 2006
 */
function bmhDSNRules($dsn_msg, $dsn_report, $debug_mode = false)
{
    // initial the result array
    $result = array('email' => '', 'bounce_type' => false, 'remove' => 0, 'rule_cat' => 'unrecognized', 'rule_no' => '0000', 'dsn_msg' => wrapmsg($dsn_msg), 'dsn_report' => wrapmsg($dsn_report));
    $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)) {
        // TRICKY : or using the regex written by myself : /Original-Recipient: rfc822;(?:.*<| *)(\S+@\S+\w)/i
        $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['dsn_original_rcpt'] = $email_arr[0]->mailbox . '@' . $email_arr[0]->host;
        }
    }
    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['dsn_final_rcpt'] = $email_arr[0]->mailbox . '@' . $email_arr[0]->host;
        }
    }
    if (!empty($result['dsn_original_rcpt'])) {
        $result['email'] = $result['dsn_original_rcpt'];
    } else {
        if (!empty($result['dsn_final_rcpt'])) {
            $result['email'] = $result['dsn_final_rcpt'];
        }
    }
    if (!empty($result['email'])) {
        if ($result['email'] == $result['dsn_original_rcpt']) {
            $result['dsn_original_rcpt'] = '-';
        }
        if ($result['email'] == $result['dsn_final_rcpt']) {
            $result['dsn_final_rcpt'] = '-';
        }
    }
    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];
    }
    // TRICKY : 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 <*****@*****.**>
        //
        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':
                $result['rule_cat'] = 'dsn_failed';
                $result['rule_no'] = '9999';
                $code = explode('.', $status_code);
                if (checkcode($code, 4)) {
                    // 4.X.X Persistent Transient Failure
                    // A persistent transient failure is one in which the message as sent
                    // is valid, but some temporary event prevents the successful sending
                    // of the message. Sending in the future may be successful.
                    $result['rule_cat'] = 'delayed';
                    $result['rule_no'] = '0245';
                } elseif (checkcode($code, 5, 1)) {
                    // 5.1.0 Other address status
                    // 5.1.1 Bad destination mailbox address
                    // 5.1.2 Bad destination system address
                    // 5.1.3 Bad destination mailbox address syntax
                    // 5.1.4 Destination mailbox address ambiguous
                    // 5.1.5 Destination mailbox address valid
                    // 5.1.6 Mailbox has moved
                    // 5.1.7 Bad sender's mailbox address syntax
                    // 5.1.8 Bad sender's system address
                    $result['rule_cat'] = 'unknown';
                    $result['rule_no'] = '0244';
                } elseif (checkcode($code, 5, 4, 4)) {
                    //Unable to route
                    $result['rule_cat'] = 'dns_unknown';
                    $result['rule_no'] = '0241';
                } else {
                    if (checkcode($code, 5, 2)) {
                        // 5.2.0 Other or undefined mailbox status
                        // 5.2.1 Mailbox disabled, not accepting messages
                        // 5.2.2 Mailbox full
                        // 5.2.3 Message length exceeds administrative limit.
                        // 5.2.4 Mailing list expansion problem
                        switch ($code[0]) {
                            case 0:
                            case 1:
                                $result['rule_cat'] = 'inactive';
                                $result['rule_no'] = '0247';
                                break;
                            case 2:
                                $result['rule_cat'] = 'full';
                                $result['rule_no'] = '0242';
                                break;
                            case 3:
                                $result['rule_cat'] = 'oversize';
                                $result['rule_no'] = '0246';
                                break;
                            case 4:
                                break;
                            default:
                                break;
                        }
                    } else {
                        if (checkcode($code, 5, 7)) {
                            // 5.7.0 Other or undefined security status
                            // 5.7.1 Delivery not authorized, message refused
                            // 5.7.2 Mailing list expansion prohibited
                            // 5.7.3 Security conversion required but not possible
                            // 5.7.4 Security features not supported
                            // 5.7.5 Cryptographic failure
                            // 5.7.6 Cryptographic algorithm not supported
                            // 5.7.7 Message integrity failure
                            switch ($code[2]) {
                                case 1:
                                    $result['rule_cat'] = 'antispam';
                                    $result['rule_no'] = '0243';
                                    break;
                                default:
                                    break;
                            }
                        } elseif (preg_match("/over.*quota/is", $diag_code)) {
                            $result['rule_cat'] = 'full';
                            $result['rule_no'] = '0105';
                        } elseif (preg_match("/exceed.*quota/is", $diag_code)) {
                            $result['rule_cat'] = 'full';
                            $result['rule_no'] = '0129';
                        } elseif (preg_match("/quota.*exceed/is", $diag_code)) {
                            $result['rule_cat'] = 'full';
                            $result['rule_no'] = '0250';
                        } elseif (preg_match("/(?:alias|account|recipient|address|email|mailbox|user).*full/is", $diag_code)) {
                            $result['rule_cat'] = 'full';
                            $result['rule_no'] = '0145';
                        } elseif (preg_match("/Insufficient system storage/is", $diag_code)) {
                            $result['rule_cat'] = 'full';
                            $result['rule_no'] = '0134';
                        } elseif (preg_match("/File too large/is", $diag_code)) {
                            $result['rule_cat'] = 'full';
                            $result['rule_no'] = '0192';
                        } elseif (preg_match("/larger than.*limit/is", $diag_code)) {
                            $result['rule_cat'] = 'oversize';
                            $result['rule_no'] = '0146';
                        } elseif (preg_match("/(?:alias|account|recipient|address|email|mailbox|user)(.*)not(.*)list/is", $diag_code)) {
                            $result['rule_cat'] = 'unknown';
                            $result['rule_no'] = '0103';
                        } elseif (preg_match("/user path no exist/is", $diag_code)) {
                            $result['rule_cat'] = 'unknown';
                            $result['rule_no'] = '0106';
                        } elseif (preg_match("/Relay.*(?:denied|prohibited)/is", $diag_code)) {
                            $result['rule_cat'] = 'unknown';
                            $result['rule_no'] = '0108';
                        } elseif (preg_match("/no.*valid.*(?:alias|account|recipient|address|email|mailbox|user)/is", $diag_code)) {
                            $result['rule_cat'] = 'unknown';
                            $result['rule_no'] = '0185';
                        } elseif (preg_match("/Invalid.*(?:alias|account|recipient|address|email|mailbox|user)/is", $diag_code)) {
                            $result['rule_cat'] = 'unknown';
                            $result['rule_no'] = '0111';
                        } elseif (preg_match("/(?:alias|account|recipient|address|email|mailbox|user).*(?:disabled|discontinued)/is", $diag_code)) {
                            $result['rule_cat'] = 'unknown';
                            $result['rule_no'] = '0114';
                        } elseif (preg_match("/user doesn't have.*account/is", $diag_code)) {
                            $result['rule_cat'] = 'unknown';
                            $result['rule_no'] = '0127';
                        } elseif (preg_match("/(?:unknown|illegal).*(?:alias|account|recipient|address|email|mailbox|user)/is", $diag_code)) {
                            $result['rule_cat'] = 'unknown';
                            $result['rule_no'] = '0128';
                        } 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';
                        } elseif (preg_match("/no (?:alias|account|recipient|address|email|mailbox|user)/is", $diag_code)) {
                            $result['rule_cat'] = 'unknown';
                            $result['rule_no'] = '0123';
                        } elseif (preg_match("/(?:alias|account|recipient|address|email|mailbox|user).*unknown/is", $diag_code)) {
                            $result['rule_cat'] = 'unknown';
                            $result['rule_no'] = '0125';
                        } elseif (preg_match("/(?:alias|account|recipient|address|email|mailbox|user).*disabled/is", $diag_code)) {
                            $result['rule_cat'] = 'unknown';
                            $result['rule_no'] = '0133';
                        } elseif (preg_match("/No such (?:alias|account|recipient|address|email|mailbox|user)/is", $diag_code)) {
                            $result['rule_cat'] = 'unknown';
                            $result['rule_no'] = '0143';
                        } elseif (preg_match("/(?:alias|account|recipient|address|email|mailbox|user).*NOT FOUND/is", $diag_code)) {
                            $result['rule_cat'] = 'unknown';
                            $result['rule_no'] = '0136';
                        } elseif (preg_match("/deactivated (?:alias|account|recipient|address|email|mailbox|user)/is", $diag_code)) {
                            $result['rule_cat'] = 'unknown';
                            $result['rule_no'] = '0138';
                        } elseif (preg_match("/(?:alias|account|recipient|address|email|mailbox|user).*reject/is", $diag_code)) {
                            $result['rule_cat'] = 'unknown';
                            $result['rule_no'] = '0148';
                        } elseif (preg_match("/bounce.*administrator/is", $diag_code)) {
                            $result['rule_cat'] = 'unknown';
                            $result['rule_no'] = '0151';
                        } elseif (preg_match("/<.*>.*disabled/is", $diag_code)) {
                            $result['rule_cat'] = 'unknown';
                            $result['rule_no'] = '0152';
                        } elseif (preg_match("/not our customer/is", $diag_code)) {
                            $result['rule_cat'] = 'unknown';
                            $result['rule_no'] = '0154';
                        } elseif (preg_match("/Wrong (?:alias|account|recipient|address|email|mailbox|user)/is", $diag_code)) {
                            $result['rule_cat'] = 'unknown';
                            $result['rule_no'] = '0159';
                        } elseif (preg_match("/(?:unknown|bad).*(?:alias|account|recipient|address|email|mailbox|user)/is", $diag_code)) {
                            $result['rule_cat'] = 'unknown';
                            $result['rule_no'] = '0160';
                        } elseif (preg_match("/(?:alias|account|recipient|address|email|mailbox|user).*not OK/is", $diag_code)) {
                            $result['rule_cat'] = 'unknown';
                            $result['rule_no'] = '0186';
                        } elseif (preg_match("/Access.*Denied/is", $diag_code)) {
                            $result['rule_cat'] = 'unknown';
                            $result['rule_no'] = '0189';
                        } elseif (preg_match("/(?:alias|account|recipient|address|email|mailbox|user).*lookup.*fail/is", $diag_code)) {
                            $result['rule_cat'] = 'unknown';
                            $result['rule_no'] = '0195';
                        } elseif (preg_match("/(?:recipient|address|email|mailbox|user).*not.*member of domain/is", $diag_code)) {
                            $result['rule_cat'] = 'unknown';
                            $result['rule_no'] = '0198';
                        } elseif (preg_match("/(?:alias|account|recipient|address|email|mailbox|user).*cannot be verified/is", $diag_code)) {
                            $result['rule_cat'] = 'unknown';
                            $result['rule_no'] = '0202';
                        } elseif (preg_match("/Unable to relay/is", $diag_code)) {
                            $result['rule_cat'] = 'unknown';
                            $result['rule_no'] = '0203';
                        } 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';
                        } elseif (preg_match("/not have an account/is", $diag_code)) {
                            $result['rule_cat'] = 'unknown';
                            $result['rule_no'] = '0207';
                        } elseif (preg_match("/(?:alias|account|recipient|address|email|mailbox|user).*is not allowed/is", $diag_code)) {
                            $result['rule_cat'] = 'unknown';
                            $result['rule_no'] = '0220';
                        } elseif (preg_match("/inactive.*(?:alias|account|recipient|address|email|mailbox|user)/is", $diag_code)) {
                            $result['rule_cat'] = 'inactive';
                            $result['rule_no'] = '0135';
                        } elseif (preg_match("/(?:alias|account|recipient|address|email|mailbox|user).*Inactive/is", $diag_code)) {
                            $result['rule_cat'] = 'inactive';
                            $result['rule_no'] = '0155';
                        } 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';
                        } elseif (preg_match("/(?:alias|account|recipient|address|email|mailbox|user) not activated/is", $diag_code)) {
                            $result['rule_cat'] = 'inactive';
                            $result['rule_no'] = '0177';
                        } elseif (preg_match("/(?:alias|account|recipient|address|email|mailbox|user).*(?:suspend|expire)/is", $diag_code)) {
                            $result['rule_cat'] = 'inactive';
                            $result['rule_no'] = '0183';
                        } elseif (preg_match("/(?:alias|account|recipient|address|email|mailbox|user).*no longer exist/is", $diag_code)) {
                            $result['rule_cat'] = 'inactive';
                            $result['rule_no'] = '0184';
                        } elseif (preg_match("/(?:forgery|abuse)/is", $diag_code)) {
                            $result['rule_cat'] = 'inactive';
                            $result['rule_no'] = '0196';
                        } elseif (preg_match("/(?:alias|account|recipient|address|email|mailbox|user).*restrict/is", $diag_code)) {
                            $result['rule_cat'] = 'inactive';
                            $result['rule_no'] = '0209';
                        } elseif (preg_match("/(?:alias|account|recipient|address|email|mailbox|user).*locked/is", $diag_code)) {
                            $result['rule_cat'] = 'inactive';
                            $result['rule_no'] = '0228';
                        } elseif (preg_match("/recipient never logged/is", $diag_code)) {
                            $result['rule_cat'] = 'inactive';
                            $result['rule_no'] = '0252';
                        } elseif (preg_match("/(?:alias|account|recipient|address|email|mailbox|user) refused/is", $diag_code)) {
                            $result['rule_cat'] = 'user_reject';
                            $result['rule_no'] = '0156';
                        } elseif (preg_match("/sender.*not/is", $diag_code)) {
                            $result['rule_cat'] = 'user_reject';
                            $result['rule_no'] = '0206';
                        } elseif (preg_match("/Message refused/is", $diag_code)) {
                            $result['rule_cat'] = 'command_reject';
                            $result['rule_no'] = '0175';
                        } elseif (preg_match("/No permit/is", $diag_code)) {
                            $result['rule_cat'] = 'command_reject';
                            $result['rule_no'] = '0190';
                        } elseif (preg_match("/domain isn't in.*allowed rcpthost/is", $diag_code)) {
                            $result['rule_cat'] = 'command_reject';
                            $result['rule_no'] = '0191';
                        } elseif (preg_match("/AUTH FAILED/is", $diag_code)) {
                            $result['rule_cat'] = 'command_reject';
                            $result['rule_no'] = '0197';
                        } elseif (preg_match("/relay.*not.*(?:permit|allow)/is", $diag_code)) {
                            $result['rule_cat'] = 'command_reject';
                            $result['rule_no'] = '0201';
                        } elseif (preg_match("/not local host/is", $diag_code)) {
                            $result['rule_cat'] = 'command_reject';
                            $result['rule_no'] = '0204';
                        } elseif (preg_match("/Unauthorized relay/is", $diag_code)) {
                            $result['rule_cat'] = 'command_reject';
                            $result['rule_no'] = '0215';
                        } elseif (preg_match("/Transaction.*fail/is", $diag_code)) {
                            $result['rule_cat'] = 'command_reject';
                            $result['rule_no'] = '0221';
                        } elseif (preg_match("/Invalid data/is", $diag_code)) {
                            $result['rule_cat'] = 'command_reject';
                            $result['rule_no'] = '0223';
                        } elseif (preg_match("/Local user only/is", $diag_code)) {
                            $result['rule_cat'] = 'command_reject';
                            $result['rule_no'] = '0224';
                        } elseif (preg_match("/not.*permit.*to/is", $diag_code)) {
                            $result['rule_cat'] = 'command_reject';
                            $result['rule_no'] = '0225';
                        } elseif (preg_match("/Content reject/is", $diag_code)) {
                            $result['rule_cat'] = 'content_reject';
                            $result['rule_no'] = '0165';
                        } elseif (preg_match("/MIME\\/REJECT/is", $diag_code)) {
                            $result['rule_cat'] = 'content_reject';
                            $result['rule_no'] = '0212';
                        } elseif (preg_match("/MIME error/is", $diag_code)) {
                            $result['rule_cat'] = 'content_reject';
                            $result['rule_no'] = '0217';
                        } elseif (preg_match("/Mail data refused.*AISP/is", $diag_code)) {
                            $result['rule_cat'] = 'content_reject';
                            $result['rule_no'] = '0218';
                        } elseif (preg_match("/Host unknown/is", $diag_code)) {
                            $result['rule_cat'] = 'dns_unknown';
                            $result['rule_no'] = '0130';
                        } elseif (preg_match("/Specified domain.*not.*allow/is", $diag_code)) {
                            $result['rule_cat'] = 'dns_unknown';
                            $result['rule_no'] = '0180';
                        } elseif (preg_match("/No route to host/is", $diag_code)) {
                            $result['rule_cat'] = 'dns_unknown';
                            $result['rule_no'] = '0188';
                        } elseif (preg_match("/domain.*(?:allowed|forbidden)/is", $diag_code)) {
                            $result['rule_cat'] = 'dns_unknown';
                            $result['rule_no'] = '0248';
                        } elseif (preg_match("/unrouteable address/is", $diag_code)) {
                            $result['rule_cat'] = 'dns_unknown';
                            $result['rule_no'] = '0208';
                        } elseif (preg_match("/System.*busy/is", $diag_code)) {
                            $result['rule_cat'] = 'defer';
                            $result['rule_no'] = '0112';
                        } elseif (preg_match("/Resources temporarily unavailable/is", $diag_code)) {
                            $result['rule_cat'] = 'defer';
                            $result['rule_no'] = '0116';
                        } elseif (preg_match("/sender is rejected/is", $diag_code)) {
                            $result['rule_cat'] = 'antispam';
                            $result['rule_no'] = '0101';
                        } elseif (preg_match("/Client host rejected/is", $diag_code)) {
                            $result['rule_cat'] = 'antispam';
                            $result['rule_no'] = '0102';
                        } elseif (preg_match("/MAIL FROM(.*)mismatches client IP/is", $diag_code)) {
                            $result['rule_cat'] = 'antispam';
                            $result['rule_no'] = '0104';
                        } elseif (preg_match("/denyip/is", $diag_code)) {
                            $result['rule_cat'] = 'antispam';
                            $result['rule_no'] = '0144';
                        } elseif (preg_match("/client host.*blocked/is", $diag_code)) {
                            $result['rule_cat'] = 'antispam';
                            $result['rule_no'] = '0201';
                        } elseif (preg_match("/mail.*reject/is", $diag_code)) {
                            $result['rule_cat'] = 'antispam';
                            $result['rule_no'] = '0147';
                        } elseif (preg_match("/spam.*detect/is", $diag_code)) {
                            $result['rule_cat'] = 'antispam';
                            $result['rule_no'] = '0162';
                        } elseif (preg_match("/reject.*spam/is", $diag_code)) {
                            $result['rule_cat'] = 'antispam';
                            $result['rule_no'] = '0216';
                        } elseif (preg_match("/SpamTrap/is", $diag_code)) {
                            $result['rule_cat'] = 'antispam';
                            $result['rule_no'] = '0200';
                        } elseif (preg_match("/Verify mailfrom failed/is", $diag_code)) {
                            $result['rule_cat'] = 'antispam';
                            $result['rule_no'] = '0210';
                        } elseif (preg_match("/MAIL.*FROM.*mismatch/is", $diag_code)) {
                            $result['rule_cat'] = 'antispam';
                            $result['rule_no'] = '0226';
                        } elseif (preg_match("/spam scale/is", $diag_code)) {
                            $result['rule_cat'] = 'antispam';
                            $result['rule_no'] = '0211';
                        } elseif (preg_match("/Client host bypass/is", $diag_code)) {
                            $result['rule_cat'] = 'antispam';
                            $result['rule_no'] = '0229';
                        } elseif (preg_match("/junk mail/is", $diag_code)) {
                            $result['rule_cat'] = 'antispam';
                            $result['rule_no'] = '0230';
                        } elseif (preg_match("/message filtered/is", $diag_code)) {
                            $result['rule_cat'] = 'antispam';
                            $result['rule_no'] = '0227';
                        } elseif (preg_match("/subject.*consider.*spam/is", $diag_code)) {
                            $result['rule_cat'] = 'antispam';
                            $result['rule_no'] = '0222';
                        } elseif (preg_match("/mail to.*recipient is not accepted.*5\\.7\\./is", $diag_code)) {
                            $result['rule_cat'] = 'antispam';
                            $result['rule_no'] = '0251';
                        } elseif (preg_match("/Temporary local problem/is", $diag_code)) {
                            $result['rule_cat'] = 'internal_error';
                            $result['rule_no'] = '0142';
                        } elseif (preg_match("/system config error/is", $diag_code)) {
                            $result['rule_cat'] = 'internal_error';
                            $result['rule_no'] = '0153';
                        } elseif (preg_match("/delivery.*suspend/is", $diag_code)) {
                            $result['rule_cat'] = 'delayed';
                            $result['rule_no'] = '0213';
                        } elseif (preg_match("/(?:alias|account|recipient|address|email|mailbox|user)(.*)invalid/i", $dsn_msg)) {
                            $result['rule_cat'] = 'unknown';
                            $result['rule_no'] = '0107';
                        } elseif (preg_match("/Deferred.*No such.*(?:file|directory)/i", $dsn_msg)) {
                            $result['rule_cat'] = 'unknown';
                            $result['rule_no'] = '0141';
                        } elseif (preg_match("/mail receiving disabled/i", $dsn_msg)) {
                            $result['rule_cat'] = 'unknown';
                            $result['rule_no'] = '0194';
                        } elseif (preg_match("/bad.*(?:alias|account|recipient|address|email|mailbox|user)/i", $dsn_msg)) {
                            $result['rule_cat'] = 'unknown';
                            $result['rule_no'] = '227';
                        } elseif (preg_match("/over.*quota/i", $dsn_msg)) {
                            $result['rule_cat'] = 'full';
                            $result['rule_no'] = '0131';
                        } elseif (preg_match("/quota.*exceeded/i", $dsn_msg)) {
                            $result['rule_cat'] = 'full';
                            $result['rule_no'] = '0150';
                        } elseif (preg_match("/exceed.*\n?.*quota/i", $dsn_msg)) {
                            $result['rule_cat'] = 'full';
                            $result['rule_no'] = '0187';
                        } elseif (preg_match("/(?:alias|account|recipient|address|email|mailbox|user).*full/i", $dsn_msg)) {
                            $result['rule_cat'] = 'full';
                            $result['rule_no'] = '0132';
                        } elseif (preg_match("/space.*not.*enough/i", $dsn_msg)) {
                            $result['rule_cat'] = 'full';
                            $result['rule_no'] = '0219';
                        } elseif (preg_match("/Deferred.*Connection (?:refused|reset)/i", $dsn_msg)) {
                            $result['rule_cat'] = 'defer';
                            $result['rule_no'] = '0115';
                        } elseif (preg_match("/Invalid host name/i", $dsn_msg)) {
                            $result['rule_cat'] = 'dns_unknown';
                            $result['rule_no'] = '0109';
                        } elseif (preg_match("/Deferred.*No route to host/i", $dsn_msg)) {
                            $result['rule_cat'] = 'dns_unknown';
                            $result['rule_no'] = '0109';
                        } elseif (preg_match("/Host unknown/i", $dsn_msg)) {
                            $result['rule_cat'] = 'dns_unknown';
                            $result['rule_no'] = '0140';
                        } elseif (preg_match("/Name server timeout/i", $dsn_msg)) {
                            $result['rule_cat'] = 'dns_unknown';
                            $result['rule_no'] = '0118';
                        } elseif (preg_match("/Deferred.*Connection.*tim(?:e|ed).*out/i", $dsn_msg)) {
                            $result['rule_cat'] = 'dns_unknown';
                            $result['rule_no'] = '0119';
                        } elseif (preg_match("/Deferred.*host name lookup failure/i", $dsn_msg)) {
                            $result['rule_cat'] = 'dns_unknown';
                            $result['rule_no'] = '0121';
                        } elseif (preg_match("/MX list.*point.*back/i", $dsn_msg)) {
                            $result['rule_cat'] = 'dns_loop';
                            $result['rule_no'] = '0199';
                        } elseif (preg_match("/I\\/O error/i", $dsn_msg)) {
                            $result['rule_cat'] = 'internal_error';
                            $result['rule_no'] = '0120';
                        } elseif (preg_match("/connection.*broken/i", $dsn_msg)) {
                            $result['rule_cat'] = 'internal_error';
                            $result['rule_no'] = '0231';
                        } elseif (preg_match("/Delivery to the following recipients failed.*\n.*\n.*" . $result['email'] . "/i", $dsn_msg)) {
                            $result['rule_cat'] = 'other';
                            $result['rule_no'] = '0176';
                        } elseif (preg_match("/User unknown/i", $dsn_msg)) {
                            $result['rule_cat'] = 'unknown';
                            $result['rule_no'] = '0193';
                        } elseif (preg_match("/Service unavailable/i", $dsn_msg)) {
                            $result['rule_cat'] = 'unknown';
                            $result['rule_no'] = '0214';
                        } elseif (preg_match("/Mail rejected.*policy reasons/i", $dsn_msg)) {
                            $result['rule_cat'] = 'antispam';
                            $result['rule_no'] = '0249';
                        }
                    }
                }
                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;
    if ($result['rule_no'] == '0000') {
        if ($debug_mode) {
            echo "email:{$result['email']}\n";
            echo "Action:{$action}\n";
            echo "Status:{$status_code}\n";
            echo "Diagnostic-Code:{$diag_code}\n";
            echo "DSN Message:\n{$dsn_msg}\n";
            //          echo "DSN Report:\n$dsn_report\n";
            echo "\n";
        }
    } else {
        if ($result['bounce_type'] === false) {
            $result['bounce_type'] = $rule_categories[$result['rule_cat']]['bounce_type'];
            $result['remove'] = $rule_categories[$result['rule_cat']]['remove'];
        }
    }
    $result['action'] = $action;
    $result['status_code'] = $status_code;
    $result['diag_code'] = $diag_code;
    return $result;
}