/** * Routes a draft to the correct issue. * * @param string $full_message The complete draft. * @return mixed true or array(ERROR_CODE, ERROR_STRING) in case of failure */ public static function route_drafts($full_message) { // save the full message for logging purposes Draft::saveRoutedMessage($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); } // need some validation here if (empty($full_message)) { return array(self::EX_NOINPUT, ev_gettext('Error: The email message was empty.') . "\n"); } // 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 draft interface is even supposed to be enabled $setup = Setup::get(); if ($setup['draft_routing']['status'] != 'enabled') { return array(self::EX_CONFIG, ev_gettext('Error: The email draft interface is disabled.') . "\n"); } if (empty($setup['draft_routing']['address_prefix'])) { return array(self::EX_CONFIG, ev_gettext('Error: Please configure the email address prefix.') . "\n"); } if (empty($setup['draft_routing']['address_host'])) { return array(self::EX_CONFIG, ev_gettext('Error: Please configure the email address domain.') . "\n"); } $structure = Mime_Helper::decode($full_message, true, false); // find which issue ID this email refers to if (isset($structure->headers['to'])) { $issue_id = self::getMatchingIssueIDs($structure->headers['to'], 'draft'); } // validation is always a good idea if (empty($issue_id) and isset($structure->headers['cc'])) { // we need to try the Cc header as well $issue_id = self::getMatchingIssueIDs($structure->headers['cc'], 'draft'); } if (empty($issue_id)) { return array(self::EX_DATAERR, ev_gettext('Error: The routed email 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 $sender_email = strtolower(Mail_Helper::getEmailAddress($structure->headers['from'])); $sender_usr_id = User::getUserIDByEmail($sender_email, true); if (!empty($sender_usr_id)) { $sender_role = User::getRoleByUser($sender_usr_id, $prj_id); if ($sender_role < User::ROLE_USER) { return array(self::EX_NOPERM, ev_gettext("Error: The sender of this email is not allowed in the project associated with issue #{$issue_id}.") . "\n"); } } AuthCookie::setAuthCookie(User::getUserIDByEmail($sender_email)); AuthCookie::setProjectCookie($prj_id); $body = $structure->body; Draft::saveEmail($issue_id, @$structure->headers['to'], @$structure->headers['cc'], @$structure->headers['subject'], $body, false, false, false); // XXX: need to handle attachments coming from drafts as well? $usr_id = Auth::getUserID(); History::add($issue_id, $usr_id, 'draft_routed', 'Draft routed from {from}', array('from' => $structure->headers['from'])); return true; }
/** * Routes a draft to the correct issue. * * @param string $full_message The complete draft. */ function route_drafts($full_message) { global $HTTP_POST_VARS; // save the full message for logging purposes Draft::saveRoutedMessage($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); } // 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 draft interface is even supposed to be enabled $setup = Setup::load(); if (@$setup['draft_routing']['status'] != 'enabled') { return array(78, "Error: The email draft interface is disabled.\n"); } $prefix = $setup['draft_routing']['address_prefix']; // escape plus signs so '*****@*****.**' becomes a valid address $prefix = str_replace('+', '\\+', $prefix); $mail_domain = quotemeta($setup['draft_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, false); // 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 draft 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); $body = Mime_Helper::getMessageBody($structure); Draft::saveEmail($issue_id, @$structure->headers['to'], @$structure->headers['cc'], @$structure->headers['subject'], $body, false, false, false); // XXX: need to handle attachments coming from drafts as well? History::add($issue_id, Auth::getUserID(), History::getTypeID('draft_routed'), "Draft routed from " . $structure->headers['from']); return true; }