My agentic slop goes here. Not intended for anyone else!
at jsont 13 kB view raw
1(** Email body part and body value representation. 2 3 This module provides types and operations for email body parts and decoded 4 body values as defined in RFC 8621 Section 4.1.4. Body parts represent the 5 MIME structure of email messages, while body values contain decoded text content. 6 7 Body parts can be either leaf parts containing actual content or multipart 8 containers holding sub-parts. They include information about MIME type, encoding, 9 disposition, size, and other RFC 2045-2047 MIME attributes. 10 11 @see <https://www.rfc-editor.org/rfc/rfc8621.html#section-4.1.4> RFC 8621, Section 4.1.4 - Email Body Structure 12*) 13 14 15(** Email body part representation. 16 17 Represents a single part within an email's MIME structure as specified in 18 RFC 8621 Section 4.1.4. Each body part can be either a leaf part containing 19 actual content or a multipart container holding sub-parts. 20*) 21type t 22 23(** JSON serialization interface *) 24include Jmap_sigs.JSONABLE with type t := t 25 26(** Pretty-printing interface *) 27include Jmap_sigs.PRINTABLE with type t := t 28 29(** Get the part ID for referencing this specific part. 30 @param t The body part 31 @return Part identifier, or None for multipart container types *) 32val id : t -> string option 33 34(** Get the blob ID for downloading the part content. 35 @param t The body part 36 @return Blob identifier for content access, or None for multipart types *) 37val blob_id : t -> Jmap.Id.t option 38 39(** Get the size of the part in bytes. 40 @param t The body part 41 @return Size in bytes of the decoded content *) 42val size : t -> Jmap.UInt.t 43 44(** Get the list of MIME headers for this part. 45 @param t The body part 46 @return List of header fields specific to this body part *) 47val headers : t -> Header.t list 48 49(** Get the filename parameter from Content-Disposition or Content-Type. 50 @param t The body part 51 @return Filename if present, None otherwise *) 52val name : t -> string option 53 54(** Get the MIME content type. 55 @param t The body part 56 @return MIME type (e.g., "text/plain", "image/jpeg") *) 57val mime_type : t -> string 58 59(** Get the character set parameter. 60 @param t The body part 61 @return Character encoding (e.g., "utf-8", "iso-8859-1"), None if not specified *) 62val charset : t -> string option 63 64(** Get the Content-Disposition header value. 65 @param t The body part 66 @return Disposition type (e.g., "attachment", "inline"), None if not specified *) 67val disposition : t -> string option 68 69(** Get the Content-Disposition parameters. 70 @param t The body part 71 @return Map of disposition parameters (e.g., filename), None if not present *) 72val disposition_params : t -> (string, string) Hashtbl.t option 73 74(** Get the boundary parameter for multipart types. 75 @param t The body part 76 @return Boundary string for multipart content, None otherwise *) 77val boundary : t -> string option 78 79(** Get the Content-Transfer-Encoding header value. 80 @param t The body part 81 @return Transfer encoding method (e.g., "base64", "quoted-printable"), None if not specified *) 82val content_transfer_encoding : t -> string option 83 84(** Get the Content-ID header value for referencing within HTML content. 85 @param t The body part 86 @return Content identifier for inline references, None if not specified *) 87val cid : t -> string option 88 89(** Get the Content-Language header values. 90 @param t The body part 91 @return List of language codes (e.g., ["en"; "fr"]), None if not specified *) 92val language : t -> string list option 93 94(** Get the Content-Location header value. 95 @param t The body part 96 @return URI reference for content location, None if not specified *) 97val location : t -> string option 98 99(** Get nested parts for multipart content types. 100 @param t The body part 101 @return List of sub-parts for multipart types, None for leaf parts *) 102val sub_parts : t -> t list option 103 104(** Get additional headers requested via header properties. 105 @param t The body part 106 @return Map of header names to their JSON values for extended header access *) 107val other_headers : t -> (string, Yojson.Safe.t) Hashtbl.t 108 109(** Create a new body part object. 110 111 Creates a body part with validation of required fields and proper MIME structure. 112 Either Jmap.Id.t+blob_id (for leaf parts) or sub_parts (for multipart) should be provided, 113 but not both. 114 115 @param Jmap.Id.t Optional part identifier for leaf parts 116 @param blob_id Optional blob ID for content access 117 @param size Size in bytes of decoded content 118 @param headers List of MIME headers for this part 119 @param name Optional filename parameter 120 @param mime_type MIME content type 121 @param charset Optional character encoding 122 @param disposition Optional Content-Disposition value 123 @param cid Optional Content-ID for inline references 124 @param language Optional Content-Language codes 125 @param location Optional Content-Location URI 126 @param sub_parts Optional list of nested parts (for multipart types) 127 @param other_headers Optional additional headers map 128 @return Result containing new body part or validation error *) 129val create : 130 ?id:string -> 131 ?blob_id:Jmap.Id.t -> 132 size:Jmap.UInt.t -> 133 headers:Header.t list -> 134 ?name:string -> 135 mime_type:string -> 136 ?charset:string -> 137 ?disposition:string -> 138 ?disposition_params:(string, string) Hashtbl.t -> 139 ?cid:string -> 140 ?language:string list -> 141 ?location:string -> 142 ?sub_parts:t list -> 143 ?boundary:string -> 144 ?content_transfer_encoding:string -> 145 ?other_headers:(string, Yojson.Safe.t) Hashtbl.t -> 146 unit -> (t, string) result 147 148(** Create a new body part object without validation. 149 150 For use when body parts are known to be valid or come from trusted sources 151 like server responses. 152 153 @param Jmap.Id.t Optional part identifier for leaf parts 154 @param blob_id Optional blob ID for content access 155 @param size Size in bytes of decoded content 156 @param headers List of MIME headers for this part 157 @param name Optional filename parameter 158 @param mime_type MIME content type 159 @param charset Optional character encoding 160 @param disposition Optional Content-Disposition value 161 @param cid Optional Content-ID for inline references 162 @param language Optional Content-Language codes 163 @param location Optional Content-Location URI 164 @param sub_parts Optional list of nested parts (for multipart types) 165 @param other_headers Optional additional headers map 166 @return New body part object *) 167val create_unsafe : 168 ?id:string -> 169 ?blob_id:Jmap.Id.t -> 170 size:Jmap.UInt.t -> 171 headers:Header.t list -> 172 ?name:string -> 173 mime_type:string -> 174 ?charset:string -> 175 ?disposition:string -> 176 ?disposition_params:(string, string) Hashtbl.t -> 177 ?cid:string -> 178 ?language:string list -> 179 ?location:string -> 180 ?sub_parts:t list -> 181 ?boundary:string -> 182 ?content_transfer_encoding:string -> 183 ?other_headers:(string, Yojson.Safe.t) Hashtbl.t -> 184 unit -> t 185 186(** Check if body part is a multipart container. 187 @param t The body part 188 @return true if this is a multipart container with sub-parts *) 189val is_multipart : t -> bool 190 191(** Check if body part is a leaf part with content. 192 @param t The body part 193 @return true if this is a leaf part with blob content *) 194val is_leaf : t -> bool 195 196(** Check if body part is an attachment. 197 198 Determines if the part should be treated as an attachment based on 199 Content-Disposition and other heuristics. 200 201 @param t The body part 202 @return true if this part should be treated as an attachment *) 203val is_attachment : t -> bool 204 205(** Check if body part is inline content. 206 207 Determines if the part should be displayed inline based on 208 Content-Disposition and MIME type. 209 210 @param t The body part 211 @return true if this part should be displayed inline *) 212val is_inline : t -> bool 213 214(** Get all leaf parts (non-multipart parts) from a body part tree. 215 216 Recursively traverses multipart structures to find all leaf parts 217 containing actual content. 218 219 @param t The body part (may be multipart or leaf) 220 @return List of all leaf parts in the structure *) 221val get_leaf_parts : t -> t list 222 223(** Find body parts by MIME type. 224 225 Searches the body part tree for parts matching the specified MIME type. 226 Supports exact matching and wildcard patterns (e.g., "text/*"). 227 228 @param t The body part tree to search 229 @param mime_type MIME type to match (supports wildcards) 230 @return List of matching body parts *) 231val find_by_mime_type : t -> string -> t list 232 233(** Generate a unique part ID for a body part at given depth and position. 234 @param depth The nesting depth (0 for top level) 235 @param position The position within the current level 236 @return Generated part ID string *) 237val generate_part_id : int -> int -> string 238 239(** Validate part ID format according to MIME structure. 240 @param part_id The part ID to validate 241 @return true if the part ID has valid format *) 242val is_valid_part_id : string -> bool 243 244(** Get text body parts for textBody property as per RFC 8621 algorithm. 245 @param t The body structure to flatten 246 @return List of parts to display as text body *) 247val get_text_body : t -> t list 248 249(** Get HTML body parts for htmlBody property as per RFC 8621 algorithm. 250 @param t The body structure to flatten 251 @return List of parts to display as HTML body *) 252val get_html_body : t -> t list 253 254(** Get attachment parts for attachments property as per RFC 8621 algorithm. 255 @param t The body structure to flatten 256 @return List of parts to treat as attachments *) 257val get_attachments : t -> t list 258 259(** Extract MIME parameters from Content-Type header in headers list. 260 @param headers List of headers to search 261 @return Content-Type value and parameter list *) 262val extract_mime_params : Header.t list -> string option * (string * string) list 263 264(** Extract Content-Disposition parameters from headers list. 265 @param headers List of headers to search 266 @return Disposition type and parameter list *) 267val extract_disposition_params : Header.t list -> string option * (string * string) list 268 269 270(** Decoded email body content. 271 272 Represents the decoded text content of a body part as specified in RFC 8621 273 Section 4.1.4. This provides access to the actual text content after MIME 274 decoding, along with metadata about potential encoding issues or truncation. 275*) 276module Value : sig 277 (** Decoded body value type *) 278 type t 279 280 (** Get the decoded text content. 281 @param t The body value 282 @return The decoded text content of the body part *) 283 val value : t -> string 284 285 (** Check if there was an encoding problem during decoding. 286 @param t The body value 287 @return true if encoding issues were encountered during decoding *) 288 val has_encoding_problem : t -> bool 289 290 (** Check if the content was truncated by the server. 291 @param t The body value 292 @return true if the content was truncated to fit size limits *) 293 val is_truncated : t -> bool 294 295 (** Create a new body value object. 296 @param value The decoded text content 297 @param encoding_problem Whether encoding problems were encountered (default: false) 298 @param truncated Whether the content was truncated (default: false) 299 @return New body value object *) 300 val create : 301 value:string -> 302 ?encoding_problem:bool -> 303 ?truncated:bool -> 304 unit -> t 305 306 (** Create body value from raw MIME part content with full decoding. 307 308 Applies Content-Transfer-Encoding decoding and character set handling 309 as specified in RFC 8621. 310 311 @param part_content Raw MIME part content 312 @param content_type Content-Type header value for charset extraction 313 @param content_transfer_encoding Transfer encoding method 314 @param max_bytes Maximum bytes to include (0 for no limit) 315 @return Body value with decoded content and encoding problem flags *) 316 val from_mime_part : 317 part_content:string -> 318 content_type:string option -> 319 content_transfer_encoding:string option -> 320 max_bytes:int -> 321 unit -> t 322 323 (** Check if body value contains displayable text content. 324 @param t The body value 325 @return true if content is non-empty after trimming whitespace *) 326 val is_text_content : t -> bool 327 328 (** Get content length in bytes. 329 @param t The body value 330 @return Number of bytes in the decoded content *) 331 val content_length : t -> int 332 333 (** Get content preview (first N characters). 334 @param t The body value 335 @param max_chars Maximum characters to include in preview 336 @return Content preview with ellipsis if truncated *) 337 val preview : t -> max_chars:int -> string 338 339 (** Convert body value to JSON representation. 340 341 Produces JSON object with "value" string field and optional boolean fields 342 for "isEncodingProblem" and "isTruncated" as specified in JMAP. 343 344 @param t The body value to convert 345 @return JSON object with body value fields *) 346 val to_json : t -> Yojson.Safe.t 347 348 (** Parse body value from JSON representation. 349 350 Parses body value from JSON object as received in Email/get responses 351 in the "bodyValues" property. 352 353 @param json JSON object representing a body value 354 @return Result containing parsed body value or parse error *) 355 val of_json : Yojson.Safe.t -> (t, string) result 356end