From 540c3f20afb9101a8b74936843f708bed98ef38e Mon Sep 17 00:00:00 2001 From: Guilhem Moulin Date: Tue, 8 Sep 2015 00:59:39 +0200 Subject: Add an option --watch to keep the connections open and wait for changes. --- interimap | 53 +++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 37 insertions(+), 16 deletions(-) (limited to 'interimap') diff --git a/interimap b/interimap index 9998427..ed80b5a 100755 --- a/interimap +++ b/interimap @@ -53,7 +53,7 @@ sub usage(;$) { } my @COMMANDS = qw/repair delete rename/; -usage(1) unless GetOptions(\%CONFIG, qw/config=s quiet|q target=s@ debug help|h/, @COMMANDS); +usage(1) unless GetOptions(\%CONFIG, qw/config=s quiet|q target=s@ debug help|h watch:i/, @COMMANDS); usage(0) if $CONFIG{help}; my $COMMAND = do { my @command = grep {exists $CONFIG{$_}} @COMMANDS; @@ -61,6 +61,8 @@ my $COMMAND = do { $command[0] }; usage(1) if defined $COMMAND and (($COMMAND eq 'delete' and !@ARGV) or $COMMAND eq 'rename' and $#ARGV != 1); +usage(1) if defined $COMMAND and defined $CONFIG{watch}; +$CONFIG{watch} = 60 if defined $CONFIG{watch} and $CONFIG{watch} == 0; @ARGV = map {uc $_ eq 'INBOX' ? 'INBOX' : $_ } @ARGV; # INBOX is case-insensitive @@ -225,6 +227,17 @@ logger(undef, ">>> $NAME $VERSION"); ############################################################################# # Connect to the local and remote IMAP servers +my $LIST = '"" '; +my @LIST_PARAMS; +if (!defined $COMMAND or $COMMAND eq 'repair') { + $LIST = '('.uc($CONF->{_}->{'list-select-opts'}).') '.$LIST if defined $CONF->{_}->{'list-select-opts'}; + $LIST .= (defined $CONF->{_}->{'list-mailbox'} ? '('.$CONF->{_}->{'list-mailbox'}.')' : '*') unless @ARGV; + @LIST_PARAMS = ('SUBSCRIBED', 'STATUS (UIDVALIDITY UIDNEXT HIGHESTMODSEQ)'); +} +$LIST .= $#ARGV == 0 ? Net::IMAP::InterIMAP::quote($ARGV[0]) + : ('('.join(' ',map {Net::IMAP::InterIMAP::quote($_)} @ARGV).')') if @ARGV; + + my $IMAP; foreach my $name (qw/local remote/) { my %config = %{$CONF->{$name}}; @@ -250,19 +263,9 @@ foreach my $name (qw/local remote/) { # XXX We shouldn't need to ask for STATUS responses here, and use # NOTIFY's STATUS indicator instead. However Dovecot violates RFC # 5464: http://dovecot.org/pipermail/dovecot/2015-July/101474.html - - my $list = '"" '; - my @params; - if (!defined $COMMAND or $COMMAND eq 'repair') { - $list = '('.uc($CONF->{_}->{'list-select-opts'}).') '.$list if defined $CONF->{_}->{'list-select-opts'}; - $list .= (defined $CONF->{_}->{'list-mailbox'} ? '('.$CONF->{_}->{'list-mailbox'}.')' : '*') unless @ARGV; - @params = ('SUBSCRIBED', 'STATUS (UIDVALIDITY UIDNEXT HIGHESTMODSEQ)'); - } - $list .= $#ARGV == 0 ? Net::IMAP::InterIMAP::quote($ARGV[0]) - : ('('.join(' ',map {Net::IMAP::InterIMAP::quote($_)} @ARGV).')') if @ARGV; - @{$IMAP->{$name}}{qw/mailboxes delims/} = $client->list($list, @params); } +@{$IMAP->{$_}}{qw/mailboxes delims/} = $IMAP->{$_}->{client}->list($LIST, @LIST_PARAMS) for qw/local remote/; ############################################################################## # @@ -414,7 +417,7 @@ elsif (defined $COMMAND and $COMMAND eq 'rename') { # Synchronize mailbox and subscription lists my @MAILBOXES; -{ +sub sync_mailbox_list() { my %mailboxes; $mailboxes{$_} = 1 foreach keys %{$IMAP->{local}->{mailboxes}}; $mailboxes{$_} = 1 foreach keys %{$IMAP->{remote}->{mailboxes}}; @@ -501,8 +504,9 @@ my @MAILBOXES; } } } + +sync_mailbox_list(); my ($lIMAP, $rIMAP) = map {$IMAP->{$_}->{client}} qw/local remote/; -undef $IMAP; ############################################################################# @@ -1189,8 +1193,25 @@ while(1) { } } # clean state! - exit 0 unless defined $COMMAND and $COMMAND eq 'watch'; - wait_notifications(900); + exit 0 unless $CONFIG{watch}; + + # we need to issue a NOOP command or go back to AUTH state since the + # LIST command may not report the correct HIGHESTMODSEQ value for + # the mailbox currently selected. + if (defined $MAILBOX) { + # Prefer UNSELECT over NOOP commands as it requires a single command per cycle + if ($lIMAP->incapable('UNSELECT') or $rIMAP->incapable('UNSELECT')) { + $_->noop() foreach ($lIMAP, $rIMAP); + } else { + $_->unselect() foreach ($lIMAP, $rIMAP); + undef $MAILBOX; + } + } + + sleep $CONFIG{watch}; + # Refresh the mailbox list and status + @{$IMAP->{$_}}{qw/mailboxes delims/} = $IMAP->{$_}->{client}->list($LIST, @LIST_PARAMS) for qw/local remote/; + sync_mailbox_list(); } END { -- cgit v1.2.3