IMAP in OCaml
at main 108 lines 3.2 kB view raw
1(*--------------------------------------------------------------------------- 2 Copyright (c) 2025 Anil Madhavapeddy <anil@recoil.org>. All rights reserved. 3 SPDX-License-Identifier: ISC 4 ---------------------------------------------------------------------------*) 5 6(** FETCH Items 7 8 Fetch data items for the FETCH command as specified in RFC 9051 Section 6.4.5. *) 9 10(** {1 Request Items} *) 11 12type request = 13 | Envelope 14 | Flags 15 | Internaldate 16 | Rfc822 17 | Rfc822_size 18 | Rfc822_header 19 | Rfc822_text 20 | Uid 21 | Body 22 | Bodystructure 23 | Body_section of string * (int * int) option 24 | Body_peek of string * (int * int) option 25 | Binary of string * (int * int) option 26 | Binary_peek of string * (int * int) option 27 | Binary_size of string 28 | Modseq (** Request MODSEQ value - RFC 7162 CONDSTORE *) 29 30let pp_request ppf = function 31 | Envelope -> Fmt.string ppf "ENVELOPE" 32 | Flags -> Fmt.string ppf "FLAGS" 33 | Internaldate -> Fmt.string ppf "INTERNALDATE" 34 | Rfc822 -> Fmt.string ppf "RFC822" 35 | Rfc822_size -> Fmt.string ppf "RFC822.SIZE" 36 | Rfc822_header -> Fmt.string ppf "RFC822.HEADER" 37 | Rfc822_text -> Fmt.string ppf "RFC822.TEXT" 38 | Uid -> Fmt.string ppf "UID" 39 | Body -> Fmt.string ppf "BODY" 40 | Bodystructure -> Fmt.string ppf "BODYSTRUCTURE" 41 | Body_section (s, _) -> Fmt.pf ppf "BODY[%s]" s 42 | Body_peek (s, _) -> Fmt.pf ppf "BODY.PEEK[%s]" s 43 | Binary (s, _) -> Fmt.pf ppf "BINARY[%s]" s 44 | Binary_peek (s, _) -> Fmt.pf ppf "BINARY.PEEK[%s]" s 45 | Binary_size s -> Fmt.pf ppf "BINARY.SIZE[%s]" s 46 | Modseq -> Fmt.string ppf "MODSEQ" 47 48(** {1 Response Items} *) 49 50type response = 51 | Item_envelope of Envelope.t 52 | Item_flags of Flag.t list 53 | Item_internaldate of string 54 | Item_rfc822_size of int64 55 | Item_uid of int64 56 | Item_modseq of int64 57 | Item_body of Body.t 58 | Item_bodystructure of Body.t 59 | Item_body_section of { 60 section : Body.section option; 61 origin : int option; 62 data : string option; 63 } 64 | Item_binary of { section : int list; data : string option } 65 | Item_binary_size of { section : int list; size : int64 } 66 67(** {1 Parsed Message} *) 68 69type message = { 70 seq : int; 71 uid : int64 option; 72 flags : Flag.t list option; 73 envelope : Envelope.t option; 74 body_structure : Body.t option; 75 internaldate : string option; 76 size : int64 option; 77 modseq : int64 option; 78 body_section : string option; 79} 80 81let empty_message = 82 { 83 seq = 0; 84 uid = None; 85 flags = None; 86 envelope = None; 87 body_structure = None; 88 internaldate = None; 89 size = None; 90 modseq = None; 91 body_section = None; 92 } 93 94let message_of_items seq items = 95 List.fold_left 96 (fun msg item -> 97 match item with 98 | Item_uid u -> { msg with uid = Some u } 99 | Item_flags f -> { msg with flags = Some f } 100 | Item_envelope e -> { msg with envelope = Some e } 101 | Item_body b | Item_bodystructure b -> { msg with body_structure = Some b } 102 | Item_internaldate d -> { msg with internaldate = Some d } 103 | Item_rfc822_size s -> { msg with size = Some s } 104 | Item_modseq m -> { msg with modseq = Some m } 105 | Item_body_section { data; _ } -> { msg with body_section = data } 106 | _ -> msg) 107 { empty_message with seq } 108 items