daaki_imap/types/notify.rs
1//! IMAP NOTIFY extension types (RFC 5465).
2//!
3//! RFC 5465 allows clients to request notifications for mailbox and message
4//! events without polling or blocking on IDLE. Event types are defined by
5//! RFC 5423 (Internet Message Store Events).
6//!
7//! All types are fully owned — no lifetime parameters.
8
9/// A mailbox filter that determines which mailboxes an event group applies to
10/// (RFC 5465 Section 6).
11///
12/// RFC 5465 Section 8 ABNF:
13/// ```text
14/// filter-mailboxes = filter-mailboxes-selected / filter-mailboxes-other
15/// filter-mailboxes-selected = "selected" / "selected-delayed"
16/// filter-mailboxes-other = "inboxes" / "personal" / "subscribed" /
17/// ("subtree" SP one-or-more-mailbox) /
18/// ("mailboxes" SP one-or-more-mailbox)
19/// ```
20#[non_exhaustive]
21#[derive(Debug, Clone, PartialEq, Eq, Hash)]
22#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
23pub enum MailboxFilter {
24 /// `selected` — the currently selected mailbox; notifications delivered
25 /// immediately, including expunges (RFC 5465 Section 6.1).
26 ///
27 /// Only message events are valid with this filter. When `MessageExpunge`
28 /// is active, MSN values can change at any time so the client MUST use
29 /// UID-based commands.
30 Selected,
31
32 /// `selected-delayed` — the currently selected mailbox with delayed
33 /// `MessageExpunge` delivery (RFC 5465 Section 6.2).
34 ///
35 /// Only message events are valid with this filter. Expunge notifications
36 /// are delayed until the client issues a command that permits returning
37 /// expunge information (e.g. NOOP, IDLE).
38 SelectedDelayed,
39
40 /// `inboxes` — all selectable mailboxes where the MDA may deliver messages
41 /// (RFC 5465 Section 6.3).
42 ///
43 /// If the server cannot compute this set, it MAY treat `inboxes` as
44 /// equivalent to `personal`.
45 Inboxes,
46
47 /// `personal` — all selectable mailboxes in the user's personal
48 /// namespace(s) per RFC 2342 (RFC 5465 Section 6.4).
49 Personal,
50
51 /// `subscribed` — all mailboxes the user has subscribed to
52 /// (RFC 5465 Section 6.5).
53 ///
54 /// The server re-evaluates this set dynamically when subscriptions change.
55 Subscribed,
56
57 /// `subtree <mailbox> ...` — the specified mailbox plus all selectable
58 /// subordinate mailboxes (RFC 5465 Section 6.6).
59 ///
60 /// Must contain at least one mailbox name per ABNF
61 /// `one-or-more-mailbox` (RFC 5465 Section 8).
62 Subtree(Vec<String>),
63
64 /// `mailboxes <mailbox> ...` — one or more explicitly named mailboxes,
65 /// no wildcard expansion (RFC 5465 Section 6.7).
66 ///
67 /// Must contain at least one mailbox name per ABNF
68 /// `one-or-more-mailbox` (RFC 5465 Section 8).
69 Mailboxes(Vec<String>),
70}
71
72/// An event type that can be requested in a NOTIFY command
73/// (RFC 5465 Section 5, RFC 5423 Section 4).
74///
75/// RFC 5465 Section 8 ABNF:
76/// ```text
77/// event = message-event / mailbox-event / user-event / event-ext
78/// message-event = ("MessageNew" [SP "(" fetch-att *(SP fetch-att) ")"])
79/// / "MessageExpunge" / "FlagChange" / "AnnotationChange"
80/// mailbox-event = "MailboxName" / "SubscriptionChange" / "MailboxMetadataChange"
81/// user-event = "ServerMetadataChange"
82/// ```
83#[non_exhaustive]
84#[derive(Debug, Clone, PartialEq, Eq, Hash)]
85#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
86pub enum NotifyEvent {
87 // --- Message events (RFC 5465 Sections 5.1–5.3, RFC 5423 Section 4.1–4.2) ---
88 /// `MessageNew` — new message delivered or appended
89 /// (RFC 5465 Section 5.2, RFC 5423 Section 4.1).
90 ///
91 /// For the selected mailbox: server sends EXISTS then FETCH with the
92 /// requested attributes. For other mailboxes: server sends STATUS with
93 /// UIDNEXT and MESSAGES.
94 ///
95 /// The optional fetch attributes are only valid with `selected` or
96 /// `selected-delayed` mailbox filters (RFC 5465 Section 5.2).
97 MessageNew {
98 /// Optional FETCH attributes to include with new-message notifications
99 /// (RFC 5465 Section 5.2). Only valid for `selected`/`selected-delayed`.
100 /// Each string is a raw FETCH attribute (e.g. `"UID"`, `"FLAGS"`,
101 /// `"BODY.PEEK[HEADER.FIELDS (From To Subject)]"`).
102 fetch_attrs: Vec<String>,
103 },
104
105 /// `MessageExpunge` — message expunged or expired
106 /// (RFC 5465 Section 5.3, RFC 5423 Section 4.1).
107 ///
108 /// MUST always be specified together with `MessageNew` (RFC 5465 Section 5.2).
109 MessageExpunge,
110
111 /// `FlagChange` — message flags changed
112 /// (RFC 5465 Section 5.1, RFC 5423 Section 4.2).
113 ///
114 /// Requires both `MessageNew` and `MessageExpunge` to also be specified
115 /// (RFC 5465 Section 5.1).
116 FlagChange,
117
118 /// `AnnotationChange` — per-message annotation changed
119 /// (RFC 5465 Section 5.1).
120 ///
121 /// Requires both `MessageNew` and `MessageExpunge` to also be specified
122 /// (RFC 5465 Section 5.1).
123 AnnotationChange,
124
125 // --- Mailbox events (RFC 5465 Sections 5.4–5.6, RFC 5423 Section 4.4) ---
126 /// `MailboxName` — mailbox created, deleted, or renamed
127 /// (RFC 5465 Section 5.4, RFC 5423 Section 4.4).
128 ///
129 /// Server sends unsolicited LIST responses. On rename, the LIST includes
130 /// an `OLDNAME` extended data item.
131 MailboxName,
132
133 /// `SubscriptionChange` — mailbox subscribed or unsubscribed
134 /// (RFC 5465 Section 5.5, RFC 5423 Section 4.4).
135 ///
136 /// Server sends unsolicited LIST response with accurate `\Subscribed`
137 /// attribute presence.
138 SubscriptionChange,
139
140 /// `MailboxMetadataChange` — per-mailbox metadata annotation changed
141 /// (RFC 5465 Section 5.6).
142 ///
143 /// Server sends unsolicited METADATA response per RFC 5464 Section 4.4.2.
144 /// Optional unless the server implements METADATA (RFC 5464).
145 MailboxMetadataChange,
146
147 // --- User events (RFC 5465 Section 5.7) ---
148 /// `ServerMetadataChange` — server-level metadata annotation changed
149 /// (RFC 5465 Section 5.7).
150 ///
151 /// Server sends unsolicited METADATA response with empty mailbox name.
152 /// Optional unless the server implements METADATA or METADATA-SERVER.
153 ServerMetadataChange,
154
155 // --- Extension events (RFC 5465 Section 8) ---
156 /// Unrecognized event type — preserved verbatim for forward compatibility
157 /// (RFC 5465 Section 8: `event-ext = atom`).
158 Other(String),
159}
160
161/// A group of events to monitor on a set of mailboxes
162/// (RFC 5465 Section 8).
163///
164/// RFC 5465 Section 8 ABNF:
165/// ```text
166/// event-group = "(" filter-mailboxes SP events ")"
167/// events = ("(" event *(SP event) ")") / "NONE"
168/// ```
169#[non_exhaustive]
170#[derive(Debug, Clone, PartialEq, Eq, Hash)]
171#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
172pub struct NotifyEventGroup {
173 /// Which mailboxes this event group applies to (RFC 5465 Section 6).
174 pub filter: MailboxFilter,
175
176 /// Events to monitor. An empty Vec means `NONE` — no events for this
177 /// filter (RFC 5465 Section 8).
178 pub events: Vec<NotifyEvent>,
179}
180
181impl NotifyEventGroup {
182 /// Create a new event group for the given mailbox filter and events
183 /// (RFC 5465 Section 8).
184 pub fn new(filter: MailboxFilter, events: Vec<NotifyEvent>) -> Self {
185 Self { filter, events }
186 }
187}
188
189/// Parameters for the `NOTIFY SET` command (RFC 5465 Section 3).
190///
191/// RFC 5465 Section 8 ABNF:
192/// ```text
193/// notify = "NOTIFY" SP (notify-set / notify-none)
194/// notify-set = "SET" [status-indicator] SP event-groups
195/// ```
196#[non_exhaustive]
197#[derive(Debug, Clone, PartialEq, Eq, Hash)]
198#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
199pub struct NotifySetParams {
200 /// When `true`, the server sends an initial STATUS response for each
201 /// non-selected mailbox with message events before the tagged OK
202 /// (RFC 5465 Section 4, `status-indicator = SP "STATUS"`).
203 pub status: bool,
204
205 /// One or more event groups defining which events to monitor on which
206 /// mailboxes (RFC 5465 Section 3).
207 pub event_groups: Vec<NotifyEventGroup>,
208}
209
210impl NotifySetParams {
211 /// Create NOTIFY SET parameters with the given event groups
212 /// (RFC 5465 Section 3).
213 ///
214 /// `status` controls whether the server sends initial STATUS responses
215 /// for non-selected mailboxes before the tagged OK (RFC 5465 Section 4).
216 pub fn new(event_groups: Vec<NotifyEventGroup>, status: bool) -> Self {
217 Self {
218 status,
219 event_groups,
220 }
221 }
222}