예제 #1
0
 /**
  * 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);
 }
예제 #2
0
 /**
  * Method used to add a new support email to the system.
  *
  * @access  public
  * @param   array $row The support email details
  * @param   object $structure The email structure object
  * @param   integer $sup_id The support ID to be passed out
  * @param   boolean $closing If this email comes from closing the issue
  * @return  integer 1 if the insert worked, -1 otherwise
  */
 function insertEmail($row, &$structure, &$sup_id, $closing = false)
 {
     // get usr_id from FROM header
     $usr_id = User::getUserIDByEmail(Mail_API::getEmailAddress($row['from']));
     if (!empty($usr_id) && !empty($row["customer_id"])) {
         $row["customer_id"] = User::getCustomerID($usr_id);
     }
     if (empty($row['customer_id'])) {
         $row['customer_id'] = "NULL";
     }
     // try to get the parent ID
     $reference_message_id = Mail_API::getReferenceMessageID($row['full_email']);
     $parent_id = '';
     if (!empty($reference_message_id)) {
         $parent_id = Support::getIDByMessageID($reference_message_id);
         // make sure it is in the same issue
         if (!empty($parent_id) && (empty($row['issue_id']) || @$row['issue_id'] != Support::getIssueFromEmail($parent_id))) {
             $parent_id = '';
         }
     }
     $stmt = "INSERT INTO\n                    " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "support_email\n                 (\n                    sup_ema_id,";
     if (!empty($parent_id)) {
         $stmt .= "\nsup_parent_id,";
     }
     $stmt .= "\n                    sup_iss_id,";
     if (!empty($usr_id)) {
         $stmt .= "\nsup_usr_id,\n";
     }
     $stmt .= "  sup_customer_id,\n                    sup_message_id,\n                    sup_date,\n                    sup_from,\n                    sup_to,\n                    sup_cc,\n                    sup_subject,\n                    sup_has_attachment\n                 ) VALUES (\n                    " . Misc::escapeInteger($row["ema_id"]) . ",\n";
     if (!empty($parent_id)) {
         $stmt .= "{$parent_id},\n";
     }
     $stmt .= Misc::escapeInteger($row["issue_id"]) . ",";
     if (!empty($usr_id)) {
         $stmt .= "\n{$usr_id},\n";
     }
     $stmt .= "\n                    " . Misc::escapeInteger($row["customer_id"]) . ",\n                    '" . Misc::escapeString($row["message_id"]) . "',\n                    '" . Misc::escapeString($row["date"]) . "',\n                    '" . Misc::escapeString($row["from"]) . "',\n                    '" . Misc::escapeString(@$row["to"]) . "',\n                    '" . Misc::escapeString(@$row["cc"]) . "',\n                    '" . Misc::escapeString($row["subject"]) . "',\n                    '" . Misc::escapeString($row["has_attachment"]) . "'\n                 )";
     $res = $GLOBALS["db_api"]->dbh->query($stmt);
     if (PEAR::isError($res)) {
         Error_Handler::logError(array($res->getMessage(), $res->getDebugInfo()), __FILE__, __LINE__);
         return -1;
     } else {
         $new_sup_id = $GLOBALS["db_api"]->get_last_insert_id();
         $sup_id = $new_sup_id;
         // now add the body and full email to the separate table
         $stmt = "INSERT INTO\n                        " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "support_email_body\n                     (\n                        seb_sup_id,\n                        seb_body,\n                        seb_full_email\n                     ) VALUES (\n                        {$new_sup_id},\n                        '" . Misc::escapeString($row["body"]) . "',\n                        '" . Misc::escapeString($row["full_email"]) . "'\n                     )";
         $res = $GLOBALS["db_api"]->dbh->query($stmt);
         if (PEAR::isError($res)) {
             Error_Handler::logError(array($res->getMessage(), $res->getDebugInfo()), __FILE__, __LINE__);
             return -1;
         } else {
             Workflow::handleNewEmail(Email_Account::getProjectID($row["ema_id"]), @$row["issue_id"], $structure, $row, $closing);
             return 1;
         }
     }
 }
예제 #3
0
 /**
  * Routes a note to the correct issue
  *
  * @param   string $full_message The full note
  */
 function route_notes($full_message)
 {
     global $HTTP_POST_VARS;
     // save the full message for logging purposes
     Note::saveRoutedNote($full_message);
     if (preg_match("/^(boundary=).*/m", $full_message)) {
         $pattern = "/(Content-Type: multipart\\/)(.+); ?\r?\n(boundary=)(.*)\$/im";
         $replacement = '$1$2; $3$4';
         $full_message = preg_replace($pattern, $replacement, $full_message);
     }
     list($headers, ) = Mime_Helper::splitHeaderBody($full_message);
     // need some validation here
     if (empty($full_message)) {
         return array(66, "Error: The email message was empty.\n");
     }
     //
     // DON'T EDIT ANYTHING BELOW THIS LINE
     //
     // remove the reply-to: header
     if (preg_match("/^(reply-to:).*/im", $full_message)) {
         $full_message = preg_replace("/^(reply-to:).*\n/im", '', $full_message, 1);
     }
     // check if the email routing interface is even supposed to be enabled
     $setup = Setup::load();
     if (@$setup['note_routing']['status'] != 'enabled') {
         return array(78, "Error: The internal note routing interface is disabled.\n");
     }
     $prefix = $setup['note_routing']['address_prefix'];
     // escape plus signs so '*****@*****.**' becomes a valid routing address
     $prefix = str_replace('+', '\\+', $prefix);
     $mail_domain = quotemeta($setup['note_routing']['address_host']);
     if (empty($prefix)) {
         return array(78, "Error: Please configure the email address prefix.\n");
     }
     if (empty($mail_domain)) {
         return array(78, "Error: Please configure the email address domain.\n");
     }
     $structure = Mime_Helper::decode($full_message, true, true);
     // find which issue ID this email refers to
     @preg_match("/{$prefix}(\\d*)@{$mail_domain}/i", $structure->headers['to'], $matches);
     @($issue_id = $matches[1]);
     // validation is always a good idea
     if (empty($issue_id)) {
         // we need to try the Cc header as well
         @preg_match("/{$prefix}(\\d*)@{$mail_domain}/i", $structure->headers['cc'], $matches);
         if (!empty($matches[1])) {
             $issue_id = $matches[1];
         } else {
             return array(65, "Error: The routed note had no associated Eventum issue ID or had an invalid recipient address.\n");
         }
     }
     $prj_id = Issue::getProjectID($issue_id);
     // check if the sender is allowed in this issue' project and if it is an internal user
     $users = Project::getUserEmailAssocList($prj_id, 'active', User::getRoleID('Customer'));
     $sender_email = strtolower(Mail_API::getEmailAddress($structure->headers['from']));
     $user_emails = array_map('strtolower', array_values($users));
     if (!in_array($sender_email, $user_emails)) {
         return array(77, "Error: The sender of this email is not allowed in the project associated with issue #{$issue_id}.\n");
     }
     Auth::createFakeCookie(User::getUserIDByEmail($sender_email), $prj_id);
     // parse the Cc: list, if any, and add these internal users to the issue notification list
     $users = array_flip($users);
     $addresses = array();
     $to_addresses = Mail_API::getEmailAddresses(@$structure->headers['to']);
     if (count($to_addresses)) {
         $addresses = $to_addresses;
     }
     $cc_addresses = Mail_API::getEmailAddresses(@$structure->headers['cc']);
     if (count($cc_addresses)) {
         $addresses = array_merge($addresses, $cc_addresses);
     }
     $cc_users = array();
     foreach ($addresses as $email) {
         if (in_array(strtolower($email), $user_emails)) {
             $cc_users[] = $users[$email];
         }
     }
     $body = Mime_Helper::getMessageBody($structure);
     $reference_msg_id = Mail_API::getReferenceMessageID($headers);
     if (!empty($reference_msg_id)) {
         $parent_id = Note::getIDByMessageID($reference_msg_id);
     } else {
         $parent_id = false;
     }
     // insert the new note and send notification about it
     $HTTP_POST_VARS = array('title' => @$structure->headers['subject'], 'note' => $body, 'note_cc' => $cc_users, 'add_extra_recipients' => 'yes', 'message_id' => @$structure->headers['message-id'], 'parent_id' => $parent_id);
     // add the full email to the note if there are any attachments
     // this is needed because the front end code will display attachment links
     if (Mime_Helper::hasAttachments($full_message)) {
         $HTTP_POST_VARS['blocked_msg'] = $full_message;
     }
     $res = Note::insert(Auth::getUserID(), $issue_id, false, false);
     // need to handle attachments coming from notes as well
     if ($res != -1) {
         Support::extractAttachments($issue_id, $full_message, true, $res);
     }
     History::add($issue_id, Auth::getUserID(), History::getTypeID('note_routed'), "Note routed from " . $structure->headers['from']);
     return true;
 }