My agentic slop goes here. Not intended for anyone else!

more

+57 -23
stack/jmap/CLAUDE.md
···
### ✅ Good - Using the typed JMAP library API:
```ocaml
(* Build Email/query request using typed constructors *)
-
let query_request = Jmap_mail.Jmap_email.Query.request_v
-
~account_id:(Jmap_core.Jmap_id.of_string account_id)
-
~limit:(Jmap_core.Jmap_primitives.UnsignedInt.of_int 10)
-
~sort:[Jmap_core.Jmap_comparator.v ~property:"receivedAt" ~is_ascending:false ()]
+
let query_request = Jmap_mail.Email.Query.request_v
+
~account_id:(Jmap_core.Id.of_string account_id)
+
~limit:(Jmap_core.Primitives.UnsignedInt.of_int 10)
+
~sort:[Jmap_core.Comparator.v ~property:"receivedAt" ~is_ascending:false ()]
~calculate_total:true
() in
(* Convert to JSON *)
-
let query_args = Jmap_mail.Jmap_email.Query.request_to_json query_request in
+
let query_args = Jmap_mail.Email.Query.request_to_json query_request in
(* Create invocation using Echo witness *)
-
let query_invocation = Jmap_core.Jmap_invocation.Invocation {
+
let query_invocation = Jmap_core.Invocation.Invocation {
method_name = "Email/query";
arguments = query_args;
call_id = "q1";
-
witness = Jmap_core.Jmap_invocation.Echo;
+
witness = Jmap_core.Invocation.Echo;
} in
(* Build request using constructors *)
-
let req = Jmap_core.Jmap_request.make
-
~using:[Jmap_core.Jmap_capability.core; Jmap_core.Jmap_capability.mail]
-
[Jmap_core.Jmap_invocation.Packed query_invocation]
+
let req = Jmap_core.Request.make
+
~using:[Jmap_core.Capability.core; Jmap_core.Capability.mail]
+
[Jmap_core.Invocation.Packed query_invocation]
in
(* Make the call *)
let query_resp = Jmap_client.call client req in
(* Extract results using type-safe response_to_json *)
-
let method_responses = Jmap_core.Jmap_response.method_responses query_resp in
+
let method_responses = Jmap_core.Response.method_responses query_resp in
match method_responses with
| [packed_resp] ->
-
let response_json = Jmap_core.Jmap_invocation.response_to_json packed_resp in
+
let response_json = Jmap_core.Invocation.response_to_json packed_resp in
(* Now parse response_json... *)
(match response_json with
| `O fields ->
···
| _ -> failwith "Unexpected response"
```
+
**Using the unified Jmap module (recommended)**:
+
```ocaml
+
(* Even cleaner with the unified Jmap module *)
+
let query_request = Jmap.Email.Query.request_v
+
~account_id:(Jmap.Id.of_string account_id)
+
~limit:(Jmap.Primitives.UnsignedInt.of_int 10)
+
~sort:[Jmap.Comparator.v ~property:"receivedAt" ~is_ascending:false ()]
+
~calculate_total:true
+
() in
+
+
let query_args = Jmap.Email.Query.request_to_json query_request in
+
let query_invocation = Jmap.Invocation.Invocation {
+
method_name = "Email/query";
+
arguments = query_args;
+
call_id = "q1";
+
witness = Jmap.Invocation.Echo;
+
} in
+
+
let req = Jmap.Request.make
+
~using:[Jmap.Capability.core; Jmap.Capability.mail]
+
[Jmap.Invocation.Packed query_invocation]
+
in
+
+
let query_resp = Jmap.Client.call client req in
+
+
let method_responses = Jmap.Response.method_responses query_resp in
+
match method_responses with
+
| [packed_resp] ->
+
let response_json = Jmap.Invocation.response_to_json packed_resp in
+
(* process response... *)
+
| _ -> failwith "Unexpected response"
+
```
+
The key principles:
1. Use typed `request_v` constructors (e.g., `Email.Query.request_v`, `Email.Get.request_v`)
2. Convert typed requests to JSON with `request_to_json`
-
3. Wrap in invocations and build JMAP requests with `Jmap_request.make`
-
4. Use `Jmap_invocation.response_to_json` to safely extract response data from packed responses
+
3. Wrap in invocations and build JMAP requests with `Request.make`
+
4. Use `Invocation.response_to_json` to safely extract response data from packed responses
## Architecture
+
- **jmap**: Unified ergonomic interface (recommended for most users)
- **jmap-core**: Core JMAP types (Session, Request, Response, Invocations, Standard Methods)
- **jmap-mail**: Email-specific types (RFC 8621)
- **jmap-client**: HTTP client implementation using Eio and the Requests library
## Key Modules
-
### Jmap_request
-
Build JMAP requests using `Jmap_request.make`:
+
### Jmap.Request (or Jmap_core.Request)
+
Build JMAP requests using `Request.make`:
```ocaml
val make :
-
?created_ids:(Jmap_id.t * Jmap_id.t) list option ->
-
using:Jmap_capability.t list ->
-
Jmap_invocation.invocation_list ->
+
?created_ids:(Id.t * Id.t) list option ->
+
using:Capability.t list ->
+
Invocation.invocation_list ->
t
```
-
### Jmap_invocation
+
### Jmap.Invocation (or Jmap_core.Invocation)
Type-safe method invocations using GADT witnesses:
```ocaml
type ('args, 'resp) method_witness =
···
For generic JSON methods, use the Echo witness. For typed methods, use the appropriate witness.
-
### Jmap_capability
+
### Jmap.Capability (or Jmap_core.Capability)
Use predefined capability constants:
```ocaml
-
let caps = [Jmap_capability.core; Jmap_capability.mail]
+
let caps = [Jmap.Capability.core; Jmap.Capability.mail]
```
Or create from URN strings:
```ocaml
-
let cap = Jmap_capability.of_string "urn:ietf:params:jmap:core"
+
let cap = Jmap.Capability.of_string "urn:ietf:params:jmap:core"
```
## Testing Against Real Servers
+43 -33
stack/jmap/README.md
···
# JMAP Implementation
-
OCaml implementation of the JMAP protocol (RFC 8620) with Eio for async I/O.
+
OCaml implementation of the JMAP protocol (RFC 8620, RFC 8621) with Eio for async I/O.
-
## Structure
+
## Packages
-
- **jmap-core**: Core JMAP protocol types and parsers
+
- **jmap**: Unified, ergonomic interface combining all libraries (recommended)
+
- **jmap-core**: Core JMAP protocol types and parsers (RFC 8620)
- **jmap-mail**: JMAP Mail extension (RFC 8621)
- **jmap-client**: HTTP client for JMAP servers using Eio
## Features
+
- ✅ **Ergonomic API**: Clean, unified `Jmap` module with short aliases
+
- ✅ **Type-safe**: Uses GADTs to ensure compile-time correctness
- ✅ Full Eio-based async I/O
- ✅ Uses `Requests` library for HTTP client layer
- ✅ Bearer token and Basic authentication
···
- ✅ API calls with proper JSON serialization
- ✅ Upload and download support
-
## Usage
+
## Installation
+
+
```bash
+
# Recommended: Install the unified package
+
opam install jmap
-
### Creating a Client
+
# Or install individual packages for specialized use
+
opam install jmap-core jmap-mail jmap-client
+
```
+
+
## Quick Start
+
+
### Using the Unified API (Recommended)
```ocaml
Eio_main.run @@ fun env ->
Eio.Switch.run @@ fun sw ->
(* Create connection with authentication *)
-
let conn = Jmap_connection.v
-
~auth:(Jmap_connection.Bearer "your-api-token")
-
() in
+
let conn = Jmap.Connection.bearer_auth ~token:"your-api-token" () in
(* Create client *)
-
let client = Jmap_client.create
+
let client = Jmap.Client.create
~sw
~env
~conn
···
() in
(* Fetch session *)
-
let session = Jmap_client.fetch_session client in
-
Printf.printf "Username: %s\n" (Jmap_core.Jmap_session.username session);
-
```
+
let session = Jmap.Client.get_session client in
+
Printf.printf "Username: %s\n" (Jmap.Session.username session);
-
### Making API Calls
+
(* Query emails using typed API *)
+
let query_req = Jmap.Email.Query.request_v
+
~account_id:(Jmap.Id.of_string account_id)
+
~limit:(Jmap.Primitives.UnsignedInt.of_int 10)
+
()
+
in
-
```ocaml
-
(* Build a JMAP request *)
-
let request_json = \`O [
-
("using", \`A [\`String "urn:ietf:params:jmap:core"; \`String "urn:ietf:params:jmap:mail"]);
-
("methodCalls", \`A [
-
\`A [
-
\`String "Email/query";
-
\`O [("accountId", \`String account_id); ("limit", \`Float 10.)];
-
\`String "c1"
-
]
-
])
-
] in
+
let query_args = Jmap.Email.Query.request_to_json query_req in
+
let invocation = Jmap.Invocation.make_echo "Email/query" query_args "q1" in
+
let req = Jmap.Request.make
+
~using:[Jmap.Capability.core; Jmap.Capability.mail]
+
[invocation]
+
in
-
let req = Jmap_core.Jmap_request.Parser.of_json request_json in
-
let resp = Jmap_client.call client req in
+
let resp = Jmap.Client.call client req
```
+
+
For more examples and advanced usage, see [USAGE_GUIDE.md](USAGE_GUIDE.md).
## Testing with Fastmail
···
dune exec jmap/test/test_fastmail.exe
```
-
## Migration from Unix to Eio
+
## Architecture
-
The JMAP client has been migrated from Unix-based I/O to Eio:
+
The library is organized into clean, modular packages:
-
- ✅ Replaced blocking I/O with Eio structured concurrency
-
- ✅ Integrated with `Requests` library for HTTP
-
- ✅ Added proper resource management with switches
-
- ✅ Maintained backward-compatible API where possible
+
- ✅ Unified `Jmap` module for ergonomic, everyday use
+
- ✅ Specialized submodules (`Jmap_core`, `Jmap_mail`) for advanced cases
+
- ✅ Full Eio integration with structured concurrency
+
- ✅ Type-safe GADTs for compile-time correctness
## Dependencies
+169
stack/jmap/USAGE_GUIDE.md
···
+
# JMAP Library Usage Guide
+
+
## Ergonomic API Design
+
+
The JMAP library provides a clean, ergonomic API with short module names and a unified entry point.
+
+
## Module Structure
+
+
### Unified `Jmap` Module (Recommended)
+
+
The unified `Jmap` module combines `jmap-core`, `jmap-mail`, and `jmap-client` into a single, easy-to-use interface.
+
+
```ocaml
+
let id = Jmap.Id.of_string "abc123"
+
let email_req = Jmap.Email.Query.request_v ~account_id ...
+
let client = Jmap.Client.create ...
+
```
+
+
### Submodules (For Specialized Use)
+
+
You can also use the submodules directly:
+
+
**Jmap_core**:
+
```ocaml
+
Jmap_core.Session.t
+
Jmap_core.Id.of_string
+
Jmap_core.Request.make
+
```
+
+
**Jmap_mail**:
+
```ocaml
+
Jmap_mail.Email.Query.request_v
+
Jmap_mail.Mailbox.get
+
```
+
+
## Module Hierarchy
+
+
### High-Level API (Recommended for Most Users)
+
+
```
+
Jmap -- Unified interface (START HERE)
+
├── Client -- HTTP client (from jmap-client)
+
├── Connection -- Connection config (from jmap-client)
+
+
├── Email -- Email operations (from jmap-mail)
+
├── Mailbox -- Mailbox operations (from jmap-mail)
+
├── Thread -- Thread operations (from jmap-mail)
+
├── Identity -- Identity management (from jmap-mail)
+
├── Email_submission -- Email submission (from jmap-mail)
+
├── Vacation_response -- Vacation responses (from jmap-mail)
+
├── Search_snippet -- Search snippets (from jmap-mail)
+
+
├── Session -- JMAP Session (from jmap-core)
+
├── Request -- Request building (from jmap-core)
+
├── Response -- Response handling (from jmap-core)
+
├── Invocation -- Method invocations (from jmap-core)
+
├── Id -- JMAP IDs (from jmap-core)
+
├── Capability -- Capabilities (from jmap-core)
+
├── Filter -- Filters (from jmap-core)
+
├── Comparator -- Sorting (from jmap-core)
+
├── Primitives -- Primitive types (from jmap-core)
+
├── Error -- Error handling (from jmap-core)
+
├── Binary -- Upload/download (from jmap-core)
+
├── Push -- Push notifications (from jmap-core)
+
+
├── Core -- Full jmap-core access
+
└── Mail -- Full jmap-mail access
+
```
+
+
### Specialized APIs (For Advanced Use Cases)
+
+
```
+
Jmap_core -- Core protocol library
+
├── Session
+
├── Id
+
├── Request
+
├── Response
+
└── ...
+
+
Jmap_mail -- Mail extension library
+
├── Email
+
├── Mailbox
+
├── Thread
+
└── ...
+
+
Jmap_client -- HTTP client library
+
└── (unwrapped: Jmap_client, Jmap_connection)
+
```
+
+
## Usage Examples
+
+
### Example 1: Creating a Client and Querying Emails
+
+
```ocaml
+
let conn = Jmap.Connection.bearer_auth ~token:"..." () in
+
let client = Jmap.Client.create ~sw ~env ~conn ~session_url:"..." () in
+
let session = Jmap.Client.get_session client in
+
+
let query_req = Jmap.Email.Query.request_v
+
~account_id:(Jmap.Id.of_string account_id)
+
~limit:(Jmap.Primitives.UnsignedInt.of_int 10)
+
~sort:[Jmap.Comparator.v ~property:"receivedAt" ~is_ascending:false ()]
+
()
+
in
+
+
let query_args = Jmap.Email.Query.request_to_json query_req in
+
let invocation = Jmap.Invocation.Invocation {
+
method_name = "Email/query";
+
arguments = query_args;
+
call_id = "q1";
+
witness = Jmap.Invocation.Echo;
+
} in
+
+
let req = Jmap.Request.make
+
~using:[Jmap.Capability.core; Jmap.Capability.mail]
+
[Jmap.Invocation.Packed invocation]
+
in
+
+
let resp = Jmap.Client.call client req in
+
```
+
+
### Example 2: Using Submodules
+
+
```ocaml
+
(* Use Jmap_core for core protocol operations *)
+
let session = Jmap_core.Session.of_json json in
+
let account_id = Jmap_core.Id.of_string "abc123" in
+
+
(* Use Jmap_mail for mail-specific operations *)
+
let email_req = Jmap_mail.Email.Query.request_v
+
~account_id
+
~limit:(Jmap_core.Primitives.UnsignedInt.of_int 50)
+
()
+
in
+
```
+
+
### Example 3: Working with IDs and Primitives
+
+
```ocaml
+
let account_id = Jmap.Id.of_string "abc123" in
+
let limit = Jmap.Primitives.UnsignedInt.of_int 50 in
+
let id_str = Jmap.Id.to_string account_id in
+
```
+
+
## Package Structure
+
+
- **`jmap`** - Unified interface (recommended for applications)
+
- **`jmap-core`** - Core protocol (RFC 8620)
+
- **`jmap-mail`** - Mail extension (RFC 8621)
+
- **`jmap-client`** - HTTP client implementation
+
- **`jmap-test`** - Test suite
+
+
Most users should depend on `jmap`, which pulls in all three libraries. For specialized use cases (e.g., you only need parsing), you can depend on individual packages.
+
+
## Quick Reference
+
+
| Use Case | Unified API | Submodule API |
+
|----------|-------------|---------------|
+
| IDs | `Jmap.Id` | `Jmap_core.Id` |
+
| Requests | `Jmap.Request` | `Jmap_core.Request` |
+
| Emails | `Jmap.Email` | `Jmap_mail.Email` |
+
| Mailboxes | `Jmap.Mailbox` | `Jmap_mail.Mailbox` |
+
| Client | `Jmap.Client` | `Jmap_client` |
+
+
## Need Help?
+
+
- See `jmap/lib/jmap.mli` for the complete unified API documentation
+
- Check `jmap/test/test_unified_api.ml` for working examples
+
- Refer to `jmap/test/test_fastmail.ml` for real-world usage
+11
stack/jmap/dune-project
···
(jmap-mail (= :version))))
(package
+
(name jmap)
+
(synopsis "Unified JMAP library combining core, mail, and client")
+
(description "Ergonomic, unified interface to the complete JMAP library (RFC 8620, RFC 8621). This is the recommended entry point for most users.")
+
(depends
+
(ocaml (>= 4.14))
+
(dune (>= 3.0))
+
(jmap-core (= :version))
+
(jmap-mail (= :version))
+
(jmap-client (= :version))))
+
+
(package
(name jmap-test)
(synopsis "Test suite for JMAP libraries")
(allow_empty)
+8 -8
stack/jmap/jmap-client/jmap_client.ml
···
get_request : timeout:Requests.Timeout.t -> string -> Requests.Response.t;
post_request : timeout:Requests.Timeout.t -> headers:Requests.Headers.t -> body:Requests.Body.t -> string -> Requests.Response.t;
conn : Jmap_connection.t;
-
session : Jmap_core.Jmap_session.t option ref;
+
session : Jmap_core.Session.t option ref;
}
let create ~sw ~env ~conn ~session_url () =
···
Buffer.contents buf
in
-
let session = Jmap_core.Jmap_session.Parser.of_string body_str in
+
let session = Jmap_core.Session.Parser.of_string body_str in
t.session := Some session;
session
···
let call t req =
let session = get_session t in
-
let api_url = Jmap_core.Jmap_session.api_url session in
+
let api_url = Jmap_core.Session.api_url session in
let config = Jmap_connection.config t.conn in
let timeout = Requests.Timeout.create ~total:(Jmap_connection.timeout config) () in
(* Convert request to JSON *)
-
let req_json = Jmap_core.Jmap_request.to_json req in
+
let req_json = Jmap_core.Request.to_json req in
(* Set up headers *)
let headers = Requests.Headers.(empty
···
(Requests.Response.status_code response))
);
-
Jmap_core.Jmap_response.Parser.of_string body_str
+
Jmap_core.Response.Parser.of_string body_str
let upload t ~account_id ~content_type:ct data =
let session = get_session t in
-
let upload_url = Jmap_core.Jmap_session.upload_url session in
+
let upload_url = Jmap_core.Session.upload_url session in
let config = Jmap_connection.config t.conn in
let timeout = Requests.Timeout.create ~total:(Jmap_connection.timeout config) () in
···
in
let json = Ezjsonm.value_from_string body_str in
-
Jmap_core.Jmap_binary.Upload.of_json json
+
Jmap_core.Binary.Upload.of_json json
let download t ~account_id ~blob_id ~name =
let session = get_session t in
-
let download_url = Jmap_core.Jmap_session.download_url session in
+
let download_url = Jmap_core.Session.download_url session in
let config = Jmap_connection.config t.conn in
let timeout = Requests.Timeout.create ~total:(Jmap_connection.timeout config) () in
+4 -4
stack/jmap/jmap-client/jmap_client.mli
···
t
(** Fetch session from server *)
-
val fetch_session : t -> Jmap_core.Jmap_session.t
+
val fetch_session : t -> Jmap_core.Session.t
(** Get cached session or fetch if needed *)
-
val get_session : t -> Jmap_core.Jmap_session.t
+
val get_session : t -> Jmap_core.Session.t
(** Make a JMAP API call *)
-
val call : t -> Jmap_core.Jmap_request.t -> Jmap_core.Jmap_response.t
+
val call : t -> Jmap_core.Request.t -> Jmap_core.Response.t
(** Upload a blob *)
val upload :
···
account_id:string ->
content_type:string ->
string ->
-
Jmap_core.Jmap_binary.Upload.t
+
Jmap_core.Binary.Upload.t
(** Download a blob *)
val download :
+1 -1
stack/jmap/jmap-core/dune
···
(library
(name jmap_core)
(public_name jmap-core)
-
(libraries ezjsonm jsonm)
+
(libraries ezjsonm jsonm unix)
(modules
jmap_core
jmap_error
+14 -15
stack/jmap/jmap-core/jmap_core.ml
···
(** JMAP Core Protocol Library *)
-
(** Re-export all submodules *)
-
module Jmap_error = Jmap_error
-
module Jmap_id = Jmap_id
-
module Jmap_primitives = Jmap_primitives
-
module Jmap_capability = Jmap_capability
-
module Jmap_filter = Jmap_filter
-
module Jmap_comparator = Jmap_comparator
-
module Jmap_standard_methods = Jmap_standard_methods
-
module Jmap_invocation = Jmap_invocation
-
module Jmap_request = Jmap_request
-
module Jmap_response = Jmap_response
-
module Jmap_session = Jmap_session
-
module Jmap_push = Jmap_push
-
module Jmap_binary = Jmap_binary
-
module Jmap_parser = Jmap_parser
+
module Error = Jmap_error
+
module Id = Jmap_id
+
module Primitives = Jmap_primitives
+
module Capability = Jmap_capability
+
module Filter = Jmap_filter
+
module Comparator = Jmap_comparator
+
module Standard_methods = Jmap_standard_methods
+
module Invocation = Jmap_invocation
+
module Request = Jmap_request
+
module Response = Jmap_response
+
module Session = Jmap_session
+
module Push = Jmap_push
+
module Binary = Jmap_binary
+
module Parser = Jmap_parser
+14 -15
stack/jmap/jmap-core/jmap_core.mli
···
(** JMAP Core Protocol Library *)
-
(** Re-export all submodules *)
-
module Jmap_error = Jmap_error
-
module Jmap_id = Jmap_id
-
module Jmap_primitives = Jmap_primitives
-
module Jmap_capability = Jmap_capability
-
module Jmap_filter = Jmap_filter
-
module Jmap_comparator = Jmap_comparator
-
module Jmap_standard_methods = Jmap_standard_methods
-
module Jmap_invocation = Jmap_invocation
-
module Jmap_request = Jmap_request
-
module Jmap_response = Jmap_response
-
module Jmap_session = Jmap_session
-
module Jmap_push = Jmap_push
-
module Jmap_binary = Jmap_binary
-
module Jmap_parser = Jmap_parser
+
module Error = Jmap_error
+
module Id = Jmap_id
+
module Primitives = Jmap_primitives
+
module Capability = Jmap_capability
+
module Filter = Jmap_filter
+
module Comparator = Jmap_comparator
+
module Standard_methods = Jmap_standard_methods
+
module Invocation = Jmap_invocation
+
module Request = Jmap_request
+
module Response = Jmap_response
+
module Session = Jmap_session
+
module Push = Jmap_push
+
module Binary = Jmap_binary
+
module Parser = Jmap_parser
+203 -203
stack/jmap/jmap-mail/jmap_email.ml
···
}
*)
let of_json json =
-
let open Jmap_core.Jmap_parser.Helpers in
+
let open Jmap_core.Parser.Helpers in
let fields = expect_object json in
let name = get_string_opt "name" fields in
let email = get_string "email" fields in
···
}
let of_json json =
-
let open Jmap_core.Jmap_parser.Helpers in
+
let open Jmap_core.Parser.Helpers in
let fields = expect_object json in
let name = get_string "name" fields in
let value = get_string "value" fields in
···
module BodyPart = struct
type t = {
part_id : string option; (** Part ID for referencing this part *)
-
blob_id : Jmap_core.Jmap_id.t option; (** Blob ID for fetching raw content *)
-
size : Jmap_core.Jmap_primitives.UnsignedInt.t; (** Size in octets *)
+
blob_id : Jmap_core.Id.t option; (** Blob ID for fetching raw content *)
+
size : Jmap_core.Primitives.UnsignedInt.t; (** Size in octets *)
headers : EmailHeader.t list; (** All header fields *)
name : string option; (** Name from Content-Disposition or Content-Type *)
type_ : string; (** Content-Type value (e.g., "text/plain") *)
···
}
*)
let rec of_json json =
-
let open Jmap_core.Jmap_parser.Helpers in
+
let open Jmap_core.Parser.Helpers in
let fields = expect_object json in
let part_id = get_string_opt "partId" fields in
let blob_id = match find_field "blobId" fields with
-
| Some (`String s) -> Some (Jmap_core.Jmap_id.of_string s)
+
| Some (`String s) -> Some (Jmap_core.Id.of_string s)
| Some `Null | None -> None
-
| Some _ -> raise (Jmap_core.Jmap_error.Parse_error "blobId must be a string")
+
| Some _ -> raise (Jmap_core.Error.Parse_error "blobId must be a string")
in
let size = match find_field "size" fields with
-
| Some s -> Jmap_core.Jmap_primitives.UnsignedInt.of_json s
-
| None -> Jmap_core.Jmap_primitives.UnsignedInt.of_int 0
+
| Some s -> Jmap_core.Primitives.UnsignedInt.of_json s
+
| None -> Jmap_core.Primitives.UnsignedInt.of_int 0
in
let headers = match find_field "headers" fields with
| Some (`A items) -> List.map EmailHeader.of_json items
| Some `Null | None -> []
-
| Some _ -> raise (Jmap_core.Jmap_error.Parse_error "headers must be an array")
+
| Some _ -> raise (Jmap_core.Error.Parse_error "headers must be an array")
in
let name = get_string_opt "name" fields in
let type_ = get_string "type" fields in
···
let language = match find_field "language" fields with
| Some (`A items) -> Some (List.map expect_string items)
| Some `Null | None -> None
-
| Some _ -> raise (Jmap_core.Jmap_error.Parse_error "language must be an array")
+
| Some _ -> raise (Jmap_core.Error.Parse_error "language must be an array")
in
let location = get_string_opt "location" fields in
let sub_parts = match find_field "subParts" fields with
| Some (`A items) -> Some (List.map of_json items)
| Some `Null | None -> None
-
| Some _ -> raise (Jmap_core.Jmap_error.Parse_error "subParts must be an array")
+
| Some _ -> raise (Jmap_core.Error.Parse_error "subParts must be an array")
in
{ part_id; blob_id; size; headers; name; type_; charset;
disposition; cid; language; location; sub_parts }
···
| None -> fields
in
let fields = match t.blob_id with
-
| Some id -> ("blobId", Jmap_core.Jmap_id.to_json id) :: fields
+
| Some id -> ("blobId", Jmap_core.Id.to_json id) :: fields
| None -> fields
in
-
let fields = ("size", Jmap_core.Jmap_primitives.UnsignedInt.to_json t.size) :: fields in
+
let fields = ("size", Jmap_core.Primitives.UnsignedInt.to_json t.size) :: fields in
let fields = if t.headers <> [] then
("headers", `A (List.map EmailHeader.to_json t.headers)) :: fields
else
···
}
*)
let of_json json =
-
let open Jmap_core.Jmap_parser.Helpers in
+
let open Jmap_core.Parser.Helpers in
let fields = expect_object json in
let value = get_string "value" fields in
let is_encoding_problem = get_bool_opt "isEncodingProblem" fields false in
···
(** Email object type (RFC 8621 Section 4.1) *)
type t = {
(* Metadata properties *)
-
id : Jmap_core.Jmap_id.t; (** Immutable server-assigned id *)
-
blob_id : Jmap_core.Jmap_id.t; (** Blob ID for downloading raw message *)
-
thread_id : Jmap_core.Jmap_id.t; (** Thread ID this email belongs to *)
-
mailbox_ids : (Jmap_core.Jmap_id.t * bool) list; (** Map of mailbox IDs to true *)
+
id : Jmap_core.Id.t; (** Immutable server-assigned id *)
+
blob_id : Jmap_core.Id.t; (** Blob ID for downloading raw message *)
+
thread_id : Jmap_core.Id.t; (** Thread ID this email belongs to *)
+
mailbox_ids : (Jmap_core.Id.t * bool) list; (** Map of mailbox IDs to true *)
keywords : (string * bool) list; (** Map of keywords to true (e.g., "$seen") *)
-
size : Jmap_core.Jmap_primitives.UnsignedInt.t; (** Size in octets *)
-
received_at : Jmap_core.Jmap_primitives.UTCDate.t; (** Date message was received *)
+
size : Jmap_core.Primitives.UnsignedInt.t; (** Size in octets *)
+
received_at : Jmap_core.Primitives.UTCDate.t; (** Date message was received *)
(* Header properties - commonly used headers *)
message_id : string list option; (** Message-ID header field values *)
···
bcc : EmailAddress.t list option; (** Bcc header *)
reply_to : EmailAddress.t list option; (** Reply-To header *)
subject : string option; (** Subject header *)
-
sent_at : Jmap_core.Jmap_primitives.Date.t option; (** Date header *)
+
sent_at : Jmap_core.Primitives.Date.t option; (** Date header *)
(* Body properties *)
body_structure : BodyPart.t option; (** Full MIME structure *)
···
}
*)
let of_json json =
-
let open Jmap_core.Jmap_parser.Helpers in
+
let open Jmap_core.Parser.Helpers in
let fields = expect_object json in
(* Required fields *)
-
let id = Jmap_core.Jmap_id.of_json (require_field "id" fields) in
-
let blob_id = Jmap_core.Jmap_id.of_json (require_field "blobId" fields) in
-
let thread_id = Jmap_core.Jmap_id.of_json (require_field "threadId" fields) in
+
let id = Jmap_core.Id.of_json (require_field "id" fields) in
+
let blob_id = Jmap_core.Id.of_json (require_field "blobId" fields) in
+
let thread_id = Jmap_core.Id.of_json (require_field "threadId" fields) in
(* mailboxIds - map of id -> bool *)
let mailbox_ids = match require_field "mailboxIds" fields with
| `O map_fields ->
List.map (fun (k, v) ->
-
(Jmap_core.Jmap_id.of_string k, expect_bool v)
+
(Jmap_core.Id.of_string k, expect_bool v)
) map_fields
-
| _ -> raise (Jmap_core.Jmap_error.Parse_error "mailboxIds must be an object")
+
| _ -> raise (Jmap_core.Error.Parse_error "mailboxIds must be an object")
in
(* keywords - map of string -> bool *)
let keywords = match require_field "keywords" fields with
| `O map_fields ->
List.map (fun (k, v) -> (k, expect_bool v)) map_fields
-
| _ -> raise (Jmap_core.Jmap_error.Parse_error "keywords must be an object")
+
| _ -> raise (Jmap_core.Error.Parse_error "keywords must be an object")
in
-
let size = Jmap_core.Jmap_primitives.UnsignedInt.of_json (require_field "size" fields) in
-
let received_at = Jmap_core.Jmap_primitives.UTCDate.of_json (require_field "receivedAt" fields) in
+
let size = Jmap_core.Primitives.UnsignedInt.of_json (require_field "size" fields) in
+
let received_at = Jmap_core.Primitives.UTCDate.of_json (require_field "receivedAt" fields) in
(* Optional header fields *)
let message_id = match find_field "messageId" fields with
| Some (`A items) -> Some (List.map expect_string items)
| Some `Null | None -> None
-
| Some _ -> raise (Jmap_core.Jmap_error.Parse_error "messageId must be an array")
+
| Some _ -> raise (Jmap_core.Error.Parse_error "messageId must be an array")
in
let in_reply_to = match find_field "inReplyTo" fields with
| Some (`A items) -> Some (List.map expect_string items)
| Some `Null | None -> None
-
| Some _ -> raise (Jmap_core.Jmap_error.Parse_error "inReplyTo must be an array")
+
| Some _ -> raise (Jmap_core.Error.Parse_error "inReplyTo must be an array")
in
let references = match find_field "references" fields with
| Some (`A items) -> Some (List.map expect_string items)
| Some `Null | None -> None
-
| Some _ -> raise (Jmap_core.Jmap_error.Parse_error "references must be an array")
+
| Some _ -> raise (Jmap_core.Error.Parse_error "references must be an array")
in
let sender = match find_field "sender" fields with
| Some (`A items) -> Some (List.map EmailAddress.of_json items)
| Some `Null | None -> None
-
| Some _ -> raise (Jmap_core.Jmap_error.Parse_error "sender must be an array")
+
| Some _ -> raise (Jmap_core.Error.Parse_error "sender must be an array")
in
let from = match find_field "from" fields with
| Some (`A items) -> Some (List.map EmailAddress.of_json items)
| Some `Null | None -> None
-
| Some _ -> raise (Jmap_core.Jmap_error.Parse_error "from must be an array")
+
| Some _ -> raise (Jmap_core.Error.Parse_error "from must be an array")
in
let to_ = match find_field "to" fields with
| Some (`A items) -> Some (List.map EmailAddress.of_json items)
| Some `Null | None -> None
-
| Some _ -> raise (Jmap_core.Jmap_error.Parse_error "to must be an array")
+
| Some _ -> raise (Jmap_core.Error.Parse_error "to must be an array")
in
let cc = match find_field "cc" fields with
| Some (`A items) -> Some (List.map EmailAddress.of_json items)
| Some `Null | None -> None
-
| Some _ -> raise (Jmap_core.Jmap_error.Parse_error "cc must be an array")
+
| Some _ -> raise (Jmap_core.Error.Parse_error "cc must be an array")
in
let bcc = match find_field "bcc" fields with
| Some (`A items) -> Some (List.map EmailAddress.of_json items)
| Some `Null | None -> None
-
| Some _ -> raise (Jmap_core.Jmap_error.Parse_error "bcc must be an array")
+
| Some _ -> raise (Jmap_core.Error.Parse_error "bcc must be an array")
in
let reply_to = match find_field "replyTo" fields with
| Some (`A items) -> Some (List.map EmailAddress.of_json items)
| Some `Null | None -> None
-
| Some _ -> raise (Jmap_core.Jmap_error.Parse_error "replyTo must be an array")
+
| Some _ -> raise (Jmap_core.Error.Parse_error "replyTo must be an array")
in
let subject = get_string_opt "subject" fields in
let sent_at = match find_field "sentAt" fields with
-
| Some (`String s) -> Some (Jmap_core.Jmap_primitives.Date.of_string s)
+
| Some (`String s) -> Some (Jmap_core.Primitives.Date.of_string s)
| Some `Null | None -> None
-
| Some _ -> raise (Jmap_core.Jmap_error.Parse_error "sentAt must be a string")
+
| Some _ -> raise (Jmap_core.Error.Parse_error "sentAt must be a string")
in
(* Body properties *)
let body_structure = match find_field "bodyStructure" fields with
| Some ((`O _) as json) -> Some (BodyPart.of_json json)
| Some `Null | None -> None
-
| Some _ -> raise (Jmap_core.Jmap_error.Parse_error "bodyStructure must be an object")
+
| Some _ -> raise (Jmap_core.Error.Parse_error "bodyStructure must be an object")
in
(* bodyValues - map of partId -> BodyValue *)
···
| Some (`O map_fields) ->
Some (List.map (fun (k, v) -> (k, BodyValue.of_json v)) map_fields)
| Some `Null | None -> None
-
| Some _ -> raise (Jmap_core.Jmap_error.Parse_error "bodyValues must be an object")
+
| Some _ -> raise (Jmap_core.Error.Parse_error "bodyValues must be an object")
in
let text_body = match find_field "textBody" fields with
| Some (`A items) -> Some (List.map BodyPart.of_json items)
| Some `Null | None -> None
-
| Some _ -> raise (Jmap_core.Jmap_error.Parse_error "textBody must be an array")
+
| Some _ -> raise (Jmap_core.Error.Parse_error "textBody must be an array")
in
let html_body = match find_field "htmlBody" fields with
| Some (`A items) -> Some (List.map BodyPart.of_json items)
| Some `Null | None -> None
-
| Some _ -> raise (Jmap_core.Jmap_error.Parse_error "htmlBody must be an array")
+
| Some _ -> raise (Jmap_core.Error.Parse_error "htmlBody must be an array")
in
let attachments = match find_field "attachments" fields with
| Some (`A items) -> Some (List.map BodyPart.of_json items)
| Some `Null | None -> None
-
| Some _ -> raise (Jmap_core.Jmap_error.Parse_error "attachments must be an array")
+
| Some _ -> raise (Jmap_core.Error.Parse_error "attachments must be an array")
in
let has_attachment = get_bool_opt "hasAttachment" fields false in
···
let to_json t =
let fields = [
-
("id", Jmap_core.Jmap_id.to_json t.id);
-
("blobId", Jmap_core.Jmap_id.to_json t.blob_id);
-
("threadId", Jmap_core.Jmap_id.to_json t.thread_id);
+
("id", Jmap_core.Id.to_json t.id);
+
("blobId", Jmap_core.Id.to_json t.blob_id);
+
("threadId", Jmap_core.Id.to_json t.thread_id);
("mailboxIds", `O (List.map (fun (id, b) ->
-
(Jmap_core.Jmap_id.to_string id, `Bool b)) t.mailbox_ids));
+
(Jmap_core.Id.to_string id, `Bool b)) t.mailbox_ids));
("keywords", `O (List.map (fun (k, b) -> (k, `Bool b)) t.keywords));
-
("size", Jmap_core.Jmap_primitives.UnsignedInt.to_json t.size);
-
("receivedAt", Jmap_core.Jmap_primitives.UTCDate.to_json t.received_at);
+
("size", Jmap_core.Primitives.UnsignedInt.to_json t.size);
+
("receivedAt", Jmap_core.Primitives.UTCDate.to_json t.received_at);
("hasAttachment", `Bool t.has_attachment);
("preview", `String t.preview);
] in
···
| None -> fields
in
let fields = match t.sent_at with
-
| Some d -> ("sentAt", Jmap_core.Jmap_primitives.Date.to_json d) :: fields
+
| Some d -> ("sentAt", Jmap_core.Primitives.Date.to_json d) :: fields
| None -> fields
in
let fields = match t.body_structure with
···
(** Email-specific filter for /query (RFC 8621 Section 4.4) *)
module Filter = struct
type t = {
-
in_mailbox : Jmap_core.Jmap_id.t option; (** Email is in this mailbox *)
-
in_mailbox_other_than : Jmap_core.Jmap_id.t list option; (** Email is in a mailbox other than these *)
-
before : Jmap_core.Jmap_primitives.UTCDate.t option; (** receivedAt < this date *)
-
after : Jmap_core.Jmap_primitives.UTCDate.t option; (** receivedAt >= this date *)
-
min_size : Jmap_core.Jmap_primitives.UnsignedInt.t option; (** size >= this value *)
-
max_size : Jmap_core.Jmap_primitives.UnsignedInt.t option; (** size < this value *)
+
in_mailbox : Jmap_core.Id.t option; (** Email is in this mailbox *)
+
in_mailbox_other_than : Jmap_core.Id.t list option; (** Email is in a mailbox other than these *)
+
before : Jmap_core.Primitives.UTCDate.t option; (** receivedAt < this date *)
+
after : Jmap_core.Primitives.UTCDate.t option; (** receivedAt >= this date *)
+
min_size : Jmap_core.Primitives.UnsignedInt.t option; (** size >= this value *)
+
max_size : Jmap_core.Primitives.UnsignedInt.t option; (** size < this value *)
all_in_thread_have_keyword : string option; (** All emails in thread have this keyword *)
some_in_thread_have_keyword : string option; (** Some email in thread has this keyword *)
none_in_thread_have_keyword : string option; (** No email in thread has this keyword *)
···
}
let of_json json =
-
let open Jmap_core.Jmap_parser.Helpers in
+
let open Jmap_core.Parser.Helpers in
let fields = expect_object json in
let in_mailbox = match find_field "inMailbox" fields with
-
| Some (`String s) -> Some (Jmap_core.Jmap_id.of_string s)
+
| Some (`String s) -> Some (Jmap_core.Id.of_string s)
| Some `Null | None -> None
-
| Some _ -> raise (Jmap_core.Jmap_error.Parse_error "inMailbox must be a string")
+
| Some _ -> raise (Jmap_core.Error.Parse_error "inMailbox must be a string")
in
let in_mailbox_other_than = match find_field "inMailboxOtherThan" fields with
-
| Some (`A items) -> Some (List.map (fun s -> Jmap_core.Jmap_id.of_json s) items)
+
| Some (`A items) -> Some (List.map (fun s -> Jmap_core.Id.of_json s) items)
| Some `Null | None -> None
-
| Some _ -> raise (Jmap_core.Jmap_error.Parse_error "inMailboxOtherThan must be an array")
+
| Some _ -> raise (Jmap_core.Error.Parse_error "inMailboxOtherThan must be an array")
in
let before = match find_field "before" fields with
-
| Some (`String s) -> Some (Jmap_core.Jmap_primitives.UTCDate.of_string s)
+
| Some (`String s) -> Some (Jmap_core.Primitives.UTCDate.of_string s)
| Some `Null | None -> None
-
| Some _ -> raise (Jmap_core.Jmap_error.Parse_error "before must be a string")
+
| Some _ -> raise (Jmap_core.Error.Parse_error "before must be a string")
in
let after = match find_field "after" fields with
-
| Some (`String s) -> Some (Jmap_core.Jmap_primitives.UTCDate.of_string s)
+
| Some (`String s) -> Some (Jmap_core.Primitives.UTCDate.of_string s)
| Some `Null | None -> None
-
| Some _ -> raise (Jmap_core.Jmap_error.Parse_error "after must be a string")
+
| Some _ -> raise (Jmap_core.Error.Parse_error "after must be a string")
in
let min_size = match find_field "minSize" fields with
-
| Some s -> Some (Jmap_core.Jmap_primitives.UnsignedInt.of_json s)
+
| Some s -> Some (Jmap_core.Primitives.UnsignedInt.of_json s)
| None -> None
in
let max_size = match find_field "maxSize" fields with
-
| Some s -> Some (Jmap_core.Jmap_primitives.UnsignedInt.of_json s)
+
| Some s -> Some (Jmap_core.Primitives.UnsignedInt.of_json s)
| None -> None
in
let all_in_thread_have_keyword = get_string_opt "allInThreadHaveKeyword" fields in
···
let has_attachment = match find_field "hasAttachment" fields with
| Some (`Bool b) -> Some b
| Some `Null | None -> None
-
| Some _ -> raise (Jmap_core.Jmap_error.Parse_error "hasAttachment must be a boolean")
+
| Some _ -> raise (Jmap_core.Error.Parse_error "hasAttachment must be a boolean")
in
let text = get_string_opt "text" fields in
let from = get_string_opt "from" fields in
···
(name, value)
) items)
| Some `Null | None -> None
-
| Some _ -> raise (Jmap_core.Jmap_error.Parse_error "header must be an array")
+
| Some _ -> raise (Jmap_core.Error.Parse_error "header must be an array")
in
{ in_mailbox; in_mailbox_other_than; before; after; min_size; max_size;
all_in_thread_have_keyword; some_in_thread_have_keyword;
···
let to_json t =
let fields = [] in
let fields = match t.in_mailbox with
-
| Some id -> ("inMailbox", Jmap_core.Jmap_id.to_json id) :: fields
+
| Some id -> ("inMailbox", Jmap_core.Id.to_json id) :: fields
| None -> fields
in
let fields = match t.in_mailbox_other_than with
-
| Some ids -> ("inMailboxOtherThan", `A (List.map Jmap_core.Jmap_id.to_json ids)) :: fields
+
| Some ids -> ("inMailboxOtherThan", `A (List.map Jmap_core.Id.to_json ids)) :: fields
| None -> fields
in
let fields = match t.before with
-
| Some d -> ("before", `String (Jmap_core.Jmap_primitives.UTCDate.to_string d)) :: fields
+
| Some d -> ("before", `String (Jmap_core.Primitives.UTCDate.to_string d)) :: fields
| None -> fields
in
let fields = match t.after with
-
| Some d -> ("after", `String (Jmap_core.Jmap_primitives.UTCDate.to_string d)) :: fields
+
| Some d -> ("after", `String (Jmap_core.Primitives.UTCDate.to_string d)) :: fields
| None -> fields
in
let fields = match t.min_size with
-
| Some s -> ("minSize", Jmap_core.Jmap_primitives.UnsignedInt.to_json s) :: fields
+
| Some s -> ("minSize", Jmap_core.Primitives.UnsignedInt.to_json s) :: fields
| None -> fields
in
let fields = match t.max_size with
-
| Some s -> ("maxSize", Jmap_core.Jmap_primitives.UnsignedInt.to_json s) :: fields
+
| Some s -> ("maxSize", Jmap_core.Primitives.UnsignedInt.to_json s) :: fields
| None -> fields
in
let fields = match t.all_in_thread_have_keyword with
···
(** Standard /get method (RFC 8621 Section 4.2) *)
module Get = struct
type request = {
-
account_id : Jmap_core.Jmap_id.t;
-
ids : Jmap_core.Jmap_id.t list option;
+
account_id : Jmap_core.Id.t;
+
ids : Jmap_core.Id.t list option;
properties : string list option;
(* Email-specific get arguments *)
body_properties : string list option; (** Properties to fetch for bodyStructure parts *)
fetch_text_body_values : bool option; (** Fetch bodyValues for textBody parts *)
fetch_html_body_values : bool option; (** Fetch bodyValues for htmlBody parts *)
fetch_all_body_values : bool option; (** Fetch bodyValues for all parts *)
-
max_body_value_bytes : Jmap_core.Jmap_primitives.UnsignedInt.t option; (** Truncate large body values *)
+
max_body_value_bytes : Jmap_core.Primitives.UnsignedInt.t option; (** Truncate large body values *)
}
-
type response = t Jmap_core.Jmap_standard_methods.Get.response
+
type response = t Jmap_core.Standard_methods.Get.response
(* Accessors for request *)
let account_id req = req.account_id
···
- test/data/mail/email_get_full_request.json
*)
let request_of_json json =
-
let open Jmap_core.Jmap_parser.Helpers in
+
let open Jmap_core.Parser.Helpers in
let fields = expect_object json in
-
let account_id = Jmap_core.Jmap_id.of_json (require_field "accountId" fields) in
+
let account_id = Jmap_core.Id.of_json (require_field "accountId" fields) in
let ids = match find_field "ids" fields with
-
| Some (`A items) -> Some (List.map Jmap_core.Jmap_id.of_json items)
+
| Some (`A items) -> Some (List.map Jmap_core.Id.of_json items)
| Some `Null | None -> None
-
| Some _ -> raise (Jmap_core.Jmap_error.Parse_error "ids must be an array")
+
| Some _ -> raise (Jmap_core.Error.Parse_error "ids must be an array")
in
let properties = match find_field "properties" fields with
| Some (`A items) -> Some (List.map expect_string items)
| Some `Null | None -> None
-
| Some _ -> raise (Jmap_core.Jmap_error.Parse_error "properties must be an array")
+
| Some _ -> raise (Jmap_core.Error.Parse_error "properties must be an array")
in
let body_properties = match find_field "bodyProperties" fields with
| Some (`A items) -> Some (List.map expect_string items)
| Some `Null | None -> None
-
| Some _ -> raise (Jmap_core.Jmap_error.Parse_error "bodyProperties must be an array")
+
| Some _ -> raise (Jmap_core.Error.Parse_error "bodyProperties must be an array")
in
let fetch_text_body_values = match find_field "fetchTextBodyValues" fields with
| Some (`Bool b) -> Some b
| Some `Null | None -> None
-
| Some _ -> raise (Jmap_core.Jmap_error.Parse_error "fetchTextBodyValues must be a boolean")
+
| Some _ -> raise (Jmap_core.Error.Parse_error "fetchTextBodyValues must be a boolean")
in
let fetch_html_body_values = match find_field "fetchHTMLBodyValues" fields with
| Some (`Bool b) -> Some b
| Some `Null | None -> None
-
| Some _ -> raise (Jmap_core.Jmap_error.Parse_error "fetchHTMLBodyValues must be a boolean")
+
| Some _ -> raise (Jmap_core.Error.Parse_error "fetchHTMLBodyValues must be a boolean")
in
let fetch_all_body_values = match find_field "fetchAllBodyValues" fields with
| Some (`Bool b) -> Some b
| Some `Null | None -> None
-
| Some _ -> raise (Jmap_core.Jmap_error.Parse_error "fetchAllBodyValues must be a boolean")
+
| Some _ -> raise (Jmap_core.Error.Parse_error "fetchAllBodyValues must be a boolean")
in
let max_body_value_bytes = match find_field "maxBodyValueBytes" fields with
-
| Some v -> Some (Jmap_core.Jmap_primitives.UnsignedInt.of_json v)
+
| Some v -> Some (Jmap_core.Primitives.UnsignedInt.of_json v)
| None -> None
in
{ account_id; ids; properties; body_properties; fetch_text_body_values;
···
- test/data/mail/email_get_full_response.json
*)
let response_of_json json =
-
Jmap_core.Jmap_standard_methods.Get.response_of_json of_json json
+
Jmap_core.Standard_methods.Get.response_of_json of_json json
(** Convert get request to JSON *)
let request_to_json req =
let fields = [
-
("accountId", Jmap_core.Jmap_id.to_json req.account_id);
+
("accountId", Jmap_core.Id.to_json req.account_id);
] in
let fields = match req.ids with
-
| Some ids -> ("ids", `A (List.map Jmap_core.Jmap_id.to_json ids)) :: fields
+
| Some ids -> ("ids", `A (List.map Jmap_core.Id.to_json ids)) :: fields
| None -> fields
in
let fields = match req.properties with
···
| None -> fields
in
let fields = match req.max_body_value_bytes with
-
| Some mbvb -> ("maxBodyValueBytes", Jmap_core.Jmap_primitives.UnsignedInt.to_json mbvb) :: fields
+
| Some mbvb -> ("maxBodyValueBytes", Jmap_core.Primitives.UnsignedInt.to_json mbvb) :: fields
| None -> fields
in
`O fields
···
(** Standard /changes method (RFC 8621 Section 4.3) *)
module Changes = struct
-
type request = Jmap_core.Jmap_standard_methods.Changes.request
-
type response = Jmap_core.Jmap_standard_methods.Changes.response
+
type request = Jmap_core.Standard_methods.Changes.request
+
type response = Jmap_core.Standard_methods.Changes.response
let request_of_json json =
-
Jmap_core.Jmap_standard_methods.Changes.request_of_json json
+
Jmap_core.Standard_methods.Changes.request_of_json json
let response_of_json json =
-
Jmap_core.Jmap_standard_methods.Changes.response_of_json json
+
Jmap_core.Standard_methods.Changes.response_of_json json
end
(** Standard /query method (RFC 8621 Section 4.4) *)
module Query = struct
type request = {
-
account_id : Jmap_core.Jmap_id.t;
-
filter : Filter.t Jmap_core.Jmap_filter.t option;
-
sort : Jmap_core.Jmap_comparator.t list option;
-
position : Jmap_core.Jmap_primitives.Int53.t option;
-
anchor : Jmap_core.Jmap_id.t option;
-
anchor_offset : Jmap_core.Jmap_primitives.Int53.t option;
-
limit : Jmap_core.Jmap_primitives.UnsignedInt.t option;
+
account_id : Jmap_core.Id.t;
+
filter : Filter.t Jmap_core.Filter.t option;
+
sort : Jmap_core.Comparator.t list option;
+
position : Jmap_core.Primitives.Int53.t option;
+
anchor : Jmap_core.Id.t option;
+
anchor_offset : Jmap_core.Primitives.Int53.t option;
+
limit : Jmap_core.Primitives.UnsignedInt.t option;
calculate_total : bool option;
(* Email-specific query arguments *)
collapse_threads : bool option; (** Return only one email per thread *)
}
-
type response = Jmap_core.Jmap_standard_methods.Query.response
+
type response = Jmap_core.Standard_methods.Query.response
(* Accessors for request *)
let account_id req = req.account_id
···
(** Parse query request from JSON.
Test files: test/data/mail/email_query_request.json *)
let request_of_json json =
-
let open Jmap_core.Jmap_parser.Helpers in
+
let open Jmap_core.Parser.Helpers in
let fields = expect_object json in
-
let account_id = Jmap_core.Jmap_id.of_json (require_field "accountId" fields) in
+
let account_id = Jmap_core.Id.of_json (require_field "accountId" fields) in
let filter = match find_field "filter" fields with
-
| Some v -> Some (Jmap_core.Jmap_filter.of_json Filter.of_json v)
+
| Some v -> Some (Jmap_core.Filter.of_json Filter.of_json v)
| None -> None
in
let sort = match find_field "sort" fields with
-
| Some (`A items) -> Some (List.map Jmap_core.Jmap_comparator.of_json items)
+
| Some (`A items) -> Some (List.map Jmap_core.Comparator.of_json items)
| Some `Null | None -> None
-
| Some _ -> raise (Jmap_core.Jmap_error.Parse_error "sort must be an array")
+
| Some _ -> raise (Jmap_core.Error.Parse_error "sort must be an array")
in
let position = match find_field "position" fields with
-
| Some v -> Some (Jmap_core.Jmap_primitives.Int53.of_json v)
+
| Some v -> Some (Jmap_core.Primitives.Int53.of_json v)
| None -> None
in
let anchor = match find_field "anchor" fields with
-
| Some (`String s) -> Some (Jmap_core.Jmap_id.of_string s)
+
| Some (`String s) -> Some (Jmap_core.Id.of_string s)
| Some `Null | None -> None
-
| Some _ -> raise (Jmap_core.Jmap_error.Parse_error "anchor must be a string")
+
| Some _ -> raise (Jmap_core.Error.Parse_error "anchor must be a string")
in
let anchor_offset = match find_field "anchorOffset" fields with
-
| Some v -> Some (Jmap_core.Jmap_primitives.Int53.of_json v)
+
| Some v -> Some (Jmap_core.Primitives.Int53.of_json v)
| None -> None
in
let limit = match find_field "limit" fields with
-
| Some v -> Some (Jmap_core.Jmap_primitives.UnsignedInt.of_json v)
+
| Some v -> Some (Jmap_core.Primitives.UnsignedInt.of_json v)
| None -> None
in
let calculate_total = match find_field "calculateTotal" fields with
| Some (`Bool b) -> Some b
| Some `Null | None -> None
-
| Some _ -> raise (Jmap_core.Jmap_error.Parse_error "calculateTotal must be a boolean")
+
| Some _ -> raise (Jmap_core.Error.Parse_error "calculateTotal must be a boolean")
in
let collapse_threads = match find_field "collapseThreads" fields with
| Some (`Bool b) -> Some b
| Some `Null | None -> None
-
| Some _ -> raise (Jmap_core.Jmap_error.Parse_error "collapseThreads must be a boolean")
+
| Some _ -> raise (Jmap_core.Error.Parse_error "collapseThreads must be a boolean")
in
{ account_id; filter; sort; position; anchor; anchor_offset;
limit; calculate_total; collapse_threads }
···
(** Parse query response from JSON.
Test files: test/data/mail/email_query_response.json *)
let response_of_json json =
-
Jmap_core.Jmap_standard_methods.Query.response_of_json json
+
Jmap_core.Standard_methods.Query.response_of_json json
(** Convert query request to JSON *)
let request_to_json req =
let fields = [
-
("accountId", Jmap_core.Jmap_id.to_json req.account_id);
+
("accountId", Jmap_core.Id.to_json req.account_id);
] in
let fields = match req.filter with
-
| Some f -> ("filter", Jmap_core.Jmap_filter.to_json Filter.to_json f) :: fields
+
| Some f -> ("filter", Jmap_core.Filter.to_json Filter.to_json f) :: fields
| None -> fields
in
let fields = match req.sort with
-
| Some s -> ("sort", `A (List.map Jmap_core.Jmap_comparator.to_json s)) :: fields
+
| Some s -> ("sort", `A (List.map Jmap_core.Comparator.to_json s)) :: fields
| None -> fields
in
let fields = match req.position with
-
| Some p -> ("position", Jmap_core.Jmap_primitives.Int53.to_json p) :: fields
+
| Some p -> ("position", Jmap_core.Primitives.Int53.to_json p) :: fields
| None -> fields
in
let fields = match req.anchor with
-
| Some a -> ("anchor", Jmap_core.Jmap_id.to_json a) :: fields
+
| Some a -> ("anchor", Jmap_core.Id.to_json a) :: fields
| None -> fields
in
let fields = match req.anchor_offset with
-
| Some ao -> ("anchorOffset", Jmap_core.Jmap_primitives.Int53.to_json ao) :: fields
+
| Some ao -> ("anchorOffset", Jmap_core.Primitives.Int53.to_json ao) :: fields
| None -> fields
in
let fields = match req.limit with
-
| Some l -> ("limit", Jmap_core.Jmap_primitives.UnsignedInt.to_json l) :: fields
+
| Some l -> ("limit", Jmap_core.Primitives.UnsignedInt.to_json l) :: fields
| None -> fields
in
let fields = match req.calculate_total with
···
(** Standard /queryChanges method (RFC 8621 Section 4.5) *)
module QueryChanges = struct
type request = {
-
account_id : Jmap_core.Jmap_id.t;
-
filter : Filter.t Jmap_core.Jmap_filter.t option;
-
sort : Jmap_core.Jmap_comparator.t list option;
+
account_id : Jmap_core.Id.t;
+
filter : Filter.t Jmap_core.Filter.t option;
+
sort : Jmap_core.Comparator.t list option;
since_query_state : string;
-
max_changes : Jmap_core.Jmap_primitives.UnsignedInt.t option;
-
up_to_id : Jmap_core.Jmap_id.t option;
+
max_changes : Jmap_core.Primitives.UnsignedInt.t option;
+
up_to_id : Jmap_core.Id.t option;
calculate_total : bool option;
(* Email-specific *)
collapse_threads : bool option;
-
type response = Jmap_core.Jmap_standard_methods.QueryChanges.response
+
type response = Jmap_core.Standard_methods.QueryChanges.response
(* Accessors for request *)
let account_id req = req.account_id
···
up_to_id; calculate_total; collapse_threads }
let request_of_json json =
-
let open Jmap_core.Jmap_parser.Helpers in
+
let open Jmap_core.Parser.Helpers in
let fields = expect_object json in
-
let account_id = Jmap_core.Jmap_id.of_json (require_field "accountId" fields) in
+
let account_id = Jmap_core.Id.of_json (require_field "accountId" fields) in
let filter = match find_field "filter" fields with
-
| Some v -> Some (Jmap_core.Jmap_filter.of_json Filter.of_json v)
+
| Some v -> Some (Jmap_core.Filter.of_json Filter.of_json v)
| None -> None
in
let sort = match find_field "sort" fields with
-
| Some (`A items) -> Some (List.map Jmap_core.Jmap_comparator.of_json items)
+
| Some (`A items) -> Some (List.map Jmap_core.Comparator.of_json items)
| Some `Null | None -> None
-
| Some _ -> raise (Jmap_core.Jmap_error.Parse_error "sort must be an array")
+
| Some _ -> raise (Jmap_core.Error.Parse_error "sort must be an array")
in
let since_query_state = get_string "sinceQueryState" fields in
let max_changes = match find_field "maxChanges" fields with
-
| Some v -> Some (Jmap_core.Jmap_primitives.UnsignedInt.of_json v)
+
| Some v -> Some (Jmap_core.Primitives.UnsignedInt.of_json v)
| None -> None
in
let up_to_id = match find_field "upToId" fields with
-
| Some (`String s) -> Some (Jmap_core.Jmap_id.of_string s)
+
| Some (`String s) -> Some (Jmap_core.Id.of_string s)
| Some `Null | None -> None
-
| Some _ -> raise (Jmap_core.Jmap_error.Parse_error "upToId must be a string")
+
| Some _ -> raise (Jmap_core.Error.Parse_error "upToId must be a string")
in
let calculate_total = match find_field "calculateTotal" fields with
| Some (`Bool b) -> Some b
| Some `Null | None -> None
-
| Some _ -> raise (Jmap_core.Jmap_error.Parse_error "calculateTotal must be a boolean")
+
| Some _ -> raise (Jmap_core.Error.Parse_error "calculateTotal must be a boolean")
in
let collapse_threads = match find_field "collapseThreads" fields with
| Some (`Bool b) -> Some b
| Some `Null | None -> None
-
| Some _ -> raise (Jmap_core.Jmap_error.Parse_error "collapseThreads must be a boolean")
+
| Some _ -> raise (Jmap_core.Error.Parse_error "collapseThreads must be a boolean")
in
{ account_id; filter; sort; since_query_state; max_changes;
up_to_id; calculate_total; collapse_threads }
let response_of_json json =
-
Jmap_core.Jmap_standard_methods.QueryChanges.response_of_json json
+
Jmap_core.Standard_methods.QueryChanges.response_of_json json
end
(** Standard /set method (RFC 8621 Section 4.6) *)
module Set = struct
-
type request = t Jmap_core.Jmap_standard_methods.Set.request
-
type response = t Jmap_core.Jmap_standard_methods.Set.response
+
type request = t Jmap_core.Standard_methods.Set.request
+
type response = t Jmap_core.Standard_methods.Set.response
(** Parse set request from JSON.
Test files: test/data/mail/email_set_request.json *)
let request_of_json json =
-
Jmap_core.Jmap_standard_methods.Set.request_of_json of_json json
+
Jmap_core.Standard_methods.Set.request_of_json of_json json
(** Parse set response from JSON.
Test files: test/data/mail/email_set_response.json *)
let response_of_json json =
-
Jmap_core.Jmap_standard_methods.Set.response_of_json of_json json
+
Jmap_core.Standard_methods.Set.response_of_json of_json json
end
(** Standard /copy method (RFC 8621 Section 4.7) *)
module Copy = struct
-
type request = t Jmap_core.Jmap_standard_methods.Copy.request
-
type response = t Jmap_core.Jmap_standard_methods.Copy.response
+
type request = t Jmap_core.Standard_methods.Copy.request
+
type response = t Jmap_core.Standard_methods.Copy.response
let request_of_json json =
-
Jmap_core.Jmap_standard_methods.Copy.request_of_json of_json json
+
Jmap_core.Standard_methods.Copy.request_of_json of_json json
let response_of_json json =
-
Jmap_core.Jmap_standard_methods.Copy.response_of_json of_json json
+
Jmap_core.Standard_methods.Copy.response_of_json of_json json
end
(** Email/import method (RFC 8621 Section 4.8) *)
module Import = struct
(** Email import request object *)
type import_email = {
-
blob_id : Jmap_core.Jmap_id.t; (** Blob ID containing raw RFC 5322 message *)
-
mailbox_ids : (Jmap_core.Jmap_id.t * bool) list; (** Mailboxes to add email to *)
+
blob_id : Jmap_core.Id.t; (** Blob ID containing raw RFC 5322 message *)
+
mailbox_ids : (Jmap_core.Id.t * bool) list; (** Mailboxes to add email to *)
keywords : (string * bool) list; (** Keywords to set *)
-
received_at : Jmap_core.Jmap_primitives.UTCDate.t option; (** Override received date *)
+
received_at : Jmap_core.Primitives.UTCDate.t option; (** Override received date *)
type request = {
-
account_id : Jmap_core.Jmap_id.t;
+
account_id : Jmap_core.Id.t;
if_in_state : string option;
-
emails : (Jmap_core.Jmap_id.t * import_email) list; (** Map of creation id to import object *)
+
emails : (Jmap_core.Id.t * import_email) list; (** Map of creation id to import object *)
type response = {
-
account_id : Jmap_core.Jmap_id.t;
+
account_id : Jmap_core.Id.t;
old_state : string option;
new_state : string;
-
created : (Jmap_core.Jmap_id.t * t) list option;
-
not_created : (Jmap_core.Jmap_id.t * Jmap_core.Jmap_error.set_error_detail) list option;
+
created : (Jmap_core.Id.t * t) list option;
+
not_created : (Jmap_core.Id.t * Jmap_core.Error.set_error_detail) list option;
(* Accessors for import_email *)
···
(** Parse import request from JSON.
Test files: test/data/mail/email_import_request.json *)
let request_of_json json =
-
let open Jmap_core.Jmap_parser.Helpers in
+
let open Jmap_core.Parser.Helpers in
let fields = expect_object json in
-
let account_id = Jmap_core.Jmap_id.of_json (require_field "accountId" fields) in
+
let account_id = Jmap_core.Id.of_json (require_field "accountId" fields) in
let if_in_state = get_string_opt "ifInState" fields in
let emails = match require_field "emails" fields with
| `O pairs ->
List.map (fun (k, v) ->
let ie_fields = expect_object v in
-
let blob_id = Jmap_core.Jmap_id.of_json (require_field "blobId" ie_fields) in
+
let blob_id = Jmap_core.Id.of_json (require_field "blobId" ie_fields) in
let mailbox_ids = match require_field "mailboxIds" ie_fields with
| `O map_fields ->
List.map (fun (mid, b) ->
-
(Jmap_core.Jmap_id.of_string mid, expect_bool b)
+
(Jmap_core.Id.of_string mid, expect_bool b)
) map_fields
-
| _ -> raise (Jmap_core.Jmap_error.Parse_error "mailboxIds must be an object")
+
| _ -> raise (Jmap_core.Error.Parse_error "mailboxIds must be an object")
in
let keywords = match require_field "keywords" ie_fields with
| `O map_fields ->
List.map (fun (kw, b) -> (kw, expect_bool b)) map_fields
-
| _ -> raise (Jmap_core.Jmap_error.Parse_error "keywords must be an object")
+
| _ -> raise (Jmap_core.Error.Parse_error "keywords must be an object")
in
let received_at = match find_field "receivedAt" ie_fields with
-
| Some (`String s) -> Some (Jmap_core.Jmap_primitives.UTCDate.of_string s)
+
| Some (`String s) -> Some (Jmap_core.Primitives.UTCDate.of_string s)
| Some `Null | None -> None
-
| Some _ -> raise (Jmap_core.Jmap_error.Parse_error "receivedAt must be a string")
+
| Some _ -> raise (Jmap_core.Error.Parse_error "receivedAt must be a string")
in
let import_email = { blob_id; mailbox_ids; keywords; received_at } in
-
(Jmap_core.Jmap_id.of_string k, import_email)
+
(Jmap_core.Id.of_string k, import_email)
) pairs
-
| _ -> raise (Jmap_core.Jmap_error.Parse_error "emails must be an object")
+
| _ -> raise (Jmap_core.Error.Parse_error "emails must be an object")
in
{ account_id; if_in_state; emails }
(** Parse import response from JSON.
Test files: test/data/mail/email_import_response.json *)
let response_of_json json =
-
let open Jmap_core.Jmap_parser.Helpers in
+
let open Jmap_core.Parser.Helpers in
let fields = expect_object json in
-
let account_id = Jmap_core.Jmap_id.of_json (require_field "accountId" fields) in
+
let account_id = Jmap_core.Id.of_json (require_field "accountId" fields) in
let old_state = get_string_opt "oldState" fields in
let new_state = get_string "newState" fields in
let created = match find_field "created" fields with
| Some `Null | None -> None
| Some (`O pairs) ->
Some (List.map (fun (k, v) ->
-
(Jmap_core.Jmap_id.of_string k, of_json v)
+
(Jmap_core.Id.of_string k, of_json v)
) pairs)
-
| Some _ -> raise (Jmap_core.Jmap_error.Parse_error "created must be an object")
+
| Some _ -> raise (Jmap_core.Error.Parse_error "created must be an object")
in
let not_created = match find_field "notCreated" fields with
| Some `Null | None -> None
| Some (`O pairs) ->
Some (List.map (fun (k, v) ->
-
(Jmap_core.Jmap_id.of_string k, Jmap_core.Jmap_error.parse_set_error_detail v)
+
(Jmap_core.Id.of_string k, Jmap_core.Error.parse_set_error_detail v)
) pairs)
-
| Some _ -> raise (Jmap_core.Jmap_error.Parse_error "notCreated must be an object")
+
| Some _ -> raise (Jmap_core.Error.Parse_error "notCreated must be an object")
in
{ account_id; old_state; new_state; created; not_created }
end
···
(** Email/parse method (RFC 8621 Section 4.9) *)
module Parse = struct
type request = {
-
account_id : Jmap_core.Jmap_id.t;
-
blob_ids : Jmap_core.Jmap_id.t list; (** Blob IDs to parse *)
+
account_id : Jmap_core.Id.t;
+
blob_ids : Jmap_core.Id.t list; (** Blob IDs to parse *)
properties : string list option; (** Email properties to return *)
body_properties : string list option; (** BodyPart properties to return *)
fetch_text_body_values : bool option;
fetch_html_body_values : bool option;
fetch_all_body_values : bool option;
-
max_body_value_bytes : Jmap_core.Jmap_primitives.UnsignedInt.t option;
+
max_body_value_bytes : Jmap_core.Primitives.UnsignedInt.t option;
type response = {
-
account_id : Jmap_core.Jmap_id.t;
-
parsed : (Jmap_core.Jmap_id.t * t) list option; (** Map of blob ID to parsed email *)
-
not_parsable : Jmap_core.Jmap_id.t list option; (** Blob IDs that couldn't be parsed *)
-
not_found : Jmap_core.Jmap_id.t list option; (** Blob IDs that don't exist *)
+
account_id : Jmap_core.Id.t;
+
parsed : (Jmap_core.Id.t * t) list option; (** Map of blob ID to parsed email *)
+
not_parsable : Jmap_core.Id.t list option; (** Blob IDs that couldn't be parsed *)
+
not_found : Jmap_core.Id.t list option; (** Blob IDs that don't exist *)
(* Accessors for request *)
···
(** Parse parse request from JSON.
Test files: test/data/mail/email_parse_request.json *)
let request_of_json json =
-
let open Jmap_core.Jmap_parser.Helpers in
+
let open Jmap_core.Parser.Helpers in
let fields = expect_object json in
-
let account_id = Jmap_core.Jmap_id.of_json (require_field "accountId" fields) in
+
let account_id = Jmap_core.Id.of_json (require_field "accountId" fields) in
let blob_ids = match require_field "blobIds" fields with
-
| `A items -> List.map Jmap_core.Jmap_id.of_json items
-
| _ -> raise (Jmap_core.Jmap_error.Parse_error "blobIds must be an array")
+
| `A items -> List.map Jmap_core.Id.of_json items
+
| _ -> raise (Jmap_core.Error.Parse_error "blobIds must be an array")
in
let properties = match find_field "properties" fields with
| Some (`A items) -> Some (List.map expect_string items)
| Some `Null | None -> None
-
| Some _ -> raise (Jmap_core.Jmap_error.Parse_error "properties must be an array")
+
| Some _ -> raise (Jmap_core.Error.Parse_error "properties must be an array")
in
let body_properties = match find_field "bodyProperties" fields with
| Some (`A items) -> Some (List.map expect_string items)
| Some `Null | None -> None
-
| Some _ -> raise (Jmap_core.Jmap_error.Parse_error "bodyProperties must be an array")
+
| Some _ -> raise (Jmap_core.Error.Parse_error "bodyProperties must be an array")
in
let fetch_text_body_values = match find_field "fetchTextBodyValues" fields with
| Some (`Bool b) -> Some b
| Some `Null | None -> None
-
| Some _ -> raise (Jmap_core.Jmap_error.Parse_error "fetchTextBodyValues must be a boolean")
+
| Some _ -> raise (Jmap_core.Error.Parse_error "fetchTextBodyValues must be a boolean")
in
let fetch_html_body_values = match find_field "fetchHTMLBodyValues" fields with
| Some (`Bool b) -> Some b
| Some `Null | None -> None
-
| Some _ -> raise (Jmap_core.Jmap_error.Parse_error "fetchHTMLBodyValues must be a boolean")
+
| Some _ -> raise (Jmap_core.Error.Parse_error "fetchHTMLBodyValues must be a boolean")
in
let fetch_all_body_values = match find_field "fetchAllBodyValues" fields with
| Some (`Bool b) -> Some b
| Some `Null | None -> None
-
| Some _ -> raise (Jmap_core.Jmap_error.Parse_error "fetchAllBodyValues must be a boolean")
+
| Some _ -> raise (Jmap_core.Error.Parse_error "fetchAllBodyValues must be a boolean")
in
let max_body_value_bytes = match find_field "maxBodyValueBytes" fields with
-
| Some v -> Some (Jmap_core.Jmap_primitives.UnsignedInt.of_json v)
+
| Some v -> Some (Jmap_core.Primitives.UnsignedInt.of_json v)
| None -> None
in
{ account_id; blob_ids; properties; body_properties; fetch_text_body_values;
···
(** Parse parse response from JSON.
Test files: test/data/mail/email_parse_response.json *)
let response_of_json json =
-
let open Jmap_core.Jmap_parser.Helpers in
+
let open Jmap_core.Parser.Helpers in
let fields = expect_object json in
-
let account_id = Jmap_core.Jmap_id.of_json (require_field "accountId" fields) in
+
let account_id = Jmap_core.Id.of_json (require_field "accountId" fields) in
let parsed = match find_field "parsed" fields with
| Some `Null | None -> None
| Some (`O pairs) ->
Some (List.map (fun (k, v) ->
-
(Jmap_core.Jmap_id.of_string k, of_json v)
+
(Jmap_core.Id.of_string k, of_json v)
) pairs)
-
| Some _ -> raise (Jmap_core.Jmap_error.Parse_error "parsed must be an object")
+
| Some _ -> raise (Jmap_core.Error.Parse_error "parsed must be an object")
in
let not_parsable = match find_field "notParsable" fields with
-
| Some (`A items) -> Some (List.map Jmap_core.Jmap_id.of_json items)
+
| Some (`A items) -> Some (List.map Jmap_core.Id.of_json items)
| Some `Null | None -> None
-
| Some _ -> raise (Jmap_core.Jmap_error.Parse_error "notParsable must be an array")
+
| Some _ -> raise (Jmap_core.Error.Parse_error "notParsable must be an array")
in
let not_found = match find_field "notFound" fields with
-
| Some (`A items) -> Some (List.map Jmap_core.Jmap_id.of_json items)
+
| Some (`A items) -> Some (List.map Jmap_core.Id.of_json items)
| Some `Null | None -> None
-
| Some _ -> raise (Jmap_core.Jmap_error.Parse_error "notFound must be an array")
+
| Some _ -> raise (Jmap_core.Error.Parse_error "notFound must be an array")
in
{ account_id; parsed; not_parsable; not_found }
end
+144 -144
stack/jmap/jmap-mail/jmap_email.mli
···
module BodyPart : sig
type t = {
part_id : string option;
-
blob_id : Jmap_id.t option;
-
size : Jmap_primitives.UnsignedInt.t;
+
blob_id : Id.t option;
+
size : Primitives.UnsignedInt.t;
headers : EmailHeader.t list;
name : string option;
type_ : string;
···
(** Accessors *)
val part_id : t -> string option
-
val blob_id : t -> Jmap_id.t option
-
val size : t -> Jmap_primitives.UnsignedInt.t
+
val blob_id : t -> Id.t option
+
val size : t -> Primitives.UnsignedInt.t
val headers : t -> EmailHeader.t list
val name : t -> string option
val type_ : t -> string
···
(** Constructor *)
val v :
?part_id:string ->
-
?blob_id:Jmap_id.t ->
-
size:Jmap_primitives.UnsignedInt.t ->
+
?blob_id:Id.t ->
+
size:Primitives.UnsignedInt.t ->
headers:EmailHeader.t list ->
?name:string ->
type_:string ->
···
(** Email object type (RFC 8621 Section 4.1) *)
type t = {
-
id : Jmap_id.t;
-
blob_id : Jmap_id.t;
-
thread_id : Jmap_id.t;
-
mailbox_ids : (Jmap_id.t * bool) list;
+
id : Id.t;
+
blob_id : Id.t;
+
thread_id : Id.t;
+
mailbox_ids : (Id.t * bool) list;
keywords : (string * bool) list;
-
size : Jmap_primitives.UnsignedInt.t;
-
received_at : Jmap_primitives.UTCDate.t;
+
size : Primitives.UnsignedInt.t;
+
received_at : Primitives.UTCDate.t;
message_id : string list option;
in_reply_to : string list option;
references : string list option;
···
bcc : EmailAddress.t list option;
reply_to : EmailAddress.t list option;
subject : string option;
-
sent_at : Jmap_primitives.Date.t option;
+
sent_at : Primitives.Date.t option;
body_structure : BodyPart.t option;
body_values : (string * BodyValue.t) list option;
text_body : BodyPart.t list option;
···
}
(** Accessors *)
-
val id : t -> Jmap_id.t
-
val blob_id : t -> Jmap_id.t
-
val thread_id : t -> Jmap_id.t
-
val mailbox_ids : t -> (Jmap_id.t * bool) list
+
val id : t -> Id.t
+
val blob_id : t -> Id.t
+
val thread_id : t -> Id.t
+
val mailbox_ids : t -> (Id.t * bool) list
val keywords : t -> (string * bool) list
-
val size : t -> Jmap_primitives.UnsignedInt.t
-
val received_at : t -> Jmap_primitives.UTCDate.t
+
val size : t -> Primitives.UnsignedInt.t
+
val received_at : t -> Primitives.UTCDate.t
val message_id : t -> string list option
val in_reply_to : t -> string list option
val references : t -> string list option
···
val bcc : t -> EmailAddress.t list option
val reply_to : t -> EmailAddress.t list option
val subject : t -> string option
-
val sent_at : t -> Jmap_primitives.Date.t option
+
val sent_at : t -> Primitives.Date.t option
val body_structure : t -> BodyPart.t option
val body_values : t -> (string * BodyValue.t) list option
val text_body : t -> BodyPart.t list option
···
(** Constructor *)
val v :
-
id:Jmap_id.t ->
-
blob_id:Jmap_id.t ->
-
thread_id:Jmap_id.t ->
-
mailbox_ids:(Jmap_id.t * bool) list ->
+
id:Id.t ->
+
blob_id:Id.t ->
+
thread_id:Id.t ->
+
mailbox_ids:(Id.t * bool) list ->
keywords:(string * bool) list ->
-
size:Jmap_primitives.UnsignedInt.t ->
-
received_at:Jmap_primitives.UTCDate.t ->
+
size:Primitives.UnsignedInt.t ->
+
received_at:Primitives.UTCDate.t ->
?message_id:string list ->
?in_reply_to:string list ->
?references:string list ->
···
?bcc:EmailAddress.t list ->
?reply_to:EmailAddress.t list ->
?subject:string ->
-
?sent_at:Jmap_primitives.Date.t ->
+
?sent_at:Primitives.Date.t ->
?body_structure:BodyPart.t ->
?body_values:(string * BodyValue.t) list ->
?text_body:BodyPart.t list ->
···
(** Email-specific filter for /query *)
module Filter : sig
type t = {
-
in_mailbox : Jmap_id.t option;
-
in_mailbox_other_than : Jmap_id.t list option;
-
before : Jmap_primitives.UTCDate.t option;
-
after : Jmap_primitives.UTCDate.t option;
-
min_size : Jmap_primitives.UnsignedInt.t option;
-
max_size : Jmap_primitives.UnsignedInt.t option;
+
in_mailbox : Id.t option;
+
in_mailbox_other_than : Id.t list option;
+
before : Primitives.UTCDate.t option;
+
after : Primitives.UTCDate.t option;
+
min_size : Primitives.UnsignedInt.t option;
+
max_size : Primitives.UnsignedInt.t option;
all_in_thread_have_keyword : string option;
some_in_thread_have_keyword : string option;
none_in_thread_have_keyword : string option;
···
}
(** Accessors *)
-
val in_mailbox : t -> Jmap_id.t option
-
val in_mailbox_other_than : t -> Jmap_id.t list option
-
val before : t -> Jmap_primitives.UTCDate.t option
-
val after : t -> Jmap_primitives.UTCDate.t option
-
val min_size : t -> Jmap_primitives.UnsignedInt.t option
-
val max_size : t -> Jmap_primitives.UnsignedInt.t option
+
val in_mailbox : t -> Id.t option
+
val in_mailbox_other_than : t -> Id.t list option
+
val before : t -> Primitives.UTCDate.t option
+
val after : t -> Primitives.UTCDate.t option
+
val min_size : t -> Primitives.UnsignedInt.t option
+
val max_size : t -> Primitives.UnsignedInt.t option
val all_in_thread_have_keyword : t -> string option
val some_in_thread_have_keyword : t -> string option
val none_in_thread_have_keyword : t -> string option
···
(** Constructor *)
val v :
-
?in_mailbox:Jmap_id.t ->
-
?in_mailbox_other_than:Jmap_id.t list ->
-
?before:Jmap_primitives.UTCDate.t ->
-
?after:Jmap_primitives.UTCDate.t ->
-
?min_size:Jmap_primitives.UnsignedInt.t ->
-
?max_size:Jmap_primitives.UnsignedInt.t ->
+
?in_mailbox:Id.t ->
+
?in_mailbox_other_than:Id.t list ->
+
?before:Primitives.UTCDate.t ->
+
?after:Primitives.UTCDate.t ->
+
?min_size:Primitives.UnsignedInt.t ->
+
?max_size:Primitives.UnsignedInt.t ->
?all_in_thread_have_keyword:string ->
?some_in_thread_have_keyword:string ->
?none_in_thread_have_keyword:string ->
···
(** Standard /get method *)
module Get : sig
type request = {
-
account_id : Jmap_id.t;
-
ids : Jmap_id.t list option;
+
account_id : Id.t;
+
ids : Id.t list option;
properties : string list option;
body_properties : string list option;
fetch_text_body_values : bool option;
fetch_html_body_values : bool option;
fetch_all_body_values : bool option;
-
max_body_value_bytes : Jmap_primitives.UnsignedInt.t option;
+
max_body_value_bytes : Primitives.UnsignedInt.t option;
}
-
type response = t Jmap_standard_methods.Get.response
+
type response = t Standard_methods.Get.response
(** Accessors for request *)
-
val account_id : request -> Jmap_id.t
-
val ids : request -> Jmap_id.t list option
+
val account_id : request -> Id.t
+
val ids : request -> Id.t list option
val properties : request -> string list option
val body_properties : request -> string list option
val fetch_text_body_values : request -> bool option
val fetch_html_body_values : request -> bool option
val fetch_all_body_values : request -> bool option
-
val max_body_value_bytes : request -> Jmap_primitives.UnsignedInt.t option
+
val max_body_value_bytes : request -> Primitives.UnsignedInt.t option
(** Constructor for request *)
val request_v :
-
account_id:Jmap_id.t ->
-
?ids:Jmap_id.t list ->
+
account_id:Id.t ->
+
?ids:Id.t list ->
?properties:string list ->
?body_properties:string list ->
?fetch_text_body_values:bool ->
?fetch_html_body_values:bool ->
?fetch_all_body_values:bool ->
-
?max_body_value_bytes:Jmap_primitives.UnsignedInt.t ->
+
?max_body_value_bytes:Primitives.UnsignedInt.t ->
unit ->
request
···
(** Standard /changes method *)
module Changes : sig
-
type request = Jmap_standard_methods.Changes.request
-
type response = Jmap_standard_methods.Changes.response
+
type request = Standard_methods.Changes.request
+
type response = Standard_methods.Changes.response
val request_of_json : Ezjsonm.value -> request
val response_of_json : Ezjsonm.value -> response
···
(** Standard /query method *)
module Query : sig
type request = {
-
account_id : Jmap_id.t;
-
filter : Filter.t Jmap_filter.t option;
-
sort : Jmap_comparator.t list option;
-
position : Jmap_primitives.Int53.t option;
-
anchor : Jmap_id.t option;
-
anchor_offset : Jmap_primitives.Int53.t option;
-
limit : Jmap_primitives.UnsignedInt.t option;
+
account_id : Id.t;
+
filter : Filter.t Jmap_core.Filter.t option;
+
sort : Comparator.t list option;
+
position : Primitives.Int53.t option;
+
anchor : Id.t option;
+
anchor_offset : Primitives.Int53.t option;
+
limit : Primitives.UnsignedInt.t option;
calculate_total : bool option;
collapse_threads : bool option;
}
-
type response = Jmap_standard_methods.Query.response
+
type response = Standard_methods.Query.response
(** Accessors for request *)
-
val account_id : request -> Jmap_id.t
-
val filter : request -> Filter.t Jmap_filter.t option
-
val sort : request -> Jmap_comparator.t list option
-
val position : request -> Jmap_primitives.Int53.t option
-
val anchor : request -> Jmap_id.t option
-
val anchor_offset : request -> Jmap_primitives.Int53.t option
-
val limit : request -> Jmap_primitives.UnsignedInt.t option
+
val account_id : request -> Id.t
+
val filter : request -> Filter.t Jmap_core.Filter.t option
+
val sort : request -> Comparator.t list option
+
val position : request -> Primitives.Int53.t option
+
val anchor : request -> Id.t option
+
val anchor_offset : request -> Primitives.Int53.t option
+
val limit : request -> Primitives.UnsignedInt.t option
val calculate_total : request -> bool option
val collapse_threads : request -> bool option
(** Constructor for request *)
val request_v :
-
account_id:Jmap_id.t ->
-
?filter:Filter.t Jmap_filter.t ->
-
?sort:Jmap_comparator.t list ->
-
?position:Jmap_primitives.Int53.t ->
-
?anchor:Jmap_id.t ->
-
?anchor_offset:Jmap_primitives.Int53.t ->
-
?limit:Jmap_primitives.UnsignedInt.t ->
+
account_id:Id.t ->
+
?filter:Filter.t Jmap_core.Filter.t ->
+
?sort:Comparator.t list ->
+
?position:Primitives.Int53.t ->
+
?anchor:Id.t ->
+
?anchor_offset:Primitives.Int53.t ->
+
?limit:Primitives.UnsignedInt.t ->
?calculate_total:bool ->
?collapse_threads:bool ->
unit ->
···
(** Standard /queryChanges method *)
module QueryChanges : sig
type request = {
-
account_id : Jmap_id.t;
-
filter : Filter.t Jmap_filter.t option;
-
sort : Jmap_comparator.t list option;
+
account_id : Id.t;
+
filter : Filter.t Jmap_core.Filter.t option;
+
sort : Comparator.t list option;
since_query_state : string;
-
max_changes : Jmap_primitives.UnsignedInt.t option;
-
up_to_id : Jmap_id.t option;
+
max_changes : Primitives.UnsignedInt.t option;
+
up_to_id : Id.t option;
calculate_total : bool option;
collapse_threads : bool option;
}
-
type response = Jmap_standard_methods.QueryChanges.response
+
type response = Standard_methods.QueryChanges.response
(** Accessors for request *)
-
val account_id : request -> Jmap_id.t
-
val filter : request -> Filter.t Jmap_filter.t option
-
val sort : request -> Jmap_comparator.t list option
+
val account_id : request -> Id.t
+
val filter : request -> Filter.t Jmap_core.Filter.t option
+
val sort : request -> Comparator.t list option
val since_query_state : request -> string
-
val max_changes : request -> Jmap_primitives.UnsignedInt.t option
-
val up_to_id : request -> Jmap_id.t option
+
val max_changes : request -> Primitives.UnsignedInt.t option
+
val up_to_id : request -> Id.t option
val calculate_total : request -> bool option
val collapse_threads : request -> bool option
(** Constructor for request *)
val request_v :
-
account_id:Jmap_id.t ->
-
?filter:Filter.t Jmap_filter.t ->
-
?sort:Jmap_comparator.t list ->
+
account_id:Id.t ->
+
?filter:Filter.t Jmap_core.Filter.t ->
+
?sort:Comparator.t list ->
since_query_state:string ->
-
?max_changes:Jmap_primitives.UnsignedInt.t ->
-
?up_to_id:Jmap_id.t ->
+
?max_changes:Primitives.UnsignedInt.t ->
+
?up_to_id:Id.t ->
?calculate_total:bool ->
?collapse_threads:bool ->
unit ->
···
(** Standard /set method *)
module Set : sig
-
type request = t Jmap_standard_methods.Set.request
-
type response = t Jmap_standard_methods.Set.response
+
type request = t Standard_methods.Set.request
+
type response = t Standard_methods.Set.response
val request_of_json : Ezjsonm.value -> request
val response_of_json : Ezjsonm.value -> response
···
(** Standard /copy method *)
module Copy : sig
-
type request = t Jmap_standard_methods.Copy.request
-
type response = t Jmap_standard_methods.Copy.response
+
type request = t Standard_methods.Copy.request
+
type response = t Standard_methods.Copy.response
val request_of_json : Ezjsonm.value -> request
val response_of_json : Ezjsonm.value -> response
···
module Import : sig
(** Email import request object *)
type import_email = {
-
blob_id : Jmap_id.t;
-
mailbox_ids : (Jmap_id.t * bool) list;
+
blob_id : Id.t;
+
mailbox_ids : (Id.t * bool) list;
keywords : (string * bool) list;
-
received_at : Jmap_primitives.UTCDate.t option;
+
received_at : Primitives.UTCDate.t option;
}
type request = {
-
account_id : Jmap_id.t;
+
account_id : Id.t;
if_in_state : string option;
-
emails : (Jmap_id.t * import_email) list;
+
emails : (Id.t * import_email) list;
}
type response = {
-
account_id : Jmap_id.t;
+
account_id : Id.t;
old_state : string option;
new_state : string;
-
created : (Jmap_id.t * t) list option;
-
not_created : (Jmap_id.t * Jmap_error.set_error_detail) list option;
+
created : (Id.t * t) list option;
+
not_created : (Id.t * Error.set_error_detail) list option;
}
(** Accessors for import_email *)
-
val import_blob_id : import_email -> Jmap_id.t
-
val import_mailbox_ids : import_email -> (Jmap_id.t * bool) list
+
val import_blob_id : import_email -> Id.t
+
val import_mailbox_ids : import_email -> (Id.t * bool) list
val import_keywords : import_email -> (string * bool) list
-
val import_received_at : import_email -> Jmap_primitives.UTCDate.t option
+
val import_received_at : import_email -> Primitives.UTCDate.t option
(** Constructor for import_email *)
val import_email_v :
-
blob_id:Jmap_id.t ->
-
mailbox_ids:(Jmap_id.t * bool) list ->
+
blob_id:Id.t ->
+
mailbox_ids:(Id.t * bool) list ->
keywords:(string * bool) list ->
-
?received_at:Jmap_primitives.UTCDate.t ->
+
?received_at:Primitives.UTCDate.t ->
unit ->
import_email
(** Accessors for request *)
-
val account_id : request -> Jmap_id.t
+
val account_id : request -> Id.t
val if_in_state : request -> string option
-
val emails : request -> (Jmap_id.t * import_email) list
+
val emails : request -> (Id.t * import_email) list
(** Constructor for request *)
val request_v :
-
account_id:Jmap_id.t ->
+
account_id:Id.t ->
?if_in_state:string ->
-
emails:(Jmap_id.t * import_email) list ->
+
emails:(Id.t * import_email) list ->
unit ->
request
(** Accessors for response *)
-
val response_account_id : response -> Jmap_id.t
+
val response_account_id : response -> Id.t
val old_state : response -> string option
val new_state : response -> string
-
val created : response -> (Jmap_id.t * t) list option
-
val not_created : response -> (Jmap_id.t * Jmap_error.set_error_detail) list option
+
val created : response -> (Id.t * t) list option
+
val not_created : response -> (Id.t * Error.set_error_detail) list option
(** Constructor for response *)
val response_v :
-
account_id:Jmap_id.t ->
+
account_id:Id.t ->
?old_state:string ->
new_state:string ->
-
?created:(Jmap_id.t * t) list ->
-
?not_created:(Jmap_id.t * Jmap_error.set_error_detail) list ->
+
?created:(Id.t * t) list ->
+
?not_created:(Id.t * Error.set_error_detail) list ->
unit ->
response
···
(** Email/parse method *)
module Parse : sig
type request = {
-
account_id : Jmap_id.t;
-
blob_ids : Jmap_id.t list;
+
account_id : Id.t;
+
blob_ids : Id.t list;
properties : string list option;
body_properties : string list option;
fetch_text_body_values : bool option;
fetch_html_body_values : bool option;
fetch_all_body_values : bool option;
-
max_body_value_bytes : Jmap_primitives.UnsignedInt.t option;
+
max_body_value_bytes : Primitives.UnsignedInt.t option;
}
type response = {
-
account_id : Jmap_id.t;
-
parsed : (Jmap_id.t * t) list option;
-
not_parsable : Jmap_id.t list option;
-
not_found : Jmap_id.t list option;
+
account_id : Id.t;
+
parsed : (Id.t * t) list option;
+
not_parsable : Id.t list option;
+
not_found : Id.t list option;
}
(** Accessors for request *)
-
val account_id : request -> Jmap_id.t
-
val blob_ids : request -> Jmap_id.t list
+
val account_id : request -> Id.t
+
val blob_ids : request -> Id.t list
val properties : request -> string list option
val body_properties : request -> string list option
val fetch_text_body_values : request -> bool option
val fetch_html_body_values : request -> bool option
val fetch_all_body_values : request -> bool option
-
val max_body_value_bytes : request -> Jmap_primitives.UnsignedInt.t option
+
val max_body_value_bytes : request -> Primitives.UnsignedInt.t option
(** Constructor for request *)
val request_v :
-
account_id:Jmap_id.t ->
-
blob_ids:Jmap_id.t list ->
+
account_id:Id.t ->
+
blob_ids:Id.t list ->
?properties:string list ->
?body_properties:string list ->
?fetch_text_body_values:bool ->
?fetch_html_body_values:bool ->
?fetch_all_body_values:bool ->
-
?max_body_value_bytes:Jmap_primitives.UnsignedInt.t ->
+
?max_body_value_bytes:Primitives.UnsignedInt.t ->
unit ->
request
(** Accessors for response *)
-
val response_account_id : response -> Jmap_id.t
-
val parsed : response -> (Jmap_id.t * t) list option
-
val not_parsable : response -> Jmap_id.t list option
-
val not_found : response -> Jmap_id.t list option
+
val response_account_id : response -> Id.t
+
val parsed : response -> (Id.t * t) list option
+
val not_parsable : response -> Id.t list option
+
val not_found : response -> Id.t list option
(** Constructor for response *)
val response_v :
-
account_id:Jmap_id.t ->
-
?parsed:(Jmap_id.t * t) list ->
-
?not_parsable:Jmap_id.t list ->
-
?not_found:Jmap_id.t list ->
+
account_id:Id.t ->
+
?parsed:(Id.t * t) list ->
+
?not_parsable:Id.t list ->
+
?not_found:Id.t list ->
unit ->
response
+47 -47
stack/jmap/jmap-mail/jmap_email_submission.ml
···
}
*)
let of_json _json =
-
raise (Jmap_core.Jmap_error.Parse_error "Address.of_json not yet implemented")
+
raise (Jmap_core.Error.Parse_error "Address.of_json not yet implemented")
let to_json _t =
-
raise (Jmap_core.Jmap_error.Parse_error "Address.to_json not yet implemented")
+
raise (Jmap_core.Error.Parse_error "Address.to_json not yet implemented")
end
(** SMTP Envelope (RFC 8621 Section 7.1.1) *)
···
}
*)
let of_json _json =
-
raise (Jmap_core.Jmap_error.Parse_error "Envelope.of_json not yet implemented")
+
raise (Jmap_core.Error.Parse_error "Envelope.of_json not yet implemented")
let to_json _t =
-
raise (Jmap_core.Jmap_error.Parse_error "Envelope.to_json not yet implemented")
+
raise (Jmap_core.Error.Parse_error "Envelope.to_json not yet implemented")
end
(** Delivery status for a single recipient (RFC 8621 Section 7.1.4) *)
···
}
*)
let of_json _json =
-
raise (Jmap_core.Jmap_error.Parse_error "DeliveryStatus.of_json not yet implemented")
+
raise (Jmap_core.Error.Parse_error "DeliveryStatus.of_json not yet implemented")
let to_json _t =
-
raise (Jmap_core.Jmap_error.Parse_error "DeliveryStatus.to_json not yet implemented")
+
raise (Jmap_core.Error.Parse_error "DeliveryStatus.to_json not yet implemented")
let delivered_of_string = function
| "queued" -> Queued
···
(** EmailSubmission object type (RFC 8621 Section 7.1) *)
type t = {
-
id : Jmap_core.Jmap_id.t; (** Immutable server-assigned id *)
-
identity_id : Jmap_core.Jmap_id.t; (** Identity to send from *)
-
email_id : Jmap_core.Jmap_id.t; (** Email to send *)
-
thread_id : Jmap_core.Jmap_id.t; (** Thread ID of email *)
+
id : Jmap_core.Id.t; (** Immutable server-assigned id *)
+
identity_id : Jmap_core.Id.t; (** Identity to send from *)
+
email_id : Jmap_core.Id.t; (** Email to send *)
+
thread_id : Jmap_core.Id.t; (** Thread ID of email *)
envelope : Envelope.t option; (** SMTP envelope (null = derive from headers) *)
-
send_at : Jmap_core.Jmap_primitives.UTCDate.t; (** When to send (may be in future) *)
+
send_at : Jmap_core.Primitives.UTCDate.t; (** When to send (may be in future) *)
undo_status : undo_status; (** Whether message can be cancelled *)
delivery_status : (string * DeliveryStatus.t) list option; (** Map of email to delivery status *)
-
dsn_blob_ids : Jmap_core.Jmap_id.t list; (** Blob IDs of received DSN messages *)
-
mdn_blob_ids : Jmap_core.Jmap_id.t list; (** Blob IDs of received MDN messages *)
+
dsn_blob_ids : Jmap_core.Id.t list; (** Blob IDs of received DSN messages *)
+
mdn_blob_ids : Jmap_core.Id.t list; (** Blob IDs of received MDN messages *)
}
(** Accessors *)
···
(** Standard /get method (RFC 8621 Section 7.2) *)
module Get = struct
-
type request = t Jmap_core.Jmap_standard_methods.Get.request
-
type response = t Jmap_core.Jmap_standard_methods.Get.response
+
type request = t Jmap_core.Standard_methods.Get.request
+
type response = t Jmap_core.Standard_methods.Get.response
(** Parse get request from JSON.
Test files: test/data/mail/email_submission_get_request.json
···
}
*)
let request_of_json _json =
-
raise (Jmap_core.Jmap_error.Parse_error "EmailSubmission.Get.request_of_json not yet implemented")
+
raise (Jmap_core.Error.Parse_error "EmailSubmission.Get.request_of_json not yet implemented")
(** Parse get response from JSON.
Test files: test/data/mail/email_submission_get_response.json
···
}
*)
let response_of_json _json =
-
raise (Jmap_core.Jmap_error.Parse_error "EmailSubmission.Get.response_of_json not yet implemented")
+
raise (Jmap_core.Error.Parse_error "EmailSubmission.Get.response_of_json not yet implemented")
end
(** Standard /changes method (RFC 8621 Section 7.3) *)
module Changes = struct
-
type request = Jmap_core.Jmap_standard_methods.Changes.request
-
type response = Jmap_core.Jmap_standard_methods.Changes.response
+
type request = Jmap_core.Standard_methods.Changes.request
+
type response = Jmap_core.Standard_methods.Changes.response
let request_of_json _json =
-
raise (Jmap_core.Jmap_error.Parse_error "EmailSubmission.Changes.request_of_json not yet implemented")
+
raise (Jmap_core.Error.Parse_error "EmailSubmission.Changes.request_of_json not yet implemented")
let response_of_json _json =
-
raise (Jmap_core.Jmap_error.Parse_error "EmailSubmission.Changes.response_of_json not yet implemented")
+
raise (Jmap_core.Error.Parse_error "EmailSubmission.Changes.response_of_json not yet implemented")
end
(** EmailSubmission-specific filter for /query (RFC 8621 Section 7.5) *)
module Filter = struct
type t = {
-
identity_ids : Jmap_core.Jmap_id.t list option; (** Submission uses one of these identities *)
-
email_ids : Jmap_core.Jmap_id.t list option; (** Submission is for one of these emails *)
-
thread_ids : Jmap_core.Jmap_id.t list option; (** Submission is for email in one of these threads *)
+
identity_ids : Jmap_core.Id.t list option; (** Submission uses one of these identities *)
+
email_ids : Jmap_core.Id.t list option; (** Submission is for one of these emails *)
+
thread_ids : Jmap_core.Id.t list option; (** Submission is for email in one of these threads *)
undo_status : undo_status option; (** undoStatus equals this *)
-
before : Jmap_core.Jmap_primitives.UTCDate.t option; (** sendAt < this *)
-
after : Jmap_core.Jmap_primitives.UTCDate.t option; (** sendAt >= this *)
+
before : Jmap_core.Primitives.UTCDate.t option; (** sendAt < this *)
+
after : Jmap_core.Primitives.UTCDate.t option; (** sendAt >= this *)
}
(** Accessors *)
···
{ identity_ids; email_ids; thread_ids; undo_status; before; after }
let of_json _json =
-
raise (Jmap_core.Jmap_error.Parse_error "EmailSubmission.Filter.of_json not yet implemented")
+
raise (Jmap_core.Error.Parse_error "EmailSubmission.Filter.of_json not yet implemented")
end
(** Standard /query method (RFC 8621 Section 7.5) *)
module Query = struct
-
type request = Filter.t Jmap_core.Jmap_standard_methods.Query.request
-
type response = Jmap_core.Jmap_standard_methods.Query.response
+
type request = Filter.t Jmap_core.Standard_methods.Query.request
+
type response = Jmap_core.Standard_methods.Query.response
let request_of_json _json =
-
raise (Jmap_core.Jmap_error.Parse_error "EmailSubmission.Query.request_of_json not yet implemented")
+
raise (Jmap_core.Error.Parse_error "EmailSubmission.Query.request_of_json not yet implemented")
let response_of_json _json =
-
raise (Jmap_core.Jmap_error.Parse_error "EmailSubmission.Query.response_of_json not yet implemented")
+
raise (Jmap_core.Error.Parse_error "EmailSubmission.Query.response_of_json not yet implemented")
end
(** Standard /queryChanges method (RFC 8621 Section 7.6) *)
module QueryChanges = struct
-
type request = Filter.t Jmap_core.Jmap_standard_methods.QueryChanges.request
-
type response = Jmap_core.Jmap_standard_methods.QueryChanges.response
+
type request = Filter.t Jmap_core.Standard_methods.QueryChanges.request
+
type response = Jmap_core.Standard_methods.QueryChanges.response
let request_of_json _json =
-
raise (Jmap_core.Jmap_error.Parse_error "EmailSubmission.QueryChanges.request_of_json not yet implemented")
+
raise (Jmap_core.Error.Parse_error "EmailSubmission.QueryChanges.request_of_json not yet implemented")
let response_of_json _json =
-
raise (Jmap_core.Jmap_error.Parse_error "EmailSubmission.QueryChanges.response_of_json not yet implemented")
+
raise (Jmap_core.Error.Parse_error "EmailSubmission.QueryChanges.response_of_json not yet implemented")
end
(** Standard /set method (RFC 8621 Section 7.4)
···
module Set = struct
(** On success action for EmailSubmission/set create *)
type on_success = {
-
set_email_keywords : (Jmap_core.Jmap_id.t * (string * bool) list) option; (** Set keywords on sent email *)
+
set_email_keywords : (Jmap_core.Id.t * (string * bool) list) option; (** Set keywords on sent email *)
}
type request = {
-
account_id : Jmap_core.Jmap_id.t;
+
account_id : Jmap_core.Id.t;
if_in_state : string option;
-
create : (Jmap_core.Jmap_id.t * t) list option;
-
update : (Jmap_core.Jmap_id.t * Jmap_core.Jmap_standard_methods.Set.patch_object) list option;
-
destroy : Jmap_core.Jmap_id.t list option;
+
create : (Jmap_core.Id.t * t) list option;
+
update : (Jmap_core.Id.t * Jmap_core.Standard_methods.Set.patch_object) list option;
+
destroy : Jmap_core.Id.t list option;
(* EmailSubmission-specific *)
-
on_success_update_email : (Jmap_core.Jmap_id.t * on_success) list option; (** Actions to perform on success *)
-
on_success_destroy_email : Jmap_core.Jmap_id.t list option; (** Email IDs to destroy on success *)
+
on_success_update_email : (Jmap_core.Id.t * on_success) list option; (** Actions to perform on success *)
+
on_success_destroy_email : Jmap_core.Id.t list option; (** Email IDs to destroy on success *)
}
-
type response = t Jmap_core.Jmap_standard_methods.Set.response
+
type response = t Jmap_core.Standard_methods.Set.response
(** Accessors for on_success *)
let on_success_set_email_keywords os = os.set_email_keywords
···
on_success_update_email; on_success_destroy_email }
let request_of_json _json =
-
raise (Jmap_core.Jmap_error.Parse_error "EmailSubmission.Set.request_of_json not yet implemented")
+
raise (Jmap_core.Error.Parse_error "EmailSubmission.Set.request_of_json not yet implemented")
let response_of_json _json =
-
raise (Jmap_core.Jmap_error.Parse_error "EmailSubmission.Set.response_of_json not yet implemented")
+
raise (Jmap_core.Error.Parse_error "EmailSubmission.Set.response_of_json not yet implemented")
end
(** Parser submodule *)
···
*)
let of_json _json =
(* TODO: Implement JSON parsing *)
-
raise (Jmap_core.Jmap_error.Parse_error "EmailSubmission.Parser.of_json not yet implemented")
+
raise (Jmap_core.Error.Parse_error "EmailSubmission.Parser.of_json not yet implemented")
let to_json _t =
(* TODO: Implement JSON serialization *)
-
raise (Jmap_core.Jmap_error.Parse_error "EmailSubmission.Parser.to_json not yet implemented")
+
raise (Jmap_core.Error.Parse_error "EmailSubmission.Parser.to_json not yet implemented")
end
(** Helper functions for undo_status *)
+66 -66
stack/jmap/jmap-mail/jmap_email_submission.mli
···
(** EmailSubmission object type (RFC 8621 Section 7.1) *)
type t = {
-
id : Jmap_id.t;
-
identity_id : Jmap_id.t;
-
email_id : Jmap_id.t;
-
thread_id : Jmap_id.t;
+
id : Id.t;
+
identity_id : Id.t;
+
email_id : Id.t;
+
thread_id : Id.t;
envelope : Envelope.t option;
-
send_at : Jmap_primitives.UTCDate.t;
+
send_at : Primitives.UTCDate.t;
undo_status : undo_status;
delivery_status : (string * DeliveryStatus.t) list option;
-
dsn_blob_ids : Jmap_id.t list;
-
mdn_blob_ids : Jmap_id.t list;
+
dsn_blob_ids : Id.t list;
+
mdn_blob_ids : Id.t list;
}
(** Accessors *)
-
val id : t -> Jmap_id.t
-
val identity_id : t -> Jmap_id.t
-
val email_id : t -> Jmap_id.t
-
val thread_id : t -> Jmap_id.t
+
val id : t -> Id.t
+
val identity_id : t -> Id.t
+
val email_id : t -> Id.t
+
val thread_id : t -> Id.t
val envelope : t -> Envelope.t option
-
val send_at : t -> Jmap_primitives.UTCDate.t
+
val send_at : t -> Primitives.UTCDate.t
val undo_status : t -> undo_status
val delivery_status : t -> (string * DeliveryStatus.t) list option
-
val dsn_blob_ids : t -> Jmap_id.t list
-
val mdn_blob_ids : t -> Jmap_id.t list
+
val dsn_blob_ids : t -> Id.t list
+
val mdn_blob_ids : t -> Id.t list
(** Constructor *)
val v :
-
id:Jmap_id.t ->
-
identity_id:Jmap_id.t ->
-
email_id:Jmap_id.t ->
-
thread_id:Jmap_id.t ->
+
id:Id.t ->
+
identity_id:Id.t ->
+
email_id:Id.t ->
+
thread_id:Id.t ->
?envelope:Envelope.t ->
-
send_at:Jmap_primitives.UTCDate.t ->
+
send_at:Primitives.UTCDate.t ->
undo_status:undo_status ->
?delivery_status:(string * DeliveryStatus.t) list ->
-
dsn_blob_ids:Jmap_id.t list ->
-
mdn_blob_ids:Jmap_id.t list ->
+
dsn_blob_ids:Id.t list ->
+
mdn_blob_ids:Id.t list ->
unit ->
t
(** Standard /get method *)
module Get : sig
-
type request = t Jmap_standard_methods.Get.request
-
type response = t Jmap_standard_methods.Get.response
+
type request = t Standard_methods.Get.request
+
type response = t Standard_methods.Get.response
val request_of_json : Ezjsonm.value -> request
val response_of_json : Ezjsonm.value -> response
···
(** Standard /changes method *)
module Changes : sig
-
type request = Jmap_standard_methods.Changes.request
-
type response = Jmap_standard_methods.Changes.response
+
type request = Standard_methods.Changes.request
+
type response = Standard_methods.Changes.response
val request_of_json : Ezjsonm.value -> request
val response_of_json : Ezjsonm.value -> response
···
(** EmailSubmission-specific filter for /query *)
module Filter : sig
type t = {
-
identity_ids : Jmap_id.t list option;
-
email_ids : Jmap_id.t list option;
-
thread_ids : Jmap_id.t list option;
+
identity_ids : Id.t list option;
+
email_ids : Id.t list option;
+
thread_ids : Id.t list option;
undo_status : undo_status option;
-
before : Jmap_primitives.UTCDate.t option;
-
after : Jmap_primitives.UTCDate.t option;
+
before : Primitives.UTCDate.t option;
+
after : Primitives.UTCDate.t option;
}
(** Accessors *)
-
val identity_ids : t -> Jmap_id.t list option
-
val email_ids : t -> Jmap_id.t list option
-
val thread_ids : t -> Jmap_id.t list option
+
val identity_ids : t -> Id.t list option
+
val email_ids : t -> Id.t list option
+
val thread_ids : t -> Id.t list option
val undo_status : t -> undo_status option
-
val before : t -> Jmap_primitives.UTCDate.t option
-
val after : t -> Jmap_primitives.UTCDate.t option
+
val before : t -> Primitives.UTCDate.t option
+
val after : t -> Primitives.UTCDate.t option
(** Constructor *)
val v :
-
?identity_ids:Jmap_id.t list ->
-
?email_ids:Jmap_id.t list ->
-
?thread_ids:Jmap_id.t list ->
+
?identity_ids:Id.t list ->
+
?email_ids:Id.t list ->
+
?thread_ids:Id.t list ->
?undo_status:undo_status ->
-
?before:Jmap_primitives.UTCDate.t ->
-
?after:Jmap_primitives.UTCDate.t ->
+
?before:Primitives.UTCDate.t ->
+
?after:Primitives.UTCDate.t ->
unit ->
t
···
(** Standard /query method *)
module Query : sig
-
type request = Filter.t Jmap_standard_methods.Query.request
-
type response = Jmap_standard_methods.Query.response
+
type request = Filter.t Standard_methods.Query.request
+
type response = Standard_methods.Query.response
val request_of_json : Ezjsonm.value -> request
val response_of_json : Ezjsonm.value -> response
···
(** Standard /queryChanges method *)
module QueryChanges : sig
-
type request = Filter.t Jmap_standard_methods.QueryChanges.request
-
type response = Jmap_standard_methods.QueryChanges.response
+
type request = Filter.t Standard_methods.QueryChanges.request
+
type response = Standard_methods.QueryChanges.response
val request_of_json : Ezjsonm.value -> request
val response_of_json : Ezjsonm.value -> response
···
module Set : sig
(** On success action for EmailSubmission/set create *)
type on_success = {
-
set_email_keywords : (Jmap_id.t * (string * bool) list) option;
+
set_email_keywords : (Id.t * (string * bool) list) option;
}
type request = {
-
account_id : Jmap_id.t;
+
account_id : Id.t;
if_in_state : string option;
-
create : (Jmap_id.t * t) list option;
-
update : (Jmap_id.t * Jmap_standard_methods.Set.patch_object) list option;
-
destroy : Jmap_id.t list option;
-
on_success_update_email : (Jmap_id.t * on_success) list option;
-
on_success_destroy_email : Jmap_id.t list option;
+
create : (Id.t * t) list option;
+
update : (Id.t * Standard_methods.Set.patch_object) list option;
+
destroy : Id.t list option;
+
on_success_update_email : (Id.t * on_success) list option;
+
on_success_destroy_email : Id.t list option;
}
-
type response = t Jmap_standard_methods.Set.response
+
type response = t Standard_methods.Set.response
(** Accessors for on_success *)
-
val on_success_set_email_keywords : on_success -> (Jmap_id.t * (string * bool) list) option
+
val on_success_set_email_keywords : on_success -> (Id.t * (string * bool) list) option
(** Constructor for on_success *)
val on_success_v :
-
?set_email_keywords:(Jmap_id.t * (string * bool) list) ->
+
?set_email_keywords:(Id.t * (string * bool) list) ->
unit ->
on_success
(** Accessors for request *)
-
val account_id : request -> Jmap_id.t
+
val account_id : request -> Id.t
val if_in_state : request -> string option
-
val create : request -> (Jmap_id.t * t) list option
-
val update : request -> (Jmap_id.t * Jmap_standard_methods.Set.patch_object) list option
-
val destroy : request -> Jmap_id.t list option
-
val on_success_update_email : request -> (Jmap_id.t * on_success) list option
-
val on_success_destroy_email : request -> Jmap_id.t list option
+
val create : request -> (Id.t * t) list option
+
val update : request -> (Id.t * Standard_methods.Set.patch_object) list option
+
val destroy : request -> Id.t list option
+
val on_success_update_email : request -> (Id.t * on_success) list option
+
val on_success_destroy_email : request -> Id.t list option
(** Constructor for request *)
val request_v :
-
account_id:Jmap_id.t ->
+
account_id:Id.t ->
?if_in_state:string ->
-
?create:(Jmap_id.t * t) list ->
-
?update:(Jmap_id.t * Jmap_standard_methods.Set.patch_object) list ->
-
?destroy:Jmap_id.t list ->
-
?on_success_update_email:(Jmap_id.t * on_success) list ->
-
?on_success_destroy_email:Jmap_id.t list ->
+
?create:(Id.t * t) list ->
+
?update:(Id.t * Standard_methods.Set.patch_object) list ->
+
?destroy:Id.t list ->
+
?on_success_update_email:(Id.t * on_success) list ->
+
?on_success_destroy_email:Id.t list ->
unit ->
request
+15 -15
stack/jmap/jmap-mail/jmap_identity.ml
···
(** Identity object type (RFC 8621 Section 6.1) *)
type t = {
-
id : Jmap_core.Jmap_id.t; (** Immutable server-assigned id *)
+
id : Jmap_core.Id.t; (** Immutable server-assigned id *)
name : string; (** Display name for this identity (e.g., "Alice Jones") *)
email : string; (** Email address (e.g., "alice@example.com") *)
reply_to : Jmap_email.EmailAddress.t list option; (** Reply-To addresses to use *)
···
controls which identities exist based on account configuration.
*)
module Get = struct
-
type request = t Jmap_core.Jmap_standard_methods.Get.request
-
type response = t Jmap_core.Jmap_standard_methods.Get.response
+
type request = t Jmap_core.Standard_methods.Get.request
+
type response = t Jmap_core.Standard_methods.Get.response
(** Parse get request from JSON.
Test files: test/data/mail/identity_get_request.json
···
}
*)
let request_of_json _json =
-
raise (Jmap_core.Jmap_error.Parse_error "Identity.Get.request_of_json not yet implemented")
+
raise (Jmap_core.Error.Parse_error "Identity.Get.request_of_json not yet implemented")
(** Parse get response from JSON.
Test files: test/data/mail/identity_get_response.json
···
}
*)
let response_of_json _json =
-
raise (Jmap_core.Jmap_error.Parse_error "Identity.Get.response_of_json not yet implemented")
+
raise (Jmap_core.Error.Parse_error "Identity.Get.response_of_json not yet implemented")
end
(** Standard /changes method (RFC 8621 Section 6.3) *)
module Changes = struct
-
type request = Jmap_core.Jmap_standard_methods.Changes.request
-
type response = Jmap_core.Jmap_standard_methods.Changes.response
+
type request = Jmap_core.Standard_methods.Changes.request
+
type response = Jmap_core.Standard_methods.Changes.response
let request_of_json _json =
-
raise (Jmap_core.Jmap_error.Parse_error "Identity.Changes.request_of_json not yet implemented")
+
raise (Jmap_core.Error.Parse_error "Identity.Changes.request_of_json not yet implemented")
let response_of_json _json =
-
raise (Jmap_core.Jmap_error.Parse_error "Identity.Changes.response_of_json not yet implemented")
+
raise (Jmap_core.Error.Parse_error "Identity.Changes.response_of_json not yet implemented")
end
(** Standard /set method (RFC 8621 Section 6.4)
···
are derived from server/account configuration.
*)
module Set = struct
-
type request = t Jmap_core.Jmap_standard_methods.Set.request
-
type response = t Jmap_core.Jmap_standard_methods.Set.response
+
type request = t Jmap_core.Standard_methods.Set.request
+
type response = t Jmap_core.Standard_methods.Set.response
let request_of_json _json =
-
raise (Jmap_core.Jmap_error.Parse_error "Identity.Set.request_of_json not yet implemented")
+
raise (Jmap_core.Error.Parse_error "Identity.Set.request_of_json not yet implemented")
let response_of_json _json =
-
raise (Jmap_core.Jmap_error.Parse_error "Identity.Set.response_of_json not yet implemented")
+
raise (Jmap_core.Error.Parse_error "Identity.Set.response_of_json not yet implemented")
end
(** Parser submodule *)
···
*)
let of_json _json =
(* TODO: Implement JSON parsing *)
-
raise (Jmap_core.Jmap_error.Parse_error "Identity.Parser.of_json not yet implemented")
+
raise (Jmap_core.Error.Parse_error "Identity.Parser.of_json not yet implemented")
let to_json _t =
(* TODO: Implement JSON serialization *)
-
raise (Jmap_core.Jmap_error.Parse_error "Identity.Parser.to_json not yet implemented")
+
raise (Jmap_core.Error.Parse_error "Identity.Parser.to_json not yet implemented")
end
+9 -9
stack/jmap/jmap-mail/jmap_identity.mli
···
(** Identity object type (RFC 8621 Section 6.1) *)
type t = {
-
id : Jmap_id.t;
+
id : Id.t;
name : string;
email : string;
reply_to : Jmap_email.EmailAddress.t list option;
···
}
(** Accessors *)
-
val id : t -> Jmap_id.t
+
val id : t -> Id.t
val name : t -> string
val email : t -> string
val reply_to : t -> Jmap_email.EmailAddress.t list option
···
(** Constructor *)
val v :
-
id:Jmap_id.t ->
+
id:Id.t ->
name:string ->
email:string ->
?reply_to:Jmap_email.EmailAddress.t list ->
···
(** Standard /get method *)
module Get : sig
-
type request = t Jmap_standard_methods.Get.request
-
type response = t Jmap_standard_methods.Get.response
+
type request = t Standard_methods.Get.request
+
type response = t Standard_methods.Get.response
val request_of_json : Ezjsonm.value -> request
val response_of_json : Ezjsonm.value -> response
···
(** Standard /changes method *)
module Changes : sig
-
type request = Jmap_standard_methods.Changes.request
-
type response = Jmap_standard_methods.Changes.response
+
type request = Standard_methods.Changes.request
+
type response = Standard_methods.Changes.response
val request_of_json : Ezjsonm.value -> request
val response_of_json : Ezjsonm.value -> response
···
(** Standard /set method *)
module Set : sig
-
type request = t Jmap_standard_methods.Set.request
-
type response = t Jmap_standard_methods.Set.response
+
type request = t Standard_methods.Set.request
+
type response = t Standard_methods.Set.response
val request_of_json : Ezjsonm.value -> request
val response_of_json : Ezjsonm.value -> response
-11
stack/jmap/jmap-mail/jmap_mail.ml
···
(** JMAP Mail Extension Library *)
-
(** Re-export all submodules *)
module Mailbox = Jmap_mailbox
module Thread = Jmap_thread
module Email = Jmap_email
···
module Vacation_response = Jmap_vacation_response
module Search_snippet = Jmap_search_snippet
module Mail_parser = Jmap_mail_parser
-
-
(** For backwards compatibility *)
-
module Jmap_mailbox = Jmap_mailbox
-
module Jmap_thread = Jmap_thread
-
module Jmap_email = Jmap_email
-
module Jmap_identity = Jmap_identity
-
module Jmap_email_submission = Jmap_email_submission
-
module Jmap_vacation_response = Jmap_vacation_response
-
module Jmap_search_snippet = Jmap_search_snippet
-
module Jmap_mail_parser = Jmap_mail_parser
+8 -9
stack/jmap/jmap-mail/jmap_mail.mli
···
(** JMAP Mail Extension Library *)
-
(** Re-export all submodules *)
-
module Jmap_mailbox = Jmap_mailbox
-
module Jmap_thread = Jmap_thread
-
module Jmap_email = Jmap_email
-
module Jmap_identity = Jmap_identity
-
module Jmap_email_submission = Jmap_email_submission
-
module Jmap_vacation_response = Jmap_vacation_response
-
module Jmap_search_snippet = Jmap_search_snippet
-
module Jmap_mail_parser = Jmap_mail_parser
+
module Mailbox = Jmap_mailbox
+
module Thread = Jmap_thread
+
module Email = Jmap_email
+
module Identity = Jmap_identity
+
module Email_submission = Jmap_email_submission
+
module Vacation_response = Jmap_vacation_response
+
module Search_snippet = Jmap_search_snippet
+
module Mail_parser = Jmap_mail_parser
+65 -65
stack/jmap/jmap-mail/jmap_mailbox.ml
···
}
*)
let of_json json =
-
let open Jmap_core.Jmap_parser.Helpers in
+
let open Jmap_core.Parser.Helpers in
let fields = expect_object json in
{
may_read_items = get_bool "mayReadItems" fields;
···
(** Mailbox object type *)
type t = {
-
id : Jmap_core.Jmap_id.t; (** Immutable server-assigned id *)
+
id : Jmap_core.Id.t; (** Immutable server-assigned id *)
name : string; (** User-visible mailbox name *)
-
parent_id : Jmap_core.Jmap_id.t option; (** Parent mailbox id (null for top-level) *)
+
parent_id : Jmap_core.Id.t option; (** Parent mailbox id (null for top-level) *)
role : string option; (** Standard role (inbox, trash, sent, etc.) *)
-
sort_order : Jmap_core.Jmap_primitives.UnsignedInt.t; (** Sort order for display *)
-
total_emails : Jmap_core.Jmap_primitives.UnsignedInt.t; (** Total number of emails in mailbox *)
-
unread_emails : Jmap_core.Jmap_primitives.UnsignedInt.t; (** Number of emails without $seen keyword *)
-
total_threads : Jmap_core.Jmap_primitives.UnsignedInt.t; (** Total number of threads with emails in mailbox *)
-
unread_threads : Jmap_core.Jmap_primitives.UnsignedInt.t; (** Number of threads with unread emails in mailbox *)
+
sort_order : Jmap_core.Primitives.UnsignedInt.t; (** Sort order for display *)
+
total_emails : Jmap_core.Primitives.UnsignedInt.t; (** Total number of emails in mailbox *)
+
unread_emails : Jmap_core.Primitives.UnsignedInt.t; (** Number of emails without $seen keyword *)
+
total_threads : Jmap_core.Primitives.UnsignedInt.t; (** Total number of threads with emails in mailbox *)
+
unread_threads : Jmap_core.Primitives.UnsignedInt.t; (** Number of threads with unread emails in mailbox *)
my_rights : Rights.t; (** Current user's access rights *)
is_subscribed : bool; (** Whether user is subscribed to this mailbox *)
}
···
}
*)
let of_json json =
-
let open Jmap_core.Jmap_parser.Helpers in
+
let open Jmap_core.Parser.Helpers in
let fields = expect_object json in
-
let id = Jmap_core.Jmap_id.of_json (require_field "id" fields) in
+
let id = Jmap_core.Id.of_json (require_field "id" fields) in
let name = get_string "name" fields in
let parent_id = match find_field "parentId" fields with
| Some `Null | None -> None
-
| Some v -> Some (Jmap_core.Jmap_id.of_json v)
+
| Some v -> Some (Jmap_core.Id.of_json v)
in
let role = match find_field "role" fields with
| Some `Null | None -> None
| Some (`String s) -> Some s
-
| Some _ -> raise (Jmap_core.Jmap_error.Parse_error "role must be a string or null")
+
| Some _ -> raise (Jmap_core.Error.Parse_error "role must be a string or null")
in
-
let sort_order = Jmap_core.Jmap_primitives.UnsignedInt.of_json (require_field "sortOrder" fields) in
-
let total_emails = Jmap_core.Jmap_primitives.UnsignedInt.of_json (require_field "totalEmails" fields) in
-
let unread_emails = Jmap_core.Jmap_primitives.UnsignedInt.of_json (require_field "unreadEmails" fields) in
-
let total_threads = Jmap_core.Jmap_primitives.UnsignedInt.of_json (require_field "totalThreads" fields) in
-
let unread_threads = Jmap_core.Jmap_primitives.UnsignedInt.of_json (require_field "unreadThreads" fields) in
+
let sort_order = Jmap_core.Primitives.UnsignedInt.of_json (require_field "sortOrder" fields) in
+
let total_emails = Jmap_core.Primitives.UnsignedInt.of_json (require_field "totalEmails" fields) in
+
let unread_emails = Jmap_core.Primitives.UnsignedInt.of_json (require_field "unreadEmails" fields) in
+
let total_threads = Jmap_core.Primitives.UnsignedInt.of_json (require_field "totalThreads" fields) in
+
let unread_threads = Jmap_core.Primitives.UnsignedInt.of_json (require_field "unreadThreads" fields) in
let my_rights = Rights.of_json (require_field "myRights" fields) in
let is_subscribed = get_bool "isSubscribed" fields in
{ id; name; parent_id; role; sort_order; total_emails; unread_emails;
···
let to_json t =
let fields = [
-
("id", Jmap_core.Jmap_id.to_json t.id);
+
("id", Jmap_core.Id.to_json t.id);
("name", `String t.name);
-
("sortOrder", Jmap_core.Jmap_primitives.UnsignedInt.to_json t.sort_order);
-
("totalEmails", Jmap_core.Jmap_primitives.UnsignedInt.to_json t.total_emails);
-
("unreadEmails", Jmap_core.Jmap_primitives.UnsignedInt.to_json t.unread_emails);
-
("totalThreads", Jmap_core.Jmap_primitives.UnsignedInt.to_json t.total_threads);
-
("unreadThreads", Jmap_core.Jmap_primitives.UnsignedInt.to_json t.unread_threads);
+
("sortOrder", Jmap_core.Primitives.UnsignedInt.to_json t.sort_order);
+
("totalEmails", Jmap_core.Primitives.UnsignedInt.to_json t.total_emails);
+
("unreadEmails", Jmap_core.Primitives.UnsignedInt.to_json t.unread_emails);
+
("totalThreads", Jmap_core.Primitives.UnsignedInt.to_json t.total_threads);
+
("unreadThreads", Jmap_core.Primitives.UnsignedInt.to_json t.unread_threads);
("myRights", Rights.to_json t.my_rights);
("isSubscribed", `Bool t.is_subscribed);
] in
let fields = match t.parent_id with
-
| Some pid -> ("parentId", Jmap_core.Jmap_id.to_json pid) :: fields
+
| Some pid -> ("parentId", Jmap_core.Id.to_json pid) :: fields
| None -> ("parentId", `Null) :: fields
in
let fields = match t.role with
···
(** Standard /get method (RFC 8621 Section 2.2) *)
module Get = struct
-
type request = t Jmap_core.Jmap_standard_methods.Get.request
-
type response = t Jmap_core.Jmap_standard_methods.Get.response
+
type request = t Jmap_core.Standard_methods.Get.request
+
type response = t Jmap_core.Standard_methods.Get.response
(** Parse get request from JSON *)
let request_of_json json =
-
Jmap_core.Jmap_standard_methods.Get.request_of_json Parser.of_json json
+
Jmap_core.Standard_methods.Get.request_of_json Parser.of_json json
(** Parse get response from JSON *)
let response_of_json json =
-
Jmap_core.Jmap_standard_methods.Get.response_of_json Parser.of_json json
+
Jmap_core.Standard_methods.Get.response_of_json Parser.of_json json
end
(** Standard /changes method (RFC 8621 Section 2.3) *)
module Changes = struct
-
type request = Jmap_core.Jmap_standard_methods.Changes.request
-
type response = Jmap_core.Jmap_standard_methods.Changes.response
+
type request = Jmap_core.Standard_methods.Changes.request
+
type response = Jmap_core.Standard_methods.Changes.response
let request_of_json json =
-
Jmap_core.Jmap_standard_methods.Changes.request_of_json json
+
Jmap_core.Standard_methods.Changes.request_of_json json
let response_of_json json =
-
Jmap_core.Jmap_standard_methods.Changes.response_of_json json
+
Jmap_core.Standard_methods.Changes.response_of_json json
end
(** Mailbox-specific filter for /query (RFC 8621 Section 2.5) *)
module Filter = struct
type t = {
-
parent_id : Jmap_core.Jmap_id.t option; (** Mailbox parentId equals this value *)
+
parent_id : Jmap_core.Id.t option; (** Mailbox parentId equals this value *)
name : string option; (** Name contains this string (case-insensitive) *)
role : string option; (** Role equals this value *)
has_any_role : bool option; (** Has any role assigned (true) or no role (false) *)
···
}
let of_json json =
-
let open Jmap_core.Jmap_parser.Helpers in
+
let open Jmap_core.Parser.Helpers in
let fields = expect_object json in
let parent_id = match find_field "parentId" fields with
| Some `Null -> Some None (* Explicitly filter for null parent *)
-
| Some v -> Some (Some (Jmap_core.Jmap_id.of_json v))
+
| Some v -> Some (Some (Jmap_core.Id.of_json v))
| None -> None (* Don't filter on parentId *)
in
let name = get_string_opt "name" fields in
let role = get_string_opt "role" fields in
let has_any_role = match find_field "hasAnyRole" fields with
| Some (`Bool b) -> Some b
-
| Some _ -> raise (Jmap_core.Jmap_error.Parse_error "hasAnyRole must be a boolean")
+
| Some _ -> raise (Jmap_core.Error.Parse_error "hasAnyRole must be a boolean")
| None -> None
in
let is_subscribed = match find_field "isSubscribed" fields with
| Some (`Bool b) -> Some b
-
| Some _ -> raise (Jmap_core.Jmap_error.Parse_error "isSubscribed must be a boolean")
+
| Some _ -> raise (Jmap_core.Error.Parse_error "isSubscribed must be a boolean")
| None -> None
in
(* Note: parent_id has special handling - None means don't filter,
···
(** Standard /query method with Mailbox-specific extensions (RFC 8621 Section 2.5) *)
module Query = struct
type request = {
-
account_id : Jmap_core.Jmap_id.t;
-
filter : Filter.t Jmap_core.Jmap_filter.t option;
-
sort : Jmap_core.Jmap_comparator.t list option;
-
position : Jmap_core.Jmap_primitives.Int53.t option;
-
anchor : Jmap_core.Jmap_id.t option;
-
anchor_offset : Jmap_core.Jmap_primitives.Int53.t option;
-
limit : Jmap_core.Jmap_primitives.UnsignedInt.t option;
+
account_id : Jmap_core.Id.t;
+
filter : Filter.t Jmap_core.Filter.t option;
+
sort : Jmap_core.Comparator.t list option;
+
position : Jmap_core.Primitives.Int53.t option;
+
anchor : Jmap_core.Id.t option;
+
anchor_offset : Jmap_core.Primitives.Int53.t option;
+
limit : Jmap_core.Primitives.UnsignedInt.t option;
calculate_total : bool option;
(* Mailbox-specific query arguments *)
sort_as_tree : bool option; (** Return results in tree order *)
filter_as_tree : bool option; (** If true, apply filter to tree roots and return descendants *)
}
-
type response = Jmap_core.Jmap_standard_methods.Query.response
+
type response = Jmap_core.Standard_methods.Query.response
(* Accessors for request *)
let account_id req = req.account_id
···
(** Parse query request from JSON.
Test files: test/data/mail/mailbox_query_request.json *)
let request_of_json json =
-
let open Jmap_core.Jmap_parser.Helpers in
+
let open Jmap_core.Parser.Helpers in
let fields = expect_object json in
-
let account_id = Jmap_core.Jmap_id.of_json (require_field "accountId" fields) in
+
let account_id = Jmap_core.Id.of_json (require_field "accountId" fields) in
let filter = match find_field "filter" fields with
-
| Some v -> Some (Jmap_core.Jmap_filter.of_json Filter.of_json v)
+
| Some v -> Some (Jmap_core.Filter.of_json Filter.of_json v)
| None -> None
in
let sort = match find_field "sort" fields with
-
| Some v -> Some (parse_array Jmap_core.Jmap_comparator.of_json v)
+
| Some v -> Some (parse_array Jmap_core.Comparator.of_json v)
| None -> None
in
let position = match find_field "position" fields with
-
| Some v -> Some (Jmap_core.Jmap_primitives.Int53.of_json v)
+
| Some v -> Some (Jmap_core.Primitives.Int53.of_json v)
| None -> None
in
let anchor = match find_field "anchor" fields with
-
| Some v -> Some (Jmap_core.Jmap_id.of_json v)
+
| Some v -> Some (Jmap_core.Id.of_json v)
| None -> None
in
let anchor_offset = match find_field "anchorOffset" fields with
-
| Some v -> Some (Jmap_core.Jmap_primitives.Int53.of_json v)
+
| Some v -> Some (Jmap_core.Primitives.Int53.of_json v)
| None -> None
in
let limit = match find_field "limit" fields with
-
| Some v -> Some (Jmap_core.Jmap_primitives.UnsignedInt.of_json v)
+
| Some v -> Some (Jmap_core.Primitives.UnsignedInt.of_json v)
| None -> None
in
let calculate_total = match find_field "calculateTotal" fields with
| Some (`Bool b) -> Some b
-
| Some _ -> raise (Jmap_core.Jmap_error.Parse_error "calculateTotal must be a boolean")
+
| Some _ -> raise (Jmap_core.Error.Parse_error "calculateTotal must be a boolean")
| None -> None
in
let sort_as_tree = match find_field "sortAsTree" fields with
| Some (`Bool b) -> Some b
-
| Some _ -> raise (Jmap_core.Jmap_error.Parse_error "sortAsTree must be a boolean")
+
| Some _ -> raise (Jmap_core.Error.Parse_error "sortAsTree must be a boolean")
| None -> None
in
let filter_as_tree = match find_field "filterAsTree" fields with
| Some (`Bool b) -> Some b
-
| Some _ -> raise (Jmap_core.Jmap_error.Parse_error "filterAsTree must be a boolean")
+
| Some _ -> raise (Jmap_core.Error.Parse_error "filterAsTree must be a boolean")
| None -> None
in
{ account_id; filter; sort; position; anchor; anchor_offset; limit;
···
(** Parse query response from JSON.
Test files: test/data/mail/mailbox_query_response.json *)
let response_of_json json =
-
Jmap_core.Jmap_standard_methods.Query.response_of_json json
+
Jmap_core.Standard_methods.Query.response_of_json json
end
(** Standard /queryChanges method (RFC 8621 Section 2.6) *)
module QueryChanges = struct
-
type request = Filter.t Jmap_core.Jmap_standard_methods.QueryChanges.request
-
type response = Jmap_core.Jmap_standard_methods.QueryChanges.response
+
type request = Filter.t Jmap_core.Standard_methods.QueryChanges.request
+
type response = Jmap_core.Standard_methods.QueryChanges.response
let request_of_json json =
-
Jmap_core.Jmap_standard_methods.QueryChanges.request_of_json Filter.of_json json
+
Jmap_core.Standard_methods.QueryChanges.request_of_json Filter.of_json json
let response_of_json json =
-
Jmap_core.Jmap_standard_methods.QueryChanges.response_of_json json
+
Jmap_core.Standard_methods.QueryChanges.response_of_json json
end
(** Standard /set method (RFC 8621 Section 2.4) *)
module Set = struct
-
type request = t Jmap_core.Jmap_standard_methods.Set.request
-
type response = t Jmap_core.Jmap_standard_methods.Set.response
+
type request = t Jmap_core.Standard_methods.Set.request
+
type response = t Jmap_core.Standard_methods.Set.response
(** Parse set request from JSON.
Test files: test/data/mail/mailbox_set_request.json *)
let request_of_json json =
-
Jmap_core.Jmap_standard_methods.Set.request_of_json Parser.of_json json
+
Jmap_core.Standard_methods.Set.request_of_json Parser.of_json json
(** Parse set response from JSON.
Test files: test/data/mail/mailbox_set_response.json *)
let response_of_json json =
-
Jmap_core.Jmap_standard_methods.Set.response_of_json Parser.of_json json
+
Jmap_core.Standard_methods.Set.response_of_json Parser.of_json json
end
(** Standard mailbox role values (RFC 8621 Section 2.1) *)
+54 -54
stack/jmap/jmap-mail/jmap_mailbox.mli
···
(** Mailbox object type *)
type t = {
-
id : Jmap_id.t;
+
id : Id.t;
name : string;
-
parent_id : Jmap_id.t option;
+
parent_id : Id.t option;
role : string option;
-
sort_order : Jmap_primitives.UnsignedInt.t;
-
total_emails : Jmap_primitives.UnsignedInt.t;
-
unread_emails : Jmap_primitives.UnsignedInt.t;
-
total_threads : Jmap_primitives.UnsignedInt.t;
-
unread_threads : Jmap_primitives.UnsignedInt.t;
+
sort_order : Primitives.UnsignedInt.t;
+
total_emails : Primitives.UnsignedInt.t;
+
unread_emails : Primitives.UnsignedInt.t;
+
total_threads : Primitives.UnsignedInt.t;
+
unread_threads : Primitives.UnsignedInt.t;
my_rights : Rights.t;
is_subscribed : bool;
}
(** Accessors *)
-
val id : t -> Jmap_id.t
+
val id : t -> Id.t
val name : t -> string
-
val parent_id : t -> Jmap_id.t option
+
val parent_id : t -> Id.t option
val role : t -> string option
-
val sort_order : t -> Jmap_primitives.UnsignedInt.t
-
val total_emails : t -> Jmap_primitives.UnsignedInt.t
-
val unread_emails : t -> Jmap_primitives.UnsignedInt.t
-
val total_threads : t -> Jmap_primitives.UnsignedInt.t
-
val unread_threads : t -> Jmap_primitives.UnsignedInt.t
+
val sort_order : t -> Primitives.UnsignedInt.t
+
val total_emails : t -> Primitives.UnsignedInt.t
+
val unread_emails : t -> Primitives.UnsignedInt.t
+
val total_threads : t -> Primitives.UnsignedInt.t
+
val unread_threads : t -> Primitives.UnsignedInt.t
val my_rights : t -> Rights.t
val is_subscribed : t -> bool
(** Constructor *)
val v :
-
id:Jmap_id.t ->
+
id:Id.t ->
name:string ->
-
?parent_id:Jmap_id.t ->
+
?parent_id:Id.t ->
?role:string ->
-
sort_order:Jmap_primitives.UnsignedInt.t ->
-
total_emails:Jmap_primitives.UnsignedInt.t ->
-
unread_emails:Jmap_primitives.UnsignedInt.t ->
-
total_threads:Jmap_primitives.UnsignedInt.t ->
-
unread_threads:Jmap_primitives.UnsignedInt.t ->
+
sort_order:Primitives.UnsignedInt.t ->
+
total_emails:Primitives.UnsignedInt.t ->
+
unread_emails:Primitives.UnsignedInt.t ->
+
total_threads:Primitives.UnsignedInt.t ->
+
unread_threads:Primitives.UnsignedInt.t ->
my_rights:Rights.t ->
is_subscribed:bool ->
unit ->
···
(** Standard /get method *)
module Get : sig
-
type request = t Jmap_standard_methods.Get.request
-
type response = t Jmap_standard_methods.Get.response
+
type request = t Standard_methods.Get.request
+
type response = t Standard_methods.Get.response
val request_of_json : Ezjsonm.value -> request
val response_of_json : Ezjsonm.value -> response
···
(** Standard /changes method *)
module Changes : sig
-
type request = Jmap_standard_methods.Changes.request
-
type response = Jmap_standard_methods.Changes.response
+
type request = Standard_methods.Changes.request
+
type response = Standard_methods.Changes.response
val request_of_json : Ezjsonm.value -> request
val response_of_json : Ezjsonm.value -> response
···
(** Mailbox-specific filter for /query *)
module Filter : sig
type t = {
-
parent_id : Jmap_id.t option;
+
parent_id : Id.t option;
name : string option;
role : string option;
has_any_role : bool option;
···
}
(** Accessors *)
-
val parent_id : t -> Jmap_id.t option
+
val parent_id : t -> Id.t option
val name : t -> string option
val role : t -> string option
val has_any_role : t -> bool option
···
(** Constructor *)
val v :
-
?parent_id:Jmap_id.t ->
+
?parent_id:Id.t ->
?name:string ->
?role:string ->
?has_any_role:bool ->
···
(** Standard /query method with Mailbox-specific extensions *)
module Query : sig
type request = {
-
account_id : Jmap_id.t;
-
filter : Filter.t Jmap_filter.t option;
-
sort : Jmap_comparator.t list option;
-
position : Jmap_primitives.Int53.t option;
-
anchor : Jmap_id.t option;
-
anchor_offset : Jmap_primitives.Int53.t option;
-
limit : Jmap_primitives.UnsignedInt.t option;
+
account_id : Id.t;
+
filter : Filter.t Jmap_core.Filter.t option;
+
sort : Comparator.t list option;
+
position : Primitives.Int53.t option;
+
anchor : Id.t option;
+
anchor_offset : Primitives.Int53.t option;
+
limit : Primitives.UnsignedInt.t option;
calculate_total : bool option;
sort_as_tree : bool option;
filter_as_tree : bool option;
}
-
type response = Jmap_standard_methods.Query.response
+
type response = Standard_methods.Query.response
(** Accessors for request *)
-
val account_id : request -> Jmap_id.t
-
val filter : request -> Filter.t Jmap_filter.t option
-
val sort : request -> Jmap_comparator.t list option
-
val position : request -> Jmap_primitives.Int53.t option
-
val anchor : request -> Jmap_id.t option
-
val anchor_offset : request -> Jmap_primitives.Int53.t option
-
val limit : request -> Jmap_primitives.UnsignedInt.t option
+
val account_id : request -> Id.t
+
val filter : request -> Filter.t Jmap_core.Filter.t option
+
val sort : request -> Comparator.t list option
+
val position : request -> Primitives.Int53.t option
+
val anchor : request -> Id.t option
+
val anchor_offset : request -> Primitives.Int53.t option
+
val limit : request -> Primitives.UnsignedInt.t option
val calculate_total : request -> bool option
val sort_as_tree : request -> bool option
val filter_as_tree : request -> bool option
(** Constructor for request *)
val request_v :
-
account_id:Jmap_id.t ->
-
?filter:Filter.t Jmap_filter.t ->
-
?sort:Jmap_comparator.t list ->
-
?position:Jmap_primitives.Int53.t ->
-
?anchor:Jmap_id.t ->
-
?anchor_offset:Jmap_primitives.Int53.t ->
-
?limit:Jmap_primitives.UnsignedInt.t ->
+
account_id:Id.t ->
+
?filter:Filter.t Jmap_core.Filter.t ->
+
?sort:Comparator.t list ->
+
?position:Primitives.Int53.t ->
+
?anchor:Id.t ->
+
?anchor_offset:Primitives.Int53.t ->
+
?limit:Primitives.UnsignedInt.t ->
?calculate_total:bool ->
?sort_as_tree:bool ->
?filter_as_tree:bool ->
···
(** Standard /queryChanges method *)
module QueryChanges : sig
-
type request = Filter.t Jmap_standard_methods.QueryChanges.request
-
type response = Jmap_standard_methods.QueryChanges.response
+
type request = Filter.t Standard_methods.QueryChanges.request
+
type response = Standard_methods.QueryChanges.response
val request_of_json : Ezjsonm.value -> request
val response_of_json : Ezjsonm.value -> response
···
(** Standard /set method *)
module Set : sig
-
type request = t Jmap_standard_methods.Set.request
-
type response = t Jmap_standard_methods.Set.response
+
type request = t Standard_methods.Set.request
+
type response = t Standard_methods.Set.response
val request_of_json : Ezjsonm.value -> request
val response_of_json : Ezjsonm.value -> response
+10 -10
stack/jmap/jmap-mail/jmap_search_snippet.ml
···
The <mark> tags indicate where the search terms matched.
*)
type t = {
-
email_id : Jmap_core.Jmap_id.t; (** Email ID this snippet is for *)
+
email_id : Jmap_core.Id.t; (** Email ID this snippet is for *)
subject : string option; (** Subject with search terms highlighted using <mark> tags *)
preview : string option; (** Preview text with search terms highlighted using <mark> tags *)
}
···
*)
module Get = struct
type request = {
-
account_id : Jmap_core.Jmap_id.t;
-
filter : Jmap_email.Filter.t Jmap_core.Jmap_filter.t; (** Filter to apply for highlighting *)
-
email_ids : Jmap_core.Jmap_id.t list; (** Email IDs to get snippets for *)
+
account_id : Jmap_core.Id.t;
+
filter : Jmap_email.Filter.t Jmap_core.Filter.t; (** Filter to apply for highlighting *)
+
email_ids : Jmap_core.Id.t list; (** Email IDs to get snippets for *)
}
type response = {
-
account_id : Jmap_core.Jmap_id.t;
+
account_id : Jmap_core.Id.t;
list : t list; (** SearchSnippets for requested emails *)
-
not_found : Jmap_core.Jmap_id.t list; (** Email IDs that don't exist *)
+
not_found : Jmap_core.Id.t list; (** Email IDs that don't exist *)
}
(** Accessors for request *)
···
}
*)
let request_of_json _json =
-
raise (Jmap_core.Jmap_error.Parse_error "SearchSnippet.Get.request_of_json not yet implemented")
+
raise (Jmap_core.Error.Parse_error "SearchSnippet.Get.request_of_json not yet implemented")
(** Parse get response from JSON.
Test files: test/data/mail/search_snippet_response.json
···
}
*)
let response_of_json _json =
-
raise (Jmap_core.Jmap_error.Parse_error "SearchSnippet.Get.response_of_json not yet implemented")
+
raise (Jmap_core.Error.Parse_error "SearchSnippet.Get.response_of_json not yet implemented")
end
(** Parser submodule *)
···
*)
let of_json _json =
(* TODO: Implement JSON parsing *)
-
raise (Jmap_core.Jmap_error.Parse_error "SearchSnippet.Parser.of_json not yet implemented")
+
raise (Jmap_core.Error.Parse_error "SearchSnippet.Parser.of_json not yet implemented")
let to_json _t =
(* TODO: Implement JSON serialization *)
-
raise (Jmap_core.Jmap_error.Parse_error "SearchSnippet.Parser.to_json not yet implemented")
+
raise (Jmap_core.Error.Parse_error "SearchSnippet.Parser.to_json not yet implemented")
end
+18 -18
stack/jmap/jmap-mail/jmap_search_snippet.mli
···
(** SearchSnippet object type (RFC 8621 Section 5.1) *)
type t = {
-
email_id : Jmap_id.t;
+
email_id : Id.t;
subject : string option;
preview : string option;
}
(** Accessors *)
-
val email_id : t -> Jmap_id.t
+
val email_id : t -> Id.t
val subject : t -> string option
val preview : t -> string option
(** Constructor *)
-
val v : email_id:Jmap_id.t -> ?subject:string -> ?preview:string -> unit -> t
+
val v : email_id:Id.t -> ?subject:string -> ?preview:string -> unit -> t
(** SearchSnippet/get method *)
module Get : sig
type request = {
-
account_id : Jmap_id.t;
-
filter : Jmap_email.Filter.t Jmap_filter.t;
-
email_ids : Jmap_id.t list;
+
account_id : Id.t;
+
filter : Jmap_email.Filter.t Filter.t;
+
email_ids : Id.t list;
}
type response = {
-
account_id : Jmap_id.t;
+
account_id : Id.t;
list : t list;
-
not_found : Jmap_id.t list;
+
not_found : Id.t list;
}
(** Accessors for request *)
-
val account_id : request -> Jmap_id.t
-
val filter : request -> Jmap_email.Filter.t Jmap_filter.t
-
val email_ids : request -> Jmap_id.t list
+
val account_id : request -> Id.t
+
val filter : request -> Jmap_email.Filter.t Filter.t
+
val email_ids : request -> Id.t list
(** Constructor for request *)
val request_v :
-
account_id:Jmap_id.t ->
-
filter:Jmap_email.Filter.t Jmap_filter.t ->
-
email_ids:Jmap_id.t list ->
+
account_id:Id.t ->
+
filter:Jmap_email.Filter.t Filter.t ->
+
email_ids:Id.t list ->
request
(** Accessors for response *)
-
val response_account_id : response -> Jmap_id.t
+
val response_account_id : response -> Id.t
val list : response -> t list
-
val not_found : response -> Jmap_id.t list
+
val not_found : response -> Id.t list
(** Constructor for response *)
val response_v :
-
account_id:Jmap_id.t ->
+
account_id:Id.t ->
list:t list ->
-
not_found:Jmap_id.t list ->
+
not_found:Id.t list ->
response
val request_of_json : Ezjsonm.value -> request
+8 -8
stack/jmap/jmap-mail/jmap_thread.ml
···
(** Thread object type *)
type t = {
-
id : Jmap_core.Jmap_id.t; (** Immutable server-assigned thread id *)
-
email_ids : Jmap_core.Jmap_id.t list; (** List of email ids in this thread, sorted by date (oldest first) *)
+
id : Jmap_core.Id.t; (** Immutable server-assigned thread id *)
+
email_ids : Jmap_core.Id.t list; (** List of email ids in this thread, sorted by date (oldest first) *)
}
(** Accessors *)
···
- /queryChanges
*)
module Get = struct
-
type request = t Jmap_core.Jmap_standard_methods.Get.request
-
type response = t Jmap_core.Jmap_standard_methods.Get.response
+
type request = t Jmap_core.Standard_methods.Get.request
+
type response = t Jmap_core.Standard_methods.Get.response
(** Parse get request from JSON.
Test files: test/data/mail/thread_get_request.json
···
}
*)
let request_of_json _json =
-
raise (Jmap_core.Jmap_error.Parse_error "Thread.Get.request_of_json not yet implemented")
+
raise (Jmap_core.Error.Parse_error "Thread.Get.request_of_json not yet implemented")
(** Parse get response from JSON.
Test files: test/data/mail/thread_get_response.json
···
}
*)
let response_of_json _json =
-
raise (Jmap_core.Jmap_error.Parse_error "Thread.Get.response_of_json not yet implemented")
+
raise (Jmap_core.Error.Parse_error "Thread.Get.response_of_json not yet implemented")
end
(** Parser submodule *)
···
*)
let of_json _json =
(* TODO: Implement JSON parsing *)
-
raise (Jmap_core.Jmap_error.Parse_error "Thread.Parser.of_json not yet implemented")
+
raise (Jmap_core.Error.Parse_error "Thread.Parser.of_json not yet implemented")
let to_json _t =
(* TODO: Implement JSON serialization *)
-
raise (Jmap_core.Jmap_error.Parse_error "Thread.Parser.to_json not yet implemented")
+
raise (Jmap_core.Error.Parse_error "Thread.Parser.to_json not yet implemented")
end
+7 -7
stack/jmap/jmap-mail/jmap_thread.mli
···
(** Thread object type *)
type t = {
-
id : Jmap_id.t;
-
email_ids : Jmap_id.t list;
+
id : Id.t;
+
email_ids : Id.t list;
}
(** Accessors *)
-
val id : t -> Jmap_id.t
-
val email_ids : t -> Jmap_id.t list
+
val id : t -> Id.t
+
val email_ids : t -> Id.t list
(** Constructor *)
-
val v : id:Jmap_id.t -> email_ids:Jmap_id.t list -> t
+
val v : id:Id.t -> email_ids:Id.t list -> t
(** Standard /get method *)
module Get : sig
-
type request = t Jmap_standard_methods.Get.request
-
type response = t Jmap_standard_methods.Get.response
+
type request = t Standard_methods.Get.request
+
type response = t Standard_methods.Get.response
val request_of_json : Ezjsonm.value -> request
val response_of_json : Ezjsonm.value -> response
+13 -13
stack/jmap/jmap-mail/jmap_vacation_response.ml
···
with id "singleton". It cannot be created or destroyed, only updated.
*)
type t = {
-
id : Jmap_core.Jmap_id.t; (** Always "singleton" *)
+
id : Jmap_core.Id.t; (** Always "singleton" *)
is_enabled : bool; (** Is vacation response currently active? *)
-
from_date : Jmap_core.Jmap_primitives.UTCDate.t option; (** Start date (null = active now) *)
-
to_date : Jmap_core.Jmap_primitives.UTCDate.t option; (** End date (null = no end) *)
+
from_date : Jmap_core.Primitives.UTCDate.t option; (** Start date (null = active now) *)
+
to_date : Jmap_core.Primitives.UTCDate.t option; (** End date (null = no end) *)
subject : string option; (** Subject for auto-reply message *)
text_body : string option; (** Plain text auto-reply body *)
html_body : string option; (** HTML auto-reply body *)
···
}
*)
module Get = struct
-
type request = t Jmap_core.Jmap_standard_methods.Get.request
-
type response = t Jmap_core.Jmap_standard_methods.Get.response
+
type request = t Jmap_core.Standard_methods.Get.request
+
type response = t Jmap_core.Standard_methods.Get.response
(** Parse get request from JSON.
Test files: test/data/mail/vacation_response_get_request.json
···
}
*)
let request_of_json _json =
-
raise (Jmap_core.Jmap_error.Parse_error "VacationResponse.Get.request_of_json not yet implemented")
+
raise (Jmap_core.Error.Parse_error "VacationResponse.Get.request_of_json not yet implemented")
(** Parse get response from JSON.
Test files: test/data/mail/vacation_response_get_response.json
···
}
*)
let response_of_json _json =
-
raise (Jmap_core.Jmap_error.Parse_error "VacationResponse.Get.response_of_json not yet implemented")
+
raise (Jmap_core.Error.Parse_error "VacationResponse.Get.response_of_json not yet implemented")
end
(** Standard /set method (RFC 8621 Section 8.3)
···
}
*)
module Set = struct
-
type request = t Jmap_core.Jmap_standard_methods.Set.request
-
type response = t Jmap_core.Jmap_standard_methods.Set.response
+
type request = t Jmap_core.Standard_methods.Set.request
+
type response = t Jmap_core.Standard_methods.Set.response
let request_of_json _json =
-
raise (Jmap_core.Jmap_error.Parse_error "VacationResponse.Set.request_of_json not yet implemented")
+
raise (Jmap_core.Error.Parse_error "VacationResponse.Set.request_of_json not yet implemented")
let response_of_json _json =
-
raise (Jmap_core.Jmap_error.Parse_error "VacationResponse.Set.response_of_json not yet implemented")
+
raise (Jmap_core.Error.Parse_error "VacationResponse.Set.response_of_json not yet implemented")
end
(** Parser submodule *)
···
*)
let of_json _json =
(* TODO: Implement JSON parsing *)
-
raise (Jmap_core.Jmap_error.Parse_error "VacationResponse.Parser.of_json not yet implemented")
+
raise (Jmap_core.Error.Parse_error "VacationResponse.Parser.of_json not yet implemented")
let to_json _t =
(* TODO: Implement JSON serialization *)
-
raise (Jmap_core.Jmap_error.Parse_error "VacationResponse.Parser.to_json not yet implemented")
+
raise (Jmap_core.Error.Parse_error "VacationResponse.Parser.to_json not yet implemented")
end
(** Singleton ID constant *)
+13 -13
stack/jmap/jmap-mail/jmap_vacation_response.mli
···
(** VacationResponse object type (RFC 8621 Section 8.1) *)
type t = {
-
id : Jmap_id.t;
+
id : Id.t;
is_enabled : bool;
-
from_date : Jmap_primitives.UTCDate.t option;
-
to_date : Jmap_primitives.UTCDate.t option;
+
from_date : Primitives.UTCDate.t option;
+
to_date : Primitives.UTCDate.t option;
subject : string option;
text_body : string option;
html_body : string option;
}
(** Accessors *)
-
val id : t -> Jmap_id.t
+
val id : t -> Id.t
val is_enabled : t -> bool
-
val from_date : t -> Jmap_primitives.UTCDate.t option
-
val to_date : t -> Jmap_primitives.UTCDate.t option
+
val from_date : t -> Primitives.UTCDate.t option
+
val to_date : t -> Primitives.UTCDate.t option
val subject : t -> string option
val text_body : t -> string option
val html_body : t -> string option
(** Constructor *)
val v :
-
id:Jmap_id.t ->
+
id:Id.t ->
is_enabled:bool ->
-
?from_date:Jmap_primitives.UTCDate.t ->
-
?to_date:Jmap_primitives.UTCDate.t ->
+
?from_date:Primitives.UTCDate.t ->
+
?to_date:Primitives.UTCDate.t ->
?subject:string ->
?text_body:string ->
?html_body:string ->
···
(** Standard /get method *)
module Get : sig
-
type request = t Jmap_standard_methods.Get.request
-
type response = t Jmap_standard_methods.Get.response
+
type request = t Standard_methods.Get.request
+
type response = t Standard_methods.Get.response
val request_of_json : Ezjsonm.value -> request
val response_of_json : Ezjsonm.value -> response
···
(** Standard /set method *)
module Set : sig
-
type request = t Jmap_standard_methods.Set.request
-
type response = t Jmap_standard_methods.Set.response
+
type request = t Standard_methods.Set.request
+
type response = t Standard_methods.Set.response
val request_of_json : Ezjsonm.value -> request
val response_of_json : Ezjsonm.value -> response
+34
stack/jmap/jmap.opam
···
+
# This file is generated by dune, edit dune-project instead
+
opam-version: "2.0"
+
version: "0.1.0"
+
synopsis: "Unified JMAP library combining core, mail, and client"
+
description:
+
"Ergonomic, unified interface to the complete JMAP library (RFC 8620, RFC 8621). This is the recommended entry point for most users."
+
maintainer: ["your.email@example.com"]
+
authors: ["Your Name"]
+
license: "MIT"
+
homepage: "https://github.com/yourusername/jmap"
+
bug-reports: "https://github.com/yourusername/jmap/issues"
+
depends: [
+
"ocaml" {>= "4.14"}
+
"dune" {>= "3.0" & >= "3.0"}
+
"jmap-core" {= version}
+
"jmap-mail" {= version}
+
"jmap-client" {= version}
+
"odoc" {with-doc}
+
]
+
build: [
+
["dune" "subst"] {dev}
+
[
+
"dune"
+
"build"
+
"-p"
+
name
+
"-j"
+
jobs
+
"@install"
+
"@runtest" {with-test}
+
"@doc" {with-doc}
+
]
+
]
+
dev-repo: "git+https://github.com/yourusername/jmap.git"
+5
stack/jmap/lib/dune
···
+
(library
+
(name jmap)
+
(public_name jmap)
+
(libraries jmap-core jmap-mail jmap-client)
+
(modules jmap))
+94
stack/jmap/lib/jmap.ml
···
+
(** Unified JMAP Library Interface
+
+
This module provides a convenient, ergonomic interface to the complete JMAP library.
+
It combines jmap-core, jmap-mail, and jmap-client into a single unified API.
+
+
For most use cases, you should use this module. For specialized functionality,
+
you can fall back to the individual submodules (Jmap_core, Jmap_mail, Jmap_client).
+
*)
+
+
(** {1 High-level Client API} *)
+
+
(** JMAP HTTP Client - Start here for most use cases *)
+
module Client = Jmap_client
+
+
(** Connection configuration *)
+
module Connection = Jmap_connection
+
+
(** {1 Mail Extension (RFC 8621)} *)
+
+
(** Email operations *)
+
module Email = Jmap_mail.Email
+
+
(** Mailbox operations *)
+
module Mailbox = Jmap_mail.Mailbox
+
+
(** Thread operations *)
+
module Thread = Jmap_mail.Thread
+
+
(** Identity management *)
+
module Identity = Jmap_mail.Identity
+
+
(** Email submission *)
+
module Email_submission = Jmap_mail.Email_submission
+
+
(** Vacation responses *)
+
module Vacation_response = Jmap_mail.Vacation_response
+
+
(** Search snippets *)
+
module Search_snippet = Jmap_mail.Search_snippet
+
+
(** Mail parsing utilities *)
+
module Mail_parser = Jmap_mail.Mail_parser
+
+
(** {1 Core Protocol (RFC 8620)} *)
+
+
(** JMAP Session *)
+
module Session = Jmap_core.Session
+
+
(** Request building *)
+
module Request = Jmap_core.Request
+
+
(** Response handling *)
+
module Response = Jmap_core.Response
+
+
(** Method invocations *)
+
module Invocation = Jmap_core.Invocation
+
+
(** JMAP IDs *)
+
module Id = Jmap_core.Id
+
+
(** Capabilities *)
+
module Capability = Jmap_core.Capability
+
+
(** Filters *)
+
module Filter = Jmap_core.Filter
+
+
(** Comparators (sorting) *)
+
module Comparator = Jmap_core.Comparator
+
+
(** Primitive types *)
+
module Primitives = Jmap_core.Primitives
+
+
(** Standard methods *)
+
module Standard_methods = Jmap_core.Standard_methods
+
+
(** Error handling *)
+
module Error = Jmap_core.Error
+
+
(** Binary data (upload/download) *)
+
module Binary = Jmap_core.Binary
+
+
(** Push notifications *)
+
module Push = Jmap_core.Push
+
+
(** JSON parsing utilities *)
+
module Parser = Jmap_core.Parser
+
+
(** {1 Full Module Access} *)
+
+
(** Complete jmap-core library *)
+
module Core = Jmap_core
+
+
(** Complete jmap-mail library *)
+
module Mail = Jmap_mail
+125
stack/jmap/lib/jmap.mli
···
+
(** Unified JMAP Library Interface
+
+
This module provides a convenient, ergonomic interface to the complete JMAP library.
+
It combines jmap-core, jmap-mail, and jmap-client into a single unified API.
+
+
For most use cases, you should use this module. For specialized functionality,
+
you can fall back to the individual submodules (Jmap_core, Jmap_mail, Jmap_client).
+
+
{2 Quick Start}
+
+
{[
+
(* Create a client *)
+
let client = Jmap.Client.create
+
~sw
+
~env
+
~conn:(Jmap.Connection.bearer_auth ~token:"your-token" ())
+
~session_url:"https://api.example.com/.well-known/jmap"
+
()
+
+
(* Fetch session *)
+
let session = Jmap.Client.get_session client
+
+
(* Build and send a request *)
+
let query_req = Jmap.Email.Query.request_v
+
~account_id:(Jmap.Id.of_string account_id)
+
~limit:(Jmap.Primitives.UnsignedInt.of_int 10)
+
()
+
in
+
+
let query_args = Jmap.Email.Query.request_to_json query_req in
+
let invocation = Jmap.Invocation.make_echo "Email/query" query_args "q1" in
+
let req = Jmap.Request.make
+
~using:[Jmap.Capability.core; Jmap.Capability.mail]
+
[invocation]
+
in
+
+
let resp = Jmap.Client.call client req
+
]}
+
*)
+
+
(** {1 High-level Client API} *)
+
+
(** JMAP HTTP Client - Start here for most use cases *)
+
module Client = Jmap_client
+
+
(** Connection configuration *)
+
module Connection = Jmap_connection
+
+
(** {1 Mail Extension (RFC 8621)} *)
+
+
(** Email operations *)
+
module Email = Jmap_mail.Email
+
+
(** Mailbox operations *)
+
module Mailbox = Jmap_mail.Mailbox
+
+
(** Thread operations *)
+
module Thread = Jmap_mail.Thread
+
+
(** Identity management *)
+
module Identity = Jmap_mail.Identity
+
+
(** Email submission *)
+
module Email_submission = Jmap_mail.Email_submission
+
+
(** Vacation responses *)
+
module Vacation_response = Jmap_mail.Vacation_response
+
+
(** Search snippets *)
+
module Search_snippet = Jmap_mail.Search_snippet
+
+
(** Mail parsing utilities *)
+
module Mail_parser = Jmap_mail.Mail_parser
+
+
(** {1 Core Protocol (RFC 8620)} *)
+
+
(** JMAP Session *)
+
module Session = Jmap_core.Session
+
+
(** Request building *)
+
module Request = Jmap_core.Request
+
+
(** Response handling *)
+
module Response = Jmap_core.Response
+
+
(** Method invocations *)
+
module Invocation = Jmap_core.Invocation
+
+
(** JMAP IDs *)
+
module Id = Jmap_core.Id
+
+
(** Capabilities *)
+
module Capability = Jmap_core.Capability
+
+
(** Filters *)
+
module Filter = Jmap_core.Filter
+
+
(** Comparators (sorting) *)
+
module Comparator = Jmap_core.Comparator
+
+
(** Primitive types *)
+
module Primitives = Jmap_core.Primitives
+
+
(** Standard methods *)
+
module Standard_methods = Jmap_core.Standard_methods
+
+
(** Error handling *)
+
module Error = Jmap_core.Error
+
+
(** Binary data (upload/download) *)
+
module Binary = Jmap_core.Binary
+
+
(** Push notifications *)
+
module Push = Jmap_core.Push
+
+
(** JSON parsing utilities *)
+
module Parser = Jmap_core.Parser
+
+
(** {1 Full Module Access} *)
+
+
(** Complete jmap-core library *)
+
module Core = Jmap_core
+
+
(** Complete jmap-mail library *)
+
module Mail = Jmap_mail
+5
stack/jmap/test/dune
···
(name test_simple_https)
(libraries eio_main requests mirage-crypto-rng.unix)
(modes exe))
+
+
(executable
+
(name test_unified_api)
+
(libraries jmap jmap-core jmap-mail)
+
(modes exe))
+28 -28
stack/jmap/test/test_fastmail.ml
···
Printf.printf "Fetching JMAP session...\n%!";
let session = Jmap_client.fetch_session client in
Printf.printf "✓ Session fetched\n";
-
Printf.printf " Username: %s\n" (Jmap_core.Jmap_session.username session);
-
Printf.printf " API URL: %s\n\n%!" (Jmap_core.Jmap_session.api_url session);
+
Printf.printf " Username: %s\n" (Jmap_core.Session.username session);
+
Printf.printf " API URL: %s\n\n%!" (Jmap_core.Session.api_url session);
(* Get primary mail account *)
-
let primary_accounts = Jmap_core.Jmap_session.primary_accounts session in
+
let primary_accounts = Jmap_core.Session.primary_accounts session in
let account_id = match List.assoc_opt "urn:ietf:params:jmap:mail" primary_accounts with
-
| Some id -> Jmap_core.Jmap_id.to_string id
+
| Some id -> Jmap_core.Id.to_string id
| None ->
Printf.eprintf "Error: No mail account found\n";
exit 1
···
(* Build a JMAP request using the typed library API *)
Printf.printf "Querying for 10 most recent emails...\n";
-
Printf.printf " API URL: %s\n%!" (Jmap_core.Jmap_session.api_url session);
+
Printf.printf " API URL: %s\n%!" (Jmap_core.Session.api_url session);
(* Build Email/query request using typed constructors *)
-
let query_request = Jmap_mail.Jmap_email.Query.request_v
-
~account_id:(Jmap_core.Jmap_id.of_string account_id)
-
~limit:(Jmap_core.Jmap_primitives.UnsignedInt.of_int 10)
-
~sort:[Jmap_core.Jmap_comparator.v ~property:"receivedAt" ~is_ascending:false ()]
+
let query_request = Jmap_mail.Email.Query.request_v
+
~account_id:(Jmap_core.Id.of_string account_id)
+
~limit:(Jmap_core.Primitives.UnsignedInt.of_int 10)
+
~sort:[Jmap_core.Comparator.v ~property:"receivedAt" ~is_ascending:false ()]
~calculate_total:true
() in
(* Convert to JSON *)
-
let query_args = Jmap_mail.Jmap_email.Query.request_to_json query_request in
+
let query_args = Jmap_mail.Email.Query.request_to_json query_request in
(* Create invocation using Echo witness *)
-
let query_invocation = Jmap_core.Jmap_invocation.Invocation {
+
let query_invocation = Jmap_core.Invocation.Invocation {
method_name = "Email/query";
arguments = query_args;
call_id = "q1";
-
witness = Jmap_core.Jmap_invocation.Echo;
+
witness = Jmap_core.Invocation.Echo;
} in
(* Build request using constructors *)
-
let req = Jmap_core.Jmap_request.make
-
~using:[Jmap_core.Jmap_capability.core; Jmap_core.Jmap_capability.mail]
-
[Jmap_core.Jmap_invocation.Packed query_invocation]
+
let req = Jmap_core.Request.make
+
~using:[Jmap_core.Capability.core; Jmap_core.Capability.mail]
+
[Jmap_core.Invocation.Packed query_invocation]
in
Printf.printf " Request built using typed Email.Query API\n%!";
···
Printf.printf "✓ Query successful!\n";
(* Extract email IDs from the query response *)
-
let method_responses = Jmap_core.Jmap_response.method_responses query_resp in
+
let method_responses = Jmap_core.Response.method_responses query_resp in
let email_ids = match method_responses with
| [packed_resp] ->
-
let response_json = Jmap_core.Jmap_invocation.response_to_json packed_resp in
+
let response_json = Jmap_core.Invocation.response_to_json packed_resp in
(match response_json with
| `O fields ->
(match List.assoc_opt "ids" fields with
| Some (`A ids) ->
List.map (fun id ->
match id with
-
| `String s -> Jmap_core.Jmap_id.of_string s
+
| `String s -> Jmap_core.Id.of_string s
| _ -> failwith "Expected string ID"
) ids
| _ -> failwith "No 'ids' field in query response")
···
if List.length email_ids > 0 then (
(* Fetch the actual emails with Email/get *)
-
let get_request = Jmap_mail.Jmap_email.Get.request_v
-
~account_id:(Jmap_core.Jmap_id.of_string account_id)
+
let get_request = Jmap_mail.Email.Get.request_v
+
~account_id:(Jmap_core.Id.of_string account_id)
~ids:email_ids
~properties:["id"; "subject"; "from"; "receivedAt"]
() in
-
let get_args = Jmap_mail.Jmap_email.Get.request_to_json get_request in
+
let get_args = Jmap_mail.Email.Get.request_to_json get_request in
-
let get_invocation = Jmap_core.Jmap_invocation.Invocation {
+
let get_invocation = Jmap_core.Invocation.Invocation {
method_name = "Email/get";
arguments = get_args;
call_id = "g1";
-
witness = Jmap_core.Jmap_invocation.Echo;
+
witness = Jmap_core.Invocation.Echo;
} in
-
let get_req = Jmap_core.Jmap_request.make
-
~using:[Jmap_core.Jmap_capability.core; Jmap_core.Jmap_capability.mail]
-
[Jmap_core.Jmap_invocation.Packed get_invocation]
+
let get_req = Jmap_core.Request.make
+
~using:[Jmap_core.Capability.core; Jmap_core.Capability.mail]
+
[Jmap_core.Invocation.Packed get_invocation]
in
let get_resp = Jmap_client.call client get_req in
(* Parse and display emails *)
-
let get_method_responses = Jmap_core.Jmap_response.method_responses get_resp in
+
let get_method_responses = Jmap_core.Response.method_responses get_resp in
(match get_method_responses with
| [packed_resp] ->
-
let response_json = Jmap_core.Jmap_invocation.response_to_json packed_resp in
+
let response_json = Jmap_core.Invocation.response_to_json packed_resp in
(match response_json with
| `O fields ->
(match List.assoc_opt "list" fields with
+264 -264
stack/jmap/test/test_jmap.ml
···
let test_mailbox_get_request () =
let json = load_json "data/mail/mailbox_get_request.json" in
-
let req = Jmap_mail.Jmap_mailbox.Get.request_of_json json in
+
let req = Jmap_mail.Mailbox.Get.request_of_json json in
(* Verify account_id *)
-
let account_id = Jmap_core.Jmap_standard_methods.Get.account_id req in
-
check string "Account ID" "u123456" (Jmap_core.Jmap_id.to_string account_id);
+
let account_id = Jmap_core.Standard_methods.Get.account_id req in
+
check string "Account ID" "u123456" (Jmap_core.Id.to_string account_id);
(* Verify ids is null (None) *)
-
let ids = Jmap_core.Jmap_standard_methods.Get.ids req in
+
let ids = Jmap_core.Standard_methods.Get.ids req in
check bool "IDs should be None" true (ids = None);
(* Verify properties list *)
-
let props = Jmap_core.Jmap_standard_methods.Get.properties req in
+
let props = Jmap_core.Standard_methods.Get.properties req in
match props with
| Some p ->
check int "Properties count" 11 (List.length p);
···
let test_mailbox_get_response () =
let json = load_json "data/mail/mailbox_get_response.json" in
-
let resp = Jmap_mail.Jmap_mailbox.Get.response_of_json json in
+
let resp = Jmap_mail.Mailbox.Get.response_of_json json in
(* Verify account_id *)
-
let account_id = Jmap_core.Jmap_standard_methods.Get.response_account_id resp in
-
check string "Account ID" "u123456" (Jmap_core.Jmap_id.to_string account_id);
+
let account_id = Jmap_core.Standard_methods.Get.response_account_id resp in
+
check string "Account ID" "u123456" (Jmap_core.Id.to_string account_id);
(* Verify state *)
-
let state = Jmap_core.Jmap_standard_methods.Get.state resp in
+
let state = Jmap_core.Standard_methods.Get.state resp in
check string "State" "m42:100" state;
(* Verify mailbox list *)
-
let mailboxes = Jmap_core.Jmap_standard_methods.Get.list resp in
+
let mailboxes = Jmap_core.Standard_methods.Get.list resp in
check int "Mailbox count" 5 (List.length mailboxes);
(* Verify not_found is empty *)
-
let not_found = Jmap_core.Jmap_standard_methods.Get.not_found resp in
+
let not_found = Jmap_core.Standard_methods.Get.not_found resp in
check int "Not found count" 0 (List.length not_found);
(* Test first mailbox (INBOX) *)
let inbox = List.hd mailboxes in
-
check string "INBOX id" "mb001" (Jmap_core.Jmap_id.to_string (Jmap_mail.Jmap_mailbox.id inbox));
-
check string "INBOX name" "INBOX" (Jmap_mail.Jmap_mailbox.name inbox);
-
check bool "INBOX parentId is None" true (Jmap_mail.Jmap_mailbox.parent_id inbox = None);
-
check string "INBOX role" "inbox" (match Jmap_mail.Jmap_mailbox.role inbox with Some r -> r | None -> "");
-
check int "INBOX sortOrder" 10 (Jmap_core.Jmap_primitives.UnsignedInt.to_int (Jmap_mail.Jmap_mailbox.sort_order inbox));
-
check int "INBOX totalEmails" 1523 (Jmap_core.Jmap_primitives.UnsignedInt.to_int (Jmap_mail.Jmap_mailbox.total_emails inbox));
-
check int "INBOX unreadEmails" 42 (Jmap_core.Jmap_primitives.UnsignedInt.to_int (Jmap_mail.Jmap_mailbox.unread_emails inbox));
-
check int "INBOX totalThreads" 987 (Jmap_core.Jmap_primitives.UnsignedInt.to_int (Jmap_mail.Jmap_mailbox.total_threads inbox));
-
check int "INBOX unreadThreads" 35 (Jmap_core.Jmap_primitives.UnsignedInt.to_int (Jmap_mail.Jmap_mailbox.unread_threads inbox));
-
check bool "INBOX isSubscribed" true (Jmap_mail.Jmap_mailbox.is_subscribed inbox);
+
check string "INBOX id" "mb001" (Jmap_core.Id.to_string (Jmap_mail.Mailbox.id inbox));
+
check string "INBOX name" "INBOX" (Jmap_mail.Mailbox.name inbox);
+
check bool "INBOX parentId is None" true (Jmap_mail.Mailbox.parent_id inbox = None);
+
check string "INBOX role" "inbox" (match Jmap_mail.Mailbox.role inbox with Some r -> r | None -> "");
+
check int "INBOX sortOrder" 10 (Jmap_core.Primitives.UnsignedInt.to_int (Jmap_mail.Mailbox.sort_order inbox));
+
check int "INBOX totalEmails" 1523 (Jmap_core.Primitives.UnsignedInt.to_int (Jmap_mail.Mailbox.total_emails inbox));
+
check int "INBOX unreadEmails" 42 (Jmap_core.Primitives.UnsignedInt.to_int (Jmap_mail.Mailbox.unread_emails inbox));
+
check int "INBOX totalThreads" 987 (Jmap_core.Primitives.UnsignedInt.to_int (Jmap_mail.Mailbox.total_threads inbox));
+
check int "INBOX unreadThreads" 35 (Jmap_core.Primitives.UnsignedInt.to_int (Jmap_mail.Mailbox.unread_threads inbox));
+
check bool "INBOX isSubscribed" true (Jmap_mail.Mailbox.is_subscribed inbox);
(* Test INBOX rights *)
-
let inbox_rights = Jmap_mail.Jmap_mailbox.my_rights inbox in
-
check bool "INBOX mayReadItems" true (Jmap_mail.Jmap_mailbox.Rights.may_read_items inbox_rights);
-
check bool "INBOX mayAddItems" true (Jmap_mail.Jmap_mailbox.Rights.may_add_items inbox_rights);
-
check bool "INBOX mayRemoveItems" true (Jmap_mail.Jmap_mailbox.Rights.may_remove_items inbox_rights);
-
check bool "INBOX maySetSeen" true (Jmap_mail.Jmap_mailbox.Rights.may_set_seen inbox_rights);
-
check bool "INBOX maySetKeywords" true (Jmap_mail.Jmap_mailbox.Rights.may_set_keywords inbox_rights);
-
check bool "INBOX mayCreateChild" true (Jmap_mail.Jmap_mailbox.Rights.may_create_child inbox_rights);
-
check bool "INBOX mayRename" false (Jmap_mail.Jmap_mailbox.Rights.may_rename inbox_rights);
-
check bool "INBOX mayDelete" false (Jmap_mail.Jmap_mailbox.Rights.may_delete inbox_rights);
-
check bool "INBOX maySubmit" true (Jmap_mail.Jmap_mailbox.Rights.may_submit inbox_rights);
+
let inbox_rights = Jmap_mail.Mailbox.my_rights inbox in
+
check bool "INBOX mayReadItems" true (Jmap_mail.Mailbox.Rights.may_read_items inbox_rights);
+
check bool "INBOX mayAddItems" true (Jmap_mail.Mailbox.Rights.may_add_items inbox_rights);
+
check bool "INBOX mayRemoveItems" true (Jmap_mail.Mailbox.Rights.may_remove_items inbox_rights);
+
check bool "INBOX maySetSeen" true (Jmap_mail.Mailbox.Rights.may_set_seen inbox_rights);
+
check bool "INBOX maySetKeywords" true (Jmap_mail.Mailbox.Rights.may_set_keywords inbox_rights);
+
check bool "INBOX mayCreateChild" true (Jmap_mail.Mailbox.Rights.may_create_child inbox_rights);
+
check bool "INBOX mayRename" false (Jmap_mail.Mailbox.Rights.may_rename inbox_rights);
+
check bool "INBOX mayDelete" false (Jmap_mail.Mailbox.Rights.may_delete inbox_rights);
+
check bool "INBOX maySubmit" true (Jmap_mail.Mailbox.Rights.may_submit inbox_rights);
(* Test second mailbox (Sent) *)
let sent = List.nth mailboxes 1 in
-
check string "Sent id" "mb002" (Jmap_core.Jmap_id.to_string (Jmap_mail.Jmap_mailbox.id sent));
-
check string "Sent name" "Sent" (Jmap_mail.Jmap_mailbox.name sent);
-
check string "Sent role" "sent" (match Jmap_mail.Jmap_mailbox.role sent with Some r -> r | None -> "");
-
check int "Sent sortOrder" 20 (Jmap_core.Jmap_primitives.UnsignedInt.to_int (Jmap_mail.Jmap_mailbox.sort_order sent));
+
check string "Sent id" "mb002" (Jmap_core.Id.to_string (Jmap_mail.Mailbox.id sent));
+
check string "Sent name" "Sent" (Jmap_mail.Mailbox.name sent);
+
check string "Sent role" "sent" (match Jmap_mail.Mailbox.role sent with Some r -> r | None -> "");
+
check int "Sent sortOrder" 20 (Jmap_core.Primitives.UnsignedInt.to_int (Jmap_mail.Mailbox.sort_order sent));
(* Test Work mailbox (no role) *)
let work = List.nth mailboxes 4 in
-
check string "Work id" "mb005" (Jmap_core.Jmap_id.to_string (Jmap_mail.Jmap_mailbox.id work));
-
check string "Work name" "Work" (Jmap_mail.Jmap_mailbox.name work);
-
check bool "Work role is None" true (Jmap_mail.Jmap_mailbox.role work = None);
-
check int "Work totalEmails" 342 (Jmap_core.Jmap_primitives.UnsignedInt.to_int (Jmap_mail.Jmap_mailbox.total_emails work));
+
check string "Work id" "mb005" (Jmap_core.Id.to_string (Jmap_mail.Mailbox.id work));
+
check string "Work name" "Work" (Jmap_mail.Mailbox.name work);
+
check bool "Work role is None" true (Jmap_mail.Mailbox.role work = None);
+
check int "Work totalEmails" 342 (Jmap_core.Primitives.UnsignedInt.to_int (Jmap_mail.Mailbox.total_emails work));
(* Test Work rights (user-created mailbox has full permissions) *)
-
let work_rights = Jmap_mail.Jmap_mailbox.my_rights work in
-
check bool "Work mayRename" true (Jmap_mail.Jmap_mailbox.Rights.may_rename work_rights);
-
check bool "Work mayDelete" true (Jmap_mail.Jmap_mailbox.Rights.may_delete work_rights)
+
let work_rights = Jmap_mail.Mailbox.my_rights work in
+
check bool "Work mayRename" true (Jmap_mail.Mailbox.Rights.may_rename work_rights);
+
check bool "Work mayDelete" true (Jmap_mail.Mailbox.Rights.may_delete work_rights)
let test_mailbox_query_request () =
let json = load_json "data/mail/mailbox_query_request.json" in
-
let req = Jmap_mail.Jmap_mailbox.Query.request_of_json json in
+
let req = Jmap_mail.Mailbox.Query.request_of_json json in
(* Verify account_id *)
-
let account_id = Jmap_mail.Jmap_mailbox.Query.account_id req in
-
check string "Account ID" "u123456" (Jmap_core.Jmap_id.to_string account_id);
+
let account_id = Jmap_mail.Mailbox.Query.account_id req in
+
check string "Account ID" "u123456" (Jmap_core.Id.to_string account_id);
(* Verify filter is present *)
-
let filter = Jmap_mail.Jmap_mailbox.Query.filter req in
+
let filter = Jmap_mail.Mailbox.Query.filter req in
check bool "Filter should be Some" true (filter <> None);
(* Verify sort *)
-
let sort = Jmap_mail.Jmap_mailbox.Query.sort req in
+
let sort = Jmap_mail.Mailbox.Query.sort req in
match sort with
| Some s ->
check int "Sort criteria count" 2 (List.length s);
(* First sort by sortOrder ascending *)
let sort1 = List.hd s in
-
check string "First sort property" "sortOrder" (Jmap_core.Jmap_comparator.property sort1);
-
check bool "First sort ascending" true (Jmap_core.Jmap_comparator.is_ascending sort1);
+
check string "First sort property" "sortOrder" (Jmap_core.Comparator.property sort1);
+
check bool "First sort ascending" true (Jmap_core.Comparator.is_ascending sort1);
(* Second sort by name ascending *)
let sort2 = List.nth s 1 in
-
check string "Second sort property" "name" (Jmap_core.Jmap_comparator.property sort2);
-
check bool "Second sort ascending" true (Jmap_core.Jmap_comparator.is_ascending sort2)
+
check string "Second sort property" "name" (Jmap_core.Comparator.property sort2);
+
check bool "Second sort ascending" true (Jmap_core.Comparator.is_ascending sort2)
| None ->
fail "Sort should not be None";
(* Verify calculateTotal *)
-
let calculate_total = Jmap_mail.Jmap_mailbox.Query.calculate_total req in
+
let calculate_total = Jmap_mail.Mailbox.Query.calculate_total req in
check bool "Calculate total should be Some true" true (calculate_total = Some true)
let test_mailbox_query_response () =
let json = load_json "data/mail/mailbox_query_response.json" in
-
let resp = Jmap_mail.Jmap_mailbox.Query.response_of_json json in
+
let resp = Jmap_mail.Mailbox.Query.response_of_json json in
(* Verify account_id *)
-
let account_id = Jmap_core.Jmap_standard_methods.Query.response_account_id resp in
-
check string "Account ID" "u123456" (Jmap_core.Jmap_id.to_string account_id);
+
let account_id = Jmap_core.Standard_methods.Query.response_account_id resp in
+
check string "Account ID" "u123456" (Jmap_core.Id.to_string account_id);
(* Verify query_state *)
-
let query_state = Jmap_core.Jmap_standard_methods.Query.query_state resp in
+
let query_state = Jmap_core.Standard_methods.Query.query_state resp in
check string "Query state" "mq42:100" query_state;
(* Verify can_calculate_changes *)
-
let can_calc = Jmap_core.Jmap_standard_methods.Query.can_calculate_changes resp in
+
let can_calc = Jmap_core.Standard_methods.Query.can_calculate_changes resp in
check bool "Can calculate changes" true can_calc;
(* Verify position *)
-
let position = Jmap_core.Jmap_standard_methods.Query.response_position resp in
-
check int "Position" 0 (Jmap_core.Jmap_primitives.UnsignedInt.to_int position);
+
let position = Jmap_core.Standard_methods.Query.response_position resp in
+
check int "Position" 0 (Jmap_core.Primitives.UnsignedInt.to_int position);
(* Verify ids *)
-
let ids = Jmap_core.Jmap_standard_methods.Query.ids resp in
+
let ids = Jmap_core.Standard_methods.Query.ids resp in
check int "IDs count" 3 (List.length ids);
-
check string "First ID" "mb005" (Jmap_core.Jmap_id.to_string (List.hd ids));
-
check string "Second ID" "mb008" (Jmap_core.Jmap_id.to_string (List.nth ids 1));
-
check string "Third ID" "mb012" (Jmap_core.Jmap_id.to_string (List.nth ids 2));
+
check string "First ID" "mb005" (Jmap_core.Id.to_string (List.hd ids));
+
check string "Second ID" "mb008" (Jmap_core.Id.to_string (List.nth ids 1));
+
check string "Third ID" "mb012" (Jmap_core.Id.to_string (List.nth ids 2));
(* Verify total *)
-
let total = Jmap_core.Jmap_standard_methods.Query.total resp in
+
let total = Jmap_core.Standard_methods.Query.total resp in
match total with
-
| Some t -> check int "Total" 3 (Jmap_core.Jmap_primitives.UnsignedInt.to_int t)
+
| Some t -> check int "Total" 3 (Jmap_core.Primitives.UnsignedInt.to_int t)
| None -> fail "Total should not be None"
let test_mailbox_set_request () =
let json = load_json "data/mail/mailbox_set_request.json" in
-
let req = Jmap_mail.Jmap_mailbox.Set.request_of_json json in
+
let req = Jmap_mail.Mailbox.Set.request_of_json json in
(* Verify account_id *)
-
let account_id = Jmap_core.Jmap_standard_methods.Set.account_id req in
-
check string "Account ID" "u123456" (Jmap_core.Jmap_id.to_string account_id);
+
let account_id = Jmap_core.Standard_methods.Set.account_id req in
+
check string "Account ID" "u123456" (Jmap_core.Id.to_string account_id);
(* Verify if_in_state *)
-
let if_in_state = Jmap_core.Jmap_standard_methods.Set.if_in_state req in
+
let if_in_state = Jmap_core.Standard_methods.Set.if_in_state req in
check bool "If in state should be Some" true (if_in_state = Some "m42:100");
(* Verify create *)
-
let create = Jmap_core.Jmap_standard_methods.Set.create req in
+
let create = Jmap_core.Standard_methods.Set.create req in
(match create with
| Some c ->
check int "Create count" 1 (List.length c);
let (temp_id, mailbox) = List.hd c in
-
check string "Temp ID" "temp-mb-1" (Jmap_core.Jmap_id.to_string temp_id);
-
check string "Created mailbox name" "Projects" (Jmap_mail.Jmap_mailbox.name mailbox);
-
check bool "Created mailbox parentId is None" true (Jmap_mail.Jmap_mailbox.parent_id mailbox = None);
-
check bool "Created mailbox role is None" true (Jmap_mail.Jmap_mailbox.role mailbox = None);
-
check int "Created mailbox sortOrder" 60 (Jmap_core.Jmap_primitives.UnsignedInt.to_int (Jmap_mail.Jmap_mailbox.sort_order mailbox));
-
check bool "Created mailbox isSubscribed" true (Jmap_mail.Jmap_mailbox.is_subscribed mailbox)
+
check string "Temp ID" "temp-mb-1" (Jmap_core.Id.to_string temp_id);
+
check string "Created mailbox name" "Projects" (Jmap_mail.Mailbox.name mailbox);
+
check bool "Created mailbox parentId is None" true (Jmap_mail.Mailbox.parent_id mailbox = None);
+
check bool "Created mailbox role is None" true (Jmap_mail.Mailbox.role mailbox = None);
+
check int "Created mailbox sortOrder" 60 (Jmap_core.Primitives.UnsignedInt.to_int (Jmap_mail.Mailbox.sort_order mailbox));
+
check bool "Created mailbox isSubscribed" true (Jmap_mail.Mailbox.is_subscribed mailbox)
| None ->
fail "Create should not be None");
(* Verify update *)
-
let update = Jmap_core.Jmap_standard_methods.Set.update req in
+
let update = Jmap_core.Standard_methods.Set.update req in
(match update with
| Some u ->
check int "Update count" 1 (List.length u);
let (update_id, _patches) = List.hd u in
-
check string "Update ID" "mb005" (Jmap_core.Jmap_id.to_string update_id)
+
check string "Update ID" "mb005" (Jmap_core.Id.to_string update_id)
| None ->
fail "Update should not be None");
(* Verify destroy *)
-
let destroy = Jmap_core.Jmap_standard_methods.Set.destroy req in
+
let destroy = Jmap_core.Standard_methods.Set.destroy req in
(match destroy with
| Some d ->
check int "Destroy count" 1 (List.length d);
-
check string "Destroy ID" "mb012" (Jmap_core.Jmap_id.to_string (List.hd d))
+
check string "Destroy ID" "mb012" (Jmap_core.Id.to_string (List.hd d))
| None ->
fail "Destroy should not be None")
let test_mailbox_set_response () =
let json = load_json "data/mail/mailbox_set_response.json" in
-
let resp = Jmap_mail.Jmap_mailbox.Set.response_of_json json in
+
let resp = Jmap_mail.Mailbox.Set.response_of_json json in
(* Verify account_id *)
-
let account_id = Jmap_core.Jmap_standard_methods.Set.response_account_id resp in
-
check string "Account ID" "u123456" (Jmap_core.Jmap_id.to_string account_id);
+
let account_id = Jmap_core.Standard_methods.Set.response_account_id resp in
+
check string "Account ID" "u123456" (Jmap_core.Id.to_string account_id);
(* Verify old_state *)
-
let old_state = Jmap_core.Jmap_standard_methods.Set.old_state resp in
+
let old_state = Jmap_core.Standard_methods.Set.old_state resp in
check bool "Old state should be Some" true (old_state = Some "m42:100");
(* Verify new_state *)
-
let new_state = Jmap_core.Jmap_standard_methods.Set.new_state resp in
+
let new_state = Jmap_core.Standard_methods.Set.new_state resp in
check string "New state" "m42:103" new_state;
(* Verify created *)
-
let created = Jmap_core.Jmap_standard_methods.Set.created resp in
+
let created = Jmap_core.Standard_methods.Set.created resp in
(match created with
| Some c ->
check int "Created count" 1 (List.length c);
let (temp_id, mailbox) = List.hd c in
-
check string "Created temp ID" "temp-mb-1" (Jmap_core.Jmap_id.to_string temp_id);
-
check string "Created mailbox ID" "mb020" (Jmap_core.Jmap_id.to_string (Jmap_mail.Jmap_mailbox.id mailbox));
-
check int "Created mailbox totalEmails" 0 (Jmap_core.Jmap_primitives.UnsignedInt.to_int (Jmap_mail.Jmap_mailbox.total_emails mailbox));
-
check int "Created mailbox unreadEmails" 0 (Jmap_core.Jmap_primitives.UnsignedInt.to_int (Jmap_mail.Jmap_mailbox.unread_emails mailbox));
+
check string "Created temp ID" "temp-mb-1" (Jmap_core.Id.to_string temp_id);
+
check string "Created mailbox ID" "mb020" (Jmap_core.Id.to_string (Jmap_mail.Mailbox.id mailbox));
+
check int "Created mailbox totalEmails" 0 (Jmap_core.Primitives.UnsignedInt.to_int (Jmap_mail.Mailbox.total_emails mailbox));
+
check int "Created mailbox unreadEmails" 0 (Jmap_core.Primitives.UnsignedInt.to_int (Jmap_mail.Mailbox.unread_emails mailbox));
(* Verify rights of created mailbox *)
-
let rights = Jmap_mail.Jmap_mailbox.my_rights mailbox in
-
check bool "Created mailbox mayRename" true (Jmap_mail.Jmap_mailbox.Rights.may_rename rights);
-
check bool "Created mailbox mayDelete" true (Jmap_mail.Jmap_mailbox.Rights.may_delete rights)
+
let rights = Jmap_mail.Mailbox.my_rights mailbox in
+
check bool "Created mailbox mayRename" true (Jmap_mail.Mailbox.Rights.may_rename rights);
+
check bool "Created mailbox mayDelete" true (Jmap_mail.Mailbox.Rights.may_delete rights)
| None ->
fail "Created should not be None");
(* Verify updated *)
-
let updated = Jmap_core.Jmap_standard_methods.Set.updated resp in
+
let updated = Jmap_core.Standard_methods.Set.updated resp in
(match updated with
| Some u ->
check int "Updated count" 1 (List.length u);
let (update_id, update_val) = List.hd u in
-
check string "Updated ID" "mb005" (Jmap_core.Jmap_id.to_string update_id);
+
check string "Updated ID" "mb005" (Jmap_core.Id.to_string update_id);
check bool "Updated value is None" true (update_val = None)
| None ->
fail "Updated should not be None");
(* Verify destroyed *)
-
let destroyed = Jmap_core.Jmap_standard_methods.Set.destroyed resp in
+
let destroyed = Jmap_core.Standard_methods.Set.destroyed resp in
(match destroyed with
| Some d ->
check int "Destroyed count" 1 (List.length d);
-
check string "Destroyed ID" "mb012" (Jmap_core.Jmap_id.to_string (List.hd d))
+
check string "Destroyed ID" "mb012" (Jmap_core.Id.to_string (List.hd d))
| None ->
fail "Destroyed should not be None");
(* Verify not_created, not_updated, not_destroyed are None *)
-
check bool "Not created is None" true (Jmap_core.Jmap_standard_methods.Set.not_created resp = None);
-
check bool "Not updated is None" true (Jmap_core.Jmap_standard_methods.Set.not_updated resp = None);
-
check bool "Not destroyed is None" true (Jmap_core.Jmap_standard_methods.Set.not_destroyed resp = None)
+
check bool "Not created is None" true (Jmap_core.Standard_methods.Set.not_created resp = None);
+
check bool "Not updated is None" true (Jmap_core.Standard_methods.Set.not_updated resp = None);
+
check bool "Not destroyed is None" true (Jmap_core.Standard_methods.Set.not_destroyed resp = None)
(** Test Mail Protocol - Email *)
let test_email_get_request () =
let json = load_json "data/mail/email_get_request.json" in
-
let request = Jmap_mail.Jmap_email.Get.request_of_json json in
+
let request = Jmap_mail.Email.Get.request_of_json json in
(* Validate account_id *)
-
let account_id = Jmap_mail.Jmap_email.Get.account_id request in
-
check string "Account ID" "u123456" (Jmap_core.Jmap_id.to_string account_id);
+
let account_id = Jmap_mail.Email.Get.account_id request in
+
check string "Account ID" "u123456" (Jmap_core.Id.to_string account_id);
(* Validate ids *)
-
let ids = Jmap_mail.Jmap_email.Get.ids request in
+
let ids = Jmap_mail.Email.Get.ids request in
check bool "IDs present" true (Option.is_some ids);
let ids_list = Option.get ids in
check int "Two IDs requested" 2 (List.length ids_list);
-
check string "First ID" "e001" (Jmap_core.Jmap_id.to_string (List.nth ids_list 0));
-
check string "Second ID" "e002" (Jmap_core.Jmap_id.to_string (List.nth ids_list 1));
+
check string "First ID" "e001" (Jmap_core.Id.to_string (List.nth ids_list 0));
+
check string "Second ID" "e002" (Jmap_core.Id.to_string (List.nth ids_list 1));
(* Validate properties *)
-
let properties = Jmap_mail.Jmap_email.Get.properties request in
+
let properties = Jmap_mail.Email.Get.properties request in
check bool "Properties present" true (Option.is_some properties);
let props_list = Option.get properties in
check bool "Properties include 'subject'" true (List.mem "subject" props_list);
···
let test_email_get_full_request () =
let json = load_json "data/mail/email_get_full_request.json" in
-
let request = Jmap_mail.Jmap_email.Get.request_of_json json in
+
let request = Jmap_mail.Email.Get.request_of_json json in
(* Validate body fetch options *)
-
let fetch_text = Jmap_mail.Jmap_email.Get.fetch_text_body_values request in
+
let fetch_text = Jmap_mail.Email.Get.fetch_text_body_values request in
check bool "Fetch text body values" true (Option.value ~default:false fetch_text);
-
let fetch_html = Jmap_mail.Jmap_email.Get.fetch_html_body_values request in
+
let fetch_html = Jmap_mail.Email.Get.fetch_html_body_values request in
check bool "Fetch HTML body values" true (Option.value ~default:false fetch_html);
-
let fetch_all = Jmap_mail.Jmap_email.Get.fetch_all_body_values request in
+
let fetch_all = Jmap_mail.Email.Get.fetch_all_body_values request in
check bool "Fetch all body values is false" false (Option.value ~default:true fetch_all);
-
let max_bytes = Jmap_mail.Jmap_email.Get.max_body_value_bytes request in
+
let max_bytes = Jmap_mail.Email.Get.max_body_value_bytes request in
check bool "Max body value bytes present" true (Option.is_some max_bytes);
check int "Max bytes is 32768" 32768
-
(Jmap_core.Jmap_primitives.UnsignedInt.to_int (Option.get max_bytes))
+
(Jmap_core.Primitives.UnsignedInt.to_int (Option.get max_bytes))
let test_email_get_response () =
let json = load_json "data/mail/email_get_response.json" in
-
let response = Jmap_mail.Jmap_email.Get.response_of_json json in
+
let response = Jmap_mail.Email.Get.response_of_json json in
(* Validate response metadata *)
-
let account_id = Jmap_core.Jmap_standard_methods.Get.response_account_id response in
-
check string "Response account ID" "u123456" (Jmap_core.Jmap_id.to_string account_id);
+
let account_id = Jmap_core.Standard_methods.Get.response_account_id response in
+
check string "Response account ID" "u123456" (Jmap_core.Id.to_string account_id);
-
let state = Jmap_core.Jmap_standard_methods.Get.state response in
+
let state = Jmap_core.Standard_methods.Get.state response in
check string "Response state" "e42:100" state;
(* Validate emails list *)
-
let emails = Jmap_core.Jmap_standard_methods.Get.list response in
+
let emails = Jmap_core.Standard_methods.Get.list response in
check int "Two emails returned" 2 (List.length emails);
(* Test first email (e001) *)
let email1 = List.nth emails 0 in
-
check string "Email 1 ID" "e001" (Jmap_core.Jmap_id.to_string (Jmap_mail.Jmap_email.id email1));
-
check string "Email 1 thread ID" "t001" (Jmap_core.Jmap_id.to_string (Jmap_mail.Jmap_email.thread_id email1));
+
check string "Email 1 ID" "e001" (Jmap_core.Id.to_string (Jmap_mail.Email.id email1));
+
check string "Email 1 thread ID" "t001" (Jmap_core.Id.to_string (Jmap_mail.Email.thread_id email1));
check string "Email 1 subject" "Project Update Q4 2025"
-
(Option.get (Jmap_mail.Jmap_email.subject email1));
+
(Option.get (Jmap_mail.Email.subject email1));
check int "Email 1 size" 15234
-
(Jmap_core.Jmap_primitives.UnsignedInt.to_int (Jmap_mail.Jmap_email.size email1));
-
check bool "Email 1 has no attachment" false (Jmap_mail.Jmap_email.has_attachment email1);
+
(Jmap_core.Primitives.UnsignedInt.to_int (Jmap_mail.Email.size email1));
+
check bool "Email 1 has no attachment" false (Jmap_mail.Email.has_attachment email1);
(* Test email 1 from address *)
-
let from1 = Option.get (Jmap_mail.Jmap_email.from email1) in
+
let from1 = Option.get (Jmap_mail.Email.from email1) in
check int "Email 1 has one from address" 1 (List.length from1);
let from_addr = List.nth from1 0 in
check string "Email 1 from name" "Bob Smith"
-
(Option.get (Jmap_mail.Jmap_email.EmailAddress.name from_addr));
+
(Option.get (Jmap_mail.Email.EmailAddress.name from_addr));
check string "Email 1 from email" "bob@example.com"
-
(Jmap_mail.Jmap_email.EmailAddress.email from_addr);
+
(Jmap_mail.Email.EmailAddress.email from_addr);
(* Test email 1 to addresses *)
-
let to1 = Option.get (Jmap_mail.Jmap_email.to_ email1) in
+
let to1 = Option.get (Jmap_mail.Email.to_ email1) in
check int "Email 1 has one to address" 1 (List.length to1);
let to_addr = List.nth to1 0 in
check string "Email 1 to name" "Alice Jones"
-
(Option.get (Jmap_mail.Jmap_email.EmailAddress.name to_addr));
+
(Option.get (Jmap_mail.Email.EmailAddress.name to_addr));
check string "Email 1 to email" "alice@example.com"
-
(Jmap_mail.Jmap_email.EmailAddress.email to_addr);
+
(Jmap_mail.Email.EmailAddress.email to_addr);
(* Test email 1 keywords *)
-
let keywords1 = Jmap_mail.Jmap_email.keywords email1 in
+
let keywords1 = Jmap_mail.Email.keywords email1 in
check bool "Email 1 has $seen keyword" true
(List.mem_assoc "$seen" keywords1);
check bool "Email 1 $seen is true" true
···
(* Test second email (e002) *)
let email2 = List.nth emails 1 in
-
check string "Email 2 ID" "e002" (Jmap_core.Jmap_id.to_string (Jmap_mail.Jmap_email.id email2));
+
check string "Email 2 ID" "e002" (Jmap_core.Id.to_string (Jmap_mail.Email.id email2));
check string "Email 2 subject" "Re: Technical Requirements Review"
-
(Option.get (Jmap_mail.Jmap_email.subject email2));
+
(Option.get (Jmap_mail.Email.subject email2));
(* Test email 2 to addresses (multiple recipients) *)
-
let to2 = Option.get (Jmap_mail.Jmap_email.to_ email2) in
+
let to2 = Option.get (Jmap_mail.Email.to_ email2) in
check int "Email 2 has two to addresses" 2 (List.length to2);
(* Test email 2 keywords *)
-
let keywords2 = Jmap_mail.Jmap_email.keywords email2 in
+
let keywords2 = Jmap_mail.Email.keywords email2 in
check bool "Email 2 has $seen keyword" true
(List.mem_assoc "$seen" keywords2);
check bool "Email 2 has $flagged keyword" true
(List.mem_assoc "$flagged" keywords2);
(* Test email 2 replyTo *)
-
let reply_to2 = Jmap_mail.Jmap_email.reply_to email2 in
+
let reply_to2 = Jmap_mail.Email.reply_to email2 in
check bool "Email 2 has replyTo" true (Option.is_some reply_to2);
let reply_to_list = Option.get reply_to2 in
check int "Email 2 has one replyTo address" 1 (List.length reply_to_list);
let reply_addr = List.nth reply_to_list 0 in
check string "Email 2 replyTo email" "support@company.com"
-
(Jmap_mail.Jmap_email.EmailAddress.email reply_addr);
+
(Jmap_mail.Email.EmailAddress.email reply_addr);
(* Validate notFound is empty *)
-
let not_found = Jmap_core.Jmap_standard_methods.Get.not_found response in
+
let not_found = Jmap_core.Standard_methods.Get.not_found response in
check int "No emails not found" 0 (List.length not_found)
let test_email_get_full_response () =
let json = load_json "data/mail/email_get_full_response.json" in
-
let response = Jmap_mail.Jmap_email.Get.response_of_json json in
+
let response = Jmap_mail.Email.Get.response_of_json json in
-
let emails = Jmap_core.Jmap_standard_methods.Get.list response in
+
let emails = Jmap_core.Standard_methods.Get.list response in
check int "One email returned" 1 (List.length emails);
let email = List.nth emails 0 in
(* Validate basic fields *)
-
check string "Email ID" "e001" (Jmap_core.Jmap_id.to_string (Jmap_mail.Jmap_email.id email));
-
check bool "Has attachment" true (Jmap_mail.Jmap_email.has_attachment email);
+
check string "Email ID" "e001" (Jmap_core.Id.to_string (Jmap_mail.Email.id email));
+
check bool "Has attachment" true (Jmap_mail.Email.has_attachment email);
(* Validate bodyStructure (multipart/mixed with nested multipart/alternative) *)
-
let body_structure = Jmap_mail.Jmap_email.body_structure email in
+
let body_structure = Jmap_mail.Email.body_structure email in
check bool "Has bodyStructure" true (Option.is_some body_structure);
let root_part = Option.get body_structure in
check string "Root type is multipart/mixed" "multipart/mixed"
-
(Jmap_mail.Jmap_email.BodyPart.type_ root_part);
+
(Jmap_mail.Email.BodyPart.type_ root_part);
-
let sub_parts = Jmap_mail.Jmap_email.BodyPart.sub_parts root_part in
+
let sub_parts = Jmap_mail.Email.BodyPart.sub_parts root_part in
check bool "Root has subParts" true (Option.is_some sub_parts);
let parts_list = Option.get sub_parts in
check int "Root has 2 subParts" 2 (List.length parts_list);
···
(* First subpart: multipart/alternative *)
let alt_part = List.nth parts_list 0 in
check string "First subpart is multipart/alternative" "multipart/alternative"
-
(Jmap_mail.Jmap_email.BodyPart.type_ alt_part);
+
(Jmap_mail.Email.BodyPart.type_ alt_part);
-
let alt_sub_parts = Option.get (Jmap_mail.Jmap_email.BodyPart.sub_parts alt_part) in
+
let alt_sub_parts = Option.get (Jmap_mail.Email.BodyPart.sub_parts alt_part) in
check int "Alternative has 2 subParts" 2 (List.length alt_sub_parts);
(* Text/plain part *)
let text_part = List.nth alt_sub_parts 0 in
-
check string "Text part type" "text/plain" (Jmap_mail.Jmap_email.BodyPart.type_ text_part);
+
check string "Text part type" "text/plain" (Jmap_mail.Email.BodyPart.type_ text_part);
check string "Text part charset" "utf-8"
-
(Option.get (Jmap_mail.Jmap_email.BodyPart.charset text_part));
-
check string "Text part ID" "1" (Option.get (Jmap_mail.Jmap_email.BodyPart.part_id text_part));
+
(Option.get (Jmap_mail.Email.BodyPart.charset text_part));
+
check string "Text part ID" "1" (Option.get (Jmap_mail.Email.BodyPart.part_id text_part));
check int "Text part size" 2134
-
(Jmap_core.Jmap_primitives.UnsignedInt.to_int (Jmap_mail.Jmap_email.BodyPart.size text_part));
+
(Jmap_core.Primitives.UnsignedInt.to_int (Jmap_mail.Email.BodyPart.size text_part));
(* Text/html part *)
let html_part = List.nth alt_sub_parts 1 in
-
check string "HTML part type" "text/html" (Jmap_mail.Jmap_email.BodyPart.type_ html_part);
-
check string "HTML part ID" "2" (Option.get (Jmap_mail.Jmap_email.BodyPart.part_id html_part));
+
check string "HTML part type" "text/html" (Jmap_mail.Email.BodyPart.type_ html_part);
+
check string "HTML part ID" "2" (Option.get (Jmap_mail.Email.BodyPart.part_id html_part));
check int "HTML part size" 4567
-
(Jmap_core.Jmap_primitives.UnsignedInt.to_int (Jmap_mail.Jmap_email.BodyPart.size html_part));
+
(Jmap_core.Primitives.UnsignedInt.to_int (Jmap_mail.Email.BodyPart.size html_part));
(* Attachment part *)
let attach_part = List.nth parts_list 1 in
check string "Attachment type" "application/pdf"
-
(Jmap_mail.Jmap_email.BodyPart.type_ attach_part);
+
(Jmap_mail.Email.BodyPart.type_ attach_part);
check string "Attachment name" "Q4_Report.pdf"
-
(Option.get (Jmap_mail.Jmap_email.BodyPart.name attach_part));
+
(Option.get (Jmap_mail.Email.BodyPart.name attach_part));
check string "Attachment disposition" "attachment"
-
(Option.get (Jmap_mail.Jmap_email.BodyPart.disposition attach_part));
+
(Option.get (Jmap_mail.Email.BodyPart.disposition attach_part));
check string "Attachment part ID" "3"
-
(Option.get (Jmap_mail.Jmap_email.BodyPart.part_id attach_part));
+
(Option.get (Jmap_mail.Email.BodyPart.part_id attach_part));
check int "Attachment size" 8533
-
(Jmap_core.Jmap_primitives.UnsignedInt.to_int (Jmap_mail.Jmap_email.BodyPart.size attach_part));
+
(Jmap_core.Primitives.UnsignedInt.to_int (Jmap_mail.Email.BodyPart.size attach_part));
(* Validate textBody *)
-
let text_body = Jmap_mail.Jmap_email.text_body email in
+
let text_body = Jmap_mail.Email.text_body email in
check bool "Has textBody" true (Option.is_some text_body);
let text_body_list = Option.get text_body in
check int "One textBody part" 1 (List.length text_body_list);
let text_body_part = List.nth text_body_list 0 in
check string "textBody part ID" "1"
-
(Option.get (Jmap_mail.Jmap_email.BodyPart.part_id text_body_part));
+
(Option.get (Jmap_mail.Email.BodyPart.part_id text_body_part));
check string "textBody type" "text/plain"
-
(Jmap_mail.Jmap_email.BodyPart.type_ text_body_part);
+
(Jmap_mail.Email.BodyPart.type_ text_body_part);
(* Validate htmlBody *)
-
let html_body = Jmap_mail.Jmap_email.html_body email in
+
let html_body = Jmap_mail.Email.html_body email in
check bool "Has htmlBody" true (Option.is_some html_body);
let html_body_list = Option.get html_body in
check int "One htmlBody part" 1 (List.length html_body_list);
let html_body_part = List.nth html_body_list 0 in
check string "htmlBody part ID" "2"
-
(Option.get (Jmap_mail.Jmap_email.BodyPart.part_id html_body_part));
+
(Option.get (Jmap_mail.Email.BodyPart.part_id html_body_part));
check string "htmlBody type" "text/html"
-
(Jmap_mail.Jmap_email.BodyPart.type_ html_body_part);
+
(Jmap_mail.Email.BodyPart.type_ html_body_part);
(* Validate attachments *)
-
let attachments = Jmap_mail.Jmap_email.attachments email in
+
let attachments = Jmap_mail.Email.attachments email in
check bool "Has attachments" true (Option.is_some attachments);
let attachments_list = Option.get attachments in
check int "One attachment" 1 (List.length attachments_list);
let attachment = List.nth attachments_list 0 in
check string "Attachment name" "Q4_Report.pdf"
-
(Option.get (Jmap_mail.Jmap_email.BodyPart.name attachment));
+
(Option.get (Jmap_mail.Email.BodyPart.name attachment));
(* Validate bodyValues *)
-
let body_values = Jmap_mail.Jmap_email.body_values email in
+
let body_values = Jmap_mail.Email.body_values email in
check bool "Has bodyValues" true (Option.is_some body_values);
let values_list = Option.get body_values in
check int "Two bodyValues" 2 (List.length values_list);
···
(* Text body value *)
check bool "Has bodyValue for part 1" true (List.mem_assoc "1" values_list);
let text_value = List.assoc "1" values_list in
-
let text_content = Jmap_mail.Jmap_email.BodyValue.value text_value in
+
let text_content = Jmap_mail.Email.BodyValue.value text_value in
check bool "Text content starts with 'Hi Alice'" true
(String.starts_with ~prefix:"Hi Alice" text_content);
check bool "Text not truncated" false
-
(Jmap_mail.Jmap_email.BodyValue.is_truncated text_value);
+
(Jmap_mail.Email.BodyValue.is_truncated text_value);
check bool "Text no encoding problem" false
-
(Jmap_mail.Jmap_email.BodyValue.is_encoding_problem text_value);
+
(Jmap_mail.Email.BodyValue.is_encoding_problem text_value);
(* HTML body value *)
check bool "Has bodyValue for part 2" true (List.mem_assoc "2" values_list);
let html_value = List.assoc "2" values_list in
-
let html_content = Jmap_mail.Jmap_email.BodyValue.value html_value in
+
let html_content = Jmap_mail.Email.BodyValue.value html_value in
check bool "HTML content starts with '<html>'" true
(String.starts_with ~prefix:"<html>" html_content);
check bool "HTML not truncated" false
-
(Jmap_mail.Jmap_email.BodyValue.is_truncated html_value)
+
(Jmap_mail.Email.BodyValue.is_truncated html_value)
let test_email_query_request () =
let json = load_json "data/mail/email_query_request.json" in
-
let request = Jmap_mail.Jmap_email.Query.request_of_json json in
+
let request = Jmap_mail.Email.Query.request_of_json json in
(* Validate account_id *)
-
let account_id = Jmap_mail.Jmap_email.Query.account_id request in
-
check string "Account ID" "u123456" (Jmap_core.Jmap_id.to_string account_id);
+
let account_id = Jmap_mail.Email.Query.account_id request in
+
check string "Account ID" "u123456" (Jmap_core.Id.to_string account_id);
(* Validate limit *)
-
let limit = Jmap_mail.Jmap_email.Query.limit request in
+
let limit = Jmap_mail.Email.Query.limit request in
check bool "Has limit" true (Option.is_some limit);
check int "Limit is 50" 50
-
(Jmap_core.Jmap_primitives.UnsignedInt.to_int (Option.get limit));
+
(Jmap_core.Primitives.UnsignedInt.to_int (Option.get limit));
(* Validate calculateTotal *)
-
let calc_total = Jmap_mail.Jmap_email.Query.calculate_total request in
+
let calc_total = Jmap_mail.Email.Query.calculate_total request in
check bool "Calculate total is true" true (Option.value ~default:false calc_total);
(* Validate collapseThreads *)
-
let collapse = Jmap_mail.Jmap_email.Query.collapse_threads request in
+
let collapse = Jmap_mail.Email.Query.collapse_threads request in
check bool "Collapse threads is false" false (Option.value ~default:true collapse);
(* Validate position *)
-
let position = Jmap_mail.Jmap_email.Query.position request in
+
let position = Jmap_mail.Email.Query.position request in
check bool "Has position" true (Option.is_some position);
check int "Position is 0" 0
-
(Jmap_core.Jmap_primitives.Int53.to_int (Option.get position))
+
(Jmap_core.Primitives.Int53.to_int (Option.get position))
let test_email_query_response () =
let json = load_json "data/mail/email_query_response.json" in
-
let response = Jmap_mail.Jmap_email.Query.response_of_json json in
+
let response = Jmap_mail.Email.Query.response_of_json json in
(* Validate account_id *)
-
let account_id = Jmap_core.Jmap_standard_methods.Query.response_account_id response in
-
check string "Account ID" "u123456" (Jmap_core.Jmap_id.to_string account_id);
+
let account_id = Jmap_core.Standard_methods.Query.response_account_id response in
+
check string "Account ID" "u123456" (Jmap_core.Id.to_string account_id);
(* Validate query state *)
-
let query_state = Jmap_core.Jmap_standard_methods.Query.query_state response in
+
let query_state = Jmap_core.Standard_methods.Query.query_state response in
check string "Query state" "eq42:100" query_state;
(* Validate can calculate changes *)
-
let can_calc = Jmap_core.Jmap_standard_methods.Query.can_calculate_changes response in
+
let can_calc = Jmap_core.Standard_methods.Query.can_calculate_changes response in
check bool "Can calculate changes" true can_calc;
(* Validate position *)
-
let position = Jmap_core.Jmap_standard_methods.Query.response_position response in
-
check int "Position is 0" 0 (Jmap_core.Jmap_primitives.UnsignedInt.to_int position);
+
let position = Jmap_core.Standard_methods.Query.response_position response in
+
check int "Position is 0" 0 (Jmap_core.Primitives.UnsignedInt.to_int position);
(* Validate IDs *)
-
let ids = Jmap_core.Jmap_standard_methods.Query.ids response in
+
let ids = Jmap_core.Standard_methods.Query.ids response in
check int "Five IDs returned" 5 (List.length ids);
-
check string "First ID" "e015" (Jmap_core.Jmap_id.to_string (List.nth ids 0));
-
check string "Last ID" "e005" (Jmap_core.Jmap_id.to_string (List.nth ids 4));
+
check string "First ID" "e015" (Jmap_core.Id.to_string (List.nth ids 0));
+
check string "Last ID" "e005" (Jmap_core.Id.to_string (List.nth ids 4));
(* Validate total *)
-
let total = Jmap_core.Jmap_standard_methods.Query.total response in
+
let total = Jmap_core.Standard_methods.Query.total response in
check bool "Has total" true (Option.is_some total);
check int "Total is 5" 5
-
(Jmap_core.Jmap_primitives.UnsignedInt.to_int (Option.get total))
+
(Jmap_core.Primitives.UnsignedInt.to_int (Option.get total))
let test_email_set_request () =
let json = load_json "data/mail/email_set_request.json" in
-
let request = Jmap_mail.Jmap_email.Set.request_of_json json in
+
let request = Jmap_mail.Email.Set.request_of_json json in
(* Validate account_id *)
-
let account_id = Jmap_core.Jmap_standard_methods.Set.account_id request in
-
check string "Account ID" "u123456" (Jmap_core.Jmap_id.to_string account_id);
+
let account_id = Jmap_core.Standard_methods.Set.account_id request in
+
check string "Account ID" "u123456" (Jmap_core.Id.to_string account_id);
(* Validate ifInState *)
-
let if_in_state = Jmap_core.Jmap_standard_methods.Set.if_in_state request in
+
let if_in_state = Jmap_core.Standard_methods.Set.if_in_state request in
check bool "Has ifInState" true (Option.is_some if_in_state);
check string "ifInState value" "e42:100" (Option.get if_in_state);
(* Validate create *)
-
let create = Jmap_core.Jmap_standard_methods.Set.create request in
+
let create = Jmap_core.Standard_methods.Set.create request in
check bool "Has create" true (Option.is_some create);
let create_list = Option.get create in
check int "One email to create" 1 (List.length create_list);
let (create_id, _email) = List.nth create_list 0 in
-
check string "Create ID" "temp-email-1" (Jmap_core.Jmap_id.to_string create_id);
+
check string "Create ID" "temp-email-1" (Jmap_core.Id.to_string create_id);
(* Validate update *)
-
let update = Jmap_core.Jmap_standard_methods.Set.update request in
+
let update = Jmap_core.Standard_methods.Set.update request in
check bool "Has update" true (Option.is_some update);
let update_list = Option.get update in
check int "Two emails to update" 2 (List.length update_list);
(* Validate destroy *)
-
let destroy = Jmap_core.Jmap_standard_methods.Set.destroy request in
+
let destroy = Jmap_core.Standard_methods.Set.destroy request in
check bool "Has destroy" true (Option.is_some destroy);
let destroy_list = Option.get destroy in
check int "One email to destroy" 1 (List.length destroy_list);
-
check string "Destroy ID" "e099" (Jmap_core.Jmap_id.to_string (List.nth destroy_list 0))
+
check string "Destroy ID" "e099" (Jmap_core.Id.to_string (List.nth destroy_list 0))
let test_email_set_response () =
let json = load_json "data/mail/email_set_response.json" in
-
let response = Jmap_mail.Jmap_email.Set.response_of_json json in
+
let response = Jmap_mail.Email.Set.response_of_json json in
(* Validate account_id *)
-
let account_id = Jmap_core.Jmap_standard_methods.Set.response_account_id response in
-
check string "Account ID" "u123456" (Jmap_core.Jmap_id.to_string account_id);
+
let account_id = Jmap_core.Standard_methods.Set.response_account_id response in
+
check string "Account ID" "u123456" (Jmap_core.Id.to_string account_id);
(* Validate states *)
-
let old_state = Jmap_core.Jmap_standard_methods.Set.old_state response in
+
let old_state = Jmap_core.Standard_methods.Set.old_state response in
check bool "Has old state" true (Option.is_some old_state);
check string "Old state" "e42:100" (Option.get old_state);
-
let new_state = Jmap_core.Jmap_standard_methods.Set.new_state response in
+
let new_state = Jmap_core.Standard_methods.Set.new_state response in
check string "New state" "e42:103" new_state;
(* Validate created *)
-
let created = Jmap_core.Jmap_standard_methods.Set.created response in
+
let created = Jmap_core.Standard_methods.Set.created response in
check bool "Has created" true (Option.is_some created);
let created_list = Option.get created in
check int "One email created" 1 (List.length created_list);
let (temp_id, email) = List.nth created_list 0 in
-
check string "Created temp ID" "temp-email-1" (Jmap_core.Jmap_id.to_string temp_id);
-
check string "Created email ID" "e101" (Jmap_core.Jmap_id.to_string (Jmap_mail.Jmap_email.id email));
+
check string "Created temp ID" "temp-email-1" (Jmap_core.Id.to_string temp_id);
+
check string "Created email ID" "e101" (Jmap_core.Id.to_string (Jmap_mail.Email.id email));
check string "Created thread ID" "t050"
-
(Jmap_core.Jmap_id.to_string (Jmap_mail.Jmap_email.thread_id email));
+
(Jmap_core.Id.to_string (Jmap_mail.Email.thread_id email));
(* Validate updated *)
-
let updated = Jmap_core.Jmap_standard_methods.Set.updated response in
+
let updated = Jmap_core.Standard_methods.Set.updated response in
check bool "Has updated" true (Option.is_some updated);
let updated_map = Option.get updated in
check int "Two emails updated" 2 (List.length updated_map);
(* Validate destroyed *)
-
let destroyed = Jmap_core.Jmap_standard_methods.Set.destroyed response in
+
let destroyed = Jmap_core.Standard_methods.Set.destroyed response in
check bool "Has destroyed" true (Option.is_some destroyed);
let destroyed_list = Option.get destroyed in
check int "One email destroyed" 1 (List.length destroyed_list);
-
check string "Destroyed ID" "e099" (Jmap_core.Jmap_id.to_string (List.nth destroyed_list 0))
+
check string "Destroyed ID" "e099" (Jmap_core.Id.to_string (List.nth destroyed_list 0))
let test_email_import_request () =
let json = load_json "data/mail/email_import_request.json" in
-
let request = Jmap_mail.Jmap_email.Import.request_of_json json in
+
let request = Jmap_mail.Email.Import.request_of_json json in
(* Validate account_id *)
-
let account_id = Jmap_mail.Jmap_email.Import.account_id request in
-
check string "Account ID" "u123456" (Jmap_core.Jmap_id.to_string account_id);
+
let account_id = Jmap_mail.Email.Import.account_id request in
+
check string "Account ID" "u123456" (Jmap_core.Id.to_string account_id);
(* Validate ifInState *)
-
let if_in_state = Jmap_mail.Jmap_email.Import.if_in_state request in
+
let if_in_state = Jmap_mail.Email.Import.if_in_state request in
check bool "Has ifInState" true (Option.is_some if_in_state);
check string "ifInState value" "e42:103" (Option.get if_in_state);
(* Validate emails *)
-
let emails = Jmap_mail.Jmap_email.Import.emails request in
+
let emails = Jmap_mail.Email.Import.emails request in
check int "Two emails to import" 2 (List.length emails);
let (import_id1, import_email1) = List.nth emails 0 in
-
check string "First import ID" "temp-import-1" (Jmap_core.Jmap_id.to_string import_id1);
-
let blob_id1 = Jmap_mail.Jmap_email.Import.import_blob_id import_email1 in
+
check string "First import ID" "temp-import-1" (Jmap_core.Id.to_string import_id1);
+
let blob_id1 = Jmap_mail.Email.Import.import_blob_id import_email1 in
check string "First blob ID starts correctly" "Gb5f55i6"
-
(String.sub (Jmap_core.Jmap_id.to_string blob_id1) 0 8);
+
(String.sub (Jmap_core.Id.to_string blob_id1) 0 8);
-
let keywords1 = Jmap_mail.Jmap_email.Import.import_keywords import_email1 in
+
let keywords1 = Jmap_mail.Email.Import.import_keywords import_email1 in
check bool "First email has $seen keyword" true
(List.mem_assoc "$seen" keywords1)
let test_email_import_response () =
let json = load_json "data/mail/email_import_response.json" in
-
let response = Jmap_mail.Jmap_email.Import.response_of_json json in
+
let response = Jmap_mail.Email.Import.response_of_json json in
(* Validate account_id *)
-
let account_id = Jmap_mail.Jmap_email.Import.response_account_id response in
-
check string "Account ID" "u123456" (Jmap_core.Jmap_id.to_string account_id);
+
let account_id = Jmap_mail.Email.Import.response_account_id response in
+
check string "Account ID" "u123456" (Jmap_core.Id.to_string account_id);
(* Validate states *)
-
let old_state = Jmap_mail.Jmap_email.Import.old_state response in
+
let old_state = Jmap_mail.Email.Import.old_state response in
check bool "Has old state" true (Option.is_some old_state);
check string "Old state" "e42:103" (Option.get old_state);
-
let new_state = Jmap_mail.Jmap_email.Import.new_state response in
+
let new_state = Jmap_mail.Email.Import.new_state response in
check string "New state" "e42:105" new_state;
(* Validate created *)
-
let created = Jmap_mail.Jmap_email.Import.created response in
+
let created = Jmap_mail.Email.Import.created response in
check bool "Has created" true (Option.is_some created);
let created_list = Option.get created in
check int "Two emails imported" 2 (List.length created_list);
let (temp_id1, email1) = List.nth created_list 0 in
-
check string "First temp ID" "temp-import-1" (Jmap_core.Jmap_id.to_string temp_id1);
-
check string "First email ID" "e102" (Jmap_core.Jmap_id.to_string (Jmap_mail.Jmap_email.id email1));
+
check string "First temp ID" "temp-import-1" (Jmap_core.Id.to_string temp_id1);
+
check string "First email ID" "e102" (Jmap_core.Id.to_string (Jmap_mail.Email.id email1));
check string "First thread ID" "t051"
-
(Jmap_core.Jmap_id.to_string (Jmap_mail.Jmap_email.thread_id email1));
+
(Jmap_core.Id.to_string (Jmap_mail.Email.thread_id email1));
let (temp_id2, email2) = List.nth created_list 1 in
-
check string "Second temp ID" "temp-import-2" (Jmap_core.Jmap_id.to_string temp_id2);
-
check string "Second email ID" "e103" (Jmap_core.Jmap_id.to_string (Jmap_mail.Jmap_email.id email2))
+
check string "Second temp ID" "temp-import-2" (Jmap_core.Id.to_string temp_id2);
+
check string "Second email ID" "e103" (Jmap_core.Id.to_string (Jmap_mail.Email.id email2))
let test_email_parse_request () =
let json = load_json "data/mail/email_parse_request.json" in
-
let request = Jmap_mail.Jmap_email.Parse.request_of_json json in
+
let request = Jmap_mail.Email.Parse.request_of_json json in
(* Validate account_id *)
-
let account_id = Jmap_mail.Jmap_email.Parse.account_id request in
-
check string "Account ID" "u123456" (Jmap_core.Jmap_id.to_string account_id);
+
let account_id = Jmap_mail.Email.Parse.account_id request in
+
check string "Account ID" "u123456" (Jmap_core.Id.to_string account_id);
(* Validate blob_ids *)
-
let blob_ids = Jmap_mail.Jmap_email.Parse.blob_ids request in
+
let blob_ids = Jmap_mail.Email.Parse.blob_ids request in
check int "One blob ID" 1 (List.length blob_ids);
let blob_id = List.nth blob_ids 0 in
check string "Blob ID starts correctly" "Gb5f77k8"
-
(String.sub (Jmap_core.Jmap_id.to_string blob_id) 0 8);
+
(String.sub (Jmap_core.Id.to_string blob_id) 0 8);
(* Validate fetch options *)
-
let fetch_text = Jmap_mail.Jmap_email.Parse.fetch_text_body_values request in
+
let fetch_text = Jmap_mail.Email.Parse.fetch_text_body_values request in
check bool "Fetch text body values" true (Option.value ~default:false fetch_text);
-
let fetch_html = Jmap_mail.Jmap_email.Parse.fetch_html_body_values request in
+
let fetch_html = Jmap_mail.Email.Parse.fetch_html_body_values request in
check bool "Fetch HTML body values" true (Option.value ~default:false fetch_html);
-
let max_bytes = Jmap_mail.Jmap_email.Parse.max_body_value_bytes request in
+
let max_bytes = Jmap_mail.Email.Parse.max_body_value_bytes request in
check bool "Has max bytes" true (Option.is_some max_bytes);
check int "Max bytes is 16384" 16384
-
(Jmap_core.Jmap_primitives.UnsignedInt.to_int (Option.get max_bytes))
+
(Jmap_core.Primitives.UnsignedInt.to_int (Option.get max_bytes))
let test_email_parse_response () =
let json = load_json "data/mail/email_parse_response.json" in
-
let response = Jmap_mail.Jmap_email.Parse.response_of_json json in
+
let response = Jmap_mail.Email.Parse.response_of_json json in
(* Validate account_id *)
-
let account_id = Jmap_mail.Jmap_email.Parse.response_account_id response in
-
check string "Account ID" "u123456" (Jmap_core.Jmap_id.to_string account_id);
+
let account_id = Jmap_mail.Email.Parse.response_account_id response in
+
check string "Account ID" "u123456" (Jmap_core.Id.to_string account_id);
(* Validate parsed *)
-
let parsed = Jmap_mail.Jmap_email.Parse.parsed response in
+
let parsed = Jmap_mail.Email.Parse.parsed response in
check bool "Has parsed emails" true (Option.is_some parsed);
let parsed_list = Option.get parsed in
check int "One email parsed" 1 (List.length parsed_list);
let (blob_id, email) = List.nth parsed_list 0 in
check string "Blob ID starts correctly" "Gb5f77k8"
-
(String.sub (Jmap_core.Jmap_id.to_string blob_id) 0 8);
+
(String.sub (Jmap_core.Id.to_string blob_id) 0 8);
(* Validate parsed email *)
check string "Subject" "Important Announcement"
-
(Option.get (Jmap_mail.Jmap_email.subject email));
-
check bool "Has no attachment" false (Jmap_mail.Jmap_email.has_attachment email);
+
(Option.get (Jmap_mail.Email.subject email));
+
check bool "Has no attachment" false (Jmap_mail.Email.has_attachment email);
(* Validate from *)
-
let from = Option.get (Jmap_mail.Jmap_email.from email) in
+
let from = Option.get (Jmap_mail.Email.from email) in
check int "One from address" 1 (List.length from);
let from_addr = List.nth from 0 in
check string "From name" "Charlie Green"
-
(Option.get (Jmap_mail.Jmap_email.EmailAddress.name from_addr));
+
(Option.get (Jmap_mail.Email.EmailAddress.name from_addr));
check string "From email" "charlie@company.com"
-
(Jmap_mail.Jmap_email.EmailAddress.email from_addr);
+
(Jmap_mail.Email.EmailAddress.email from_addr);
(* Validate bodyStructure (simple text/plain) *)
-
let body_structure = Jmap_mail.Jmap_email.body_structure email in
+
let body_structure = Jmap_mail.Email.body_structure email in
check bool "Has bodyStructure" true (Option.is_some body_structure);
let body_part = Option.get body_structure in
-
check string "Body type" "text/plain" (Jmap_mail.Jmap_email.BodyPart.type_ body_part);
+
check string "Body type" "text/plain" (Jmap_mail.Email.BodyPart.type_ body_part);
check string "Body part ID" "1"
-
(Option.get (Jmap_mail.Jmap_email.BodyPart.part_id body_part));
+
(Option.get (Jmap_mail.Email.BodyPart.part_id body_part));
check int "Body size" 1523
-
(Jmap_core.Jmap_primitives.UnsignedInt.to_int (Jmap_mail.Jmap_email.BodyPart.size body_part));
+
(Jmap_core.Primitives.UnsignedInt.to_int (Jmap_mail.Email.BodyPart.size body_part));
(* Validate textBody *)
-
let text_body = Jmap_mail.Jmap_email.text_body email in
+
let text_body = Jmap_mail.Email.text_body email in
check bool "Has textBody" true (Option.is_some text_body);
let text_body_list = Option.get text_body in
check int "One textBody part" 1 (List.length text_body_list);
(* Validate htmlBody is empty *)
-
let html_body = Jmap_mail.Jmap_email.html_body email in
+
let html_body = Jmap_mail.Email.html_body email in
check bool "Has htmlBody" true (Option.is_some html_body);
let html_body_list = Option.get html_body in
check int "No htmlBody parts" 0 (List.length html_body_list);
(* Validate attachments is empty *)
-
let attachments = Jmap_mail.Jmap_email.attachments email in
+
let attachments = Jmap_mail.Email.attachments email in
check bool "Has attachments" true (Option.is_some attachments);
let attachments_list = Option.get attachments in
check int "No attachments" 0 (List.length attachments_list);
(* Validate bodyValues *)
-
let body_values = Jmap_mail.Jmap_email.body_values email in
+
let body_values = Jmap_mail.Email.body_values email in
check bool "Has bodyValues" true (Option.is_some body_values);
let values_list = Option.get body_values in
check int "One bodyValue" 1 (List.length values_list);
check bool "Has bodyValue for part 1" true (List.mem_assoc "1" values_list);
let body_value = List.assoc "1" values_list in
-
let content = Jmap_mail.Jmap_email.BodyValue.value body_value in
+
let content = Jmap_mail.Email.BodyValue.value body_value in
check bool "Content starts with 'Team'" true
(String.starts_with ~prefix:"Team" content);
(* Validate notParsable and notFound are empty *)
-
let not_parsable = Jmap_mail.Jmap_email.Parse.not_parsable response in
+
let not_parsable = Jmap_mail.Email.Parse.not_parsable response in
check bool "Has notParsable" true (Option.is_some not_parsable);
check int "No unparsable blobs" 0 (List.length (Option.get not_parsable));
-
let not_found = Jmap_mail.Jmap_email.Parse.not_found response in
+
let not_found = Jmap_mail.Email.Parse.not_found response in
check bool "Has notFound" true (Option.is_some not_found);
check int "No blobs not found" 0 (List.length (Option.get not_found))
+69
stack/jmap/test/test_unified_api.ml
···
+
(** Test demonstrating the unified Jmap API *)
+
+
let test_module_aliases () =
+
(* Using the clean, ergonomic unified Jmap module *)
+
let id1 = Jmap.Id.of_string "test123" in
+
let id2 = Jmap.Id.of_string "test456" in
+
+
assert (Jmap.Id.to_string id1 = "test123");
+
assert (Jmap.Id.to_string id2 = "test456");
+
+
(* Test capability creation *)
+
let caps = [Jmap.Capability.core; Jmap.Capability.mail] in
+
assert (List.length caps = 2);
+
+
(* Test primitives *)
+
let limit = Jmap.Primitives.UnsignedInt.of_int 10 in
+
assert (Jmap.Primitives.UnsignedInt.to_int limit = 10);
+
+
(* Test comparator *)
+
let sort = Jmap.Comparator.v ~property:"receivedAt" ~is_ascending:false () in
+
assert (Jmap.Comparator.property sort = "receivedAt");
+
assert (not (Jmap.Comparator.is_ascending sort));
+
+
print_endline "✓ Unified Jmap module API works correctly";
+
print_endline " - Short aliases: Jmap.Id, Jmap.Capability, etc.";
+
print_endline " - Mail modules: Jmap.Email, Jmap.Mailbox, etc.";
+
print_endline " - Client API: Jmap.Client"
+
+
let test_mail_module_aliases () =
+
(* The unified module provides direct access to mail modules *)
+
let account_id = Jmap.Id.of_string "test-account" in
+
let limit = Jmap.Primitives.UnsignedInt.of_int 10 in
+
+
let query_req = Jmap.Email.Query.request_v
+
~account_id
+
~limit
+
~calculate_total:true
+
()
+
in
+
+
(* Verify it works *)
+
let _json = Jmap.Email.Query.request_to_json query_req in
+
+
print_endline "✓ Unified mail module aliases work";
+
print_endline " - Jmap.Email, Jmap.Mailbox, Jmap.Thread";
+
print_endline " - Clean and ergonomic"
+
+
let test_submodule_aliases () =
+
(* You can also use the submodules directly for specialized use *)
+
let id1 = Jmap_core.Id.of_string "test123" in
+
let id2 = Jmap_mail.Email.Query.request_v
+
~account_id:id1
+
~limit:(Jmap_core.Primitives.UnsignedInt.of_int 5)
+
()
+
in
+
let _json = Jmap_mail.Email.Query.request_to_json id2 in
+
+
print_endline "✓ Submodule access works";
+
print_endline " - Jmap_core.Id, Jmap_mail.Email";
+
print_endline " - For specialized use cases"
+
+
let () =
+
print_endline "=== Testing Unified Jmap API ===\n";
+
test_module_aliases ();
+
print_endline "";
+
test_mail_module_aliases ();
+
print_endline "";
+
test_submodule_aliases ();
+
print_endline "\n✓ All tests passed!"