diff options
Diffstat (limited to 'imapsync')
-rwxr-xr-x | imapsync | 46 |
1 files changed, 26 insertions, 20 deletions
@@ -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 |