aboutsummaryrefslogtreecommitdiffstats
path: root/imapsync
diff options
context:
space:
mode:
Diffstat (limited to 'imapsync')
-rwxr-xr-ximapsync46
1 files changed, 26 insertions, 20 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