Entries tagged sieve

Related tags: maildir, maildrop, procmail.

Delivering to a Maildir folder, but marking as read

Monday, 25 October 2010

Email. We get a lot of it. We filter out the SPAM. Then if we're well-organized we file it away into folders as it arrives. (To be fair some people use priority settings such that all mail stays in their INBOX until they're "done" with it. I've never had the patience for that kind of behaviour.)

One problem which I often encounter is wanting to have email be delivered, archived, and stored, but I don't want to read it. Yet when I see a folder in my mail client which has unread mail in it I cannot unsee.

In my case I deliver mail to folders as it arrives via either Exim's filter language, or procmail. Procmail blows goats on the whole, but it is common and available everywhere - I just don't trust my own DSL enough to rely upon it (which is a dangerous sign).

So, how do you deliver a new mail to a Maildir folder, and mark it read at the same time? Well you can be naïve and do what I did which is to invoke formail to add "Status: ro" to the header. Unfortunately that's insufficient to mark a mail as read when viewed in mutt.

When an email is stored in a Maildir folder its status is encoded in part of its filename - which is why you'll have files like:


The latter file has been Seen. So to mark a message as not-new you need to do two things:

  • Save it to ./cur/ not ./new/.
  • Append the appropriate flags to the filename (generally :2,S).

I've seen some horrific shell + procmail code to do the job, but the simpler version is:

| ~/bin/read-to-maildir .machines.debian-administration.org/

Similarly you can use Exim's filter language to do the same job:

# Exim filter
if $h_to: contains "hostmaster@" then
    pipe "/home/skx/bin/read-to-maildir /home/steve/Maildir/.hostmaster/"

Cute. Obvious too? Maybe not to me.

ObSubject: Why did you murder someone, Raymond? - In Bruges



Sometimes you just wonder would other people like this?

Tuesday, 27 July 2010

Sometimes I write things that are for myself, and later decide to release on the off-chance other people might be interested.

I've hated procmail for a long time, but it is extremely flexible, and for the longest time I figured since I'd got things working the way I wanted there was little point changing.

When it comes to procmail there are few alternatives:

Unfortunately both Exim and Email::Filter suffer from a lack of "pipe" support. To be more specific Exim filters and Email::Filter allow you to pipe an incoming message to an external program - but they regard that as the end of the delivery process.

So, for example, you cannot receive a message (on STDIN), pipe it through crm114, then process that updated message. (i.e. The output of crm114).

Maildrop does allow pipes, but suffers from other problems which makes me "not like it".

My own approach is to have a simple mail-sieve command which is configured thusly:

set maildir=/home/steve/Maildir
set logfile=/home/.trash.d/mail-sieve.log

#  Null-senders
Return-Path: /<>/        save .Automated.bounces/

#  Spam filter
filter /usr/bin/crm -u /home/steve/.crm /usr/share/crm114/mailreaver.crm

#  Spam?
X-CRM114-Status: /SPAM/   save .CRM.Spam/
X-CRM114-Status: /Unsure/ save .CRM.Unsure/

#  People / Lists
From: /foo@example.com/  save .people.foo/
From: /bar@example.com/  save .people.bar/

#  Domains
To: /steve.org.uk$/               save .steve.org.uk/
To: /debian-administration.org$/  save .debian-administration.org.personal/

#  All done.
save .inbox.unfiled/

On the one hand this is simple, readable, and complete enough for myself. On the other hand if I were going to make it releasable I think I'd probably want to add both conditionals and the ability to match upon multiple header values.

Getting there would probably involve something like this on the ~/.mail-filter side :

if ( ( From: /foo@example.com ) ||
     ( From: /bar@example.com ) )
   save .people.example.com/
# ps. remind me how much I hate parsers and lexers?

That starts to look very much like Exim's filter language, at which point I think "why should I bother". Pragmatically the simplest solution would be to add a "Filter" primitive to Email::Filter - and pretend I understood the nasty "Exit" settings.

ObQuote: Andre, we don't use profanity or double negatives here at True Directions. - "But I'm a Cheerleader".



Recent Posts

Recent Tags