Search for a flag/keywords.
public flag ( string $name, boolean $set = true, array $opts = [] ) | ||
$name | string | The flag or keyword name. |
$set | boolean | If true, search for messages that have the flag set. If false, search for messages that do not have the flag set. |
$opts | array | Additional options: - fuzzy: (boolean) If true, perform a fuzzy search. The IMAP server MUST support RFC 6203. |
public function getLatestMails($o) { $aResults = array(); $aRes = $this->imapProxy->getMMGMaxInFolder($this->imapProxy->currentFolder64, $this->imapProxy->currentFolderStatus['uidvalidity']); $sMinDate = $aRes[0]['max_date'] == '' ? '1980-01-01' : $aRes[0]['max_date']; //$iMinId = max(1,O + $aRes[0]['max_id']); $oUnseenQuery = new Horde_Imap_Client_Search_Query(array('peek' => true)); $oUnseenQuery->flag('SEEN', false); $oUnseenQuery->dateSearch($sMinDate, Horde_Imap_Client_Search_Query::DATE_SINCE); $results = $this->imapProxy->search($oUnseenQuery); $aAllIDs = $results['match']->ids; if (count($aAllIDs)) { $aChunksID = array_chunk($aAllIDs, 30); foreach ($aChunksID as $aMsg) { $oMMG = new MMG_MAIL_MESSAGE(); $aMMG = $oMMG->get(array('cols' => array('group_concat(MMG_UID order by MMG_UID) as UIDS'), 'where' => array('MMG_FOLDER' => $this->imapProxy->currentFolder64, 'MMG_FOLDER_UUID' => $this->imapProxy->currentFolderStatus['uidvalidity'], 'MMG_UID' => array('IN', $aMsg)))); $aMMGId = explode(',', $aMMG[0]['uids']); $aMsgToDo = array_diff($aMsg, $aMMGId); $aTmp = $this->imapProxy->fetch_overviewWithCache($aMsgToDo, array('account' => $o['account'], 'folder' => $this->imapProxy->currentFolder64)); foreach ($aTmp as $aHeader) { $from = $aHeader->from[0]->name ? $aHeader->from[0]->name : $aHeader->from[0]->email; if (!array_key_exists($from, $aResults)) { $aResults[$from] = array(); } $aResults[$from][] = $aHeader->subject; } } if (count($aResults) > 0) { $this->stomp->send("/topic/imapNotifierOnMessage/" . $o['account'], json_encode(array('newEmails' => $aResults))); } } }
/** */ protected function _content() { $inbox = IMP_Mailbox::get('INBOX'); /* Filter on INBOX display, if requested. */ $inbox->filterOnDisplay(); $query = new Horde_Imap_Client_Search_Query(); $query->flag(Horde_Imap_Client::FLAG_SEEN, false); $ids = $inbox->runSearchQuery($query, Horde_Imap_Client::SORT_SEQUENCE, 1); $indices = $ids['INBOX']; $html = '<table cellspacing="0" width="100%">'; $text = _("Go to your Inbox..."); if (empty($indices)) { $html .= '<tr><td><em>' . _("No unread messages") . '</em></td></tr>'; } else { $imp_ui = new IMP_Mailbox_Ui($inbox); $shown = empty($this->_params['msgs_shown']) ? 3 : $this->_params['msgs_shown']; $query = new Horde_Imap_Client_Fetch_Query(); $query->envelope(); try { $imp_imap = $GLOBALS['injector']->getInstance('IMP_Factory_Imap')->create($inbox); $fetch_ret = $imp_imap->fetch($inbox, $query, array('ids' => $imp_imap->getIdsOb(array_slice($indices, 0, $shown)))); } catch (IMP_Imap_Exception $e) { $fetch_ret = new Horde_Imap_Client_Fetch_Results(); } foreach ($fetch_ret as $uid => $ob) { $envelope = $ob->getEnvelope(); $date = $imp_ui->getDate(isset($envelope->date) ? $envelope->date : null); $from = $imp_ui->getFrom($envelope); $subject = $imp_ui->getSubject($envelope->subject, true); $html .= '<tr style="cursor:pointer" class="text"><td>' . $inbox->url('message', $uid)->link() . '<strong>' . htmlspecialchars($from['from'], ENT_QUOTES, 'UTF-8') . '</strong><br />' . $subject . '</a></td>' . '<td>' . htmlspecialchars($date, ENT_QUOTES, 'UTF-8') . '</td></tr>'; } $more_msgs = count($indices) - $shown; if ($more_msgs > 0) { $text = sprintf(ngettext("%d more unseen message...", "%d more unseen messages...", $more_msgs), $more_msgs); } } return $html . '<tr><td colspan="2" style="cursor:pointer" align="right">' . $inbox->url('mailbox')->link() . $text . '</a></td></tr>' . '</table>'; }
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)); }
/** */ protected function _expunge($options) { $expunged_ob = $modseq = null; $ids = $options['ids']; $list_msgs = !empty($options['list']); $uidplus = $this->queryCapability('UIDPLUS'); $unflag = array(); $use_cache = $this->_initCache(true); if ($ids->all) { if (!$uidplus || $list_msgs || $use_cache) { $ids = $this->resolveIds($this->_selected, $ids, 2); } } elseif ($uidplus) { /* If QRESYNC is not available, and we are returning the list of * expunged messages (or we are caching), we have to make sure we * have a mapping of Sequence -> UIDs. If we have QRESYNC, the * server SHOULD return a VANISHED response with UIDs. However, * even if the server returns EXPUNGEs instead, we can use * vanished() to grab the list. */ unset($this->_temp['search_save']); if (isset($this->_temp['enabled']['QRESYNC'])) { $ids = $this->resolveIds($this->_selected, $ids, 1); if ($list_msgs) { $modseq = $this->_mailboxOb()->getStatus(Horde_Imap_Client::STATUS_HIGHESTMODSEQ); } } else { $ids = $this->resolveIds($this->_selected, $ids, $list_msgs || $use_cache ? 2 : 1); } if (!empty($this->_temp['search_save'])) { $ids = $this->getIdsOb(Horde_Imap_Client_Ids::SEARCH_RES); } } else { /* Without UIDPLUS, need to temporarily unflag all messages marked * as deleted but not a part of requested IDs to delete. Use NOT * searches to accomplish this goal. */ $squery = new Horde_Imap_Client_Search_Query(); $squery->flag(Horde_Imap_Client::FLAG_DELETED, true); $squery->ids($ids, true); $s_res = $this->search($this->_selected, $squery, array('results' => array(Horde_Imap_Client::SEARCH_RESULTS_MATCH, Horde_Imap_Client::SEARCH_RESULTS_SAVE))); $this->store($this->_selected, array('ids' => empty($s_res['save']) ? $s_res['match'] : $this->getIdsOb(Horde_Imap_Client_Ids::SEARCH_RES), 'remove' => array(Horde_Imap_Client::FLAG_DELETED))); $unflag = $s_res['match']; } if ($list_msgs) { $expunged_ob = $this->getIdsOb(); $this->_temp['expunged'] = $expunged_ob; } /* Always use UID EXPUNGE if available. */ if ($uidplus) { /* We can only pipeline STORE w/ EXPUNGE if using UIDs and UIDPLUS * is available. */ if (empty($options['delete'])) { $pipeline = $this->_pipeline(); } else { $pipeline = $this->_storeCmd(array('add' => array(Horde_Imap_Client::FLAG_DELETED), 'ids' => $ids)); } foreach ($ids->split(2000) as $val) { $pipeline->add($this->_command('UID EXPUNGE')->add($val)); } $resp = $this->_sendCmd($pipeline); } else { if (!empty($options['delete'])) { $this->store($this->_selected, array('add' => array(Horde_Imap_Client::FLAG_DELETED), 'ids' => $ids)); } if ($use_cache || $list_msgs) { $this->_sendCmd($this->_command('EXPUNGE')); } else { /* This is faster than an EXPUNGE because the server will not * return untagged EXPUNGE responses. We can only do this if * we are not updating cache information. */ $this->close(array('expunge' => true)); } } unset($this->_temp['expunged']); if (!empty($unflag)) { $this->store($this->_selected, array('add' => array(Horde_Imap_Client::FLAG_DELETED), 'ids' => $unflag)); } if (!is_null($modseq) && !empty($resp->data['expunge_seen'])) { /* There's a chance we actually did a full map of sequence -> UID, * but this code should never be reached in the first place so * be ultra-safe and just do a full VANISHED search. */ $expunged_ob = $this->vanished($this->_selected, $modseq, array('ids' => $ids)); $this->_deleteMsgs($this->_selected, $expunged_ob, array('pipeline' => $resp)); } return $expunged_ob; }
/** * Returns a query object prepared for adding further criteria. * * @return Ingo_IMAP_Search_Query A query object. */ protected function _getQuery() { $ob = new Horde_Imap_Client_Search_Query(); $ob->flag('\\deleted', false); if ($this->_params['filter_seen'] == Ingo::FILTER_SEEN || $this->_params['filter_seen'] == Ingo::FILTER_UNSEEN) { $ob->flag('\\seen', $this->_params['filter_seen'] == Ingo::FILTER_SEEN); } return $ob; }
/** */ protected function _expunge($options) { $unflag = array(); $mailbox = clone $this->_selected; $s_res = null; $uidplus = $this->queryCapability('UIDPLUS'); $use_cache = $this->_initCache(true); if ($options['ids']->all) { $uid_string = strval($options['ids']); } elseif ($uidplus) { /* UID EXPUNGE command needs UIDs. */ if ($options['ids']->sequence) { $results = array(Horde_Imap_Client::SEARCH_RESULTS_MATCH); if ($this->queryCapability('SEARCHRES')) { $results[] = Horde_Imap_Client::SEARCH_RESULTS_SAVE; } $s_res = $this->search($mailbox, null, array('results' => $results)); $uid_string = in_array(Horde_Imap_Client::SEARCH_RESULTS_SAVE, $results) && !empty($s_res['save']) ? '$' : strval($s_res['match']); } else { $uid_string = strval($options['ids']); } } else { /* Without UIDPLUS, need to temporarily unflag all messages marked * as deleted but not a part of requested IDs to delete. Use NOT * searches to accomplish this goal. */ $search_query = new Horde_Imap_Client_Search_Query(); $search_query->flag(Horde_Imap_Client::FLAG_DELETED, true); if ($options['ids']->search_res) { $search_query->previousSearch(true); } else { $search_query->ids($options['ids'], true); } $res = $this->search($mailbox, $search_query); $this->store($mailbox, array('ids' => $res['match'], 'remove' => array(Horde_Imap_Client::FLAG_DELETED))); $unflag = $res['match']; } $list_msgs = !empty($options['list']); $tmp =& $this->_temp; $tmp['expunge'] = $tmp['vanished'] = array(); /* We need to get sequence num -> UID lookup table if we are caching. * There is no guarantee that if we are using QRESYNC that we will get * VANISHED responses, so this is unfortunately necessary. */ if (is_null($s_res) && ($list_msgs || $use_cache)) { $s_res = $uidplus ? $this->_getSeqUidLookup($options['ids'], true) : $this->_getSeqUidLookup($this->getIdsOb(Horde_Imap_Client_Ids::ALL, true)); } /* Always use UID EXPUNGE if available. */ if ($uidplus) { $cmd = $this->_clientCommand(array('UID', 'EXPUNGE', $uid_string)); $this->_sendLine($cmd); } elseif ($use_cache || $list_msgs) { $this->_sendLine($this->_clientCommand('EXPUNGE')); } else { /* This is faster than an EXPUNGE because the server will not * return untagged EXPUNGE responses. We can only do this if * we are not updating cache information. */ $this->close(array('expunge' => true)); } if (!empty($unflag)) { $this->store($mailbox, array('add' => array(Horde_Imap_Client::FLAG_DELETED), 'ids' => $unflag)); } if (!$use_cache && !$list_msgs) { return null; } $expunged = array(); if (!empty($tmp['vanished'])) { $expunged = $tmp['vanished']->ids; } elseif (!empty($tmp['expunge'])) { $lookup = $s_res['lookup']; /* Expunge responses can come in any order. Thus, we need to * reindex anytime we have an index that appears equal to or * after a previously seen index. If an IMAP server is smart, * it will expunge in reverse order instead. */ foreach ($tmp['expunge'] as &$val) { $found = false; $tmp2 = array(); foreach (array_keys($lookup) as $i => $seq) { if ($found) { $tmp2[$seq - 1] = $lookup[$seq]; } elseif ($seq == $val) { $expunged[] = $lookup[$seq]; $tmp2 = array_slice($lookup, 0, $i, true); $found = true; } } $lookup = $tmp2; } } if (empty($expunged)) { return null; } if ($use_cache) { $this->_deleteMsgs($mailbox, $expunged); } /* Update MODSEQ if active for mailbox (QRESYNC only; CONDSTORE * requires us to re-SELECT/EXAMINE the mailbox). */ if (!empty($this->_temp['mailbox']['highestmodseq']) && isset($this->_init['enabled']['QRESYNC'])) { $this->_updateMetaData($mailbox, array(self::CACHE_MODSEQ => $this->_temp['mailbox']['highestmodseq']), isset($this->_temp['mailbox']['uidvalidity']) ? $this->_temp['mailbox']['uidvalidity'] : null); } return $list_msgs ? $this->getIdsOb($expunged, $options['ids']->sequence) : null; }
/** * Get the list of unseen messages in the mailbox (IMAP UNSEEN flag, with * UNDELETED if we're hiding deleted messages). * * @param integer $results A Horde_Imap_Client::SEARCH_RESULTS_* constant * that indicates the desired return type. * @param array $opts Additional options: * - sort: (array) List of sort criteria to use. * - uids: (boolean) Return UIDs instead of sequence numbers (for * $results queries that return message lists). * DEFAULT: false * * @return mixed Whatever is requested in $results. */ public function unseenMessages($results, array $opts = array()) { $count = $results == Horde_Imap_Client::SEARCH_RESULTS_COUNT; if (empty($this->_sorted)) { return $count ? 0 : array(); } $criteria = new Horde_Imap_Client_Search_Query(); $imp_imap = $this->_mailbox->imp_imap; if ($this->_mailbox->hideDeletedMsgs()) { $criteria->flag(Horde_Imap_Client::FLAG_DELETED, false); } elseif ($count) { try { $status_res = $imp_imap->status($this->_mailbox, Horde_Imap_Client::STATUS_UNSEEN); return $status_res['unseen']; } catch (IMP_Imap_Exception $e) { return 0; } } $criteria->flag(Horde_Imap_Client::FLAG_SEEN, false); try { $res = $imp_imap->search($this->_mailbox, $criteria, array('results' => array($results), 'sequence' => empty($opts['uids']), 'sort' => empty($opts['sort']) ? null : $opts['sort'])); return $count ? $res['count'] : $res; } catch (IMP_Imap_Exception $e) { return $count ? 0 : array(); } }
/** * Returns the message ids of the messages in this folder. * * @param string $folder Check the status of this folder. * * @return array The message ids. */ public function getUids($folder) { $search_query = new Horde_Imap_Client_Search_Query(); $search_query->flag('DELETED', false); try { $uidsearch = $this->getBackend()->search($folder, $search_query); } 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); } $uids = $uidsearch['match']; return $uids->ids; }
/** * 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'); } }
/** * Close the connection to the currently selected mailbox, optionally * expunging all deleted messages (RFC 3501 [6.4.2]). * * @param array $options Additional options: * - expunge: (boolean) Expunge all messages flagged as deleted? * DEFAULT: No * * @throws Horde_Imap_Client_Exception */ public function close(array $options = array()) { // This check catches the non-logged in case. if (is_null($this->_selected)) { return; } /* If we are caching, search for deleted messages. */ if (!empty($options['expunge']) && $this->_initCache(true)) { /* Make sure mailbox is read-write to expunge. */ $this->openMailbox($this->_selected, Horde_Imap_Client::OPEN_READWRITE); if ($this->_mode == Horde_Imap_Client::OPEN_READONLY) { throw new Horde_Imap_Client_Exception(Horde_Imap_Client_Translation::r("Cannot expunge read-only mailbox."), Horde_Imap_Client_Exception::MAILBOX_READONLY); } $search_query = new Horde_Imap_Client_Search_Query(); $search_query->flag(Horde_Imap_Client::FLAG_DELETED, true); $search_res = $this->search($this->_selected, $search_query); $mbox = $this->_selected; } else { $search_res = null; } $this->_close($options); $this->_selected = null; $this->_mode = 0; if (!is_null($search_res)) { $this->_deleteMsgs($mbox, $search_res['match']); } }
/** * @depends testMoveMessage */ public function testOptimizedSearches() { // Searching test mailbox (should be optimized by using internal // status instead). $res = self::$live->search(self::$test_mbox, new Horde_Imap_Client_Search_Query(), array('results' => array(Horde_Imap_Client::SEARCH_RESULTS_COUNT))); $this->assertEquals(4, $res['count']); // All messages are unseen $query2 = new Horde_Imap_Client_Search_Query(); $query2->flag(Horde_Imap_Client::FLAG_SEEN, false); $res = self::$live->search(self::$test_mbox, $query2, array('results' => array(Horde_Imap_Client::SEARCH_RESULTS_COUNT))); $this->assertEquals(4, $res['count']); }
$ns_info = $mailbox->imp_imap->getNamespace(IMP_Imap::NS_DEFAULT); $mailbox = IMP_Mailbox::get(preg_replace('/\\//', $ns_info->delimiter, trim($request_parts[0], '/')))->namespace_append; /* Make sure mailbox exists or else exit immediately. */ if (!$mailbox->exists) { exit; } } $new_mail = isset($request_parts[1]) && $request_parts[1] === 'new'; } $imp_mailbox = $mailbox->list_ob; /* Obtain some information describing the mailbox state. */ $total_num = count($imp_mailbox); $unseen_num = $mailbox->vinbox ? $total_num : $imp_mailbox->unseenMessages(Horde_Imap_Client::SEARCH_RESULTS_COUNT); $query = new Horde_Imap_Client_Search_Query(); if ($new_mail) { $query->flag(Horde_Imap_Client::FLAG_SEEN, false); } $ids = $mailbox->runSearchQuery($query, Horde_Imap_Client::SORT_ARRIVAL, 1); if (count($ids)) { $imp_ui = new IMP_Mailbox_Ui($mailbox); $overview = $imp_mailbox->getMailboxArray(array_slice($ids[strval($mailbox)], 0, 20), array('preview' => $prefs->getValue('preview_enabled'))); foreach ($overview['overview'] as $ob) { $from_addr = $imp_ui->getFrom($ob['envelope']); $items[] = array_map('htmlspecialchars', array('title' => $imp_ui->getSubject($ob['envelope']->subject), 'pubDate' => $ob['envelope']->date->format('r'), 'description' => isset($ob['preview']) ? $ob['preview'] : '', 'url' => Horde::url($mailbox->url('message', $imp_mailbox->getBuid($mailbox, $ob['uid'])), true, array('append_session' => -1)), 'fromAddr' => strval($from_addr['from_list']), 'toAddr' => strval($ob['envelope']->to))); } } $description = $total_num === 0 ? _("No Messages") : sprintf(_("%u of %u messages in %s unread."), $unseen_num, $total_num, $mailbox->label); $view = new Horde_View(array('templatePath' => IMP_TEMPLATES . '/rss')); $view->addHelper('Text'); $view->desc = $description; $view->items = $items;