Skip to main content

mailrs_jmap/
types.rs

1//! Minimal JMAP-facing data types.
2//!
3//! These are intentionally decoupled from any backing store (Maildir, IMAP, S3,
4//! whatever). A `MailStore` implementation is responsible for mapping its own
5//! representation into these shapes.
6//!
7//! ## Flag bitmask
8//!
9//! The `FLAG_*` constants mirror the wire-level numbering already used by
10//! mailrs-mailbox, so a server that wraps mailrs-mailbox can pass flags
11//! through without translation.
12
13use serde::{Deserialize, Serialize};
14
15/// Mailbox metadata as needed by JMAP's `Mailbox/get` and `Mailbox/query`.
16///
17/// `id` is the store's native primary key. The dispatcher renders it to the
18/// JMAP-visible id `mb-{id}`.
19#[derive(Debug, Clone, Serialize, Deserialize)]
20pub struct Mailbox {
21    /// Store-native primary key. Rendered on the wire as `mb-{id}`.
22    pub id: i64,
23    /// Human-visible mailbox name (e.g. `INBOX`, `Sent`, `Drafts`).
24    pub name: String,
25}
26
27/// Per-mailbox counts returned by [`crate::store::MailStore::mailbox_status`].
28#[derive(Debug, Clone, Copy, Default)]
29pub struct MailboxCounts {
30    /// Total number of messages in the mailbox.
31    pub total: u32,
32    /// Number of messages without the `\Seen` flag.
33    pub unread: u32,
34}
35
36/// A single message as JMAP needs to see it for `Email/get`, `Email/query`,
37/// `Email/set`, `Thread/get`, and `EmailSubmission/set`.
38///
39/// JMAP-visible email id is `msg-{id}`.
40#[derive(Debug, Clone)]
41pub struct Message {
42    /// Store-native primary key. Rendered on the wire as `msg-{id}`.
43    pub id: i64,
44    /// FK into the message's containing mailbox.
45    pub mailbox_id: i64,
46    /// IMAP-style UID within `mailbox_id`. Combined with `mailbox_id` it
47    /// uniquely identifies the row for flag updates.
48    pub uid: u32,
49    /// Raw `From:` header value, may include a display name (e.g.
50    /// `"Alice" <alice@example.com>`).
51    pub sender: String,
52    /// Raw `To:` header value. Comma-separated address list.
53    pub recipients: String,
54    /// Decoded `Subject:` header.
55    pub subject: String,
56    /// `Date:` header epoch seconds.
57    pub date: i64,
58    /// Message size in bytes.
59    pub size: u32,
60    /// Flag bitmask. See the `FLAG_*` constants in this module.
61    pub flags: u32,
62    /// Internal delivery time epoch seconds.
63    pub internal_date: i64,
64    /// `Message-ID:` header value, without the angle brackets.
65    pub message_id: String,
66    /// `In-Reply-To:` header value, without angle brackets, or empty when
67    /// the message is not a reply.
68    pub in_reply_to: String,
69    /// Store-defined thread identifier, stable across all messages in the same
70    /// conversation.
71    pub thread_id: String,
72    /// Owner's full address (used to read the raw bytes from a store).
73    pub user_address: String,
74    /// Optional pre-extracted plain-text snippet, used for `preview`.
75    pub new_content: Option<String>,
76    /// Implementation-defined opaque id used by [`crate::store::MailStore::read_message_raw`]
77    /// to locate the on-disk / blob copy of the message.
78    pub blob_id: String,
79}
80
81/// Parsed message body parts as returned by [`crate::store::MailStore::parse_message`].
82#[derive(Debug, Clone, Default)]
83pub struct ParsedBody {
84    /// Decoded `text/plain` body, if any.
85    pub text: Option<String>,
86    /// Decoded `text/html` body, if any.
87    pub html: Option<String>,
88    /// Attachment metadata (no body bytes — see [`Attachment`]).
89    pub attachments: Vec<Attachment>,
90}
91
92/// Attachment metadata exposed via JMAP's `Email/get` `attachments` property.
93///
94/// Body bytes are **not** included; if a client needs them it has to use a
95/// separate blob/download endpoint (out of scope for this crate).
96#[derive(Debug, Clone)]
97pub struct Attachment {
98    /// Suggested filename from the `Content-Disposition` header.
99    pub filename: String,
100    /// MIME type from the `Content-Type` header.
101    pub content_type: String,
102    /// Size in bytes of the (decoded) attachment payload.
103    pub size: u32,
104}
105
106/// Result of submitting a previously-stored email through the outbound queue.
107#[derive(Debug, Clone)]
108pub struct SubmissionResult {
109    /// `true` when the message was successfully queued for delivery.
110    pub success: bool,
111    /// Optional human-readable explanation. On failure this typically carries
112    /// the reason; on success it's `None`.
113    pub message: Option<String>,
114}
115
116/// IMAP `\Seen` flag — message has been viewed.
117pub const FLAG_SEEN: u32 = 0b0000_0001;
118/// IMAP `\Answered` flag — a reply has been sent.
119pub const FLAG_ANSWERED: u32 = 0b0000_0010;
120/// IMAP `\Flagged` flag — user-marked for follow-up.
121pub const FLAG_FLAGGED: u32 = 0b0000_0100;
122/// IMAP `\Deleted` flag — marked for purge on EXPUNGE.
123pub const FLAG_DELETED: u32 = 0b0000_1000;
124/// IMAP `\Draft` flag — composed but not yet sent.
125pub const FLAG_DRAFT: u32 = 0b0001_0000;