Header text is defined only for the base RFC 2822 message or
message/rfc822 parts.
public headerText ( array $opts = [] ) | ||
$opts | array | The following options are available: - id: (string) The MIME ID to obtain the header text for. DEFAULT: The header text for the base message will be returned. - 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. |
/** * Generates a string that can be saved out to an mbox format mailbox file * for a mailbox (or set of mailboxes), optionally including all * subfolders of the selected mailbox(es) as well. All mailboxes will be * output in the same string. * * @param mixed $mboxes A mailbox name (UTF-8), or list of mailbox names, * to generate a mbox file for. * * @return resource A stream resource containing the text of a mbox * format mailbox file. */ public function generate($mboxes) { $body = fopen('php://temp', 'r+'); if (!is_array($mboxes)) { if (!strlen($mboxes)) { return $body; } $mboxes = array($mboxes); } if (empty($mboxes)) { return $body; } $query = new Horde_Imap_Client_Fetch_Query(); $query->envelope(); $query->imapDate(); $query->headerText(array('peek' => true)); $query->bodyText(array('peek' => true)); foreach (IMP_Mailbox::get($mboxes) as $val) { $imp_imap = $val->imp_imap; $slices = $imp_imap->getSlices($val, $imp_imap->getIdsOb(Horde_Imap_Client_Ids::ALL, true)); foreach ($slices as $slice) { try { $res = $imp_imap->fetch($val, $query, array('ids' => $slice, 'nocache' => true)); } catch (IMP_Imap_Exception $e) { continue; } foreach ($res as $ptr) { $from_env = $ptr->getEnvelope()->from; $from = count($from_env) ? $from_env[0]->bare_address : '<>'; /* We need this long command since some MUAs (e.g. pine) * require a space in front of single digit days. */ $imap_date = $ptr->getImapDate(); $date = sprintf('%s %2s %s', $imap_date->format('D M'), $imap_date->format('j'), $imap_date->format('H:i:s Y')); fwrite($body, 'From ' . $from . ' ' . $date . "\r\n"); /* Remove spurious 'From ' line in headers. */ $stream = $ptr->getHeaderText(0, Horde_Imap_Client_Data_Fetch::HEADER_STREAM); while (!feof($stream)) { $line = fgets($stream); if (substr($line, 0, 5) != 'From ') { fwrite($body, $line); } } fwrite($body, "\r\n"); /* Add Body text. */ $stream = $ptr->getBodyText(0, true); while (!feof($stream)) { fwrite($body, fread($stream, 8192)); } fwrite($body, "\r\n"); } } } return $body; }
/** * 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; }
/** * * @param Horde_Imap_Client_Mailbox $mbox The mailbox * @param array $uids An array of message uids * @param array $options An options array * - headers: (boolean) Fetch header text if true. * DEFAULT: false (Do not fetch header text). * - structure: (boolean) Fetch message structure. * DEFAULT: true (Fetch message structure). * - flags: (boolean) Fetch messagge flags. * DEFAULT: true (Fetch message flags). * - envelope: (boolen) Fetch the envelope data. * DEFAULT: false (Do not fetch envelope). @since 2.4.0 * * @return Horde_Imap_Fetch_Results The results. * @throws Horde_ActiveSync_Exception */ protected function _getMailMessages(Horde_Imap_Client_Mailbox $mbox, array $uids, array $options = array()) { $options = array_merge(array('headers' => false, 'structure' => true, 'flags' => true, 'envelope' => false), $options); $query = new Horde_Imap_Client_Fetch_Query(); if ($options['structure']) { $query->structure(); } if ($options['flags']) { $query->flags(); } if ($options['envelope']) { $query->envelope(); } if (!empty($options['headers'])) { $query->headerText(array('peek' => true)); } try { return $this->_getImapOb()->fetch($mbox, $query, array('ids' => new Horde_Imap_Client_Ids($uids), 'exists' => true)); } catch (Horde_Imap_Client_Exception $e) { $this->_logger->err(sprintf('[%s] Unable to fetch message: %s', $this->_procid, $e->getMessage())); throw new Horde_ActiveSync_Exception($e); } }
/** * Returns base header information. * * @param integer $type See getHeader(). * @param boolean $seen Mark message as seen? * * @return mixed See getHeader(). */ protected function _getHeader($type, $seen) { if (!isset($this->_header)) { if (!$this->_indices) { $this->_header = $this->_message->addMimeHeaders(); } else { $query = new Horde_Imap_Client_Fetch_Query(); $query->headerText(array('peek' => !$seen)); $this->_header = ($res = $this->_fetchData($query)) ? $res : new Horde_Imap_Client_Data_Fetch(); } } switch ($type) { case self::HEADER_OB: return $this->_indices ? $this->_header->getHeaderText(0, Horde_Imap_Client_Data_Fetch::HEADER_PARSE) : $this->_header; case self::HEADER_TEXT: return $this->_indices ? $this->_header->getHeaderText() : $this->_header->toString(); case self::HEADER_STREAM: if ($this->_indices) { return $this->_header->getHeaderText(0, Horde_Imap_Client_Data_Fetch::HEADER_STREAM); } $stream = new Horde_Support_StringStream($this->_header->toString()); $stream->fopen(); return $stream; } }
/** * 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); }
/** * Attempt to determine whether this message is a bulk message (e.g. automated reply). * * @param \Horde_Imap_Client_Data_Fetch $message The message to process * @param string|\Horde_Imap_Client_Ids $messageid The Hore message Uid * @return boolean */ private function is_bulk_message(\Horde_Imap_Client_Data_Fetch $message, $messageid) { $query = new \Horde_Imap_Client_Fetch_Query(); $query->headerText(array('peek' => true)); $messagedata = $this->client->fetch($this->get_mailbox(), $query, array('ids' => $messageid))->first(); // Assume that this message is not bulk to begin with. $isbulk = false; // An auto-reply may itself include the Bulk Precedence. $precedence = $messagedata->getHeaderText(0, \Horde_Imap_Client_Data_Fetch::HEADER_PARSE)->getValue('Precedence'); $isbulk = $isbulk || strtolower($precedence) == 'bulk'; // If the X-Autoreply header is set, and not 'no', then this is an automatic reply. $autoreply = $messagedata->getHeaderText(0, \Horde_Imap_Client_Data_Fetch::HEADER_PARSE)->getValue('X-Autoreply'); $isbulk = $isbulk || $autoreply && $autoreply != 'no'; // If the X-Autorespond header is set, and not 'no', then this is an automatic response. $autorespond = $messagedata->getHeaderText(0, \Horde_Imap_Client_Data_Fetch::HEADER_PARSE)->getValue('X-Autorespond'); $isbulk = $isbulk || $autorespond && $autorespond != 'no'; // If the Auto-Submitted header is set, and not 'no', then this is a non-human response. $autosubmitted = $messagedata->getHeaderText(0, \Horde_Imap_Client_Data_Fetch::HEADER_PARSE)->getValue('Auto-Submitted'); $isbulk = $isbulk || $autosubmitted && $autosubmitted != 'no'; return $isbulk; }
/** * Process a message to retrieve it's header data without body and attachemnts. * * @param Horde_Imap_Client_Data_Envelope $envelope The Envelope of the message * @param Horde_Imap_Client_Data_Fetch $messagedata The structure and part of the message body * @param string|Horde_Imap_Client_Ids $messageid The Hore message Uid * @return \stdClass The current value of the messagedata */ private function process_message_data(\Horde_Imap_Client_Data_Envelope $envelope, \Horde_Imap_Client_Data_Fetch $basemessagedata, $messageid) { // Get the current mailbox. $mailbox = $this->get_mailbox(); // We need the structure at various points below. $structure = $basemessagedata->getStructure(); // Now fetch the rest of the message content. $query = new \Horde_Imap_Client_Fetch_Query(); $query->imapDate(); // Fetch all of the message parts too. $typemap = $structure->contentTypeMap(); foreach ($typemap as $part => $type) { // The header. $query->headerText(array('id' => $part)); } $messagedata = $this->client->fetch($mailbox, $query, array('ids' => $messageid))->first(); // Store the data for this message. $headers = ''; foreach ($typemap as $part => $type) { // Grab all of the header data into a string. $headers .= $messagedata->getHeaderText($part); // We don't handle any of the other MIME content at this stage. } $data = new \stdClass(); // The message ID should always be in the first part. $data->messageid = $messagedata->getHeaderText(0, \Horde_Imap_Client_Data_Fetch::HEADER_PARSE)->getValue('Message-ID'); $data->subject = $envelope->subject; $data->timestamp = $messagedata->getImapDate()->__toString(); $data->envelope = $envelope; $data->data = $this->addressmanager->get_data(); $data->headers = $headers; $this->currentmessagedata = $data; return $this->currentmessagedata; }
/** * @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)); }
function Execute($aparams) { require_once JPATH_SITE . DS . "Horde" . DS . "Autoloader.php"; require_once JPATH_SITE . DS . "Horde" . DS . "Autoloader" . DS . "ClassPathMapper.php"; require_once JPATH_SITE . DS . "Horde" . DS . "Autoloader" . DS . "ClassPathMapper" . DS . "Default.php"; require_once JPATH_SITE . DS . "Horde" . DS . "Autoloader" . DS . "Default.php"; $this->Log("Checking email account - {$aparams['name']}"); /*if (JRequest::getVar('email') != 1) return;*/ if (!$aparams['server']) { return $this->Log("No server specified"); } if (!$aparams['port']) { return $this->Log("No port specified"); } if (!$aparams['username']) { return $this->Log("No username specified"); } if (!$aparams['password']) { return $this->Log("No password specified"); } $this->params = $aparams; $this->connect(); if (!$this->conn) { return $this->Log("Unable to connect to server"); } // check if we have any messages at all $messages = $this->conn->search("INBOX"); $ids = $messages['match']; $ids->reverse(); $msgcount = $ids->count(); if ($msgcount == 0) { $this->Log("No messages"); $this->disconnect(); return; } else { $this->Log("{$msgcount} messaeges"); } // only get the first 20 messages to make sure web page response is quicker $maxmsgcount = 50; if ($msgcount < $maxmsgcount) { $maxmsgcount = $msgcount; } $query = new Horde_Imap_Client_Fetch_Query(); $query->flags(); $query->structure(); $query->headerText(array('peek' => 1)); $uid = new Horde_Imap_Client_Ids(); for ($i = 0; $i < $maxmsgcount; $i++) { $uid->add($ids->ids[$i]); } $messages = $this->conn->fetch('INBOX', $query, array('ids' => $uid)); // for the most recent xx messages for ($i = 0; $i < $maxmsgcount; $i++) { $mapped = $ids->ids[$i]; $message = $messages->get($mapped); $this->Log("---------------------"); $this->Log("Processing message {$i} / {$mapped}"); // get headres of message if (!$this->GetHeaders($message)) { $this->Log("Error getting headers"); continue; } $subject = $this->headers->getValue("subject"); $this->Log("Subject : " . $subject); $this->from = $this->parse_addys($this->headers->getValue("from")); $this->to = $this->parse_addys($this->headers->getValue("to")); $this->Log("From : {$this->from[0]->mailbox}@{$this->from[0]->host} ({$this->from[0]->personal})"); if ($this->from[0]->mailbox == "no-reply") { // no-reply from form builder, attempt to find address in name $text = $this->from[0]->personal; //$text = str_replace("\"","",$text); $matches = array(); $pattern = "/(?:[a-z0-9!#\$%&'*+=?^_`{|}~-]+(?:\\.[a-z0-9!#\$%&'*+=?^_`{|}~-]+)*|\"(?:[-\v\f-!#-[]-]|\\[-\t\v\f-])*\")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[-\v\f-!-ZS-]|\\[-\t\v\f-])+)\\])/"; preg_match_all($pattern, $text, $matches); //print_p($matches); if (count($matches[0]) > 0) { // new email found $newemail = $matches[0][0]; list($name, $host) = explode("@", $newemail); $this->Log("No Reply message, New From address : {$name}@{$host}"); $this->from[0]->mailbox = $name; $this->from[0]->host = $host; $this->from[0]->personal = trim(str_replace("{$name}@{$host}", "", $this->from[0]->personal)); } } // skip if already read if ($aparams['type'] == "imap" && $this->IsMessageRead($message)) { $this->Log("Skipping read message"); continue; } // validate to address is required if (!$this->ValidateToAddress()) { $this->Log("Skipping invalid to address"); continue; } if (!$this->ValidateFromAddress()) { $this->Log("Skipping due to from address"); continue; } //check subject and to email to see if we have found a user and or ticket $subject = $this->headers->getValue("subject"); list($ticketid, $userid, $subject) = $this->ParseSubject($subject, $this->from[0]->mailbox . '@' . $this->from[0]->host); $this->subject = $subject; //echo "Ticket : $ticketid, $userid, $subject<br>"; // ok, need to get the message as we have decided its ok to use this ticket if ($ticketid < 1 && $userid < 1 && $this->params['newticketsfrom'] == "registered") { $this->Log("Skipping as registered only and not a registered email"); continue; } if ($this->params['allowrepliesonly'] && $ticketid < 1) { $this->Log("Skipping as not a reply"); continue; } // validate that the ticket is being replied to by user or handler if ($ticketid > 0) { $ticket = $this->getTicket($ticketid); if ($this->params['allowunknown'] < 1) { if ($ticket['user_id'] == 0 && $ticket['email'] != "{$this->from[0]->mailbox}@{$this->from[0]->host}") { $this->Log("Unknown email replying to the message, ignore the email ({$this->from[0]->mailbox}@{$this->from[0]->host})"); continue; } if ($userid != $ticket['handler_id'] && $userid != $ticket['user_id']) { $this->Log("Unknown user replying to the message, ignore the email ({$this->from[0]->mailbox}@{$this->from[0]->host})"); continue; } } } $this->GetMessage($message); $this->TrimMessage(); $messageid = 0; $filesok = true; // add to existing ticket if ($ticketid > 0) { // unreg ticket, just check email if ($ticket['user_id'] == 0) { //echo "Adding message to ticket - {$ticket['email']}<br>"; $this->DoTicketReply($ticketid, $userid, 0, $messageid); } else { if ($userid == $ticket['handler_id']) { //echo "Adding admin message to ticket - {$ticket['user_id']} -> {$userid}<br>"; $this->DoTicketReply($ticketid, $userid, 1, $messageid); } else { if ($userid == $ticket['user_id']) { //echo "Adding message to ticket - {$ticket['user_id']} -> {$userid}<br>"; $this->DoTicketReply($ticketid, $userid, 0, $messageid); if (!FSS_Settings::get('support_user_attach')) { $filesok = false; } } else { if ($this->params['allowunknown']) { // unreg ticket, add users reply $this->DoTicketReply($ticketid, 0, 0, $messageid); } } } } } else { if ($userid > 0) { //echo "Opening new ticket<br>"; $ticketid = $this->OpenNewTicket($userid, $messageid); } else { // open ticket for unregistered user //echo "Opening new ticket for unreg user<br>"; $ticketid = $this->OpenNewTicketUnreg($messageid); } } $ticket = $this->getTicket($ticketid); if ($userid > 0) { $user = JFactory::getUser($userid); $this->Log("Ticket ID : {$ticketid} - {$ticket['reference']}, UserID : {$userid} - {$user->name} ({$user->username})"); } else { $this->Log("Ticket ID : {$ticketid} - {$ticket['reference']}, Unregistered User"); } /* if ($filesok) $this->AttachFiles($ticketid, $userid, $messageid);*/ } //imap_expunge($this->conn); $this->disconnect(); //echo "</div>"; }