1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
|
Mbox Mailbox Format
===================
Contents
1. Mbox Mailbox Format
1. Locking
1. Dotlock
2. Deadlocks
2. Directory Structure
3. Dovecot's Metadata
4. Dovecot's Speed Optimizations
5. From Escaping
6. Mbox Variants
7. References
Usually UNIX systems are configured by default to deliver mails to
'/var/mail/username' or '/var/spool/mail/username' mboxes. In IMAP world these
files are called INBOX mailboxes. IMAP protocol supports multiple mailboxes
however, so there needs to be a place for them as well. Typically they're
stored in '~/mail/' or '~/Mail/' directories.
The mbox file contains all the messages of a single mailbox. Because of this,
the mbox format is typically thought of as a slow format. However with
Dovecot's indexing this isn't true. Only expunging messages from the beginning
of a large mbox file is slow with Dovecot, most other operations should be
fast. Also because all the mails are in a single file, searching is much faster
than with maildir.
Modifications to mbox may require moving data around within the file, so
interruptions (eg. power failures) can cause the mbox to break more or less
badly. Although Dovecot tries to minimize the damage by moving the data in a
way that data should never get lost (only duplicated), mboxes still aren't
recommended to be used for important data.
Locking
-------
Locking is a mess with mboxes. There are multiple different ways to lock a
mbox, and software often uses incompatible locking. See <MboxLocking.txt> for
how to check what locking methods some commonly used programs use.
There are at least four different ways to lock a mbox:
* *dotlock*: 'mailboxname.lock' file created by almost all software when
writing to mboxes. This grants the writer an exclusive lock over the mbox,
so it's usually not used while reading the mbox so that other processes can
also read it at the same time. So while using a dotlock typically prevents
actual mailbox corruption, it doesn't protect against read errors if mailbox
is modified while a process is reading.
* *flock*: 'flock()' system call is quite commonly used for both read and
write locking. The read lock allows multiple processes to obtain a read lock
for the mbox, so it works well for reading as well. The one downside to it
is that it doesn't work if mailboxes are stored in NFS.
* *fcntl*: Very similar to *flock*, also commonly used by software. In some
systems this 'fcntl()' system call is compatible with 'flock()', but in
other systems it's not, so you shouldn't rely on it.*fcntl* works with NFS
if you're using lockd daemon in both NFS server and client.
* *lockf*: POSIX 'lockf()' locking. Because it allows creating only exclusive
locks, it's somewhat useless so Dovecot doesn't support it. With Linux
'lockf()' is internally compatible with 'fcntl()' locks, but again you
shouldn't rely on this.
Dotlock
-------
Another problem with dotlocks is that if the mailboxes exist in '/var/mail/',
the user may not have write access to the directory, so the dotlock file can't
be created. There are a couple of ways to work around this:
* Give a mail group write access to the directory and then make sure that all
software requiring access to the directory runs with the group's privileges.
This may mean making the binary itself setgid-mail, or using a separate
dotlock helper program which is setgid-mail. With Dovecot this can be done
by setting 'mail_privileged_group = mail'.
* Set sticky bit to the directory ('chmod +t /var/mail'). This makes it
somewhat safe to use, because users can't delete each others mailboxes, but
they can still create new files (the dotlock files). The downside to this is
that users can create whatever files they wish in there, such as a mbox for
newly created user who hadn't yet received mail.
Deadlocks
---------
If multiple lock methods are used, which is usually the case since dotlocks
aren't typically used for read locking, the order in which the locking is done
is important. Consider if two programs were running at the same time, both use
dotlock and fcntl locking but in different order:
* Program A: fcntl locks the mbox
* Program B at the same time: dotlocks the mbox
* Program A continues: tries to dotlock the mbox, but since it's already
dotlocked by B, it starts waiting
* Program B continues: tries to fcntl lock the mbox, but since it's already
fcntl locked by A, it starts waiting
Now both of them are waiting for each others locks. Finally after a couple of
minutes they time out and fail the operation.
Directory Structure
-------------------
By default, when listing mailboxes, Dovecot simply assumes that all files it
sees are mboxes and all directories mean that they contain sub-mailboxes. There
are two special cases however which aren't listed:
* '.subscriptions' file contains IMAP's mailbox subscriptions.
* '.imap/' directory contains Dovecot's index files.
Because it's not possible to have a file which is also a directory, it's not
normally possible to create a mailbox and child mailboxes under it.
However if you really want to be able to have mailboxes containing both
messages and child mailboxes under mbox, then Dovecot can be configured to do
this, subject to certain provisos; see <MboxChildFolders.txt>.
Dovecot's Metadata
------------------
Dovecot uses C-Client (ie. UW-IMAP, Pine) compatible headers in mbox messages
to store metadata. These headers are:
* X-IMAPbase: Contains UIDVALIDITY, last used UID and list of used keywords
* X-IMAP: Same as X-IMAPbase but also specifies that the message is a "pseudo
message"
* X-UID: Message's allocated UID
* Status: R (\Seen) and O (non-\Recent) flags
* X-Status: A (\Answered), F (\Flagged), T (\Draft) and D (\Deleted) flags
* X-Keywords: Message's keywords
* Content-Length: Length of the message body in bytes
Whenever any of these headers exist, Dovecot treats them as its own private
metadata. It does sanity checks for them, so the headers may also be modified
or removed completely. None of these headers are sent to IMAP/POP3 clients when
they read the mail.
*The MTA, MDA or LDA should strip all these headers _case-insensitively_ before
writing the mail to the mbox.*
Only the first message contains the X-IMAP or X-IMAPbase header. The difference
is that when all the messages are deleted from mbox file, a "pseudo message" is
written to the mbox which contains X-IMAP header. This is the "DON'T DELETE
THIS MESSAGE -- FOLDER INTERNAL DATA" message which you hate seeing when using
non-C-client and non-Dovecot software. This is however important to prevent
abuse, otherwise the first mail which is received could contain faked
X-IMAPbase header which could cause trouble.
If message contains X-Keywords header, it contains a space-separated list of
keywords for the mail. Since the same header can come from the mail's sender,
only the keywords are listed in X-IMAP header are used.
The UID for a new message is calculated from "last used UID" in X-IMAP header +
1. This is done always, so fake X-UID headers don't really matter. This is also
why the pseudo message is important. Otherwise the UIDs could easily grow over
2^31 which some clients start treating as negative numbers, which then cause
all kinds of problems. Also when 2^32 is exceeded, Dovecot will also start
having some problems.
Content-Length is used as long as another valid mail starts after that many
bytes. Because the byte count must be exact, it's quite unlikely that abusing
it can cause messages to be skipped (or rather appended to the previous
message's body).
Status and X-Status headers are trusted completely, so it's pretty good idea to
filter them in LDA if possible.
Dovecot's Speed Optimizations
-----------------------------
Updating messages' flags and keywords can be a slow operation since you may
have to insert a new header (Status, X-Status, X-Keywords) or at least insert
data in the header's value. Some mbox MUAs do this simply by rewriting all of
the mbox after the inserted data. If the mbox is large, this can be very slow.
Dovecot optimizes this by always leaving some space characters after some of
its internal headers. It can use this space to move only minimal amount of data
necessary to get the necessary data inserted. Also if data is removed, it just
grows these spaces areas.
'mbox_lazy_writes' setting works by adding and/or updating Dovecot's metadata
headers only after closing the mailbox or when messages are expunged from the
mailbox. C-Client works the same way. The upside of this is that it reduces
writes because multiple flag updates to same message can be grouped, and
sometimes the writes don't have to be done at all if the whole message is
expunged. The downside is that other processes don't notice the changes
immediately (but other Dovecot processes do notice because the changes are in
index files).
'mbox_dirty_syncs' setting tries to avoid re-reading the mbox every time
something changes. Whenever the mbox changes (ie. timestamp or size), it first
checks if the mailbox's size changed. If it didn't, it most likely meant that
only message flags were changed so it does a full mbox read to find it. If the
mailbox shrunk, it means that mails were expunged and again Dovecot does a full
sync. Usually however the only thing besides Dovecot that modifies the mbox is
the LDA which appends new mails to the mbox. So if the mbox size was grown,
Dovecot first checks if the last known message is still where it was last time.
If it is, Dovecot reads only the newly added messages and goes into a "dirty
mode". As long as Dovecot is in dirty mode, it can't be certain that mails are
where it expects them to be, so whenever accessing some mail, it first verifies
that it really is the correct mail by finding its X-UID header. If the X-UID
header is different, it fallbacks to a full sync to find the mail's correct
position. The dirty mode goes away after a full sync. If 'mbox_lazy_writes' was
enabled and the mail didn't yet have X-UID header, Dovecot uses MD5 sum of a
couple of headers to compare the mails.
'mbox_very_dirty_syncs' does the same as 'mbox_dirty_syncs', but the dirty
state is kept also when opening the mailbox. Normally opening the mailbox does
a full sync if it had been changed outside Dovecot.
From Escaping
-------------
In mboxes a new mail always begins with a "From " line, commonly referred to as
From_-line. To avoid confusion, lines beginning with "From " in message bodies
are usually prefixed with '>' character while the message is being written to
in mbox.
Dovecot doesn't currently do this escaping however. Instead it prevents this
confusion by adding Content-Length headers so it knows later where the next
message begins. Dovecot doesn't either remove the '>' characters before sending
the data to clients. Both of these will probably be implemented later.
Mbox Variants
-------------
There are a few minor variants of this format:
*mboxo* is the name of original mbox format originated with Unix System V.
Messages are stored in a single file, with each message beginning with a line
containing "From SENDER DATE". If "From " (case-sensitive, with the space)
occurs at the beginning of a line anywhere in the email, it is escaped with a
greater-than sign (to ">From "). Lines already quoted as such, for example
">From " or ">>>From " are *not* quoted again, which leads to irrecoverable
corruption of the message content.
*mboxrd* was named for Raul Dhesi in June 1995, though several people came up
with the same idea around the same time. An issue with the mboxo format was
that if the text ">From " appeared in the body of an email (such as from a
reply quote), it was not possible to distinguish this from the mailbox format's
quoted ">From ". mboxrd fixes this by always quoting already quoted "From "
lines (e.g. ">From ", ">>From ", ">>>From ", etc.) as well, so readers can just
remove the first ">" character. This format is used by qmail and getmail
(>=4.35.0).
*mboxcl* format was originated with Unix System V Release 4 mail tools. It adds
a Content-Length field which indicates the number of bytes in the message. This
is used to determine message boundaries. It still quotes "From " as the
original mboxo format does (and *not* as mboxrd does it).
*mboxcl2* is like mboxcl but does away with the "From " quoting.
*MMDF* (Multi-channel Memorandum Distribution Facility mailbox format) was
originated with the MMDF daemon. The format surrounds each message with lines
containing four control-A's. This eliminates the need to escape From: lines.
Dovecot currently uses mboxcl2 format internally, but it's planned to move to
combination of mboxrd and mboxcl.
*How a message is read stored in mbox extension ?*
* An email client reader scans throughout mbox file looking for From_ lines.
* Any From_ line marks the beginning of a message.
* Once the reader finds a message, it extracts a (possibly corrupted) envelope
sender and delivery date out of the From_ line.
* It then reads until the next From_ line or scans till the end of file,
whenever From_ comes first.
* It removes the last blank line and deletes the quoting of >From_ lines and
>>From_ lines and so on.
References
----------
* Wikipedia [http://en.wikipedia.org/wiki/Mbox]
* Qmail mbox [http://www.qmail.org/man/man5/mbox.html]
* Mbox family
[http://homepage.ntlworld.com/jonathan.deboynepollard/FGA/mail-mbox-formats.html]
* CommuniGatePro mbox
[http://www.communigate.com/CommuniGatePro/Mailboxes.html#mbox]
* MBOX File Viewer [http://www.freeviewer.org/mbox/]
(This file was created from the wiki on 2019-06-19 12:42)
|