function getOriginalMessageHeaders($mid) { if (!($body = $this->getPart($mid, 'message/rfc822'))) { // Handle rfc1892 style bounces if (!($body = $this->getPart($mid, 'text/rfc822-headers'))) { return null; } else { // Add a junk body for the parser $body .= "\n\nIgnored"; } } $msg = new Mail_Parse($body); if (!$msg->decode()) { return null; } return $msg->struct->headers; }
function parse($stream) { global $cfg; $contents = ''; if (is_resource($stream)) { while (!feof($stream)) { $contents .= fread($stream, 8192); } } else { $contents = $stream; } $parser = new Mail_Parse($contents); if (!$parser->decode()) { //Decode...returns false on decoding errors return $this->err('Email parse failed [' . $parser->getError() . ']'); } $data = array(); $data['emailId'] = 0; $data['recipients'] = array(); $data['subject'] = $parser->getSubject(); $data['header'] = $parser->getHeader(); $data['mid'] = $parser->getMessageId(); $data['priorityId'] = $parser->getPriority(); $data['flags'] = new ArrayObject(); //FROM address: who sent the email. if ($fromlist = $parser->getFromAddressList()) { $from = $fromlist[0]; //Default. foreach ($fromlist as $fromobj) { if (!Validator::is_email($fromobj->mailbox . '@' . $fromobj->host)) { continue; } $from = $fromobj; break; } $data['email'] = $from->mailbox . '@' . $from->host; $data['name'] = trim($from->personal, '"'); if ($from->comment && $from->comment[0]) { $data['name'] .= ' (' . $from->comment[0] . ')'; } //Use email address as name when FROM address doesn't have a name. if (!$data['name'] && $data['email']) { $data['name'] = $data['email']; } } /* Scan through the list of addressees (via To, Cc, and Delivered-To headers), and identify * how the mail arrived at the system. One of the mails should be in the system email list. * The recipient list (without the Delivered-To addressees) will be made available to the * ticket filtering system. However, addresses in the Delivered-To header should never be * considered for the collaborator list. */ $tolist = array(); if ($to = $parser->getToAddressList()) { $tolist['to'] = $to; } if ($cc = $parser->getCcAddressList()) { $tolist['cc'] = $cc; } if ($dt = $parser->getDeliveredToAddressList()) { $tolist['delivered-to'] = $dt; } foreach ($tolist as $source => $list) { foreach ($list as $addr) { if (!($emailId = Email::getIdByEmail(strtolower($addr->mailbox) . '@' . $addr->host))) { //Skip virtual Delivered-To addresses if ($source == 'delivered-to') { continue; } $data['recipients'][] = array('source' => sprintf(_S("Email (%s)"), $source), 'name' => trim(@$addr->personal, '"'), 'email' => strtolower($addr->mailbox) . '@' . $addr->host); } elseif (!$data['emailId']) { $data['emailId'] = $emailId; } } } /* * In the event that the mail was delivered to the system although none of the system * mail addresses are in the addressee lists, be careful not to include the addressee * in the collaborator list. Therefore, the delivered-to addressees should be flagged so they * are not added to the collaborator list in the ticket creation process. */ if ($tolist['delivered-to']) { foreach ($tolist['delivered-to'] as $addr) { foreach ($data['recipients'] as $i => $r) { if (strcasecmp($r['email'], $addr->mailbox . '@' . $addr->host) === 0) { $data['recipients'][$i]['source'] = 'delivered-to'; } } } } //maybe we got BCC'ed?? if (!$data['emailId']) { $emailId = 0; if ($bcc = $parser->getBccAddressList()) { foreach ($bcc as $addr) { if ($emailId = Email::getIdByEmail($addr->mailbox . '@' . $addr->host)) { break; } } } $data['emailId'] = $emailId; } if ($parser->isBounceNotice()) { // Fetch the original References and assign to 'references' if ($headers = $parser->getOriginalMessageHeaders()) { $data['references'] = $headers['references']; $data['in-reply-to'] = @$headers['in-reply-to'] ?: null; } // Fetch deliver status report $data['message'] = $parser->getDeliveryStatusMessage() ?: $parser->getBody(); $data['thread-type'] = 'N'; $data['flags']['bounce'] = true; } else { // Typical email $data['message'] = $parser->getBody(); $data['in-reply-to'] = @$parser->struct->headers['in-reply-to']; $data['references'] = @$parser->struct->headers['references']; $data['flags']['bounce'] = TicketFilter::isBounce($data['header']); } $data['to-email-id'] = $data['emailId']; if ($replyto = $parser->getReplyTo()) { $replyto = $replyto[0]; $data['reply-to'] = $replyto->mailbox . '@' . $replyto->host; if ($replyto->personal) { $data['reply-to-name'] = trim($replyto->personal, " \t\n\r\v\""); } } $data['attachments'] = $parser->getAttachments(); return $data; }
//The concern here is having enough mem for emails with attachments. require 'api.inc.php'; require_once INCLUDE_DIR . 'class.mailparse.php'; require_once INCLUDE_DIR . 'class.email.php'; //Make sure piping is enabled! if (!$cfg->isEmailPipingEnabled()) { api_exit(EX_UNAVAILABLE, 'Email piping not enabled - check MTA settings.'); } //Get the input $data = isset($_SERVER['HTTP_HOST']) ? file_get_contents('php://input') : file_get_contents('php://stdin'); if (empty($data)) { api_exit(EX_NOINPUT, 'No data'); } //Parse the email. $parser = new Mail_Parse($data); if (!$parser->decode()) { //Decode...returns false on decoding errors api_exit(EX_DATAERR, 'Email parse failed [' . $parser->getError() . "]\n\n" . $data); } //Check from address. make sure it is not a banned address. $fromlist = $parser->getFromAddressList(); //Check for parsing errors on FROM address. if (!$fromlist || PEAR::isError($fromlist)) { api_exit(EX_DATAERR, 'Invalid FROM address [' . $fromlist ? $fromlist->getMessage() : '' . "]\n\n" . $data); } $from = $fromlist[0]; //Default. foreach ($fromlist as $fromobj) { if (!Validator::is_email($fromobj->mailbox . '@' . $fromobj->host)) { continue; }
function parse($stream) { global $cfg; $contents = ''; if (is_resource($stream)) { while (!feof($stream)) { $contents .= fread($stream, 8192); } } else { $contents = $stream; } $parser = new Mail_Parse($contents); if (!$parser->decode()) { //Decode...returns false on decoding errors return $this->err('Email parse failed [' . $parser->getError() . ']'); } $data = array(); //FROM address: who sent the email. if (($fromlist = $parser->getFromAddressList()) && !PEAR::isError($fromlist)) { $from = $fromlist[0]; //Default. foreach ($fromlist as $fromobj) { if (!Validator::is_email($fromobj->mailbox . '@' . $fromobj->host)) { continue; } $from = $fromobj; break; } $data['email'] = $from->mailbox . '@' . $from->host; $data['name'] = trim($from->personal, '"'); if ($from->comment && $from->comment[0]) { $data['name'] .= ' (' . $from->comment[0] . ')'; } //Use email address as name when FROM address doesn't have a name. if (!$data['name'] && $data['email']) { $data['name'] = $data['email']; } } //TO Address:Try to figure out the email address... associated with the incoming email. $emailId = 0; if ($tolist = $parser->getToAddressList()) { foreach ($tolist as $toaddr) { if ($emailId = Email::getIdByEmail($toaddr->mailbox . '@' . $toaddr->host)) { break; } } } //maybe we got CC'ed?? if (!$emailId && ($cclist = $parser->getCcAddressList())) { foreach ($cclist as $ccaddr) { if ($emailId = Email::getIdByEmail($ccaddr->mailbox . '@' . $ccaddr->host)) { break; } } } $data['subject'] = $parser->getSubject(); $data['message'] = Format::stripEmptyLines($parser->getBody()); $data['header'] = $parser->getHeader(); $data['mid'] = $parser->getMessageId(); $data['priorityId'] = $parser->getPriority(); $data['emailId'] = $emailId; $data['in-reply-to'] = $parser->struct->headers['in-reply-to']; $data['references'] = $parser->struct->headers['references']; if (($replyto = $parser->getReplyTo()) && !PEAR::isError($replyto)) { $replyto = $replyto[0]; $data['reply-to'] = $replyto->mailbox . '@' . $replyto->host; if ($replyto->personal) { $data['reply-to-name'] = trim($replyto->personal, " \t\n\r\v\""); } } if ($cfg && $cfg->allowEmailAttachments()) { $data['attachments'] = $parser->getAttachments(); } return $data; }