From 15cd4f6ea5074ffb33de8670bd1877603e504289 Mon Sep 17 00:00:00 2001 From: Guilhem Moulin Date: Thu, 10 May 2018 17:56:45 +0200 Subject: pullimap: use extended SEARCH (RFC 4731) when available --- pullimap | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) (limited to 'pullimap') diff --git a/pullimap b/pullimap index dca8c49..736bbff 100755 --- a/pullimap +++ b/pullimap @@ -249,10 +249,20 @@ sub purge() { my @now = gmtime($now - $days*86400); my @m = qw/Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec/; # RFC 3501's date-month my $date = sprintf("%02d-%s-%04d", $now[3], $m[$now[4]], $now[5]+1900); - my @uid = $IMAP->search("UID $set BEFORE $date"); - - $set = @uid ? compact_set(@uid) : undef; - $IMAP->log("Removing ".($#uid+1)." UID(s) $set") if defined $set and !$CONFIG{quiet}; + my $ext = $IMAP->incapable('ESEARCH') ? undef : [qw/COUNT ALL/]; + my @uid = $IMAP->search((defined $ext ? "RETURN (".join(' ', @$ext).') ' : '') + ."UID $set BEFORE $date"); + my $count; + if (defined $ext) { + my ($uid_indicator, %resp) = @uid; + $IMAP->panic() unless defined $uid_indicator and $uid_indicator = 'UID'; + $count = $resp{COUNT} // $IMAP->panic(); + $set = $resp{ALL}; # MUST NOT be present if there are no matches + } else { + $count = $#uid+1; + $set = $count == 0 ? undef : compact_set(@uid); + } + $IMAP->log("Removing $count UID(s) $set") if $count > 0 and !$CONFIG{quiet}; } if (defined $set) { -- cgit v1.2.3 From dd7edb8eac0c11fb8168f5028c8b6d8706cc8fdb Mon Sep 17 00:00:00 2001 From: Guilhem Moulin Date: Sun, 20 Jan 2019 19:55:33 +0100 Subject: pullimap, interimap: Use $XDG_CONFIG_HOME/$NAME/config as config file. --- pullimap | 35 +++++++++++++++-------------------- 1 file changed, 15 insertions(+), 20 deletions(-) (limited to 'pullimap') diff --git a/pullimap b/pullimap index 736bbff..e666114 100755 --- a/pullimap +++ b/pullimap @@ -31,7 +31,7 @@ use List::Util 'first'; use Socket qw/PF_INET PF_INET6 SOCK_STREAM/; use lib 'lib'; -use Net::IMAP::InterIMAP qw/read_config compact_set/; +use Net::IMAP::InterIMAP qw/xdg_basedir read_config compact_set/; # Clean up PATH $ENV{PATH} = join ':', qw{/usr/bin /bin}; @@ -59,15 +59,19 @@ usage(1) unless $#ARGV == 0 and $ARGV[0] ne '_'; ####################################################################### # Read and validate configuration # -my $CONF = read_config( delete $CONFIG{config} // $NAME, - , [$ARGV[0]] - , statefile => qr/\A(\P{Control}+)\z/ - , mailbox => qr/\A([\x01-\x7F]+)\z/ - , 'deliver-method' => qr/\A([ls]mtp:\[.*\]:\d+)\z/ - , 'deliver-ehlo' => qr/\A(\P{Control}+)\z/ - , 'deliver-rcpt' => qr/\A(\P{Control}+)\z/ - , 'purge-after' => qr/\A(\d*)\z/ - )->{$ARGV[0]}; +my $CONF = do { + my $conffile = delete($CONFIG{config}) // "config"; + $conffile = xdg_basedir( XDG_CONFIG_HOME => ".config", $NAME, $conffile ); + read_config( $conffile + , [$ARGV[0]] + , statefile => qr/\A(\P{Control}+)\z/ + , mailbox => qr/\A([\x01-\x7F]+)\z/ + , 'deliver-method' => qr/\A([ls]mtp:\[.*\]:\d+)\z/ + , 'deliver-ehlo' => qr/\A(\P{Control}+)\z/ + , 'deliver-rcpt' => qr/\A(\P{Control}+)\z/ + , 'purge-after' => qr/\A(\d*)\z/ + )->{$ARGV[0]}; +}; my ($MAILBOX, $STATE); do { @@ -75,16 +79,7 @@ do { my $statefile = $CONF->{statefile} // $ARGV[0]; die "Missing option statefile" unless defined $statefile; - $statefile = $statefile =~ /\A(\p{Print}+)\z/ ? $1 : die "Insecure $statefile"; - - unless ($statefile =~ /\A\//) { - my $dir = ($ENV{XDG_DATA_HOME} // "$ENV{HOME}/.local/share") .'/'. $NAME; - $dir = $dir =~ /\A(\/\p{Print}+)\z/ ? $1 : die "Insecure $dir"; - $statefile = $dir .'/'. $statefile; - unless (-d $dir) { - mkdir $dir, 0700 or die "Can't mkdir $dir: $!\n"; - } - } + $statefile = xdg_basedir( XDG_DATA_HOME => ".local/share", $NAME, $statefile ); sysopen($STATE, $statefile, O_CREAT|O_RDWR|O_DSYNC, 0600) or die "Can't open $statefile: $!"; # XXX we need to pack the struct flock manually: not portable! -- cgit v1.2.3 From 452ae91f06bec4c21e7ba7b7bc4309b089f7afe3 Mon Sep 17 00:00:00 2001 From: Guilhem Moulin Date: Sun, 20 Jan 2019 19:55:58 +0100 Subject: Specify minimum Perl and Net::SSLeay versions. --- pullimap | 1 + 1 file changed, 1 insertion(+) (limited to 'pullimap') diff --git a/pullimap b/pullimap index e666114..e044df5 100755 --- a/pullimap +++ b/pullimap @@ -21,6 +21,7 @@ use strict; use warnings; +use v5.20.2; our $VERSION = '0.3'; my $NAME = 'pullimap'; -- cgit v1.2.3 From 8c0f59f3f3add18a9ee8be767f54f43996ddbd78 Mon Sep 17 00:00:00 2001 From: Guilhem Moulin Date: Sun, 20 Jan 2019 20:16:53 +0100 Subject: Note on migrations. --- pullimap | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'pullimap') diff --git a/pullimap b/pullimap index e044df5..bd9b1cf 100755 --- a/pullimap +++ b/pullimap @@ -88,6 +88,11 @@ do { fcntl($STATE, F_SETLK, $struct_flock) or die "Can't lock $statefile: $!"; my $flags = fcntl($STATE, F_GETFD, 0) or die "fcntl F_GETFD: $!"; fcntl($STATE, F_SETFD, $flags | FD_CLOEXEC) or die "fcntl F_SETFD: $!"; + + # We have no version number in the statefile, but if we ever need a + # migration, we'll add a 1-byte header for the version number, and + # assume version 1.0 if the size of the file is a multiple of 4 + # bytes. (We can also use the fact that bytes 5 to 8 are never all 0.) }; -- cgit v1.2.3 From 1492f504316eb506e72f7a84ecd23207bb07e226 Mon Sep 17 00:00:00 2001 From: Guilhem Moulin Date: Mon, 21 Jan 2019 17:54:53 +0100 Subject: pullimap, interimap: don't autocreate statefile or database in long-lived mode. --- pullimap | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'pullimap') diff --git a/pullimap b/pullimap index bd9b1cf..b752b14 100755 --- a/pullimap +++ b/pullimap @@ -82,7 +82,11 @@ do { die "Missing option statefile" unless defined $statefile; $statefile = xdg_basedir( XDG_DATA_HOME => ".local/share", $NAME, $statefile ); - sysopen($STATE, $statefile, O_CREAT|O_RDWR|O_DSYNC, 0600) or die "Can't open $statefile: $!"; + my $mode = O_RDWR | O_DSYNC; + # don't auto-create in long-lived mode + $mode |= O_CREAT unless defined $CONFIG{idle}; + + sysopen($STATE, $statefile, $mode, 0600) or die "Can't open $statefile: $!"; # XXX we need to pack the struct flock manually: not portable! my $struct_flock = pack('s!s!l!l!i!', F_WRLCK, SEEK_SET, 0, 0, 0); fcntl($STATE, F_SETLK, $struct_flock) or die "Can't lock $statefile: $!"; -- cgit v1.2.3 From e85db0b140eb2c56fa46231829a1bfe6f98ede7d Mon Sep 17 00:00:00 2001 From: Guilhem Moulin Date: Sun, 20 Jan 2019 20:29:58 +0100 Subject: Bump version number. --- pullimap | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'pullimap') diff --git a/pullimap b/pullimap index b752b14..233172f 100755 --- a/pullimap +++ b/pullimap @@ -22,7 +22,7 @@ use strict; use warnings; use v5.20.2; -our $VERSION = '0.3'; +our $VERSION = '0.4'; my $NAME = 'pullimap'; use Errno 'EINTR'; @@ -32,7 +32,7 @@ use List::Util 'first'; use Socket qw/PF_INET PF_INET6 SOCK_STREAM/; use lib 'lib'; -use Net::IMAP::InterIMAP qw/xdg_basedir read_config compact_set/; +use Net::IMAP::InterIMAP 0.0.4 qw/xdg_basedir read_config compact_set/; # Clean up PATH $ENV{PATH} = join ':', qw{/usr/bin /bin}; -- cgit v1.2.3 From 64dd58fb503c5ee31da3bcbe52313c723730a122 Mon Sep 17 00:00:00 2001 From: Guilhem Moulin Date: Sun, 20 Jan 2019 20:42:56 +0100 Subject: Bump copyright years. --- pullimap | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'pullimap') diff --git a/pullimap b/pullimap index 233172f..495b99e 100755 --- a/pullimap +++ b/pullimap @@ -2,7 +2,7 @@ #---------------------------------------------------------------------- # Pull mails from an IMAP mailbox and deliver them to a SMTP session -# Copyright © 2016 Guilhem Moulin +# Copyright © 2016-2018 Guilhem Moulin # # 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 -- cgit v1.2.3