Skip to content

IMAP configuration ​

Yarilo implements IMAP4rev2 (RFC 9051) with backward compatibility to IMAP4rev1 (RFC 3501).

Listeners: services.imaps (implicit TLS, port 993) and services.imap (STARTTLS, port 143). See Services configuration for listener-level settings (port, ssl_mode, haproxy_protocol, etc.).


protocol.imap ​

Protocol-level behaviour, shared across both IMAP listeners.

imap_idle_notify_interval ​

Default
120
Type
integer, seconds
Helm
protocol.imap.imap_idle_notify_interval

Interval between unsolicited EXISTS/RECENT responses during IDLE (RFC 2177 keepalive). 0 disables them.

imap_max_line_length ​

Default
65536
Type
integer, bytes
Helm
protocol.imap.imap_max_line_length

Maximum IMAP command line length. 0 is unlimited.

imap_id_send ​

Default
name *
Type
string
Helm
protocol.imap.imap_id_send

Space-separated key-value pairs sent in the ID response (RFC 2971). * means the server's own value. An empty string turns the ID extension off after login.

imap_id_retain ​

Default
false
Type
boolean
Helm
protocol.imap.imap_id_retain
Added
2.4.5

Keep what a client sends in ID before login and pass it to the auth service, where the policy server sees it as device_id. The login's own x- keys are left out; at most 30 pairs and 256 bytes are kept.

login_greeting ​

Default
none
Type
string
Helm
protocol.imap.login_greeting

Replaces IMAP server ready in the backend's greeting. Clients behind a login proxy see yarilo-imap-login's own greeting, Yarilo Login ready, which this key does not change. Empty keeps the default.

imap_logout_format ​

Default
none
Type
string
Helm
protocol.imap.imap_logout_format

Format of the line logged at session end; the variables are listed below. Empty logs no stats line.

imap_quota ​

Default
true
Type
boolean
Helm
protocol.imap.imap_quota

Advertise and serve the QUOTA extension (RFC 9208). Independent of quota enforcement.

imap_special_use_defaults ​

Default
Archive: \Archive, Drafts: \Drafts, Junk: \Junk, Sent: \Sent, Trash: \Trash
Type
map
Helm
protocol.imap.imap_special_use_defaults

Folder name (case-sensitive) to its RFC 6154 attribute, e.g. Sent: "\\Sent". A user's own CREATE (USE …) wins.

imap_client_workarounds ​

Default
[]
Type
list
Values
tb-extra-mailbox-sep tb-lsub-flags
Also accepted as
client_workarounds
Helm
protocol.imap.client_workarounds

Compatibility shims for clients that break the protocol.

imap_logout_format variables ​

VariableDescription
%{deleted}Number of messages marked \Deleted in the session.
%{expunged}Number of messages expunged (removed from disk).
%{fetch_hdr_count}Number of header fetch operations.
%{fetch_hdr_bytes}Bytes transferred for header fetches.
%{fetch_body_count}Number of body fetch operations.
%{fetch_body_bytes}Bytes transferred for body fetches.

Example:

yaml
protocol:
  imap:
    imap_logout_format: "in=%{fetch_hdr_bytes}+%{fetch_body_bytes} expunged=%{expunged}"

Recent messages ​

A message is \Recent to the first session that selects its folder after the message arrives (RFC 3501). That session sees it in * n RECENT, in FLAGS and in SEARCH RECENT, NEW and OLD. Every later session sees it as old.

  • SELECT takes the folder's recent messages. Mail that arrives while the folder is selected is recent to that session.
  • EXAMINE and STATUS (RECENT) report the recent messages and leave them for the next SELECT.
  • A virtual mailbox has recent messages of its own and is taken the same way. A folder its configuration names with + gives up its recent messages to that SELECT; see Virtual Mailboxes.
  • A client cannot set \Recent: STORE and APPEND with it are answered BAD.

IMAP4rev2 removed \Recent. After ENABLE IMAP4rev2 the session gets no RECENT response and no \Recent flag. Its SELECT still takes the recent messages, so a later IMAP4rev1 session sees them as old.

Each folder's index records which messages are no longer recent. An index written before this record existed reports every message as recent once, to the first SELECT.


Supported IMAP extensions ​

Feature coverage is the exhaustive list of what the server advertises. This table explains the ones that need it.

IMAP4rev2 also brings ENABLE, SASL-IR, LITERAL+, SEARCHRES and STATUS=SIZE; LIST-EXTENDED, LIST-STATUS, CREATE-SPECIAL-USE and SORT (RFC 5256, without SORT=DISPLAY) are advertised too.

ExtensionRFCNotes
IDLERFC 2177Server-push new-mail notifications.
MOVERFC 6851Atomic move (no COPY + STORE + EXPUNGE round-trip).
CONDSTORERFC 7162MODSEQ flag, conditional STORE.
QRESYNCRFC 7162Fast mailbox resync after reconnect.
UIDPLUSRFC 4315APPENDUID / COPYUID response codes.
UNSELECTRFC 3691Close mailbox without expunge.
NAMESPACERFC 2342Shared / Other Users namespaces.
QUOTARFC 9208Per-user storage quota. Advertised while imap_quota is on (the default).
ACLRFC 4314Per-mailbox access control lists. Advertised only with acl.enabled. A body FETCH sets \Seen only for a reader holding s; with r alone the body is served and the flag left as it is. SELECT answers [READ-ONLY] when the reader holds none of i, e, w, t, s.
BINARYRFC 3516Binary content transfer.
THREADRFC 5256Threading of the searched messages, both algorithms: THREAD=REFERENCES (ancestry from References / In-Reply-To, then joining by base subject) and THREAD=ORDEREDSUBJECT (base subject alone). Computed per command from message headers.
ESEARCHRFC 4731Extended SEARCH with MIN/MAX/COUNT.
NOTIFYRFC 5465Event-based notifications. NOTIFY SET/NONE parsed with all mailbox filters; the selected mailbox honours SELECTED / SELECTED-DELAYED (MessageNew / MessageExpunge / FlagChange), suppressing the unsolicited responses the client did not request (RFC 5465 §5). Non-selected mailbox filters (PERSONAL / INBOXES / SUBSCRIBED / SUBTREE / MAILBOXES) are watched via the pkg/locks event bus and their MessageNew / MessageExpunge / FlagChange activity is reported as untagged * STATUS (RFC 5465 §6), delivered during IDLE and before the next command's tagged response. The watched set is re-evaluated dynamically: mailboxes created, renamed or subscribed after NOTIFY SET join or leave the set live (via the per-user mlist: event key). Mailbox-level events - MailboxName (create / delete / rename, the last with OLDNAME) and SubscriptionChange (subscribe / unsubscribe) - are reported as untagged * LIST responses (RFC 5465 §5) when requested. AnnotationChange / metadata events are not yet reported.
SPECIAL-USERFC 6154\Sent, \Drafts, \Trash folder flags.
IDRFC 2971Server identity advertisement. Always offered before login; after login only while imap_id_send is non-empty.
OBJECTIDRFC 8474Stable object identifiers: MAILBOXID (SELECT/EXAMINE response code + STATUS item, from the folder GUID), EMAILID (FETCH, from the message GUID), THREADID (FETCH, the conversation a message belongs to; NIL for accounts whose threading data has not been built yet). IDs are 32 lowercase hex chars of the 128-bit GUID; they survive RENAME.
METADATARFC 5464Advertised only when a metadata dict is configured. Server and per-mailbox annotations (GETMETADATA / SETMETADATA). State lives in cfg.Dicts["metadata"] (pkg/dict). Keys: priv/box/<folder_guid>/<entry> and shared/box/<folder_guid>/<entry>; server-scope entries live under INBOX's GUID with a vendor/yarilo/pvt/server/ prefix so they cannot collide with INBOX mailbox attributes.