Skip to content
Switch branches/tags

Latest commit


Git stats


Failed to load latest commit information.
Latest commit message
Commit time

Maildir User Agent

This is a maildir based mail user agent for Emacs.

The basic idea is:

  • you pull new files from a remote MTA's maildir with SSH/rsync (or some other method)
  • Emacs manages the local maildir using a cache directory

The maildir flow looks like this:

  • the command maildir-pull - pulls any new files from the remote ssh in your maildir new
  • maildir-import-new - is automatically run by maildir-pull
    • it pulls files from new into the local cache
    • and symlinks them to cur

Finally, you can use the command maildir-list to generate a buffer with a listing of your current maildir in.

New mail pulling

I am implementing IMAP pulling for this using the GNUs IMAP library. The idea is that you can spawn a separate Emacs instance to establish a connection to your IMAP server (or even, many IMAP servers) and pull your mail to your maildir.

The Emacs instance you actually use can then poll that maildir (by checking the maildir's new directory) and inform you when there is new mail to collect (or just collect it and inform you, since it's quite cheap).

The expensive, blocking part, of talking to the IMAP server is kept in the second Emacs instance. Hopefully we can also do things like detect when the server connection is broken and flag that.

Maildir management

The maildir is just a directory on your local machine. We make one modifcation to the maildir standard which is to add a cache directory to the maildir. The cache directory is used to keep a record of every message file in the mailbox so that we can effectively rsync. The message files in the normal maildir directories (cur and new) are actually only symlinks into the cache directory.

All mail you pull from the remote maildir will end up in the cache, even if you never see it in your INBOX. This is because we do some filtering on whether maildir.el can actually display your mail or not.

If you feel like you're not seeing email grep your cache directory for the mail. If you find a bug, obviously, report it to me.


RET open the message
n next line
p previous line
TAB next field
+ make a new maildir
d delete the message
1 or k delete AND mark as spam
m move the message to another folder
C-s ... M-m move everything matching the incremental search
q quit
r pull from the remote and refresh

Message view

The maildir message view relies a lot on Emacs mail facilities. I just use the mm- functions.

The maildir-message-open tries to find a sensible part to display. When viewing the message the following keys are added to message-mode:

F fill the message
> view next part
> view previous part
i view part list
O open a part by completing-read on the part list
C-u O specify a viewer for a part
C-c w wide reply
C-c r direct reply


  • `maildir/message-open-external-part' needs to have a sentinel on the command
    • when you open a part with a specific viewer it uses an async shell command
    • but the buffers are left around when the command is killed
    • just add a sentinel to destroy the buffers if/when the command dies
  • implement SEEN/READ/REPLIED state
    • handling SEEN seems easy, just add something on open
    • handling reply is harder, have to add a hook to mail send
      • and some reference in the reply mail buffer to the original message filename?
  • shard the storage of the mails in the cache directory.
  • actorize the pull and index into a child-emacs
    • so that it doesn't slow anything down
  • add an Elnode app that we can run on the remote for delivering mail
    • this will replace rsync
    • a query interface to find all files since a particular date
    • POST /maildir/query since=YYYYMMDDHHMMSS
    • the client interface can then track the youngest file we have
      • and ask for any files since


maildir based mail user agent just in emacs-lisp






No releases published


No packages published