Skip to main content

io_jmap/rfc8621/
mailbox.rs

1//! JMAP for Mail: Mailbox (RFC 8621 §2).
2
3use core::fmt;
4
5use alloc::string::{String, ToString};
6
7use serde::{Deserialize, Deserializer, Serialize, Serializer};
8
9pub mod changes;
10pub mod get;
11pub mod query;
12pub mod set;
13
14/// A JMAP Mailbox object (RFC 8621 §2.1): a named container for emails.
15#[derive(Clone, Debug, Default, Serialize, Deserialize)]
16#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
17#[serde(rename_all = "camelCase")]
18pub struct JmapMailbox {
19    /// The server-assigned mailbox id.
20    pub id: Option<String>,
21    /// The user-visible mailbox name.
22    pub name: Option<String>,
23    /// `None` for a top-level mailbox.
24    pub parent_id: Option<String>,
25    /// The special-use role of the mailbox, when any.
26    #[cfg_attr(feature = "schemars", schemars(with = "Option<String>"))]
27    pub role: Option<JmapMailboxRole>,
28    /// Position hint for display ordering (lower first).
29    #[serde(default)]
30    pub sort_order: u32,
31    /// The number of emails in the mailbox.
32    #[serde(default)]
33    pub total_emails: u32,
34    /// The number of unread emails in the mailbox.
35    #[serde(default)]
36    pub unread_emails: u32,
37    /// The number of threads with at least one email in the mailbox.
38    #[serde(default)]
39    pub total_threads: u32,
40    /// The number of threads with at least one unread email in the mailbox.
41    #[serde(default)]
42    pub unread_threads: u32,
43    /// The user's rights on the mailbox.
44    #[serde(default)]
45    pub my_rights: JmapMailboxRights,
46    /// Whether the user is subscribed to the mailbox.
47    #[serde(default)]
48    pub is_subscribed: bool,
49}
50
51/// Access rights on a mailbox (RFC 8621 §2.1).
52#[derive(Clone, Debug, Default, Serialize, Deserialize)]
53#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
54#[serde(rename_all = "camelCase")]
55pub struct JmapMailboxRights {
56    /// May read items in the mailbox.
57    pub may_read_items: bool,
58    /// May add items to the mailbox.
59    pub may_add_items: bool,
60    /// May remove items from the mailbox.
61    pub may_remove_items: bool,
62    /// May set/unset the `$seen` keyword on items.
63    pub may_set_seen: bool,
64    /// May set/unset any keyword other than `$seen`.
65    pub may_set_keywords: bool,
66    /// May create child mailboxes.
67    pub may_create_child: bool,
68    /// May rename this mailbox.
69    pub may_rename: bool,
70    /// May delete this mailbox.
71    pub may_delete: bool,
72    /// May submit email from this mailbox.
73    pub may_submit: bool,
74}
75
76/// Mailbox role per the IANA JMAP Mailbox Roles registry (RFC 8621 §2.1).
77/// Any unknown or server-defined role is held by [`JmapMailboxRole::Other`].
78#[derive(Clone, Debug, PartialEq, Eq)]
79pub enum JmapMailboxRole {
80    /// Primary inbox.
81    Inbox,
82    /// Archived messages.
83    Archive,
84    /// Draft messages.
85    Drafts,
86    /// Flagged / starred messages.
87    Flagged,
88    /// Messages marked as important.
89    Important,
90    /// Spam / junk messages.
91    Junk,
92    /// Sent messages.
93    Sent,
94    /// Virtual mailbox of all subscribed mailboxes.
95    Subscribed,
96    /// Deleted messages.
97    Trash,
98    /// A server-defined or unrecognised role.
99    Other(String),
100}
101
102impl fmt::Display for JmapMailboxRole {
103    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
104        f.write_str(match self {
105            Self::Inbox => "inbox",
106            Self::Archive => "archive",
107            Self::Drafts => "drafts",
108            Self::Flagged => "flagged",
109            Self::Important => "important",
110            Self::Junk => "junk",
111            Self::Sent => "sent",
112            Self::Subscribed => "subscribed",
113            Self::Trash => "trash",
114            Self::Other(s) => s.as_str(),
115        })
116    }
117}
118
119impl Serialize for JmapMailboxRole {
120    fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
121        s.serialize_str(&self.to_string())
122    }
123}
124
125impl<'de> Deserialize<'de> for JmapMailboxRole {
126    fn deserialize<D: Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
127        let s = String::deserialize(d)?;
128        Ok(match s.as_str() {
129            "inbox" => Self::Inbox,
130            "archive" => Self::Archive,
131            "drafts" => Self::Drafts,
132            "flagged" => Self::Flagged,
133            "important" => Self::Important,
134            "junk" => Self::Junk,
135            "sent" => Self::Sent,
136            "subscribed" => Self::Subscribed,
137            "trash" => Self::Trash,
138            _ => Self::Other(s),
139        })
140    }
141}
142
143/// [`JmapMailbox`] properties requestable in `Mailbox/get` (RFC 8621 §2.1).
144#[derive(Clone, Debug, Serialize)]
145#[serde(rename_all = "camelCase")]
146pub enum JmapMailboxProperty {
147    /// The `id` property.
148    Id,
149    /// The `name` property.
150    Name,
151    /// The `parentId` property.
152    ParentId,
153    /// The `role` property.
154    Role,
155    /// The `sortOrder` property.
156    SortOrder,
157    /// The `totalEmails` property.
158    TotalEmails,
159    /// The `unreadEmails` property.
160    UnreadEmails,
161    /// The `totalThreads` property.
162    TotalThreads,
163    /// The `unreadThreads` property.
164    UnreadThreads,
165    /// The `myRights` property.
166    MyRights,
167    /// The `isSubscribed` property.
168    IsSubscribed,
169}