/** * Connects to the SMTP server and sends the queued message. * * @param string $recipient The recipient of this message * @param string $text_headers The full headers of this message * @param string $body The full body of this message * @param string $status The status of this message * @return true, or a PEAR_Error object */ private function _sendEmail($recipient, $text_headers, &$body, $status) { $header_names = Mime_Helper::getHeaderNames($text_headers); $_headers = self::_getHeaders($text_headers, $body); $headers = array(); foreach ($_headers as $lowercase_name => $value) { // need to remove the quotes to avoid a parsing problem // on senders that have extended characters in the first // or last words in their sender name if ($lowercase_name == 'from') { $value = Mime_Helper::removeQuotes($value); } $value = Mime_Helper::encode($value); // add the quotes back if ($lowercase_name == 'from') { $value = Mime_Helper::quoteSender($value); } $headers[$header_names[$lowercase_name]] = $value; } // remove any Reply-To:/Return-Path: values from outgoing messages unset($headers['Reply-To']); unset($headers['Return-Path']); // mutt sucks, so let's remove the broken Mime-Version header and add the proper one if (in_array('Mime-Version', array_keys($headers))) { unset($headers['Mime-Version']); $headers['MIME-Version'] = '1.0'; } $mail = Mail::factory('smtp', Mail_Helper::getSMTPSettings()); $res = $mail->send($recipient, $headers, $body); if (Misc::isError($res)) { // special handling of errors when the mail server is down $msg = $res->getMessage(); $cant_notify = $status == 'error' || strstr($msg, 'unable to connect to smtp server') || stristr($msg, 'Failed to connect to') !== false; Error_Handler::logError(array($msg, $res->getDebugInfo()), __FILE__, __LINE__, !$cant_notify); return $res; } return true; }
/** * Connects to the SMTP server and sends the queued message. * * @param string $recipient The recipient of this message * @param string $text_headers The full headers of this message * @param string $body The full body of this message * @param string $status The status of this message * @return true, or a PEAR_Error object */ private function _sendEmail($recipient, $text_headers, &$body, $status) { $header_names = Mime_Helper::getHeaderNames($text_headers); $_headers = self::_getHeaders($text_headers, $body); $headers = array(); foreach ($_headers as $lowercase_name => $value) { // need to remove the quotes to avoid a parsing problem // on senders that have extended characters in the first // or last words in their sender name if ($lowercase_name == 'from') { $value = Mime_Helper::removeQuotes($value); } $value = Mime_Helper::encode($value); // add the quotes back if ($lowercase_name == 'from') { $value = Mime_Helper::quoteSender($value); } $headers[$header_names[$lowercase_name]] = $value; } // remove any Reply-To:/Return-Path: values from outgoing messages unset($headers['Reply-To']); unset($headers['Return-Path']); // mutt sucks, so let's remove the broken Mime-Version header and add the proper one if (in_array('Mime-Version', array_keys($headers))) { unset($headers['Mime-Version']); $headers['MIME-Version'] = '1.0'; } $mail = Mail::factory('smtp', Mail_Helper::getSMTPSettings()); $res = $mail->send($recipient, $headers, $body); if (Misc::isError($res)) { Logger::app()->error($res->getMessage(), array('debug' => $res->getDebugInfo())); return $res; } return true; }
/** * Method used to save a copy of the given email to a configurable address. * * @access public * @param array $email The email to save. */ function saveEmailInformation($email) { static $subjects; $hdrs = $email['headers']; $body = $email['body']; $issue_id = $email['maq_iss_id']; $sender_usr_id = $email['maq_usr_id']; // do we really want to save every outgoing email? $setup = Setup::load(); if (@$setup['smtp']['save_outgoing_email'] != 'yes' || empty($setup['smtp']['save_address'])) { return false; } // ok, now parse the headers text and build the assoc array $full_email = $hdrs . "\n\n" . $body; $structure = Mime_Helper::decode($full_email, FALSE, FALSE); $_headers =& $structure->headers; $header_names = Mime_Helper::getHeaderNames($hdrs); $headers = array(); foreach ($_headers as $lowercase_name => $value) { $headers[$header_names[$lowercase_name]] = $value; } // remove any Reply-To:/Return-Path: values from outgoing messages unset($headers['Reply-To']); unset($headers['Return-Path']); // prevent duplicate emails from being sent out... $subject = @$headers['Subject']; if (@in_array($subject, $subjects)) { return false; } // replace the To: header with the requested address $address = $setup['smtp']['save_address']; $headers['To'] = $address; // add specialized headers if they are not already added if (empty($headers['X-Eventum-Type'])) { $headers += Mail_API::getSpecializedHeaders($issue_id, $email['maq_type'], $headers, $sender_usr_id); } $params = Mail_API::getSMTPSettings($address); $mail =& Mail::factory('smtp', $params); $res = $mail->send($address, $headers, $body); if (PEAR::isError($res)) { Error_Handler::logError(array($res->getMessage(), $res->getDebugInfo()), __FILE__, __LINE__); } $subjects[] = $subject; }
/** * Method used to save a copy of the given email to a configurable address. * * @param array $email The email to save. */ public static function saveOutgoingEmailCopy(&$email) { // check early: do we really want to save every outgoing email? $setup = Setup::load(); $save_outgoing_email = !empty($setup['smtp']['save_outgoing_email']) && $setup['smtp']['save_outgoing_email'] == 'yes'; if (!$save_outgoing_email || empty($setup['smtp']['save_address'])) { return false; } static $subjects = array(); $hdrs =& $email['headers']; $body =& $email['body']; $issue_id = $email['maq_iss_id']; $sender_usr_id = $email['maq_usr_id']; // ok, now parse the headers text and build the assoc array $full_email = $hdrs . "\n\n" . $body; $structure = Mime_Helper::decode($full_email, false, false); $_headers =& $structure->headers; $header_names = Mime_Helper::getHeaderNames($hdrs); $headers = array(); foreach ($_headers as $lowercase_name => $value) { // need to remove the quotes to avoid a parsing problem // on senders that have extended characters in the first // or last words in their sender name if ($lowercase_name == 'from') { $value = Mime_Helper::removeQuotes($value); } $value = Mime_Helper::encode($value); // add the quotes back if ($lowercase_name == 'from') { $value = Mime_Helper::quoteSender($value); } $headers[$header_names[$lowercase_name]] = $value; } // remove any Reply-To:/Return-Path: values from outgoing messages unset($headers['Reply-To']); unset($headers['Return-Path']); // prevent duplicate emails from being sent out... $subject = @$headers['Subject']; if (@in_array($subject, $subjects)) { return false; } // replace the To: header with the requested address $address = $setup['smtp']['save_address']; $headers['To'] = $address; // add specialized headers if they are not already added if (empty($headers['X-Eventum-Type'])) { $headers += self::getSpecializedHeaders($issue_id, $email['maq_type'], $headers, $sender_usr_id); } $params = self::getSMTPSettings($address); $mail = Mail::factory('smtp', $params); $res = $mail->send($address, $headers, $body); if (Misc::isError($res)) { Error_Handler::logError(array($res->getMessage(), $res->getDebugInfo()), __FILE__, __LINE__); } $subjects[] = $subject; }
/** * Method used to forward the new email to the list of subscribers. * * @param integer $user_id The user ID of the person performing this action * @param integer $issue_id The issue ID * @param array $message An array containing the email * @param boolean $internal_only Whether the email should only be redirected to internal users or not * @param boolean $assignee_only Whether the email should only be sent to the assignee * @param boolean $type The type of email this is * @param integer $sup_id the ID of this email * @return void */ public static function notifyNewEmail($usr_id, $issue_id, $message, $internal_only = false, $assignee_only = false, $type = '', $sup_id = false) { $prj_id = Issue::getProjectID($issue_id); $full_message = $message['full_email']; $sender = $message['from']; $sender_email = strtolower(Mail_Helper::getEmailAddress($sender)); // get ID of whoever is sending this. $sender_usr_id = User::getUserIDByEmail($sender_email, true); if (empty($sender_usr_id)) { $sender_usr_id = false; } // automatically subscribe this sender to email notifications on this issue $subscribed_emails = self::getSubscribedEmails($issue_id, 'emails'); $subscribed_emails = Misc::lowercase($subscribed_emails); if (!self::isIssueRoutingSender($issue_id, $sender) && !self::isBounceMessage($sender_email) && !in_array($sender_email, $subscribed_emails) && Workflow::shouldAutoAddToNotificationList($prj_id)) { $actions = array('emails'); self::subscribeEmail($usr_id, $issue_id, $sender_email, $actions); } // get the subscribers $emails = array(); $users = self::getUsersByIssue($issue_id, 'emails'); foreach ($users as $user) { if (empty($user['sub_usr_id'])) { if ($internal_only == false) { $email = $user['sub_email']; } } else { // 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($user['sub_usr_id'], Issue::getProjectID($issue_id)) < User::ROLE_USER) { continue; } // check if we are only supposed to send email to the assignees if ($internal_only == true && $assignee_only == true) { $assignee_usr_ids = Issue::getAssignedUserIDs($issue_id); if (!in_array($user['sub_usr_id'], $assignee_usr_ids)) { continue; } } $email = User::getFromHeader($user['sub_usr_id']); } if (empty($email)) { continue; } // don't send the email to the same person who sent it unless they want it if ($sender_usr_id != false) { $prefs = Prefs::get($sender_usr_id); if (!isset($prefs['receive_copy_of_own_action'][$prj_id])) { $prefs['receive_copy_of_own_action'][$prj_id] = 0; } if ($prefs['receive_copy_of_own_action'][$prj_id] == 0 && (!empty($user['sub_usr_id']) && $sender_usr_id == $user['sub_usr_id'] || strtolower(Mail_Helper::getEmailAddress($email)) == $sender_email)) { continue; } } $emails[] = $email; } if (!$emails) { return; } // change the sender of the message to {prefix}{issue_id}@{host} // - keep everything else in the message, except 'From:', 'Sender:', 'To:', 'Cc:' // make 'Joe Blow <*****@*****.**>' become 'Joe Blow [CSC] <*****@*****.**>' $from = self::getFixedFromHeader($issue_id, $sender, 'issue'); list($_headers, $body) = Mime_Helper::splitBodyHeader($full_message); $header_names = Mime_Helper::getHeaderNames($_headers); $current_headers = Mail_Helper::stripHeaders($message['headers']); $headers = array(); // build the headers array required by the smtp library foreach ($current_headers as $header_name => $value) { if ($header_name == 'from') { $headers['From'] = $from; } else { if (is_array($value)) { $value = implode('; ', $value); } $headers[$header_names[$header_name]] = $value; } } $headers['Subject'] = Mail_Helper::formatSubject($issue_id, $headers['Subject']); if (empty($type)) { if ($sender_usr_id != false && User::getRoleByUser($sender_usr_id, Issue::getProjectID($issue_id)) == User::ROLE_CUSTOMER) { $type = 'customer_email'; } else { $type = 'other_email'; } } $options = array('save_email_copy' => 1, 'issue_id' => $issue_id, 'type' => $type, 'sender_usr_id' => $sender_usr_id, 'type_id' => $sup_id); foreach ($emails as $to) { // add the warning message about replies being blocked or not // FIXME: $headers contains $headers['To'] from previous iteration $fixed_body = Mail_Helper::addWarningMessage($issue_id, $to, $body, $headers); $headers['To'] = Mime_Helper::encodeAddress($to); $mail = array('to' => $to, 'headers' => $headers, 'body' => $fixed_body); Mail_Queue::addMail($mail, $options); } }
/** * Method used to forward the new email to the list of subscribers. * * @access public * @param integer $user_id The user ID of the person performing this action * @param integer $issue_id The issue ID * @param array $message An array containing the email * @param boolean $internal_only Whether the email should only be redirected to internal users or not * @param boolean $assignee_only Whether the email should only be sent to the assignee * @param boolean $type The type of email this is * @param integer $sup_id the ID of this email * @return void */ function notifyNewEmail($usr_id, $issue_id, $message, $internal_only = FALSE, $assignee_only = FALSE, $type = '', $sup_id = false) { $full_message = $message['full_email']; $sender = $message['from']; $sender_email = strtolower(Mail_API::getEmailAddress($sender)); // get ID of whoever is sending this. $sender_usr_id = User::getUserIDByEmail($sender_email); if (empty($sender_usr_id)) { $sender_usr_id = false; } // automatically subscribe this sender to email notifications on this issue $subscribed_emails = Notification::getSubscribedEmails($issue_id, 'emails'); $subscribed_emails = array_map('strtolower', $subscribed_emails); if (!Notification::isIssueRoutingSender($issue_id, $sender) && !Notification::isBounceMessage($sender_email) && !in_array($sender_email, $subscribed_emails)) { $actions = array('emails'); Notification::subscribeEmail($usr_id, $issue_id, $sender_email, $actions); } // get the subscribers $emails = array(); $users = Notification::getUsersByIssue($issue_id, 'emails'); for ($i = 0; $i < count($users); $i++) { if (empty($users[$i]["sub_usr_id"])) { if ($internal_only == false) { $email = $users[$i]["sub_email"]; } } else { // 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; } // check if we are only supposed to send email to the assignees if ($internal_only == true && $assignee_only == true) { $assignee_usr_ids = Issue::getAssignedUserIDs($issue_id); if (!in_array($users[$i]["sub_usr_id"], $assignee_usr_ids)) { continue; } } $email = User::getFromHeader($users[$i]["sub_usr_id"]); } if (!empty($email)) { // don't send the email to the same person who sent it if (strtolower(Mail_API::getEmailAddress($email)) == $sender_email) { continue; } $emails[] = $email; } } if (count($emails) == 0) { return; } $setup = Setup::load(); // change the sender of the message to {prefix}{issue_id}@{host} // - keep everything else in the message, except 'From:', 'Sender:', 'To:', 'Cc:' // make 'Joe Blow <*****@*****.**>' become 'Joe Blow [CSC] <*****@*****.**>' $from = Notification::getFixedFromHeader($issue_id, $sender, 'issue'); list($_headers, $body) = Mime_Helper::splitBodyHeader($full_message); // strip any 'Received:' headers $_headers = Mail_API::stripHeaders($_headers); $header_names = Mime_Helper::getHeaderNames($_headers); // we don't want to keep the (B)Cc list for an eventum-based email $ignore_headers = array('to', 'cc', 'bcc'); $headers = array(); // build the headers array required by the smtp library foreach ($message['headers'] as $header_name => $value) { if (in_array(strtolower($header_name), $ignore_headers) || !in_array($header_name, array_keys($header_names)) || strstr($header_name, ' ')) { continue; } elseif ($header_name == 'from') { $headers['From'] = $from; } else { if (is_array($value)) { $value = implode("; ", $value); } $headers[$header_names[$header_name]] = $value; } } $headers["Subject"] = Mail_API::formatSubject($issue_id, $headers['Subject']); if (empty($type)) { if (User::getRoleByUser($usr_id, Issue::getProjectID($issue_id)) == User::getRoleID("Customer")) { $type = 'customer_email'; } else { $type = 'other_email'; } } @(include_once APP_PEAR_PATH . 'Mail/mime.php'); foreach ($emails as $to) { $recipient_usr_id = User::getUserIDByEmail(Mail_API::getEmailAddress($to)); $to = MIME_Helper::encodeAddress($to); // add the warning message about replies being blocked or not $fixed_body = Mail_API::addWarningMessage($issue_id, $to, $body); $headers['To'] = $to; $mime = new Mail_mime("\r\n"); $hdrs = $mime->headers($headers); Mail_Queue::add($to, $hdrs, $fixed_body, 1, $issue_id, $type, $sender_usr_id, $sup_id); } }