]> git.g-eek.se Git - interimap.git/commitdiff
bugfix: Fetching new messages from local and adding them to remote modifies its UIDNEXT.
authorGuilhem Moulin <guilhem@fripost.org>
Sun, 26 Jul 2015 13:53:13 +0000 (15:53 +0200)
committerGuilhem Moulin <guilhem@fripost.org>
Sun, 26 Jul 2015 13:54:43 +0000 (15:54 +0200)
So we need to check again the first $source (remote) whenever the last
one (local) added new messages to it.

imapsync
lib/Net/IMAP/Sync.pm

index c0da7d6d2683b480abe4fa4f40fbcfaaf030f12e..25e65d6ddca08e07016e3846dcf36d3a9648bb8a 100755 (executable)
--- a/imapsync
+++ b/imapsync
@@ -961,26 +961,32 @@ sub callback_new_message_flush($$$@) {
 # the given UIDs.
 sub sync_messages($$;$$) {
     my ($idx, $mailbox, $lIgnore, $rIgnore) = @_;
-    my ($buff, $bufflen, @lUIDs);
-
-    # get new messages from remote (except @$rIgnore) and APPEND them to local
-    ($buff, $bufflen) = ([], 0);
-    undef $buff if $lIMAP->incapable('MULTIAPPEND');
-    $rIMAP->pull_new_messages(sub($) {
-        callback_new_message($idx, $mailbox, 'remote', shift, \@lUIDs, $buff, \$bufflen)
-    }, @{$rIgnore // []});
-    push @lUIDs, callback_new_message_flush($idx, $mailbox, 'remote', @$buff)
-        if defined $buff and @$buff;
-
-    # get new messages from local (except @$lIgnore and the newly allocated local
-    # UIDs @lUIDs) and APPEND them to remote
-    ($buff, $bufflen) = ([], 0);
-    undef $buff if $rIMAP->incapable('MULTIAPPEND');
-    $lIMAP->pull_new_messages(sub($) {
-        callback_new_message($idx, $mailbox, 'local', shift, undef, $buff, \$bufflen)
-    }, @{$lIgnore // []}, @lUIDs);
-    callback_new_message_flush($idx, $mailbox, 'local', @$buff)
-        if defined $buff and @$buff;
+
+    my %ignore = (local => ($lIgnore // []), remote => ($rIgnore // []));
+    my $loop;
+    do {
+        # get new messages from $source (except @{$ignore{$source}}) and APPEND them to $target
+        foreach my $source (qw/remote local/) { # pull remote mails first
+            my $target = $source eq 'remote' ? 'local' : 'remote';
+            my $buff    = [] unless ($target eq 'local' ? $lIMAP : $rIMAP)->incapable('MULTIAPPEND');
+            my $bufflen = 0;
+            my @tUIDs;
+
+            ($source eq 'remote' ? $rIMAP : $lIMAP)->pull_new_messages(sub($) {
+                callback_new_message($idx, $mailbox, $source, shift, \@tUIDs, $buff, \$bufflen)
+            }, @{$ignore{$source}});
+
+            push @tUIDs, callback_new_message_flush($idx, $mailbox, $source, @$buff)
+                if defined $buff and @$buff;
+            push @{$ignore{$target}}, @tUIDs;
+
+            $loop = @tUIDs ? 1 : 0;
+        }
+        # since $source modifies $target's UIDNEXT upon new mails, we
+        # need to check again the first $source (remote) whenever the
+        # last one (local) added new messages to it
+    }
+    while ($loop);
 
     # both local and remote UIDNEXT are now up to date; proceed with
     # pending flag updates and vanished messages
index 26303a6cb8746984e6e09a8ea40424e9c8a717fd..bf56519a30fb5337df660810874c499f55d40e92 100644 (file)
@@ -657,12 +657,12 @@ sub append($$@) {
     my @uids;
     foreach (split /,/, $uidset) {
         if (/\A([0-9]+)\z/) {
-            $UIDNEXT = $1 + 1 if $UIDNEXT <= $1;
+            $UIDNEXT = $1 + 1 if defined $UIDNEXT and $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 defined $UIDNEXT and $UIDNEXT <= $max;
         } else {
             $self->panic($_);
         }