My agentic slop goes here. Not intended for anyone else!
at main 11 kB view raw
1(** High-level JMAP Client API. 2 3 This module provides a high-level JMAP client API inspired by the Rust 4 jmap-client library. Features include automatic result reference chaining, 5 comprehensive error handling, and fluent method calls. 6 7 Key features: 8 - Automatic method chaining with result references (no manual call IDs) 9 - Comprehensive error handling with detailed context and retry hints 10 - Fluent builder patterns for complex queries and operations 11 - High-level methods that eliminate manual JSON construction 12 - Production-ready with connection management and resource cleanup 13 14 {b Usage example}: 15 {[ 16 let* client = Client.connect ~credentials env "https://jmap.example.org" in 17 let* emails = Client.query_emails client ~filter:(Filter.in_mailbox inbox_id) ~limit:5 in 18 let* mailbox_id = Client.create_mailbox client ~account_id ~name:"Test" () in 19 Client.destroy_email client ~account_id ~email_id 20 ]} *) 21 22(** {1 Client Lifecycle} *) 23 24(** JMAP client with automatic resource management *) 25type t 26 27(** Enhanced authentication methods *) 28type credentials = [ 29 | `Basic of string * string (** Basic auth with username and password *) 30 | `Bearer of string (** Bearer token auth *) 31 | `Custom of string * string (** Custom header name and value *) 32 | `Session_cookie of string * string (** Session cookie name and value *) 33] 34 35(** Advanced client configuration *) 36type config = { 37 connect_timeout : float option; (** Connection timeout in seconds (default: 10.0) *) 38 request_timeout : float option; (** Request timeout in seconds (default: 30.0) *) 39 max_concurrent_requests : int option; (** Maximum concurrent requests (default: 10) *) 40 max_request_size : int option; (** Maximum request size in bytes (default: 10MB) *) 41 user_agent : string option; (** User-Agent header value *) 42 retry_attempts : int option; (** Number of automatic retries (default: 3) *) 43 retry_delay : float option; (** Base delay between retries in seconds (default: 1.0) *) 44 enable_push : bool; (** Enable push notifications (default: false) *) 45} 46 47(** Create default client configuration *) 48val default_config : unit -> config 49 50(** Connect to JMAP server. 51 52 This single function handles: 53 - Session discovery via .well-known/jmap 54 - Authentication and capability negotiation 55 - Connection pooling and resource setup 56 - Error handling with detailed diagnostics 57 58 @param credentials Authentication method 59 @param env Eio environment for network operations 60 @param url Base server URL (will auto-discover JMAP endpoint) 61 @param config Optional configuration (uses defaults if not provided) 62 @return Connected client ready for operations *) 63val connect : 64 credentials:credentials -> 65 ?config:config -> 66 < net : 'a Eio.Net.t ; .. > -> 67 string -> 68 (t, Jmap.Error.error) result 69 70(** Get the primary account ID for mail operations. 71 Most clients only need this for email, mailbox, and thread operations. *) 72val primary_account : t -> string 73 74(** Get account ID for specific capability. 75 @param capability JMAP capability URI (e.g., "urn:ietf:params:jmap:mail") 76 @return Account ID supporting that capability, or None if not available *) 77val account_for_capability : t -> string -> string option 78 79(** Check if server supports a specific capability *) 80val has_capability : t -> string -> bool 81 82(** Get server capabilities and limits *) 83val capabilities : t -> (string * Yojson.Safe.t) list 84 85(** Close client and cleanup all resources *) 86val close : t -> unit 87 88(** {1 Email Operations} *) 89 90(** High-level email query with automatic result chaining. 91 92 Combines Email/query and Email/get into single operation with automatic 93 result reference handling. No manual JSON construction required. 94 95 @param client Connected JMAP client 96 @param account_id Account to query (uses primary_account if not specified) 97 @param filter Email filter conditions (optional) 98 @param sort Sort criteria list (optional, defaults to date descending) 99 @param limit Maximum results to return (optional, defaults to 20) 100 @param properties Email properties to fetch (optional, uses smart defaults) 101 @return List of email objects matching criteria *) 102val query_emails : 103 t -> 104 ?account_id:string -> 105 ?filter:Jmap_email.Query.Filter.t -> 106 ?sort:Jmap_email.Query.Sort.t list -> 107 ?limit:int -> 108 ?properties:Jmap_email.Property.t list -> 109 unit -> 110 (Jmap_email.Email.t list, Jmap.Error.error) result 111 112(** Get specific emails by ID with property selection. 113 114 @param client Connected JMAP client 115 @param account_id Account containing the emails 116 @param ids List of email IDs to fetch 117 @param properties Properties to include (optional, uses smart defaults) 118 @return List of email objects (may be fewer than requested if some IDs don't exist) *) 119val get_emails : 120 t -> 121 ?account_id:string -> 122 string list -> 123 ?properties:Jmap_email.Property.t list -> 124 unit -> 125 (Jmap_email.Email.t list, Jmap.Error.error) result 126 127(** Import raw email message into mailboxes. 128 129 @param client Connected JMAP client 130 @param account_id Target account 131 @param raw_message Complete RFC 5322 message as bytes 132 @param mailbox_ids List of mailboxes to place the message in 133 @param keywords Initial keywords/flags (optional) 134 @param received_at Override received timestamp (optional, uses current time) 135 @return Imported email object *) 136val import_email : 137 t -> 138 account_id:string -> 139 raw_message:bytes -> 140 mailbox_ids:string list -> 141 ?keywords:string list -> 142 ?received_at:Jmap.Types.date -> 143 unit -> 144 (Jmap_email.Email.t, Jmap.Error.error) result 145 146(** Destroy email by ID. 147 148 @param client Connected JMAP client 149 @param account_id Account containing the email 150 @param email_id Email to destroy 151 @return Success unit or detailed error *) 152val destroy_email : 153 t -> 154 account_id:string -> 155 email_id:string -> 156 (unit, Jmap.Error.error) result 157 158(** Set email keywords (flags) - replaces all existing keywords. 159 160 @param client Connected JMAP client 161 @param account_id Account containing the email 162 @param email_id Email to modify 163 @param keywords New keyword list (e.g., ["$seen"; "$flagged"]) 164 @return Success unit or detailed error *) 165val set_email_keywords : 166 t -> 167 account_id:string -> 168 email_id:string -> 169 keywords:string list -> 170 (unit, Jmap.Error.error) result 171 172(** Set email mailboxes - replaces all existing mailbox assignments. 173 174 @param client Connected JMAP client 175 @param account_id Account containing the email 176 @param email_id Email to modify 177 @param mailbox_ids New mailbox list 178 @return Success unit or detailed error *) 179val set_email_mailboxes : 180 t -> 181 account_id:string -> 182 email_id:string -> 183 mailbox_ids:string list -> 184 (unit, Jmap.Error.error) result 185 186(** {1 Mailbox Operations} *) 187 188(** Query mailboxes with filtering and sorting. 189 190 @param client Connected JMAP client 191 @param account_id Account to query 192 @param filter Mailbox filter conditions (optional) 193 @param sort Sort criteria (optional, defaults to name ascending) 194 @return List of mailbox objects *) 195val query_mailboxes : 196 t -> 197 ?account_id:string -> 198 ?filter:Jmap_email.Mailbox.Filter.t -> 199 ?sort:Jmap_email.Mailbox.Sort.t list -> 200 unit -> 201 (Jmap_email.Mailbox.t list, Jmap.Error.error) result 202 203(** Create new mailbox. 204 205 @param client Connected JMAP client 206 @param account_id Target account 207 @param name Mailbox name (human-readable) 208 @param parent_id Parent mailbox ID for hierarchy (optional) 209 @param role Special mailbox role (optional, e.g., Inbox, Sent) 210 @return ID of newly created mailbox *) 211val create_mailbox : 212 t -> 213 account_id:string -> 214 name:string -> 215 ?parent_id:string -> 216 ?role:Jmap_email.Mailbox.Role.t -> 217 unit -> 218 (string, Jmap.Error.error) result 219 220(** Destroy mailbox. 221 222 @param client Connected JMAP client 223 @param account_id Account containing mailbox 224 @param mailbox_id Mailbox to destroy 225 @param on_destroy_remove_emails If true, delete contained emails; if false, move to Trash (default: false) 226 @return Success unit or detailed error *) 227val destroy_mailbox : 228 t -> 229 account_id:string -> 230 mailbox_id:string -> 231 ?on_destroy_remove_emails:bool -> 232 unit -> 233 (unit, Jmap.Error.error) result 234 235(** {1 Advanced Features} *) 236 237(** Batch request builder for multiple operations with automatic result chaining. 238 239 This provides the foundation for complex multi-method operations while 240 maintaining the automatic result reference system. 241 242 {b Usage example}: 243 {[ 244 let batch = Client.batch client in 245 let query_ref = Batch.query_emails batch ~filter ~limit:10 in 246 let get_ref = Batch.get_emails_ref batch query_ref ~properties in 247 let* (emails, _) = Batch.execute batch in 248 process_emails emails 249 ]} *) 250module Batch : sig 251 type batch_builder 252 type 'a batch_operation 253 254 (** Create new batch request builder *) 255 val create : t -> batch_builder 256 257 (** Add email query to batch with automatic result reference *) 258 val query_emails : 259 batch_builder -> 260 ?account_id:string -> 261 ?filter:Jmap_email.Query.Filter.t -> 262 ?sort:Jmap_email.Query.Sort.t list -> 263 ?limit:int -> 264 unit -> 265 string list batch_operation 266 267 (** Add email get operation using result reference from query *) 268 val get_emails_ref : 269 batch_builder -> 270 string list batch_operation -> 271 ?properties:Jmap_email.Property.t list -> 272 unit -> 273 Jmap_email.Email.t list batch_operation 274 275 (** Execute batch request and return results *) 276 val execute : batch_builder -> (unit, Jmap.Error.error) result 277 278 (** Extract results from completed operations *) 279 val result : 'a batch_operation -> ('a, Jmap.Error.error) result 280end 281 282(** {1 Connection and Resource Management} *) 283 284(** Connection statistics for monitoring *) 285type connection_stats = { 286 requests_sent : int; 287 requests_successful : int; 288 requests_failed : int; 289 bytes_sent : int64; 290 bytes_received : int64; 291 connection_reuses : int; 292 average_response_time : float; 293} 294 295(** Get connection statistics for monitoring *) 296val stats : t -> connection_stats 297 298(** Test connection health *) 299val ping : t -> (unit, Jmap.Error.error) result 300 301(** Force connection refresh (useful after network changes) *) 302val refresh_connection : t -> (unit, Jmap.Error.error) result