Wandering Thoughts archives

2024-06-21

The IMAP LIST command as it interacts with client prefixes in Dovecot

Good IMAP clients will support the notion of a prefix the client puts on IMAP paths under some name. When I've written about this in the past (cf) I've been abstract about how it worked at the level of IMAP commands, and in particular at the level of the IMAP LIST command, which lists (some of) your folders and mailboxes. The IMAP LIST command is special here because it has two basic arguments, which in RFC 9051 are vaguely described as 'the reference name' and 'the mailbox name with possible wildcards'. This probably makes sense to IMAP experts who understand the difference, but for the rest of us it gets a bit confusing.

(The reason it's confusing is that other IMAP commands involving mailboxes (such as 'SELECT') only have a single argument, and also LIST reports folders and mailboxes as single arguments. This makes it a bit mysterious why LIST has two basic arguments, and how you're supposed to ask for things like 'please list all folders under X'. Or, if you're a system administrator reading Dovecot event logs, it makes it hard to know if a client is behaving badly or is just unusual.)

In particular, you might ask where an IMAP client puts its client prefix in a LIST command. The answer is that it depends on the IMAP client, as we discovered recently during some testing. If the client prefix is 'IMail/' and the client wants to know all of your folders and mailboxes, some clients will send:

x LIST "IMail/" "*"

Other IMAP clients will send:

x LIST "" "IMail/*"

As I have experimentally verified, Dovecot 2.3.16 will accept wildcards in either LIST argument, although this may not be something RFC 9051 requires. In a basic LIST syntax (the two-argument form I've given above), a second argument of "" has a special purpose and needs to be avoided (unless you want the information it provides). On Dovecot, you can write 'LIST "IMail/*" "%"' if you want to put all the heavy wildcard lifting into the first argument.

(Dovecot will let you play special tricks this way. Suppose that you want to find a mailbox called 'Barney' and you know it's somewhere in your mail hierarchy; then you can ask for 'LIST "*" "Barney"' and get just it. I suspect no actual IMAP clients attempt to do this.)

In our logs, we see recursively wildcarded IMAP LIST commands (ie, ones using the '*' wildcard operator) with a first argument that both includes and omits a trailing slash, that is we see clients generate both 'LIST "mail" "*"' and 'LIST "mail/" "*"'. For the recursive wildcard I think this gets you the same result, but there is a difference between them when you use '%':

a LIST "Imap-List-Test" "%"
* LIST (\Noselect \HasChildren) "/" Imap-List-Test
a OK List completed (0.001 + 0.000 secs).

a LIST "Imap-List-Test/" "%"
* LIST (\Noselect \HasChildren) "/" Imap-List-Test/One
a OK List completed (0.001 + 0.000 secs).

Given this, if I was writing an IMAP client program that used LIST and had a non-blank first argument, I would always put the trailing slash on (technically I think this is the folder separator, which doesn't have to be '/' but always is for us).

(I'm not going to write an actual mail reader, but I do sometimes need to write IMAP tests and similar automated things.)

PS: I'm sure that this is all familiar ground to IMAP mavens but we dip into this area only occasionally and I want to write this down for future use before it falls out of my head again.

(We're currently looking at IMAP client prefixes and how clients handle them for reasons well outside the scope of this entry.)

sysadmin/IMAPListAndClientPrefixes written at 23:53:36;


Page tools: See As Normal.
Search:
Login: Password:

This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.