From 4a291f2bc29c735e8f73aa2b476fe932517b83b5 Mon Sep 17 00:00:00 2001
From: Guilhem Moulin <guilhem@fripost.org>
Date: Sat, 5 Sep 2015 16:44:51 +0200
Subject: Sample UIDs in SELECT $mailbox (QRESYNC ...) commands.

This should avoids most false-positive among messages reported as
VANISHED by the server but unknown from the database.  The reason for
this server behavior is that QRESYNC [RFC7162] doesn't force the server
to remember the MODSEQs of EXPUNGEd messages.  By passing a sample of
known UIDs/sequence numbers we let the server know that the messages
have been EXPUNGEd [RFC7162, section 3.2.5.2].
---
 lib/Net/IMAP/Sync.pm | 31 +++++++++++++++++++------------
 1 file changed, 19 insertions(+), 12 deletions(-)

(limited to 'lib/Net/IMAP')

diff --git a/lib/Net/IMAP/Sync.pm b/lib/Net/IMAP/Sync.pm
index 85ca487..ca85a54 100644
--- a/lib/Net/IMAP/Sync.pm
+++ b/lib/Net/IMAP/Sync.pm
@@ -482,19 +482,21 @@ sub search($$) {
 }
 
 
-# $self->select($mailbox)
-# $self->examine($mailbox)
+# $self->select($mailbox,  [$UIDs, $seqs])
+# $self->examine($mailbox, [$UIDs, $seqs])
 #   Issue a SELECT or EXAMINE command for the $mailbox. Upon success,
 #   change the state to SELECTED, otherwise go back to AUTH.
-sub select($$) {
+#   The optional $UIDs and $seqs are passed are 3rd and 4th arguments to
+#   the QRESYNC parameter, respectively.
+sub select($$;$$) {
     my $self = shift;
     my $mailbox = shift;
-    $self->_select_or_examine('SELECT', $mailbox);
+    $self->_select_or_examine('SELECT', $mailbox, @_);
 }
-sub examine($$) {
+sub examine($$;$$) {
     my $self = shift;
     my $mailbox = shift;
-    $self->_select_or_examine('EXAMINE', $mailbox);
+    $self->_select_or_examine('EXAMINE', $mailbox, @_);
 }
 
 
@@ -1276,13 +1278,16 @@ sub _open_mailbox($$) {
 }
 
 
-# $self->_select_or_examine($command, $mailbox)
+# $self->_select_or_examine($command, $mailbox, [$UIDs, $seqs])
 #   Issue a SELECT or EXAMINE command for the $mailbox.  Upon success,
 #   change the state to SELECTED, otherwise go back to AUTH.
-sub _select_or_examine($$$) {
+#   The optional $UIDs and $seqs are passed are 3rd and 4th arguments to
+#   the QRESYNC parameter, respectively.
+sub _select_or_examine($$$;$$) {
     my $self = shift;
     my $command = shift;
     my $mailbox = shift;
+    my ($uids, $seqs) = @_;
 
     my $pcache = $self->{_PCACHE}->{$mailbox} //= {};
     my $cache = $self->{_CACHE}->{$mailbox} //= {};
@@ -1290,10 +1295,12 @@ sub _select_or_examine($$$) {
 
     $mailbox = uc $mailbox eq 'INBOX' ? 'INBOX' : $mailbox; # INBOX is case-insensitive
     $command .= ' '.quote($mailbox);
-    $command .= " (QRESYNC ($pcache->{UIDVALIDITY} $pcache->{HIGHESTMODSEQ} "
-                           ."1:".($pcache->{UIDNEXT}-1)."))"
-        if $self->_enabled('QRESYNC') and
-           ($pcache->{HIGHESTMODSEQ} // 0) > 0 and ($pcache->{UIDNEXT} // 1) > 1;
+    if ($self->_enabled('QRESYNC') and ($pcache->{HIGHESTMODSEQ} // 0) > 0 and ($pcache->{UIDNEXT} // 1) > 1) {
+        $command .= " (QRESYNC ($pcache->{UIDVALIDITY} $pcache->{HIGHESTMODSEQ} "
+                               ."1:".($pcache->{UIDNEXT}-1);
+        $command .= " ($uids $seqs)" if defined $uids and defined $seqs;
+        $command .= "))";
+    }
 
     if ($self->{_STATE} eq 'SELECTED' and ($self->_capable('CONDSTORE') or $self->_capable('QRESYNC'))) {
         # A mailbox is currently selected and the server advertises
-- 
cgit v1.2.3