summaryrefslogtreecommitdiffstats
path: root/doc/wiki/Design.Storage.MailboxList.txt
blob: 6c27883848a67cf4c420b2fd492e5023bfeb165d (plain)
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
Mailbox List
============

'src/lib-storage/mailbox-list.h' and 'mailbox-list-private.h' describes mailbox
list. The purpose of mailbox list is to manage mailbox storage name<-> physical
directory path mapping. Its most important functions are:

 * listing existing mailboxes,
 * creating directories for new mailboxes (but not the mailboxes themselves,
   that's storage's job),
 * deleting mailboxes,
 * renaming mailboxes and
 * managing mailbox subscriptions.

Mailbox list code also internally creates and updates mailbox changelog (in
'dovecot.mailbox.log' file), which keeps track of mailbox deletions, renames
and subscription changes. This is primarily useful for dsync utility.

Mailbox list is configured by <mail_location> [MailLocation.txt] setting, which
fills 'struct mailbox_list_settings':

 * root_dir: The root mail directory (e.g. with
   'mail_location=maildir:~/Maildir' it would be the '~/Maildir').
 * index_dir: Directory under which index files are written to. Empty string
   means in-memory indexes. Defaults to root_dir.
 * control_dir: Directory under which control files are written to. Control
   files are files that contain some important metadata information about
   mailbox so (unlike index files) they should never be deleted. For example
   subscriptions file is a control file. Defaults to root_dir.
 * alt_dir: This is currently <dbox> [MailboxFormat.dbox.txt]-specific setting.

 * inbox_path: Path to INBOX mailbox. This exists mainly because with mbox
   format INBOX is often in a different location than other mailboxes.
 * subscription_fname: Filename used by subscriptions file.
 * dir_guid_fname: Filename used to store directories' (not mailboxes') global
   UIDs. Directory GUIDs are mainly useful for dsync.
 * maildir_name: Directory name under which the actual mailboxes are stored in,
   such as dbox-Mails/ with dbox. See the .h file for more detailed
   description.
 * mailbox_dir_name: If non-empty, store all mailboxes under
   root_dir/mailbox_dir_name/.

Listing mailboxes
-----------------

First the list operation is initialized with one of the init functions:

 * 'mailbox_list_iter_init()' lists mailboxes that match the given pattern.
 * 'mailbox_list_iter_init_multiple()' lists mailboxes that match any of the
   given patterns list.
 * 'mailbox_list_iter_init_namespaces()' lists matching mailboxes from all
   namespaces.
    * 'MAILBOX_LIST_ITER_SKIP_ALIASES' flag skips namespaces that have
      'alias_for' set. You usually want to set this flag to avoid processing
      the same mailbox multiple times.

The patterns are IMAP-style patterns with '%' and '*' wildcards as described by
RFC 3501: '%' matches only up to next hierarchy separator, while '*' matches
the rest of the string.

These flags control what mailboxes are returned:

 * 'MAILBOX_LIST_ITER_NO_AUTO_INBOX' doesn't list INBOX unless it physically
   exists. Normally INBOX is listed, because INBOX doesn't need to be (and
   cannot be) explicitly created. It can always be opened and messages can be
   saved to it, it's just automatically created when it doesn't exist.
 * 'MAILBOX_LIST_ITER_SELECT_SUBSCRIBED' lists only subscribed mailboxes.
 * 'MAILBOX_LIST_ITER_SELECT_RECURSIVEMATCH' is currently only useful when
   combined with '_SELECT_SUBSCRIBED' flag. Then it adds
   'MAILBOX_CHILD_SUBSCRIBED' flags for mailboxes whose children are
   subscribed. It also lists mailboxes that aren't themselves subscribed, but
   have children that do.

These flags control what is returned for matching mailboxes:

 * 'MAILBOX_LIST_ITER_RETURN_NO_FLAGS' can be set when you don't care about
   mailbox flags. They're then set only if it can be done without any
   additional disk I/O.
 * 'MAILBOX_LIST_ITER_RETURN_SUBSCRIBED' returns mailbox's subscription state.
 * 'MAILBOX_LIST_ITER_RETURN_CHILDREN' sets "has child mailboxes" or "doesn't
   have child mailboxes" flag.

Other flags:

 * 'MAILBOX_LIST_ITER_RAW_LIST' should usually be avoided. It ignores ACLs and
   just returns everything.
 * 'MAILBOX_LIST_ITER_VIRTUAL_NAMES' enables listing to use virtual names
   instead of storage names in patterns and returned mailbox names.

Once listing is initialized, 'mailbox_list_iter_next()' can be called until it
returns NULL. The returned mailbox_info struct contains:

 * 'name': Mailbox's name, either virtual or storage name depending on
   '_VIRTUAL_NAMES' flag.
 * 'ns': Mailbox's namespace. This is useful only when mailboxes are listed
   using 'mailbox_list_iter_init_namespaces()'.
 * 'flags': Mailbox flags:
    * 'MAILBOX_NOSELECT': Mailbox exists, but can't be selected. It's possible
      that it can be created and then it becomes selectable. For example with
      mbox and FS layout the directories aren't selectable mailboxes.
    * 'MAILBOX_NONEXISTENT': Mailbox doesn't exist. It's listed only because it
      has child mailboxes that do exist but don't match the pattern.
       * Example: "foo/bar" exists, but "foo" doesn't. "%", "foo" or "*o"
         pattern would list "foo", because it matches the pattern but its child
         doesn't. Then again "*", "*bar" or "%/%" wouldn't list "foo", because
         "foo/bar" matches the pattern (and is also listed). Something like
         "*asd*" wouldn't match either "foo" or "foo/bar" so neither is
         returned.
    * 'MAILBOX_CHILDREN' and 'MAILBOX_NOCHILDREN': Mailbox has or doesn't have
      children. If neither of these flags are set, it's not known if mailbox
      has children.
    * 'MAILBOX_NOINFERIORS': Mailbox doesn't have children and none can ever be
      created. For example with mbox and FS layout the mailboxes have this flag
      set, because files can't be created under files.
    * 'MAILBOX_MARKED' and 'MAILBOX_UNMARKED': Mailbox has or doesn't have
      messages with \Recent flags. If neither is set, the state is unknown.
      Because this check is done in a very cheap way, having 'MAILBOX_MARKED'
      doesn't always mean that there are \Recent flags. However, if
      'MAILBOX_UNMARKED' is returned it is guaranteed to be correct. (False
      positives are ok, false negatives are not ok.)
    * 'MAILBOX_SUBSCRIBED': Mailbox is subscribed.
    * 'MAILBOX_CHILD_SUBSCRIBED': Mailbox has a child that is subscribed (and
      '_SELECT_RECURSIVEMATCH' flag was set).

Finally the listing is deinitalized with 'mailbox_list_iter_deinit()'. If it
returns -1, it means that some mailboxes perhaps weren't listed due to some
internal error.

If you wish to get mailbox_info flags only for a single mailbox, you can use
'mailbox_list_mailbox()'.

Directory permissions
---------------------

'mailbox_list_get_permissions()' and 'mailbox_list_get_dir_permissions()' can
be used to get wanted permissions for newly created files and directories.

 * For global files, give NULL as the mailbox name. The permissions are then
   based on the root_dir. If root_dir doesn't exist, it returns 0700/0600 mode.
 * For per-mailbox files, give the mailbox name. The permissions are then based
   on the mailbox's directory.

The returned permissions are:

 * mode: Creation mode, like 0600.
 * gid: Group that should be set, unless it's '(gid_t)-1'. There are 3 reasons
   why it could be that:
    * directory has g+s bit set, so the wanted group is set automatically
    * group is the same as process's effective GID, so it gets set
      automatically
    * mode's group permissions are the same as world permissions, so group
      doesn't matter.
 * gid_origin: This string points to the directory where the group (and
   permissions in general) was based on, or "defaults" for internal defaults.

If changing the group fails with EPERM, 'eperm_error_get_chgrp()' can be used
to log a nice and understandable error message.

(This file was created from the wiki on 2019-06-19 12:42)