nmsync
works with mbsync
and notmuch
on Unix systems and is
programmable in scheme. It’s sort of an alternative to afew except
that it also calls mbsync
for you and you don’t have to Python.
So this depends on having a working mbsync
setup, and Chicken
Scheme. I’m not gonna try to make an egg for it because it kinda makes
no sense if you don’t compile your own version—the idea is to be able
to write more complex tagging and untagging scripts.
I used to have an offlineimap setup that called a tagging shellscript
as a hook; as far as I know mbsync doesn’t have hooks in the same way.
And nmsync
is the solution to that: calling the fetcher from the
tagger instead of the other way around.
It checks to see if there’s already an instance of mbsync
or
nmsync
running and if there is, it just quits immediately. Not the
most sofisticated mutex in the world but it’s nice to be able to have
nmsync
being called from cron while still being able to call it
manually when you want to specificially get an email someone just told
you they sent you without having to worry about them colliding.
(Maybe in a future version there could be inotify on the server instead of polling every X minutes.)
Most of the tagging is done by notmuch’s built in tagfile handling, so for example you might have an ~/.nmsync.tags file that looks like this:
# immediately archive all messages from "me"
-new -- tag:new and from:myownaddress@example.xyz
#paper trail
-new +paper from:billing@example.xyz and subject:"/^Example XYZ - Invoice/" and tag:new
-new +paper from:billing@example.xyz and subject:"/^Example.xyz - Payment Receipt/" and tag:new
#feed
-new +feed -- from:CozyNewsletter@example.xyz and tag:new
#spam
-new +spam -- Xspam:yes and tag:new
# inbox
+inbox +unread +personal -new -- tag:new
That’s just an example, mine is like 95 lines by now.
Notmuch’s internal tagging system can read the tags and combine the multiple operations to run them efficiently, and it can already handle regexes (as seen in the “paper trail” examples above).
So If I can solve an issue by this kind of “vanilla tagging”, I do. Most of my .nmsync.tags is putting things in the feed or in the paper trail (terminology inspired by the proprietary Rails email app “Hey!”, except here I can also sort by subject, body etc.)
I’m not one to overly sort thing by sender or date, since notmuch already is so good at searching senders, date ranges and such. I have a lot of saved searches in emacs, like “search for $terms among email from last seven days” or “show me all threads I’m involved in since midnight” or “show me all email from the last 48 hours” etc.
By the way, in order to search custom headers like Xspam
in my example, run
notmuch config set index.header.Xspam X-Spam
from a shell. That’s just an example, you might have some other cockamamie headers.
In addition to the “vanilla tagging”, nmsync
can also do more
conditional tagging and untagging via the Scheme code.
Let’s say I’m using the tagfile to remove +personal and +inbox from invoices and receipts from billing@example.xyz but I still want to get notified if something there isn’t a normal receipt from them.
(let ((latest-invoice (timestamp
(nm search --limit=1 from:billing@example.xyz
and "subject:/^Example XYZ - Invoice/"))))
(when ; When the invoice is newer than the receipt...
(and (> latest-invoice (timestamp
(nm search --limit=1 from:billing@example.xyz
and "subject:/^Example.xyz - Payment Receipt/")))
; and older than 259200 seconds (four days)
(> (- (current-seconds) latest-invoice) 259200))
; then show all mail from them from the last ten days
(run (notmuch tag +personal +inbox -new -- from:billing@example.xyz and date:-10_days..))))
The “nm” macro gives you sexps that you can parse; “timestamp” is one example of doing that:
(define (timestamp e)
(second (find-tail (cut equal? ':timestamp <>) (car e))))
Play around with the sexp tree in the REPL with your typical pretty-printing and SRFI-1 stuff to see its structure.
Do not mess this up. Be careful. As with all free software, there’s no warranty if you miss invoices etc.
For source code, git clone https://idiomdrottning.org/nmsync