Example #1
0
    if (!@empty($HTTP_POST_VARS['new_status'])) {
        $res = Issue::setStatus($issue_id, $HTTP_POST_VARS['new_status']);
        if ($res != -1) {
            $new_status = Status::getStatusTitle($HTTP_POST_VARS['new_status']);
            History::add($issue_id, $usr_id, History::getTypeID('status_changed'), "Status changed to '{$new_status}' by " . User::getFullName($usr_id));
        }
    }
    $res = Note::insert($usr_id, $issue_id);
    $tpl->assign("post_result", $res);
    // enter the time tracking entry about this phone support entry
    if (!empty($HTTP_POST_VARS['time_spent'])) {
        $HTTP_POST_VARS['issue_id'] = $issue_id;
        $HTTP_POST_VARS['category'] = $HTTP_POST_VARS['time_category'];
        $HTTP_POST_VARS['summary'] = 'Time entry inserted when sending an internal note.';
        Time_Tracking::insertEntry();
    }
} elseif (@$HTTP_GET_VARS["cat"] == "reply") {
    if (!@empty($HTTP_GET_VARS["id"])) {
        $note = Note::getDetails($HTTP_GET_VARS["id"]);
        $date = Misc::formatReplyDate($note["timestamp"]);
        $header = "\n\n\nOn {$date}, " . $note["not_from"] . " wrote:\n>\n";
        $note["not_body"] = $header . Misc::formatReply($note["not_note"]);
        $tpl->bulkAssign(array("note" => $note, "parent_note_id" => $HTTP_GET_VARS["id"]));
        $reply_subject = Mail_API::removeExcessRe($note['not_title']);
    }
}
if (empty($reply_subject)) {
    $reply_subject = 'Re: ' . $details['iss_summary'];
}
$tpl->assign(array('from' => User::getFromHeader($usr_id), 'users' => Project::getUserAssocList($prj_id, 'active', User::getRoleID('Customer')), 'current_user_prefs' => Prefs::get($usr_id), 'subscribers' => Notification::getSubscribers($issue_id, false, User::getRoleID("Standard User")), 'statuses' => Status::getAssocStatusList($prj_id, false), 'current_issue_status' => Issue::getStatusID($issue_id), 'time_categories' => Time_Tracking::getAssocCategories(), 'note_category_id' => Time_Tracking::getCategoryID('Note Discussion'), 'reply_subject' => $reply_subject));
$tpl->displayTemplate();
Example #2
0
 /**
  * Believe it or not, this is a method that will remove excess occurrences
  * of 'Re:' that commonly are found in email subject lines.
  * If the second parameter is true, issue #'s will also be stripped.
  *
  * @access  public
  * @param   string $subject The subject line
  * @param   boolean $remove_issue_id If the issue ID should be removed
  * @return  string The subject line with the extra occurrences removed from it
  */
 function removeExcessRe($subject, $remove_issue_id = false)
 {
     if ($remove_issue_id) {
         $subject = trim(preg_replace("/\\[#\\d+\\] {0,1}/", '', $subject));
     }
     $re_pattern = "/(\\[#\\d+\\] ){0,1}(([Rr][Ee][Ss]?|Îòâåò|Antwort|SV|[Aa][Ww])(\\[[0-9]+\\])?[ \t]*: ){2}(.*)/";
     if (preg_match($re_pattern, $subject, $matches)) {
         $subject = preg_replace($re_pattern, '$1Re: $5', $subject);
         return Mail_API::removeExcessRe($subject);
     } else {
         return $subject;
     }
 }
Example #3
0
 /**
  * Method used to send an email from the user interface.
  *
  * @access  public
  * @return  integer 1 if it worked, -1 otherwise
  */
 function sendEmail($parent_sup_id = FALSE)
 {
     global $HTTP_POST_VARS, $HTTP_SERVER_VARS;
     // if we are replying to an existing email, set the In-Reply-To: header accordingly
     if ($parent_sup_id) {
         $in_reply_to = Support::getMessageIDByID($parent_sup_id);
     } else {
         $in_reply_to = false;
     }
     // get ID of whoever is sending this.
     $sender_usr_id = User::getUserIDByEmail(Mail_API::getEmailAddress($HTTP_POST_VARS["from"]));
     if (empty($sender_usr_id)) {
         $sender_usr_id = false;
     }
     // get type of email this is
     if (!empty($HTTP_POST_VARS['type'])) {
         $type = $HTTP_POST_VARS['type'];
     } else {
         $type = '';
     }
     // remove extra 'Re: ' from subject
     $HTTP_POST_VARS['subject'] = Mail_API::removeExcessRe($HTTP_POST_VARS['subject'], true);
     $internal_only = false;
     $message_id = Mail_API::generateMessageID();
     // hack needed to get the full headers of this web-based email
     $full_email = Support::buildFullHeaders($HTTP_POST_VARS["issue_id"], $message_id, $HTTP_POST_VARS["from"], $HTTP_POST_VARS["to"], $HTTP_POST_VARS["cc"], $HTTP_POST_VARS["subject"], $HTTP_POST_VARS["message"], $in_reply_to);
     // email blocking should only be done if this is an email about an associated issue
     if (!empty($HTTP_POST_VARS['issue_id'])) {
         $user_info = User::getNameEmail(Auth::getUserID());
         // check whether the current user is allowed to send this email to customers or not
         if (!Support::isAllowedToEmail($HTTP_POST_VARS["issue_id"], $user_info['usr_email'])) {
             // add the message body as a note
             $HTTP_POST_VARS['blocked_msg'] = $full_email;
             $HTTP_POST_VARS['title'] = $HTTP_POST_VARS["subject"];
             $HTTP_POST_VARS['note'] = Mail_API::getCannedBlockedMsgExplanation() . $HTTP_POST_VARS["message"];
             Note::insert(Auth::getUserID(), $HTTP_POST_VARS["issue_id"]);
             Workflow::handleBlockedEmail(Issue::getProjectID($HTTP_POST_VARS['issue_id']), $HTTP_POST_VARS['issue_id'], $HTTP_POST_VARS, 'web');
             return 1;
         }
     }
     // only send a direct email if the user doesn't want to add the Cc'ed people to the notification list
     if (@$HTTP_POST_VARS['add_unknown'] == 'yes') {
         if (!empty($HTTP_POST_VARS['issue_id'])) {
             // add the recipients to the notification list of the associated issue
             $recipients = array($HTTP_POST_VARS['to']);
             $recipients = array_merge($recipients, Support::getRecipientsCC($HTTP_POST_VARS['cc']));
             for ($i = 0; $i < count($recipients); $i++) {
                 if (!empty($recipients[$i]) && !Notification::isIssueRoutingSender($HTTP_POST_VARS["issue_id"], $recipients[$i])) {
                     Notification::subscribeEmail(Auth::getUserID(), $HTTP_POST_VARS["issue_id"], Mail_API::getEmailAddress($recipients[$i]), array('emails'));
                 }
             }
         }
     } else {
         // Usually when sending out emails associated to an issue, we would
         // simply insert the email in the table and call the Notification::notifyNewEmail() method,
         // but on this case we need to actually send the email to the recipients that are not
         // already in the notification list for the associated issue, if any.
         // In the case of replying to an email that is not yet associated with an issue, then
         // we are always directly sending the email, without using any notification list
         // functionality.
         if (!empty($HTTP_POST_VARS['issue_id'])) {
             // send direct emails only to the unknown addresses, and leave the rest to be
             // catched by the notification list
             $from = Notification::getFixedFromHeader($HTTP_POST_VARS['issue_id'], $HTTP_POST_VARS['from'], 'issue');
             // build the list of unknown recipients
             if (!empty($HTTP_POST_VARS['to'])) {
                 $recipients = array($HTTP_POST_VARS['to']);
                 $recipients = array_merge($recipients, Support::getRecipientsCC($HTTP_POST_VARS['cc']));
             } else {
                 $recipients = Support::getRecipientsCC($HTTP_POST_VARS['cc']);
             }
             $unknowns = array();
             for ($i = 0; $i < count($recipients); $i++) {
                 if (!Notification::isSubscribedToEmails($HTTP_POST_VARS['issue_id'], $recipients[$i])) {
                     $unknowns[] = $recipients[$i];
                 }
             }
             if (count($unknowns) > 0) {
                 $to = array_shift($unknowns);
                 $cc = implode('; ', $unknowns);
                 // send direct emails
                 Support::sendDirectEmail($HTTP_POST_VARS['issue_id'], $from, $to, $cc, $HTTP_POST_VARS['subject'], $HTTP_POST_VARS['message'], $message_id, $sender_usr_id);
             }
         } else {
             // send direct emails to all recipients, since we don't have an associated issue
             $project_info = Project::getOutgoingSenderAddress(Auth::getCurrentProject());
             // use the project-related outgoing email address, if there is one
             if (!empty($project_info['email'])) {
                 $from = Mail_API::getFormattedName(User::getFullName(Auth::getUserID()), $project_info['email']);
             } else {
                 // otherwise, use the real email address for the current user
                 $from = User::getFromHeader(Auth::getUserID());
             }
             // send direct emails
             Support::sendDirectEmail($HTTP_POST_VARS['issue_id'], $from, $HTTP_POST_VARS['to'], $HTTP_POST_VARS['cc'], $HTTP_POST_VARS['subject'], $HTTP_POST_VARS['message'], $message_id);
         }
     }
     $t = array('customer_id' => 'NULL', 'issue_id' => $HTTP_POST_VARS["issue_id"] ? $HTTP_POST_VARS["issue_id"] : 0, 'ema_id' => $HTTP_POST_VARS['ema_id'], 'message_id' => $message_id, 'date' => Date_API::getCurrentDateGMT(), 'from' => $HTTP_POST_VARS['from'], 'to' => $HTTP_POST_VARS['to'], 'cc' => @$HTTP_POST_VARS['cc'], 'subject' => @$HTTP_POST_VARS['subject'], 'body' => $HTTP_POST_VARS['message'], 'full_email' => $full_email, 'has_attachment' => 0);
     // associate this new email with a customer, if appropriate
     if (Auth::getCurrentRole() == User::getRoleID('Customer')) {
         $customer_id = User::getCustomerID(Auth::getUserID());
         if (!empty($customer_id) && $customer_id != -1) {
             $t['customer_id'] = $customer_id;
         }
     }
     $structure = Mime_Helper::decode($full_email, true, false);
     $t['headers'] = $structure->headers;
     $res = Support::insertEmail($t, $structure, $sup_id);
     if (!empty($HTTP_POST_VARS["issue_id"])) {
         // need to send a notification
         Notification::notifyNewEmail(Auth::getUserID(), $HTTP_POST_VARS["issue_id"], $t, $internal_only, false, $type, $sup_id);
         // mark this issue as updated
         if (!empty($t['customer_id']) && $t['customer_id'] != 'NULL') {
             Issue::markAsUpdated($HTTP_POST_VARS["issue_id"], 'customer action');
         } else {
             if (!empty($sender_usr_id) && User::getRoleByUser($sender_usr_id, Issue::getProjectID($HTTP_POST_VARS['issue_id'])) > User::getRoleID('Customer')) {
                 Issue::markAsUpdated($HTTP_POST_VARS["issue_id"], 'staff response');
             } else {
                 Issue::markAsUpdated($HTTP_POST_VARS["issue_id"], 'user response');
             }
         }
         // save a history entry for this
         History::add($HTTP_POST_VARS["issue_id"], Auth::getUserID(), History::getTypeID('email_sent'), 'Outgoing email sent by ' . User::getFullName(Auth::getUserID()));
         // also update the last_response_date field for the associated issue
         if (Auth::getCurrentRole() > User::getRoleID('Customer')) {
             $stmt = "UPDATE\n                            " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "issue\n                         SET\n                            iss_last_response_date='" . Date_API::getCurrentDateGMT() . "'\n                         WHERE\n                            iss_id=" . Misc::escapeInteger($HTTP_POST_VARS["issue_id"]);
             $GLOBALS["db_api"]->dbh->query($stmt);
             $stmt = "UPDATE\n                            " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "issue\n                         SET\n                            iss_first_response_date='" . Date_API::getCurrentDateGMT() . "'\n                         WHERE\n                            iss_first_response_date IS NULL AND\n                            iss_id=" . Misc::escapeInteger($HTTP_POST_VARS["issue_id"]);
             $GLOBALS["db_api"]->dbh->query($stmt);
         }
     }
     return 1;
 }
Example #4
0
 /**
  * Routes an email to the correct issue.
  *
  * @param   string $full_message The full email message, including headers
  * @param   integer $email_account_id The ID of the email account this email should be routed too. If empty this method will try to figure it out
  */
 function route_emails($full_message, $email_account_id = 0)
 {
     global $HTTP_POST_VARS;
     // save the full message for logging purposes
     Support::saveRoutedEmail($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);
     }
     // associate routed emails to the internal system account
     $sys_account = User::getNameEmail(APP_SYSTEM_USER_ID);
     $associated_user = $sys_account['usr_email'];
     // need some validation here
     if (empty($full_message)) {
         return array(66, "Error: The email message was empty.\n");
     }
     if (empty($associated_user)) {
         return array(78, "Error: The associated user for the email routing interface needs to be set.\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 for magic cookie
     if (Mail_API::hasMagicCookie($full_message)) {
         // strip the magic cookie
         $full_message = Mail_API::stripMagicCookie($full_message);
         $has_magic_cookie = true;
     } else {
         $has_magic_cookie = false;
     }
     Auth::createFakeCookie(APP_SYSTEM_USER_ID);
     // check if the email routing interface is even supposed to be enabled
     $setup = Setup::load();
     if ($setup['email_routing']['status'] != 'enabled') {
         return array(78, "Error: The email routing interface is disabled.\n");
     }
     $prefix = $setup['email_routing']['address_prefix'];
     // escape plus signs so '*****@*****.**' becomes a valid routing address
     $prefix = str_replace('+', '\\+', $prefix);
     $mail_domain = quotemeta($setup['email_routing']['address_host']);
     $mail_domain_alias = quotemeta(@$setup['email_routing']['host_alias']);
     if (!empty($mail_domain_alias)) {
         $mail_domain = "(?:" . $mail_domain . "|" . $mail_domain_alias . ")";
     }
     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 email had no associated Eventum issue ID or had an invalid recipient address.\n");
         }
     }
     if (empty($email_account_id)) {
         $issue_prj_id = Issue::getProjectID($issue_id);
         if (empty($issue_prj_id)) {
             return array(65, "Error: The routed email had no associated Eventum issue ID or had an invalid recipient address.\n");
         }
         $email_account_id = Email_Account::getEmailAccount($issue_prj_id);
     }
     if (empty($email_account_id)) {
         return array(78, "Error: Please provide the email account ID.\n");
     }
     $body = Mime_Helper::getMessageBody($structure);
     // hack for clients that set more then one from header
     if (is_array($structure->headers['from'])) {
         $structure->headers['from'] = $structure->headers['from'][0];
     }
     // associate the email to the issue
     $parts = array();
     Mime_Helper::parse_output($structure, $parts);
     // get the sender's email address
     $sender_email = strtolower(Mail_API::getEmailAddress($structure->headers['from']));
     // strip out the warning message sent to staff users
     if ($setup['email_routing']['status'] == 'enabled' && $setup['email_routing']['warning']['status'] == 'enabled') {
         $full_message = Mail_API::stripWarningMessage($full_message);
         $body = Mail_API::stripWarningMessage($body);
     }
     $prj_id = Issue::getProjectID($issue_id);
     Auth::createFakeCookie(APP_SYSTEM_USER_ID, $prj_id);
     $staff_emails = Project::getUserEmailAssocList($prj_id, 'active', User::getRoleID('Customer'));
     $staff_emails = array_map('strtolower', $staff_emails);
     // only allow staff users to use the magic cookie
     if (!in_array($sender_email, array_values($staff_emails))) {
         $has_magic_cookie = false;
     }
     if (Mime_Helper::hasAttachments($full_message)) {
         $has_attachments = 1;
     } else {
         $has_attachments = 0;
     }
     // remove certain CC addresses
     if (!empty($structure->headers['cc']) && @$setup['smtp']['save_outgoing_email'] == 'yes') {
         $ccs = explode(",", @$structure->headers['cc']);
         for ($i = 0; $i < count($ccs); $i++) {
             if (Mail_API::getEmailAddress($ccs[$i]) == $setup['smtp']['save_address']) {
                 unset($ccs[$i]);
             }
         }
         @($structure->headers['cc'] = join(', ', $ccs));
     }
     // Remove excess Re's
     @($structure->headers['subject'] = Mail_API::removeExcessRe(@$structure->headers['subject'], true));
     $t = array('issue_id' => $issue_id, 'ema_id' => $email_account_id, 'message_id' => @$structure->headers['message-id'], 'date' => Date_API::getCurrentDateGMT(), 'from' => @$structure->headers['from'], 'to' => @$structure->headers['to'], 'cc' => @$structure->headers['cc'], 'subject' => @$structure->headers['subject'], 'body' => @$body, 'full_email' => @$full_message, 'has_attachment' => $has_attachments, 'headers' => @$structure->headers);
     // automatically associate this incoming email with a customer
     if (Customer::hasCustomerIntegration($prj_id)) {
         if (!empty($structure->headers['from'])) {
             list($customer_id, ) = Customer::getCustomerIDByEmails($prj_id, array($sender_email));
             if (!empty($customer_id)) {
                 $t['customer_id'] = $customer_id;
             }
         }
     }
     if (empty($t['customer_id'])) {
         $t['customer_id'] = "NULL";
     }
     if (!$has_magic_cookie && Support::blockEmailIfNeeded($t)) {
         return true;
     }
     // re-write Threading headers if needed
     list($t['full_email'], $t['headers']) = Mail_API::rewriteThreadingHeaders($t['issue_id'], $t['full_email'], $t['headers'], "email");
     $res = Support::insertEmail($t, $structure, $sup_id);
     if ($res != -1) {
         Support::extractAttachments($issue_id, $full_message);
         // notifications about new emails are always external
         $internal_only = false;
         $assignee_only = false;
         // special case when emails are bounced back, so we don't want a notification to customers about those
         if (Notification::isBounceMessage($sender_email)) {
             // broadcast this email only to the assignees for this issue
             $internal_only = true;
             $assignee_only = true;
         }
         Notification::notifyNewEmail(Auth::getUserID(), $issue_id, $t, $internal_only, $assignee_only, '', $sup_id);
         // try to get usr_id of sender, if not, use system account
         $usr_id = User::getUserIDByEmail(Mail_API::getEmailAddress($structure->headers['from']));
         if (!$usr_id) {
             $usr_id = APP_SYSTEM_USER_ID;
         }
         // mark this issue as updated
         if (!empty($t['customer_id']) && $t['customer_id'] != 'NULL') {
             Issue::markAsUpdated($issue_id, 'customer action');
         } else {
             if (!empty($usr_id) && User::getRoleByUser($usr_id, $prj_id) > User::getRoleID('Customer')) {
                 Issue::markAsUpdated($issue_id, 'staff response');
             } else {
                 Issue::markAsUpdated($issue_id, 'user response');
             }
         }
         // log routed email
         History::add($issue_id, $usr_id, History::getTypeID('email_routed'), "Email routed from " . $structure->headers['from']);
     }
     return true;
 }