async_imap/types/mod.rs
1//! This module contains types used throughout the IMAP protocol.
2
3use std::borrow::Cow;
4
5/// From section [2.3.1.1 of RFC 3501](https://tools.ietf.org/html/rfc3501#section-2.3.1.1).
6///
7/// A 32-bit value assigned to each message, which when used with the unique identifier validity
8/// value (see below) forms a 64-bit value that will not refer to any other message in the mailbox
9/// or any subsequent mailbox with the same name forever. Unique identifiers are assigned in a
10/// strictly ascending fashion in the mailbox; as each message is added to the mailbox it is
11/// assigned a higher UID than the message(s) which were added previously. Unlike message sequence
12/// numbers, unique identifiers are not necessarily contiguous.
13///
14/// The unique identifier of a message will not change during the session, and will generally not
15/// change between sessions. Any change of unique identifiers between sessions will be detectable
16/// using the `UIDVALIDITY` mechanism discussed below. Persistent unique identifiers are required
17/// for a client to resynchronize its state from a previous session with the server (e.g.,
18/// disconnected or offline access clients); this is discussed further in
19/// [`IMAP-DISC`](https://tools.ietf.org/html/rfc3501#ref-IMAP-DISC).
20///
21/// Associated with every mailbox are two values which aid in unique identifier handling: the next
22/// unique identifier value and the unique identifier validity value.
23///
24/// The next unique identifier value is the predicted value that will be assigned to a new message
25/// in the mailbox. Unless the unique identifier validity also changes (see below), the next
26/// unique identifier value will have the following two characteristics. First, the next unique
27/// identifier value will not change unless new messages are added to the mailbox; and second, the
28/// next unique identifier value will change whenever new messages are added to the mailbox, even
29/// if those new messages are subsequently expunged.
30///
31/// > Note: The next unique identifier value is intended to provide a means for a client to
32/// > determine whether any messages have been delivered to the mailbox since the previous time it
33/// > checked this value. It is not intended to provide any guarantee that any message will have
34/// > this unique identifier. A client can only assume, at the time that it obtains the next
35/// > unique identifier value, that messages arriving after that time will have a UID greater than
36/// > or equal to that value.
37///
38/// The unique identifier validity value is sent in a `UIDVALIDITY` response code in an `OK`
39/// untagged response at mailbox selection time. If unique identifiers from an earlier session fail
40/// to persist in this session, the unique identifier validity value will be greater than the one
41/// used in the earlier session.
42///
43/// > Note: Ideally, unique identifiers will persist at all
44/// > times. Although this specification recognizes that failure
45/// > to persist can be unavoidable in certain server
46/// > environments, it STRONGLY ENCOURAGES message store
47/// > implementation techniques that avoid this problem. For
48/// > example:
49/// >
50/// > 1. Unique identifiers are strictly ascending in the
51/// > mailbox at all times. If the physical message store is
52/// > re-ordered by a non-IMAP agent, this requires that the
53/// > unique identifiers in the mailbox be regenerated, since
54/// > the former unique identifiers are no longer strictly
55/// > ascending as a result of the re-ordering.
56/// > 2. If the message store has no mechanism to store unique
57/// > identifiers, it must regenerate unique identifiers at
58/// > each session, and each session must have a unique
59/// > `UIDVALIDITY` value.
60/// > 3. If the mailbox is deleted and a new mailbox with the
61/// > same name is created at a later date, the server must
62/// > either keep track of unique identifiers from the
63/// > previous instance of the mailbox, or it must assign a
64/// > new `UIDVALIDITY` value to the new instance of the
65/// > mailbox. A good `UIDVALIDITY` value to use in this case
66/// > is a 32-bit representation of the creation date/time of
67/// > the mailbox. It is alright to use a constant such as
68/// > 1, but only if it guaranteed that unique identifiers
69/// > will never be reused, even in the case of a mailbox
70/// > being deleted (or renamed) and a new mailbox by the
71/// > same name created at some future time.
72/// > 4. The combination of mailbox name, `UIDVALIDITY`, and `UID`
73/// > must refer to a single immutable message on that server
74/// > forever. In particular, the internal date, [RFC 2822](https://tools.ietf.org/html/rfc2822)
75/// > size, envelope, body structure, and message texts
76/// > (RFC822, RFC822.HEADER, RFC822.TEXT, and all BODY[...]
77/// > fetch data items) must never change. This does not
78/// > include message numbers, nor does it include attributes
79/// > that can be set by a `STORE` command (e.g., `FLAGS`).
80pub type Uid = u32;
81
82/// From section [2.3.1.2 of RFC 3501](https://tools.ietf.org/html/rfc3501#section-2.3.1.2).
83///
84/// A relative position from 1 to the number of messages in the mailbox.
85/// This position is ordered by ascending unique identifier. As
86/// each new message is added, it is assigned a message sequence number
87/// that is 1 higher than the number of messages in the mailbox before
88/// that new message was added.
89///
90/// Message sequence numbers can be reassigned during the session. For
91/// example, when a message is permanently removed (expunged) from the
92/// mailbox, the message sequence number for all subsequent messages is
93/// decremented. The number of messages in the mailbox is also
94/// decremented. Similarly, a new message can be assigned a message
95/// sequence number that was once held by some other message prior to an
96/// expunge.
97///
98/// In addition to accessing messages by relative position in the
99/// mailbox, message sequence numbers can be used in mathematical
100/// calculations. For example, if an untagged "11 EXISTS" is received,
101/// and previously an untagged "8 EXISTS" was received, three new
102/// messages have arrived with message sequence numbers of 9, 10, and 11.
103/// Another example, if message 287 in a 523 message mailbox has UID
104/// 12345, there are exactly 286 messages which have lesser UIDs and 236
105/// messages which have greater UIDs.
106pub type Seq = u32;
107
108/// Message flags.
109///
110/// With the exception of [`Flag::Custom`], these flags are system flags that are pre-defined in
111/// [RFC 3501 section 2.3.2](https://tools.ietf.org/html/rfc3501#section-2.3.2). All system flags
112/// begin with `\` in the IMAP protocol. Certain system flags (`\Deleted` and `\Seen`) have
113/// special semantics described elsewhere.
114///
115/// A flag can be permanent or session-only on a per-flag basis. Permanent flags are those which
116/// the client can add or remove from the message flags permanently; that is, concurrent and
117/// subsequent sessions will see any change in permanent flags. Changes to session flags are valid
118/// only in that session.
119///
120/// > Note: The `\Recent` system flag is a special case of a session flag. `\Recent` can not be
121/// > used as an argument in a `STORE` or `APPEND` command, and thus can not be changed at all.
122#[derive(Clone, Debug, Hash, PartialEq, Eq)]
123pub enum Flag<'a> {
124 /// Message has been read
125 Seen,
126
127 /// Message has been answered
128 Answered,
129
130 /// Message is "flagged" for urgent/special attention
131 Flagged,
132
133 /// Message is "deleted" for removal by later EXPUNGE
134 Deleted,
135
136 /// Message has not completed composition (marked as a draft).
137 Draft,
138
139 /// Message is "recently" arrived in this mailbox. This session is the first session to have
140 /// been notified about this message; if the session is read-write, subsequent sessions will
141 /// not see `\Recent` set for this message. This flag can not be altered by the client.
142 ///
143 /// If it is not possible to determine whether or not this session is the first session to be
144 /// notified about a message, then that message will generally be considered recent.
145 ///
146 /// If multiple connections have the same mailbox selected simultaneously, it is undefined
147 /// which of these connections will see newly-arrived messages with `\Recent` set and which
148 /// will see it without `\Recent` set.
149 Recent,
150
151 /// The [`Mailbox::permanent_flags`] can include this special flag (`\*`), which indicates that
152 /// it is possible to create new keywords by attempting to store those flags in the mailbox.
153 MayCreate,
154
155 /// A non-standard user- or server-defined flag.
156 Custom(Cow<'a, str>),
157}
158
159impl Flag<'static> {
160 fn system(s: &str) -> Option<Self> {
161 match s {
162 "\\Seen" => Some(Flag::Seen),
163 "\\Answered" => Some(Flag::Answered),
164 "\\Flagged" => Some(Flag::Flagged),
165 "\\Deleted" => Some(Flag::Deleted),
166 "\\Draft" => Some(Flag::Draft),
167 "\\Recent" => Some(Flag::Recent),
168 "\\*" => Some(Flag::MayCreate),
169 _ => None,
170 }
171 }
172}
173
174impl From<String> for Flag<'_> {
175 fn from(s: String) -> Self {
176 if let Some(f) = Flag::system(&s) {
177 f
178 } else {
179 Flag::Custom(Cow::Owned(s))
180 }
181 }
182}
183
184impl<'a> From<&'a str> for Flag<'a> {
185 fn from(s: &'a str) -> Self {
186 if let Some(f) = Flag::system(s) {
187 f
188 } else {
189 Flag::Custom(Cow::Borrowed(s))
190 }
191 }
192}
193
194mod mailbox;
195pub use self::mailbox::Mailbox;
196
197mod fetch;
198pub use self::fetch::Fetch;
199
200mod name;
201pub use self::name::{Name, NameAttribute};
202
203mod capabilities;
204pub use self::capabilities::{Capabilities, Capability};
205
206/// re-exported from imap_proto;
207pub use imap_proto::StatusAttribute;
208
209mod id_generator;
210pub(crate) use self::id_generator::IdGenerator;
211
212mod response_data;
213pub(crate) use self::response_data::ResponseData;
214
215mod request;
216pub(crate) use self::request::Request;
217
218mod quota;
219pub use self::quota::*;
220
221/// Responses that the server sends that are not related to the current command.
222///
223/// [RFC 3501](https://tools.ietf.org/html/rfc3501#section-7) states that clients need to be able
224/// to accept any response at any time. These are the ones we've encountered in the wild.
225///
226/// Note that `Recent`, `Exists` and `Expunge` responses refer to the currently `SELECT`ed folder,
227/// so the user must take care when interpreting these.
228#[derive(Debug, PartialEq, Eq)]
229pub enum UnsolicitedResponse {
230 /// An unsolicited [`STATUS response`](https://tools.ietf.org/html/rfc3501#section-7.2.4).
231 Status {
232 /// The mailbox that this status response is for.
233 mailbox: String,
234 /// The attributes of this mailbox.
235 attributes: Vec<StatusAttribute>,
236 },
237
238 /// An unsolicited [`RECENT` response](https://tools.ietf.org/html/rfc3501#section-7.3.2)
239 /// indicating the number of messages with the `\Recent` flag set. This response occurs if the
240 /// size of the mailbox changes (e.g., new messages arrive).
241 ///
242 /// > Note: It is not guaranteed that the message sequence
243 /// > numbers of recent messages will be a contiguous range of
244 /// > the highest n messages in the mailbox (where n is the
245 /// > value reported by the `RECENT` response). Examples of
246 /// > situations in which this is not the case are: multiple
247 /// > clients having the same mailbox open (the first session
248 /// > to be notified will see it as recent, others will
249 /// > probably see it as non-recent), and when the mailbox is
250 /// > re-ordered by a non-IMAP agent.
251 /// >
252 /// > The only reliable way to identify recent messages is to
253 /// > look at message flags to see which have the `\Recent` flag
254 /// > set, or to do a `SEARCH RECENT`.
255 Recent(u32),
256
257 /// An unsolicited [`EXISTS` response](https://tools.ietf.org/html/rfc3501#section-7.3.1) that
258 /// reports the number of messages in the mailbox. This response occurs if the size of the
259 /// mailbox changes (e.g., new messages arrive).
260 Exists(u32),
261
262 /// An unsolicited [`EXPUNGE` response](https://tools.ietf.org/html/rfc3501#section-7.4.1) that
263 /// reports that the specified message sequence number has been permanently removed from the
264 /// mailbox. The message sequence number for each successive message in the mailbox is
265 /// immediately decremented by 1, and this decrement is reflected in message sequence numbers
266 /// in subsequent responses (including other untagged `EXPUNGE` responses).
267 ///
268 /// The EXPUNGE response also decrements the number of messages in the mailbox; it is not
269 /// necessary to send an `EXISTS` response with the new value.
270 ///
271 /// As a result of the immediate decrement rule, message sequence numbers that appear in a set
272 /// of successive `EXPUNGE` responses depend upon whether the messages are removed starting
273 /// from lower numbers to higher numbers, or from higher numbers to lower numbers. For
274 /// example, if the last 5 messages in a 9-message mailbox are expunged, a "lower to higher"
275 /// server will send five untagged `EXPUNGE` responses for message sequence number 5, whereas a
276 /// "higher to lower server" will send successive untagged `EXPUNGE` responses for message
277 /// sequence numbers 9, 8, 7, 6, and 5.
278 // TODO: the spec doesn't seem to say anything about when these may be received as unsolicited?
279 Expunge(u32),
280 /// Any other kind of unsolicted response.
281 Other(ResponseData),
282}