About Archive Tags RSS Feed


I won't write another email client

8 January 2020 19:19

Once upon a time I wrote an email client, in a combination of C++ and Lua.

Later I realized it was flawed, and because I hadn't realized that writing email clients is hard I decided to write it anew (again in C++ and Lua).

Nowadays I do realize how hard writing email clients is, so I'm not going to do that again. But still .. but still ..

I was doing some mail-searching recently and realized I wanted to write something that processed all the messages in a Maildir folder. Imagine I wanted to run:

 message-dump ~/Maildir/people-foo/ ~/Maildir/people-bar/  \
     --format '${flags} ${filename} ${subject}'

As this required access to (arbitrary) headers I had to read, parse, and process each message. It was slow, but it wasn't that slow. The second time I ran it, even after adjusting the format-string, it was nice and fast because buffer-caches rock.

Anyway after that I wanted to write a script to dump the list of folders (because I store them recursively so ls -1 ~/Maildir wasn't enough):

 maildir-dump --format '${unread}/${total} ${path}'

I guess you can see where this is going now! If you have the following three primitives, you have a mail-client (albeit read-only)

  • List "folders"
  • List "messages"
  • List a single message.

So I hacked up a simple client that would have a sub-command for each one of these tasks. I figured somebody else could actually use that, be a little retro, be a little cool, pretend they were using MH. Of course I'd have to write something horrid as a bash-script to prove it worked - probably using dialog to drive it.

And then I got interested. The end result is a single golang binary that will either:

  • List maildirs, with a cute format string.
  • List messages, with a cute format string.
  • List a single message, decoding the RFC2047 headers, showing text/plain, etc.

And now I wonder, am I crazy? Is writing an email client hard? I can't remember

Probably best to forget the GUI exists. Probably best to keep it a couple of standalone sub-commands for "scripting email stuff".

But still .. but still ..



Comments on this entry

icon micahel at 11:48 on 9 January 2020

hi steve

Sorry if this sounds stupid but how do i build this?


icon Steve Kemp at 12:15 on 9 January 2020

If you've cloned the repository you should be able to build via:

  go build .

If you wish to fetch/install in one-step:

  go get github.com/skx/maildir-utils/
  go install github.com/skx/maildir-utils/

I'll be updating the structure/layout shortly to make it more idiomatic, and testable, but when I do that I'll make sure I include an installation section in the README.md file.

icon James Rowe at 20:27 on 10 January 2020

These tools look interesting, thanks for releasing! I'm always on the look out for The Way to deal with mail, but can't seem to find it.

Not sure if you're aware but Leah Neukirchen also has a interesting set of tools for dealing with maildirsĀ¹. Perhaps there are some ideas in there you'd be interested in.

  1. https://github.com/leahneukirchen/mblaze
icon Steve Kemp at 21:11 on 10 January 2020

Thanks for the comment James, I'd not come across mblaze before. But already I see a lot of overlap:

  • maddr(1) - extract mail addresses from messages
    • Is the same as maildir-tools messages --format '${to} ${from} ${cc} ${reply-to}
  • mdirs(1) - maildir folders, recursively
    • Is the same as maildir-tools maildirs
  • mless(1) - read messages in less(1)
    • Is the same as maildir-tools message file1 .. fileN

There is more too, but I can still see some things to consider. If only I had a scripting language for searching multiple fields ;)