]> git.g-eek.se Git - interimap.git/commitdiff
pullimap: mark downloaded messages as \Seen
authorGuilhem Moulin <guilhem@fripost.org>
Sat, 5 Mar 2016 14:52:27 +0000 (15:52 +0100)
committerGuilhem Moulin <guilhem@fripost.org>
Sat, 5 Mar 2016 14:52:27 +0000 (15:52 +0100)
interimap
lib/Net/IMAP/InterIMAP.pm
pullimap

index f8989dc68b88f5715d98a3c97ae4fa9c2d769dc0..b377d4e5988de15e91404ad95903a32662d3e1c2 100755 (executable)
--- a/interimap
+++ b/interimap
@@ -2,7 +2,7 @@
 
 #----------------------------------------------------------------------
 # Fast bidirectional synchronization for QRESYNC-capable IMAP servers
-# Copyright © 2015 Guilhem Moulin <guilhem@fripost.org>
+# Copyright © 2015,2016 Guilhem Moulin <guilhem@fripost.org>
 #
 # This program is free software: you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -65,12 +65,12 @@ usage(1) if defined $COMMAND and defined $CONFIG{watch};
 usage(1) if $CONFIG{target} and !(defined $COMMAND and ($COMMAND eq 'delete'or $COMMAND eq 'rename'));
 $CONFIG{watch} = 60 if defined $CONFIG{watch} and $CONFIG{watch} == 0;
 @ARGV = map {uc $_ eq 'INBOX' ? 'INBOX' : $_ } @ARGV; # INBOX is case-insensitive
+die "Invalid mailbox name $_" foreach grep !/\A([\x01-\x7F]+)\z/, @ARGV;
 
 
 my $CONF = read_config( delete $CONFIG{config} // $NAME
                       , [qw/_ local remote/]
                       , database => qr/\A(\P{Control}+)\z/
-                      , logfile => qr/\A(\/\P{Control}+)\z/
                       , 'list-mailbox' => qr/\A([\x01-\x09\x0B\x0C\x0E-\x7F]+)\z/
                       , 'list-select-opts' => qr/\A([\x21\x23\x24\x26\x27\x2B-\x5B\x5E-\x7A\x7C-\x7E]+)\z/
                       , 'ignore-mailbox' => qr/\A([\x01-\x09\x0B\x0C\x0E-\x7F]+)\z/
index 7d6e4683397c96995b4e8b940607f8138cfaf8f3..15682b396ee130cca4b5c3ea5156c6121c843d68 100644 (file)
@@ -58,6 +58,7 @@ my %OPTIONS = (
     command => qr/\A(\P{Control}+)\z/,
     'null-stderr' => qr/\A(YES|NO)\z/i,
     compress => qr/\A($RE_ATOM_CHAR+(?: $RE_ATOM_CHAR+)*)\z/,
+    logfile => qr/\A(\/\P{Control}+)\z/,
     SSL_protocols => qr/\A(!?$RE_SSL_PROTO(?: !?$RE_SSL_PROTO)*)\z/,
     SSL_fingerprint => qr/\A((?:[A-Za-z0-9]+\$)?\p{AHex}+)\z/,
     SSL_cipherlist => qr/\A(\P{Control}+)\z/,
@@ -535,9 +536,10 @@ sub logger($@) {
     if (defined $self->{'logger-fd'}->fileno and defined $self->{'logger-fd'}->fileno
             and $self->{'logger-fd'}->fileno != fileno STDERR) {
         my ($s, $us) = Time::HiRes::gettimeofday();
-        $prefix = POSIX::strftime("%b %e %H:%M:%S", localtime($s)).".$us ";
+        $prefix = POSIX::strftime("%b %e %H:%M:%S", localtime($s)).".$us";
+        $prefix .= ' ' if defined $self->{name} or $self->{_STATE} eq 'SELECTED';
     }
-    $prefix .= $self->{name} // '';
+    $prefix .= $self->{name} if defined $self->{name};
     $prefix .= "($self->{_SELECTED})" if $self->{_STATE} eq 'SELECTED';
     $prefix .= ': ' unless $prefix eq '';
     $self->{'logger-fd'}->say($prefix, @_);
@@ -1255,6 +1257,17 @@ sub push_flag_updates($$@) {
 }
 
 
+# $self->silent_store($set, $mod, @flags)
+#   Set / Add / Update the flags list on the UID $set.
+#   /!\ there is no check that messages flags been set!
+sub silent_store($$$@) {
+    my $self = shift;
+    my $set = shift;
+    my $mod = shift;
+    $self->_send("UID STORE $set ${mod}FLAGS.SILENT (".join(' ', @_).")");
+}
+
+
 #############################################################################
 # Private methods
 
index d1a2f4ae3ee29a9ef7bcadec18900254787d8d96..e79e64470c1c60018f03676fffbdfd4428bcb175 100755 (executable)
--- a/pullimap
+++ b/pullimap
@@ -29,7 +29,7 @@ use Getopt::Long qw/:config posix_default no_ignore_case gnu_getopt auto_version
 use List::Util 'first';
 
 use lib 'lib';
-use Net::IMAP::InterIMAP 'read_config';
+use Net::IMAP::InterIMAP qw/read_config compact_set/;
 
 my %CONFIG;
 sub usage(;$) {
@@ -140,11 +140,16 @@ do {
         writeUID(1);
     }
     else {
+        # put the remaining UIDs in the @ignore list: these messages
+        # have already been delivered, but the process exited before the
+        # statefile was updated
         while (defined (my $uid = readUID())) {
             push @ignore, $uid;
         }
     }
 
+    # use BODY.PEEK[] so if something gets wrong, unpulled messages
+    # won't be marked as \Seen in the mailbox
     my $attrs = join ' ', qw/ENVELOPE INTERNALDATE BODY.PEEK[]/;
     my @uid;
 
@@ -163,7 +168,8 @@ do {
         writeUID($uid);
     }, @ignore);
 
-    # TODO mark (@ignore, @uid) as seen
+    # now that everything has been deliverd, mark @ignore and @uid as \Seen
+    $IMAP->silent_store(compact_set(@ignore, @uid), '+', '\Seen') if @ignore or @uid;
 
     # update the statefile
     sysseek($STATE, 4, SEEK_SET) // die "Can't seek: $!";