From 7da4bafd83dbd8c84cc529b132ece06497d6f49d Mon Sep 17 00:00:00 2001 From: Guilhem Moulin Date: Fri, 24 Jul 2015 17:29:52 +0200 Subject: bugfix: new messages can be received while FETCHing new messages. --- lib/Net/IMAP/Sync.pm | 69 +++++++++++++++++++++++++++++----------------------- 1 file changed, 38 insertions(+), 31 deletions(-) diff --git a/lib/Net/IMAP/Sync.pm b/lib/Net/IMAP/Sync.pm index 1aceb70..fc1ab81 100644 --- a/lib/Net/IMAP/Sync.pm +++ b/lib/Net/IMAP/Sync.pm @@ -651,12 +651,12 @@ sub append($$$@) { my @uids; foreach (split /,/, $uidset) { if (/\A([0-9]+)\z/) { - $UIDNEXT = $1 + 1 if $UIDNEXT < $1; + $UIDNEXT = $1 + 1 if $UIDNEXT <= $1; push @uids, $1; } elsif (/\A([0-9]+):([0-9]+)\z/) { my ($min, $max) = $1 <= $2 ? ($1,$2) : ($2,$1); push @uids, ($min .. $max); - $UIDNEXT = $max + 1 if $UIDNEXT < $max; + $UIDNEXT = $max + 1 if $UIDNEXT <= $max; } else { $self->panic($_); } @@ -917,36 +917,43 @@ sub pull_new_messages($$@) { my $attrs = join ' ', qw/MODSEQ FLAGS INTERNALDATE/, @attrs, 'BODY.PEEK[]'; my $mailbox = $self->{_SELECTED} // $self->panic(); - my $since = $self->{_PCACHE}->{$mailbox}->{UIDNEXT} // 1; - - my $range = ''; - my $first; - foreach my $uid (@ignore) { - if ($since < $uid) { - $first //= $since; - $range .= ',' if $range ne ''; - $range .= $since; - $range .= ':'.($uid-1) if $since < $uid-1; - $since = $uid+1; - } - elsif ($since == $uid) { - $since++; - } - } - - $first //= $since; - $range .= ',' if $range ne ''; - # 2^32-1: don't use '*' since the highest UID can be known already - $range .= "$since:4294967295"; - - my $UIDNEXT = $self->{_CACHE}->{$mailbox}->{UIDNEXT}; - $self->panic() unless defined $UIDNEXT and $UIDNEXT > 0; # sanity check - $self->_send("UID FETCH $range ($attrs)", $callback) if $first < $UIDNEXT;; + my $UIDNEXT; + do { + my $range = ''; + my $first; + my $since = $self->{_PCACHE}->{$mailbox}->{UIDNEXT} // 1; + foreach my $uid (@ignore) { + if ($since < $uid) { + $first //= $since; + $range .= ',' if $range ne ''; + $range .= $since; + $range .= ':'.($uid-1) if $since < $uid-1; + $since = $uid+1; + } + elsif ($since == $uid) { + $since++; + } + } - # update the persistent cache for UIDNEXT (not for HIGHESTMODSEQ - # since there might be pending updates) - $self->set_cache($mailbox, %{$self->{_CACHE}->{$mailbox}}{UIDNEXT}); + $first //= $since; + $range .= ',' if $range ne ''; + # 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 + $self->_send("UID FETCH $range ($attrs)", sub(%) { + my %mail = @_; + $UIDNEXT = $mail{UID} + 1 if $UIDNEXT <= $mail{UID}; + $callback->(%mail) if defined $callback; + }) if $first < $UIDNEXT; + + # update the persistent cache for UIDNEXT (not for HIGHESTMODSEQ + # since there might be pending updates) + $self->set_cache($mailbox, UIDNEXT => $UIDNEXT); + } + # loop if new messages were received in the meantime + while ($UIDNEXT < $self->{_CACHE}->{$mailbox}->{UIDNEXT}); } @@ -1461,7 +1468,7 @@ sub _resp($$;$$$) { # always present, cf RFC 3501 section 6.4.8 $mail{UID} = $1; # the actual UIDNEXT is *at least* that - $cache->{UIDNEXT} = $1+1 if !defined $cache->{UIDNEXT} or $cache->{UIDNEXT} < $1; + $cache->{UIDNEXT} = $1+1 if !defined $cache->{UIDNEXT} or $cache->{UIDNEXT} <= $1; } if (s/\AMODSEQ \(([0-9]+)\)//) { # RFC 4551/7162 CONDSTORE/QRESYNC # always present in unsolicited FETCH responses if QRESYNC has been enabled -- cgit v1.2.3