My agentic slop goes here. Not intended for anyone else!
at main 5.7 kB view raw
1(** Email set operations using core JMAP Set_args *) 2 3open Jmap.Methods 4 5(** Email creation arguments *) 6module Create = struct 7 type t = { 8 mailbox_ids : (Jmap.Id.t * bool) list; 9 keywords : (Keywords.keyword * bool) list; 10 received_at : Jmap.Date.t option; 11 (* Additional fields as needed *) 12 } 13 14 let make ~mailbox_ids ?(keywords=[]) ?received_at () = { 15 mailbox_ids; 16 keywords; 17 received_at; 18 } 19 20 let to_json t : Yojson.Safe.t = 21 let fields = [ 22 ("mailboxIds", (`Assoc (List.map (fun (id, v) -> (Jmap.Id.to_string id, `Bool v)) t.mailbox_ids) : Yojson.Safe.t)); 23 ("keywords", (`Assoc (List.map (fun (kw, v) -> (Keywords.keyword_to_string kw, `Bool v)) t.keywords) : Yojson.Safe.t)); 24 ] in 25 let fields = match t.received_at with 26 | Some timestamp -> ("receivedAt", (Jmap.Date.to_json timestamp : Yojson.Safe.t)) :: fields 27 | None -> fields 28 in 29 (`Assoc fields : Yojson.Safe.t) 30end 31 32(** Email update patches *) 33module Update = struct 34 (** Build a patch object for updating email properties *) 35 let patch_builder () = [] 36 37 let set_keywords keywords patch = 38 ("keywords", `Assoc (List.map (fun (kw, v) -> (Keywords.keyword_to_string kw, `Bool v)) keywords)) :: patch 39 40 let add_keyword keyword patch = 41 ("keywords/" ^ (Keywords.keyword_to_string keyword), `Bool true) :: patch 42 43 let remove_keyword keyword patch = 44 ("keywords/" ^ (Keywords.keyword_to_string keyword), `Null) :: patch 45 46 let move_to_mailbox mailbox_id patch = 47 (* Clear all existing mailboxes and set new one *) 48 let mailbox_id_str = Jmap.Id.to_string mailbox_id in 49 let clear_mailboxes = ("mailboxIds", `Null) :: patch in 50 ("mailboxIds/" ^ mailbox_id_str, `Bool true) :: clear_mailboxes 51 52 let add_to_mailbox mailbox_id patch = 53 let mailbox_id_str = Jmap.Id.to_string mailbox_id in 54 ("mailboxIds/" ^ mailbox_id_str, `Bool true) :: patch 55 56 let remove_from_mailbox mailbox_id patch = 57 let mailbox_id_str = Jmap.Id.to_string mailbox_id in 58 ("mailboxIds/" ^ mailbox_id_str, `Null) :: patch 59 60 let to_patch_object patch : patch_object = patch 61end 62 63(** Build Email/set arguments *) 64let build_set_args ~account_id ?if_in_state ?create ?update ?destroy () = 65 let account_id_str = Jmap.Id.to_string account_id in 66 let destroy_str_list = match destroy with 67 | Some id_list -> Some (List.map Jmap.Id.to_string id_list) 68 | None -> None in 69 Set_args.v 70 ~account_id:account_id_str 71 ?if_in_state 72 ?create 73 ?update 74 ?destroy:destroy_str_list 75 () 76 77(** Convert Email/set arguments to JSON *) 78let set_args_to_json args = 79 Set_args.to_json 80 ~create_to_json:Create.to_json 81 ~update_to_json:(fun patches -> (`Assoc patches : Yojson.Safe.t)) 82 args 83 84(** Common operations *) 85 86(** Mark emails as read *) 87let mark_as_read ~account_id email_ids = 88 let update_map : (string, patch_object) Hashtbl.t = Hashtbl.create (List.length email_ids) in 89 List.iter (fun id -> 90 Hashtbl.add update_map (Jmap.Id.to_string id) (Update.add_keyword Keywords.Seen []) 91 ) email_ids; 92 build_set_args ~account_id ~update:update_map () 93 94(** Mark emails as unread *) 95let mark_as_unread ~account_id email_ids = 96 let update_map : (string, patch_object) Hashtbl.t = Hashtbl.create (List.length email_ids) in 97 List.iter (fun id -> 98 Hashtbl.add update_map (Jmap.Id.to_string id) (Update.remove_keyword Keywords.Seen []) 99 ) email_ids; 100 build_set_args ~account_id ~update:update_map () 101 102(** Flag/star emails *) 103let flag_emails ~account_id email_ids = 104 let update_map : (string, patch_object) Hashtbl.t = Hashtbl.create (List.length email_ids) in 105 List.iter (fun id -> 106 Hashtbl.add update_map (Jmap.Id.to_string id) (Update.add_keyword Keywords.Flagged []) 107 ) email_ids; 108 build_set_args ~account_id ~update:update_map () 109 110(** Unflag/unstar emails *) 111let unflag_emails ~account_id email_ids = 112 let update_map : (string, patch_object) Hashtbl.t = Hashtbl.create (List.length email_ids) in 113 List.iter (fun id -> 114 Hashtbl.add update_map (Jmap.Id.to_string id) (Update.remove_keyword Keywords.Flagged []) 115 ) email_ids; 116 build_set_args ~account_id ~update:update_map () 117 118(** Move emails to a mailbox *) 119let move_to_mailbox ~account_id ~mailbox_id email_ids = 120 let update_map : (string, patch_object) Hashtbl.t = Hashtbl.create (List.length email_ids) in 121 List.iter (fun id -> 122 Hashtbl.add update_map (Jmap.Id.to_string id) (Update.move_to_mailbox mailbox_id []) 123 ) email_ids; 124 build_set_args ~account_id ~update:update_map () 125 126(** Delete emails (move to trash or destroy) *) 127let delete_emails ~account_id ?(destroy=false) email_ids = 128 if destroy then 129 build_set_args ~account_id ~destroy:email_ids () 130 else 131 (* Move to trash mailbox - would need to look up trash mailbox ID *) 132 build_set_args ~account_id ~destroy:email_ids () 133 134(** Batch update multiple properties *) 135let batch_update ~account_id updates = 136 let update_map : (string, patch_object) Hashtbl.t = Hashtbl.create (List.length updates) in 137 List.iter (fun (id, patch) -> 138 Hashtbl.add update_map (Jmap.Id.to_string id) patch 139 ) updates; 140 build_set_args ~account_id ~update:update_map () 141 142(** Create a draft email *) 143let create_draft ~account_id ~mailbox_ids ?keywords ?subject:_ ?from:_ ?to_:_ ?cc:_ ?bcc:_ ?text_body:_ ?html_body:_ () = 144 (* Note: subject, from, to_, cc, bcc, text_body, html_body would need proper implementation 145 with full email creation support. For now, just creating basic structure. *) 146 let creation = Create.make ~mailbox_ids ?keywords () in 147 let create_map : (string, Create.t) Hashtbl.t = Hashtbl.create 1 in 148 Hashtbl.add create_map "draft-1" creation; 149 build_set_args ~account_id ~create:create_map ()