JMAP OCaml Client#
A type-safe OCaml interface to the JMAP protocol (RFC8620) and JMAP Mail extension (RFC8621).
Note: This library is largely AI-generated and has not been audited carefully. It's a proof-of-concept implementation of the JMAP specification.
Overview#
JMAP (JSON Meta Application Protocol) is a modern protocol for synchronizing email, calendars, and contacts designed as a replacement for legacy protocols like IMAP. This OCaml implementation provides:
- Type-safe OCaml interfaces to the JMAP Core and Mail specifications
- Authentication with username/password or API tokens (Fastmail support)
- Convenient functions for common email and mailbox operations
- Support for composing complex multi-part requests with result references
- Typed handling of message flags, keywords, and mailbox attributes
Installation#
Add to your project with opam:
opam install jmap
Or pin the development version:
opam pin add jmap.dev git+https://github.com/example/jmap-ocaml.git
Quick Start#
open Lwt.Syntax
open Jmap
open Jmap_mail
(* Authentication *)
let token = Sys.getenv "JMAP_API_TOKEN" in
let* result = Jmap_mail.login_with_token
~uri:"https://api.fastmail.com/jmap/session"
~api_token:token
in
match result with
| Error err ->
Printf.eprintf "Authentication failed\n";
exit 1
| Ok conn ->
(* Get primary account ID *)
let mail_capability = Jmap_mail.Capability.to_string Jmap_mail.Capability.Mail in
let account_id = List.assoc mail_capability conn.session.primary_accounts in
(* Get mailboxes *)
let* mailboxes_result = Jmap_mail.get_mailboxes conn ~account_id in
match mailboxes_result with
| Error err ->
Printf.eprintf "Failed to get mailboxes\n";
exit 1
| Ok mailboxes ->
(* Find the inbox *)
let inbox = List.find_opt (fun m ->
m.Types.role = Some Types.Inbox
) mailboxes in
match inbox with
| None ->
Printf.eprintf "No inbox found\n";
exit 1
| Some inbox ->
(* Get recent emails *)
let* emails_result = Jmap_mail.get_messages_in_mailbox
conn
~account_id
~mailbox_id:inbox.Types.id
~limit:10
()
in
match emails_result with
| Error err ->
Printf.eprintf "Failed to get emails\n";
exit 1
| Ok emails ->
(* Display emails *)
List.iter (fun email ->
Printf.printf "%s - %s\n"
(Option.value ~default:"<unknown>"
(Option.map (fun addrs ->
match addrs with
| [] -> "<unknown>"
| addr::_ -> addr.Types.email
) email.Types.from))
(Option.value ~default:"<no subject>" email.Types.subject)
) emails;
Lwt.return_unit
Features#
-
Core JMAP Protocol
- Session handling
- API request/response management
- Type-safe representation of all JMAP structures
- Result references for composing multi-step requests
-
JMAP Mail Extension
- Mailbox operations (folders/labels)
- Email retrieval and manipulation
- Thread handling
- Identity management
- Email submission
- Message flags and keywords
-
Fastmail Integration
- API token authentication
- Example tools for listing messages
Documentation#
The library includes comprehensive OCamldoc documentation with cross-references to the relevant sections of the JMAP specifications.
Build the documentation with:
dune build @doc
Example Tools#
The package includes several example tools:
fastmail-list: Lists emails from a Fastmail account (requires JMAP_API_TOKEN)jmap-tutorial-examples: Demonstrates basic JMAP operations as shown in the tutorial