Search for text in the header of a message.
public headerText ( string $header, string $text, boolean $not = false, array $opts = [] ) | ||
$header | string | The header field. |
$text | string | The search text. |
$not | boolean | If true, do a 'NOT' search of $text. |
$opts | array | Additional options: - fuzzy: (boolean) If true, perform a fuzzy search. The IMAP server MUST support RFC 6203. |
/** */ public function createQuery($mbox, $queryob) { $ajax = new IMP_Ajax_Imple_ContactAutoCompleter(); foreach ($ajax->getAddressList()->bare_addresses as $val) { $ob = new Horde_Imap_Client_Search_Query(); $ob->headerText('from', $val, $this->_data); $queryob->orSearch($ob); } return $queryob; }
/** */ public function createQuery($mbox, $queryob) { global $injector; $contacts = $injector->getInstance('IMP_Contacts'); foreach ($contacts as $val) { if ($val instanceof Horde_Mail_Rfc822_Address) { $ob = new Horde_Imap_Client_Search_Query(); $ob->headerText('from', $val->bare_address, $this->_data); $queryob->orSearch($ob); } } return $queryob; }
/** */ public function createQuery($mbox, $queryob) { $ob = new Horde_Imap_Client_Search_Query(); $ob2 = clone $ob; $ob3 = clone $ob; $ob->headerText('content-type', 'multipart/mixed', $this->_data); $ob2->headerText('content-type', 'message/rfc822', $this->_data); /* If regular search, searches are OR'd: only one must match. * If NOT search, searches are AND'd: both must not match. */ if ($this->_data) { $ob3->andSearch(array($ob, $ob2)); } else { $ob3->orSearch(array($ob, $ob2)); } /* ...but the combined search must be AND'd with the rest of the * search terms. */ $queryob->andSearch($ob3); return $queryob; }
/** * 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; }
public function testOrQueriesWithABaseQuery() { $or_ob = new Horde_Imap_Client_Search_Query(); $ob = new Horde_Imap_Client_Search_Query(); $ob->flag('\\deleted', false); $ob->headerText('from', 'ABC'); $or_ob->orSearch($ob); $ob = new Horde_Imap_Client_Search_Query(); $ob->flag('\\deleted', true); $ob->headerText('from', 'DEF'); $or_ob->orSearch($ob); $base_ob = new Horde_Imap_Client_Search_Query(); $base_ob->flag('\\seen', false); $base_ob->andSearch($or_ob); $this->assertEquals('UNSEEN OR (DELETED FROM DEF) (UNDELETED FROM ABC)', strval($base_ob)); }
/** * Attempt to find a Message-ID in a list of mail folders. * * @return array An array with the 0 element being the mbox * @throws Horde_Exception_NotFound, Horde_ActiveSync_Exception * * @deprecated This is unused and should be removed. */ public function getUidFromMidInFolders($id, array $folders) { $search_q = new Horde_Imap_Client_Search_Query(); $search_q->headerText('Message-ID', $id); foreach ($folders as $folder) { $mbox = new Horde_Imap_Client_Mailbox($folder->_serverid); try { $results = $this->_getImapOb()->search($mbox, $search_q); } catch (Horde_Imap_Client_Exception $e) { throw new Horde_ActiveSync_Exception($e->getMessage()); } $uid = $results['match']->ids; if (!empty($uid)) { return array($mbox, current($uid)); } } throw new Horde_Exception_NotFound('Message not found.'); }
/** * Performs the filtering specified in the rules. * * @param integer $change The timestamp of the latest rule change during * the current session. */ protected function _perform($change) { $api = $this->_params['api']; $notification = $this->_params['notification']; /* Indices that will be ignored by subsequent rules. */ $ignore_ids = array(); /* Only do filtering if: 1. We have not done filtering before -or- 2. The mailbox has changed -or- 3. The rules have changed. */ $cache = $api->getCache(); if ($cache !== false && $cache == $change) { return; } $filters = Ingo_Storage_FilterIterator_Skip::create($this->_params['storage'], $this->_params['skip']); /* Parse through the rules, one-by-one. */ foreach ($filters as $rule) { /* Check to make sure this is a valid rule and that the rule is not disabled. */ if (!$this->_validRule($rule) || $rule->disable) { continue; } switch ($class = get_class($rule)) { case 'Ingo_Rule_System_Blacklist': case 'Ingo_Rule_System_Whitelist': $addr = $rule->addresses; $bl_folder = $class === 'Ingo_Rule_System_Blacklist' ? $rule->mailbox : null; /* If list is empty, move on. */ if (empty($addr)) { continue; } $addr = new Horde_Mail_Rfc822_List($addr); $query = $this->_getQuery(); $or_ob = new Horde_Imap_Client_Search_Query(); foreach ($addr->bare_addresses as $val) { $ob = new Horde_Imap_Client_Search_Query(); $ob->charset('UTF-8', false); $ob->headerText('from', $val); $or_ob->orSearch(array($ob)); } $query->andSearch(array($or_ob)); $indices = $api->search($query); if (!($msgs = $api->fetchEnvelope($indices))) { continue; } /* Remove any indices that got in there by way of partial * address match. */ $remove = array(); foreach ($msgs as $v) { foreach ($v->getEnvelope()->from as $v2) { if (!$addr->contains($v2)) { $remove[] = $v->getUid(); break; } } } if ($remove) { $indices = array_diff($indices, $remove); } if ($class === 'Ingo_Rule_System_Blacklist') { $indices = array_diff($indices, $ignore_ids); if (!empty($indices)) { if (!empty($bl_folder)) { $api->moveMessages($indices, $bl_folder); } else { $api->deleteMessages($indices); } $notification->push(sprintf(_("Filter activity: %s message(s) that matched the blacklist were deleted."), count($indices)), 'horde.message'); } } else { $ignore_ids = $indices; } break; case 'Ingo_Rule_User_Discard': case 'Ingo_Rule_User_Keep': case 'Ingo_Rule_User_Move': case 'Ingo_Rule_User_MoveKeep': $base_query = $this->_getQuery(); $query = new Horde_Imap_Client_Search_Query(); foreach ($rule->conditions as $val) { $ob = new Horde_Imap_Client_Search_Query(); if (!empty($val['type']) && $val['type'] == Ingo_Rule_User::TEST_SIZE) { $ob->size($val['value'], $val['match'] == 'greater than'); } elseif (!empty($val['type']) && $val['type'] == Ingo_Rule_User::TEST_BODY) { $ob->charset('UTF-8', false); $ob->text($val['value'], true, $val['match'] == 'not contain'); } else { if (strpos($val['field'], ',') == false) { $ob->charset('UTF-8', false); $ob->headerText($val['field'], $val['value'], $val['match'] == 'not contain'); } else { foreach (explode(',', $val['field']) as $header) { $hdr_ob = new Horde_Imap_Client_Search_Query(); $hdr_ob->charset('UTF-8', false); $hdr_ob->headerText($header, $val['value'], $val['match'] == 'not contain'); if ($val['match'] == 'contains') { $ob->orSearch(array($hdr_ob)); } elseif ($val['match'] == 'not contain') { $ob->andSearch(array($hdr_ob)); } } } } switch ($rule->combine) { case Ingo_Rule_User::COMBINE_ALL: $query->andSearch(array($ob)); break; case Ingo_Rule_User::COMBINE_ANY: $query->orSearch(array($ob)); break; } } $base_query->andSearch(array($query)); $indices = $api->search($base_query); if ($indices = array_diff($indices, $ignore_ids)) { if ($rule->stop) { /* If the stop action is set, add these * indices to the list of ids that will be * ignored by subsequent rules. */ $ignore_ids = array_unique($indices + $ignore_ids); } /* Set the flags. */ if ($class !== 'Ingo_Rule_User_Discard') { $flags = array(); if ($rule->flags & Ingo_Rule_User::FLAG_ANSWERED) { $flags[] = '\\answered'; } if ($rule->flags & Ingo_Rule_User::FLAG_DELETED) { $flags[] = '\\deleted'; } if ($rule->flags & Ingo_Rule_User::FLAG_FLAGGED) { $flags[] = '\\flagged'; } if ($rule->flags & Ingo_Rule_User::FLAG_SEEN) { $flags[] = '\\seen'; } if (!empty($flags)) { $api->setMessageFlags($indices, $flags); } } switch ($class) { case 'Ingo_Rule_User_Keep': /* Add these indices to the ignore list. */ $ignore_ids = array_unique($indices + $ignore_ids); break; case 'Ingo_Rule_User_Move': /* We need to grab the envelope first. */ if ($this->_params['show_filter_msg'] && !($fetch = $api->fetchEnvelope($indices))) { continue 2; } $mbox = new Horde_Imap_Client_Mailbox($rule->value); /* Move the messages to the requested mailbox. */ $api->moveMessages($indices, strval($mbox)); /* Display notification message(s). */ if ($this->_params['show_filter_msg']) { foreach ($fetch as $msg) { $envelope = $msg->getEnvelope(); $notification->push(sprintf(_("Filter activity: The message \"%s\" from \"%s\" has been moved to the folder \"%s\"."), !empty($envelope->subject) ? Horde_Mime::decode($envelope->subject) : _("[No Subject]"), !empty($envelope->from) ? strval($envelope->from) : _("[No Sender]"), $mbox), 'horde.message'); } } else { $notification->push(sprintf(_("Filter activity: %s message(s) have been moved to the folder \"%s\"."), count($indices), $mbox), 'horde.message'); } break; case 'Ingo_Rule_User_Discard': /* We need to grab the envelope first. */ if ($this->_params['show_filter_msg'] && !($fetch = $api->fetchEnvelope($indices))) { continue; } /* Delete the messages now. */ $api->deleteMessages($indices); /* Display notification message(s). */ if ($this->_params['show_filter_msg']) { foreach ($fetch as $msg) { $envelope = $msg->getEnvelope(); $notification->push(sprintf(_("Filter activity: The message \"%s\" from \"%s\" has been deleted."), !empty($envelope->subject) ? Horde_Mime::decode($envelope->subject) : _("[No Subject]"), !empty($envelope->from) ? strval($envelope->from) : _("[No Sender]")), 'horde.message'); } } else { $notification->push(sprintf(_("Filter activity: %s message(s) have been deleted."), count($indices)), 'horde.message'); } break; case 'Ingo_Rule_User_MoveKeep': $mbox = new Horde_Imap_Client_Mailbox($rule->value); /* Copy the messages to the requested mailbox. */ $api->copyMessages($indices, strval($mbox)); /* Display notification message(s). */ if ($this->_params['show_filter_msg']) { if (!($fetch = $api->fetchEnvelope($indices))) { continue; } foreach ($fetch as $msg) { $envelope = $msg->getEnvelope(); $notification->push(sprintf(_("Filter activity: The message \"%s\" from \"%s\" has been copied to the folder \"%s\"."), !empty($envelope->subject) ? Horde_Mime::decode($envelope->subject) : _("[No Subject]"), !empty($envelope->from) ? strval($envelope->from) : _("[No Sender]"), $mbox), 'horde.message'); } } else { $notification->push(sprintf(_("Filter activity: %s message(s) have been copied to the folder \"%s\"."), count($indices), $mbox), 'horde.message'); } } } break; } } /* Set cache flag. */ $api->storeCache($change); }
/** * Process a message received and validated by the Inbound Message processor. * * @param \stdClass $maildata The data retrieved from the database for the current record. * @return bool Whether the message was successfully processed. * @throws \core\message\inbound\processing_failed_exception if the message cannot be found. */ public function process_existing_message(\stdClass $maildata) { // Grab the new IMAP client. if (!$this->get_imap_client()) { return false; } // Build the search. $search = new \Horde_Imap_Client_Search_Query(); // When dealing with Inbound Message messages, we mark them as flagged and seen. Restrict the search to those criterion. $search->flag(self::MESSAGE_SEEN, true); $search->flag(self::MESSAGE_FLAGGED, true); mtrace("Searching for a Seen, Flagged message in the folder '" . $this->get_confirmation_folder() . "'"); // Match the message ID. $search->headerText('message-id', $maildata->messageid); $search->headerText('to', $maildata->address); $results = $this->client->search($this->get_confirmation_folder(), $search); // Build the base query. $query = new \Horde_Imap_Client_Fetch_Query(); $query->envelope(); $query->structure(); // Fetch the first message from the client. $messages = $this->client->fetch($this->get_confirmation_folder(), $query, array('ids' => $results['match'])); $this->addressmanager = new \core\message\inbound\address_manager(); if ($message = $messages->first()) { mtrace("--> Found the message. Passing back to the pickup system."); // Process the message. $this->process_message($message, true, true); // Close the client connection. $this->close_connection(); mtrace("============================================================================"); return true; } else { // Close the client connection. $this->close_connection(); mtrace("============================================================================"); throw new \core\message\inbound\processing_failed_exception('oldmessagenotfound', 'tool_messageinbound'); } }
/** * Get a message UID by the Message-ID. Returns the last message in a * mailbox that matches. * * @param Horde_Imap_Client_Mailbox $mailbox The mailbox to search * @param string $msgid Message-ID. * * @return string UID (null if not found). */ protected function _getUidByMessageId($mailbox, $msgid) { if (!$msgid) { return null; } $query = new Horde_Imap_Client_Search_Query(); $query->headerText('Message-ID', $msgid); $res = $this->search($mailbox, $query, array('results' => array(Horde_Imap_Client::SEARCH_RESULTS_MAX))); return $res['max']; }
/** * 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; }
/** * Return the search query to use to find the sent message. * * @return Horde_Imap_Client_Search_Query The query object. */ public function searchQuery() { $query = new Horde_Imap_Client_Search_Query(); $query->headerText($this->_msgidHeader, $this->msg_id); return $query; }