function export($value) { return !$value ? $value : Format::html2text($value); }
function getBody($mid) { global $cfg; if ($cfg->isHtmlThreadEnabled()) { if ($html = $this->getPart($mid, 'text/html', $this->charset)) { $body = new HtmlThreadBody($html); } elseif ($text = $this->getPart($mid, 'text/plain', $this->charset)) { $body = new TextThreadBody($text); } } elseif ($text = $this->getPart($mid, 'text/plain', $this->charset)) { $body = new TextThreadBody($text); } elseif ($html = $this->getPart($mid, 'text/html', $this->charset)) { $body = new TextThreadBody(Format::html2text(Format::safe_html($html), 100, false)); } if (!isset($body)) { $body = new TextThreadBody(''); } if ($cfg->stripQuotedReply()) { $body->stripQuotedReply($cfg->getReplySeparator()); } return $body; }
function cannedResponse($tid, $cid, $format = 'text') { global $thisstaff, $cfg; if (!($ticket = Ticket::lookup($tid)) || !$ticket->checkStaffAccess($thisstaff)) { Http::response(404, 'Unknown ticket ID'); } if ($cid && !is_numeric($cid)) { if (!($response = $ticket->getThread()->getVar($cid))) { Http::response(422, 'Unknown ticket variable'); } // Ticket thread variables are assumed to be quotes $response = "<br/><blockquote>{$response}</blockquote><br/>"; // Return text if html thread is not enabled if (!$cfg->isHtmlThreadEnabled()) { $response = Format::html2text($response, 90); } // XXX: assuming json format for now. return Format::json_encode(array('response' => $response)); } if (!$cfg->isHtmlThreadEnabled()) { $format .= '.plain'; } $varReplacer = function (&$var) use($ticket) { return $ticket->replaceVars($var); }; include_once INCLUDE_DIR . 'class.canned.php'; if (!$cid || !($canned = Canned::lookup($cid)) || !$canned->isEnabled()) { Http::response(404, 'No such premade reply'); } return $canned->getFormattedResponse($format, $varReplacer); }
function send($to, $subject, $message, $options = null) { global $ost, $cfg; //Get the goodies require_once PEAR_DIR . 'Mail.php'; // PEAR Mail package require_once PEAR_DIR . 'Mail/mime.php'; // PEAR Mail_Mime packge //do some cleanup $to = preg_replace("/(\r\n|\r|\n)/s", '', trim($to)); $subject = preg_replace("/(\r\n|\r|\n)/s", '', trim($subject)); /* Message ID - generated for each outgoing email */ $messageId = sprintf('<%s-%s-%s>', substr(md5('mail' . SECRET_SALT), -9), Misc::randCode(9), $this->getEmail() ? $this->getEmail()->getEmail() : '@osTicketMailer'); $headers = array('From' => $this->getFromAddress(), 'To' => $to, 'Subject' => $subject, 'Date' => date('D, d M Y H:i:s O'), 'Message-ID' => $messageId, 'X-Mailer' => 'osTicket Mailer'); // Add in the options passed to the constructor $options = ($options ?: array()) + $this->options; if (isset($options['nobounce']) && $options['nobounce']) { $headers['Return-Path'] = '<>'; } elseif ($this->getEmail() instanceof Email) { $headers['Return-Path'] = $this->getEmail()->getEmail(); } //Bulk. if (isset($options['bulk']) && $options['bulk']) { $headers += array('Precedence' => 'bulk'); } //Auto-reply - mark as autoreply and supress all auto-replies if (isset($options['autoreply']) && $options['autoreply']) { $headers += array('Precedence' => 'auto_reply', 'X-Autoreply' => 'yes', 'X-Auto-Response-Suppress' => 'DR, RN, OOF, AutoReply', 'Auto-Submitted' => 'auto-replied'); } //Notice (sort of automated - but we don't want auto-replies back if (isset($options['notice']) && $options['notice']) { $headers += array('X-Auto-Response-Suppress' => 'OOF, AutoReply', 'Auto-Submitted' => 'auto-generated'); } if ($options) { if (isset($options['inreplyto']) && $options['inreplyto']) { $headers += array('In-Reply-To' => $options['inreplyto']); } if (isset($options['references']) && $options['references']) { if (is_array($options['references'])) { $headers += array('References' => implode(' ', $options['references'])); } else { $headers += array('References' => $options['references']); } } } // The Suhosin patch will muck up the line endings in some // cases // // References: // https://github.com/osTicket/osTicket-1.8/issues/202 // http://pear.php.net/bugs/bug.php?id=12032 // http://us2.php.net/manual/en/function.mail.php#97680 if ((extension_loaded('suhosin') || defined("SUHOSIN_PATCH")) && !$this->getSMTPInfo()) { $mime = new Mail_mime("\n"); } else { // Use defaults $mime = new Mail_mime(); } // If the message is not explicitly declared to be a text message, // then assume that it needs html processing to create a valid text // body $isHtml = true; $mid_token = isset($options['thread']) ? $options['thread']->asMessageId($to) : ''; if (!(isset($options['text']) && $options['text'])) { if ($cfg && $cfg->stripQuotedReply() && ($tag = $cfg->getReplySeparator()) && (!isset($options['reply-tag']) || $options['reply-tag'])) { $message = "<div style=\"display:none\"\n data-mid=\"{$mid_token}\">{$tag}<br/><br/></div>{$message}"; } $txtbody = rtrim(Format::html2text($message, 90, false)) . ($mid_token ? "\nRef-Mid: {$mid_token}\n" : ''); $mime->setTXTBody($txtbody); } else { $mime->setTXTBody($message); $isHtml = false; } if ($isHtml && $cfg && $cfg->isHtmlThreadEnabled()) { // Pick a domain compatible with pear Mail_Mime $matches = array(); if (preg_match('#(@[0-9a-zA-Z\\-\\.]+)#', $this->getFromAddress(), $matches)) { $domain = $matches[1]; } else { $domain = '@localhost'; } // Format content-ids with the domain, and add the inline images // to the email attachment list $self = $this; $message = preg_replace_callback('/cid:([\\w.-]{32})/', function ($match) use($domain, $mime, $self) { if (!($file = AttachmentFile::lookup($match[1]))) { return $match[0]; } $mime->addHTMLImage($file->getData(), $file->getType(), $file->getName(), false, $match[1] . $domain); // Don't re-attach the image below unset($self->attachments[$file->getId()]); return $match[0] . $domain; }, $message); // Add an HTML body $mime->setHTMLBody($message); } //XXX: Attachments if ($attachments = $this->getAttachments()) { foreach ($attachments as $attachment) { if ($attachment['file_id'] && ($file = AttachmentFile::lookup($attachment['file_id']))) { $mime->addAttachment($file->getData(), $file->getType(), $file->getName(), false); } } } //Desired encodings... $encodings = array('head_encoding' => 'quoted-printable', 'text_encoding' => 'base64', 'html_encoding' => 'base64', 'html_charset' => 'utf-8', 'text_charset' => 'utf-8', 'head_charset' => 'utf-8'); //encode the body $body = $mime->get($encodings); //encode the headers. $headers = $mime->headers($headers, true); // Cache smtp connections made during this request static $smtp_connections = array(); if ($smtp = $this->getSMTPInfo()) { //Send via SMTP $key = sprintf("%s:%s:%s", $smtp['host'], $smtp['port'], $smtp['username']); if (!isset($smtp_connections[$key])) { $mail = mail::factory('smtp', array('host' => $smtp['host'], 'port' => $smtp['port'], 'auth' => $smtp['auth'], 'username' => $smtp['username'], 'password' => $smtp['password'], 'timeout' => 20, 'debug' => false, 'persist' => true)); if ($mail->connect()) { $smtp_connections[$key] = $mail; } } else { // Use persistent connection $mail = $smtp_connections[$key]; } $result = $mail->send($to, $headers, $body); if (!PEAR::isError($result)) { return $messageId; } // Force reconnect on next ->send() unset($smtp_connections[$key]); $alert = sprintf("Unable to email via SMTP:%s:%d [%s]\n\n%s\n", $smtp['host'], $smtp['port'], $smtp['username'], $result->getMessage()); $this->logError($alert); } //No SMTP or it failed....use php's native mail function. $mail = mail::factory('mail'); return PEAR::isError($mail->send($to, $headers, $body)) ? false : $messageId; }
function getFormattedResponse($format = 'text', $cb = null) { $resp = array(); $html = true; switch ($format) { case 'json.plain': $html = false; // fall-through // fall-through case 'json': $resp['id'] = $this->getId(); $resp['title'] = $this->getTitle(); $resp['response'] = $this->getResponseWithImages(); // Callback to strip or replace variables! if ($cb && is_callable($cb)) { $resp = $cb($resp); } $resp['files'] = $this->attachments->getSeparates(); // strip html if (!$html) { $resp['response'] = Format::html2text($resp['response'], 90); $resp['files'] += $this->attachments->getInlines(); } return Format::json_encode($resp); break; case 'html': case 'text.html': $response = $this->getResponseWithImages(); break; case 'text.plain': $html = false; case 'text': default: $response = $this->getResponse(); if (!$html) { $response = Format::html2text($response, 90); } break; } // Callback to strip or replace variables! if ($response && $cb && is_callable($cb)) { $response = $cb($response); } return $response; }
function convertTo($type) { if ($type === $this->type) { return $this; } $conv = $this->type . ':' . strtolower($type); switch ($conv) { case 'text:html': return new ThreadBody(sprintf('<pre>%s</pre>', Format::htmlchars($this->body)), $type); case 'html:text': return new ThreadBody(Format::html2text((string) $this), $type); } }
function send($to, $subject, $message, $options = null) { global $ost, $cfg; //Get the goodies require_once PEAR_DIR . 'Mail.php'; // PEAR Mail package require_once PEAR_DIR . 'Mail/mime.php'; // PEAR Mail_Mime packge $messageId = $this->getMessageId($to, $options); if (is_object($to) && is_callable(array($to, 'getEmail'))) { // Add personal name if available if (is_callable(array($to, 'getName'))) { $to = sprintf('"%s" <%s>', $to->getName()->getOriginal(), $to->getEmail()); } else { $to = $to->getEmail(); } } //do some cleanup $to = preg_replace("/(\r\n|\r|\n)/s", '', trim($to)); $subject = preg_replace("/(\r\n|\r|\n)/s", '', trim($subject)); $headers = array('From' => $this->getFromAddress(), 'To' => $to, 'Subject' => $subject, 'Date' => date('D, d M Y H:i:s O'), 'Message-ID' => $messageId, 'X-Mailer' => 'osTicket Mailer'); // Add in the options passed to the constructor $options = ($options ?: array()) + $this->options; if (isset($options['nobounce']) && $options['nobounce']) { $headers['Return-Path'] = '<>'; } elseif ($this->getEmail() instanceof Email) { $headers['Return-Path'] = $this->getEmail()->getEmail(); } //Bulk. if (isset($options['bulk']) && $options['bulk']) { $headers += array('Precedence' => 'bulk'); } //Auto-reply - mark as autoreply and supress all auto-replies if (isset($options['autoreply']) && $options['autoreply']) { $headers += array('Precedence' => 'auto_reply', 'X-Autoreply' => 'yes', 'X-Auto-Response-Suppress' => 'DR, RN, OOF, AutoReply', 'Auto-Submitted' => 'auto-replied'); } //Notice (sort of automated - but we don't want auto-replies back if (isset($options['notice']) && $options['notice']) { $headers += array('X-Auto-Response-Suppress' => 'OOF, AutoReply', 'Auto-Submitted' => 'auto-generated'); } if ($options) { if (isset($options['inreplyto']) && $options['inreplyto']) { $headers += array('In-Reply-To' => $options['inreplyto']); } if (isset($options['references']) && $options['references']) { if (is_array($options['references'])) { $headers += array('References' => implode(' ', $options['references'])); } else { $headers += array('References' => $options['references']); } } } // Make the best effort to add In-Reply-To and References headers $reply_tag = $mid_token = ''; if (isset($options['thread']) && $options['thread'] instanceof ThreadEntry) { if ($irt = $options['thread']->getEmailMessageId()) { // This is an response from an email, like and autoresponse. // Web posts will not have a email message-id $headers += array('In-Reply-To' => $irt, 'References' => $options['thread']->getEmailReferences()); } elseif ($parent = $options['thread']->getParent()) { // Use the parent item as the email information source. This // will apply for staff replies $headers += array('In-Reply-To' => $parent->getEmailMessageId(), 'References' => $parent->getEmailReferences()); } // Configure the reply tag and embedded message id token $mid_token = $options['thread']->asMessageId($to); if ($cfg && $cfg->stripQuotedReply() && (!isset($options['reply-tag']) || $options['reply-tag'])) { $reply_tag = $cfg->getReplySeparator() . '<br/><br/>'; } } // Use general failsafe default initially $eol = "\n"; // MAIL_EOL setting can be defined in `ost-config.php` if (defined('MAIL_EOL') && is_string(MAIL_EOL)) { $eol = MAIL_EOL; } $mime = new Mail_mime($eol); // If the message is not explicitly declared to be a text message, // then assume that it needs html processing to create a valid text // body $isHtml = true; if (!(isset($options['text']) && $options['text'])) { if ($reply_tag || $mid_token) { $message = "<div style=\"display:none\"\n class=\"mid-{$mid_token}\">{$reply_tag}</div>{$message}"; } $txtbody = rtrim(Format::html2text($message, 90, false)) . ($mid_token ? "\nRef-Mid: {$mid_token}\n" : ''); $mime->setTXTBody($txtbody); } else { $mime->setTXTBody($message); $isHtml = false; } if ($isHtml && $cfg && $cfg->isHtmlThreadEnabled()) { // Pick a domain compatible with pear Mail_Mime $matches = array(); if (preg_match('#(@[0-9a-zA-Z\\-\\.]+)#', $this->getFromAddress(), $matches)) { $domain = $matches[1]; } else { $domain = '@localhost'; } // Format content-ids with the domain, and add the inline images // to the email attachment list $self = $this; $message = preg_replace_callback('/cid:([\\w.-]{32})/', function ($match) use($domain, $mime, $self) { if (!($file = AttachmentFile::lookup($match[1]))) { return $match[0]; } $mime->addHTMLImage($file->getData(), $file->getType(), $file->getName(), false, $match[1] . $domain); // Don't re-attach the image below unset($self->attachments[$file->getId()]); return $match[0] . $domain; }, $message); // Add an HTML body $mime->setHTMLBody($message); } //XXX: Attachments if ($attachments = $this->getAttachments()) { foreach ($attachments as $attachment) { if ($attachment['file_id'] && ($file = AttachmentFile::lookup($attachment['file_id']))) { $mime->addAttachment($file->getData(), $file->getType(), $file->getName(), false); } } } //Desired encodings... $encodings = array('head_encoding' => 'quoted-printable', 'text_encoding' => 'base64', 'html_encoding' => 'base64', 'html_charset' => 'utf-8', 'text_charset' => 'utf-8', 'head_charset' => 'utf-8'); //encode the body $body = $mime->get($encodings); //encode the headers. $headers = $mime->headers($headers, true); // Cache smtp connections made during this request static $smtp_connections = array(); if ($smtp = $this->getSMTPInfo()) { //Send via SMTP $key = sprintf("%s:%s:%s", $smtp['host'], $smtp['port'], $smtp['username']); if (!isset($smtp_connections[$key])) { $mail = mail::factory('smtp', array('host' => $smtp['host'], 'port' => $smtp['port'], 'auth' => $smtp['auth'], 'username' => $smtp['username'], 'password' => $smtp['password'], 'timeout' => 20, 'debug' => false, 'persist' => true)); if ($mail->connect()) { $smtp_connections[$key] = $mail; } } else { // Use persistent connection $mail = $smtp_connections[$key]; } $result = $mail->send($to, $headers, $body); if (!PEAR::isError($result)) { return $messageId; } // Force reconnect on next ->send() unset($smtp_connections[$key]); $alert = sprintf(__("Unable to email via SMTP:%1\$s:%2\$d [%3\$s]\n\n%4\$s\n"), $smtp['host'], $smtp['port'], $smtp['username'], $result->getMessage()); $this->logError($alert); } //No SMTP or it failed....use php's native mail function. $mail = mail::factory('mail'); return PEAR::isError($mail->send($to, $headers, $body)) ? false : $messageId; }