(** Eio-based JMAP client implementation interface. This module provides functions to interact with a JMAP server using Eio for structured concurrency and network communication. @see RFC 8620, Section 4 *) (** TLS configuration options *) type tls_config = { authenticator : X509.Authenticator.t option; (** Custom TLS authenticator *) certificates : Tls.Config.own_cert list; (** Client certificates for mutual TLS *) ciphers : Tls.Ciphersuite.ciphersuite list option; (** Allowed cipher suites *) version : (Tls.Core.tls_version * Tls.Core.tls_version) option; (** Min and max TLS versions *) alpn_protocols : string list option; (** ALPN protocol list *) } (** Configuration options for a JMAP client context *) type client_config = { connect_timeout : float option; (** Connection timeout in seconds *) request_timeout : float option; (** Request timeout in seconds *) max_concurrent_requests : int option; (** Maximum concurrent requests *) max_request_size : int option; (** Maximum request size in bytes *) user_agent : string option; (** User-Agent header value *) authentication_header : string option; (** Custom Authentication header name *) tls : tls_config option; (** TLS configuration *) } (** Authentication method options *) type auth_method = | Basic of string * string (** Basic auth with username and password *) | Bearer of string (** Bearer token auth *) | Custom of (string * string) (** Custom header name and value *) | Session_cookie of (string * string) (** Session cookie name and value *) | No_auth (** No authentication *) (** Represents an active JMAP connection context. Opaque type. *) type context (** Represents an active EventSource connection. Opaque type. *) type event_source_connection (** A request builder for constructing and sending JMAP requests *) type request_builder (** Create default TLS configuration with system CA certificates *) val default_tls_config : unit -> tls_config (** Create default configuration options *) val default_config : unit -> client_config (** {1 Session Discovery and Authentication} *) (** Authentication types for session retrieval. *) type session_auth = | Bearer_token of string (** OAuth2 bearer token *) | Basic_auth of string * string (** Username and password *) | No_session_auth (** No authentication *) (** Service discovery for JMAP. Attempts to discover the JMAP session endpoint using well-known URIs. Follows RFC 8620 service discovery process. @param env Eio environment for network operations @param domain The domain to discover JMAP service for @return The session URL if discovery succeeds, None otherwise @see RFC 8620, Section 2.2 *) val discover_session : env:< net : 'a Eio.Net.t ; clock : 'b Eio.Time.clock ; .. > -> domain:string -> Uri.t option (** Fetch a session object from a given URL with authentication. Retrieves and parses the session resource from the server using cohttp-eio. @param env Eio environment for network operations @param url The session endpoint URL @param auth Authentication credentials to use @return The parsed session object or error message *) val get_session : env:< net : 'a Eio.Net.t ; clock : 'b Eio.Time.clock ; .. > -> url:Uri.t -> auth:session_auth -> (Jmap.Session.Session.t, string) result (** Extract domain from email address for discovery. Utility function to extract the domain part from an email address. @param email Email address to extract domain from @return Domain string or error message *) val extract_domain_from_email : email:string -> (string, string) result (** Create a client context with the specified configuration @return The context object used for JMAP API calls *) val create_client : ?config:client_config -> unit -> context (** Enable connection pooling on a client context. @param ctx The client context to enable pooling for @param sw Eio switch for resource management @param pool_config Optional pool configuration @return The connection pool instance *) val enable_connection_pooling : context -> sw:Eio.Switch.t -> ?pool_config:Connection_pool.pool_config -> unit -> Connection_pool.t (** Get connection pool statistics if pooling is enabled. @param ctx The client context @return Pool statistics or None if pooling not enabled *) val get_connection_stats : context -> Connection_pool.pool_stats option (** Connect to a JMAP server and retrieve the session. This handles discovery (if needed) and authentication. @param env The Eio environment for network operations. @param ctx The client context. @param ?session_url Optional direct URL to the Session resource. @param ?username Optional username (e.g., email address) for discovery. @param ?use_tls Whether to use TLS for the connection (default true). @param ?auth_method Authentication method to use (default Basic). @param credentials Authentication credentials. @return A result with either (context, session) or an error. *) val connect : < net : 'a Eio.Net.t ; .. > -> context -> ?session_url:Uri.t -> ?username:string -> host:string -> ?port:int -> ?use_tls:bool -> ?auth_method:auth_method -> unit -> (context * Jmap.Session.Session.t) Jmap.Error.result (** Create a request builder for constructing a JMAP request. @param ctx The client context. @return A request builder object. *) val build : context -> request_builder (** Specify capabilities to use with type-safe variants. @param builder The request builder. @param capabilities List of capability variants to use. @return The updated request builder. *) val using : request_builder -> Jmap.Capability.t list -> request_builder (** Add a method call to a request builder. @param builder The request builder. @param method_name Typed method name variant. @param args Method arguments. @param id Method call ID. @return The updated request builder. *) val add_method_call : request_builder -> Jmap.Method_names.jmap_method -> Yojson.Safe.t -> string -> request_builder (** Create a reference to a previous method call result. @param result_of Method call ID to reference. @param name Path in the response. @return A ResultReference to use in another method call. *) val create_reference : string -> string -> Jmap.Wire.Result_reference.t (** Execute a request and return the response. @param env The Eio environment for network operations. @param builder The request builder to execute. @return The JMAP response from the server. *) val execute : < net : 'a Eio.Net.t ; .. > -> request_builder -> Jmap.Wire.Response.t Jmap.Error.result (** Perform a JMAP API request. @param env The Eio environment for network operations. @param ctx The connection context. @param request The JMAP request object. @return The JMAP response from the server. *) val request : < net : 'a Eio.Net.t ; .. > -> context -> Jmap.Wire.Request.t -> Jmap.Wire.Response.t Jmap.Error.result (** Upload binary data. @param env The Eio environment for network operations. @param ctx The connection context. @param account_id The target account ID. @param content_type The MIME type of the data. @param data_stream A stream providing the binary data chunks. @return A result with either an upload response or an error. *) val upload : < net : 'a Eio.Net.t ; .. > -> context -> account_id:string -> content_type:string -> data_stream:string Seq.t -> Jmap.Binary.Upload_response.t Jmap.Error.result (** Download binary data. @param env The Eio environment for network operations. @param ctx The connection context. @param account_id The account ID. @param blob_id The blob ID to download. @param ?content_type The desired Content-Type for the download response. @param ?name The desired filename for the download response. @return A result with either a stream of data chunks or an error. *) val download : < net : 'a Eio.Net.t ; .. > -> context -> account_id:string -> blob_id:string -> ?content_type:string -> ?name:string -> unit -> (string Seq.t) Jmap.Error.result (** Copy blobs between accounts. @param env The Eio environment for network operations. @param ctx The connection context. @param from_account_id Source account ID. @param account_id Destination account ID. @param blob_ids List of blob IDs to copy. @return A result with either the copy response or an error. *) val copy_blobs : < net : 'a Eio.Net.t ; .. > -> context -> from_account_id:string -> account_id:string -> blob_ids:string list -> Jmap.Binary.Blob_copy_response.t Jmap.Error.result (** Connect to the EventSource for push notifications. @param env The Eio environment for network operations. @param ctx The connection context. @param ?types List of types to subscribe to (default "*"). @param ?close_after Request server to close after first state event. @param ?ping Request ping interval in seconds (default 0). @return A result with either a tuple of connection handle and event stream, or an error. @see RFC 8620, Section 7.3 *) val connect_event_source : < net : 'a Eio.Net.t ; .. > -> context -> ?types:string list -> ?close_after:[`State | `No] -> ?ping:Jmap.UInt.t -> unit -> (event_source_connection * ([`State of Jmap.Push.State_change.t | `Ping of Jmap.Push.Event_source_ping_data.t ] Seq.t)) Jmap.Error.result (** Create a websocket connection for JMAP over WebSocket. @param env The Eio environment for network operations. @param ctx The connection context. @return A result with either a websocket connection or an error. @see RFC 8887 *) val connect_websocket : < net : 'a Eio.Net.t ; .. > -> context -> event_source_connection Jmap.Error.result (** Send a message over a websocket connection. @param env The Eio environment for network operations. @param conn The websocket connection. @param request The JMAP request to send. @return A result with either the response or an error. *) val websocket_send : < net : 'a Eio.Net.t ; .. > -> event_source_connection -> Jmap.Wire.Request.t -> Jmap.Wire.Response.t Jmap.Error.result (** Close an EventSource or WebSocket connection. @param conn The connection handle. @return A result with either unit or an error. *) val close_connection : event_source_connection -> unit Jmap.Error.result (** Close the JMAP connection context. @return A result with either unit or an error. *) val close : context -> unit Jmap.Error.result (** {2 Helper Methods for Common Tasks} *) (** Helper to get a single object by ID. @param env The Eio environment for network operations. @param ctx The context. @param method_name The get method (e.g., "Email/get"). @param account_id The account ID. @param object_id The ID of the object to get. @param ?properties Optional list of properties to fetch. @return A result with either the object as JSON or an error. *) val get_object : < net : 'a Eio.Net.t ; .. > -> context -> method_name:Jmap.Method_names.jmap_method -> account_id:string -> object_id:string -> ?properties:string list -> unit -> Yojson.Safe.t Jmap.Error.result (** Helper to set up the connection with minimal options. @param env The Eio environment for network operations. @param host The JMAP server hostname. @param username Username for basic auth. @param password Password for basic auth. @param ?use_tls Whether to use TLS (default true). @param ?port Port number (default 443 for TLS, 80 for plain). @return A result with either (context, session) or an error. *) val quick_connect : < net : 'a Eio.Net.t ; .. > -> host:string -> username:string -> password:string -> ?use_tls:bool -> ?port:int -> unit -> (context * Jmap.Session.Session.t) Jmap.Error.result (** Perform a Core/echo request to test connectivity. @param env The Eio environment for network operations. @param ctx The JMAP connection context. @param ?data Optional data to echo back. @return A result with either the response or an error. *) val echo : < net : 'a Eio.Net.t ; .. > -> context -> ?data:Yojson.Safe.t -> unit -> Yojson.Safe.t Jmap.Error.result (** {2 Request Builder Pattern} *) (** High-level request builder for constructing JMAP requests in a type-safe manner. This provides convenience functions that eliminate manual JSON construction. *) module Request_builder : sig type t = request_builder (** Create a new request builder with specified capabilities. @param using List of capability variants to use in the request @return A new request builder with the specified capabilities *) val create : using:Jmap.Capability.t list -> context -> t (** Add a query method call to the request builder. @param t The request builder @param method_name The JMAP method name (e.g., "Email/query") @param args The query arguments, already converted to JSON @param method_call_id Unique identifier for this method call @return Updated request builder *) val add_query : t -> method_name:Jmap.Method_names.jmap_method -> args:Yojson.Safe.t -> method_call_id:string -> t (** Add a get method call to the request builder. @param t The request builder @param method_name The JMAP method name variant @param args The get arguments, already converted to JSON @param method_call_id Unique identifier for this method call @return Updated request builder *) val add_get : t -> method_name:Jmap.Method_names.jmap_method -> args:Yojson.Safe.t -> method_call_id:string -> t (** Add a get method call with result reference to the request builder. @param t The request builder @param method_name The JMAP method name variant @param account_id The account ID to use @param result_reference Reference to a previous method call result @param ?properties Optional list of properties to fetch @param method_call_id Unique identifier for this method call @return Updated request builder *) val add_get_with_reference : t -> method_name:Jmap.Method_names.jmap_method -> account_id:string -> result_reference:Jmap.Wire.Result_reference.t -> ?properties:string list -> method_call_id:string -> unit -> t (** Convert the request builder to a JMAP Request object. @param t The request builder @return A JMAP Request ready to be sent *) val to_request : t -> Jmap.Wire.Request.t end (** {2 Email Operations} *) (** High-level email operations that map to JMAP email methods *) module Email : sig (** Arguments for Email/query method calls. This type eliminates manual JSON construction for Email/query requests. It follows the JMAP Email/query specification exactly. @see RFC 8621, Section 4.4 *) module Query_args : sig type t (** Create Email/query arguments. @param account_id The account ID to query in @param ?filter Optional filter to apply (None = no filter) @param ?sort Optional sort order (None = server default) @param ?position Starting position in results (None = start from beginning) @param ?limit Maximum number of results (None = server default) @param ?calculate_total Whether to calculate total result count (None = false) @param ?collapse_threads Whether to collapse threads (None = false) @return Email query arguments object *) val create : account_id:string -> ?filter:Jmap.Methods.Filter.t -> ?sort:Jmap.Methods.Comparator.t list -> ?position:int -> ?limit:Jmap.UInt.t -> ?calculate_total:bool -> ?collapse_threads:bool -> unit -> t (** Convert query arguments to JSON for JMAP requests. @param t The query arguments to serialize @return JSON representation suitable for Email/query method calls *) val to_json : t -> Yojson.Safe.t end (** Arguments for Email/get method calls. This type eliminates manual JSON construction for Email/get requests and properly handles result references from previous method calls. @see RFC 8621, Section 4.2 *) module Get_args : sig type t (** Create Email/get arguments with specific IDs. @param account_id The account ID to get emails from @param ids List of email IDs to fetch @param ?properties Optional list of properties to return (None = all properties) @return Email get arguments object *) val create : account_id:string -> ids:string list -> ?properties:string list -> unit -> t (** Create Email/get arguments with result reference to another method. This is used when the IDs come from a previous method call result. @param account_id The account ID to get emails from @param result_of Method call ID that produced the IDs @param name Method name that produced the IDs (e.g., "Email/query") @param path JSON pointer to the IDs in the result (e.g., "/ids") @param ?properties Optional list of properties to return (None = all properties) @return Email get arguments object *) val create_with_reference : account_id:string -> result_of:string -> name:string -> path:string -> ?properties:string list -> unit -> t (** Convert get arguments to JSON for JMAP requests. @param t The get arguments to serialize @return JSON representation suitable for Email/get method calls *) val to_json : t -> Yojson.Safe.t end (** Get an email by ID @param env The Eio environment for network operations @param ctx The JMAP client context @param account_id The account ID @param email_id The email ID to fetch @param ?properties Optional list of properties to fetch @return The email object or an error *) val get_email : < net : 'a Eio.Net.t ; .. > -> context -> account_id:string -> email_id:string -> ?properties:string list -> unit -> Jmap_email.Email.t Jmap.Error.result (** Search for emails using a filter @param env The Eio environment for network operations @param ctx The JMAP client context @param account_id The account ID @param filter The search filter @param ?sort Optional sort criteria (default received date newest first) @param ?limit Optional maximum number of results @param ?properties Optional properties to fetch for the matching emails @return The list of matching email IDs and optionally the email objects *) val search_emails : < net : 'a Eio.Net.t ; .. > -> context -> account_id:string -> filter:Jmap.Methods.Filter.t -> ?sort:Jmap.Methods.Comparator.t list -> ?limit:Jmap.UInt.t -> ?position:int -> ?properties:string list -> unit -> (string list * Jmap_email.Email.t list option) Jmap.Error.result (** Mark multiple emails with a keyword @param env The Eio environment for network operations @param ctx The JMAP client context @param account_id The account ID @param email_ids List of email IDs to update @param keyword The keyword to add @return The result of the operation *) val mark_emails : < net : 'a Eio.Net.t ; .. > -> context -> account_id:string -> email_ids:string list -> keyword:Jmap_email.Keywords.keyword -> unit -> unit Jmap.Error.result (** Mark emails as seen/read @param env The Eio environment for network operations @param ctx The JMAP client context @param account_id The account ID @param email_ids List of email IDs to mark @return The result of the operation *) val mark_as_seen : < net : 'a Eio.Net.t ; .. > -> context -> account_id:string -> email_ids:string list -> unit -> unit Jmap.Error.result (** Mark emails as unseen/unread @param env The Eio environment for network operations @param ctx The JMAP client context @param account_id The account ID @param email_ids List of email IDs to mark @return The result of the operation *) val mark_as_unseen : < net : 'a Eio.Net.t ; .. > -> context -> account_id:string -> email_ids:string list -> unit -> unit Jmap.Error.result (** Move emails to a different mailbox @param env The Eio environment for network operations @param ctx The JMAP client context @param account_id The account ID @param email_ids List of email IDs to move @param mailbox_id Destination mailbox ID @param ?remove_from_mailboxes Optional list of source mailbox IDs to remove from @return The result of the operation *) val move_emails : < net : 'a Eio.Net.t ; .. > -> context -> account_id:string -> email_ids:string list -> mailbox_id:string -> ?remove_from_mailboxes:string list -> unit -> unit Jmap.Error.result (** Import an RFC822 message @param env The Eio environment for network operations @param ctx The JMAP client context @param account_id The account ID @param rfc822 Raw message content @param mailbox_ids Mailboxes to add the message to @param ?keywords Optional keywords to set @param ?received_at Optional received timestamp @return The ID of the imported email *) val import_email : < net : 'a Eio.Net.t ; .. > -> context -> account_id:string -> rfc822:string -> mailbox_ids:string list -> ?keywords:Jmap_email.Keywords.t -> ?received_at:Jmap.Date.t -> unit -> string Jmap.Error.result (** {2 JSON Parsing Functions} *) (** Parse an Email object from JSON representation. This function eliminates the need for manual JSON parsing with Yojson.Safe.Util. It properly handles all standard Email fields from RFC 8621 and provides descriptive error messages for malformed JSON. @param json JSON object representing an email as returned by Email/get @return Parsed Email object @see RFC 8621, Section 4.1 *) (* val from_json : Yojson.Safe.t -> t (** Parse an EmailAddress object from JSON representation. @param json JSON object with 'email' and optional 'name' fields @return Parsed EmailAddress object @see RFC 8621, Section 4.1.2.3 *) val from_json_address : Yojson.Safe.t -> Email_address.t (** Parse Keywords from JSON representation. @param json JSON object mapping keyword strings to boolean values @return Parsed Keywords set @see RFC 8621, Section 4.1.1 *) val from_json_keywords : Yojson.Safe.t -> Jmap_email.Keywords.t *) end (** {2 Utility Functions} *) (** Authentication utilities for handling credential files and tokens *) module Auth : sig (** Read an API key from a file. @param filename Path to the file containing the API key @return The API key as a string, with whitespace trimmed *) val read_api_key : string -> string (** Read an API key from the default ".api-key" file in the current directory. @return The API key as a string, with whitespace trimmed *) val read_api_key_default : unit -> string end (** Session utilities for common session operations *) module Session_utils : sig (** Print detailed session information to stdout for debugging. @param session The JMAP session to display *) val print_session_info : Jmap.Session.Session.t -> unit (** Get the primary mail account ID from a session. Falls back to the first available account if no primary mail account is found. @param session The JMAP session @return The account ID to use for mail operations *) val get_primary_mail_account : Jmap.Session.Session.t -> string end (** Response utilities for extracting data from JMAP responses *) module Response : sig (** Extract a specific method response from a JMAP Response. @param method_name Typed method name to search for @param method_call_id The method call ID to match @param response The JMAP response to search @return The method response arguments or an error *) val extract_method : method_name:Jmap.Method_names.jmap_method -> method_call_id:string -> Jmap.Wire.Response.t -> Yojson.Safe.t Jmap.Error.result (** Extract the first method response with a given name, ignoring call ID. @param method_name Typed method name to search for @param response The JMAP response to search @return The method response arguments or an error *) val extract_method_by_name : method_name:Jmap.Method_names.jmap_method -> Jmap.Wire.Response.t -> Yojson.Safe.t Jmap.Error.result end (** {2 Email High-Level Operations} *) (** High-level email method operations that combine builders from jmap-email with I/O *) module Email_methods : sig (** Request builder for email method chaining *) module RequestBuilder : sig type t (** Create a new request builder with jmap-unix context *) val create : context -> t (** Add Email/query method *) val email_query : ?account_id:string -> ?filter:Yojson.Safe.t -> ?sort:Jmap.Methods.Comparator.t list -> ?limit:int -> ?position:int -> t -> t (** Add Email/get method with automatic result reference *) val email_get : ?account_id:string -> ?ids:Jmap.Id.t list -> ?properties:string list -> ?reference_from:string -> (* Call ID to reference *) t -> t (** Add Email/set method *) val email_set : ?account_id:string -> ?create:(string * Yojson.Safe.t) list -> ?update:(Jmap.Id.t * Jmap.Patch.t) list -> ?destroy:Jmap.Id.t list -> t -> t (** Add Thread/get method *) val thread_get : ?account_id:string -> ?ids:Jmap.Id.t list -> t -> t (** Add Mailbox/query method *) val mailbox_query : ?account_id:string -> ?filter:Yojson.Safe.t -> ?sort:Jmap.Methods.Comparator.t list -> t -> t (** Add Mailbox/get method *) val mailbox_get : ?account_id:string -> ?ids:Jmap.Id.t list -> t -> t (** Execute the built request *) val execute : < net : 'a Eio.Net.t ; .. > -> session:Jmap.Session.Session.t -> t -> (Jmap.Wire.Response.t, Jmap.Error.error) result (** Get specific method response by type *) val get_response : method_:Jmap.Method_names.jmap_method -> ?call_id:string -> Jmap.Wire.Response.t -> (Yojson.Safe.t, Jmap.Error.error) result end (** Response parsing functions *) module Response : sig (** Extract and parse Email/query response *) val parse_email_query : ?call_id:string -> Jmap.Wire.Response.t -> (Yojson.Safe.t, Jmap.Error.error) result (** Extract and parse Email/get response *) val parse_email_get : ?call_id:string -> Jmap.Wire.Response.t -> (Yojson.Safe.t list, Jmap.Error.error) result (** Extract and parse Thread/get response *) val parse_thread_get : ?call_id:string -> Jmap.Wire.Response.t -> (Yojson.Safe.t list, Jmap.Error.error) result (** Extract and parse Mailbox/get response *) val parse_mailbox_get : ?call_id:string -> Jmap.Wire.Response.t -> (Yojson.Safe.t list, Jmap.Error.error) result end (** Common email operation patterns *) (** Execute Email/query and automatically chain Email/get *) val query_and_fetch : < net : 'a Eio.Net.t ; .. > -> ctx:context -> session:Jmap.Session.Session.t -> ?account_id:string -> ?filter:Yojson.Safe.t -> ?sort:Jmap.Methods.Comparator.t list -> ?limit:int -> ?properties:string list -> unit -> (Yojson.Safe.t list, Jmap.Error.error) result (** Get emails by IDs *) val get_emails_by_ids : < net : 'a Eio.Net.t ; .. > -> ctx:context -> session:Jmap.Session.Session.t -> ?account_id:string -> ?properties:string list -> Jmap.Id.t list -> (Yojson.Safe.t list, Jmap.Error.error) result (** Get all mailboxes *) val get_mailboxes : < net : 'a Eio.Net.t ; .. > -> ctx:context -> session:Jmap.Session.Session.t -> ?account_id:string -> unit -> (Yojson.Safe.t list, Jmap.Error.error) result (** Find mailbox by role (e.g., "inbox", "sent", "drafts") *) val find_mailbox_by_role : < net : 'a Eio.Net.t ; .. > -> ctx:context -> session:Jmap.Session.Session.t -> ?account_id:string -> string -> (Yojson.Safe.t option, Jmap.Error.error) result end (** {2 Email Query Operations} *) (** High-level email query operations using Eio *) module Email_query : sig (** Execute just the query (returns IDs only) *) val execute_query : < net : 'a Eio.Net.t ; .. > -> ctx:context -> session:Jmap.Session.Session.t -> Yojson.Safe.t -> (Yojson.Safe.t, Jmap.Error.error) result (** Execute query and automatically fetch email data *) val execute_with_fetch : < net : 'a Eio.Net.t ; .. > -> ctx:context -> session:Jmap.Session.Session.t -> Yojson.Safe.t -> (Yojson.Safe.t, Jmap.Error.error) result end (** {2 Email Batch Operations} *) (** High-level batch email operations using Eio *) module Email_batch : sig (** Execute batch operations *) val execute : < net : 'a Eio.Net.t ; .. > -> ctx:context -> session:Jmap.Session.Session.t -> ?account_id:string -> Yojson.Safe.t -> (Yojson.Safe.t, Jmap.Error.error) result (** Common batch workflow operations *) (** Process inbox - mark as read and archive *) val process_inbox : < net : 'a Eio.Net.t ; .. > -> ctx:context -> session:Jmap.Session.Session.t -> email_ids:Jmap.Id.t list -> (Yojson.Safe.t, Jmap.Error.error) result (** Bulk delete spam/trash emails older than N days *) val cleanup_old_emails : < net : 'a Eio.Net.t ; .. > -> ctx:context -> session:Jmap.Session.Session.t -> mailbox_role:string -> (* "spam" or "trash" *) older_than_days:int -> (Yojson.Safe.t, Jmap.Error.error) result (** Organize emails by sender into mailboxes *) val organize_by_sender : < net : 'a Eio.Net.t ; .. > -> ctx:context -> session:Jmap.Session.Session.t -> rules:(string * string) list -> (* sender email -> mailbox name *) (Yojson.Safe.t, Jmap.Error.error) result (** Progress callback for long operations *) type progress = { current : int; total : int; message : string; } (** Execute with progress reporting *) val execute_with_progress : < net : 'a Eio.Net.t ; .. > -> ctx:context -> session:Jmap.Session.Session.t -> ?account_id:string -> progress_fn:(progress -> unit) -> Yojson.Safe.t -> (Yojson.Safe.t, Jmap.Error.error) result end (** High-level email submission API. Provides ergonomic functions for submitting emails via JMAP, including envelope management and delivery tracking. @see RFC 8621, Section 7 *) module Email_submission : module type of Email_submission