/** * Checks to make sure In-Reply-To and References headers are correct. * */ function rewriteThreadingHeaders($issue_id, $full_email, $headers, $type = 'email') { list($text_headers, $body) = Mime_Helper::splitHeaderBody($full_email); if ($type == 'note') { $class = 'Note'; } else { $class = 'Support'; } $msg_id = Mail_API::getMessageID($text_headers, $body); // check if the In-Reply-To header exists and if so, does it relate to a message stored in Eventum // if it does not, set new In-Reply-To header $reference_msg_id = Mail_API::getReferenceMessageID($text_headers); $reference_issue_id = false; if (!empty($reference_msg_id)) { // check if referenced msg id is associated with this issue $reference_issue_id = call_user_func(array($class, 'getIssueByMessageID'), $reference_msg_id); } if (empty($reference_msg_id) || $reference_issue_id != $issue_id) { $reference_msg_id = Issue::getRootMessageID($issue_id); } $references = Mail_API::getReferences($issue_id, $reference_msg_id, $type); // now the fun part, re-writing the email headers if (empty($headers['message-id'])) { // add Message-ID since it doesn't exist (curses on Outlook 2003) $text_headers .= "\r\nMessage-ID: {$msg_id}"; $headers['message-id'] = $msg_id; } if (preg_match('/^In-Reply-To: (.*)/mi', $text_headers) > 0) { // replace existing header $text_headers = preg_replace('/^In-Reply-To: (.*)/mi', 'In-Reply-To: ' . $reference_msg_id, $text_headers, 1); } else { // add new header after message ID $text_headers = preg_replace('/^Message-ID: (.*)$/mi', "Message-ID: \$1\r\nIn-Reply-To: {$reference_msg_id}", $text_headers, 1); } $headers['in-reply-to'] = $reference_msg_id; if (preg_match('/^References: (.*)/mi', $text_headers) > 0) { // replace existing header $text_headers = preg_replace('/^References: (.*)/mi', 'References: ' . Mail_API::fold(join(' ', $references)), $text_headers, 1); } else { // add new header after In-Reply-To $text_headers = preg_replace('/^In-Reply-To: (.*)$/mi', "In-Reply-To: \$1\r\nReferences: " . Mail_API::fold(join(' ', $references)), $text_headers, 1); } $headers['references'] = Mail_API::fold(join(' ', $references)); return array($text_headers . "\r\n\r\n" . $body, $headers); }
/** * Method used to send email notifications for a given issue. * * @access public * @param integer $issue_id The issue ID * @param string $type The notification type * @param array $ids The list of entries that were changed * @param integer $internal_only Whether the notification should only be sent to internal users or not * @return void */ function notify($issue_id, $type, $ids = FALSE, $internal_only = FALSE, $extra_recipients = FALSE) { if ($extra_recipients) { $extra = array(); for ($i = 0; $i < count($extra_recipients); $i++) { $extra[] = array('sub_usr_id' => $extra_recipients[$i], 'sub_email' => ''); } } $emails = array(); $users = Notification::getUsersByIssue($issue_id, $type); if ($extra_recipients && count($extra) > 0) { $users = array_merge($users, $extra); } $user_emails = Project::getUserEmailAssocList(Issue::getProjectID($issue_id), 'active', User::getRoleID('Customer')); $user_emails = array_map('strtolower', $user_emails); for ($i = 0; $i < count($users); $i++) { if (empty($users[$i]["sub_usr_id"])) { if ($internal_only == false || in_array(strtolower($users[$i]["sub_email"]), array_values($user_emails))) { $email = $users[$i]["sub_email"]; } } else { // don't send the notification email to the person who performed the action if (Auth::getUserID() == $users[$i]["sub_usr_id"]) { continue; } // if we are only supposed to send email to internal users, check if the role is lower than standard user if ($internal_only == true && User::getRoleByUser($users[$i]["sub_usr_id"], Issue::getProjectID($issue_id)) < User::getRoleID('standard user')) { continue; } $email = User::getFromHeader($users[$i]["sub_usr_id"]); } // now add it to the list of emails if (!empty($email) && !in_array($email, $emails)) { $emails[] = $email; } } // prevent the primary customer contact from receiving two emails about the issue being closed if ($type == 'closed') { $stmt = "SELECT\r\n iss_customer_contact_id\r\n FROM\r\n " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "issue\r\n WHERE\r\n iss_id=" . Misc::escapeInteger($issue_id); $customer_contact_id = $GLOBALS["db_api"]->dbh->getOne($stmt); if (!empty($customer_contact_id)) { list($contact_email, , ) = Customer::getContactLoginDetails(Issue::getProjectID($issue_id), $customer_contact_id); for ($i = 0; $i < count($emails); $i++) { $email = Mail_API::getEmailAddress($emails[$i]); if ($email == $contact_email) { unset($emails[$i]); $emails = array_values($emails); break; } } } } if (count($emails) > 0) { $headers = false; switch ($type) { case 'closed': $data = Notification::getIssueDetails($issue_id); $data["closer_name"] = User::getFullName(History::getIssueCloser($issue_id)); $subject = 'Closed'; if ($ids != false) { $data['reason'] = Support::getEmail($ids); } break; case 'updated': // this should not be used anymore return false; break; case 'notes': $data = Notification::getNote($issue_id, $ids); $headers = array('Message-ID' => $data['note']['not_message_id']); if (@$data['note']['reference_msg_id'] != false) { $headers['In-Reply-To'] = $data['note']['reference_msg_id']; } else { $headers['In-Reply-To'] = Issue::getRootMessageID($issue_id); } $headers['References'] = Mail_API::fold(join(' ', Mail_API::getReferences($issue_id, @$data['note']['reference_msg_id'], 'note'))); $subject = 'Note'; break; case 'emails': // this should not be used anymore return false; break; case 'files': $data = Notification::getAttachment($issue_id, $ids); $subject = 'File Attached'; break; } Notification::notifySubscribers($issue_id, $emails, $type, $data, $subject, $internal_only, $ids, $headers); } }