From: Michael M Slusarz Date: Wed, 25 Mar 2009 06:38:32 +0000 (-0600) Subject: Continue trying to sort out the CONDSTORE/QRESYNC mess. X-Git-Url: https://git.internetallee.de/?a=commitdiff_plain;h=099a0cb3a9bc7b309a30f520da59a9c42be5ffeb;p=horde.git Continue trying to sort out the CONDSTORE/QRESYNC mess. --- diff --git a/framework/Imap_Client/lib/Horde/Imap/Client/Base.php b/framework/Imap_Client/lib/Horde/Imap/Client/Base.php index e5907dfe4..aa025be60 100644 --- a/framework/Imap_Client/lib/Horde/Imap/Client/Base.php +++ b/framework/Imap_Client/lib/Horde/Imap/Client/Base.php @@ -907,9 +907,9 @@ abstract class Horde_Imap_Client_Base * * Flag: Horde_Imap_Client::STATUS_HIGHESTMODSEQ * Return key: 'highestmodseq' - * Return format: (mixed) If the server supports the CONDSTORE IMAP + * Return format: (integer) If the server supports the CONDSTORE IMAP * extension, this will be the highest mod-sequence value - * of all messages in the mailbox or null if the mailbox + * of all messages in the mailbox or 0 if the mailbox * does not support mod-sequences. Else, this value will * be undefined. * @@ -1313,7 +1313,9 @@ abstract class Horde_Imap_Client_Base !$query->flagSearch())) { $cache = $this->_getSearchCache('search', $mailbox, $options); if (isset($cache['data'])) { - $cache['data'][$type] = $this->_utils->fromSequenceString($cache['data'][$type]); + if (isset($cache['data'][$type])) { + $cache['data'][$type] = $this->_utils->fromSequenceString($cache['data'][$type]); + } return $cache['data']; } } @@ -1328,7 +1330,9 @@ abstract class Horde_Imap_Client_Base if ($cache) { $save = $ret; - $save[$type] = $this->_utils->toSequenceString($ret[$type], array('nosort' => true)); + if (isset($save[$type])) { + $save[$type] = $this->_utils->toSequenceString($ret[$type], array('nosort' => true)); + } $this->_setSearchCache($save, $cache); } @@ -1903,15 +1907,14 @@ abstract class Horde_Imap_Client_Base if (!$qresync) { /* Grab all flags updated since the cached modseq * val. */ - $metadata = $this->_cache->getMetaData($this->_selected, array('HICmodseq')); + $metadata = $this->_cache->getMetaData($this->_selected, $status_res['uidvalidity'], array('HICmodseq')); if (isset($metadata['HICmodseq']) && ($metadata['HICmodseq'] != $status_res['highestmodseq'])) { $uids = $this->_cache->get($this->_selected, array(), array(), $status_res['uidvalidity']); if (!empty($uids)) { $this->_fetch(array(Horde_Imap_Client::FETCH_FLAGS => true), array('changedsince' => $metadata['HICmodseq'], 'ids' => $uids)); } - - $this->_updateMetaData($mailbox, array('HICmodseq' => $status_res['highestmodseq'])); + $this->_updateMetaData($this->_selected, $status_res['highestmodseq']); } } @@ -1966,14 +1969,7 @@ abstract class Horde_Imap_Client_Base } /* Get the cached values. */ - try { - $data = $this->_cache->get($this->_selected, $uids, $get_fields, $status_res['uidvalidity']); - } catch (Horde_Imap_Client_Exception $e) { - if ($e->getCode() != Horde_Imap_Client_Exception::CACHEUIDINVALID) { - throw $e; - } - $data = array(); - } + $data = $this->_cache->get($this->_selected, $uids, $get_fields, $status_res['uidvalidity']); // Build a list of what we still need. foreach ($uids as $val) { @@ -2456,20 +2452,26 @@ abstract class Horde_Imap_Client_Base } $cf = $this->_params['cache']['fields']; - $is_flags = false; - $highestmodseq = $tocache = array(); + $tocache = array(); $mailbox = empty($options['mailbox']) ? $this->_selected : $options['mailbox']; + $status_flags = 0; + if (isset($this->_init['enabled']['CONDSTORE'])) { + $status_flags |= Horde_Imap_Client::STATUS_HIGHESTMODSEQ; + } if (empty($options['uidvalid'])) { - $status_res = $this->status($mailbox, Horde_Imap_Client::STATUS_HIGHESTMODSEQ | Horde_Imap_Client::STATUS_UIDVALIDITY); - $uidvalid = $status_res['uidvalidity']; - if (isset($status_res['highestmodseq'])) { - $highestmodseq[] = $status_res['highestmodseq']; - } - } else { - $uidvalid = $options['uidvalid']; + $status_flags |= Horde_Imap_Client::STATUS_UIDVALIDITY; } + $status_res = $this->status($mailbox, $status_flags); + + $highestmodseq = isset($status_res['highestmodseq']) + ? array($status_res['highestmodseq']) + : array(); + $uidvalid = isset($status_res['uidvalidity']) + ? $status_res['uidvalidity'] + : $options['uidvalid']; + reset($data); while (list($k, $v) = each($data)) { $tmp = array(); @@ -2505,7 +2507,6 @@ abstract class Horde_Imap_Client_Base $highestmodseq[] = $v['modseq']; } $tmp['HICflags'] = $val; - $is_flags = true; } break; @@ -2528,14 +2529,14 @@ abstract class Horde_Imap_Client_Base } } - try { - $this->_cache->set($mailbox, $tocache, $uidvalid); - if ($is_flags) { - $this->_updateMetaData($mailbox, array('HICmodseq' => max($highestmodseq))); - } - } catch (Horde_Imap_Client_Exception $e) { - if ($e->getCode() != Horde_Imap_Client_Exception::CACHEUIDINVALID) { - throw $e; + $this->_cache->set($mailbox, $tocache, $uidvalid); + + if (!empty($highestmodseq)) { + $modseq = max($highestmodseq); + $metadata = $this->_cache->getMetaData($this->_selected, $uidvalid, array('HICmodseq')); + if (isset($metadata['HICmodseq']) && + ($metadata['HICmodseq'] != $modseq)) { + $this->_updateMetaData($mailbox, array('HICmodseq' => $modseq)); } } } @@ -2554,19 +2555,19 @@ abstract class Horde_Imap_Client_Base { ksort($options); $cache = hash('md5', $type . serialize($options)); - $metadata = $this->_cache->getMetaData($mailbox, array('HICsearch')); - - /* Do check for cache expiration for non-CONDSTORE hosts here. */ - if (!isset($this->_init['enabled']['CONDSTORE'])) { - $mboxid = $this->getCacheId($mailbox); - if (isset($metadata['HICsearch']['cacheid']) && - ($metadata['HICsearch']['cacheid'] != $mboxid)) { - $metadata['HICsearch'] = array(); - if ($this->_debug) { - fwrite($this->_debug, sprintf("Horde_Imap_Client: Expired %s results from cache (mailbox: %s; id: %s)\n", $type, $mailbox, $cache)); - } + + $status = $this->status($mailbox, Horde_Imap_Client::STATUS_UIDVALIDITY); + $metadata = $this->_cache->getMetaData($mailbox, $status['uidvalidity'], array('HICsearch')); + print_r($metadata); + + $cacheid = $this->getCacheId($mailbox); + print "CACHEID: $cacheid\n"; + if (isset($metadata['HICsearch']['cacheid']) && + ($metadata['HICsearch']['cacheid'] != $cacheid)) { + $metadata['HICsearch'] = array(); + if ($this->_debug) { + fwrite($this->_debug, sprintf("Horde_Imap_Client: Expired search results from cache (mailbox: %s)\n", $mailbox)); } - $metadata['HICsearch']['cacheid'] = $mboxid; } if (isset($metadata['HICsearch'][$cache])) { @@ -2576,6 +2577,8 @@ abstract class Horde_Imap_Client_Base return array('data' => unserialize($metadata['HICsearch'][$cache])); } + $metadata['HICsearch']['cacheid'] = $cacheid; + return array( 'id' => $cache, 'mailbox' => $mailbox, @@ -2594,6 +2597,7 @@ abstract class Horde_Imap_Client_Base protected function _setSearchCache($data, $cache) { $cache['metadata']['HICsearch'][$cache['id']] = serialize($data); + $this->_updateMetaData($cache['mailbox'], $cache['metadata']); if ($this->_debug) { @@ -2602,20 +2606,15 @@ abstract class Horde_Imap_Client_Base } /** - * Update metadata entries. + * Updates metadata for a mailbox. * * @param string $mailbox Mailbox to update. - * @param array $data The data to update with. + * @param string $data The data to update. */ protected function _updateMetaData($mailbox, $data) { - /* If we see that HICmodseq is being updated, we know that we have - * to invalidate the search cache. */ - if (isset($data['HICmodseq']) && !isset($data['HICsearch'])) { - $data['HICsearch'] = array(); - } - - $this->_cache->setMetaData($mailbox, $data); + $status = $this->status($mailbox, Horde_Imap_Client::STATUS_UIDVALIDITY); + $this->_cache->setMetaData($mailbox, $status['uidvalidity'], $data); } } diff --git a/framework/Imap_Client/lib/Horde/Imap/Client/Cache.php b/framework/Imap_Client/lib/Horde/Imap/Client/Cache.php index 8da395c38..e52741874 100644 --- a/framework/Imap_Client/lib/Horde/Imap/Client/Cache.php +++ b/framework/Imap_Client/lib/Horde/Imap/Client/Cache.php @@ -266,7 +266,7 @@ class Horde_Imap_Client_Cache * the uidvalidity is still valid. * @param integer $uidvalid The IMAP uidvalidity value of the mailbox. */ - public function set($mailbox, $data, $uidvalid = null) + public function set($mailbox, $data, $uidvalid) { $save = array_keys($data); if (empty($save)) { @@ -303,9 +303,10 @@ class Horde_Imap_Client_Cache /** * Get metadata information for a mailbox. * - * @param string $mailbox An IMAP mailbox string. - * @param array $entries An array of entries to return. If empty, - * returns all metadata. + * @param string $mailbox An IMAP mailbox string. + * @param integer $uidvalid The IMAP uidvalidity value of the mailbox. + * @param array $entries An array of entries to return. If empty, + * returns all metadata. * * @return array The requested metadata. Requested entries that do not * exist will be undefined. The following entries are @@ -314,9 +315,9 @@ class Horde_Imap_Client_Cache * 'uidvalid' - (integer) The UIDVALIDITY of the mailbox. * */ - public function getMetaData($mailbox, $entries = array()) + public function getMetaData($mailbox, $uidvalid = null, $entries = array()) { - $this->_loadSliceMap($mailbox); + $this->_loadSliceMap($mailbox, $uidvalid); return empty($entries) ? $this->_slicemap[$mailbox]['data'] : array_intersect_key($this->_slicemap[$mailbox]['data'], array_flip($entries)); @@ -325,17 +326,18 @@ class Horde_Imap_Client_Cache /** * Set metadata information for a mailbox. * - * @param string $mailbox An IMAP mailbox string. - * @param array $data The list of data to save. The keys are the - * metadata IDs, the values are the associated - * data. The following labels are reserved: - * 'uidvalid'. + * @param string $mailbox An IMAP mailbox string. + * @param integer $uidvalid The IMAP uidvalidity value of the mailbox. + * @param array $data The list of data to save. The keys are the + * metadata IDs, the values are the associated + * data. The following labels are reserved: + * 'uidvalid'. */ - public function setMetaData($mailbox, $data = array()) + public function setMetaData($mailbox, $uidvalid, $data = array()) { if (!empty($data)) { unset($data['uidvalid']); - $this->_loadSliceMap($mailbox); + $this->_loadSliceMap($mailbox, $uidvalid); $this->_slicemap[$mailbox]['data'] = array_merge($this->_slicemap[$mailbox]['data'], $data); if (!isset($this->_save[$mailbox])) { $this->_save[$mailbox] = array(); @@ -591,22 +593,24 @@ class Horde_Imap_Client_Cache $ptr = &$this->_slicemap[$mailbox]['data']['uidvalid']; if (is_null($ptr)) { $ptr = $uidvalid; + return; } elseif (!is_null($uidvalid) && ($ptr != $uidvalid)) { $this->deleteMailbox($mailbox); - throw new Horde_Imap_Client_Exception('UIDs have been invalidated', Horde_Imap_Client_Exception::CACHEUIDINVALID); + } else { + return; } - } else { - $this->_slicemap[$mailbox] = array( - // Tracking count for purposes of determining slices - 'count' => 0, - // Metadata storage - // By default includes UIDVALIDITY of mailbox. - 'data' => array('uidvalid' => $uidvalid), - // UIDs to delete - 'delete' => array(), - // The slice list. - 'slice' => array() - ); } + + $this->_slicemap[$mailbox] = array( + // Tracking count for purposes of determining slices + 'count' => 0, + // Metadata storage + // By default includes UIDVALIDITY of mailbox. + 'data' => array('uidvalid' => $uidvalid), + // UIDs to delete + 'delete' => array(), + // The slice list. + 'slice' => array() + ); } } diff --git a/framework/Imap_Client/lib/Horde/Imap/Client/Exception.php b/framework/Imap_Client/lib/Horde/Imap/Client/Exception.php index 07230f0d6..f2ae3b473 100644 --- a/framework/Imap_Client/lib/Horde/Imap/Client/Exception.php +++ b/framework/Imap_Client/lib/Horde/Imap/Client/Exception.php @@ -50,11 +50,8 @@ class Horde_Imap_Client_Exception extends Exception // mod-sequences. const MBOXNOMODSEQ = 10; - // Thrown if the cache has become invalid. - const CACHEUIDINVALID = 11; - // Thrown if server denies the network connection. - const SERVER_CONNECT = 12; + const SERVER_CONNECT = 11; /** * Define a callback function used to log the exception. Will be passed diff --git a/framework/Imap_Client/lib/Horde/Imap/Client/Socket.php b/framework/Imap_Client/lib/Horde/Imap/Client/Socket.php index ad5b7ba32..c8e6ce59b 100644 --- a/framework/Imap_Client/lib/Horde/Imap/Client/Socket.php +++ b/framework/Imap_Client/lib/Horde/Imap/Client/Socket.php @@ -34,9 +34,9 @@ * RFC 5267 - ESORT * * [NO RFC] - XIMAPPROXY - * + Requires imapproxy v1.2.7-rc1 or later - * + See http://lists.andrew.cmu.edu/pipermail/imapproxy-info/2008-October/000771.html and - * http://lists.andrew.cmu.edu/pipermail/imapproxy-info/2008-October/000772.html + * + Requires imapproxy v1.2.7-rc1 or later + * + See http://lists.andrew.cmu.edu/pipermail/imapproxy-info/2008-October/000771.html and + * http://lists.andrew.cmu.edu/pipermail/imapproxy-info/2008-October/000772.html * * TODO (or not necessary?): * RFC 2177 - IDLE (probably not necessary due to the limited connection @@ -567,15 +567,14 @@ class Horde_Imap_Client_Socket extends Horde_Imap_Client_Base /* Only active QRESYNC/CONDSTORE if caching is enabled. */ if ($this->_initCache()) { if ($this->queryCapability('QRESYNC')) { - /* QRESYNC REQUIRES ENABLE, so we just need to send one ENABLE + /* QRESYNC requires ENABLE, so we just need to send one ENABLE * QRESYNC call to enable both QRESYNC && CONDSTORE. */ $this->_enable(array('QRESYNC')); $this->_init['enabled']['CONDSTORE'] = true; - } elseif ($this->queryCapability('CONDSTORE')) { + } elseif ($this->queryCapability('CONDSTORE') && + $this->queryCapability('ENABLE')) { /* CONDSTORE may be available, but ENABLE may not be. */ - if ($this->queryCapability('ENABLE')) { - $this->_enable(array('CONDSTORE')); - } + $this->_enable(array('CONDSTORE')); } } @@ -781,7 +780,8 @@ class Horde_Imap_Client_Socket extends Horde_Imap_Client_Base /* If QRESYNC is available, synchronize the mailbox. */ if ($qresync) { $this->_initCache(); - $metadata = $this->_cache->getMetaData($mailbox, array('HICmodseq', 'uidvalid')); + $metadata = $this->_cache->getMetaData($mailbox, null, array('HICmodseq', 'uidvalid')); + if (isset($metadata['HICmodseq'])) { $uids = $this->_cache->get($mailbox); if (!empty($uids)) { @@ -818,18 +818,22 @@ class Horde_Imap_Client_Socket extends Horde_Imap_Client_Base throw $e; } - if ($qresync && isset($metadata['uidvalid'])) { - if (is_null($this->_temp['mailbox']['highestmodseq']) || - ($this->_temp['mailbox']['uidvalidity'] != $metadata['uidvalid'])) { + if ($condstore) { + $this->_init['enabled']['CONDSTORE'] = true; + } + + if (isset($this->_init['enabled']['CONDSTORE'])) { + /* MODSEQ should be set if CONDSTORE is active. Some servers won't + * advertise in SELECT/EXAMINE info though. */ + if (!isset($this->_temp['mailbox']['highestmodseq'])) { + $this->_temp['mailbox']['highestmodseq'] = 1; + } elseif ($qresync && + empty($this->_temp['mailbox']['highestmodseq'])) { + /* Check that MODSEQ is enabled for the mailbox and, if not, + * delete the cache. Note: Invalidating the cache based on + * UIDVALIDITY is done within Horde_Imap_Client_Cache::. */ $this->_cache->deleteMailbox($mailbox); - } elseif (!isset($metadata['HICmodseq']) || - ($metadata['HICmodseq'] != $this->_temp['mailbox']['highestmodseq'])) { - /* We know the mailbox has been updated, so update the - * highestmodseq metadata in the cache. */ - $this->_updateMetaData($mailbox, array('HICmodseq' => $this->_temp['mailbox']['highestmodseq'])); } - } elseif ($condstore) { - $this->_init['enabled']['CONDSTORE'] = true; } } @@ -1126,11 +1130,7 @@ class Horde_Imap_Client_Socket extends Horde_Imap_Client_Base { for ($i = 0, $len = count($data); $i < $len; $i += 2) { $item = strtolower($data[$i]); - $val = $data[$i + 1]; - if (!$val && ($item == 'highestmodseq')) { - $val = null; - } - $this->_temp['status'][$item] = $val; + $this->_temp['status'][$item] = $data[$i + 1]; } } @@ -1398,10 +1398,16 @@ class Horde_Imap_Client_Socket extends Horde_Imap_Client_Base if (!empty($expunged)) { $this->_cache->deleteMsgs($mailbox, $expunged); $tmp['mailbox']['messages'] -= $i; - } - - if (isset($this->_init['enabled']['QRESYNC'])) { - $this->_updateMetaData($mailbox, array('HICmodseq' => $this->_temp['mailbox']['highestmodseq'])); + if (isset($this->_init['enabled']['QRESYNC'])) { + $this->_updateMetaData($mailbox, array('HICmodseq' => $this->_temp['mailbox']['highestmodseq'])); + } elseif (isset($this->_init['enabled']['CONDSTORE'])) { + /* Unfortunately, RFC 4551 does not provide any method to + * obtain the HIGHESTMODSEQ after an EXPUNGE is completed. + * Instead, unselect the mailbox - if we need to reselect + * the mailbox, the HIGHESTMODSEQ info will appear in the + * EXAMINE/SELECT response. */ + $this->close(); + } } return $list_msgs ? $expunged : null; @@ -1470,7 +1476,7 @@ class Horde_Imap_Client_Socket extends Horde_Imap_Client_Base * doesn't support it will return BAD. Catch that here and thrown * an exception. */ if (($val == 'CONDSTORE') && - is_null($this->_temp['mailbox']['highestmodseq']) && + empty($this->_temp['mailbox']['highestmodseq']) && (strpos($options['_query']['query'], 'MODSEQ ') !== false)) { throw new Horde_Imap_Client_Exception('Mailbox does not support mod-sequences.', Horde_Imap_Client_Exception::MBOXNOMODSEQ); } @@ -2209,14 +2215,18 @@ class Horde_Imap_Client_Socket extends Horde_Imap_Client_Base break; case Horde_Imap_Client::FETCH_SEQ: - // Nothing we need to add to fetch criteria. + // Nothing we need to add to fetch criteria unless sequence + // is the only criteria. + if (count($criteria) == 1) { + $fetch[] = 'UID'; + } break; case Horde_Imap_Client::FETCH_MODSEQ: /* RFC 4551 [3.1] - trying to do a FETCH of MODSEQ on a * mailbox that doesn't support it will return BAD. Catch that * here and throw an exception. */ - if (is_null($this->_temp['mailbox']['highestmodseq'])) { + if (empty($this->_temp['mailbox']['highestmodseq'])) { throw new Horde_Imap_Client_Exception('Mailbox does not support mod-sequences.', Horde_Imap_Client_Exception::MBOXNOMODSEQ); } $fetch[] = 'MODSEQ'; @@ -2234,7 +2244,7 @@ class Horde_Imap_Client_Socket extends Horde_Imap_Client_Base $cmd = ($use_seq ? '' : 'UID ') . 'FETCH ' . $seq . ' (' . implode(' ', $fetch) . ')'; if (!empty($options['changedsince'])) { - if (is_null($this->_temp['mailbox']['highestmodseq'])) { + if (empty($this->_temp['mailbox']['highestmodseq'])) { throw new Horde_Imap_Client_Exception('Mailbox does not support mod-sequences.', Horde_Imap_Client_Exception::MBOXNOMODSEQ); } $cmd .= ' (CHANGEDSINCE ' . intval($options['changedsince']) . ')'; @@ -2305,6 +2315,12 @@ class Horde_Imap_Client_Socket extends Horde_Imap_Client_Base case 'MODSEQ': $tmp['modseq'] = reset($data[++$i]); + + /* Update highestmodseq, if it exists. */ + if (!empty($this->_temp['mailbox']['highestmodseq']) && + ($tmp['modseq'] > $this->_temp['mailbox']['highestmodseq'])) { + $this->_temp['mailbox']['highestmodseq'] = $tmp['modseq']; + } break; default: @@ -2620,27 +2636,35 @@ class Horde_Imap_Client_Socket extends Horde_Imap_Client_Base $cmd_prefix = (empty($options['sequence']) ? 'UID ' : '') . 'STORE ' . $seq . ' '; - $ucsince = !empty($options['unchangedsince']); - if ($ucsince) { - /* RFC 4551 [3.1] - trying to do a UNCHANGEDSINCE STORE on a - * mailbox that doesn't support it will return BAD. Catch that - * here and throw an exception. */ - if (is_null($this->_temp['mailbox']['highestmodseq'])) { + $ucsince = null; + if (empty($this->_temp['mailbox']['highestmodseq'])) { + if (!empty($options['unchangedsince'])) { + /* RFC 4551 [3.1] - trying to do a UNCHANGEDSINCE STORE on a + * mailbox that doesn't support it will return BAD. Catch that + * here and throw an exception. */ throw new Horde_Imap_Client_Exception('Mailbox does not support mod-sequences.', Horde_Imap_Client_Exception::MBOXNOMODSEQ); } + } elseif (!empty($options['unchangedsince'])) { + $ucsince = intval($options['unchangedsince']); + } else { + /* If CONDSTORE is enabled, we need to add UNCHANGEDSINCE output + * to ensure we get MODSEQ updated information. */ + $ucsince = $this->_temp['mailbox']['highestmodseq']; + } - $cmd .= '(UNCHANGEDSINCE ' . intval($options['unchangedsince']) . ') '; + if ($ucsince) { + $cmd_prefix .= '(UNCHANGEDSINCE ' . $ucsince . ') '; } $this->_temp['modified'] = array(); if (!empty($options['replace'])) { - $this->_sendLine($cmd_prefix . 'FLAGS' . ($this->_debug ? '.SILENT' : '') . ' (' . implode(' ', $options['replace']) . ')'); + $this->_sendLine($cmd_prefix . 'FLAGS' . ($this->_debug ? '' : '.SILENT') . ' (' . implode(' ', $options['replace']) . ')'); } else { foreach (array('add' => '+', 'remove' => '-') as $k => $v) { if (!empty($options[$k])) { - $this->_sendLine($cmd_prefix . $v . 'FLAGS' . ($this->_debug ? '.SILENT' : '') . ' (' . implode(' ', $options[$k]) . ')'); + $this->_sendLine($cmd_prefix . $v . 'FLAGS' . ($this->_debug ? '' : '.SILENT') . ' (' . implode(' ', $options[$k]) . ')'); } } } @@ -3554,7 +3578,7 @@ class Horde_Imap_Client_Socket extends Horde_Imap_Client_Base case 'HIGHESTMODSEQ': case 'NOMODSEQ': // Defined by RFC 4551 [3.1.1 & 3.1.2] - $this->_temp['mailbox']['highestmodseq'] = ($code == 'HIGHESTMODSEQ') ? $data : null; + $this->_temp['mailbox']['highestmodseq'] = ($code == 'HIGHESTMODSEQ') ? $data : 0; break; case 'MODIFIED':