function testRecipients() { db_connect(new MockDbSource()); $email = <<<EOF Delivered-To: jared@osticket.com Received: by 10.60.55.168 with SMTP id t8csp161432oep; Fri, 7 Feb 2014 22:11:19 -0800 (PST) X-Received: by 10.182.18.9 with SMTP id s9mr16356699obd.15.1391839879167; Fri, 07 Feb 2014 22:11:19 -0800 (PST) Return-Path: <*****@*****.**> To: jared@osticket.com Subject: =?utf-8?Q?System_test_email_=C2=AE?= Content-Type: multipart/alternative; boundary="=_28022448a1f58a3af7edf57ff2e3af44" From: "Support" <*****@*****.**> Date: Sat, 08 Feb 2014 01:11:18 -0500 Message-ID: <*****@*****.**> MIME-Version: 1.0 --=_28022448a1f58a3af7edf57ff2e3af44 Content-Transfer-Encoding: base64 Content-Type: text/plain; charset=utf-8 Q2hlZXJzISE= --=_28022448a1f58a3af7edf57ff2e3af44 Content-Transfer-Encoding: base64 Content-Type: text/html; charset=utf-8 Q2hlZXJzISE= --=_28022448a1f58a3af7edf57ff2e3af44-- EOF; $result = EmailDataParser::parse($email); $this->assert(count($result['recipients']) == 1, 'Expected 1 recipient'); $this->assert($result['recipients'][0]['source'] == 'delivered-to', 'Delivered-To header used as a collaborator'); }
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; }
function parse($stream) { return $this->fixup(parent::parse($stream)); }