Recent from talks
Nothing was collected or created yet.
Maildir
View on WikipediaThe Maildir e-mail format is a common way of storing email messages on a file system, rather than in a database. Each message is assigned a file with a unique name, and each mail folder is a file system directory containing these files. Maildir was designed by Daniel J. Bernstein circa 1995, with a major goal of eliminating the need for program code to handle file locking and unlocking through use of the local filesystem.[1] Maildir design reflects the fact that the only operations valid for an email message is that it be created, deleted or have its status changed in some way.

Specifications
[edit]A Maildir directory (often named Maildir) usually has three subdirectories named tmp, new, and cur.[2]
- The
tmpsubdirectory temporarily stores e-mail messages that are in the process of being delivered. This subdirectory may also store other kinds of temporary files. - The
newsubdirectory stores messages that have been delivered, but have not yet been seen by any mail application. - The
cursubdirectory stores messages that have already been seen by mail applications.[3]
Maildir++
[edit]Sam Varshavchik, the author of the Courier Mail Server and other software, defined the Maildir++ extension[3][4] to the Maildir format to support subfolders and mail quotas. Maildir++ directories contain subdirectories with names that start with a '.' (dot) which are also Maildir++ folders. The extension complies with the original Maildir specification, which allows for subdirectories in addition to tmp, new and cur.
Technical operation
[edit]A mail delivery agent is a program that delivers an email message into a Maildir. The mail delivery agent creates a new file with a unique filename in the tmp directory.[5][6][3] At the time of its invention guaranteeing unique filenames efficiently was difficult. The original qmail[1] algorithm for unique names was:
- read the current Unix time
- read the current process identifier (PID)
- read the current hostname
- concatenate the above three values into a string separated by the period character; this is the new filename
- if
stat()reports that the filename exists, then wait two seconds - go to previous step until the filename does not exist
- create a file with the unique filename and write the message contents to the new file
By 2000, the qmail author recommended in an updated specification[5] to append the value of a per-process counter to the PID, whose value should be incremented after each delivery. The rate-limiting recommendation to "wait two seconds" was dropped.
By 2003, the recommendations had been further amended to require that instead of the PID and counter, the middle part of the filename should be created by "concatenating enough of the following strings to guarantee uniqueness" even in the face of multiple simultaneous deliveries to the same maildir from one or more processes:[7]
- #n, where n is (in hexadecimal) the output of the operating system's
unix_sequencenumber()system call, which returns a number that increases by 1 every time it is called, starting from 0 after reboot.- Xn, where n is (in hexadecimal) the output of the operating system's
unix_bootnumber()system call, which reports the number of times that the system has been booted. Together with #, this guarantees uniqueness; unfortunately, most operating systems don't supportunix_sequencenumber()andunix_bootnumber().- Rn, where n is (in hexadecimal) the output of the operating system's
unix_cryptorandomnumber()system call or an equivalent source, such as/dev/urandom. Unfortunately, some operating systems don't include cryptographic random number generators.- In, where n is (in hexadecimal) the UNIX inode number of this file. Unfortunately, inode numbers aren't always available through NFS.
- Vn, where n is (in hexadecimal) the UNIX device number of this file. Unfortunately, device numbers aren't always available through NFS. (Device numbers are also not helpful with the standard UNIX filesystem: a maildir has to be within a single UNIX device for
link()andrename()to work.)- Mn, where n is (in decimal) the microsecond counter from the same
gettimeofday()used for the left part of the unique name.- Pn, where n is (in decimal) the process ID.
- Qn, where n is (in decimal) the number of deliveries made by this process.
This 2003 algorithm was criticised[8] in 2006 as being unnecessarily complex by Timo Sirainen, the creator of Dovecot.
As of November 2023, qmail author Daniel Bernstein had made no further changes to the 2003 filename generation recommendations.[9] On modern POSIX systems, temporary files can be safely created with the mkstemp C library function.
The delivery process stores the message in the maildir by creating and writing to tmp/uniquefilename, and then moving this file to new/uniquefilename. The moving can be done using rename, which is atomic in many systems.[10] Alternatively, it can be done by hard-linking the file to new and then unlinking the file from tmp. Any leftover file will eventually be deleted. This sequence guarantees that a maildir-reading program will not see a partially written message. There can be multiple programs reading a maildir at the same time. They range from mail user agents (MUAs), which access the server's file system directly, through Internet Message Access Protocol or Post Office Protocol servers acting on behalf of remote MUAs, to utilities such as biff and rsync, which may or may not be aware of the maildir structure. Readers should never look in tmp.
When a cognizant maildir-reading process (either a POP or IMAP server, or a mail user agent acting locally) finds messages in the new directory, it must move them to cur. It is just a means to notify the user "you have X new messages".[11] This moving needs to be done using the atomic filesystem rename(), as the alternative link-then-unlink technique is non-atomic and may result in duplicated messages. An informational suffix is appended to filenames at this stage. It consists of a colon (to separate the unique part of the filename from the actual information), a "2", a comma and various flags. The "2" specifies the version of the information that follows the comma. "2" is the only currently officially specified version, "1" being an experimental version. The specification defines flags that show whether the message has been read, deleted and so on: the initial (capital) letter of "Passed", "Replied", "Seen", "Trashed", "Draft", and "Flagged".[7] Applications often choose to supplement this very limited set of flags, for example notmuch[12] offers flag synchronization in addition to arbitrary user-defined flags,[13] while Dovecot uses lowercase letters to match 26 IMAP keywords,[6] which may include keywords such as $MDNSent or user-defined flags.
Although Maildir was intended to allow lockless usage, in practice some software that uses Maildirs also uses locks, such as Dovecot.[14]
File-system compatibility issues
[edit]The Maildir standard can only be implemented on systems that accept colons in filenames. [15]
Systems that don't allow colons in filenames (this includes Microsoft Windows and some configurations of Novell Storage Services) can use a non-standard alternative separator, such as ";" or "-". It is often trivial to patch free and open-source software to use a different separator.[16]
As there is currently no agreement on what character this alternative separator should be, there can be interoperability difficulties between different Maildir-supporting programs on these systems. However, not all Maildir-related software needs to know what the separator character is, because not all Maildir-related software needs to be able to read or modify the flags of a message ("read", "replied to" etc.); software that merely delivers to a Maildir or archives old messages from it based only on date, should work no matter what separator is in use. If only the MUA needs to read or modify message flags, and only one MUA is used, then non-standard alternative separators may be used without interoperability problems.
Software that supports Maildir directly
[edit]- Dovecot IMAP server
- Courier Mail Server SMTP and IMAP server, for which the Maildir++ format was invented
- Sendmail The original SMTP server
- Exim SMTP server
- Postfix SMTP server
- qmail SMTP server, for which the Maildir format was invented
- MeTA1 SMTP server
- OpenSMTPD SMTP server
- Stalwart Mail Server, SMTP and IMAP server implemented in Rust
- procmail
- Dovecot delivery agent
- maildrop
- getmail, a Maildir-aware mail-retrieval and delivery agent alternative to Fetchmail
- fdm
- muchsync, synchronising notmuch mail mailboxes between any number of replicas
- OfflineIMAP
- isync, synchronises mailboxes, supporting Maildir and IMAP4
- Attomail, a minimal Maildir-aware MDA implemented in Haskell
- aerc[17] (efficient and extensible email client)
- Balsa previously the official GNOME mail reader (prior to Evolution)
- Cone a curses-based mail reader
- Evolution, official GNOME mail client
- GNUMail
- Gnus
- KMail, KDE mail reader
- mailx
- Mutt
- Notmuch[18] (fast, global-search and tag-based email system)
- Pine/Alpine
- Mozilla Thunderbird – experimental and “disabled by default because there are still many bugs” [19]
Notes and references
[edit]- ^ a b Bernstein, Daniel J. (1995). "maildir(5)". Archived from the original on 1997-10-12. Retrieved 2018-11-23.
- ^ Blum, Richard (2001). Postfix. Sams Publishing. ISBN 978-0-672-32114-6.
- ^ a b c Varshavchik, Sam (2009). "maildir(5)". Archived from the original on 2024-04-17. Retrieved 2024-08-09.
- ^ Varshavchik, Sam (2011). "Maildir++". Archived from the original on 2024-05-29. Retrieved 2024-08-09.
- ^ a b Bernstein., Daniel J. (c. 2000) [First published 2000 or earlier]. "Using maildir format". Archived from the original on 2000-09-02. Retrieved 2018-11-23.
- ^ a b Dovecot Wiki: maildir format
- ^ a b Bernstein., Daniel J. (2003) [The earliest version of this document was first published in 2000 or earlier]. "Using maildir format". Archived from the original on 2003-04-01. Retrieved 2018-11-23.
- ^ Sirainen, Timo. "Maildir Mailbox Format: Mail Delivery'". Archived from the original on 2024-06-24. Retrieved 2024-08-09.
All this trouble is rather pointless. Only the first step is what really guarantees that the mails won't get overwritten, the rest just sounds nice. Even though they might catch a problem once in a while, they give no guaranteed protection and will just as easily pass duplicate filenames through and overwrite existing mails.¶ Step 2 is pointless because there's a race condition between steps 2 and 3. PID/host combination by itself should already guarantee that it never finds such a file. If it does, something's broken and the stat() check won't help since another process might be doing the same thing at the same time, and you end up writing to the same file in tmp/, causing the mail to get corrupted.¶ In step 4 the link() would fail if an identical file already existed in the Maildir, right? Wrong. The file may already have been moved to cur/ directory, and since it may contain any number of flags by then you can't check with a simple stat() anymore if it exists or not.¶ Step 2 was pointed out to be useful if clock had moved backwards. However, this doesn't give any actual safety guarantees because an identical base filename could already exist in cur/. Besides if the system was just rebooted, the file in tmp/ could probably be even overwritten safely (assuming it wasn't already link()ed to new/).¶ So really, all that's important in not getting mails overwritten in your Maildir is step 1: Always create filenames that are guaranteed to be unique. Forget about the 2 second waits and such that the Qmail's man page talks about.
- ^ "Wayback Machine snapshots of cr.yp.to/proto/maildir.html". Internet Archive. 2023. Archived from the original on 2023-05-03. Retrieved 2023-11-23.
{{cite web}}: CS1 maint: bot: original URL status unknown (link) - ^ "rename". The Open Group. 2013. Retrieved 23 July 2016.
That specification requires that the action of the function be atomic.
- ^ Sam Varshavchik (25 July 2016). "Management of maildir structures". courier-users (Mailing list). Retrieved 26 July 2016.
- ^ "Notmuch mail system homepage". notmuchmail.org. Retrieved 2019-06-22.
- ^ "notmuch 0.38.3 documentation". notmuch-config. Retrieved 2024-04-17.
- ^ Sirainen, Timo. "Maildir Mailbox Format: Locking". Archived from the original on 2024-06-24. Retrieved 2024-08-09.
- ^ "mailbox — Manipulate mailboxes in various formats". Python documentation. Retrieved 2023-06-19.
- ^ mutt maildir support: workaround for filesystems that don't accept colons
- ^ "aerc - the world's best email client homepage". aerc-mail.org.
- ^ "Notmuch mail system homepage". notmuchmail.org. Retrieved 2019-06-22.
- ^ "Maildir in Thunderbird". mozilla.org. Retrieved 2020-12-06.
See also
[edit]External links
[edit]Maildir
View on Grokipedia1491941793.M41850P8566.example.com:2,S), where the info portion after the colon denotes status flags like read, flagged, or replied.[1] This structure prevents partial deliveries and corruption risks inherent in appending to a shared file, making it particularly advantageous for multi-user environments and high-volume servers.[2]
Widely adopted in modern email systems, Maildir is supported by servers like Postfix, Dovecot, and Courier, as well as clients such as Mutt and Thunderbird (with recent experimental support).[3] Extensions like Maildir++ enhance it for hierarchical folders and quotas, while implementations often include index files (e.g., dovecot-uidlist) for faster IMAP access and keyword handling.[3] Its simplicity and robustness have made it a standard for Unix-like systems, prioritizing data safety without compromising performance.[1]
Introduction
Definition and Purpose
Maildir is an on-disk email storage format that organizes individual email messages as separate files within a directory-based structure, distinct from concatenated formats like mbox that store all messages in a single shared file. This approach inherently avoids the file locking issues prevalent in mbox, where multiple processes accessing the same file risk race conditions, partial writes, or data corruption.[4][1] The primary purpose of Maildir is to facilitate safe, concurrent access to email storage by multiple processes—such as mail delivery agents and user agents—without requiring locks or synchronization mechanisms, thereby minimizing the potential for errors in multi-user or networked environments. Designed specifically for Unix-like systems, it ensures that operations like delivery and retrieval can occur simultaneously across processes or even over network file systems like NFS, with guaranteed message integrity.[4][1] At its core, Maildir separates email storage into per-user directories, each containing three subdirectories: tmp for temporary message creation, new for incoming unread messages, and cur for messages that have been processed or read. Delivery follows an atomic process where a message is fully written to the tmp subdirectory before being renamed and moved to new, ensuring the operation is indivisible and complete even if interrupted.[4][1] Maildir was introduced by Daniel J. Bernstein as part of the qmail mail transfer agent's delivery model, emphasizing reliability and robustness in shared hosting scenarios over absolute performance optimizations.[4][5]History and Development
The Maildir format was developed by Daniel J. Bernstein as part of the qmail mail transfer agent, with initial work beginning in December 1995 to address the limitations of traditional mbox formats, such as risks of corruption from concurrent access and the need for file locking mechanisms.[6] qmail's beta versions incorporated Maildir as an optional mailbox structure to enable reliable delivery without locking, even over network file systems like NFS, ensuring messages could be safely appended during crashes or simultaneous operations.[1] The format was first specified in qmail 0.90, released on August 1, 1996, and became part of the stable qmail 1.00 release on February 20, 1997.[6] Adoption of Maildir expanded beyond qmail in the early 2000s, driven by its reliability advantages for multi-user environments. Postfix, a widely used mail transfer agent, integrated native Maildir support from its inaugural version 1.0, released in February 2001, allowing seamless delivery to Maildir directories via configuration parameters likehome_mailbox = Maildir/.[7] The Courier mail server, released in 1999, also adopted Maildir and extended it for IMAP folder hierarchies.[8] Dovecot, an IMAP and POP3 server launched in July 2002, further popularized the format by incorporating it as a default storage option in the early 2000s.[9]
A key evolutionary milestone was the introduction of Maildir++ by the Courier project in the early 2000s to support hierarchical mailboxes for IMAP, using dotted subdirectories (e.g., .Sent) and adding message flags and keywords via filename extensions, which Dovecot later adopted for enhanced IMAP compatibility.[8] Although Maildir has not been formally ratified as an IETF standard, RFC 6778 (2012) specifies requirements for IETF email list archiving systems to support Maildir as a one-message-per-file format for import and export, reflecting ongoing efforts to document its use in IETF contexts like list archives.[10] Its popularity surged in the 2010s alongside the rise of IMAP servers, as implementations like Dovecot and Postfix emphasized its scalability for large-scale deployments.
Modern adaptations of Maildir, particularly post-2015, have incorporated support for Unicode filenames to handle internationalized email, leveraging underlying file system capabilities and protocols like SMTPUTF8 in Postfix 3.0 (released February 2015), which enables UTF-8 in message headers and addresses without corrupting directory structures.[11] Dovecot implementations from this period also updated folder naming to better accommodate Unicode via modified UTF-7 encoding for IMAP compatibility, ensuring robustness in global environments while preserving the format's core atomic delivery principles.[9]
Format Specifications
Core Directory Structure
The Maildir format organizes email storage in a per-user root directory, typically namedMaildir, which serves as the foundation for all message handling without requiring database locks or shared files. This root directory contains exactly three subdirectories: tmp for temporary message delivery, new for incoming undelivered messages, and cur for messages that have been delivered and potentially read.[1]
The tmp subdirectory is used exclusively for atomic writes during message delivery, where a mail delivery agent (MDA) writes the message file to a unique temporary name to avoid corruption from concurrent operations; once complete, the file is atomically renamed or linked into new to ensure safe integration into the mailbox. The new subdirectory holds messages ready for retrieval by the mail user agent (MUA), representing undelivered or unseen mail that has not yet been processed. In contrast, the cur subdirectory stores messages that have been accessed or manipulated, with filenames optionally appended by an Info string (e.g., status flags like 'S' for seen or 'R' for replied) to track user interactions without altering the message content itself. These rules enable race-free operations across multiple processes, as the format relies on filesystem semantics rather than explicit locking.[1][3]
To support hierarchical organization beyond a single inbox, Maildir incorporates extensions for subfolders using the convention of prefixed dot-directories, such as .Sent/ or .Archive/, each replicating the standard tmp, new, and cur structure within the parent root (e.g., Maildir/.Sent/{tmp,new,cur}). This allows for categorized storage like sent mail or drafts while maintaining the core format's integrity.[1][12]
A distinctive feature of Maildir is the absence of any central index file or metadata database; instead, message lists are generated by scanning the new and cur subdirectories at runtime, which promotes scalability in distributed environments but can increase I/O overhead for large mailboxes due to repeated filesystem traversals.[1][3]
File Naming and Content Rules
In the Maildir format, filenames for message files in thetmp and new subdirectories are designed to ensure uniqueness without relying on atomic operations beyond standard filesystem rename capabilities. The original specification recommends a structured format consisting of the current Unix timestamp in seconds since January 1, 1970 (e.g., 1234567890), followed by a dot, a delivery identifier (typically including the process ID, queue ID, and microsecond fraction for granularity, such as M12345P001), another dot, and the fully qualified hostname (with invalid characters escaped, e.g., server.example.com). This results in examples like 1234567890.M12345P001.server.example.com, preventing collisions even for simultaneous deliveries on the same system.[1]
Each Maildir file stores a complete, unmodified email message conforming to the Internet Message Format specified in RFC 5322, encompassing all original headers followed immediately by the body, which may include binary data and need not end with a newline. No additional metadata, such as UUCP-style "From_" lines or quoting of special characters, is inserted during storage to preserve the message's integrity.[1][13]
Upon processing, when a message is relocated from new to the cur subdirectory, an optional info string may be appended to the filename in the form :2,flags, where flags are a comma-separated sequence of status indicators in ASCII order, such as RS for replied and seen (:2,RS). The base specification defines flags including R (replied), S (seen), D (draft), F (flagged), P (passed), A (answered, implementation-specific), and T (trashed), though their usage is optional and varies by implementation.[1]
Delivered files in new and cur are treated as immutable, with no further modifications permitted to ensure safe concurrent access by multiple processes. File size limits are governed by the filesystem; for example, modern ext4 supports individual files up to 16 terabytes.[1][3][14]
Maildir++ Extensions
Maildir++ is a Dovecot-specific extension to the base Maildir format, introduced in 2003 to enhance support for advanced IMAP4rev1 features such as message flags and custom keywords. This extension modifies the Info portion of message filenames—appended after the second colon in the format<time>.<host>.<pid>.<random>:2,<info>—to include a comma-separated list of flags without altering the core file content or naming conventions. For instance, a filename might end in :2,SFRAK, where S denotes seen, F flagged, R replied, A answered, and K a custom keyword, enabling IMAP clients to track message states efficiently.[3]
A key addition in Maildir++ is the support for up to 26 custom IMAP keywords, mapped to lowercase letters a through z via a dovecot-keywords file in the mailbox root, with each keyword limited to 32 characters. These keywords allow for user-defined labels like $Junk or $Important, expanding beyond the standard Maildir flags (D for draft, F for flagged, P for passed, R for replied, S for seen, T for trashed). The doveadm utility facilitates management of these extensions, including commands to search, copy, or expunge messages based on flags and keywords. Maildir++ maintains backward compatibility with standard Maildir implementations by preserving unrecognized fields, though strict qmail-based systems may ignore or overwrite the extended info during delivery.[3]
Unlike the original Maildir specification by Daniel J. Bernstein, which lacks native IMAP keyword support, Maildir++ originated as a Courier-IMAP innovation and was adopted by Dovecot for its IMAP server, with variants appearing in some Courier implementations. This extension is not part of the qmail core spec and can lead to interoperability issues in environments enforcing strict adherence to the original format, as non-standard fields like size metadata (e.g., ,S=<bytes>) may be discarded by other mail user agents.[8]
Operational Mechanics
Message Delivery Process
The message delivery process in Maildir relies on a structured workflow designed to ensure atomicity and concurrency without the need for file locking. A delivery agent, such as a local mail transfer agent, begins by generating a unique filename for the incoming message, typically in the formattime.<delivery_identifier>.<hostname>, where time is the current Unix timestamp in seconds, delivery_identifier is a unique string (e.g., starting with M followed by process ID or counter) to ensure uniqueness across deliveries on the same host within the same second, and hostname has / replaced by \057 and : by \072 to handle invalid characters.[1][8] The agent then creates a temporary file in the tmp subdirectory using this name and writes the complete message content to it, verifying that all bytes are successfully written to prevent partial deliveries.[8]
Once the message is fully written to the temporary file, the agent performs an atomic rename operation to move it to the new subdirectory, preserving the unique filename; this rename is guaranteed to be atomic on Unix-like filesystems, ensuring that either the entire message appears in new or it remains in tmp if the operation fails, thus avoiding race conditions with concurrent readers or other deliverers.[1] To handle potential duplicates, the agent checks for the existence of a file with the same base timestamp and identifier in the new or cur subdirectories before proceeding; if found, it retries with a modified identifier after a short delay, such as 2 seconds.[8] Additionally, to prevent mail loops in aliasing or forwarding scenarios, delivery agents like those in qmail add a Delivered-To header containing the recipient address and check for its presence matching the target before delivering, refusing delivery if a loop is detected.
Maildir files and directories enforce strict permissions for privacy and security: the Maildir root and its subdirectories (tmp, new, [cur](/page/Cur)) are owned by the recipient user with mode 0700, preventing access by other users or groups, while individual message files are owned by the user with mode 0600, readable and writable only by the owner.[8][15] This setup assumes delivery runs as the recipient user or with appropriate privileges to set ownership.
The absence of locking is a core feature, enabled by the atomic rename and unique filenames, allowing multiple deliveries and message retrievals to occur simultaneously without interference on the same Maildir.[1] For error handling, delivery agents return standardized exit codes from <sysexits.h>: for instance, code 71 (EX_OSERR) or 75 (EX_TEMPFAIL) indicates a temporary failure, such as inability to access the tmp directory or write the file, prompting the mail transfer agent to retry later, while permanent errors like quota exceeded result in code 0 or other values leading to bounces.[16] If the rename fails after successful writing, the file remains in tmp for potential cleanup or retry.[8]
Message Retrieval and Management
In the Maildir format, message retrieval begins with mail user agents (MUAs) or servers scanning thenew/ subdirectory for unseen messages, which are stored as individual files with unique filenames typically formatted as time.delivery_identifier.hostname, where the delivery_identifier often includes details like process ID and, in some implementations, microseconds, reflecting the delivery time.[1] Upon accessing a message, the MUA moves the file from new/ to the cur/ subdirectory and appends an info string to the filename, such as :2,S to indicate the "seen" flag, allowing status tracking without modifying the message content.[8] Messages in cur/ retain their original delivery timestamp in the filename for ordering, while the file's modification time (mtime) is preserved and used by many implementations for sorting purposes, aligning with IMAP's INTERNALDATE attribute as defined in RFC 3501.[3]
Management operations in Maildir emphasize simple filesystem actions for efficiency and reliability. Deletion is performed by unlinking the file directly from new/ or cur/, removing it atomically without affecting other messages.[1] Archiving involves moving the file to a subfolder, represented as a dotted subdirectory like .Archive/cur/, which maintains the Maildir structure recursively while preserving the filename and flags.[8] Basic searching relies on filesystem tools to scan directories or grep contents, though for larger stores, external indexing tools are commonly employed since Maildir lacks native support for threading or full-text search.[1]
Maildir's design ensures concurrency safety during retrieval and management, as all messages are independent files, allowing multiple MUAs to read from new/ and cur/ without locks or coordination, even over network filesystems like NFS.[1] Writes, such as deliveries or moves, are restricted to authorized processes that use the tmp/ subdirectory for temporary staging, ensuring atomicity and preventing conflicts through unique filename generation.[8] Post-2010 developments like the notmuch indexer, which builds a Xapian-based database over Maildir stores for tag-based searching and threading, and mu, a similar tool for fast querying by metadata and content, address the format's limitations in scalable retrieval for large archives.[17][18]
Compatibility and Limitations
File System Compatibility
Maildir relies on POSIX-compliant filesystems that support atomic rename operations to ensure safe message delivery without the need for locking mechanisms. This atomicity, provided by the rename() system call, allows messages to be moved from the temporary (tmp) subdirectory to the new (new) subdirectory in a single, uninterruptible operation, preventing partial deliveries or duplicates. Examples of suitable filesystems include ext3, ext4, XFS, and ZFS, which meet these POSIX requirements as defined in the Single UNIX Specification.[1] In addition to atomic renames, Maildir requires support for long pathnames exceeding 255 characters and large individual file sizes to accommodate deeply nested directory structures in extensions like Maildir++ and sizable email attachments. POSIX standards define a minimum _POSIX_PATH_MAX of 256 bytes for total path lengths (though many implementations support larger values, such as 4096 on Linux) and NAME_MAX of at least 14 characters per component (though modern implementations typically support 255), enabling the format's scalability. Large file support, as per POSIX Large File Specification extensions, is also essential for handling messages beyond 2 GB without truncation. Maildir operates fully on Unix-like systems such as Linux, BSD variants, and macOS, where native filesystems like ext4, UFS, and APFS provide the necessary POSIX features. On Windows, compatibility is partial and typically achieved through environments like Cygwin, which emulates POSIX semantics atop NTFS; however, limitations arise due to Windows' restriction on colons (:) in filenames, a character integral to Maildir's unique message naming convention (e.g., 1234567890.M123P456Q789R,c:2,S). Samba can facilitate access to Maildir stores on shared Unix filesystems, but Windows clients face similar rename atomicity and character constraints when writing.[1][19] Certain filesystems pose specific challenges for Maildir. FAT32 and VFAT, common in cross-platform removable media, prohibit colons in filenames and lack robust atomic rename guarantees in non-POSIX contexts, rendering them unsuitable for reliable Maildir use despite support for long filenames. NFSv3 environments can encounter performance issues related to directory listing operations (e.g., readdirplus), though Maildir's lock-free design mitigates traditional locking problems; mounting with the nordirplus option is recommended to address these. Case-sensitive filesystems are advised to avoid potential conflicts in folder naming, as case-insensitive variants like the default configuration of APFS on macOS (as of macOS 10.13 and later) may lead to ambiguities in subfolder hierarchies.[3][20] Modern filesystems enhance Maildir's efficiency through features like TRIM support on SSDs, which enables automatic space reclamation upon message deletion by issuing discard commands during unlink operations, reducing wear and improving performance. Since around 2008, with the widespread adoption of UTF-8 as the standard encoding for filenames in POSIX systems, Maildir has benefited from native Unicode support in path components, allowing internationalized folder names without additional encoding layers.Common Issues and Workarounds
One common issue with the Maildir format is disk space inefficiency arising from storing each email as a separate file, which leads to overhead from filesystem metadata, inodes, and minimum block allocation sizes, particularly for small messages. For instance, on filesystems such as ext4 or NTFS, even tiny files typically consume at least 4 KB, resulting in significant bloat for inboxes with thousands of short emails.[21] Another frequent problem occurs with large inboxes containing millions of messages, where scanning the directory for new or unread mail becomes slow due to the filesystem's need to enumerate and inspect numerous files, exacerbating performance on shared or network filesystems like NFS.[22] To address this, external indexers such as mu, which builds a Xapian database for full-text search, enable rapid querying without full directory scans.[23] Quota enforcement poses challenges in the original Maildir specification, which lacks built-in limits, allowing mailboxes to grow unbounded and complicating resource management on servers hosting multiple users.[1] The Maildir++ extension mitigates this by introducing amaildirsize file that tracks total bytes and message count, enforcing soft quotas through delivery agents like those in Courier MTA, though updates occur periodically (every 15 minutes) and can be bypassed by non-compliant clients.[24][25]
Early Maildir implementations were susceptible to symlink attacks in the tmp/ subdirectory during message delivery, where a local attacker could create a symbolic link pointing to a sensitive file, causing the delivery process to overwrite arbitrary locations if it followed the link before writing. This vulnerability, exemplified in tools like procmail and getmail, was largely mitigated in secure delivery agents after 2005 through techniques like exclusive file opens (O_EXCL) or temporary file creation APIs that prevent race conditions.
Interrupted deliveries in Maildir leave incomplete files in the tmp/ directory, as the atomic rename to new/ fails; these stale files accumulate if not addressed, potentially filling disk space.[1] Periodic cleanup scripts, often run via cron, resolve this by deleting tmp/ files older than 36 hours, a threshold recommended in the format specification to balance safety and storage.[26]
The format's reliance on frequent small writes—for deliveries, flag updates, and moves—can accelerate wear on solid-state drives (SSDs) due to write amplification and limited program/erase cycles, though modern SSDs with overprovisioning mitigate this for typical workloads. In Dovecot 2.3 and later (released 2017), lazy scanning optimizes this by checking the cur/ directory's modification time instead of rescanning all files on every access, reducing unnecessary I/O.[27]
Software Integration
Mail Transfer and Delivery Agents
Mail Transfer Agents (MTAs) and Mail Delivery Agents (MDAs) play crucial roles in handling email transport and local delivery to Maildir-format mailboxes, ensuring reliable storage without the locking issues common in older formats like mbox. Several prominent open-source MTAs natively or configurably support Maildir delivery, originating from the format's introduction with qmail in 1996.[4] These agents leverage Maildir's file-per-message structure to enable concurrent access and atomic delivery operations. qmail, developed by Daniel J. Bernstein, was the first MTA to implement Maildir as its default storage format upon its initial release in 1996, emphasizing strict adherence to the specification for reliability and security in high-volume environments. Postfix, introduced in 2001, provides built-in Maildir support through its local delivery mechanism, allowing messages to be appended to individual files in the specified directory when the mailbox path ends with a slash.[28] A key feature in Postfix is thevirtual_mailbox_domains parameter, which defines domains for virtual mailboxes stored in Maildir format, enabling efficient handling of multiple domains without system user accounts.[29] Exim offers configurable Maildir support via its appendfile transport, where delivery to a directory with maildir_format enabled creates files using the standard Maildir naming convention (timestamp, hostname, delivery identifier), supporting both local and virtual users through runtime options.[30]
For local delivery, several MDAs integrate seamlessly with Maildir. procmail, a filtering-capable MDA, supports Maildir delivery through configuration, such as appending a slash to the folder path in recipes, allowing recipe-based sorting into subfolders while respecting the format's structure.[31] maildrop, part of the Courier mail server suite, natively supports Maildir delivery with built-in filtering, extending qmail's format to include features like quotas and hierarchical folders.[32] Dovecot's LMTP (Local Mail Transfer Protocol) implementation serves as an MDA for final delivery to Maildir, handling authentication and indexing in a single process to minimize overhead during local drops.
Integration between MTAs and MDAs often involves simple configuration directives; for example, Postfix can invoke procmail for Maildir delivery by setting mailbox_command = /usr/bin/[procmail](/page/Procmail) -a "$EXTENSION" in its main.cf file, passing recipient extensions for virtual aliasing.[28] This setup ensures filtered delivery while maintaining Maildir's atomicity, as referenced in the broader message delivery process.
