/** * Handle a bounce report. * @param string $bounceString - the string from header X-e107-id * @param string $emailAddress - optional email address string for checks * @return boolean - TRUE on success, FALSE on failure */ public function markBounce($bounceString, $emailAddress = '') { $bounceInfo = array('mail_bounce_string' => $bounceString, 'mail_recipient_email' => $emailAddress); // Ready for event data $errors = array(); // Log all errors, at least until proven $vals = explode('/', $bounceString); // Should get one or four fields if (!is_numeric($vals[0])) { $errors[] = 'Bad user ID: ' . $vals[0]; } $uid = intval($vals[0]); // User ID (zero is valid) if (count($vals) == 4) { if (md5($vals[0] . '/' . $vals[1] . '/' . $vals[2] . '/') != $vals[3]) { // 'Extended' ID has md5 validation $errors[] = 'Bad md5'; } if (!is_numeric($vals[1])) { $errors[] = 'Bad body record: ' . $vals[1]; } if (!is_numeric($vals[2])) { $errors[] = 'Bad recipient record: ' . $vals[2]; } $vals[1] = intval($vals[1]); $vals[2] = intval($vals[2]); if (count($errors) == 0) { // Look up in mailer DB if no errors so far $this->checkDB(1); if (FALSE === $this->db->db_Select_gen("SELECT mr.`mail_recipient_id`, mr.`mail_recipient_email`, mr.`mail_recipient_name` FROM `#mail_recipients` AS mr \n\t\t\t\t\t\tLEFT JOIN `#mail_content` as mc ON mr.`mail_detail_id` = mc.`mail_source_id`\n\t\t\t\t\t\tWHERE mr.`mail_target_id` = {$vals[2]} AND mc.`mail_source_id` = {$vals[1]}")) { // Invalid mailer record $errors[] = 'Not found in DB: ' . $vals[1] . '/' . $vals[2]; } $row = $this->db->db_Fetch(MYSQL_ASSOC); if ($emailAddress && $emailAddress != $row['mail_recipient_email']) { // Email address mismatch $errors[] = 'Email address mismatch: ' . $emailAddress . '/' . $row['mail_recipient_email']; } if ($uid != $row['mail_recipient_id']) { // User ID mismatch $errors[] = 'User ID mismatch: ' . $uid . '/' . $row['mail_recipient_id']; } if (count($errors) == 0) { // All passed - can update mailout databases $this->db->db_Update('mail_content', '`mail_bounce_count` = `mail_bounce_count` + 1 WHERE `mail_source_id` = ' . $vals[1]); $this->db->db_Update('mail_recipients', '`mail_status` = ' . MAIL_STATUS_BOUNCED . ' WHERE `mail_target_id` = ' . $vals[2]); $bounceInfo['mail_source_id'] = $vals[1]; $bounceInfo['mail_target_id'] = $vals[2]; $bounceInfo['mail_recipient_id'] = $uid; $bounceInfo['mail_recipient_name'] = $row['mail_recipient_name']; } } } if (count($vals) != 1 && count($vals) != 4) { $errors[] = 'Bad element count: ' . count($vals); } elseif ($uid || $emailAddress) { // Now log the bounce against the user (user handler will do any required logging) require_once e_HANDLER . 'user_handler.php'; $result = userHandler::userStatusUpdate('bounce', $uid, $emailAddress); if ($result) { $errors[] = $result; } } if (count($errors)) { $logString = $bounceString . ' (' . $emailAddress . ')[!br!]' . implode('[!br!]', $errors); $this->e107->admin_log->e_log_event(10, -1, 'BOUNCE', 'Bounce receive error', $logString, FALSE, LOG_TO_ROLLING); return FALSE; } $this->e107->admin_log->e_log_event(10, -1, 'BOUNCE', 'Bounce received/logged', $bounceString . ' (' . $emailAddress . ')', FALSE, LOG_TO_ROLLING); e107::getEvent()->trigger('mailbounce', $bounceInfo); return TRUE; }
/** * Handle a bounce report. * @param string $bounceString - the string from header X-e107-id * @param string $emailAddress - optional email address string for checks * @return boolean - TRUE on success, FALSE on failure */ public function markBounce($bounceString, $emailAddress = '') { $bounceString = trim($bounceString); $bounceInfo = array('mail_bounce_string' => $bounceString, 'mail_recipient_email' => $emailAddress); // Ready for event data $errors = array(); // Log all errors, at least until proven $vals = explode('/', $bounceString); // Should get one or four fields if ($this->debugMode) { echo "<h4>Bounce String</h4>"; print_a($bounceString); echo "<h4>Vals</h4>"; print_a($vals); } if (!is_numeric($vals[0])) { $errors[] = 'Bad user ID: ' . $vals[0]; } $uid = intval($vals[0]); // User ID (zero is valid) if (count($vals) == 4) { if (!is_numeric($vals[1])) { $errors[] = 'Bad body record: ' . $vals[1]; } if (!is_numeric($vals[2])) { $errors[] = 'Bad recipient record: ' . $vals[2]; } $vals[0] = intval($vals[0]); $vals[1] = intval($vals[1]); $vals[2] = intval($vals[2]); $vals[3] = trim($vals[3]); $hash = $vals[0] . '/' . $vals[1] . '/' . $vals[2] . '/'; if (md5($hash) != $vals[3]) { $errors[] = 'Bad md5'; $errors[] = print_r($vals, true); $errors[] = 'hash:' . md5($hash); } if (empty($errors)) { $this->checkDB(1); // Look up in mailer DB if no errors so far if (false === $this->db->gen("SELECT mr.`mail_recipient_id`, mr.`mail_recipient_email`, mr.`mail_recipient_name`, mr.mail_target_info, \n\t\t\t\t\tmc.mail_create_date, mc.mail_start_send, mc.mail_end_send, mc.`mail_title`, mc.`mail_subject`, mc.`mail_creator`, mc.`mail_other` FROM `#mail_recipients` AS mr \n\t\t\t\t\tLEFT JOIN `#mail_content` as mc ON mr.`mail_detail_id` = mc.`mail_source_id`\n\t\t\t\t\t\tWHERE mr.`mail_target_id` = {$vals[2]} AND mc.`mail_source_id` = {$vals[1]}")) { // Invalid mailer record $errors[] = 'Not found in DB: ' . $vals[1] . '/' . $vals[2]; } $row = $this->db->fetch(MYSQL_ASSOC); $row = $this->dbToBoth($row); $bounceInfo = $row; if ($emailAddress && $emailAddress != $row['mail_recipient_email']) { $errors[] = 'Email address mismatch: ' . $emailAddress . '/' . $row['mail_recipient_email']; } if ($uid != $row['mail_recipient_id']) { $errors[] = 'User ID mismatch: ' . $uid . '/' . $row['mail_recipient_id']; } if (count($errors) == 0) { $bounceInfo['mail_source_id'] = $vals[1]; $bounceInfo['mail_target_id'] = $vals[2]; $bounceInfo['mail_recipient_id'] = $uid; $bounceInfo['mail_recipient_name'] = $row['mail_recipient_name']; if (!$this->db->update('mail_content', '`mail_bounce_count` = `mail_bounce_count` + 1 WHERE `mail_source_id` = ' . $vals[1])) { e107::getAdminLog()->add('Unable to increment bounce-count on mail_source_id=' . $vals[1], $bounceInfo, E_LOG_FATAL, 'BOUNCE', LOG_TO_ROLLING); } if (!$this->db->update('mail_recipients', '`mail_status` = ' . MAIL_STATUS_BOUNCED . ' WHERE `mail_target_id` = ' . $vals[2])) { e107::getAdminLog()->add('Unable to update recipient mail_status to bounce on mail_target_id = ' . $vals[2], $bounceInfo, E_LOG_FATAL, 'BOUNCE', LOG_TO_ROLLING); } $addons = array_keys($row['mail_selectors']); // trigger e_mailout.php addons. 'bounce' method. foreach ($addons as $plug) { if ($plug == 'core') { require_once e_HANDLER . 'user_handler.php'; if ($err = userHandler::userStatusUpdate('bounce', $uid, $emailAddress)) { } $errors[] = $err; } else { if ($cls = e107::getAddon($plug, 'e_mailout')) { if (e107::callMethod($cls, 'bounce', $bounceInfo) === false) { e107::getAdminLog()->add($plug . ' bounce process failed', $bounceInfo, E_LOG_FATAL, 'BOUNCE', LOG_TO_ROLLING); } } } } } // echo e107::getMessage()->render(); // print_a($bounceInfo); } } elseif (count($vals) != 1 && count($vals) != 4) { $errors[] = 'Bad element count: ' . count($vals); } elseif (!empty($uid) || !empty($emailAddress)) { // require_once(e_HANDLER.'user_handler.php'); $err = e107::getUserSession()->userStatusUpdate('bounce', $uid, $emailAddress); if ($err) { $errors[] = $err; } } if (!empty($errors)) { $logErrors = $bounceInfo; $logErrors['user_id'] = $uid; $logErrors['mailshot'] = $vals[1]; $logErrors['mailshot_recipient'] = $vals[2]; $logErrors['errors'] = $errors; $logErrors['email'] = $emailAddress; $logErrors['bounceString'] = $bounceString; $logString = $bounceString . ' (' . $emailAddress . ')[!br!]' . implode('[!br!]', $errors) . implode('[!br!]', $bounceInfo); // e107::getAdminLog()->e_log_event(10,-1,'BOUNCE','Bounce receive error',$logString, FALSE,LOG_TO_ROLLING); e107::getAdminLog()->add('Bounce receive error', $logErrors, E_LOG_WARNING, 'BOUNCE', LOG_TO_ROLLING); return $errors; } else { // e107::getAdminLog()->e_log_event(10,-1,'BOUNCE','Bounce received/logged',$bounceInfo, FALSE,LOG_TO_ROLLING); e107::getAdminLog()->add('Bounce received/logged', $bounceInfo, E_LOG_INFORMATIVE, 'BOUNCE', LOG_TO_ROLLING); } e107::getEvent()->trigger('mailbounce', $bounceInfo); return false; }