]> git.g-eek.se Git - interimap.git/commitdiff
Net::IMAP::InterIMAP: Don't increase UIDNEXT when receiving EXISTS responses.
authorGuilhem Moulin <guilhem@fripost.org>
Fri, 11 Mar 2016 21:04:17 +0000 (22:04 +0100)
committerGuilhem Moulin <guilhem@fripost.org>
Fri, 11 Mar 2016 23:48:39 +0000 (00:48 +0100)
Indeed, if the server sends

    * n EXISTS
    * n EXPUNGE

meaning a new message is received, and is immediately removed
afterwards, the server might have allocated a new UID for the removed
message.

lib/Net/IMAP/InterIMAP.pm

index be61cb6e250fc9aeef199638c3d483a2c96f70c2..cdc5697aef2c6067aa17916a329f8809787607f2 100644 (file)
@@ -645,6 +645,7 @@ sub unselect($) {
     # we'll get back to it
     $self->{_VANISHED} = [];
     $self->{_MODIFIED} = {};
+    $self->{_NEW} = 0;
 }
 
 
@@ -1082,6 +1083,7 @@ sub get_cache($@) {
 #   persistent cache's values.
 sub is_dirty($$) {
     my ($self, $mailbox) = @_;
+    return 1 if $self->{_NEW};
     $self->_updated_cache($mailbox, qw/HIGHESTMODSEQ UIDNEXT/);
 }
 
@@ -1091,6 +1093,7 @@ sub is_dirty($$) {
 #   internal cache's UIDNEXT value differs from its persistent cache's.
 sub has_new_mails($$) {
     my ($self, $mailbox) = @_;
+    return 1 if $self->{_NEW};
     $self->_updated_cache($mailbox, 'UIDNEXT');
 }
 
@@ -1181,6 +1184,7 @@ sub pull_new_messages($$&@) {
     my @ignore = sort { $a <=> $b } @_;
 
     my $mailbox = $self->{_SELECTED} // $self->panic();
+    my $cache = $self->{_CACHE}->{$mailbox};
 
     my $UIDNEXT;
     do {
@@ -1205,19 +1209,20 @@ sub pull_new_messages($$&@) {
         # 2^32-1: don't use '*' since the highest UID can be known already
         $range .= "$since:4294967295";
 
-        $UIDNEXT = $self->{_CACHE}->{$mailbox}->{UIDNEXT} // $self->panic(); # sanity check
+        $UIDNEXT = $cache->{UIDNEXT} // $self->panic(); # sanity check
         $self->_send("UID FETCH $range ($attrs)", sub($) {
             my $mail = shift;
             $UIDNEXT = $mail->{UID} + 1 if $UIDNEXT <= $mail->{UID};
             $callback->($mail) if defined $callback;
-        }) if $first < $UIDNEXT;
+        }) if $first < $UIDNEXT or $self->{_NEW};
 
         # update the persistent cache for UIDNEXT (not for HIGHESTMODSEQ
         # since there might be pending updates)
         $self->set_cache($mailbox, UIDNEXT => $UIDNEXT);
+        $self->{_NEW} = 0;
     }
     # loop if new messages were received in the meantime
-    while ($UIDNEXT < $self->{_CACHE}->{$mailbox}->{UIDNEXT});
+    while ($self->{_NEW} or $UIDNEXT < $cache->{UIDNEXT});
 }
 
 
@@ -1993,6 +1998,7 @@ sub _open_mailbox($$) {
     # we'll get back to it
     $self->{_VANISHED} = [];
     $self->{_MODIFIED} = {};
+    $self->{_NEW} = 0;
 
     $self->{_SELECTED} = $mailbox;
     $self->{_CACHE}->{$mailbox} //= {};
@@ -2233,12 +2239,12 @@ sub _resp($$;&$$) {
             # /!\ $cache->{EXISTS} MUST NOT be defined on SELECT
             if (defined $cache->{EXISTS}) {
                 $self->panic("Unexpected EXISTS shrink $1 < $cache->{EXISTS}!") if $1 < $cache->{EXISTS};
-                # the actual UIDNEXT is *at least* that
-                $cache->{UIDNEXT} += $1 - $cache->{EXISTS} if defined $cache->{UIDNEXT};
+                $self->{_NEW} += $1 - $cache->{EXISTS} if $1 > $cache->{EXISTS}; # new mails
             }
             $cache->{EXISTS} = $1;
         }
         elsif (/\A([0-9]+) EXPUNGE\z/) {
+            $self->panic() unless defined $cache->{EXISTS}; # sanity check
             # /!\ No bookkeeping since there is no internal cache mapping sequence numbers to UIDs
             if ($self->_enabled('QRESYNC')) {
                 $self->panic("$1 <= $cache->{EXISTS}") if $1 <= $cache->{EXISTS}; # sanity check
@@ -2270,7 +2276,7 @@ sub _resp($$;&$$) {
             $callback->($mailbox, %status) if defined $callback and $cmd eq 'STATUS';
         }
         elsif (s/\A([0-9]+) FETCH \(//) {
-            $self->panic("$1 <= $cache->{EXISTS}") unless $1 <= $cache->{EXISTS}; # sanity check
+            $cache->{EXISTS} = $1 if $1 > $cache->{EXISTS};
             my ($seq, $first) = ($1, 1);
             my %mail;
             while ($_ ne ')') {