#!/usr/bin/perl use 5.032; use strict; use warnings; use autodie ":all"; use Fcntl qw(LOCK_EX LOCK_NB); use Net::Domain "hostfqdn"; # Ensure only one copy of this script is ever running, and then we assume that # mbsync isn't already running either, as always invoked via this script. open our $us, "<", $0 or die $!; exit 0 unless flock $us, LOCK_EX|LOCK_NB; our $root = "$ENV{HOME}/.fmail"; our $on_athena = hostfqdn eq "athena.silentflame.com"; die "no movemymail\n" if -e "$ENV{HOME}/.nomovemymail"; open my $df, "-|", "df", "-kP", $root; <$df>, my @df_fields = split " ", <$df>; $df_fields[3] > 1048576 or die "free space low; no movemymail\n"; # Sync notmuch's database to maildir and to git. if (-d "$root/.notmuch/xapian") { # Skip on athena because it's v. slow atm. system "mr", "-d", "$ENV{HOME}/lib/nmbug-spw", "autoci" unless $on_athena; # Ensure messages tagged in Emacs are in the appropriate folder. In the # case of spam, this should train FastMail's spam filter. search2folder("drafts", "tag:draft", "and", "not", "tag:deleted"); search2folder("spam", "tag:spam"); search2folder("trash", "tag:deleted"); } system [0, 1], "offline"; $? >> 8 == 0 and die "we're offline; cannot further sync mail\n"; system "postqueue", "-f"; eval { system "mbsync", "fastmail" }; if (my $exception = $@) { local $ENV{XDG_RUNTIME_DIR} = "/run/user/$<"; system "notify-send", "--urgency=critical", "--icon=dialog-warning", "'mbsync fastmail' exited nonzero"; die $exception; } # athena's 'notmuch new' cronjob is responsible for imap-dl(1) runs. We have # this here rather than separate cronjob entries so that hitting 'G' in # athena's Emacs inbox displays new mail from the other accounts. if ($on_athena) { system "imap-dl", "$ENV{HOME}/.config/mailscripts/imap-dl.selene"; system "imap-dl", "$ENV{HOME}/.config/mailscripts/imap-dl.catmail"; } # Move all mail new/ -> cur/ such that notmuch never sees anything in new/. # The reason for this is that notmuch tries to avoid moving files new/ -> cur/ # to avoid confusing Mutt, but messages in new/ aren't meant to have flags, so # they can't be marked seen. See id:87r1ypsb1p.fsf@tethera.net and maildir(5). for (<$root/*/new/*>) { m#^\Q$root\E/([^/]+)/new/([^/]+?)(:2,[^/]*)?$# or die "inadequate glob!"; rename $_, "$root/$1/cur/$2" . ($3 || ":2,"); } # Useful to see if any mail has got stuck before closing laptop lid. `mailq` =~ "Mail queue is empty" or warn "WARNING: Outbox not empty.\n"; sub search2folder { my ($folder, @terms) = @_; open my $search, "-|", "notmuch", "search", "--output=files", "--", "(", @terms, ")", "and", "not", "folder:$folder"; my @matches; for (<$search>) { next if m{^\Q$root\E/annex/}; chomp; # If notmuch's database is out-of-date the file may no longer exist # because it's already been moved by a previous run of this script. -f and push @matches, $_ } @matches and system "mdmv", @matches, "$root/$folder"; }