aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuilhem Moulin <guilhem@fripost.org>2015-07-26 15:53:13 +0200
committerGuilhem Moulin <guilhem@fripost.org>2015-07-26 15:54:43 +0200
commit464862335d1bc09437d4238214d30a1db7b829bd (patch)
tree191bebd200c0a14581ab08bc921a7568da9c634d
parent0ceb23a6c85c1c77dfac5e8eac6bf66657d08d07 (diff)
bugfix: Fetching new messages from local and adding them to remote modifies its UIDNEXT.
So we need to check again the first $source (remote) whenever the last one (local) added new messages to it.
-rwxr-xr-ximapsync46
-rw-r--r--lib/Net/IMAP/Sync.pm4
2 files changed, 28 insertions, 22 deletions
diff --git a/imapsync b/imapsync
index c0da7d6..25e65d6 100755
--- 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
diff --git a/lib/Net/IMAP/Sync.pm b/lib/Net/IMAP/Sync.pm
index 26303a6..bf56519 100644
--- a/lib/Net/IMAP/Sync.pm
+++ b/lib/Net/IMAP/Sync.pm
@@ -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($_);
}