function processEmail() { $data = $this->getEmailRequest(); if ($data['ticketId'] && ($ticket = Ticket::lookup($data['ticketId']))) { if ($msgid = $ticket->postMessage($data, 'Email')) { return $ticket; } } if (($thread = ThreadEntry::lookupByEmailHeaders($data)) && $thread->postEmail($data)) { return $thread->getTicket(); } return $this->createTicket($data); }
function createTicket($mid) { global $ost; if (!($mailinfo = $this->getHeaderInfo($mid))) { return false; } // TODO: If the content-type of the message is 'message/rfc822', // then this is a message with the forwarded message as the // attachment. Download the body and pass it along to the mail // parsing engine. $info = Mail_Parse::splitHeaders($mailinfo['header']); if (strtolower($info['Content-Type']) == 'message/rfc822') { if ($wrapped = $this->getPart($mid, 'message/rfc822')) { require_once INCLUDE_DIR . 'api.tickets.php'; // Simulate piping the contents into the system $api = new TicketApiController(); $parser = new EmailDataParser(); if ($data = $parser->parse($wrapped)) { return $api->processEmail($data); } } // If any of this fails, create the ticket as usual } //Is the email address banned? if ($mailinfo['email'] && TicketFilter::isBanned($mailinfo['email'])) { //We need to let admin know... $ost->logWarning(_S('Ticket denied'), sprintf(_S('Banned email — %s'), $mailinfo['email']), false); return true; //Report success (moved or delete) } // Parse MS TNEF emails if (($struct = imap_fetchstructure($this->mbox, $mid)) && ($attachments = $this->getAttachments($struct))) { foreach ($attachments as $i => $info) { if (0 === strcasecmp('application/ms-tnef', $info['type'])) { try { $data = $this->decode(imap_fetchbody($this->mbox, $mid, $info['index']), $info['encoding']); $tnef = new TnefStreamParser($data); $this->tnef = $tnef->getMessage(); // No longer considered an attachment unset($attachments[$i]); // There should only be one of these break; } catch (TnefException $ex) { // Noop -- winmail.dat remains an attachment } } } } $vars = $mailinfo; $vars['name'] = $mailinfo['name']; $vars['subject'] = $mailinfo['subject'] ?: '[No Subject]'; $vars['emailId'] = $mailinfo['emailId'] ?: $this->getEmailId(); $vars['to-email-id'] = $mailinfo['emailId'] ?: 0; $vars['flags'] = new ArrayObject(); if ($this->isBounceNotice($mid)) { // Fetch the original References and assign to 'references' if ($headers = $this->getOriginalMessageHeaders($mid)) { $vars['references'] = $headers['references']; $vars['in-reply-to'] = @$headers['in-reply-to'] ?: null; } // Fetch deliver status report $vars['message'] = $this->getDeliveryStatusMessage($mid) ?: $this->getBody($mid); $vars['thread-type'] = 'N'; $vars['flags']['bounce'] = true; } else { $vars['message'] = $this->getBody($mid); $vars['flags']['bounce'] = TicketFilter::isBounce($info); } //Missing FROM name - use email address. if (!$vars['name']) { list($vars['name']) = explode('@', $vars['email']); } if ($ost->getConfig()->useEmailPriority()) { $vars['priorityId'] = $this->getPriority($mid); } $ticket = null; $newticket = true; $errors = array(); $seen = false; // Use the settings on the thread entry on the ticket details // form to validate the attachments in the email $tform = TicketForm::objects()->one()->getForm(); $messageField = $tform->getField('message'); $fileField = $messageField->getWidget()->getAttachments(); // Fetch attachments if any. if ($messageField->isAttachmentsEnabled()) { // Include TNEF attachments in the attachments list if ($this->tnef) { foreach ($this->tnef->attachments as $at) { $attachments[] = array('cid' => @$at->AttachContentId ?: false, 'data' => $at, 'size' => @$at->DataSize ?: null, 'type' => @$at->AttachMimeTag ?: false, 'name' => $at->getName()); } } $vars['attachments'] = array(); foreach ($attachments as $a) { $file = array('name' => $a['name'], 'type' => $a['type']); if (@$a['data'] instanceof TnefAttachment) { $file['data'] = $a['data']->getData(); } else { // only fetch the body if necessary $self = $this; $file['data'] = function () use($self, $mid, $a) { return $self->decode(imap_fetchbody($self->mbox, $mid, $a['index']), $a['encoding']); }; } // Include the Content-Id if specified (for inline images) $file['cid'] = isset($a['cid']) ? $a['cid'] : false; // Validate and save immediately try { $file['id'] = $fileField->uploadAttachment($file); } catch (FileUploadError $ex) { $file['error'] = $file['name'] . ': ' . $ex->getMessage(); } $vars['attachments'][] = $file; } } // Allow signal handlers to interact with the message decoding Signal::send('mail.processed', $this, $vars); $seen = false; if (($thread = ThreadEntry::lookupByEmailHeaders($vars, $seen)) && ($t = $thread->getTicket()) && ($vars['staffId'] || !$t->isClosed() || $t->isReopenable()) && ($message = $thread->postEmail($vars))) { if (!$message instanceof ThreadEntry) { // Email has been processed previously return $message; } $ticket = $message->getTicket(); } elseif ($seen) { // Already processed, but for some reason (like rejection), no // thread item was created. Ignore the email return true; } elseif ($ticket = Ticket::create($vars, $errors, 'Email')) { $message = $ticket->getLastMessage(); } else { //Report success if the email was absolutely rejected. if (isset($errors['errno']) && $errors['errno'] == 403) { // Never process this email again! ThreadEntry::logEmailHeaders(0, $vars['mid']); return true; } // Log an error to the system logs $mailbox = Email::lookup($vars['emailId']); $ost->logError(_S('Mail Processing Exception'), sprintf(_S("Mailbox: %s | Error(s): %s"), $mailbox->getEmail(), print_r($errors, true)), false); // Indicate failure of mail processing return null; } return $ticket; }
<?php $threadContent = ""; if(isset($_REQUEST['thread_id'])&&is_numeric($_REQUEST['thread_id'])) { $thread = ThreadEntry::lookup($_REQUEST['thread_id']); $threadContent = $thread->getMessage(); } ?> <form method="POST" action="/scp/modifyThread.php"> <?php csrf_token(); ?> <input type="hidden" name="ticket_id" value="<?php echo $_REQUEST['ticket_id'];?>"> <input type="hidden" name="thread_id" value="<?php echo $_REQUEST['thread_id'];?>"> <label><b>Original Content:</b></label><br><hr> <?php echo $threadContent; ?><br><hr> <label><b>Input the new content:</b></label> <textarea name="thread_content" style="width:100%;height:150px;"></textarea> <div id="reply_form_attachments" class="attachments"> <?php print $response_form->getField('attachments')->render(); ?> <input type='submit' value="Save"> </form>
function processEmail($data = false) { if (!$data) { $data = $this->getEmailRequest(); } if (($thread = ThreadEntry::lookupByEmailHeaders($data)) && ($t = $thread->getTicket()) && ($data['staffId'] || !$t->isClosed() || $t->isReopenable()) && $thread->postEmail($data)) { return $thread->getTicket(); } return $this->createTicket($data); }
function add($vars, &$errors) { //Check required params. if (!$vars || !is_array($vars) || !$vars['ticketId']) { $errors['err'] = __('Missing or invalid data'); } elseif (!$vars['note']) { $errors['note'] = __('Note content is required'); } if ($errors) { return false; } //TODO: use array_intersect_key when we move to php 5 to extract just what we need. $vars['type'] = 'N'; $vars['body'] = $vars['note']; return ThreadEntry::add($vars); }
function postReply($vars, &$errors, $alert = true, $claim = true) { global $thisstaff, $cfg; if (!$vars['poster'] && $thisstaff) { $vars['poster'] = $thisstaff; } if (!$vars['staffId'] && $thisstaff) { $vars['staffId'] = $thisstaff->getId(); } if (!$vars['ip_address'] && $_SERVER['REMOTE_ADDR']) { $vars['ip_address'] = $_SERVER['REMOTE_ADDR']; } $attachments = array(); $response = null; if ($vars['emailreply'] == 2 || $vars['emailreply'] == 1) { $responseBody = null; $finalBody = null; $threadIdList = array(); if (isset($vars['thread_list'])) { $threadIdList = explode(",", $vars['thread_list']); } // $this->logErrors($vars['thread_list']); // $this->logErrors(json_encode($threadIdList)); // if(!($clientThreadEntries = $this->getClientThread())) // return null; // foreach ($clientThreadEntries as $clientThreadEntry) { // if(!($response = ThreadEntry::lookup($clientThreadEntry['id']))) // return null; if ($response = $this->getThread()->addResponse($vars, $errors)) { // $responseBody = $responseBody ."<br>--------------Reply from ".$response->getPoster()."--------------<br>"; $responseBody = $responseBody . $response->ht['body']; if (isset($thisstaff) && $thisstaff->getSignature() && $vars['emailreply'] == 2 && sizeof($threadIdList) > 1) { $responseBody = $responseBody . $thisstaff->getSignature(); } // if($vars['emailreply']==1) $finalThreadBody = $response->ht['body']; $attachments = array_merge($attachments, $response->getAttachments()); } foreach ($threadIdList as $threadId) { if ($threadId != "") { $response = ThreadEntry::lookup(intval($threadId)); // return null; if ($response->getType() == 'M') { $responseBody = $responseBody . "<br>--------------Message from " . $response->getPoster() . "--------------<br>"; if ($response->getUserId() != 0) { if ($user = $response->getUser()) { $responseBody = $responseBody . "<b>Name:</b> " . $user->getFullName() . "<br>"; $responseBody = $responseBody . "<b>Email:</b> " . $user->getEmail() . "<br>"; if ($user->getPhoneNumber() != "") { $responseBody = $responseBody . "<b>Phone number:</b> " . $user->getPhoneNumber() . "<br>"; } } } } else { $responseBody = $responseBody . "<br>--------------Reply from " . $response->getPoster() . "--------------<br>"; if ($response->getStaffId() != 0) { if ($currentThreadStaff = $response->getStaff()) { $responseBody = $responseBody . "<b>Name:</b> " . $currentThreadStaff->getName() . "<br>"; $responseBody = $responseBody . "<b>Email:</b> " . $currentThreadStaff->getEmail() . "<br>"; // if($currentThreadStaff->getPhoneNumber() != "") // $responseBody = $responseBody ."<b>Phone number:</b> ".$currentThreadStaff->getPhoneNumber()."<br>"; } } } $responseBody = $responseBody . $response->ht['body']; $responseBody = $responseBody . "<br><br>"; $finalThreadBody = $response->ht['body']; $attachments = array_merge($attachments, $response->getAttachments()); } } $response->setBody(ThreadBody::fromFormattedText($responseBody, $response->ht['format'])); $response->reload(); if (!$this->postReplyFromThread($vars, $errors, $alert = true, $claim = true, $response, $attachments)) { return null; } $response->setBody(ThreadBody::fromFormattedText($finalThreadBody, $response->ht['format'])); $response->reload(); } else { if (!($response = $this->getThread()->addResponse($vars, $errors))) { return null; } if (!$this->postReplyFromThread($vars, $errors, $alert = true, $claim = true, $response, $attachments)) { return null; } } return $response; }
<?php require('staff.inc.php'); require_once(INCLUDE_DIR.'class.attachment.php'); require_once(INCLUDE_DIR.'class.thread.php'); error_reporting(~0); ini_set('display_errors', 1); echo "1111"; if(!isset($_REQUEST['thread_id'])) { echo ("Thread ID not provided"); } elseif(is_numeric($_REQUEST['thread_id'])&&($thread = ThreadEntry::lookup($_REQUEST['thread_id']))) { foreach ($_REQUEST['attach:response'] as $fileID) { $thread->saveAttachment($fileID); } header("Location: /scp/tickets.php?id=".$_REQUEST['ticket_id']); } if($_REQUEST['thread_content']!=null&&$_REQUEST['thread_content']!=""&&$thread->setBody(nl2br($_REQUEST['thread_content']))) { $thread->reload(); header("Location: /scp/tickets.php?id=".$_REQUEST['ticket_id']); } ?>
function processEmail($data = false) { if (!$data) { $data = $this->getEmailRequest(); } if (($thread = ThreadEntry::lookupByEmailHeaders($data)) && $thread->postEmail($data)) { return $thread->getTicket(); } return $this->createTicket($data); }
function createTicket($mid) { global $ost; if (!($mailinfo = $this->getHeaderInfo($mid))) { return false; } //Is the email address banned? if ($mailinfo['email'] && TicketFilter::isBanned($mailinfo['email'])) { //We need to let admin know... $ost->logWarning('Ticket denied', 'Banned email - ' . $mailinfo['email'], false); return true; //Report success (moved or delete) } $vars = $mailinfo; $vars['name'] = $this->mime_decode($mailinfo['name']); $vars['subject'] = $mailinfo['subject'] ? $this->mime_decode($mailinfo['subject']) : '[No Subject]'; $vars['message'] = Format::stripEmptyLines($this->getBody($mid)); $vars['emailId'] = $mailinfo['emailId'] ? $mailinfo['emailId'] : $this->getEmailId(); //Missing FROM name - use email address. if (!$vars['name']) { $vars['name'] = $vars['email']; } //An email with just attachments can have empty body. if (!$vars['message']) { $vars['message'] = '-'; } if ($ost->getConfig()->useEmailPriority()) { $vars['priorityId'] = $this->getPriority($mid); } $ticket = null; $newticket = true; $errors = array(); $seen = false; if (($thread = ThreadEntry::lookupByEmailHeaders($vars, $seen)) && ($message = $thread->postEmail($vars))) { if (!$message instanceof ThreadEntry) { // Email has been processed previously return $message; } $ticket = $message->getTicket(); } elseif ($seen) { // Already processed, but for some reason (like rejection), no // thread item was created. Ignore the email return true; } elseif ($ticket = Ticket::create($vars, $errors, 'Email')) { $message = $ticket->getLastMessage(); } else { //Report success if the email was absolutely rejected. if (isset($errors['errno']) && $errors['errno'] == 403) { // Never process this email again! ThreadEntry::logEmailHeaders(0, $vars['mid']); return true; } # check if it's a bounce! if ($vars['header'] && TicketFilter::isAutoBounce($vars['header'])) { $ost->logWarning('Bounced email', $vars['message'], false); return true; } //TODO: Log error.. return null; } //Save attachments if any. if ($message && $ost->getConfig()->allowEmailAttachments() && ($struct = imap_fetchstructure($this->mbox, $mid)) && ($attachments = $this->getAttachments($struct))) { foreach ($attachments as $a) { $file = array('name' => $a['name'], 'type' => $a['type']); //Check the file type if (!$ost->isFileTypeAllowed($file)) { $file['error'] = 'Invalid file type (ext) for ' . Format::htmlchars($file['name']); } else { //only fetch the body if necessary TODO: Make it a callback. $file['data'] = $this->decode(imap_fetchbody($this->mbox, $mid, $a['index']), $a['encoding']); } $message->importAttachment($file); } } return $ticket; }