/** * Function to process each individual message * * @param int $pos message number * @param string $type DNS or BODY type * @param string $totalFetched total number of messages in mailbox * * @return boolean */ public function processBounce($pos, $type, $totalFetched) { $header = imap_header($this->mailboxLink, $pos); $subject = strip_tags($header->subject); $body = ''; if ($type == 'DSN') { // first part of DSN (Delivery Status Notification), human-readable explanation $dsnMsg = imap_fetchbody($this->mailboxLink, $pos, "1"); $dsnMsgStructure = imap_bodystruct($this->mailboxLink, $pos, "1"); if ($dsnMsgStructure->encoding == 4) { $dsnMsg = quoted_printable_decode($dsnMsg); } elseif ($dsnMsgStructure->encoding == 3) { $dsnMsg = base64_decode($dsnMsg); } // second part of DSN (Delivery Status Notification), delivery-status $dsnReport = imap_fetchbody($this->mailboxLink, $pos, "2"); // process bounces by rules $result = bmhDSNRules($dsnMsg, $dsnReport, $this->debugDsnRule); } elseif ($type == 'BODY') { $structure = imap_fetchstructure($this->mailboxLink, $pos); switch ($structure->type) { case 0: // Content-type = text $body = imap_fetchbody($this->mailboxLink, $pos, "1"); $result = bmhBodyRules($body, $structure, $this->debugBodyRule); break; case 1: // Content-type = multipart $body = imap_fetchbody($this->mailboxLink, $pos, "1"); // Detect encoding and decode - only base64 if ($structure->parts[0]->encoding == 4) { $body = quoted_printable_decode($body); } elseif ($structure->parts[0]->encoding == 3) { $body = base64_decode($body); } $result = bmhBodyRules($body, $structure, $this->debugBodyRule); break; case 2: // Content-type = message $body = imap_body($this->mailboxLink, $pos); if ($structure->encoding == 4) { $body = quoted_printable_decode($body); } elseif ($structure->encoding == 3) { $body = base64_decode($body); } $body = substr($body, 0, 1000); $result = bmhBodyRules($body, $structure, $this->debugBodyRule); break; default: // unsupport Content-type $this->output('Msg #' . $pos . ' is unsupported Content-Type:' . $structure->type, self::VERBOSE_REPORT); return false; } } else { // internal error $this->errorMessage = 'Internal Error: unknown type'; return false; } $email = $result['email']; $bounceType = $result['bounce_type']; if ($this->moveHard && $result['remove'] == 1) { $remove = 'moved (hard)'; } elseif ($this->moveSoft && $result['remove'] == 1) { $remove = 'moved (soft)'; } elseif ($this->disableDelete) { $remove = 0; } else { $remove = $result['remove']; } $ruleNumber = $result['rule_no']; $ruleCategory = $result['rule_cat']; $xheader = false; if ($ruleNumber === '0000') { // unrecognized if (trim($email) == '') { $email = $header->fromaddress; } if ($this->testMode) { $this->output('Match: ' . $ruleNumber . ':' . $ruleCategory . '; ' . $bounceType . '; ' . $email); } else { // code below will use the Callback function, but return no value $params = array($pos, $bounceType, $email, $subject, $header, $remove, $ruleNumber, $ruleCategory, $totalFetched, $body); call_user_func_array($this->actionFunction, $params); } } else { // match rule, do bounce action if ($this->testMode) { $this->output('Match: ' . $ruleNumber . ':' . $ruleCategory . '; ' . $bounceType . '; ' . $email); return true; } else { $params = array($pos, $bounceType, $email, $subject, $xheader, $remove, $ruleNumber, $ruleCategory, $totalFetched, $body); return call_user_func_array($this->actionFunction, $params); } } }
/** * Function to process each individual message. * * @param int $pos message number * @param string $type DNS or BODY type * @param string $totalFetched total number of messages in mailbox * * @return boolean */ public function processBounce($pos, $type, $totalFetched) { $header = imap_header($this->mailboxLink, $pos); $subject = isset($header->subject) ? strip_tags($header->subject) : '[NO SUBJECT]'; $body = ''; $headerFull = imap_fetchheader($this->mailboxLink, $pos); $bodyFull = imap_body($this->mailboxLink, $pos); if ($type == 'DSN') { // first part of DSN (Delivery Status Notification), human-readable explanation $dsnMsg = imap_fetchbody($this->mailboxLink, $pos, '1'); $dsnMsgStructure = imap_bodystruct($this->mailboxLink, $pos, '1'); if ($dsnMsgStructure->encoding == 4) { $dsnMsg = quoted_printable_decode($dsnMsg); } elseif ($dsnMsgStructure->encoding == 3) { $dsnMsg = base64_decode($dsnMsg); } // second part of DSN (Delivery Status Notification), delivery-status $dsnReport = imap_fetchbody($this->mailboxLink, $pos, '2'); // process bounces by rules $result = bmhDSNRules($dsnMsg, $dsnReport, $this->debugDsnRule); $result = is_callable($this->customDSNRulesCallback) ? call_user_func($this->customDSNRulesCallback, $result, $dsnMsg, $dsnReport, $this->debugDsnRule) : $result; } elseif ($type == 'BODY') { /** @noinspection PhpUsageOfSilenceOperatorInspection */ $structure = @imap_fetchstructure($this->mailboxLink, $pos); if (!is_object($structure)) { return false; } switch ($structure->type) { case 0: // Content-type = text $body = imap_fetchbody($this->mailboxLink, $pos, '1'); $result = bmhBodyRules($body, $structure, $this->debugBodyRule); $result = is_callable($this->customBodyRulesCallback) ? call_user_func($this->customBodyRulesCallback, $result, $body, $structure, $this->debugBodyRule) : $result; break; case 1: // Content-type = multipart $body = imap_fetchbody($this->mailboxLink, $pos, '1'); // Detect encoding and decode - only base64 if ($structure->parts[0]->encoding == 4) { $body = quoted_printable_decode($body); } elseif ($structure->parts[0]->encoding == 3) { $body = base64_decode($body); } $result = bmhBodyRules($body, $structure, $this->debugBodyRule); $result = is_callable($this->customBodyRulesCallback) ? call_user_func($this->customBodyRulesCallback, $result, $body, $structure, $this->debugBodyRule) : $result; break; case 2: // Content-type = message $body = imap_body($this->mailboxLink, $pos); if ($structure->encoding == 4) { $body = quoted_printable_decode($body); } elseif ($structure->encoding == 3) { $body = base64_decode($body); } $body = substr($body, 0, 1000); $result = bmhBodyRules($body, $structure, $this->debugBodyRule); $result = is_callable($this->customBodyRulesCallback) ? call_user_func($this->customBodyRulesCallback, $result, $body, $structure, $this->debugBodyRule) : $result; break; default: // unsupport Content-type $this->output('Msg #' . $pos . ' is unsupported Content-Type:' . $structure->type, self::VERBOSE_REPORT); return false; } } else { // internal error $this->errorMessage = 'Internal Error: unknown type'; return false; } $email = $result['email']; $bounceType = $result['bounce_type']; // workaround: I think there is a error in one of the reg-ex in "phpmailer-bmh_rules.php". if ($email && strpos($email, 'TO:<')) { $email = str_replace('TO:<', '', $email); } if ($this->moveHard && $result['remove'] == 1) { $remove = 'moved (hard)'; } elseif ($this->moveSoft && $result['remove'] == 1) { $remove = 'moved (soft)'; } elseif ($this->disableDelete) { $remove = 0; } else { $remove = $result['remove']; } $ruleNumber = $result['rule_no']; $ruleCategory = $result['rule_cat']; $status_code = $result['status_code']; $action = $result['action']; $diagnostic_code = $result['diagnostic_code']; $xheader = false; if ($ruleNumber === '0000') { // unrecognized if (trim($email) == '' && property_exists($header, 'fromaddress') === true) { $email = $header->fromaddress; } if ($this->testMode) { $this->output('Match: ' . $ruleNumber . ':' . $ruleCategory . '; ' . $bounceType . '; ' . $email); } else { // code below will use the Callback function, but return no value $params = array($pos, $bounceType, $email, $subject, $header, $remove, $ruleNumber, $ruleCategory, $totalFetched, $body, $headerFull, $bodyFull, $status_code, $action, $diagnostic_code); call_user_func_array($this->actionFunction, $params); } } else { // match rule, do bounce action if ($this->testMode) { $this->output('Match: ' . $ruleNumber . ':' . $ruleCategory . '; ' . $bounceType . '; ' . $email); return true; } else { $params = array($pos, $bounceType, $email, $subject, $xheader, $remove, $ruleNumber, $ruleCategory, $totalFetched, $body, $headerFull, $bodyFull, $status_code, $action, $diagnostic_code); return call_user_func_array($this->actionFunction, $params); } } return false; }
/** * Function to process each individual message * @param int $pos (message UID) * @param string $type (DNS or BODY type) * @param string $totalFetched (total number of messages in mailbox) * @return boolean */ function processBounce($pos, $type, $totalFetched) { $time = mktime(); //var_dump('process bounce ' . $pos .'-'. $type .'-'. $totalFetched); $header = $this->protocol->getMessageHeaders($pos, FT_UID); //imap_header //var_dump('headers ' . (mktime() - $time)); if (!empty($header->subject)) { $subject = strip_tags($header->subject); } else { $subject = ''; } $met = ini_get('max_execution_time'); if ($met < 6000 && $met != 0) { set_time_limit(6000); } $this->protocol->setTimeout(6000); //var_dump($header, $subject); if ($type == 'DSN') { // first part of DSN (Delivery Status Notification), human-readable explanation //var_dump('getMessageBody ' . (mktime() - $time)); $dsn_msg = $this->protocol->getMessageBody($pos, "1", FT_UID); //var_dump('getMessageBody(end) ' . (mktime() - $time)); $dsn_msg_structure = $this->protocol->getMessageBodyStruct($pos, "1", FT_UID); //var_dump('getMessageBodyStruct(end) ' . (mktime() - $time)); if ($dsn_msg_structure->encoding == 4) { $dsn_msg = quoted_printable_decode($dsn_msg); } elseif ($dsn_msg_structure->encoding == 3) { $dsn_msg = base64_decode($dsn_msg); } // second part of DSN (Delivery Status Notification), delivery-status $dsn_report = $this->protocol->getMessageBody($pos, "2", FT_UID); //imap_fetchbody($this->_mailbox_link, $pos, "2"); //var_dump('getMessageBody(pos2)-end ' . (mktime() - $time)); // process bounces by rules $result = bmhDSNRules($dsn_msg, $dsn_report, $this->debug_dsn_rule); } elseif ($type == 'BODY') { //var_dump('getMessageBodyStructure ' . (mktime() - $time)); $structure = $this->protocol->getMessageBodyStructure($pos, FT_UID); // imap_fetchstructure($this->_mailbox_link, $pos); //var_dump('getMessageBodyStructure-end ' . (mktime() - $time)); switch ($structure->type) { case 0: // Content-type = text // Content-type = text case 1: // Content-type = multipart //var_dump('getMessageBody2 ' . (mktime() - $time)); $body = $this->protocol->getMessageFetchedBody($pos, "1", FT_UID); //imap_fetchbody($this->_mailbox_link, $pos, "1"); //var_dump('getMessageBody2-end ' . (mktime() - $time)); // Detect encoding and decode - only base64 if (!empty($structure->parts[0]->encoding) && $structure->parts[0]->encoding == 4) { $body = quoted_printable_decode($body); } elseif (!empty($structure->parts[0]->encoding) && $structure->parts[0]->encoding == 3) { $body = base64_decode($body); } //var_dump('bmhBodyRules ' . (mktime() - $time) . ' body length ' . strlen($body)); $result = bmhBodyRules($body, $structure); //var_dump('bmhBodyRules-end ' . (mktime() - $time)); break; case 2: // Content-type = message //var_dump('getMessageBody3 ' . (mktime() - $time)); $body = $this->protocol->getMessageBody($pos, FT_UID); //imap_body($this->_mailbox_link, $pos); //var_dump('getMessageBody3-end ' . (mktime() - $time)); if ($structure->encoding == 4) { $body = quoted_printable_decode($body); } elseif ($structure->encoding == 3) { $body = base64_decode($body); } $body = substr($body, 0, 1000); //var_dump('bmhBodyRules ' . (mktime() - $time)); $result = bmhBodyRules($body, $structure); //var_dump('bmhBodyRules-end ' . (mktime() - $time)); break; default: // unsupport Content-type $this->output('Msg #' . $pos . ' is unsupported Content-Type:' . $structure->type, VERBOSE_REPORT); return false; } } else { // internal error $this->error_msg = 'Internal Error: unknown type'; return false; } $email = $result['email']; $bounce_type = $result['bounce_type']; if ($this->moveHard && $result['remove'] == 1) { $remove = 'moved (hard)'; } elseif ($this->disableDelete) { $remove = 0; } else { $remove = $result['remove']; } $rule_no = $result['rule_no']; $rule_cat = $result['rule_cat']; $xheader = false; if ($rule_no == '0000') { // internal error return false; // code below will use the Callback function, but return no value if (trim($email) == '') { if (!empty($header->fromaddress)) { $email = $header->fromaddress; } } $params = array($pos, $body, $bounce_type, $email, $subject, $xheader, $remove, $rule_no, $rule_cat, $totalFetched); call_user_func_array(array($this, 'callbackAction'), $params); } else { // match rule, do bounce action $params = array($pos, $body, $bounce_type, $email, $subject, $xheader, $remove, $rule_no, $rule_cat, $totalFetched); return call_user_func_array(array($this, 'callbackAction'), $params); } //var_dump('process bounce-end ' . (mktime() - $time)); return true; }
/** * Function to process each individual message * @param int $pos (message number) * @param string $type (DNS or BODY type) * @param string $totalFetched (total number of messages in mailbox) * @return boolean */ function processBounce($pos, $type, $totalFetched) { $header = imap_header($this->_mailbox_link, $pos); $subject = strip_tags($header->subject); $met = ini_get('max_execution_time'); if ($met < 6000 && $met != 0) { set_time_limit(6000); } imap_timeout(IMAP_READTIMEOUT, 6000); imap_timeout(IMAP_WRITETIMEOUT, 6000); if ($type == 'DSN') { // first part of DSN (Delivery Status Notification), human-readable explanation $dsn_msg = imap_fetchbody($this->_mailbox_link, $pos, "1"); $dsn_msg_structure = imap_bodystruct($this->_mailbox_link, $pos, "1"); if ($dsn_msg_structure->encoding == 4) { $dsn_msg = quoted_printable_decode($dsn_msg); } elseif ($dsn_msg_structure->encoding == 3) { $dsn_msg = base64_decode($dsn_msg); } // second part of DSN (Delivery Status Notification), delivery-status $dsn_report = imap_fetchbody($this->_mailbox_link, $pos, "2"); // process bounces by rules $result = bmhDSNRules($dsn_msg, $dsn_report, $this->debug_dsn_rule); } elseif ($type == 'BODY') { $structure = imap_fetchstructure($this->_mailbox_link, $pos); switch ($structure->type) { case 0: // Content-type = text // Content-type = text case 1: // Content-type = multipart $body = imap_fetchbody($this->_mailbox_link, $pos, "1"); // Detect encoding and decode - only base64 if (!empty($structure->parts[0]->encoding) && $structure->parts[0]->encoding == 4) { $body = quoted_printable_decode($body); } elseif (!empty($structure->parts[0]->encoding) && $structure->parts[0]->encoding == 3) { $body = base64_decode($body); } $result = bmhBodyRules($body, $structure, $this->debug_body_rule); break; case 2: // Content-type = message $body = imap_body($this->_mailbox_link, $pos); if ($structure->encoding == 4) { $body = quoted_printable_decode($body); } elseif ($structure->encoding == 3) { $body = base64_decode($body); } $body = substr($body, 0, 1000); $result = bmhBodyRules($body, $structure, $this->debug_body_rule); break; default: // unsupport Content-type $this->output('Msg #' . $pos . ' is unsupported Content-Type:' . $structure->type, VERBOSE_REPORT); return false; } } else { // internal error $this->error_msg = 'Internal Error: unknown type'; return false; } $email = $result['email']; $bounce_type = $result['bounce_type']; if ($this->moveHard && $result['remove'] == 1) { $remove = 'moved (hard)'; } elseif ($this->moveSoft && $result['remove'] == 1) { $remove = 'moved (soft)'; } elseif ($this->disable_delete) { $remove = 0; } else { $remove = $result['remove']; } $rule_no = $result['rule_no']; $rule_cat = $result['rule_cat']; $xheader = false; if ($rule_no == '0000') { // internal error return false; // code below will use the Callback function, but return no value if (trim($email) == '') { $email = $header->fromaddress; } $params = array($pos, $body, $bounce_type, $email, $subject, $xheader, $remove, $rule_no, $rule_cat, $totalFetched); call_user_func_array($this->action_function, $params); } else { // match rule, do bounce action if ($this->testmode) { $this->output('Match: ' . $rule_no . ':' . $rule_cat . '; ' . $bounce_type . '; ' . $email); return true; } else { $params = array($pos, $body, $bounce_type, $email, $subject, $xheader, $remove, $rule_no, $rule_cat, $totalFetched); return call_user_func_array($this->action_function, $params); } } }
function processBounce($pos, $type, $header = null) { if (!empty($header)) { $md5header = md5($header); } else { $md5header = null; } if ($type == 'DSN') { // first part of DSN (Delivery Status Notification), human-readable explanation $dsn_msg = imap_fetchbody($this->_mailbox_link, $pos, "1"); $dsn_msg_structure = imap_bodystruct($this->_mailbox_link, $pos, "1"); if ($dsn_msg_structure->encoding == 3) { $dsn_msg = base64_decode($dsn_msg); } // second part of DSN (Delivery Status Notification), delivery-status $dsn_report = imap_fetchbody($this->_mailbox_link, $pos, "2"); // process bounces by rules $result = bmhDSNRules($dsn_msg, $dsn_report, $this->debug_dsn_rule); } elseif ($type == 'BODY') { $structure = imap_fetchstructure($this->_mailbox_link, $pos); switch ($structure->type) { case 0: // Content-type = text // Content-type = text case 2: // Content-type = message $body = imap_body($this->_mailbox_link, $pos); if ($structure->encoding == 3) { $body = base64_decode($body); } $body = substr($body, 0, 1000); $result = bmhBodyRules($body, $structure, $this->debug_body_rule); break; case 1: // Content-type = multipart $body = imap_fetchbody($this->_mailbox_link, $pos, "1"); // TRICKY : detect encoding and decode // only handle base64 right now if ($structure->parts[0]->encoding == 3) { $body = base64_decode($body); } $body = substr($body, 0, 1000); $result = bmhBodyRules($body, $structure, $this->debug_body_rule); break; default: // unsupport Content-type $this->output("The No. {$pos} is unsupport Content-Type:{$structure->type}", VERBOSE_REPORT); return false; } } else { // internal error $this->error_msg = 'Internal Error: unknown type'; return false; } $result['rule_type'] = $type; if (!empty($header)) { if (preg_match("/Subject:((?:[^\n]|\n[\t ])+)(?:\n[^\t ]|\$)/is", $header, $match)) { $result['subject'] = trim($match[1]); } if (preg_match("/Date:[\t ]*(.*)/i", $header, $match)) { $result['date'] = trim($match[1]); } if (preg_match("/From:((?:[^\n]|\n[\t ])+)(?:\n[^\t ]|\$)/is", $header, $match)) { $addresses = imap_rfc822_parse_adrlist($match[1], '???'); if (!empty($addresses) && is_array($addresses)) { $result['from'] = $addresses[0]->mailbox . '@' . $addresses[0]->host; } } } // last chance for unmatched rules if ($result['rule_no'] == '0000') { $result = bmhOtherRules($result); } $result['md5header'] = $md5header; // log the result if wanted if (!empty($this->log_function) && function_exists($this->log_function)) { call_user_func($this->log_function, $result); $this->c_log++; } // call user function for unmatched rules if ($result['rule_no'] == '0000') { if (!empty($this->unmatched_function) && function_exists($this->unmatched_function)) { return call_user_func($this->unmatched_function, $result); } return false; } if ($this->testmode) { $this->output(print_r($result, true)); return false; } // match a rule, take bounce action if (!empty($this->action_function) && function_exists($this->action_function)) { return call_user_func($this->action_function, $result); } return true; }