Attempts to build a Horde_Mime_Part object from message text.
public static parseMessage ( string $text, array $opts = [] ) : Horde_Mime_Part | ||
$text | string | The text of the MIME message. |
$opts | array | Additional options: - forcemime: (boolean) If true, the message data is assumed to be MIME data. If not, a MIME-Version header must exist (RFC 2045 [4]) to be parsed as a MIME message. DEFAULT: false - level: (integer) Current nesting level of the MIME data. DEFAULT: 0 - no_body: (boolean) If true, don't set body contents of parts (since 2.2.0). DEFAULT: false |
return | Horde_Mime_Part | A MIME Part object. |
/** * @requires extension bcmath */ public function testvTodo() { $tnef = Horde_Compress::factory('Tnef'); $mime = Horde_Mime_Part::parseMessage(file_get_contents(__DIR__ . '/fixtures/tnef_task.eml')); try { $tnef_data = $tnef->decompress($mime->getPart(2)->getContents()); } catch (Horde_Mapi_Exception $e) { $this->markTestSkipped('Horde_Mapi is not available'); } catch (Horde_Compress_Exception $e) { var_dump($e); } // Test the generated iCalendar. $iCal = new Horde_Icalendar(); if (!$iCal->parsevCalendar($tnef_data[0]['stream'])) { throw new Horde_Compress_Exception(_("There was an error importing the iCalendar data.")); } $this->assertEquals($iCal->getAttribute('METHOD'), 'REQUEST'); $components = $iCal->getComponents(); if (count($components) == 0) { throw new Horde_Compress_Exception(_("No iCalendar data was found.")); } $vTodo = current($components); $this->assertEquals($vTodo->getAttribute('SUMMARY'), 'Test Task'); $this->assertEquals($vTodo->getAttribute('UID'), 'EDF71E6FA6FB69A79D79FE1D6DCDBBD300000000DFD9B6FB'); $this->assertEquals($vTodo->getAttribute('ATTENDEE'), 'Michael Rubinsky <*****@*****.**>'); $params = $vTodo->getAttribute('ATTENDEE', true); if (!$params) { throw new Horde_Compress_Exception('Could not find expected parameters.'); } $this->assertEquals($params[0]['ROLE'], 'REQ-PARTICIPANT'); $this->assertEquals($vTodo->getAttribute('ORGANIZER'), 'mailto: mike@theupstairsroom.com'); }
/** * @dataProvider message_inbound_handler_trim_testprovider */ public function test_messageinbound_handler_trim($file, $source, $expectedplain, $expectedhtml) { $this->resetAfterTest(); $mime = Horde_Mime_Part::parseMessage($source); if ($plainpartid = $mime->findBody('plain')) { $messagedata = new stdClass(); $messagedata->plain = $mime->getPart($plainpartid)->getContents(); $messagedata->html = ''; list($message, $format) = test_handler::remove_quoted_text($messagedata); list($message, $expectedplain) = preg_replace("#\r\n#", "\n", array($message, $expectedplain)); // Normalise line endings on both strings. $this->assertEquals($expectedplain, $message); $this->assertEquals(FORMAT_PLAIN, $format); } if ($htmlpartid = $mime->findBody('html')) { $messagedata = new stdClass(); $messagedata->plain = ''; $messagedata->html = $mime->getPart($htmlpartid)->getContents(); list($message, $format) = test_handler::remove_quoted_text($messagedata); // Normalise line endings on both strings. list($message, $expectedhtml) = preg_replace("#\r\n#", "\n", array($message, $expectedhtml)); $this->assertEquals($expectedhtml, $message); $this->assertEquals(FORMAT_PLAIN, $format); } }
public function testIconvHtmlMessage() { $conn = $this->getMockBuilder('Horde_Imap_Client_Socket')->disableOriginalConstructor()->setMethods(['fetch'])->getMock(); $urlGenerator = $this->getMockBuilder('\\OCP\\IURLGenerator')->disableOriginalConstructor()->getMock(); //linkToRoute 'mail.proxy.proxy' $urlGenerator->expects($this->any())->method('linkToRoute')->will($this->returnCallback(function ($url) { return "https://docs.example.com/server/go.php?to={$url}"; })); $htmlService = new \OCA\Mail\Service\Html($urlGenerator); // mock first fetch $firstFetch = new Horde_Imap_Client_Data_Fetch(); $firstPart = Horde_Mime_Part::parseMessage(file_get_contents(__DIR__ . '/data/mail-message-123.txt'), ['level' => 1]); $firstFetch->setStructure($firstPart); $firstFetch->setBodyPart(1, $firstPart->getPart(1)->getContents()); $firstFetch->setBodyPart(2, $firstPart->getPart(2)->getContents()); $firstResult = new Horde_Imap_Client_Fetch_Results(); $firstResult[123] = $firstFetch; $conn->expects($this->any())->method('fetch')->willReturn($firstResult); $message = new \OCA\Mail\Message($conn, 'INBOX', 123, null, true, $htmlService); $htmlBody = $message->getHtmlBody(0, 0, 123, function () { return null; }); $this->assertTrue(strlen($htmlBody) > 1000); $plainTextBody = $message->getPlainBody(); $this->assertTrue(strlen($plainTextBody) > 1000); }
/** * Test creating a Horde_ActiveSync_Message_MeetingRequest from a MIME Email */ public function testInvite() { $this->markTestIncomplete('Has issues on 32bit systems'); $fixture = file_get_contents(__DIR__ . '/fixtures/invitation_one.eml'); $mime = Horde_Mime_Part::parseMessage($fixture); $msg = new Horde_ActiveSync_Message_MeetingRequest(); foreach ($mime->contentTypeMap() as $id => $type) { if ($type == 'text/calendar') { $vcal = new Horde_Icalendar(); $vcal->parseVcalendar($mime->getPart($id)->getContents()); $msg->fromvEvent($vcal); break; } } $stream = fopen('php://memory', 'wb+'); $encoder = new Horde_ActiveSync_Wbxml_Encoder($stream); $msg->encodeStream($encoder); rewind($stream); $results = stream_get_contents($stream); fclose($stream); $stream = fopen(__DIR__ . '/fixtures/meeting_request_one.wbxml', 'r+'); $expected = ''; // Using file_get_contents or even fread mangles the binary data for some // reason. while ($line = fgets($stream)) { $expected .= $line; } fclose($stream); $this->assertEquals($expected, $results); }
public function testHasiCalendar() { $fixture = file_get_contents(__DIR__ . '/fixtures/invitation_one.eml'); $mime = new Horde_ActiveSync_Mime(Horde_Mime_Part::parseMessage($fixture)); $this->assertEquals(true, $mime->hasAttachments()); $this->assertEquals(false, $mime->isSigned()); $this->assertEquals(true, (bool) $mime->hasiCalendar()); }
public function testReplace() { $part = Horde_Mime_Part::parseMessage(file_get_contents(__DIR__ . '/fixtures/related_msg.txt')); $related = new Horde_Mime_Related($part); $ob = $related->cidReplace($part['1']->getContents(), array($this, 'callbackTestReplace')); $body = $ob->dom->getElementsByTagName('body'); $this->assertEquals(1, $body->length); $this->assertEquals('2', $body->item(0)->getAttribute('background')); $body = $ob->dom->getElementsByTagName('img'); $this->assertEquals(1, $body->length); $this->assertEquals('3', $body->item(0)->getAttribute('src')); }
/** * 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) { $query = new Horde_Imap_Client_Fetch_Query(); $query->fullText(); try { $ret = $this->getBackend()->fetch($folder, $query, array('ids' => new Horde_Imap_Client_Ids($uid))); if (!isset($ret[$uid])) { throw new Horde_Kolab_Storage_Exception(sprintf(Horde_Kolab_Storage_Translation::t("Failed fetching message %s in folder %s."), $uid, $folder)); } $msg = $ret[$uid]->getFullMsg(); } 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 array(Horde_Mime_Headers::parseHeaders($msg), Horde_Mime_Part::parseMessage($msg)); }
private function _getMimeMessage() { $mail = $this->_getMail(); return Horde_Mime_Part::parseMessage($mail); }
/** * @throws Horde_Imap_Client_Exception_NoSupportPop3 */ protected function _fetch(Horde_Imap_Client_Fetch_Results $results, Horde_Imap_Client_Fetch_Query $query, $options) { // These options are not supported by this driver. if (!empty($options['changedsince']) || !empty($options['vanished'])) { throw new Horde_Imap_Client_Exception_NoSupportPop3('Fetch options'); } // Grab sequence IDs - IDs will always be the message number for // POP3 fetch commands. $seq_ids = $this->_getSeqIds($options['ids']); if (empty($seq_ids)) { return; } $lookup = $options['ids']->sequence ? array_combine($seq_ids, $seq_ids) : $this->_pop3Cache('uidl'); foreach ($query as $type => $c_val) { switch ($type) { case Horde_Imap_Client::FETCH_FULLMSG: foreach ($seq_ids as $id) { $tmp = $this->_pop3Cache('msg', $id); if (empty($c_val['start']) && empty($c_val['length'])) { $tmp2 = fopen('php://temp', 'r+'); stream_copy_to_stream($tmp, $tmp2, empty($c_val['length']) ? -1 : $c_val['length'], empty($c_val['start']) ? 0 : $c_val['start']); $results->get($lookup[$id])->setFullMsg($tmp2); } else { $results->get($lookup[$id])->setFullMsg($tmp); } } break; case Horde_Imap_Client::FETCH_HEADERTEXT: // Ignore 'peek' option foreach ($c_val as $key => $val) { foreach ($seq_ids as $id) { /* Message header can be retrieved via TOP, if the * command is available. */ try { $tmp = $key == 0 ? $this->_pop3Cache('hdr', $id) : Horde_Mime_Part::getRawPartText(stream_get_contents($this->_pop3Cache('msg', $id)), 'header', $key); $results->get($lookup[$id])->setHeaderText($key, $this->_processString($tmp, $c_val)); } catch (Horde_Mime_Exception $e) { } } } break; case Horde_Imap_Client::FETCH_BODYTEXT: // Ignore 'peek' option foreach ($c_val as $key => $val) { foreach ($seq_ids as $id) { try { $results->get($lookup[$id])->setBodyText($key, $this->_processString(Horde_Mime_Part::getRawPartText(stream_get_contents($this->_pop3Cache('msg', $id)), 'body', $key), $val)); } catch (Horde_Mime_Exception $e) { } } } break; case Horde_Imap_Client::FETCH_MIMEHEADER: // Ignore 'peek' option foreach ($c_val as $key => $val) { foreach ($seq_ids as $id) { try { $results->get($lookup[$id])->setMimeHeader($key, $this->_processString(Horde_Mime_Part::getRawPartText(stream_get_contents($this->_pop3Cache('msg', $id)), 'header', $key), $val)); } catch (Horde_Mime_Exception $e) { } } } break; case Horde_Imap_Client::FETCH_BODYPART: // Ignore 'decode', 'peek' foreach ($c_val as $key => $val) { foreach ($seq_ids as $id) { try { $results->get($lookup[$id])->setBodyPart($key, $this->_processString(Horde_Mime_Part::getRawPartText(stream_get_contents($this->_pop3Cache('msg', $id)), 'body', $key), $val)); } catch (Horde_Mime_Exception $e) { } } } break; case Horde_Imap_Client::FETCH_HEADERS: // Ignore 'length', 'peek' foreach ($seq_ids as $id) { $ob = $this->_pop3Cache('hdrob', $id); foreach ($c_val as $key => $val) { $tmp = $ob; if (empty($val['notsearch'])) { $tmp2 = $tmp->toArray(array('nowrap' => true)); foreach (array_keys($tmp2) as $hdr) { if (!in_array($hdr, $val['headers'])) { $tmp->removeHeader($hdr); } } } else { foreach ($val['headers'] as $hdr) { $tmp->removeHeader($hdr); } } $results->get($lookup[$id])->setHeaders($key, $tmp); } } break; case Horde_Imap_Client::FETCH_STRUCTURE: foreach ($seq_ids as $id) { if ($ptr = $this->_pop3Cache('msg', $id)) { try { $results->get($lookup[$id])->setStructure(Horde_Mime_Part::parseMessage(stream_get_contents($ptr))); } catch (Horde_Exception $e) { } } } break; case Horde_Imap_Client::FETCH_ENVELOPE: foreach ($seq_ids as $id) { $tmp = $this->_pop3Cache('hdrob', $id); $results->get($lookup[$id])->setEnvelope(array('date' => $tmp->getValue('date'), 'subject' => $tmp->getValue('subject'), 'from' => $tmp->getOb('from'), 'sender' => $tmp->getOb('sender'), 'reply_to' => $tmp->getOb('reply-to'), 'to' => $tmp->getOb('to'), 'cc' => $tmp->getOb('cc'), 'bcc' => $tmp->getOb('bcc'), 'in_reply_to' => $tmp->getValue('in-reply-to'), 'message_id' => $tmp->getValue('message-id'))); } break; case Horde_Imap_Client::FETCH_IMAPDATE: foreach ($seq_ids as $id) { $tmp = $this->_pop3Cache('hdrob', $id); $results->get($lookup[$id])->setImapDate($tmp->getValue('date')); } break; case Horde_Imap_Client::FETCH_SIZE: $sizelist = $this->_pop3Cache('size'); foreach ($seq_ids as $id) { $results->get($lookup[$id])->setSize($sizelist[$id]); } break; case Horde_Imap_Client::FETCH_SEQ: foreach ($seq_ids as $id) { $results->get($lookup[$id])->setSeq($id); } break; case Horde_Imap_Client::FETCH_UID: $uidllist = $this->_pop3Cache('uidl'); foreach ($seq_ids as $id) { if (isset($uidllist[$id])) { $results->get($lookup[$id])->setUid($uidllist[$id]); } } break; } } $this->_updateCache($results, array('seq' => $options['ids']->sequence)); }
/** * Fetch data for a given fetch query. * * @param Horde_Imap_Client_Fetch_Results $results Fetch results. * @param array $options Fetch query options. */ protected function _fetchCmd(Horde_Imap_Client_Fetch_Results $results, $options) { // Grab sequence IDs - IDs will always be the message number for // POP3 fetch commands. $seq_ids = $this->_getSeqIds($options['ids']); if (empty($seq_ids)) { return; } $lookup = $options['ids']->sequence ? array_combine($seq_ids, $seq_ids) : $this->_pop3Cache('uidl'); foreach ($options['_query'] as $type => $c_val) { switch ($type) { case Horde_Imap_Client::FETCH_FULLMSG: foreach ($seq_ids as $id) { $tmp = $this->_pop3Cache('msg', $id); if (empty($c_val['start']) && empty($c_val['length'])) { $tmp2 = fopen('php://temp', 'r+'); stream_copy_to_stream($tmp, $tmp2, empty($c_val['length']) ? -1 : $c_val['length'], empty($c_val['start']) ? 0 : $c_val['start']); $results->get($lookup[$id])->setFullMsg($tmp2); } else { $results->get($lookup[$id])->setFullMsg($tmp); } } break; case Horde_Imap_Client::FETCH_HEADERTEXT: // Ignore 'peek' option foreach ($c_val as $key => $val) { foreach ($seq_ids as $id) { /* Message header can be retrieved via TOP, if the * command is available. */ try { $tmp = $key == 0 ? $this->_pop3Cache('hdr', $id) : Horde_Mime_Part::getRawPartText(stream_get_contents($this->_pop3Cache('msg', $id)), 'header', $key); $results->get($lookup[$id])->setHeaderText($key, $this->_processString($tmp, $c_val)); } catch (Horde_Mime_Exception $e) { } } } break; case Horde_Imap_Client::FETCH_BODYTEXT: // Ignore 'peek' option foreach ($c_val as $key => $val) { foreach ($seq_ids as $id) { try { $results->get($lookup[$id])->setBodyText($key, $this->_processString(Horde_Mime_Part::getRawPartText(stream_get_contents($this->_pop3Cache('msg', $id)), 'body', $key), $val)); } catch (Horde_Mime_Exception $e) { } } } break; case Horde_Imap_Client::FETCH_MIMEHEADER: // Ignore 'peek' option foreach ($c_val as $key => $val) { foreach ($seq_ids as $id) { try { $results->get($lookup[$id])->setMimeHeader($key, $this->_processString(Horde_Mime_Part::getRawPartText(stream_get_contents($this->_pop3Cache('msg', $id)), 'header', $key), $val)); } catch (Horde_Mime_Exception $e) { } } } break; case Horde_Imap_Client::FETCH_BODYPART: // Ignore 'decode', 'peek' foreach ($c_val as $key => $val) { foreach ($seq_ids as $id) { try { $results->get($lookup[$id])->setBodyPart($key, $this->_processString(Horde_Mime_Part::getRawPartText(stream_get_contents($this->_pop3Cache('msg', $id)), 'body', $key), $val)); } catch (Horde_Mime_Exception $e) { } } } break; case Horde_Imap_Client::FETCH_HEADERS: // Ignore 'length', 'peek' foreach ($seq_ids as $id) { $ob = $this->_pop3Cache('hdrob', $id); foreach ($c_val as $key => $val) { $tmp = $ob; if (empty($val['notsearch'])) { $tmp2 = $tmp->toArray(array('nowrap' => true)); foreach (array_keys($tmp2) as $hdr) { if (!in_array($hdr, $val['headers'])) { unset($tmp[$hdr]); } } } else { foreach ($val['headers'] as $hdr) { unset($tmp[$hdr]); } } $results->get($lookup[$id])->setHeaders($key, $tmp); } } break; case Horde_Imap_Client::FETCH_STRUCTURE: foreach ($seq_ids as $id) { if ($ptr = $this->_pop3Cache('msg', $id)) { try { $results->get($lookup[$id])->setStructure(Horde_Mime_Part::parseMessage(stream_get_contents($ptr), array('no_body' => true))); } catch (Horde_Exception $e) { } } } break; case Horde_Imap_Client::FETCH_ENVELOPE: foreach ($seq_ids as $id) { $tmp = $this->_pop3Cache('hdrob', $id); $results->get($lookup[$id])->setEnvelope(array('date' => $tmp['Date'], 'subject' => $tmp['Subject'], 'from' => ($h = $tmp['From']) ? $h->getAddressList(true) : null, 'sender' => ($h = $tmp['Sender']) ? $h->getAddressList(true) : null, 'reply_to' => ($h = $tmp['Reply-to']) ? $h->getAddressList(true) : null, 'to' => ($h = $tmp['To']) ? $h->getAddressList(true) : null, 'cc' => ($h = $tmp['Cc']) ? $h->getAddressList(true) : null, 'bcc' => ($h = $tmp['Bcc']) ? $h->getAddressList(true) : null, 'in_reply_to' => $tmp['In-Reply-To'], 'message_id' => $tmp['Message-ID'])); } break; case Horde_Imap_Client::FETCH_IMAPDATE: foreach ($seq_ids as $id) { $tmp = $this->_pop3Cache('hdrob', $id); $results->get($lookup[$id])->setImapDate($tmp['Date']); } break; case Horde_Imap_Client::FETCH_SIZE: $sizelist = $this->_pop3Cache('size'); foreach ($seq_ids as $id) { $results->get($lookup[$id])->setSize($sizelist[$id]); } break; case Horde_Imap_Client::FETCH_SEQ: foreach ($seq_ids as $id) { $results->get($lookup[$id])->setSeq($id); } break; case Horde_Imap_Client::FETCH_UID: $uidllist = $this->_pop3Cache('uidl'); foreach ($seq_ids as $id) { if (isset($uidllist[$id])) { $results->get($lookup[$id])->setUid($uidllist[$id]); } } break; } } }
/** * Parse signed data. * * @param boolean $sig_only Only do signature checking? * * @return mixed See self::_getEmbeddedMimeParts(). */ protected function _parseSignedData($sig_only = false) { $partlist = array_keys($this->_mimepart->contentTypeMap()); $base_id = reset($partlist); $data_id = next($partlist); $sig_id = Horde_Mime::mimeIdArithmetic($data_id, 'next'); /* Initialize inline data. */ $status = new IMP_Mime_Status(_("The data in this part has been digitally signed via S/MIME.")); $status->icon('mime/encryption.png', 'S/MIME'); $cache = $this->getConfigParam('imp_contents')->getViewCache(); $cache->smime[$base_id] = array('sig' => $sig_id, 'status' => $status, 'wrap' => 'mimePartWrap'); if (!$GLOBALS['prefs']->getValue('use_smime')) { $status->addText(_("S/MIME support is not enabled so the digital signature is unable to be verified.")); return null; } /* Sanity checking to make sure MIME structure is correct. */ if (!in_array($sig_id, $partlist)) { $status->action(IMP_Mime_Status::ERROR); $cache->smime[$base_id]['wrap'] = 'mimePartWrapInvalid'; $status->addText(_("Invalid S/MIME data.")); /* This will suppress displaying the invalid part. */ $cache->smime[$base_id]['sig'] = $data_id; return null; } $imp_contents = $this->getConfigParam('imp_contents'); $stream = $imp_contents->isEmbedded($base_id) ? $this->_mimepart->getMetadata('imp-smime-decrypt')->stream : $this->_getPartStream($base_id); $raw_text = $this->_mimepart->replaceEOL($stream, Horde_Mime_Part::RFC_EOL); $this->_initSmime(); $sig_result = null; if ($GLOBALS['prefs']->getValue('smime_verify') || $GLOBALS['injector']->getInstance('Horde_Variables')->smime_verify_msg) { try { $sig_result = $this->_impsmime->verifySignature($raw_text); if ($sig_result->verify) { $status->action(IMP_Mime_Status::SUCCESS); } else { $status->action(IMP_Mime_Status::WARNING); } $cache->smime[$base_id]['wrap'] = 'mimePartWrapValid'; $email = is_array($sig_result->email) ? implode(', ', $sig_result->email) : $sig_result->email; $status->addText($sig_result->msg); if (!empty($sig_result->cert)) { $cert = $this->_impsmime->parseCert($sig_result->cert); if (isset($cert['certificate']['subject']['CommonName']) && strcasecmp($email, $cert['certificate']['subject']['CommonName']) !== 0) { $email = $cert['certificate']['subject']['CommonName'] . ' (' . trim($email) . ')'; } } if (!empty($sig_result->cert) && isset($sig_result->email) && $GLOBALS['registry']->hasMethod('contacts/addField') && $GLOBALS['prefs']->getValue('add_source')) { $status->addText(sprintf(_("Sender: %s"), $imp_contents->linkViewJS($this->_mimepart, 'view_attach', htmlspecialchars(strlen($email) ? $email : $sig_result->email), array('jstext' => _("View certificate details"), 'params' => array('mode' => IMP_Contents::RENDER_INLINE, 'view_smime_key' => 1))))); try { $this->_impsmime->getPublicKey($sig_result->email); } catch (Horde_Exception $e) { $imple = $GLOBALS['injector']->getInstance('Horde_Core_Factory_Imple')->create('IMP_Ajax_Imple_ImportEncryptKey', array('mime_id' => $base_id, 'muid' => strval($imp_contents->getIndicesOb()), 'type' => 'smime')); $status->addText(Horde::link('#', '', '', '', '', '', '', array('id' => $imple->getDomId())) . _("Save the certificate to your Address Book.") . '</a>'); } } elseif (strlen($email)) { $status->addText(sprintf(_("Sender: %s"), htmlspecialchars($email))); } } catch (Horde_Exception $e) { $status->action(IMP_Mime_Status::ERROR); $cache->smime[$base_id]['wrap'] = 'mimePartWrapInvalid'; $status->addText($e->getMessage()); } } else { switch ($GLOBALS['registry']->getView()) { case Horde_Registry::VIEW_BASIC: $status->addText(Horde::link(Horde::selfUrlParams()->add('smime_verify_msg', 1)) . _("Click HERE to verify the data.") . '</a>'); break; case Horde_Registry::VIEW_DYNAMIC: $status->addText(Horde::link('#', '', 'smimeVerifyMsg') . _("Click HERE to verify the data.") . '</a>'); break; } } if ($sig_only) { return; } $subpart = $imp_contents->getMIMEPart($sig_id); if (empty($subpart)) { try { $msg_data = $this->_impsmime->extractSignedContents($raw_text); $subpart = Horde_Mime_Part::parseMessage($msg_data, array('forcemime' => true)); } catch (Horde_Exception $e) { $status->addText($e->getMessage()); return null; } } return $subpart; }
/** * 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)))); }
/** * 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; }
/** * Rebuilds $part and forces it to be a base64 encoded * application/octet-stream part. * * @param Horde_Mime_Part $part The MIME part. */ protected function _reEncodeMessageAttachment(Horde_Mime_Part $part) { $new_part = Horde_Mime_Part::parseMessage($part->getContents()); $part->setContents($new_part->getContents(array('stream' => true)), array('encoding' => self::ENCODE_BINARY)); $part->setTransferEncoding('base64', array('send' => true)); }
public function testBug13117() { $msg = file_get_contents(__DIR__ . '/fixtures/bug13117.txt'); $part = Horde_Mime_Part::parseMessage($msg); $this->assertTrue(isset($part['2'])); $this->assertTrue(isset($part['2.0'])); $this->assertTrue(isset($part['2.1'])); $this->assertFalse(isset($part['2.2'])); $multipart = $part['2.0']; $multipart->addPart(new Horde_Mime_Part()); $multipart->buildMimeIds('2.0'); $this->assertTrue(isset($part['2'])); $this->assertTrue(isset($part['2.0'])); $this->assertTrue(isset($part['2.1'])); $this->assertTrue(isset($part['2.2'])); }
/** * Retrieves a bodypart for the given message ID and mime part ID. * * @param string $folder The folder to fetch the messages from. * @param array $uid The message UID. * @param array $id The mime part ID. * * @return resource The body part, as a stream resource. */ public function fetchBodypart($folder, $uid, $id) { $this->select($folder); if (isset($this->_selected['mails'][$uid]['parts'][$id])) { if (isset($this->_selected['mails'][$uid]['parts'][$id]['file'])) { return fopen($this->_selected['mails'][$uid]['parts'][$id]['file'], 'r'); } } elseif (isset($this->_selected['mails'][$uid]['stream'])) { rewind($this->_selected['mails'][$uid]['stream']); return Horde_Mime_Part::parseMessage(stream_get_contents($this->_selected['mails'][$uid]['stream']))->getPart($id)->getContents(array('stream' => true)); } throw new Horde_Kolab_Storage_Exception(sprintf('No such part %s for message uid %s in folder %s!', $id, $uid, $folder)); }
public function testMimeMessageWithNoContentType() { $msg = file_get_contents(__DIR__ . '/fixtures/sample_msg4.txt'); $part = Horde_Mime_Part::parseMessage($msg); $this->assertEquals('text/plain', $part->getType()); $this->assertEquals('us-ascii', $part->getCharset()); }
public function append($folder, $mail_string, $flag) { $text = Horde_Mime_Part::parseMessage($mail_string); return $this->imap_imp->append($folder, array(array('data' => $mail_string, 'flags' => array(Horde_Imap_Client::FLAG_SEEN))), array('create' => false)); }
/** * Sign a MIME part using S/MIME. This produces S/MIME Version 3.2 * compatible data (see RFC 5751 [3.4]). * * @param Horde_Mime_Part $mime_part The object to sign. * @param array $params The parameters required for signing. * * @return Horde_Mime_Part A signed MIME part object. * @throws Horde_Crypt_Exception */ public function signMIMEPart($mime_part, $params) { /* Sign the part as a message */ $message = $this->encrypt($mime_part->toString(array('headers' => true, 'canonical' => true)), $params); /* Break the result into its components */ $mime_message = Horde_Mime_Part::parseMessage($message, array('forcemime' => true)); $smime_sign = $mime_message->getPart('2'); $smime_sign->setDescription(Horde_Crypt_Translation::t("S/MIME Signature")); $smime_sign->setTransferEncoding('base64', array('send' => true)); $smime_part = new Horde_Mime_Part(); $smime_part->setType('multipart/signed'); $smime_part->setContents("This is a cryptographically signed message in MIME format.\n"); $smime_part->setContentTypeParameter('protocol', 'application/pkcs7-signature'); // Per RFC 5751 [3.4.3.2], 'sha1' has been deprecated for 'sha-1'. $smime_part->setContentTypeParameter('micalg', 'sha-1'); $smime_part->addPart($mime_part); $smime_part->addPart($smime_sign); return $smime_part; }
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')); }
public function setUp() { $this->_part = Horde_Mime_Part::parseMessage(file_get_contents(__DIR__ . '/fixtures/related_msg.txt')); $this->_relatedOb = new Horde_Mime_Related($this->_part); }
/** * 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())); } }
/** * If this MIME part can contain embedded MIME part(s), and those part(s) * exist, return a representation of that data. * * @return mixed A Horde_Mime_Part object representing the embedded data. * Returns null if no embedded MIME part(s) exist. */ protected function _getEmbeddedMimeParts() { $id = $this->_mimepart->getContentTypeParameter('id'); $number = $this->_mimepart->getContentTypeParameter('number'); $total = $this->_mimepart->getContentTypeParameter('total'); if (is_null($id) || is_null($number) || is_null($total)) { return null; } /* Perform the search to find the other parts of the message. */ $query = new Horde_Imap_Client_Search_Query(); $query->headerText('Content-Type', $id); $indices = $this->getConfigParam('imp_contents')->getMailbox()->runSearchQuery($query); /* If not able to find the other parts of the message, prepare a * status message. */ $msg_count = count($indices); if ($msg_count != $total) { $status = new IMP_Mime_Status($this->_mimepart, sprintf(_("Cannot display message - found only %s of %s parts of this message in the current mailbox."), $msg_count, $total)); $status->action(IMP_Mime_Status::ERROR); $cache = $this->getConfigParam('imp_contents')->getViewCache(); $cache->partial[$this->_mimepart->getMimeId()] = $status; return null; } /* Get the contents of each of the parts. */ $parts = array(); foreach ($indices as $ob) { foreach ($ob->uids as $val) { /* No need to fetch the current part again. */ if ($val == $number) { $parts[$number] = $this->_mimepart->getContents(); } else { $ic = $GLOBALS['injector']->getInstance('IMP_Factory_Contents')->create($ob->mbox->getIndicesOb($val)); $parts[$ic->getMIMEMessage()->getContentTypeParameter('number')] = $ic->getBody(); } } } /* Sort the parts in numerical order. */ ksort($parts, SORT_NUMERIC); /* Combine the parts. */ $mime_part = Horde_Mime_Part::parseMessage(implode('', $parts), array('forcemime' => true)); return $mime_part === false ? null : $mime_part; }
/** * If this MIME part can contain embedded MIME part(s), and those part(s) * exist, return a representation of that data. * * @return mixed A Horde_Mime_Part object representing the embedded data. * Returns null if no embedded MIME part(s) exist. */ protected function _getEmbeddedMimeParts() { if ($this->_mimepart->getType() != 'multipart/encrypted') { return null; } $imp_contents = $this->getConfigParam('imp_contents'); $iterator = $this->_mimepart->partIterator(); $iterator->rewind(); $base_id = $iterator->current()->getMimeId(); $iterator->next(); $version_id = $iterator->current()->getMimeId(); $id_ob = new Horde_Mime_Id($version_id); $data_id = $id_ob->idArithmetic($id_ob::ID_NEXT); $status = new IMP_Mime_Status($this->_mimepart); $status->icon('mime/encryption.png', 'PGP'); $cache = $imp_contents->getViewCache(); $cache->pgp[$base_id] = array('status' => array($status), 'other' => array($version_id => null, $data_id => null), 'wrap' => ''); /* Is PGP active? */ if (!IMP_Pgp::enabled()) { $status->addText(_("The data in this part has been encrypted via PGP, however, PGP support is disabled so the message cannot be decrypted.")); return null; } /* PGP version information appears in the first MIME subpart. We * don't currently need to do anything with this information. The * encrypted data appears in the second MIME subpart. */ if (!($encrypted_part = $imp_contents->getMimePart($data_id))) { return null; } $encrypted_data = $encrypted_part->getContents(); $symmetric_pass = $personal_pass = null; /* Check if this a symmetrically encrypted message. */ try { $imp_pgp = $GLOBALS['injector']->getInstance('IMP_Pgp'); $symmetric = $imp_pgp->encryptedSymmetrically($encrypted_data); if ($symmetric) { $symmetric_id = $this->_getSymmetricID(); $symmetric_pass = $imp_pgp->getPassphrase('symmetric', $symmetric_id); if (is_null($symmetric_pass)) { $status->addText(_("The data in this part has been encrypted via PGP.")); /* Ask for the correct passphrase if this is encrypted * symmetrically. */ $imple = $GLOBALS['injector']->getInstance('Horde_Core_Factory_Imple')->create('IMP_Ajax_Imple_PassphraseDialog', array('params' => array('symmetricid' => $symmetric_id), 'type' => 'pgpSymmetric')); $status->addText(Horde::link('#', '', '', '', '', '', '', array('id' => $imple->getDomId())) . _("You must enter the passphrase used to encrypt this message to view it.") . '</a>'); return null; } } } catch (Horde_Exception $e) { Horde::log($e, 'INFO'); return null; } /* Check if this is a literal compressed message. */ try { $info = $imp_pgp->pgpPacketInformation($encrypted_data); } catch (Horde_Exception $e) { Horde::log($e, 'INFO'); return null; } $literal = !empty($info['literal']); if ($literal) { $status->addText(_("The data in this part has been compressed via PGP.")); } else { $status->addText(_("The data in this part has been encrypted via PGP.")); if (!$symmetric) { if ($imp_pgp->getPersonalPrivateKey()) { $personal_pass = $imp_pgp->getPassphrase('personal'); if (is_null($personal_pass)) { /* Ask for the private key's passphrase if this is * encrypted asymmetrically. */ $imple = $GLOBALS['injector']->getInstance('Horde_Core_Factory_Imple')->create('IMP_Ajax_Imple_PassphraseDialog', array('type' => 'pgpPersonal')); $status->addText(Horde::link('#', '', '', '', '', '', '', array('id' => $imple->getDomId())) . _("You must enter the passphrase for your PGP private key to view this message.") . '</a>'); return null; } } else { /* Output if there is no personal private key to decrypt * with. */ $status->addText(_("However, no personal private key exists so the message cannot be decrypted.")); return null; } } } try { if (!is_null($symmetric_pass)) { $decrypted_data = $imp_pgp->decryptMessage($encrypted_data, 'symmetric', array('passphrase' => $symmetric_pass, 'sender' => $this->_getSender()->bare_address)); } elseif (!is_null($personal_pass)) { $decrypted_data = $imp_pgp->decryptMessage($encrypted_data, 'personal', array('passphrase' => $personal_pass, 'sender' => $this->_getSender()->bare_address)); } else { $decrypted_data = $imp_pgp->decryptMessage($encrypted_data, 'literal'); } } catch (Horde_Exception $e) { $status->addText(_("The data in this part does not appear to be a valid PGP encrypted message. Error: ") . $e->getMessage()); if (!is_null($symmetric_pass)) { $imp_pgp->unsetPassphrase('symmetric', $this->_getSymmetricID()); return $this->_getEmbeddedMimeParts(); } return null; } $cache->pgp[$base_id]['wrap'] = 'mimePartWrapValid'; /* Check for combined encryption/signature data. */ if ($decrypted_data->result) { $sig_text = is_bool($decrypted_data->result) ? _("The data in this part has been digitally signed via PGP.") : $this->_textFilter($decrypted_data->result, 'text2html', array('parselevel' => Horde_Text_Filter_Text2html::NOHTML)); $status2 = new IMP_Mime_Status($this->_mimepart, $sig_text); $status2->action(IMP_Mime_Status::SUCCESS); $cache->pgp[$base_id]['status'][] = $status2; } /* Force armor data as text/plain data. */ if ($this->_mimepart->getMetadata(Horde_Crypt_Pgp_Parse::PGP_ARMOR)) { $decrypted_data->message = "Content-Type: text/plain\n\n" . $decrypted_data->message; } $new_part = Horde_Mime_Part::parseMessage($decrypted_data->message, array('forcemime' => true)); if ($new_part->getType() == 'multipart/signed') { $data = new Horde_Stream_Temp(); try { $data->add(Horde_Mime_Part::getRawPartText($decrypted_data->message, 'header', '1')); $data->add("\n\n"); $data->add(Horde_Mime_Part::getRawPartText($decrypted_data->message, 'body', '1')); } catch (Horde_Mime_Exception $e) { } $new_part->setMetadata(self::PGP_SIGN_ENC, $data->stream); $new_part->setContents($decrypted_data->message, array('encoding' => 'binary')); } return $new_part; }
/** * 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))); }
/** * 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); } }
public function testEnvelope() { setlocale(LC_MESSAGES, 'C'); $driver = new Horde_Kolab_Storage_Stub_Driver('user'); $folder = $this->getMock('Horde_Kolab_Storage_Folder'); $folder->expects($this->once())->method('getPath')->will($this->returnValue('INBOX')); $writer = $this->getMock('Horde_Kolab_Storage_Object_Writer'); $object = new Horde_Kolab_Storage_Object(); $object->setData(array('uid' => 'UID')); $object->setDriver($driver); $object->create($folder, $writer, 'event'); $this->assertContains('Content-Disposition: attachment; filename="Kolab Groupware Data"', $driver->messages['INBOX'][0]); $this->assertContains('Content-Type: multipart/mixed;', $driver->messages['INBOX'][0]); $this->assertContains('Content-Type: text/plain; name="Kolab Groupware Information"; charset=utf-8', $driver->messages['INBOX'][0]); $this->assertContains('Content-Disposition: inline; filename="Kolab Groupware Information"', $driver->messages['INBOX'][0]); $this->assertContains("This is a Kolab Groupware object. To view this object you will need an email client that understands the Kolab Groupware format. For a list of such email clients please visit http://www.kolab.org/content/kolab-clients", $driver->messages['INBOX'][0]); $this->assertContains('User-Agent: Horde_Kolab_Storage ' . Horde_Kolab_Storage::VERSION, $driver->messages['INBOX'][0]); $this->assertContains('Subject: UID', $driver->messages['INBOX'][0]); $this->assertContains('From: user', $driver->messages['INBOX'][0]); $this->assertContains('To: user', $driver->messages['INBOX'][0]); $this->assertContains('X-Kolab-Type: application/x-vnd.kolab.event', $driver->messages['INBOX'][0]); $this->assertContains('Content-Type: application/x-vnd.kolab.event; name=kolab.xml', $driver->messages['INBOX'][0]); $this->assertEquals(array(0 => 'multipart/mixed', 1 => 'text/plain', 2 => 'application/x-vnd.kolab.event'), Horde_Mime_Part::parseMessage($driver->messages['INBOX'][0])->contentTypeMap(true)); }
/** * 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) { return array(Horde_Mime_Headers::parseHeaders($this->messages[$folder][$uid]), Horde_Mime_Part::parseMessage($this->messages[$folder][$uid])); }
/** * Return a Mime object representing the entire message. * * @return Horde_Mime_Part The Mime object. */ public function getMimeObject() { $this->_stream->rewind(); $part = Horde_Mime_Part::parseMessage($this->_stream->getString()); $part->isBasePart(true); return $part; }
/** * Parse signed data. * * @param boolean $sig_only Only do signature checking? * * @return mixed See self::_getEmbeddedMimeParts(). */ protected function _parseSignedData($sig_only = false) { $iterator = $this->_mimepart->partIterator(); $iterator->rewind(); if (!($curr = $iterator->current())) { return null; } $base_id = $curr->getMimeId(); $iterator->next(); if (!($curr = $iterator->current())) { // application/pkcs-7-mime might be the base part. // See RFC 5751 3.4.2 $data_id = $base_id; } else { $data_id = $curr->getMimeId(); } $id_ob = new Horde_Mime_Id($data_id); $sig_id = $id_ob->idArithmetic($id_ob::ID_NEXT); /* Initialize inline data. */ $status = new IMP_Mime_Status($this->_mimepart, _("The data in this part has been digitally signed via S/MIME.")); $status->icon('mime/encryption.png', 'S/MIME'); $cache = $this->getConfigParam('imp_contents')->getViewCache(); $cache->smime[$base_id] = array('sig' => $sig_id, 'status' => $status, 'wrap' => 'mimePartWrap'); if (!IMP_Smime::enabled()) { $status->addText(_("S/MIME support is not enabled so the digital signature is unable to be verified.")); return null; } $imp_contents = $this->getConfigParam('imp_contents'); $stream = $imp_contents->isEmbedded($base_id) ? $this->_mimepart->getMetadata('imp-smime-decrypt')->stream : $this->_getPartStream($base_id); $raw_text = $this->_mimepart->replaceEOL($stream, Horde_Mime_Part::RFC_EOL); $this->_initSmime(); $sig_result = null; if ($GLOBALS['prefs']->getValue('smime_verify') || $GLOBALS['injector']->getInstance('Horde_Variables')->smime_verify_msg) { try { $sig_result = $this->_impsmime->verifySignature($raw_text); if ($sig_result->verify) { $status->action(IMP_Mime_Status::SUCCESS); } else { $status->action(IMP_Mime_Status::WARNING); } if (!is_array($sig_result->email)) { $sig_result->email = array($sig_result->email); } $email = implode(', ', $sig_result->email); $cache->smime[$base_id]['wrap'] = 'mimePartWrapValid'; $status->addText($sig_result->msg); if (!empty($sig_result->cert)) { $cert = $this->_impsmime->parseCert($sig_result->cert); if (isset($cert['certificate']['subject']['CommonName']) && strcasecmp($email, $cert['certificate']['subject']['CommonName']) !== 0) { $email = $cert['certificate']['subject']['CommonName'] . ' (' . trim($email) . ')'; } } if (!empty($sig_result->cert) && isset($sig_result->email) && $GLOBALS['registry']->hasMethod('contacts/addField') && $GLOBALS['prefs']->getValue('add_source')) { $status->addText(sprintf(_("Sender: %s"), $imp_contents->linkViewJS($this->_mimepart, 'view_attach', htmlspecialchars($email), array('jstext' => _("View certificate details"), 'params' => array('mode' => IMP_Contents::RENDER_INLINE, 'view_smime_key' => 1))))); foreach ($sig_result->email as $single_email) { try { $this->_impsmime->getPublicKey($single_email); } catch (Horde_Exception $e) { $imple = $GLOBALS['injector']->getInstance('Horde_Core_Factory_Imple')->create('IMP_Ajax_Imple_ImportEncryptKey', array('mime_id' => $base_id, 'muid' => strval($imp_contents->getIndicesOb()), 'type' => 'smime')); $status->addText(Horde::link('#', '', '', '', '', '', '', array('id' => $imple->getDomId())) . _("Save the certificate to your Address Book.") . '</a>'); break; } } } elseif (strlen($email)) { $status->addText(sprintf(_("Sender: %s"), htmlspecialchars($email))); } } catch (Horde_Exception $e) { $status->action(IMP_Mime_Status::ERROR); $cache->smime[$base_id]['wrap'] = 'mimePartWrapInvalid'; $status->addText($e->getMessage()); } } else { $status->addMimeAction('smimeVerifyMsg', _("Click to verify the data.")); } if ($sig_only) { return; } if (!($subpart = $imp_contents->getMimePart($sig_id))) { try { $msg_data = $this->_impsmime->extractSignedContents($raw_text); $subpart = Horde_Mime_Part::parseMessage($msg_data, array('forcemime' => true)); } catch (Horde_Exception $e) { $status->addText($e->getMessage()); return null; } } return $subpart; }