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