rusmes_jmap/lib.rs
1//! JMAP protocol implementation for RusMES
2//!
3//! This crate implements the JSON Meta Application Protocol (JMAP) for the RusMES mail
4//! server, providing an HTTP/JSON API for email access as defined in:
5//!
6//! - **RFC 8620** — The JSON Meta Application Protocol (core protocol)
7//! - **RFC 8621** — Using JMAP for Email (Email, Mailbox, Thread, EmailSubmission,
8//! VacationResponse, SearchSnippet, Identity)
9//!
10//! # Module Overview
11//!
12//! | Module | Contents |
13//! |--------|----------|
14//! [`api`] | Axum-based HTTP server (`JmapServer`), request dispatch, auth middleware |
15//! [`blob`] | Blob upload (`POST /upload/:account`) and download (`GET /download/…`) endpoints |
16//! [`eventsource`] | Server-Sent Events push channel (`GET /eventsource`) for state-change notifications |
17//! [`session`] | JMAP Session resource (`GET /.well-known/jmap`), capability advertisement |
18//! [`types`] | Shared JSON types: `Email`, `JmapRequest`, `JmapResponse`, `JmapError`, etc. |
19//! [`methods`] | Method handlers for all JMAP objects (see sub-modules below) |
20//!
21//! ## Method Handlers
22//!
23//! | Sub-module | RFC | Methods |
24//! |-----------|-----|---------|
25//! `methods::mailbox` | RFC 8621 §2 | `Mailbox/get`, `Mailbox/set`, `Mailbox/query`, `Mailbox/changes`, `Mailbox/queryChanges` |
26//! `methods::email` | RFC 8621 §4 | `Email/get`, `Email/set`, `Email/query` |
27//! `methods::email_advanced` | RFC 8621 §4 | `Email/changes`, `Email/queryChanges`, `Email/copy`, `Email/import`, `Email/parse` |
28//! `methods::thread` | RFC 8621 §3 | `Thread/get`, `Thread/changes` |
29//! `methods::submission` | RFC 8621 §7 | `EmailSubmission/get`, `EmailSubmission/set`, `EmailSubmission/query`, `EmailSubmission/changes` |
30//! `methods::identity` | RFC 8621 §5 | `Identity/get`, `Identity/set`, `Identity/changes` |
31//! `methods::vacation` | RFC 8621 §8 | `VacationResponse/get`, `VacationResponse/set` |
32//! `methods::search_snippet` | RFC 8621 §9 | `SearchSnippet/get` |
33//!
34//! # Example — Starting the JMAP server
35//!
36//! ```rust,no_run
37//! use rusmes_jmap::JmapServer;
38//! use axum::Router;
39//!
40//! // Obtain the JMAP routes and nest them inside an Axum application.
41//! let app: Router = JmapServer::routes();
42//! // e.g. axum::serve(listener, app).await.unwrap();
43//! ```
44//!
45//! # EventSource Push
46//!
47//! The [`eventsource::EventSourceManager`] can be used to broadcast state-change
48//! notifications to JMAP clients that maintain a long-lived SSE connection:
49//!
50//! ```rust,no_run
51//! use rusmes_jmap::EventSourceManager;
52//!
53//! let manager = EventSourceManager::new();
54//! // Notify all connected clients that the Email state has changed:
55//! manager.notify_change("Email".to_string(), "new-state-token".to_string());
56//! ```
57//!
58//! # Blob Handling
59//!
60//! [`BlobStorage`] supports two persistence backends:
61//!
62//! - **Memory** (default, via [`BlobStorage::new`]): blobs live in-memory and are
63//! lost on restart. Existing callers are unaffected.
64//! - **Filesystem** (via [`BlobStorage::new_filesystem`]): blobs are written to
65//! `<root>/blobs/<id>` with a JSON sidecar and survive server restarts. The
66//! in-memory index is rebuilt by scanning `.meta.json` sidecars on open.
67//!
68//! Both backends enforce a configurable `max_blob_size` (default 50 MiB) and
69//! return [`UploadError::TooLarge`] before writing any bytes when the limit is
70//! exceeded. Uploaded blobs are referenced by `blobId` strings throughout JMAP
71//! Email import/parse operations.
72
73pub mod api;
74pub mod auth;
75pub mod back_reference;
76pub mod blob;
77pub mod eventsource;
78pub mod methods;
79pub mod session;
80pub mod types;
81
82pub use api::JmapServer;
83pub use auth::{
84 authenticate, extract_credentials, require_auth, AuthError, Credentials, SharedAuth,
85};
86pub use blob::{BlobMeta, BlobStorage, UploadError, UploadErrorBody, UploadResponse};
87pub use eventsource::{EventSourceManager, EventSourcePushHint, StateChange};
88pub mod web_push;
89pub use session::{Account, AccountCapability, Capability, Session};
90pub use types::{
91 derive_account_id, Email, EmailAddress, EmailGetRequest, EmailGetResponse, EmailQueryRequest,
92 EmailQueryResponse, EmailSetRequest, EmailSetResponse, JmapError, JmapErrorType, JmapMethod,
93 JmapRequest, JmapResponse, Principal, PushSubscription,
94};