rusmes-jmap 0.1.2

JMAP server for RusMES — RFC 8620/8621 HTTP/JSON mail API with Email, Mailbox, Thread, Blob, EventSource push, and VacationResponse support
Documentation
# rusmes-jmap

JMAP (JSON Meta Application Protocol) server for RusMES, targeting RFC 8620 (JMAP Core) and RFC 8621 (JMAP Mail) compliance.

## Status

Alpha. All core JMAP methods are implemented and tested. Bearer token authentication is wired to the real `AuthBackend`. Email threading (RFC 5256), email import, and email parse are fully operational.

## Architecture

JMAP uses HTTP/JSON instead of a text-based protocol:

```
JmapServer (axum)
  |-- GET  /.well-known/jmap     -> Session resource
  |-- POST /jmap                 -> API endpoint (method calls)
  |-- GET  /download/:acct/:blob -> Blob download
  |-- POST /upload/:acct         -> Blob upload
  '-- GET  /eventsource          -> Push notifications (SSE)
```

## Implemented JMAP Methods

### Core (RFC 8620)
- Session endpoint (`/.well-known/jmap`) with capabilities
- Request validation (`using`, `methodCalls` structure)
- Error responses (`unknownMethod`, `invalidArguments`, `unknownCapability`, `limit`, etc.)
- Account discovery
- Account permission enforcement (per RFC 8620 §3.3 `forbidden` on account mismatch)

### Email Methods (RFC 8621)
- `Email/get`, `Email/set` (create / update / destroy), `Email/query`
- `Email/changes`, `Email/copy`
- `Email/import` — import raw RFC 5322 messages into a mailbox
- `Email/parse` — parse a blob as an RFC 5322 message without storing it
- `EmailSubmission/set`, `EmailSubmission/get`, `EmailSubmission/query`, `EmailSubmission/changes`

### Mailbox Methods
- `Mailbox/get`, `Mailbox/set`, `Mailbox/query`, `Mailbox/changes`

### Other Methods
- `Thread/get`, `Thread/changes`
- `SearchSnippet/get`
- `Identity/get`, `Identity/set` (create / update / destroy)
- `VacationResponse/get`, `VacationResponse/set`

### Email Conversion Correctness
- `EmailConversionContext<'_>`: content-addressed blob IDs (`compute_blob_id` via SHA-256), RFC 8621 keywords (`$seen`, `$flagged`, `$answered`, `$draft`, `$deleted`), real `received_at`, `mailbox_ids`, `thread_id` — no placeholder values in `Email/get` responses

### Threading
- RFC 5256 thread ID assignment via References-chain algorithm

### Authentication
- Bearer token authentication — wired to real `AuthBackend` (token introspection)
- HTTP Basic authentication — delegated to `AuthBackend::authenticate`
- `Principal { account_id, scopes }` attached to request extensions for downstream enforcement

### Blob & Push
- Blob download endpoint (`/download/:account/:blob/:name`)
- Blob upload endpoint (`/upload/:account`)
- EventSource (Server-Sent Events) with broadcast channel

## Modules

| Module | Description |
|--------|-------------|
| `api` | `JmapServer` — axum router and endpoint handlers |
| `auth` | Bearer / Basic credential extraction and `AuthBackend` delegation |
| `types` | `JmapRequest`, `JmapResponse`, `JmapMethod`, `Principal` |
| `methods` | Method dispatch and per-method handlers |

## Key Types

```rust
pub struct JmapRequest {
    pub using: Vec<String>,            // Capability URIs
    pub method_calls: Vec<JmapMethod>, // Batched method invocations
}

pub struct JmapResponse {
    pub method_responses: Vec<JmapMethod>,
    pub session_state: String,
}

pub enum JmapMethod {
    EmailGet { ... },
    EmailSet { ... },
    EmailQuery { ... },
    MailboxGet { ... },
    // ...
}

pub struct Principal {
    pub account_id: String,
    pub scopes: Vec<String>,
}
```

## Dependencies
- `rusmes-proto` - mail types
- `rusmes-storage` - mailbox and message storage
- `rusmes-auth` - authentication
- `axum` / `hyper` - HTTP server
- `serde` / `serde_json` - JSON serialization
- `tokio` - async runtime

## Tests

```bash
cargo nextest run -p rusmes-jmap --all-features   # 135 tests
```