diff options
author | Guilhem Moulin <guilhem@fripost.org> | 2016-03-08 23:13:43 +0100 |
---|---|---|
committer | Guilhem Moulin <guilhem@fripost.org> | 2016-03-08 23:13:43 +0100 |
commit | ec87e1965d758bc3af4403a3cf469c3297f8cb1a (patch) | |
tree | 64989e2ace4e84da226177cdc9a8e95bd5c2f5ef | |
parent | aecdd0c6657e3edb0482751efffdcafb96f2c2c5 (diff) | |
parent | 6bf9ee9a1e1c704490489f682dfe106f2c1ee46a (diff) |
Merge branch 'master' into debian
-rw-r--r-- | README | 14 | ||||
-rw-r--r-- | interimap.1 | 8 | ||||
-rw-r--r-- | lib/Net/IMAP/InterIMAP.pm | 13 | ||||
-rwxr-xr-x | pullimap | 15 | ||||
-rw-r--r-- | pullimap.1 | 10 | ||||
-rw-r--r-- | pullimap@.service | 12 |
6 files changed, 46 insertions, 26 deletions
@@ -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 e23b953..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 @@ -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.) @@ -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. 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"); } @@ -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 ); }; @@ -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); @@ -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]; @@ -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,10 @@ 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. 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 @@ -180,7 +184,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.) 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 |