Maildir manual | D. J. Bernstein
With extra notes by Rik Hemsley rik@kde.org | Last update: Sun Sep 19

Contents

- Introduction
- Reliability issues
- The Maildir structure
- How a message is read
- Environment variables
- Additional notes

Introduction

maildir is a structure for directories of incoming mail messages. It solves the reliability problems that plague mbox files and mh folders.

Reliability issues

A machine may crash while it is delivering a message. For both mbox files and mh folders this means that the message will be silently truncated. Even worse: for mbox format, if the message is truncated in the middle of a line, it will be silently joined to the next message. The mail transport agent will try again later to deliver the message, but it is unacceptable that a corrupted message should show up at all. In maildir, every message is guaranteed complete upon delivery.

A machine may have two programs simultaneously delivering mail to the same user. The mbox and mh formats require the programs to update a single central file. If the programs do not use some locking mechanism, the central file will be corrupted. There are several mbox and mh locking mechanisms, none of which work portably and reliably. In contrast, in maildir, no locks are ever necessary. Different delivery processes never touch the same file.

A user may try to delete messages from his mailbox at the same moment that the machine delivers a new message. For mbox and mh formats, the user's mail-reading program must know what locking mechanism the mail-delivery programs use. In contrast, in maildir, any delivered message can be safely updated or deleted by a mail-reading program.

Many sites use Sun's Network Failure System (NFS), presumably because the operating system vendor does not offer anything else. NFS exacerbates all of the above problems. Some NFS implementations don't provide any reliable locking mechanism. With mbox and mh formats, if two machines deliver mail to the same user, or if a user reads mail anywhere except the delivery machine, the user's mail is at risk. maildir works without trouble over NFS.

The Maildir structure

A directory in maildir format has three subdirectories, all on the same filesystem: tmp, new and cur.

Each file in new is a newly delivered mail message. The modification time of the file is the delivery date of the message. The message is delivered without an extra UUCP-style From_ line, without any >From quoting, and without an extra blank line at the end. The message is normally in RFC 822 format, starting with a Return-Path line and a Delivered-To line, but it could contain arbitrary binary data. It might not even end with a newline.

Files in cur are just like files in new. The big difference is that files in cur are no longer new mail: they have been seen by the user's mail-reading program.

How a message is delivered

The tmp directory is used to ensure reliable delivery, as discussed here.

A program delivers a mail message in six steps.

1. It chdir()s to the maildir directory.

2. It stat()s the name tmp/time.pid.host, where time is the number of seconds since the beginning of 1970 GMT, pid is the program's process ID, and host is the host name.

3. If stat() returned anything other than ENOENT, the program sleeps for two seconds, updates time and tries the stat() again, a limited number of times.

4. The program creates tmp/time.pid.host.

5. The program NFS-writes the message to the file.

6. The program link()s the file to new/time.pid.host. At that instant the message has been successfully delivered.

The delivery program is required to start a 24-hour timer before creating tmp/time.pid.host, and to abort the delivery if the timer expires. Upon error, timeout, or normal completion, the delivery program may attempt to unlink() tmp/time.pid.host.

NFS-writing means

1. as usual, checking the number of bytes returned from each write() call;
2. calling fsync() and checking its return value;
3. calling close() and checking its return value.

Note: Standard NFS implementations handle fsync() incorrectly but make up for it by abusing close().

How a message is read

A mail reader operates as follows.

It looks through the new directory for new messages.

Say there is a new message, new/unique. The reader may freely display the contents of new/unique, delete new/unique, or rename new/unique as cur/unique:info. See here for the meaning of info.

The reader is also expected to look through the tmp directory and to clean up any old files found there. A file in tmp may be safely removed if it has not been accessed in 36 hours.

It is a good idea for readers to skip all filenames in new and cur starting with a dot. Other than this, readers should not attempt to parse filenames.

Environment variables

Mail readers supporting maildir use the MAILDIR environment variable as the name of the user's primary mail directory.

Additional notes [by Rik]

To have mail delivered to a maildir format box, you need some form of Mail Delivery Agent (MDA) that understands the maildir format.

Note that most mail clients actually act as MDAs, even though they're given the term MUA (Mail User Agent). A pure IMAP4 client doesn't count, as it doesn't actually deliver anything to a mailbox, it asks the IMAP server to do it. Examples of maildir-aware MUAs are mutt and Empath

If you want to have mail delivered by your MTA (Message Transmission Agent, e.g. sendmail), you'll have to use either qmail (a safe, secure, fast, sendmail replacement), which is the only MTA currently available which is capable of writing directly to maildir, or use something to replace the standard MDA behaviour of your MTA. At the time of writing there is only one such utility, maildrop which is similar to procmail - the traditional mail delivery and filtering agent.

Instructions for setting up and using qmail and maildrop are included with the respective packages. It's a great deal easier to set up maildrop than qmail, though I'd recommend moving your site to qmail if you don't need sendmail's extra functionality and care about mail security and safety.