pub trait MailStore: Send + Sync {
// Required methods
fn list_mailboxes<'life0, 'life1, 'async_trait>(
&'life0 self,
user: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<Vec<Mailbox>, StoreError>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait;
fn mailbox_status<'life0, 'async_trait>(
&'life0 self,
mailbox_id: i64,
) -> Pin<Box<dyn Future<Output = Result<MailboxCounts, StoreError>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait;
fn list_messages<'life0, 'async_trait>(
&'life0 self,
mailbox_id: i64,
offset: u32,
limit: u32,
) -> Pin<Box<dyn Future<Output = Result<Vec<Message>, StoreError>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait;
fn get_message_by_db_id<'life0, 'life1, 'async_trait>(
&'life0 self,
user: &'life1 str,
id: i64,
) -> Pin<Box<dyn Future<Output = Result<Option<Message>, StoreError>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait;
fn list_thread_messages<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
user: &'life1 str,
thread_id: &'life2 str,
) -> Pin<Box<dyn Future<Output = Result<Vec<Message>, StoreError>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait;
fn update_flags<'life0, 'async_trait>(
&'life0 self,
mailbox_id: i64,
uid: u32,
flags: u32,
) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait;
fn add_flags<'life0, 'async_trait>(
&'life0 self,
mailbox_id: i64,
uid: u32,
flags: u32,
) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait;
fn read_message_raw<'life0, 'life1, 'async_trait>(
&'life0 self,
message: &'life1 Message,
) -> Pin<Box<dyn Future<Output = Option<Vec<u8>>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait;
fn parse_message(&self, raw: &[u8]) -> ParsedBody;
fn submit_message<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
user: &'life1 str,
message: &'life2 Message,
raw: &'life3 [u8],
) -> Pin<Box<dyn Future<Output = SubmissionResult> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait;
}Expand description
Storage operations every JMAP method handler in this crate needs.
One implementation per backing store (e.g. PostgreSQL + Maildir, IMAP proxy,
in-memory test fixture). Method handlers reach the store via
&dyn MailStore, so the trait is async, object-safe, and Send + Sync.
Identity conventions:
useris the authenticated owner’s full email address — handler code never invents one; auth resolution is the caller’s job.mailbox_id/ messageidare the store’s native primary keys; the dispatcher renders them on the wire asmb-{id}/msg-{id}.(mailbox_id, uid)is the IMAP-style addressing tuple used for the flag update methods.
Error contract: any returned StoreError is rendered into a JMAP
serverFail method error with its Display value as description. The
store is not expected to map errors itself.
Required Methods§
Sourcefn list_mailboxes<'life0, 'life1, 'async_trait>(
&'life0 self,
user: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<Vec<Mailbox>, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn list_mailboxes<'life0, 'life1, 'async_trait>(
&'life0 self,
user: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<Vec<Mailbox>, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
List all mailboxes for user. Used by Mailbox/get and Mailbox/query.
Sourcefn mailbox_status<'life0, 'async_trait>(
&'life0 self,
mailbox_id: i64,
) -> Pin<Box<dyn Future<Output = Result<MailboxCounts, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn mailbox_status<'life0, 'async_trait>(
&'life0 self,
mailbox_id: i64,
) -> Pin<Box<dyn Future<Output = Result<MailboxCounts, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Return (total, unread) for a mailbox. May be best-effort: handlers
fall back to (0, 0) on error.
Sourcefn list_messages<'life0, 'async_trait>(
&'life0 self,
mailbox_id: i64,
offset: u32,
limit: u32,
) -> Pin<Box<dyn Future<Output = Result<Vec<Message>, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn list_messages<'life0, 'async_trait>(
&'life0 self,
mailbox_id: i64,
offset: u32,
limit: u32,
) -> Pin<Box<dyn Future<Output = Result<Vec<Message>, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
List up to limit messages in mailbox_id starting at offset,
ordered however the store deems natural (typically by uid).
Sourcefn get_message_by_db_id<'life0, 'life1, 'async_trait>(
&'life0 self,
user: &'life1 str,
id: i64,
) -> Pin<Box<dyn Future<Output = Result<Option<Message>, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn get_message_by_db_id<'life0, 'life1, 'async_trait>(
&'life0 self,
user: &'life1 str,
id: i64,
) -> Pin<Box<dyn Future<Output = Result<Option<Message>, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Look up a message by its database/primary id. Returns Ok(None) when
the id exists but doesn’t belong to user, or when no such id exists.
Sourcefn list_thread_messages<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
user: &'life1 str,
thread_id: &'life2 str,
) -> Pin<Box<dyn Future<Output = Result<Vec<Message>, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn list_thread_messages<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
user: &'life1 str,
thread_id: &'life2 str,
) -> Pin<Box<dyn Future<Output = Result<Vec<Message>, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
All messages in thread_id for user, ordered chronologically.
Sourcefn update_flags<'life0, 'async_trait>(
&'life0 self,
mailbox_id: i64,
uid: u32,
flags: u32,
) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn update_flags<'life0, 'async_trait>(
&'life0 self,
mailbox_id: i64,
uid: u32,
flags: u32,
) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Replace a message’s flag bitmask. mailbox_id + uid identify the row.
Sourcefn add_flags<'life0, 'async_trait>(
&'life0 self,
mailbox_id: i64,
uid: u32,
flags: u32,
) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn add_flags<'life0, 'async_trait>(
&'life0 self,
mailbox_id: i64,
uid: u32,
flags: u32,
) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
OR flags into the message’s flag bitmask. Used to set \Deleted.
Sourcefn read_message_raw<'life0, 'life1, 'async_trait>(
&'life0 self,
message: &'life1 Message,
) -> Pin<Box<dyn Future<Output = Option<Vec<u8>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn read_message_raw<'life0, 'life1, 'async_trait>(
&'life0 self,
message: &'life1 Message,
) -> Pin<Box<dyn Future<Output = Option<Vec<u8>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Read the raw RFC 5322 bytes for a message. Returns None when not
available (e.g. blob missing on disk). Used to populate bodyValues,
textBody, htmlBody, and the submission path.
Sourcefn parse_message(&self, raw: &[u8]) -> ParsedBody
fn parse_message(&self, raw: &[u8]) -> ParsedBody
Parse raw bytes into text/html body plus attachment metadata. Pulled
out of Self::read_message_raw so the same bytes can serve both
Email/get rendering and EmailSubmission/set outbound delivery.
Sourcefn submit_message<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
user: &'life1 str,
message: &'life2 Message,
raw: &'life3 [u8],
) -> Pin<Box<dyn Future<Output = SubmissionResult> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
fn submit_message<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
user: &'life1 str,
message: &'life2 Message,
raw: &'life3 [u8],
) -> Pin<Box<dyn Future<Output = SubmissionResult> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
Submit a previously-stored email through the outbound queue.
The handler has already resolved the Message and read its raw bytes
via Self::read_message_raw; the store implementation is responsible
for queueing / signing / actually sending.
Dyn Compatibility§
This trait is dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".