MIME header text is defined only for non-RFC 2822 messages and
non-message/rfc822 parts.
public mimeHeader ( string $id, array $opts = [] ) | ||
$id | string | The MIME ID to obtain the MIME header text for. |
$opts | array | The following options are available: - length: (integer) The length of the substring to return. DEFAULT: The entire text is returned. - peek: (boolean) If set, does not set the '\Seen' flag on the message. DEFAULT: The seen flag is set. - start: (integer) If a portion of the full text is desired to be returned, the starting position is identified here. DEFAULT: The entire text is returned. |
private function load() { $headers = []; $fetch_query = new \Horde_Imap_Client_Fetch_Query(); $fetch_query->bodyPart($this->attachmentId); $fetch_query->mimeHeader($this->attachmentId); $headers = array_merge($headers, ['importance', 'list-post', 'x-priority']); $headers[] = 'content-type'; $fetch_query->headers('imp', $headers, ['cache' => true]); // $list is an array of Horde_Imap_Client_Data_Fetch objects. $ids = new \Horde_Imap_Client_Ids($this->messageId); $headers = $this->conn->fetch($this->mailBox, $fetch_query, ['ids' => $ids]); /** @var $fetch Horde_Imap_Client_Data_Fetch */ if (!isset($headers[$this->messageId])) { throw new DoesNotExistException('Unable to load the attachment.'); } $fetch = $headers[$this->messageId]; $mimeHeaders = $fetch->getMimeHeader($this->attachmentId, Horde_Imap_Client_Data_Fetch::HEADER_PARSE); $this->mimePart = new \Horde_Mime_Part(); // To prevent potential problems with the SOP we serve all files with the // MIME type "application/octet-stream" $this->mimePart->setType('application/octet-stream'); // Serve all files with a content-disposition of "attachment" to prevent Cross-Site Scripting $this->mimePart->setDisposition('attachment'); // Extract headers from part $contentDisposition = $mimeHeaders->getValue('content-disposition', \Horde_Mime_Headers::VALUE_PARAMS); if (!is_null($contentDisposition)) { $vars = ['filename']; foreach ($contentDisposition as $key => $val) { if (in_array($key, $vars)) { $this->mimePart->setDispositionParameter($key, $val); } } } else { $contentDisposition = $mimeHeaders->getValue('content-type', \Horde_Mime_Headers::VALUE_PARAMS); $vars = ['name']; foreach ($contentDisposition as $key => $val) { if (in_array($key, $vars)) { $this->mimePart->setContentTypeParameter($key, $val); } } } /* Content transfer encoding. */ if ($tmp = $mimeHeaders->getValue('content-transfer-encoding')) { $this->mimePart->setTransferEncoding($tmp); } $body = $fetch->getBodyPart($this->attachmentId); $this->mimePart->setContents($body); }
/** * Gets the raw text for one section of the message. * * @param integer $id The ID of the MIME part. * @param array $options Additional options: * - decode: (boolean) Attempt to decode the bodypart on the remote * server. * DEFAULT: No * - length: (integer) If set, only download this many bytes of the * bodypart from the server. * DEFAULT: All data is retrieved. * - mimeheaders: (boolean) Include the MIME headers also? * DEFAULT: No * - stream: (boolean) If true, return a stream. * DEFAULT: No * * @return object Object with the following properties: * - data: (mixed) The text of the part or a stream resource if 'stream' * option is true. * - decode: (string) If 'decode' option is true, and bodypart decoded * on server, the content-type of the decoded data. */ public function getBodyPart($id, $options = array()) { $ret = new stdClass(); $ret->data = ''; $ret->decode = null; if (empty($id)) { return $ret; } if (!$this->_indices || $this->isEmbedded($id)) { if (empty($options['mimeheaders']) || in_array($id, $this->_embedded)) { $ob = $this->getMimePart($id, array('nocontents' => true)); if (empty($options['stream'])) { if (!is_null($ob)) { $ret->data = $ob->getContents(); } } else { $ret->data = is_null($ob) ? fopen('php://temp', 'r+') : $ob->getContents(array('stream' => true)); } return $ret; } $base_id = new Horde_Mime_Id($id); while (!in_array($base_id->id, $this->_embedded, true)) { $base_id->id = $base_id->idArithmetic($base_id::ID_UP); if (is_null($base_id->id)) { return $ret; } } $body = ''; $part = $this->getMimePart($base_id->id, array('nocontents' => true)); if ($part) { $txt = $part->addMimeHeaders()->toString() . "\n" . $part->getContents(); try { $body = Horde_Mime_Part::getRawPartText($txt, 'header', '1') . "\n\n" . Horde_Mime_Part::getRawPartText($txt, 'body', '1'); } catch (Horde_Mime_Exception $e) { } } if (empty($options['stream'])) { $ret->data = $body; return $ret; } $ret->data = fopen('php://temp', 'r+'); if (strlen($body)) { fwrite($ret->data, $body); fseek($ret->data, 0); } return $ret; } $query = new Horde_Imap_Client_Fetch_Query(); if (substr($id, -2) === '.0') { $rfc822 = true; $id = substr($id, 0, -2); $options['mimeheaders'] = true; } else { $rfc822 = false; } if (!isset($options['length']) || !empty($options['length'])) { $bodypart_params = array('decode' => !empty($options['decode']), 'peek' => true); if (isset($options['length'])) { $bodypart_params['start'] = 0; $bodypart_params['length'] = $options['length']; } if ($rfc822) { $bodypart_params['id'] = $id; $query->bodyText($bodypart_params); } else { $query->bodyPart($id, $bodypart_params); } } if (!empty($options['mimeheaders'])) { if ($rfc822) { $query->headerText(array('id' => $id, 'peek' => true)); } else { $query->mimeHeader($id, array('peek' => true)); } } if ($res = $this->_fetchData($query)) { try { if (empty($options['mimeheaders'])) { $ret->decode = $res->getBodyPartDecode($id); $ret->data = $rfc822 ? $res->getBodyText($id, !empty($options['stream'])) : $res->getBodyPart($id, !empty($options['stream'])); return $ret; } elseif (empty($options['stream'])) { $ret->data = $rfc822 ? $res->getHeaderText($id) . $res->getBodyText($id) : $res->getMimeHeader($id) . $res->getBodyPart($id); return $ret; } if ($rfc822) { $data = array($res->getHeaderText($id, Horde_Imap_Client_Data_Fetch::HEADER_STREAM), $res->getBodyText($id, true)); } else { $data = array($res->getMimeHeader($id, Horde_Imap_Client_Data_Fetch::HEADER_STREAM), $res->getBodyPart($id, true)); } $ret->data = Horde_Stream_Wrapper_Combine::getStream($data); return $ret; } catch (Horde_Exception $e) { } } if (!empty($options['stream'])) { $ret->data = fopen('php://temp', 'r+'); } return $ret; }
/** * Gets the raw text for one section of the message. * * @param integer $id The ID of the MIME part. * @param array $options Additional options: * - decode: (boolean) Attempt to decode the bodypart on the remote * server. If successful, sets self::$_lastBodyPartDecode to * the content-type of the decoded data. * DEFAULT: No * - length: (integer) If set, only download this many bytes of the * bodypart from the server. * DEFAULT: All data is retrieved. * - mimeheaders: (boolean) Include the MIME headers also? * DEFAULT: No * - stream: (boolean) If true, return a stream. * DEFAULT: No * * @return mixed The text of the part or a stream resource if 'stream' * is true. * @todo Simplify by removing 'mimeheaders' parameter (not used). */ public function getBodyPart($id, $options) { $options = array_merge(array('decode' => false, 'mimeheaders' => false, 'stream' => false), $options); $this->_lastBodyPartDecode = null; $query = new Horde_Imap_Client_Fetch_Query(); if (!isset($options['length']) || !empty($options['length'])) { $bodypart_params = array('decode' => true, 'peek' => true); if (isset($options['length'])) { $bodypart_params['start'] = 0; $bodypart_params['length'] = $options['length']; } $query->bodyPart($id, $bodypart_params); } if (!empty($options['mimeheaders'])) { $query->mimeHeader($id, array('peek' => true)); } $fetch_res = $this->_imap->fetch($this->_mbox, $query, array('ids' => new Horde_Imap_Client_Ids(array($this->uid)))); if (empty($options['mimeheaders'])) { $this->_lastBodyPartDecode = $fetch_res[$this->uid]->getBodyPartDecode($id); return $fetch_res[$this->uid]->getBodyPart($id, $options['stream']); } elseif (empty($options['stream'])) { return $fetch_res[$this->uid]->getMimeHeader($id) . $fetch_res[$this->uid]->getBodyPart($id); } else { $swrapper = new Horde_Support_CombineStream(array($fetch_res[$this->uid]->getMimeHeader($id, Horde_Imap_Client_Data_Fetch::HEADER_STREAM), $fetch_res[$this->uid]->getBodyPart($id, true))); return $swrapper->fopen(); } }
/** * Given an IMAP URL, fetches the corresponding part. * * @param Horde_Imap_Client_Url_Imap $url An IMAP URL. * * @return resource The section contents in a stream. Returns null if * the part could not be found. * * @throws Horde_Imap_Client_Exception */ public function fetchFromUrl(Horde_Imap_Client_Url_Imap $url) { $ids_ob = $this->_socket->getIdsOb($url->uid); // BODY[] if (is_null($url->section)) { $query = new Horde_Imap_Client_Fetch_Query(); $query->fullText(array('peek' => true)); $fetch = $this->_socket->fetch($url->mailbox, $query, array('ids' => $ids_ob)); return $fetch[$url->uid]->getFullMsg(true); } $section = trim($url->section); // BODY[<#.>HEADER.FIELDS<.NOT>()] if (($pos = stripos($section, 'HEADER.FIELDS')) !== false) { $hdr_pos = strpos($section, '('); $cmd = substr($section, 0, $hdr_pos); $query = new Horde_Imap_Client_Fetch_Query(); $query->headers('section', explode(' ', substr($section, $hdr_pos + 1, strrpos($section, ')') - $hdr_pos)), array('id' => $pos ? substr($section, 0, $pos - 1) : 0, 'notsearch' => stripos($cmd, '.NOT') !== false, 'peek' => true)); $fetch = $this->_socket->fetch($url->mailbox, $query, array('ids' => $ids_ob)); return $fetch[$url->uid]->getHeaders('section', Horde_Imap_Client_Data_Fetch::HEADER_STREAM); } // BODY[#] if (is_numeric(substr($section, -1))) { $query = new Horde_Imap_Client_Fetch_Query(); $query->bodyPart($section, array('peek' => true)); $fetch = $this->_socket->fetch($url->mailbox, $query, array('ids' => $ids_ob)); return $fetch[$url->uid]->getBodyPart($section, true); } // BODY[<#.>HEADER] if (($pos = stripos($section, 'HEADER')) !== false) { $id = $pos ? substr($section, 0, $pos - 1) : 0; $query = new Horde_Imap_Client_Fetch_Query(); $query->headerText(array('id' => $id, 'peek' => true)); $fetch = $this->_socket->fetch($url->mailbox, $query, array('ids' => $ids_ob)); return $fetch[$url->uid]->getHeaderText($id, Horde_Imap_Client_Data_Fetch::HEADER_STREAM); } // BODY[<#.>TEXT] if (($pos = stripos($section, 'TEXT')) !== false) { $id = $pos ? substr($section, 0, $pos - 1) : 0; $query = new Horde_Imap_Client_Fetch_Query(); $query->bodyText(array('id' => $id, 'peek' => true)); $fetch = $this->_socket->fetch($url->mailbox, $query, array('ids' => $ids_ob)); return $fetch[$url->uid]->getBodyText($id, true); } // BODY[<#.>MIMEHEADER] if (($pos = stripos($section, 'MIME')) !== false) { $id = $pos ? substr($section, 0, $pos - 1) : 0; $query = new Horde_Imap_Client_Fetch_Query(); $query->mimeHeader($id, array('peek' => true)); $fetch = $this->_socket->fetch($url->mailbox, $query, array('ids' => $ids_ob)); return $fetch[$url->uid]->getMimeHeader($id, Horde_Imap_Client_Data_Fetch::HEADER_STREAM); } return null; }
/** * @depends testOptimizedSearches */ public function testComplexFetch() { // Fetching message information from complex MIME message. $complex_fetch = new Horde_Imap_Client_Fetch_Query(); $complex_fetch->fullText(array('length' => 100, 'peek' => true)); // Header of entire message $complex_fetch->headerText(array('length' => 100, 'peek' => true)); // Header of message/rfc822 part $complex_fetch->headerText(array('id' => 2, 'length' => 100, 'peek' => true)); // Body text of entire message $complex_fetch->bodyText(array('length' => 100, 'peek' => true)); // Body text of message/rfc822 part $complex_fetch->bodyText(array('id' => 2, 'length' => 100, 'peek' => true)); // MIME Header of multipart/alternative part $complex_fetch->mimeHeader('1', array('length' => 100, 'peek' => true)); // MIME Header of text/plain part embedded in message/rfc822 part $complex_fetch->mimeHeader('2.1', array('length' => 100, 'peek' => true)); // Body text of multipart/alternative part $complex_fetch->bodyPart('1', array('length' => 100, 'peek' => true)); // Body text of image/png part embedded in message/rfc822 part // Try to do server-side decoding, if available $complex_fetch->mimeHeader('2.2', array('decode' => true, 'length' => 100, 'peek' => true)); // If supported, return decoded body part size $complex_fetch->bodyPartSize('2.2'); // Select message-id header from base message header $complex_fetch->headers('headersearch1', array('message-id'), array('length' => 100, 'peek' => true)); // Select everything but message-id header from message/rfc822 header $complex_fetch->headers('headersearch2', array('message-id'), array('id' => '2', 'length' => 100, 'notsearch' => true, 'peek' => true)); $complex_fetch->structure(); $complex_fetch->flags(); $complex_fetch->imapDate(); $complex_fetch->size(); $complex_fetch->uid(); if (self::$live->capability->query('CONDSTORE')) { $complex_fetch->modseq(); } try { $res = self::$live->fetch(self::$test_mbox, $complex_fetch, array('ids' => new Horde_Imap_Client_Ids(3, true))); } catch (Horde_Imap_Client_Exception $e) { if ($e->getCode() === $e::MBOXNOMODSEQ) { $this->markTestSkipped('Mailbox does not support MODSEQ.'); } throw $e; } $this->assertInstanceOf('Horde_Imap_Client_Fetch_Results', $res); $this->assertEquals(1, count($res)); $this->assertEquals('Message-ID: <*****@*****.**>', trim($res[3]->getHeaders('headersearch1'))); /* Return stream instead. */ $this->assertInternalType('resource', $res[3]->getHeaders('headersearch1', Horde_Imap_Client_Data_Fetch::HEADER_STREAM)); /* Parse headers instead. */ $this->assertInstanceOf('Horde_Mime_Headers', $res[3]->getHeaders('headersearch1', Horde_Imap_Client_Data_Fetch::HEADER_PARSE)); }
/** * @param \Horde_Mime_Part $p * @param int $partNo * @return string * @throws DoesNotExistException * @throws \Exception */ private function loadBodyData($p, $partNo) { // DECODE DATA $fetch_query = new \Horde_Imap_Client_Fetch_Query(); $ids = new \Horde_Imap_Client_Ids($this->messageId); $fetch_query->bodyPart($partNo, ['peek' => true]); $fetch_query->bodyPartSize($partNo); $fetch_query->mimeHeader($partNo, ['peek' => true]); $headers = $this->conn->fetch($this->mailBox, $fetch_query, ['ids' => $ids]); /** @var $fetch \Horde_Imap_Client_Data_Fetch */ $fetch = $headers[$this->messageId]; if (is_null($fetch)) { throw new DoesNotExistException("Mail body for this mail({$this->messageId}) could not be loaded"); } $mimeHeaders = $fetch->getMimeHeader($partNo, Horde_Imap_Client_Data_Fetch::HEADER_PARSE); if ($enc = $mimeHeaders->getValue('content-transfer-encoding')) { $p->setTransferEncoding($enc); } $data = $fetch->getBodyPart($partNo); $p->setContents($data); $data = $p->getContents(); $data = iconv($p->getCharset(), 'utf-8//IGNORE', $data); return $data; }