From c61cd2c80674757c9a910b4d379e5b92f65cbec7 Mon Sep 17 00:00:00 2001 From: Guilhem Moulin Date: Tue, 8 Mar 2016 17:30:48 +0100 Subject: Net::IMAP::InterIMAP: try again if connect(2) was interrupted. --- lib/Net/IMAP/InterIMAP.pm | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/lib/Net/IMAP/InterIMAP.pm b/lib/Net/IMAP/InterIMAP.pm index be62a9d..785de38 100644 --- a/lib/Net/IMAP/InterIMAP.pm +++ b/lib/Net/IMAP/InterIMAP.pm @@ -1366,15 +1366,18 @@ sub _tcp_connect($$$) { my ($err, @res) = getaddrinfo($host, $port, \%hints); $self->fail("Can't getaddrinfo: $err") if $err ne ''; + SOCKETS: foreach my $ai (@res) { - socket my $s, $ai->{family}, $ai->{socktype}, $ai->{protocol}; + socket (my $s, $ai->{family}, $ai->{socktype}, $ai->{protocol}) or $self->panic("connect: $!"); # TODO: add a connection timeout # http://devpit.org/wiki/Connect%28%29_with_timeout_%28in_Perl%29 - if (defined $s and connect($s, $ai->{addr})) { - my $flags = fcntl($s, F_GETFL, 0) or $self->panic("fcntl F_GETFL: $!"); - fcntl($s, F_SETFL, $flags | FD_CLOEXEC) or $self->panic("fcntl F_SETFL: $!"); - return $s; + until (connect($s, $ai->{addr})) { + next if $! == EINTR; # try again if connect(2) was interrupted by a signal + next SOCKETS; } + my $flags = fcntl($s, F_GETFL, 0) or $self->panic("fcntl F_GETFL: $!"); + fcntl($s, F_SETFL, $flags | FD_CLOEXEC) or $self->panic("fcntl F_SETFL: $!"); + return $s; } $self->fail("Can't connect to $host:$port"); } -- cgit v1.2.3 From f8387c281f2a73343fcca9e599d29bd93ece4524 Mon Sep 17 00:00:00 2001 From: Guilhem Moulin Date: Tue, 8 Mar 2016 17:43:14 +0100 Subject: pullimap: improve doc. --- interimap.1 | 2 +- pullimap | 2 +- pullimap.1 | 8 +++++--- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/interimap.1 b/interimap.1 index e23b953..a73117b 100644 --- a/interimap.1 +++ b/interimap.1 @@ -298,7 +298,7 @@ advertising it. the \(lq[remote]\(rq section.) .TP -.I null-stderr +.I null\-stderr Whether to redirect \fIcommand\fR's standard error to \(lq/dev/null\(rq for type \fItype\fR=tunnel. (Default: \(lqNO\(rq.) diff --git a/pullimap b/pullimap index 0e31a90..d2de66f 100755 --- a/pullimap +++ b/pullimap @@ -221,7 +221,7 @@ sub smtp_send(@) { $CONF->{'logger-fd'} = \*STDERR if $CONFIG{debug}; my $IMAP = do { my %config = (%$CONF, %CONFIG{qw/quiet debug/}, name => $ARGV[0]); - $config{keepalive} = 1 if defined $CONFIG{idle} and $config{type} ne 'tunnel'; + $config{keepalive} = 1 if defined $CONFIG{idle}; Net::IMAP::InterIMAP::->new( %config ); }; diff --git a/pullimap.1 b/pullimap.1 index 52a6152..746e2ff 100644 --- a/pullimap.1 +++ b/pullimap.1 @@ -12,8 +12,7 @@ PullIMAP \- Pull mails from an IMAP mailbox and deliver them to a SMTP session .PP .B PullIMAP\fR retrieves messages from an IMAP mailbox and deliver them to a SMTP or LMTP transmission channel. -It can also remove delivered messages after a configurable retention -period. +It can also remove old messages after a configurable retention period. .PP A statefile is used to keep track of the mailbox's UIDVALIDITY and @@ -33,6 +32,7 @@ environment variable is unset. Don't exit after a successful poll; instead, keep the connection open and issue IDLE commands (requires an IMAP server supporting RFC 2177) to watch for updates in the mailbox. +This also sets SO_KEEPALIVE on the socket. Each IDLE is terminated after at most \fIseconds\fR (29 minutes by default) to avoid being logged out for inactivity. @@ -113,6 +113,8 @@ Message recipient. Retention period (in days), after which messages are removed from the IMAP server. (The value is at best 24h accurate due to IMAP SEARCH criterion ignoring time and timezone.) +If \fIpurge\-after\fR is set to \(lq0\(rq then messages are deleted +immediately after delivery. .TP .I type @@ -180,7 +182,7 @@ advertising it. (Default: \(lqYES\(rq.) .TP -.I null-stderr +.I null\-stderr Whether to redirect \fIcommand\fR's standard error to \(lq/dev/null\(rq for type \fItype\fR=tunnel. (Default: \(lqNO\(rq.) -- cgit v1.2.3 From 69e2f637222f81fd538809ef48f77d5334ef9c71 Mon Sep 17 00:00:00 2001 From: Guilhem Moulin Date: Tue, 8 Mar 2016 17:49:47 +0100 Subject: pullimap: don't FETCH messages BODY if --no-delivery is set. --- pullimap | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pullimap b/pullimap index d2de66f..c3fd4a0 100755 --- a/pullimap +++ b/pullimap @@ -254,7 +254,8 @@ sub purge() { # Use BODY.PEEK[] so if something gets wrong, unpulled messages # won't be marked as \Seen in the mailbox -my $ATTRS = "ENVELOPE INTERNALDATE BODY.PEEK[]"; +my $ATTRS = "ENVELOPE INTERNALDATE"; +$ATTRS .= " BODY.PEEK[]" unless $CONFIG{'no-delivery'}; # Pull new messages from IMAP and deliver them to SMTP, then update the # statefile @@ -265,7 +266,7 @@ sub pull(;$) { # invariant: we're at pos 8 + 4*(1+$#ignore + 1+$#uids) in the statefile $IMAP->pull_new_messages($ATTRS, sub($) { my $mail = shift; - return unless exists $mail->{RFC822}; # not for us + return unless exists $mail->{RFC822} or $CONFIG{'no-delivery'}; # not for us my $uid = $mail->{UID}; my $from = first { defined $_ and @$_ } @{$mail->{ENVELOPE}}[2,3,4]; -- cgit v1.2.3 From e19354c1b2b8015f58b7119763bb8cec401fb3fa Mon Sep 17 00:00:00 2001 From: Guilhem Moulin Date: Tue, 8 Mar 2016 18:02:10 +0100 Subject: pullimap: Don't rely on the last purged timestamp when purge-after=0. --- pullimap | 8 ++++---- pullimap.1 | 4 +++- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/pullimap b/pullimap index c3fd4a0..c16d6ac 100755 --- a/pullimap +++ b/pullimap @@ -234,11 +234,11 @@ sub purge() { return unless 1<$uidnext; my $set = "1:".($uidnext-1); - my $now = time; - return if defined $LAST_PURGED and $now - $LAST_PURGED < 6*3600; - $LAST_PURGED = $now; - unless ($days == 0) { + my $now = time; + return if defined $LAST_PURGED and $now - $LAST_PURGED < 6*3600; # purge every 6h + $LAST_PURGED = $now; + 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); diff --git a/pullimap.1 b/pullimap.1 index 746e2ff..57a4adf 100644 --- a/pullimap.1 +++ b/pullimap.1 @@ -114,7 +114,9 @@ Retention period (in days), after which messages are removed from the IMAP server. (The value is at best 24h accurate due to IMAP SEARCH criterion ignoring time and timezone.) If \fIpurge\-after\fR is set to \(lq0\(rq then messages are deleted -immediately after delivery. +immediately after delivery. Otherwise \fBPullIMAP\fR issues an IMAP +SEARCH command to list old messages; if \fB\-\-idle\fR is set then the +SEARCH command is issued again every 6 hours. .TP .I type -- cgit v1.2.3 From 750b6cbca59325c3419a5303f40359025e5b344d Mon Sep 17 00:00:00 2001 From: Guilhem Moulin Date: Tue, 8 Mar 2016 18:03:08 +0100 Subject: pullimap: add systemd service unit file. --- pullimap@.service | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 pullimap@.service diff --git a/pullimap@.service b/pullimap@.service new file mode 100644 index 0000000..d066886 --- /dev/null +++ b/pullimap@.service @@ -0,0 +1,12 @@ +[Unit] +Description=Pull mails from an IMAP mailbox and deliver them to a SMTP session +Wants=network-online.target +After=network-online.target + +[Service] +ExecStart=/usr/bin/pullimap --idle %i +RestartSec=2min +Restart=always + +[Install] +WantedBy=default.target -- cgit v1.2.3 From 6bf9ee9a1e1c704490489f682dfe106f2c1ee46a Mon Sep 17 00:00:00 2001 From: Guilhem Moulin Date: Tue, 8 Mar 2016 22:56:53 +0100 Subject: interimap: improve manpage. --- README | 14 +++++++------- interimap.1 | 6 +++--- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/README b/README index 2b577a5..8fcbb05 100644 --- a/README +++ b/README @@ -1,9 +1,11 @@ InterIMAP is a fast bidirectional synchronization program for QRESYNC-capable -IMAP4rev1 servers. Consult the manual for more information. +IMAP4rev1 servers. PullIMAP retrieves messages a remote IMAP mailbox and +deliver them to a SMTP session. Consult the manuals for more information. + https://guilhem.org/man/interimap.1.html + https://guilhem.org/man/pullimap.1.html -####################################################################### - +_______________________________________________________________________ Compared to IMAP-to-Maildir synchronization solutions like OfflineIMAP, adding an IMAP server between the Maildir storage and the MUA saves @@ -32,8 +34,7 @@ extensions are: * UNSELECT [RFC3691]. -####################################################################### - +_______________________________________________________________________ IMAP traffic is mostly text (beside message bodies perhaps) hence compresses pretty well: enabling compression can save a great amount of @@ -81,8 +82,7 @@ compress=DEFLATE to the configuration can also greatly reduce bandwidth usage with regular INET sockets (type=imaps or type=imap). -####################################################################### - +_______________________________________________________________________ InterIMAP is Copyright© 2015 Guilhem Moulin ⟨guilhem@fripost.org⟩, and licensed for use under the GNU General Public License version 3 or diff --git a/interimap.1 b/interimap.1 index a73117b..93e463e 100644 --- a/interimap.1 +++ b/interimap.1 @@ -33,7 +33,7 @@ Conceptually, the synchronization algorithm is derived from [RFC4549] with the [RFC7162, section 6] amendments, and works as follows: .nr step 1 1 -.IP \n[step]. 8 +.IP \n[step]. 4 SELECT (on both servers) a mailbox the current UIDNEXT or HIGHESTMODSEQ values of which differ from the values found in the database (for either server). Use the QRESYNC SELECT parameter from [RFC7162] to list @@ -353,7 +353,7 @@ authentication if \(lq\fISSL_verify\fR=YES\(rq. Performance is better for servers supporting the following extensions to the IMAP4rev1 [RFC3501] protocol: -.IP \[bu] +.IP \[bu] 4 LITERAL+ [RFC2088] non-synchronizing literals (recommended), .IP \[bu] MULTIAPPEND [RFC3502] (recommended), @@ -366,7 +366,7 @@ UNSELECT [RFC3691]. .SH KNOWN BUGS AND LIMITATIONS -.IP \[bu] +.IP \[bu] 4 Using \fBInterIMAP\fR on two identical servers with a non-existent or empty database will duplicate each message due to the absence of local/remote UID association. -- cgit v1.2.3