···379379(** Apple Mail extensions *)
380380module Apple_mail = Jmap_email_apple
381381382382+(** Email query builder and operations *)
383383+module Jmap_email_query = Jmap_email_query
384384+382385(** Legacy aliases for backward compatibility *)
383386module Types : sig
384387 module Keywords = Jmap_email_keywords
+75-39
jmap/jmap-email/jmap_email_query.ml
···104104 sort = [Sort.by_date_desc];
105105 limit_count = None;
106106 position = None;
107107- properties = PropertySets.list_view;
107107+ properties = Jmap_email_property.common_list_properties;
108108 collapse_threads = false;
109109}
110110···128128129129let select_preset preset builder =
130130 let properties = match preset with
131131- | `ListV -> PropertySets.list_view
132132- | `Preview -> PropertySets.preview
133133- | `Full -> PropertySets.full
134134- | `Threading -> PropertySets.threading
131131+ | `ListV -> Jmap_email_property.common_list_properties
132132+ | `Preview -> Jmap_email_property.for_preview ()
133133+ | `Full -> Jmap_email_property.for_reading ()
134134+ | `Threading -> Jmap_email_property.minimal_for_query ()
135135 in
136136 { builder with properties }
137137···145145 can_calculate_changes : bool;
146146}
147147148148-type fetch_result = {
149149- emails : Jmap_email.t list;
148148+type 'email fetch_result = {
149149+ emails : 'email list;
150150 total : int option;
151151}
152152153153+(* JSON generation functions for jmap-unix layer *)
154154+155155+let build_email_query builder =
156156+ let account_id = match builder.account_id with
157157+ | Some id -> id
158158+ | None -> failwith "Account ID must be set before building query"
159159+ in
160160+ let json_fields = [
161161+ ("accountId", `String account_id);
162162+ ("sort", `List (List.map Jmap.Methods.Comparator.to_json builder.sort));
163163+ ] in
164164+ let json_fields = match builder.filter with
165165+ | Some filter -> ("filter", Filter.to_json filter) :: json_fields
166166+ | None -> json_fields
167167+ in
168168+ let json_fields = match builder.limit_count with
169169+ | Some limit -> ("limit", `Int limit) :: json_fields
170170+ | None -> json_fields
171171+ in
172172+ let json_fields = match builder.position with
173173+ | Some pos -> ("position", `Int pos) :: json_fields
174174+ | None -> json_fields
175175+ in
176176+ let json_fields =
177177+ if builder.collapse_threads then
178178+ ("collapseThreads", `Bool true) :: json_fields
179179+ else json_fields
180180+ in
181181+ `Assoc json_fields
182182+183183+let property_preset_to_strings = function
184184+ | `ListV -> Jmap_email_property.to_string_list Jmap_email_property.common_list_properties
185185+ | `Preview -> Jmap_email_property.to_string_list (Jmap_email_property.for_preview ())
186186+ | `Full -> Jmap_email_property.to_string_list (Jmap_email_property.for_reading ())
187187+ | `Threading -> Jmap_email_property.to_string_list (Jmap_email_property.minimal_for_query ())
188188+189189+let build_email_get_with_ref ~account_id ~properties ~result_of ~method_name ~path =
190190+ `Assoc [
191191+ ("accountId", `String account_id);
192192+ ("properties", `List (List.map (fun s -> `String s) properties));
193193+ ("#ids", `Assoc [
194194+ ("resultOf", `String result_of);
195195+ ("name", `String method_name);
196196+ ("path", `String path)
197197+ ])
198198+ ]
199199+200200+let properties_to_strings properties =
201201+ Jmap_email_property.to_string_list properties
202202+153203154204(* Common query builders *)
155155-let inbox ?limit () =
205205+let inbox ?limit:lim () =
156206 let q = query () |> where (Filter.in_mailbox_role "inbox") in
157157- match limit with
207207+ match lim with
158208 | Some n -> limit n q
159209 | None -> q
160210161161-let unread ?limit () =
211211+let unread ?limit:lim () =
162212 let q = query () |> where Filter.unread in
163163- match limit with
213213+ match lim with
164214 | Some n -> limit n q
165215 | None -> q
166216167167-let recent ?limit () =
217217+let recent ?limit:lim () =
168218 let yesterday = Jmap.Date.of_timestamp (Unix.time () -. 86400.) in
169219 let q = query () |> where (Filter.after yesterday) in
170170- match limit with
220220+ match lim with
171221 | Some n -> limit n q
172222 | None -> q
173223174174-let from_sender sender ?limit () =
224224+let from_sender sender ?limit:lim () =
175225 let q = query () |> where (Filter.from sender) in
176176- match limit with
226226+ match lim with
177227 | Some n -> limit n q
178228 | None -> q
179229180180-let search text ?limit () =
230230+let search text ?limit:lim () =
181231 let q = query () |> where (Filter.or_
182232 (Filter.subject_contains text)
183233 (Filter.body_contains text)) in
184184- match limit with
234234+ match lim with
185235 | Some n -> limit n q
186236 | None -> q
187237188188-let flagged ?limit () =
238238+let flagged ?limit:lim () =
189239 let q = query () |> where Filter.flagged in
190190- match limit with
240240+ match lim with
191241 | Some n -> limit n q
192242 | None -> q
193243194194-let with_attachments ?limit () =
244244+let with_attachments ?limit:lim () =
195245 let q = query () |> where Filter.has_attachment in
196196- match limit with
246246+ match lim with
197247 | Some n -> limit n q
198248 | None -> q
199249200200-(* Pretty printing *)
201201-let pp_email ppf email =
202202- let open Format in
203203- fprintf ppf "@[<v 2>Email:@,";
204204- (match Jmap_email.subject email with
205205- | Some s -> fprintf ppf "Subject: %s@," s
206206- | None -> ());
207207- (match Jmap_email.from email with
208208- | Some addrs when addrs <> [] ->
209209- let addr = List.hd addrs in
210210- fprintf ppf "From: %s@," (Jmap_email.Email_address.email addr)
211211- | _ -> ());
212212- (match Jmap_email.received_at email with
213213- | Some ts ->
214214- let date = Jmap.Date.of_timestamp ts in
215215- fprintf ppf "Date: %s@," (Jmap.Date.to_rfc3339 date)
216216- | None -> ());
217217- fprintf ppf "@]"
250250+(* Pretty printing - generic functions that need specific email extractors *)
251251+let pp_email ppf _email =
252252+ (* This function is generic and needs to be specialized at call site *)
253253+ Format.fprintf ppf "Email (generic printer)"
218254219255let pp_email_list ppf emails =
220256 Format.fprintf ppf "@[<v>%a@]"
+54-4
jmap/jmap-email/jmap_email_query.mli
···125125(** Enable thread collapsing *)
126126val collapse_threads : bool -> query_builder -> query_builder
127127128128+(** {1 JSON Generation} *)
129129+130130+(** Build JSON for Email/query method call.
131131+132132+ Converts a query_builder into the JSON format expected by the
133133+ JMAP Email/query method. This is the core function that jmap-unix
134134+ uses to construct Email/query requests.
135135+136136+ @param query_builder The query to convert
137137+ @return JSON object for Email/query method arguments *)
138138+val build_email_query : query_builder -> Yojson.Safe.t
139139+140140+(** Convert property presets to string lists.
141141+142142+ Maps property preset enums to their corresponding string lists
143143+ for use in Email/get requests. Used internally by jmap-unix
144144+ for building method arguments.
145145+146146+ @param preset Property preset to convert
147147+ @return List of property strings *)
148148+val property_preset_to_strings : [`ListV | `Preview | `Full | `Threading] -> string list
149149+150150+(** Build JSON for Email/get method call with result references.
151151+152152+ Creates the JSON for Email/get calls that reference the results of a previous
153153+ Email/query call. This is the standard pattern for chained JMAP requests.
154154+155155+ @param account_id Account identifier
156156+ @param properties List of property strings to fetch
157157+ @param result_of Method call ID to reference (e.g., "q1")
158158+ @param method_name Method name being referenced (e.g., "Email/query")
159159+ @param path Path to extract from result (e.g., "/ids")
160160+ @return JSON object for Email/get method arguments *)
161161+val build_email_get_with_ref :
162162+ account_id:string ->
163163+ properties:string list ->
164164+ result_of:string ->
165165+ method_name:string ->
166166+ path:string ->
167167+ Yojson.Safe.t
168168+169169+(** Convert property list to string list for Email/get requests.
170170+171171+ Maps property variants to their JMAP protocol string representations.
172172+ Used to prepare property lists for Email/get method calls.
173173+174174+ @param properties List of property variants
175175+ @return List of property strings *)
176176+val properties_to_strings : property list -> string list
177177+128178(** {1 Execution} *)
129179130180(** Query result containing email IDs *)
···136186}
137187138188(** Query result with full email data *)
139139-type fetch_result = {
140140- emails : Jmap_email.t list;
189189+type 'email fetch_result = {
190190+ emails : 'email list;
141191 total : int option;
142192}
143193···167217(** {1 Pretty Printing} *)
168218169219(** Pretty-print an email for display *)
170170-val pp_email : Format.formatter -> Jmap_email.t -> unit
220220+val pp_email : Format.formatter -> 'email -> unit
171221172222(** Pretty-print a list of emails as a summary *)
173173-val pp_email_list : Format.formatter -> Jmap_email.t list -> unit223223+val pp_email_list : Format.formatter -> 'email list -> unit
+2-1
jmap/jmap-unix/jmap_unix.ml
···18181919(* Email-layer imports - using proper jmap-email abstractions *)
2020module JmapEmail = Jmap_email
2121-(* module JmapEmailQuery = Jmap_email_query (* Module not available yet *) *)
2121+(* module JmapEmailQuery = Jmap_email_query (* Module interface issue - will implement later *) *)
222223232424(* Simple Base64 encoding function *)
···11921192 | Ok json -> Ok json
11931193 | Error e -> Error e)
11941194 | Error e -> Error e
11951195+11951196end
1196119711971198module Email_batch = struct