/**
 * Check an email.
 *
 * @param string $email Contents of an email to check
 *
 * @return void
 */
function checkmail($email)
{
    global $total;
    $bh = new Bouncehandler();
    $bounceinfo = $bh->get_the_facts($email);
    // var_dump($bounceinfo);
    // var_dump($bh);
    print " TYPE      " . @$bh->type . "\n";
    if ($bh->type == 'bounce') {
        print " ACTION    " . $bounceinfo[0]['action'] . "\n";
        print " STATUS    " . $bounceinfo[0]['status'] . "\n";
        print " RECIPIENT " . $bounceinfo[0]['recipient'] . "\n";
    }
    if ($bh->type == 'fbl') {
        print " ENV FROM  " . @$bh->fbl_hash['Original-mail-from'] . "\n";
        print " AGENT     " . @$bh->fbl_hash['User-agent'] . "\n";
        print " IP        " . @$bh->fbl_hash['Source-ip'] . "\n";
    }
    if ($bh->type == 'autoresponse') {
        print " AUTO      " . $bounceinfo[0]['autoresponse'] . "\n";
    }
    if ($bh->type) {
        @$total[$bh->type]++;
    } else {
        @$total['unknown']++;
    }
    print "\n";
}
Esempio n. 2
0
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<body>

<?php 
require_once "bounce_driver.class.php";
$bouncehandler = new Bouncehandler();
if ($_GET['testall']) {
    $files = get_sorted_file_list('eml');
    if (is_array($files)) {
        echo "<P>File Tests:</P>\n";
        foreach ($files as $file) {
            echo "<a href=\"" . $_SERVER['PHP_SELF'] . "?eml=" . urlencode($file) . "\">{$file}</a> ";
            $bounce = file_get_contents("eml/" . $file);
            $multiArray = $bouncehandler->get_the_facts($bounce);
            if (!empty($multiArray[0]['action']) && !empty($multiArray[0]['status']) && !empty($multiArray[0]['recipient'])) {
                print " - Passed<br>\n";
            } else {
                print "<font color=red> - WRONG</font><br>\n";
                print "<pre>\n";
                print_r($multiArray[0]);
                print "</pre>\n";
            }
        }
    }
}
?>

<h1>bounce_driver.class.php -- Version 7.0</h1>

<P>
Esempio n. 3
0
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<body>

<?php 
//error_reporting(E_ALL);
require_once "bounce_driver.class.php";
$bouncehandler = new Bouncehandler();
if (!empty($_GET['testall'])) {
    $files = get_sorted_file_list('eml');
    if (is_array($files)) {
        echo "<P>File Tests:</P>\n";
        foreach ($files as $file) {
            echo "<a href=\"" . $_SERVER['PHP_SELF'] . "?eml=" . urlencode($file) . "\">{$file}</a> ";
            $bounce = file_get_contents("eml/" . $file);
            $multiArray = $bouncehandler->get_the_facts($bounce);
            if (!empty($multiArray[0]['action']) && !empty($multiArray[0]['status']) && !empty($multiArray[0]['recipient'])) {
                print " - Passed<br>\n";
            } else {
                print "<font color=red> - WRONG</font><br>\n";
                print "<pre>\n";
                print_r($multiArray[0]);
                print "</pre>\n";
            }
        }
    }
}
?>

<h1>bounce_driver.class.php -- Version 7.3</h1>
 /**
  * Tests a single email.
  *
  * @param string $bounce Contents of the bounce email.
  *
  * @return void
  */
 private function _testSingle($bounce)
 {
     $multiArray = $this->_bouncehandler->get_the_facts($bounce);
     echo "<TEXTAREA COLS=100 ROWS=" . count($multiArray) * 8 . ">";
     print_r($multiArray);
     echo "</TEXTAREA>";
     $bounce = $this->_bouncehandler->init_bouncehandler($bounce, 'string');
     list($head, $body) = preg_split("/\r\n\r\n/", $bounce, 2);
     echo '<h2>Raw email:</h2><br />';
     echo "<TEXTAREA COLS=100 ROWS=12>";
     echo htmlspecialchars($bounce);
     echo "</TEXTAREA><br />";
     echo "<h2>Parsed head</h2>\n";
     $head_hash = $this->_bouncehandler->parse_head($head);
     echo "<TEXTAREA COLS=100 ROWS=" . count($head_hash) * 2.7 . ">";
     print_r($head_hash);
     echo "</TEXTAREA><br />";
     if ($this->_bouncehandler->is_RFC1892_multipart_report($head_hash)) {
         echo '<h2 style="color:red;">';
         echo 'Looks like an RFC1892 multipart report';
         echo '</h2>';
     } else {
         if ($this->_bouncehandler->looks_like_an_FBL) {
             echo '<h2 style="color:red;">';
             echo 'Looks like a feedback loop';
             if ($this->_bouncehandler->is_hotmail_fbl) {
                 echo ' in Hotmail Doofus Format (HDF?)';
             } else {
                 echo ' in Abuse Feedback Reporting format (ARF)';
             }
             echo '</h2>';
             echo "<TEXTAREA COLS=100 ROWS=12>";
             print_r($this->_bouncehandler->fbl_hash);
             echo "</TEXTAREA>";
         } else {
             echo "<h2 style='color:red;'>Not an RFC1892 multipart report</H2>";
             echo "<TEXTAREA COLS=100 ROWS=100>";
             print_r($body);
             echo "</TEXTAREA>";
             exit;
         }
     }
     echo "<h2>Here is the parsed report</h2>\n";
     echo '<p>Postfix adds an appropriate X- header (X-Postfix-Sender:), ';
     echo 'so you do not need to create one via phpmailer.  RFC\'s call ';
     echo 'for an optional Original-recipient field, but mandatory ';
     echo 'Final-recipient field is a fair substitute.</p>';
     $boundary = $head_hash['Content-type']['boundary'];
     $mime_sections = $this->_bouncehandler->parse_body_into_mime_sections($body, $boundary);
     $rpt_hash = $this->_bouncehandler->parse_machine_parsable_body_part($mime_sections['machine_parsable_body_part']);
     echo "<TEXTAREA COLS=100 ROWS=" . count($rpt_hash) * 16 . ">";
     print_r($rpt_hash);
     echo "</TEXTAREA>";
     echo "<h2>Here is the error status code</h2>\n";
     echo "<P>It's all in the status code, if you can find one.</P>";
     for ($i = 0; $i < count($rpt_hash['per_recipient']); $i++) {
         echo "<P>Report #" . ($i + 1) . "<BR>\n";
         echo $this->_bouncehandler->find_recipient($rpt_hash['per_recipient'][$i]);
         $scode = $rpt_hash['per_recipient'][$i]['Status'];
         echo "<PRE>{$scode}</PRE>";
         echo $this->_bouncehandler->fetch_status_messages($scode);
         echo "</P>\n";
     }
     echo '<h2>The Diagnostic-code</h2>';
     echo '<p>is not the same as the reported status code, but it seems ';
     echo 'to be more descriptive, so it should be extracted (if possible).';
     for ($i = 0; $i < count($rpt_hash['per_recipient']); $i++) {
         echo "<P>Report #" . ($i + 1) . " <BR>\n";
         echo $this->_bouncehandler->find_recipient($rpt_hash['per_recipient'][$i]);
         $dcode = $rpt_hash['per_recipient'][$i]['Diagnostic-code']['text'];
         if ($dcode) {
             echo "<PRE>{$dcode}</PRE>";
             echo $this->_bouncehandler->fetch_status_messages($dcode);
         } else {
             echo "<PRE>couldn't decode</PRE>";
         }
         echo "</P>\n";
     }
     echo '<h2>Grab original To: and From:</h2>\\n';
     echo '<p>Just in case we don\'t have an Original-recipient: field, or ';
     echo 'a X-Postfix-Sender: field, we can retrieve information from ';
     echo 'the (optional) returned message body part</p>' . PHP_EOL;
     $head = $this->_bouncehandler->get_head_from_returned_message_body_part($mime_sections);
     echo "<P>From: " . $head['From'];
     echo "<br>To: " . $head['To'];
     echo "<br>Subject: " . $head['Subject'] . "</P>";
     echo "<h2>Here is the body in RFC1892 parts</h2>\n";
     echo '<[>Three parts: [first_body_part], ';
     echo '[machine_parsable_body_part], and ';
     echo ' [returned_message_body_part]</p>';
     echo "<TEXTAREA cols=100 rows=100>";
     print_r($mime_sections);
     echo "</TEXTAREA>";
 }
<?php

require_once "extension/jaj_newsletter/lib/bounce_handler/bounce_driver.class.php";
$server = "zmail-01.hikt.no";
$username = "******";
$password = "******";
$bouncehandler = new Bouncehandler();
$pop3 = new ezcMailPop3Transport($server);
$pop3->authenticate($username, $password);
$pop3->status($num, $size);
$cli->output('Bounce messages to check: ' . $num);
$messages = $pop3->listMessages();
foreach ($messages as $index => $size) {
    $set = $pop3->fetchByMessageNr($index);
    do {
        $raw_message = "";
        $line = "";
        while (($line = $set->getNextLine()) !== null) {
            $raw_message .= $line;
        }
        $result = $bouncehandler->get_the_facts($raw_message);
        $result = $result[0];
        $status = $result['status'];
        $action = $result['action'];
        $recipient = trim($result['recipient']);
        if (!in_array($action, array("delayed", "failed", "autoreply"))) {
            $cli->output("Message index: {$index}, unknown action: {$action}, skipping...");
            continue;
        }
        if ($action == 'delayed' || $action == 'autoreply') {
            $cli->output("Deleting message: {$index}, action: {$action}");
 function alo_em_handle_bounces($report = false)
 {
     global $wpdb;
     $output = '';
     $bounce_settings = alo_em_bounce_settings();
     $conn = alo_em_bounce_connect();
     if (!$conn) {
         return FALSE;
     }
     $num_msgs = imap_num_msg($conn);
     // start bounce class
     require_once 'inc/bouncehandler/bounce_driver.class.php';
     $bouncehandler = new Bouncehandler();
     // get the failures
     $email_addresses = array();
     $delete_addresses = array();
     $max_msgs = min($num_msgs, $bounce_settings['bounce_maxmsg']);
     if ($report) {
         $output .= 'Bounces handled in: ' . $bounce_settings['bounce_email'];
     }
     for ($n = 1; $n <= $max_msgs; $n++) {
         $msg_headers = imap_fetchheader($conn, $n);
         $msg_body = imap_body($conn, $n);
         $bounce = $msg_headers . $msg_body;
         //entire message
         $multiArray = $bouncehandler->get_the_facts($bounce);
         if (!empty($multiArray[0]['action']) && !empty($multiArray[0]['status']) && !empty($multiArray[0]['recipient'])) {
             if ($report) {
                 $output .= '<br /> - MSG #' . $n . ' - Bounce response: ' . $multiArray[0]['action'];
             }
             // If delivery permanently failed, unsubscribe
             if ($multiArray[0]['action'] == 'failed') {
                 $email = trim($multiArray[0]['recipient']);
                 // Unsubscribe email address
                 if ($s_id = alo_em_is_subscriber($email)) {
                     alo_em_delete_subscriber_by_id($s_id);
                     do_action('alo_easymail_bounce_email_unsubscribed', $email);
                     // Hook
                     if ($report) {
                         $output .= ' - ' . $email . ' UNSUBSCRIBED';
                     }
                 }
             }
             // If delivery temporary or permanently failed, mark recipient as bounced
             if ($multiArray[0]['action'] == 'failed' || $multiArray[0]['action'] == 'transient' || $multiArray[0]['action'] == 'autoreply') {
                 // TODO maybe use: $bouncehandler->x_header_search_1 = 'ALO-EM-Newsletter';
                 // Look fo EasyMail custom headers: Newsletter and Recipient
                 // NOTE: searching in body because IDs are inside original message included in body
                 $newsletter_id = 0;
                 $recipient_id = 0;
                 if (preg_match('/X-ALO-EM-Newsletter: (\\d+)/i', $bounce, $matches)) {
                     if (!empty($matches[1]) && is_numeric($matches[1])) {
                         $newsletter_id = (int) $matches[1];
                     }
                 }
                 if (preg_match('/X-ALO-EM-Recipient: (\\d+)/i', $bounce, $matches)) {
                     if (!empty($matches[1]) && is_numeric($matches[1])) {
                         $recipient_id = (int) $matches[1];
                     }
                 }
                 // Mark recipient as bounced only if not a debug to author
                 if ($newsletter_id > 0 && $recipient_id > 0 && strpos($msg_headers, "( DEBUG - TO: ") === false) {
                     $wpdb->update("{$wpdb->prefix}easymail_recipients", array('result' => -3), array('ID' => $recipient_id, 'newsletter' => $newsletter_id, 'email' => $email));
                 }
                 if ($report) {
                     $output .= ' - Recipient ID #' . $recipient_id . ' marked as not delivered';
                 }
                 // mark msg for deletion
                 imap_delete($conn, $n);
             }
         } else {
             if ($report) {
                 $output .= '<br /><span class="description"> - MSG #' . $n . ' - Not a bounce</span>';
             }
         }
     }
     //for loop
     // delete messages
     imap_expunge($conn);
     // close
     imap_close($conn);
     if ($report) {
         return $output;
     }
 }
Esempio n. 7
0
 function get_status_code_from_text($recipient, $arrBody, $index)
 {
     for ($i = $index; $i < count($arrBody); $i++) {
         $line = trim($arrBody[$i]);
         /******** recurse into the email if you find the recipient ********/
         if (stristr($line, $recipient) !== FALSE) {
             // the status code MIGHT be in the next few lines after the recipient line,
             // depending on the message from the foreign host... What a laugh riot!
             $output = BounceHandler::get_status_code_from_text($recipient, $arrBody, $i + 1);
             if ($output) {
                 return $output;
             }
         }
         /******** exit conditions ********/
         // if it's the end of the human readable part in this stupid bounce
         if (stristr($line, '------ This is a copy of the message') !== FALSE) {
             return '';
         }
         //if we see an email address other than our current recipient's,
         if (count(BounceHandler::find_email_addresses($line)) >= 1 && stristr($line, $recipient) === FALSE && strstr($line, 'FROM:<') === FALSE) {
             // Kanon added this line because Hotmail puts the e-mail address too soon and there actually is error message stuff after it.
             return '';
         }
         /******** pattern matching ********/
         if (stristr($line, 'no such address') !== FALSE || stristr($line, 'Recipient address rejected') !== FALSE || stristr($line, 'User unknown in virtual alias table') !== FALSE) {
             return '5.1.1';
         } else {
             if (stristr($line, 'unrouteable mail domain') !== FALSE || stristr($line, 'Esta casilla ha expirado por falta de uso') !== FALSE) {
                 return '5.1.2';
             } else {
                 if (stristr($line, 'mailbox is full') !== FALSE || stristr($line, 'Mailbox quota usage exceeded') !== FALSE || stristr($line, 'User mailbox exceeds allowed size') !== FALSE) {
                     return '4.2.2';
                 } else {
                     if (stristr($line, 'not yet been delivered') !== FALSE) {
                         return '4.2.0';
                     } else {
                         if (stristr($line, 'mailbox unavailable') !== FALSE) {
                             return '5.2.0';
                         } else {
                             if (stristr($line, 'Unrouteable address') !== FALSE) {
                                 return '5.4.4';
                             } else {
                                 if (stristr($line, 'retry timeout exceeded') !== FALSE) {
                                     return '4.4.7';
                                 } else {
                                     if (stristr($line, 'The account or domain may not exist, they may be blacklisted, or missing the proper dns entries.') !== FALSE) {
                                         // Kanon added
                                         return '5.2.0';
                                         // I guess.... seems like 5.1.1, 5.1.2, or 5.4.4 would fit too, but 5.2.0 seemed most generic
                                     } else {
                                         if (stristr($line, '554 TRANSACTION FAILED') !== FALSE) {
                                             // Kanon added
                                             return '5.5.4';
                                             // I think this should be 5.7.1. "SMTP error from remote mail server after end of data: ... (HVU:B1) http://postmaster.info.aol.com/errors/554hvub1.html" -- AOL rejects messages that have links to certain sites in them.
                                         } else {
                                             if (stristr($line, 'Status: 4.4.1') !== FALSE || stristr($line, 'delivery temporarily suspended') !== FALSE) {
                                                 // Kanon added
                                                 return '4.4.1';
                                             } else {
                                                 if (stristr($line, '550 OU-002') !== FALSE || stristr($line, 'Mail rejected by Windows Live Hotmail for policy reasons') !== FALSE) {
                                                     // Kanon added
                                                     return '5.5.0';
                                                     // Again, why isn't this 5.7.1 instead?
                                                 } else {
                                                     if (stristr($line, 'PERM_FAILURE: DNS Error: Domain name not found') !== FALSE) {
                                                         // Kanon added
                                                         return '5.1.2';
                                                         // Not sure if this is right code. Just copied from above.
                                                     } else {
                                                         if (stristr($line, 'Delivery attempts will continue to be made for') !== FALSE) {
                                                             // Kanon added. From Symantec_AntiVirus_for_SMTP_Gateways@uqam.ca
                                                             return '4.2.0';
                                                             // I'm not sure why Symantec delayed this message, but x.2.x means something to do with the mailbox, which seemed appropriate. x.5.x (protocol) or x.7.x (security) also seem possibly appropriate. It seems a lot of times it's x.5.x when it seems to me it should be x.7.x, so maybe x.5.x is standard when mail is rejected due to spam-like characteristics instead of x.7.x like I think it should be.
                                                         } else {
                                                             if (stristr($line, '554 delivery error:') !== FALSE) {
                                                                 return '5.5.4';
                                                                 // rogers.com
                                                             } else {
                                                                 if (strstr($line, '550-5.1.1') !== FALSE || stristr($line, 'This Gmail user does not exist.') !== FALSE) {
                                                                     // Kanon added
                                                                     return '5.1.1';
                                                                     // Or should it be 5.5.0?
                                                                 } else {
                                                                     // end strstr tests
                                                                 }
                                                             }
                                                         }
                                                     }
                                                 }
                                             }
                                         }
                                     }
                                 }
                             }
                         }
                     }
                 }
             }
         }
         // rfc1893 return code
         if (preg_match('/([245]\\.[01234567]\\.[012345678])/', $line, $matches)) {
             $mycode = str_replace('.', '', $matches[1]);
             $mycode = Bouncehandler::format_status_code($mycode);
             return implode('.', $mycode['code']);
         }
         // search for RFC821 return code
         // thanks to mark.tolman@gmail.com
         // Maybe at some point it should have it's own place within the main parsing scheme (at line 88)
         if (preg_match('/\\]?: ([45][01257][012345]) /', $line, $matches) || preg_match('/^([45][01257][012345]) (?:.*?)(?:denied|inactive|deactivated|rejected|disabled|unknown|no such|not (?:our|activated|a valid))+/i', $line, $matches)) {
             $mycode = $matches[1];
             // map common codes to new rfc values
             if ($mycode == '450' || $mycode == '550' || $mycode == '551' || $mycode == '554') {
                 $mycode = '511';
             } else {
                 if ($mycode == '452' || $mycode == '552') {
                     $mycode = '422';
                 } else {
                     if ($mycode == '421') {
                         $mycode = '432';
                     }
                 }
             }
             $mycode = Bouncehandler::format_status_code($mycode);
             return implode('.', $mycode['code']);
         }
     }
     return '';
 }
<?php

global $Knews_plugin, $knewsOptions, $wpdb;
if (!$Knews_plugin->initialized) {
    $Knews_plugin->init();
}
if ($knewsOptions['bounce_on'] == '1') {
    require_once KNEWS_DIR . "/includes/knews_util.php";
    require_once KNEWS_DIR . "/includes/bouncehandler/bounce_driver.class.php";
    $bouncehandler = new Bouncehandler();
    if ($inst = knews_pop3_login($knewsOptions['bounce_host'], $knewsOptions['bounce_port'], $knewsOptions['bounce_user'], $knewsOptions['bounce_pass'], "INBOX", $knewsOptions['bounce_ssl'], $knewsOptions['bounce_mode'])) {
        $stat = knews_pop3_stat($inst);
        //print_r($stat);
        //die();
        if ($stat['Nmsgs'] > 0) {
            $messages = $stat['Nmsgs'];
            if ($messages > 50) {
                $messages = 50;
            }
            $list = knews_pop3_list($inst, $messages);
            $count = 0;
            foreach ($list as $row) {
                $count++;
                $b = $bouncehandler->get_the_facts($row);
                $fail_code = 0;
                $read_blog_id = 0;
                $posid = strpos($row, 'Knews-Blog-Id:');
                $posid = $posid + 14;
                if ($posid !== false) {
                    $posid2 = strpos($row, '_', $posid);
                    if ($posid2 !== false) {