/** * Return the rendered information about the Horde_Mime_Part object. * * @return array See parent::render(). */ protected function _renderInfo() { global $registry; if ($registry->getView() == $registry::VIEW_MINIMAL) { return array(); } $status = array(); $mime_id = $this->_mimepart->getMimeId(); $headers = Horde_Mime_Headers::parseHeaders($this->getConfigParam('imp_contents')->getBodyPart($mime_id, array('length' => 0, 'mimeheaders' => true, 'stream' => true))->data); if (($duration = $headers->getValue('content-duration')) !== null) { $text = array(); if ($minutes = floor($duration / 60)) { $text[] = sprintf(ngettext(_("%d minute"), _("%d minutes"), $minutes), $minutes); } if ($seconds = $duration % 60) { $text[] = sprintf(ngettext(_("%d second"), _("%d seconds"), $seconds), $seconds); } $status[] = sprintf(_("This video file is reported to be %s in length."), implode(' ', $text)); } if ($this->_thumbnailBinary()) { $status[] = _("This is a thumbnail of a video attachment."); $status[] = $this->getConfigParam('imp_contents')->linkViewJS($this->_mimepart, 'view_attach', '<img src="' . $this->getConfigParam('imp_contents')->urlView($this->_mimepart, 'view_attach', array('params' => array('imp_video_view' => 'view_thumbnail'))) . '" />', null, null, null); } if (empty($status)) { return array(); } $s = new IMP_Mime_Status($status); $s->icon('mime/video.png'); return array($this->_mimepart->getMimeId() => array('data' => '', 'status' => $s, 'type' => 'text/html; charset=UTF-8')); }
/** * See Bug #13456 Wnen we add the Message-Id/User-Agent headers, make sure * we don't cause the subject header to not be MIME encoded. */ public function testMIMEEncodingWhenStandardHeadersAreAdded() { $fixture = file_get_contents(__DIR__ . '/fixtures/mime_encoding.eml'); $rfc822 = new Horde_ActiveSync_Rfc822($fixture, true); $hdrs = Horde_Mime_Headers::parseHeaders($rfc822->getString()); $hdr_array = $hdrs->toArray(array('charset' => 'UTF-8')); $this->assertEquals('=?utf-8?b?w4PDhMOjw6s=?=', $hdr_array['Subject']); }
/** * TODO */ public function loadFixtures($dir) { $this->_fixtures = array(); $dh = opendir($dir); while (($dent = readdir($dh)) !== false) { if (!in_array($dent, array('.', '..'))) { $this->_fixtures[$dent] = Horde_Mime_Headers::parseHeaders(file_get_contents($dir . '/' . $dent)); } } closedir($dh); $i = 0; foreach (array_keys($this->_fixtures) as $key) { $this->_folders['INBOX'][] = array('uid' => ++$i, 'fixture' => $key, 'deleted' => false); } }
/** * Return the rendered information about the Horde_Mime_Part object. * * @return array See parent::render(). */ protected function _renderInfo() { $mime_id = $this->_mimepart->getMimeId(); $headers = Horde_Mime_Headers::parseHeaders($this->getConfigParam('imp_contents')->getBodyPart($mime_id, array('length' => 0, 'mimeheaders' => true, 'stream' => true))->data); if (($duration = $headers->getValue('content-duration')) === null) { return array(); } $text = array(); if ($minutes = floor($duration / 60)) { $text[] = sprintf(ngettext(_("%d minute"), _("%d minutes"), $minutes), $minutes); } if ($seconds = $duration % 60) { $text[] = sprintf(ngettext(_("%d second"), _("%d seconds"), $seconds), $seconds); } $status = new IMP_Mime_Status(sprintf(_("This audio file is reported to be %s in length."), implode(' ', $text))); $status->icon('mime/audio.png'); return array($this->_mimepart->getMimeId() => array('data' => '', 'status' => $status, 'type' => 'text/html; charset=UTF-8')); }
/** * Return the rendered information about the Horde_Mime_Part object. * * @return array See parent::render(). */ protected function _renderInfo() { /* Get the text of the part. Since we need to look for the end of * the headers by searching for the CRLFCRLF sequence, use * getCanonicalContents() to make sure we are getting the text with * CRLF's. */ $text = $this->_mimepart->getContents(array('canonical' => true)); if (empty($text)) { return array(); } /* Search for the end of the header text (CRLFCRLF). */ $text = substr($text, 0, strpos($text, "\r\n\r\n")); /* Get the list of headers now. */ $headers = Horde_Mime_Headers::parseHeaders($text); $header_array = array('date' => Horde_Mime_Viewer_Translation::t("Date"), 'from' => Horde_Mime_Viewer_Translation::t("From"), 'to' => Horde_Mime_Viewer_Translation::t("To"), 'cc' => Horde_Mime_Viewer_Translation::t("Cc"), 'bcc' => Horde_Mime_Viewer_Translation::t("Bcc"), 'reply-to' => Horde_Mime_Viewer_Translation::t("Reply-To"), 'subject' => Horde_Mime_Viewer_Translation::t("Subject")); $header_output = array(); foreach ($header_array as $key => $val) { $hdr = $this->_getHeaderValue($headers, $key); if (!empty($hdr)) { $header_output[] = '<strong>' . $val . ':</strong> ' . htmlspecialchars($hdr); } } return $this->_renderReturn(empty($header_output) ? '' : '<div class="fixed mimeHeaders">' . $this->_textFilter(implode("<br />\n", $header_output), 'emails') . '</div>', 'text/html; charset=UTF-8'); }
public function fetchHeaders($folder, $uid) { return Horde_Mime_Headers::parseHeaders($this->messages[$folder][$uid]); }
/** * Return representation of a header field. * * @param string $id The header id. * @param integer $format The return format. If self::HEADER_PARSE, * returns a Horde_Mime_Headers object. If * self::HEADER_STREAM, returns a stream. * Otherwise, returns header text. * @param integer $key The array key where the data is stored in the * internal array. * * @return mixed The data in the format specified by $format. */ protected function _getHeaders($id, $format, $key) { switch ($format) { case self::HEADER_STREAM: if (!isset($this->_data[$key][$id])) { return $this->_msgText(true, null); } elseif (is_object($this->_data[$key][$id])) { return $this->_getHeaders($id, 0, $key); } return $this->_msgText(true, $this->_data[$key][$id]); case self::HEADER_PARSE: if (!isset($this->_data[$key][$id])) { return new Horde_Mime_Headers(); } elseif (is_object($this->_data[$key][$id])) { return clone $this->_data[$key][$id]; } return Horde_Mime_Headers::parseHeaders($this->_getHeaders($id, self::HEADER_STREAM, $key)); } if (!isset($this->_data[$key][$id])) { return ''; } return is_object($this->_data[$key][$id]) ? $this->_data[$key][$id]->toString(array('nowrap' => true)) : $this->_msgText(false, $this->_data[$key][$id]); }
public function testInvalidHeaderParsing() { $data = file_get_contents(__DIR__ . '/fixtures/invalid_hdr.txt'); $hdrs = Horde_Mime_Headers::parseHeaders($data); $this->assertEquals('*****@*****.**', strval($hdrs['to'])); $this->assertNull($hdrs['From test2@example.com Sun Apr 5 09']); }
public function testMultiplePriorityHeaders() { $hdrs = Horde_Mime_Headers::parseHeaders("Importance: High\n" . "Importance: Low\n"); $this->assertInternalType('string', $hdrs->getValue('importance', Horde_Mime_Headers::VALUE_BASE)); $this->assertEquals('High', $hdrs->getValue('importance')); $hdrs = Horde_Mime_Headers::parseHeaders("X-Priority: 1\n" . "X-priority: 5\n"); $this->assertInternalType('string', $hdrs->getValue('x-priority', Horde_Mime_Headers::VALUE_BASE)); $this->assertEquals('1', $hdrs->getValue('x-priority')); }
/** * Return message changes from the specified mailbox. * * @param Horde_ActiveSync_Folder_Imap $folder The folder object. * @param array $options Additional options: * - sincedate: (integer) Timestamp of earliest message to retrieve. * DEFAULT: 0 (Don't filter). * - protocolversion: (float) EAS protocol version to support. * DEFAULT: none REQUIRED * - softdelete: (boolean) If true, calculate SOFTDELETE data. * @since 2.8.0 * * @return Horde_ActiveSync_Folder_Imap The folder object, containing any * change instructions for the device. * * @throws Horde_ActiveSync_Exception_FolderGone, * Horde_ActiveSync_Exception, Horde_ActiveSync_Exception_StaleState */ public function getMessageChanges(Horde_ActiveSync_Folder_Imap $folder, array $options = array()) { $imap = $this->_getImapOb(); $mbox = new Horde_Imap_Client_Mailbox($folder->serverid()); // Note: non-CONDSTORE servers will return a highestmodseq of 0 $status_flags = Horde_Imap_Client::STATUS_HIGHESTMODSEQ | Horde_Imap_Client::STATUS_UIDVALIDITY | Horde_Imap_Client::STATUS_UIDNEXT_FORCE | Horde_Imap_Client::STATUS_MESSAGES | Horde_Imap_Client::STATUS_FORCE_REFRESH; try { $status = $imap->status($mbox, $status_flags); } catch (Horde_Imap_Client_Exception $e) { // If we can't status the mailbox, assume it's gone. throw new Horde_ActiveSync_Exception_FolderGone($e); } $this->_logger->info(sprintf('[%s] IMAP status: %s', $this->_procid, serialize($status))); $flags = array(); $categories = array(); $modseq = $status[Horde_ActiveSync_Folder_Imap::HIGHESTMODSEQ]; if ($modseq && $folder->modseq() > 0 && $folder->modseq() < $modseq) { $this->_logger->info(sprintf('[%s] CONDSTORE and CHANGES', $this->_procid)); $folder->checkValidity($status); $query = new Horde_Imap_Client_Fetch_Query(); $query->modseq(); $query->flags(); $query->headerText(array('peek' => true)); try { $fetch_ret = $imap->fetch($mbox, $query, array('changedsince' => $folder->modseq())); } catch (Horde_Imap_Client_Exception $e) { $this->_logger->err($e->getMessage()); throw new Horde_ActiveSync_Exception($e); } // Prepare the changes and flags array, ensuring no changes after // $modseq sneak in yet (they will be caught on the next PING or // SYNC). $changes = array(); // Get custom flags to use as categories. $msgFlags = $this->_getMsgFlags(); foreach ($fetch_ret as $uid => $data) { if ($options['sincedate']) { $since = new Horde_Date($options['sincedate']); $headers = Horde_Mime_Headers::parseHeaders($data->getHeaderText()); try { $date = new Horde_Date($headers->getValue('Date')); if ($date->compareDate($since) <= -1) { // Ignore, it's out of the FILTERTYPE range. $this->_logger->info(sprintf('[%s] Ignoring UID %s since it is outside of the FILTERTYPE (%s)', $this->_procid, $uid, $headers->getValue('Date'))); continue; } } catch (Horde_Date_Exception $e) { } } if ($data->getModSeq() <= $modseq) { $changes[] = $uid; $flags[$uid] = array('read' => array_search(Horde_Imap_Client::FLAG_SEEN, $data->getFlags()) !== false ? 1 : 0); if ($options['protocolversion'] > Horde_ActiveSync::VERSION_TWOFIVE) { $flags[$uid]['flagged'] = array_search(Horde_Imap_Client::FLAG_FLAGGED, $data->getFlags()) !== false ? 1 : 0; } if ($options['protocolversion'] > Horde_ActiveSync::VERSION_TWELVEONE) { $categories[$uid] = array(); foreach ($data->getFlags() as $flag) { if (($key = array_search(strtolower($flag), array_map('strtolower', $msgFlags))) !== false) { $categories[$uid][] = $msgFlags[$key]; } } } } } $folder->setChanges($changes, $flags, $categories); try { $deleted = $imap->vanished($mbox, $folder->modseq(), array('ids' => new Horde_Imap_Client_Ids($folder->messages()))); } catch (Horde_Imap_Client_Excetion $e) { $this->_logger->err($e->getMessage()); throw new Horde_ActiveSync_Exception($e); } $folder->setRemoved($deleted->ids); if (!empty($options['softdelete']) && !empty($options['sincedate'])) { $this->_logger->info(sprintf('[%s] Polling for SOFTDELETE in %s before %d', $this->_procid, $folder->serverid(), $options['sincedate'])); $query = new Horde_Imap_Client_Search_Query(); $query->dateSearch(new Horde_Date($options['sincedate']), Horde_Imap_Client_Search_Query::DATE_BEFORE); $query->ids(new Horde_Imap_Client_Ids($folder->messages())); try { $search_ret = $imap->search($mbox, $query, array('results' => array(Horde_Imap_Client::SEARCH_RESULTS_MATCH))); } catch (Horde_Imap_Client_Exception $e) { $this->_logger->err($e->getMessage()); throw new Horde_ActiveSync_Exception($e); } if ($search_ret['count']) { $this->_logger->info(sprintf('[%s] Found %d messages to SOFTDELETE.', $this->_procid, count($search_ret['match']->ids))); $folder->setSoftDeleted($search_ret['match']->ids); } else { $this->_logger->info(sprintf('[%s] Found NO messages to SOFTDELETE.', $this->_procid)); } $folder->setSoftDeleteTimes($options['sincedate'], time()); } } elseif ($folder->uidnext() == 0) { $this->_logger->info(sprintf('[%s] INITIAL SYNC', $this->_procid)); $query = new Horde_Imap_Client_Search_Query(); if (!empty($options['sincedate'])) { $query->dateSearch(new Horde_Date($options['sincedate']), Horde_Imap_Client_Search_Query::DATE_SINCE); } $search_ret = $imap->search($mbox, $query, array('results' => array(Horde_Imap_Client::SEARCH_RESULTS_MATCH))); if ($modseq && $folder->modseq() > 0 && $search_ret['count']) { $folder->setChanges($search_ret['match']->ids, array()); } elseif (count($search_ret['match']->ids)) { $query = new Horde_Imap_Client_Fetch_Query(); $query->flags(); $fetch_ret = $imap->fetch($mbox, $query, array('ids' => $search_ret['match'])); foreach ($fetch_ret as $uid => $data) { $flags[$uid] = array('read' => array_search(Horde_Imap_Client::FLAG_SEEN, $data->getFlags()) !== false ? 1 : 0); if ($options['protocolversion'] > Horde_ActiveSync::VERSION_TWOFIVE) { $flags[$uid]['flagged'] = array_search(Horde_Imap_Client::FLAG_FLAGGED, $data->getFlags()) !== false ? 1 : 0; } } $folder->setChanges($search_ret['match']->ids, $flags); } } elseif ($modseq == 0) { $this->_logger->info(sprintf('[%s] NO CONDSTORE or per mailbox MODSEQ. minuid: %s, total_messages: %s', $this->_procid, $folder->minuid(), $status['messages'])); $folder->checkValidity($status); $query = new Horde_Imap_Client_Search_Query(); if (!empty($options['sincedate'])) { $query->dateSearch(new Horde_Date($options['sincedate']), Horde_Imap_Client_Search_Query::DATE_SINCE); } try { $search_ret = $imap->search($mbox, $query, array('results' => array(Horde_Imap_Client::SEARCH_RESULTS_MATCH))); } catch (Horde_Imap_Client_Exception $e) { $this->_logger->err($e->getMessage()); throw new Horde_ActiveSync_Exception($e); } if (count($search_ret['match']->ids)) { // Update flags. $query = new Horde_Imap_Client_Fetch_Query(); $query->flags(); try { $fetch_ret = $imap->fetch($mbox, $query, array('ids' => $search_ret['match'])); } catch (Horde_Imap_Client_Exception $e) { $this->_logger->err($e->getMessage()); throw new Horde_ActiveSync_Exception($e); } foreach ($fetch_ret as $uid => $data) { $flags[$uid] = array('read' => array_search(Horde_Imap_Client::FLAG_SEEN, $data->getFlags()) !== false ? 1 : 0); if ($options['protocolversion'] > Horde_ActiveSync::VERSION_TWOFIVE) { $flags[$uid]['flagged'] = array_search(Horde_Imap_Client::FLAG_FLAGGED, $data->getFlags()) !== false ? 1 : 0; } } $folder->setChanges($search_ret['match']->ids, $flags); } $folder->setRemoved($imap->vanished($mbox, null, array('ids' => new Horde_Imap_Client_Ids($folder->messages())))->ids); } elseif ($modseq > 0 && $folder->modseq() == 0) { throw new Horde_ActiveSync_Exception_StaleState('Transition to MODSEQ enabled server'); } $folder->setStatus($status); return $folder; }
/** * Parse a MIME message and create a new ticket. * * @param string $text This is the full text of the MIME message. * @param array $info An array of information for the new ticket. * This should include: * - 'queue' => queue id * - 'type' => type id * - 'state' => state id * - 'priority' => priority id * - 'ticket' => ticket id (prevents creation * of new tickets) * @param string $auth_user This will be the Horde user that creates the * ticket. If null, we will try to deduce from * the message's From: header. We do NOT default * to $GLOBALS['registry']->getAuth(). * * @return Whups_Ticket Ticket. */ public static function processMail($text, array $info, $auth_user = null) { global $conf; $message = Horde_Mime_Part::parseMessage($text); if (preg_match("/^(.*?)\r?\n\r?\n/s", $text, $matches)) { $hdrText = $matches[1]; } else { $hdrText = $text; } $headers = Horde_Mime_Headers::parseHeaders($hdrText); // If this message was generated by Whups, don't process it. if ($headers->getValue('X-Whups-Generated')) { return true; } // Try to avoid bounces, auto-replies, and mailing list responses. $from = $headers->getValue('from'); if (strpos($headers->getValue('Content-Type'), 'multipart/report') !== false || stripos($from, 'mailer-daemon@') !== false || stripos($from, 'postmaster@') !== false || !is_null($headers->getValue('X-Failed-Recipients')) || !is_null($headers->getValue('X-Autoreply-Domain')) || $headers->getValue('Auto-Submitted') == 'auto-replied' || $headers->getValue('Precedence') == 'auto_reply' || $headers->getValue('X-Precedence') == 'auto_reply' || $headers->getValue('X-Auto-Response-Suppress') == 'All' || $headers->getValue('X-List-Administrivia') == 'Yes') { return true; } // Use the message subject as the ticket summary. $info['summary'] = trim($headers->getValue('subject')); if (empty($info['summary'])) { $info['summary'] = _("[No Subject]"); } // Format the message into a comment. $comment = _("Received message:") . "\n\n"; if (!empty($GLOBALS['conf']['mail']['include_headers'])) { foreach ($headers->toArray(array('nowrap' => true)) as $name => $vals) { if (!in_array(strtolower($name), array('subject', 'from', 'to', 'cc', 'date'))) { if (is_array($vals)) { foreach ($vals as $val) { $comment .= $name . ': ' . $val . "\n"; } } else { $comment .= $name . ': ' . $vals . "\n"; } } } $comment .= "\n"; } // Look for the body part. $body_id = $message->findBody(); if ($body_id) { $part = $message->getPart($body_id); $content = Horde_String::convertCharset($part->getContents(), $part->getCharset(), 'UTF-8'); switch ($part->getType()) { case 'text/plain': $comment .= $content; break; case 'text/html': $comment .= Horde_Text_Filter::filter($content, array('Html2text'), array(array('width' => 0))); break; default: $comment .= _("[ Could not render body of message. ]"); break; } } else { $comment .= _("[ Could not render body of message. ]"); } $info['comment'] = $comment . "\n"; // Try to determine the Horde user for creating the ticket. if (empty($auth_user)) { $tmp = new Horde_Mail_Rfc822_Address($from); $auth_user = self::_findAuthUser($tmp->bare_address); } $author = $auth_user; if (empty($auth_user) && !empty($info['default_auth'])) { $auth_user = $info['default_auth']; if (!empty($from)) { $info['user_email'] = $from; } } if (empty($auth_user) && !empty($conf['mail']['username'])) { $auth_user = $conf['mail']['username']; if (!empty($from)) { $info['user_email'] = $from; } } // Authenticate as the correct Horde user. if (!empty($auth_user) && $auth_user != $GLOBALS['registry']->getAuth()) { $GLOBALS['registry']->setAuth($auth_user, array()); } // Attach message. $attachments = array(); if (!empty($GLOBALS['conf']['mail']['attach_message'])) { $tmp_name = Horde::getTempFile('whups'); $fp = @fopen($tmp_name, 'wb'); if (!$fp) { throw new Whups_Exception(sprintf('Cannot open file %s for writing.', $tmp_name)); } fwrite($fp, $text); fclose($fp); $attachments[] = array('name' => _("Original Message") . '.eml', 'tmp_name' => $tmp_name); } // Extract attachments. $dl_list = array_slice(array_keys($message->contentTypeMap()), 1); foreach ($dl_list as $key) { $part = $message->getPart($key); if ($key == $body_id && $part->getType() == 'text/plain' || $part->getType() == 'multipart/alternative' || $part->getType() == 'multipart/mixed') { continue; } $tmp_name = Horde::getTempFile('whups'); $fp = @fopen($tmp_name, 'wb'); if (!$fp) { throw new Whups_Exception(sprintf('Cannot open file %s for writing.', $tmp_name)); } fwrite($fp, $part->getContents()); fclose($fp); $part_name = $part->getName(true); if (!$part_name) { $ptype = $part->getPrimaryType(); switch ($ptype) { case 'multipart': case 'application': $part_name = sprintf(_("%s part"), ucfirst($part->getSubType())); break; default: $part_name = sprintf(_("%s part"), ucfirst($ptype)); break; } if ($ext = Horde_Mime_Magic::mimeToExt($part->getType())) { $part_name .= '.' . $ext; } } $attachments[] = array('name' => $part_name, 'tmp_name' => $tmp_name); } // See if we can match this message to an existing ticket. if ($ticket = self::_findTicket($info)) { $ticket->change('comment', $info['comment']); $ticket->change('comment-email', $from); if ($attachments) { $ticket->change('attachments', $attachments); } $ticket->commit($author); } elseif (!empty($info['ticket'])) { // Didn't match an existing ticket though a ticket number had been // specified. throw new Whups_Exception(sprintf(_("Could not find ticket \"%s\"."), $info['ticket'])); } else { if (!empty($info['guess-queue'])) { // Try to guess the queue name for the new ticket from the // message subject. $queues = $GLOBALS['whups_driver']->getQueues(); foreach ($queues as $queueId => $queueName) { if (preg_match('/\\b' . preg_quote($queueName, '/') . '\\b/i', $info['summary'])) { $info['queue'] = $queueId; break; } } } $info['attachments'] = $attachments; // Create a new ticket. $ticket = Whups_Ticket::newTicket($info, $author); } }
/** * Retrieves the message headers. * * @param string $folder The folder to fetch the message from. * @param array $uid The message UID. * * @return Horde_Mime_Headers The message headers. */ public function fetchHeaders($folder, $uid) { $query = new Horde_Imap_Client_Fetch_Query(); $query->headerText(); try { $ret = $this->getBackend()->fetch($folder, $query, array('ids' => new Horde_Imap_Client_Ids($uid))); $msg = $ret[$uid]->getHeaderText(); } catch (Horde_Imap_Client_Exception_ServerResponse $e) { throw new Horde_Kolab_Storage_Exception($e->details); } catch (Horde_Imap_Client_Exception $e) { throw new Horde_Kolab_Storage_Exception($e); } return Horde_Mime_Headers::parseHeaders($msg); }
/** * Retrieves a complete message. * * @param string $folder The folder to fetch the messages from. * @param array $uid The message UID. * * @return array The message encapsuled as an array that contains a * Horde_Mime_Headers and a Horde_Mime_Part object. */ public function fetchComplete($folder, $uid) { $this->select($folder); return array(Horde_Mime_Headers::parseHeaders(Horde_Kolab_Storage_Exception_Pear::catchError($this->getBackend()->getRawHeaders($uid, '', true))), Horde_Mime_Part::parseMessage(Horde_Kolab_Storage_Exception_Pear::catchError($this->getBackend()->getBody($uid, true)))); }
/** * Return the rendered information about the Horde_Mime_Part object. * * @return array See parent::render(). */ protected function _renderInfo() { $imp_contents = $this->getConfigParam('imp_contents'); $machine = $original = $status = null; $mime_id = $this->_mimepart->getMimeId(); $ret = array(); switch ($this->_mimepart->getType()) { case 'message/delivery-status': $machine = $imp_contents->getMimePart($mime_id); break; case 'multipart/report': /* RFC 3464 [2]: There are three parts to a delivery status * multipart/report message: * (1) Human readable message * (2) Machine parsable body part (message/delivery-status) * (3) Returned message (optional) */ $iterator = $this->_mimepart->partIterator(false); $iterator->rewind(); if (!($curr = $iterator->current())) { break; } $part1_id = $curr->getMimeId(); $id_ob = new Horde_Mime_Id($part1_id); /* Technical details. */ $id_ob->id = $id_ob->idArithmetic($id_ob::ID_NEXT); $ret[$id_ob->id] = null; $machine = $imp_contents->getMimePart($id_ob->id); /* Returned message. */ $original = $imp_contents->getMimePart($id_ob->idArithmetic($id_ob::ID_NEXT)); if ($original) { foreach ($this->_mimepart->partIterator() as $val) { $ret[$val->getMimeId()] = null; } /* Allow the human readable part to be displayed * separately. */ unset($ret[$part1_id]); } break; } if (!$machine) { return array($mime_id => null); } $parse = Horde_Mime_Headers::parseHeaders(preg_replace('/\\n{2,}/', "\n", strtr($machine->getContents(), "\r", "\n"))); /* Information on the message status is found in the 'Action' * field located in part #2 (RFC 3464 [2.3.3]). */ if (isset($parse['Action'])) { switch (trim($parse['Action']->value_single)) { case 'failed': case 'delayed': $msg_link = _("View details of the returned message."); $status_action = IMP_Mime_Status::ERROR; $status_msg = _("ERROR: Your message could not be delivered."); break; case 'delivered': case 'expanded': case 'relayed': $msg_link = _("View details of the delivered message."); $status_action = IMP_Mime_Status::SUCCESS; $status_msg = _("Your message was successfully delivered."); break; } if (isset($msg_link)) { $status = new IMP_Mime_Status($this->_mimepart, $status_msg); $status->action($status_action); if (isset($parse['Final-Recipient'])) { list(, $recip) = explode(';', $parse['Final-Recipient']->value_single); $recip_ob = new Horde_Mail_Rfc822_List($recip); if (count($recip_ob)) { $status->addText(sprintf(_("Recipient: %s"), $recip_ob[0])); } } /* Display a link to the returned message, if it exists. */ if ($original) { $status->addText($imp_contents->linkViewJS($original, 'view_attach', $msg_link, array('params' => array('ctype' => 'message/rfc822')))); } } } $ret[$mime_id] = array_filter(array('data' => '', 'status' => $status ?: null, 'type' => 'text/html; charset=' . $this->getConfigParam('charset'), 'wrap' => 'mimePartWrap')); return $ret; }
/** * Return representation of a header field. * * @param string $id The header id. * @param integer $format The return format. If self::HEADER_PARSE, * returns a Horde_Mime_Headers object. If * self::HEADER_STREAM, returns a stream. * Otherwise, returns header text. * @param integer $key The array key where the data is stored in the * internal array. * * @return mixed The data in the format specified by $format. */ protected function _getHeaders($id, $format, $key) { switch ($format) { case self::HEADER_STREAM: if (!isset($this->_data[$key][$id])) { $data = null; } elseif (is_object($this->_data[$key][$id])) { switch ($key) { case Horde_Imap_Client::FETCH_HEADERS: $data = $this->_getHeaders($id, 0, $key); break; case Horde_Imap_Client::FETCH_HEADERTEXT: case Horde_Imap_Client::FETCH_MIMEHEADER: return $this->_data[$key][$id]->stream; } } else { $data = $this->_data[$key][$id]; } return $this->_msgText(true, $data); case self::HEADER_PARSE: if (!isset($this->_data[$key][$id])) { return new Horde_Mime_Headers(); } elseif (is_object($this->_data[$key][$id])) { switch ($key) { case Horde_Imap_Client::FETCH_HEADERS: return clone $this->_data[$key][$id]; case Horde_Imap_Client::FETCH_HEADERTEXT: case Horde_Imap_Client::FETCH_MIMEHEADER: $hdrs = $this->_data[$key][$id]; break; } } else { $hdrs = $this->_getHeaders($id, self::HEADER_STREAM, $key); } return Horde_Mime_Headers::parseHeaders($hdrs); } if (!isset($this->_data[$key][$id])) { return ''; } if (is_object($this->_data[$key][$id])) { switch ($key) { case Horde_Imap_Client::FETCH_HEADERS: return $this->_data[$key][$id]->toString(array('nowrap' => true)); case Horde_Imap_Client::FETCH_HEADERTEXT: case Horde_Imap_Client::FETCH_MIMEHEADER: return strval($this->_data[$key][$id]); } } return $this->_msgText(false, $this->_data[$key][$id]); }
/** * Return the rendered information about the Horde_Mime_Part object. * * @return array See parent::render(). */ protected function _renderInfo() { $imp_contents = $this->getConfigParam('imp_contents'); $machine = $original = null; $ret = array(); switch ($this->_mimepart->getType()) { case 'message/disposition-notification': /* Outlook can send a disposition-notification without the * RFC-required multipart/report wrapper. */ $machine = $imp_contents->getMimePart($this->_mimepart->getMimeId()); break; case 'multipart/report': /* RFC 3798 [3]: There are three parts to a delivery status * multipart/report message: * (1) Human readable message * (2) Machine parsable body part * [message/disposition-notification] * (3) Original message (optional) */ $iterator = $this->_mimepart->partIterator(false); $iterator->rewind(); if (!($curr = $iterator->current())) { break; } $part1_id = $curr->getMimeId(); $id_ob = new Horde_Mime_Id($part1_id); /* Technical details. */ $id_ob->id = $id_ob->idArithmetic($id_ob::ID_NEXT); $ret[$id_ob->id] = null; $machine = $imp_contents->getMimePart($id_ob->id); /* Original sent message. */ $original = $imp_contents->getMimePart($id_ob->idArithmetic($id_ob::ID_NEXT)); if ($original) { foreach ($this->_mimepart->partIterator() as $val) { $ret[$val->getMimeId()] = null; } /* Allow the human readable part to be displayed * separately. */ unset($ret[$part1_id]); } break; default: return array($this->_mimepart->getMimeId() => null); } $mdn_status = array(_("A message you have sent has resulted in a return notification from the recipient.")); if ($machine) { $parse = Horde_Mime_Headers::parseHeaders(preg_replace('/\\n{2,}/', "\n", strtr($machine->getContents(), "\r", "\n"))); if (isset($parse['Final-Recipient'])) { list(, $recip) = explode(';', $parse['Final-Recipient']->value_single); if ($recip) { $mdn_status[] = sprintf(_("Recipient: %s"), trim($recip)); } } if (isset($parse['Disposition'])) { list($modes, $type) = explode(';', $parse['Disposition']->value_single); list($action, $sent) = explode('/', $modes); switch (trim(Horde_String::lower($type))) { case 'displayed': $mdn_status[] = _("The message has been displayed to the recipient."); break; case 'deleted': $mdn_status[] = _("The message has been deleted by the recipient; it is unknown whether they viewed the message."); break; } switch (trim(Horde_String::lower($action))) { case 'manual-action': // NOOP break; case 'automatic-action': // NOOP break; } switch (trim(Horde_String::lower($sent))) { case 'mdn-sent-manually': $mdn_status[] = _("This notification was explicitly sent by the recipient."); break; case 'mdn-sent-automatically': // NOOP break; } } } $status = new IMP_Mime_Status($this->_mimepart, $mdn_status); $status->icon('info_icon.png', _("Info")); if ($original) { $status->addText($imp_contents->linkViewJS($original, 'view_attach', _("View the text of the original sent message."), array('params' => array('ctype' => 'message/rfc822', 'mode' => IMP_Contents::RENDER_FULL)))); } $ret[$this->_mimepart->getMimeId()] = array('data' => '', 'status' => $status, 'type' => 'text/html; charset=' . $this->getConfigParam('charset'), 'wrap' => 'mimePartWrap'); return $ret; }
/** * Retrieves a complete message. * * @param string $folder The folder to fetch the messages from. * @param array $uid The message UID. * * @return array The message encapsuled as an array that contains a * Horde_Mime_Headers and a Horde_Mime_Part object. */ public function fetchComplete($folder, $uid) { $this->select($folder); $headers = @imap_fetchheader($this->getBackend(), $uid, FT_UID | FT_PREFETCHTEXT); $body = @imap_body($this->getBackend(), $uid, FT_UID); if ($headers && $body) { return array(Horde_Mime_Headers::parseHeaders($headers), Horde_Mime_Part::parseMessage($body)); } else { throw new Horde_Kolab_Storage_Exception(sprintf(Horde_Kolab_Storage_Translation::t("Failed fetching message %s in folder %s.") . ' ' . Horde_Kolab_Storage_Translation::t("Error: %s"), $uid, $this->_getBaseMbox() . $folder, imap_last_error())); } }
function GetHeaders($message) { $this->headers = Horde_Mime_Headers::parseHeaders($message->getHeaderText()); return true; }
private function _getMailHeaders() { if (isset($GLOBALS['injector']->getInstance('IMP_Mail')->sentMessages[0])) { $headers = Horde_Mime_Headers::parseHeaders($GLOBALS['injector']->getInstance('IMP_Mail')->sentMessages[0]['header_text']); if (!$headers instanceof Horde_Mime_Headers) { $this->fail('Failed parsing message headers!'); return new Horde_Mime_Headers(); } return $headers; } $this->fail('No message has been sent!'); }
/** * Get an IMAP message and retrieve the Kolab Format object. * * @param int $id The message to retrieve. * @param string $mime_type The mime type of the part to retrieve. * @param boolean $parse_headers Should the heades be Mime parsed? * @param array $formats The list of possible format parts. * * @return array|PEAR_Error An array that list the Kolab XML * object text, the mime ID of the part * with the XML object, the Mime parsed * message and the Mime parsed headers if * requested. */ function parseMessage($id, $mime_type, $parse_headers = true, $formats = array('XML')) { $raw_headers = $this->_driver->getMessageHeader($this->_path, $id); if (is_a($raw_headers, 'PEAR_Error')) { return PEAR::raiseError(sprintf(Horde_Kolab_Storage_Translation::t("Failed retrieving the message with ID %s. Original error: %s."), $id, $raw_headers->getMessage())); } $body = $this->_driver->getMessageBody($this->_path, $id); if (is_a($body, 'PEAR_Error')) { return PEAR::raiseError(sprintf(Horde_Kolab_Storage_Translation::t("Failed retrieving the message with ID %s. Original error: %s."), $id, $body->getMessage())); } //@todo: not setting "forcemime" means the subparts get checked too. Seems incorrect. $mime_message = Horde_Mime_Part::parseMessage($raw_headers . "\r" . $body, array('forcemime' => true)); $parts = $mime_message->contentTypeMap(); $mime_headers = false; $xml = false; // Read in a Kolab event object, if one exists $part_ids['XML'] = array_search($mime_type, $parts); if ($part_ids['XML'] !== false) { if ($parse_headers) { $mime_headers = Horde_Mime_Headers::parseHeaders($raw_headers); $mime_headers->setEOL("\r\n"); } $part = $mime_message->getPart($part_ids['XML']); //@todo: Check what happened to this call //$part->transferDecodeContents(); $xml = $part->getContents(); } $alternate_formats = array_diff(array('XML'), $formats); if (!empty($alternate_formats)) { foreach ($alternate_formats as $type) { $part_ids[$type] = false; } foreach ($mime_message->getParts() as $part) { $params = $part->getDispositionParameters(); foreach ($alternate_formats as $type) { if (isset($params['x-kolab-format']) && $params['x-kolab-format'] == $type) { $part_ids[$type] = $part->getMimeId(); } } } } $result = array($xml, $part_ids, $mime_message, $mime_headers); return $result; }
/** * Retrieve locally cached message data. * * @param string $type Either 'hdr', 'hdrob', 'msg', 'size', 'stat', * or 'uidl'. * @param integer $index The message index. * @param mixed $data Additional information needed. * * @return mixed The cached data. 'msg' returns a stream resource. All * other types return strings. * * @throws Horde_Imap_Client_Exception */ protected function _pop3Cache($type, $index = null, $data = null) { if (isset($this->_temp['pop3cache'][$index][$type])) { if ($type == 'msg') { rewind($this->_temp['pop3cache'][$index][$type]); } return $this->_temp['pop3cache'][$index][$type]; } switch ($type) { case 'hdr': $data = null; if ($this->queryCapability('TOP')) { try { $resp = $this->_sendLine('TOP ' . $index . ' 0'); $ptr = $this->_getMultiline(); rewind($ptr); $data = stream_get_contents($ptr); fclose($ptr); } catch (Horde_Imap_Client_Exception $e) { } } if (is_null($data)) { $data = Horde_Mime_Part::getRawPartText(stream_get_contents($this->_pop3Cache('msg', $index)), 'header', 0); } break; case 'hdrob': $data = Horde_Mime_Headers::parseHeaders($this->_pop3Cache('hdr', $index)); break; case 'msg': $resp = $this->_sendLine('RETR ' . $index); $data = $this->_getMultiline(); rewind($data); break; case 'size': case 'uidl': $data = array(); try { $this->_sendLine($type == 'size' ? 'LIST' : 'UIDL'); foreach ($this->_getMultiline(true) as $val) { $resp_data = explode(' ', $val, 2); $data[$resp_data[0]] = $resp_data[1]; } } catch (Horde_Imap_Client_Exception $e) { } break; case 'stat': $resp = $this->_sendLine('STAT'); $resp_data = explode(' ', $resp['line'], 2); $data = array('msgs' => $resp_data[0], 'size' => $resp_data[1]); break; } $this->_temp['pop3cache'][$index][$type] = $data; return $data; }
/** * Retrieve locally cached message data. * * @param string $type Either 'hdr', 'hdrob', 'msg', 'size', 'stat', * 'top', or 'uidl'. * @param integer $index The message index. * @param mixed $data Additional information needed. * * @return mixed The cached data. 'msg' returns a stream resource. All * other types return strings. * * @throws Horde_Imap_Client_Exception */ protected function _pop3Cache($type, $index = self::MBOX_CACHE, $data = null) { if (isset($this->_temp['pop3cache'][$index][$type])) { if ($type == 'msg') { rewind($this->_temp['pop3cache'][$index][$type]); } return $this->_temp['pop3cache'][$index][$type]; } switch ($type) { case 'hdr': case 'top': $data = null; if ($type == 'top' || $this->_capability('TOP')) { try { $res = $this->_sendLine('TOP ' . $index . ' 0', array('multiline' => 'stream')); rewind($res['data']); $data = stream_get_contents($res['data']); fclose($res['data']); } catch (Horde_Imap_Client_Exception $e) { $this->_temp['no_top'] = true; if ($type == 'top') { return null; } } } if (is_null($data)) { $data = Horde_Mime_Part::getRawPartText(stream_get_contents($this->_pop3Cache('msg', $index)), 'header', 0); } break; case 'hdrob': $data = Horde_Mime_Headers::parseHeaders($this->_pop3Cache('hdr', $index)); break; case 'msg': $res = $this->_sendLine('RETR ' . $index, array('multiline' => 'stream')); $data = $res['data']; rewind($data); break; case 'size': case 'uidl': $data = array(); try { $res = $this->_sendLine($type == 'size' ? 'LIST' : 'UIDL', array('multiline' => 'array')); foreach ($res['data'] as $val) { $resp_data = explode(' ', $val, 2); $data[$resp_data[0]] = $resp_data[1]; } } catch (Horde_Imap_Client_Exception $e) { if ($type == 'uidl') { $this->_temp['no_uidl'] = true; } } break; case 'stat': $resp = $this->_sendLine('STAT'); $resp_data = explode(' ', $resp['resp'], 2); $data = array('msgs' => $resp_data[0], 'size' => $resp_data[1]); break; } $this->_temp['pop3cache'][$index][$type] = $data; return $data; }
public function testBug13709() { $p_part = new Horde_Mime_Part(); $p_part->setType('text/plain'); $p_part->setContents('Foo bär'); $h_part = new Horde_Mime_Part(); $h_part->setType('text/html'); $h_part->setContents('Foo<br /> <br /> "smith, Jane (IAM)" <<a href="mailto:Jane.smith@kit.edu">Jane.smith@kit.edu</a>> wrote:<br /> <br /> <blockquote type="cite" style="border-left:2px solid blue;margin-left:2px;padding-left:12px;"><html><head><meta http-equiv="Content-Type" content="text/html charset=windows-1252"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;">Hallo Jörk,<div><br></div><div>hoffe es geht dir gut und bei HHHH ist alles okay?</div><div><br></div><div>Ich wollte gerade auf die XXX III Homepage schauen und haben im Browser nur <a href="http://example.com">example.com</a> eingegeben.</div><div>Damit bin ich auf einer Seite mit XXX II - Logo gelandet, die sofort Passwort und Nutzername abgefragt hat.</div><div>Ist diese Seite auch von Euch?</div><div><br></div><div>Liebe Grüße,</div><div>Jane</div><div><br></div><div><br></div><div><br></div><div><br></div><div><br><div> <div><div style="orphans: 2; text-align: -webkit-auto; widows: 2; word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; font-size: 10px;">--------------------------------------------------<br>Dr. Jane smith</div><div style="orphans: 2; text-align: -webkit-auto; widows: 2; word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; font-size: 10px;">( geb. Repper)<br>Karlsruhe Institute of Technology (KIT) <br>IAM-WK@INT <br>Hermann-von-Helmholtz-Platz 1, Building 640, </div><div style="orphans: 2; text-align: -webkit-auto; widows: 2; word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; font-size: 10px;">76344 Eggenstein-Leopoldshafen, Germany<br><br>Phone CN: +49 721 608-26960</div><div style="orphans: 2; text-align: -webkit-auto; widows: 2; word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; font-size: 10px;">Phone CS: +49 721 608-47447<br>Web: <a href="http://www.kit.edu/">http://www.kit.edu/</a> <br><br>KIT – University of the State of Baden-Wuerttemberg and<br>National Research Center of the Helmholtz Association</div></div> </div> <br></div></body></html></blockquote><br /><br />'); $base_part = new Horde_Mime_Part(); $base_part->setType('multipart/alternative'); $base_part[] = $p_part; $base_part[] = $h_part; $headers = $base_part->addMimeHeaders(); $headers->addHeader('From', '*****@*****.**'); $headers->addHeader('Subject', 'My Subject'); $mailer = new Horde_Mail_Transport_Mock(); $base_part->send('*****@*****.**', $headers, $mailer, array('encode' => Horde_Mime_Part::ENCODE_8BIT)); $sent = current($mailer->sentMessages); $sent_mime = Horde_Mime_Part::parseMessage($sent['header_text'] . "\n\n" . $sent['body']); $headers = Horde_Mime_Headers::parseHeaders($sent_mime[$sent_mime->findBody('plain')]->toString(array('headers' => true, 'encode' => Horde_Mime_Part::ENCODE_8BIT))); $this->assertEquals('8bit', $headers->getHeader('Content-Transfer-Encoding')->value_single); $headers = Horde_Mime_Headers::parseHeaders($sent_mime[$sent_mime->findBody('html')]->toString(array('headers' => true, 'encode' => Horde_Mime_Part::ENCODE_8BIT))); $this->assertEquals('quoted-printable', $headers->getHeader('Content-Transfer-Encoding')); }
/** * Append message(s) to a mailbox. * * @param mixed $mailbox The mailbox to append the message(s) to. Either * a Horde_Imap_Client_Mailbox object or a string * (UTF-8). * @param array $data The message data to append, along with * additional options. An array of arrays with * each embedded array having the following * entries: * <ul> * <li> * data: (mixed) The data to append. If a string or a stream resource, * this will be used as the entire contents of a single message. If an * array, will catenate all given parts into a single message. This * array contains one or more arrays with two keys: * <ul> * <li> * t: (string) Either 'url' or 'text'. * </li> * <li> * v: (mixed) If 't' is 'url', this is the IMAP URL to the message * part to append. If 't' is 'text', this is either a string or * resource representation of the message part data. * DEFAULT: NONE (entry is MANDATORY) * </li> * </ul> * </li> * <li> * flags: (array) An array of flags/keywords to set on the appended * message. * DEFAULT: Only the \Recent flag is set. * </li> * <li> * internaldate: (DateTime) The internaldate to set for the appended * message. * DEFAULT: internaldate will be the same date as when the message was * appended. * </li> * </ul> * @param array $options Additonal options: * - create: (boolean) Try to create $mailbox if it does not exist? * DEFAULT: No. * * @return Horde_Imap_Client_Ids The UIDs of the appended messages. * * @throws Horde_Imap_Client_Exception */ public function append($mailbox, $data, array $options = array()) { $this->login(); $mailbox = Horde_Imap_Client_Mailbox::get($mailbox); $ret = $this->_append($mailbox, $data, $options); if ($ret instanceof Horde_Imap_Client_Ids) { return $ret; } $uids = $this->getIdsOb(); while (list(, $val) = each($data)) { if (is_string($val['data'])) { $text = $val['data']; } elseif (is_resource($val['data'])) { $text = ''; rewind($val['data']); while (!feof($val['data'])) { $text .= fread($val['data'], 512); if (preg_match("/\n\r{2,}/", $text)) { break; } } } $headers = Horde_Mime_Headers::parseHeaders($text); $msgid = $headers->getValue('message-id'); if ($msgid) { $search_query = new Horde_Imap_Client_Search_Query(); $search_query->headerText('Message-ID', $msgid); $uidsearch = $this->search($mailbox, $search_query); $uids->add($uidsearch['match']); } } return $uids; }
/** * Retrieves a complete message. * * @param string $folder The folder to fetch the messages from. * @param array $uid The message UID. * * @return array The message encapsuled as an array that contains a * Horde_Mime_Headers and a Horde_Mime_Part object. */ public function fetchComplete($folder, $uid) { $msg = $this->getBackend()->handlePartBody($this->encodePath($folder), $uid, true, '', null, false); if ($this->getBackend()->errornum != 0) { throw new Horde_Kolab_Storage_Exception(sprintf(Horde_Kolab_Storage_Translation::t("Failed fetching message %s in folder %s.") . ' ' . Horde_Kolab_Storage_Translation::t("Error: %s"), $uid, $folder, $this->getBackend()->error)); } return array(Horde_Mime_Headers::parseHeaders($msg), Horde_Mime_Part::parseMessage(Horde_Mime_Part::getRawPartText($msg, 'body', 0))); }
public function fetchComplete($folder, $uid) { $this->select($folder); if (isset($this->_selected['mails'][$uid]['stream'])) { rewind($this->_selected['mails'][$uid]['stream']); $msg = stream_get_contents($this->_selected['mails'][$uid]['stream']); return array(Horde_Mime_Headers::parseHeaders($msg), Horde_Mime_Part::parseMessage($msg)); } else { throw new Horde_Kolab_Storage_Exception(sprintf('No message %s in folder %s!', $uid, $folder)); } }
/** * Append message(s) to a mailbox. * * @param mixed $mailbox The mailbox to append the message(s) to. Either * a Horde_Imap_Client_Mailbox object or a string * (UTF-8). * @param array $data The message data to append, along with * additional options. An array of arrays with * each embedded array having the following * entries: * <pre> * - data: (mixed) The data to append. If a string or a stream resource, * this will be used as the entire contents of a single message. * If an array, will catenate all given parts into a single * message. This array contains one or more arrays with * two keys: * - t: (string) Either 'url' or 'text'. * - v: (mixed) If 't' is 'url', this is the IMAP URL to the message * part to append. If 't' is 'text', this is either a string or * resource representation of the message part data. * DEFAULT: NONE (entry is MANDATORY) * - flags: (array) An array of flags/keywords to set on the appended * message. * DEFAULT: Only the \Recent flag is set. * - internaldate: (DateTime) The internaldate to set for the appended * message. * DEFAULT: internaldate will be the same date as when * the message was appended. * </pre> * @param array $options Additonal options: * <pre> * - create: (boolean) Try to create $mailbox if it does not exist? * DEFAULT: No. * </pre> * * @return Horde_Imap_Client_Ids The UIDs of the appended messages. * * @throws Horde_Imap_Client_Exception */ public function append($mailbox, $data, array $options = array()) { $this->login(); $mailbox = Horde_Imap_Client_Mailbox::get($mailbox); $ret = $this->_append($mailbox, $data, $options); if ($ret instanceof Horde_Imap_Client_Ids) { return $ret; } $uids = $this->getIdsOb(); while (list(, $val) = each($data)) { if (is_resource($val['data'])) { rewind($val['data']); } $uids->add($this->_getUidByMessageId($mailbox, Horde_Mime_Headers::parseHeaders($val['data'])->getHeader('Message-ID'))); } return $uids; }
/** * Attempts to obtain the raw text of a MIME part. * * @param mixed $text The full text of the MIME message. The text is * assumed to be MIME data (no MIME-Version checking * is performed). It can be either a stream or a * string. * @param string $type Either 'header' or 'body'. * @param string $id The MIME ID. * * @return string The raw text. * @throws Horde_Mime_Exception */ public static function getRawPartText($text, $type, $id) { /* Mini-hack to get a blank Horde_Mime part so we can call * replaceEOL(). From an API perspective, getRawPartText() should be * static since it is not working on MIME part data. */ $part = new Horde_Mime_Part(); $rawtext = $part->replaceEOL($text, self::RFC_EOL); /* We need to carry around the trailing "\n" because this is needed * to correctly find the boundary string. */ $hdr_pos = self::_findHeader($rawtext, self::RFC_EOL); $curr_pos = $hdr_pos + 3; if ($id == 0) { switch ($type) { case 'body': return substr($rawtext, $curr_pos + 1); case 'header': return trim(substr($rawtext, 0, $hdr_pos)); } } $hdr_ob = Horde_Mime_Headers::parseHeaders(trim(substr($rawtext, 0, $hdr_pos))); /* If this is a message/rfc822, pass the body into the next loop. * Don't decrement the ID here. */ if (($ct = $hdr_ob['Content-Type']) && $ct == 'message/rfc822') { return self::getRawPartText(substr($rawtext, $curr_pos + 1), $type, $id); } $base_pos = strpos($id, '.'); $orig_id = $id; if ($base_pos !== false) { $id = substr($id, $base_pos + 1); $base_pos = substr($orig_id, 0, $base_pos); } else { $base_pos = $id; $id = 0; } if ($ct && !isset($ct->params['boundary'])) { if ($orig_id == '1') { return substr($rawtext, $curr_pos + 1); } throw new Horde_Mime_Exception('Could not find MIME part.'); } $b_find = self::_findBoundary($rawtext, $curr_pos, $ct->params['boundary'], $base_pos); if (!isset($b_find[$base_pos])) { throw new Horde_Mime_Exception('Could not find MIME part.'); } return self::getRawPartText(substr($rawtext, $b_find[$base_pos]['start'], $b_find[$base_pos]['length'] - 1), $type, $id); }
/** * Return the message headers. * * @return Horde_Mime_Headers The header object. */ public function getHeaders() { if (!empty($this->_header_text)) { $hdr_text = $this->_header_text; } else { $this->_stream->rewind(); $hdr_text = $this->_stream->substring(0, $this->_hdr_pos); } return Horde_Mime_Headers::parseHeaders($hdr_text); }
public function testParsingAndSending() { $rfc822_in = 'Subject: Test From: mike@theupstairsroom.com Content-Type: text/plain; charset=us-ascii Message-Id: <*****@*****.**> Date: Sat, 17 Mar 2012 13:29:10 -0400 To: =?utf-8?Q?Mich=C3=B1el_Rubinsky?= <*****@*****.**> Content-Transfer-Encoding: 7bit Mime-Version: 1.0 (1.0) Testing 123 -- Mike'; $headers = Horde_Mime_Headers::parseHeaders($rfc822_in); $message_part = Horde_Mime_Part::parseMessage($rfc822_in); $this->assertEquals('Michñel Rubinsky <*****@*****.**>', $headers->getValue('To')); $mail = new Horde_Mime_Mail(); $part = $message_part->getPart($message_part->findBody()); $body = $part->getContents(); $this->assertEquals('Testing 123 -- Mike', $body); $mail->addHeaders($headers->toArray()); $dummy = new Horde_Mail_Transport_Mock(); $mail->send($dummy); }