My agentic slop goes here. Not intended for anyone else!
1(** Email header field representation.
2
3 This module provides types and operations for email header fields as defined in
4 RFC 8621 Section 4.1.3. Each header field consists of a field name and its raw,
5 unprocessed value as it appears in the original email message.
6
7 Header fields follow RFC 5322 syntax and provide access to both standard headers
8 (Subject, From, To, etc.) and custom headers that may not be parsed into specific
9 Email object properties.
10
11 @see <https://www.rfc-editor.org/rfc/rfc8621.html#section-4.1.3> RFC 8621, Section 4.1.3 - Email Header Fields
12*)
13
14(** Email header field type.
15
16 Represents a single email header field as specified in RFC 8621 Section 4.1.3.
17 Each header consists of a field name and its raw, unprocessed value as it
18 appears in the original email message.
19*)
20type t
21
22(** JSON serialization interface *)
23include Jmap_sigs.JSONABLE with type t := t
24
25(** Pretty-printing interface *)
26include Jmap_sigs.PRINTABLE with type t := t
27
28(** Get the header field name.
29 @param t The header field
30 @return The header field name (e.g., "Subject", "X-Custom-Header") *)
31val name : t -> string
32
33(** Get the raw header field value.
34 @param t The header field
35 @return The unprocessed header value as it appears in the message *)
36val value : t -> string
37
38(** Create a new header field.
39
40 Creates a header field with validation of the field name according to RFC 5322.
41 Header names must contain only printable ASCII characters and cannot contain
42 control characters, spaces, or certain special characters.
43
44 @param name The header field name
45 @param value The raw header field value
46 @return Result containing new header field object or validation error *)
47val create :
48 name:string ->
49 value:string ->
50 unit -> (t, string) result
51
52(** Create a new header field without validation.
53
54 For use when header field names are known to be valid or come from
55 trusted sources like server responses.
56
57 @param name The header field name
58 @param value The raw header field value
59 @return New header field object *)
60val create_unsafe :
61 name:string ->
62 value:string ->
63 unit -> t
64
65(** Convert a list of header fields to JSON array.
66
67 Utility function for converting header field lists to JSON arrays
68 as used in Email body parts and other contexts.
69
70 @param headers List of header fields to convert
71 @return JSON array containing header field objects *)
72val list_to_json : t list -> Yojson.Safe.t
73
74(** Parse a list of header fields from JSON array.
75
76 Utility function for parsing JSON arrays of header field objects.
77 Individual parsing errors are collected and reported.
78
79 @param json JSON array containing header field objects
80 @return Result containing parsed header field list or parse errors *)
81val list_of_json : Yojson.Safe.t -> (t list, string) result
82
83(** Find a header field by name (case-insensitive).
84
85 Searches a list of header fields for the first field matching the given
86 name using case-insensitive comparison as specified in RFC 5322.
87
88 @param headers List of header fields to search
89 @param name Header field name to find
90 @return The first matching header field, or None if not found *)
91val find_by_name : t list -> string -> t option
92
93(** Get all header fields with a given name (case-insensitive).
94
95 Returns all header fields matching the given name. This is useful for
96 headers that may appear multiple times like "Received" or "X-*" headers.
97
98 @param headers List of header fields to search
99 @param name Header field name to find
100 @return List of all matching header fields *)
101val find_all_by_name : t list -> string -> t list
102
103(** Validate a header field name according to RFC 5322.
104
105 Checks that a header field name consists only of printable ASCII characters
106 and does not contain control characters, spaces, or the colon character.
107
108 @param name The header field name to validate
109 @return Ok if valid, Error with description if invalid *)
110val validate_name : string -> (unit, string) result
111
112(** Structured header parsing support for JMAP access patterns *)
113module Value : sig
114 (** Header value access patterns as defined in RFC 8621 Section 4.1.2 *)
115 type access_form =
116 | Raw (** Raw octets as they appear in the message *)
117 | Text (** Decoded and unfolded text *)
118 | Addresses (** Parsed email addresses *)
119 | GroupedAddresses (** Parsed addresses preserving group information *)
120 | MessageIds (** Parsed message ID list *)
121 | Date (** Parsed date value *)
122 | URLs (** Parsed URL list *)
123
124 (** Structured header value types *)
125 type parsed_value =
126 | Raw_value of string
127 | Text_value of string
128 | Addresses_value of Address.t list
129 | GroupedAddresses_value of Address.Group.t list
130 | MessageIds_value of string list
131 | Date_value of Jmap.Date.t
132 | URLs_value of string list
133
134 (** Parse error types *)
135 type parse_error =
136 | Invalid_encoding of string (** RFC 2047 encoding error *)
137 | Malformed_header of string (** Malformed header structure *)
138 | Unsupported_form of string * access_form (** Unsupported access form for header *)
139 | Parse_failure of string (** General parse failure *)
140end
141
142(** Header access pattern functions following RFC 8621 Section 4.1.2 *)
143
144(** Get header value as Raw form.
145
146 Returns the raw octets of the header field value as specified in
147 {{:https://www.rfc-editor.org/rfc/rfc8621.html#section-4.1.2.1}RFC 8621 Section 4.1.2.1}.
148 This form always succeeds and returns the header value as-is.
149
150 @param t The header field
151 @return Raw header field value *)
152val as_raw : t -> string
153
154(** Get header value as Text form.
155
156 Processes the header value according to
157 {{:https://www.rfc-editor.org/rfc/rfc8621.html#section-4.1.2.2}RFC 8621 Section 4.1.2.2}
158 with white space unfolding, RFC 2047 decoding, and normalization.
159 Only valid for specific header fields as defined in the RFC.
160
161 @param t The header field
162 @return Result containing decoded text or parse error *)
163val as_text : t -> (string, Value.parse_error) result
164
165(** Get header value as parsed email addresses.
166
167 Parses the header as an address-list according to
168 {{:https://www.rfc-editor.org/rfc/rfc8621.html#section-4.1.2.3}RFC 8621 Section 4.1.2.3}.
169 Only valid for address-type header fields (From, To, Cc, etc.).
170
171 @param t The header field
172 @return Result containing list of email addresses or parse error *)
173val as_addresses : t -> (Address.t list, Value.parse_error) result
174
175(** Get header value as grouped addresses.
176
177 Similar to addresses but preserves group information according to
178 {{:https://www.rfc-editor.org/rfc/rfc8621.html#section-4.1.2.4}RFC 8621 Section 4.1.2.4}.
179 Only valid for address-type header fields.
180
181 @param t The header field
182 @return Result containing list of address groups or parse error *)
183val as_grouped_addresses : t -> (Address.Group.t list, Value.parse_error) result
184
185(** Get header value as message ID list.
186
187 Parses the header as message IDs according to
188 {{:https://www.rfc-editor.org/rfc/rfc8621.html#section-4.1.2.5}RFC 8621 Section 4.1.2.5}.
189 Only valid for message ID header fields (Message-ID, In-Reply-To, References).
190
191 @param t The header field
192 @return Result containing list of message IDs or parse error *)
193val as_message_ids : t -> (string list, Value.parse_error) result
194
195(** Get header value as parsed date.
196
197 Parses the header as a date-time according to
198 {{:https://www.rfc-editor.org/rfc/rfc8621.html#section-4.1.2.6}RFC 8621 Section 4.1.2.6}.
199 Only valid for date header fields (Date, Resent-Date).
200
201 @param t The header field
202 @return Result containing parsed date or parse error *)
203val as_date : t -> (Jmap.Date.t, Value.parse_error) result
204
205(** Get header value as URL list.
206
207 Parses the header as URLs according to
208 {{:https://www.rfc-editor.org/rfc/rfc8621.html#section-4.1.2.7}RFC 8621 Section 4.1.2.7}.
209 Only valid for URL-type header fields (List-Archive, List-Post, etc.).
210
211 @param t The header field
212 @return Result containing list of URLs or parse error *)
213val as_urls : t -> (string list, Value.parse_error) result
214
215(** Parse header in the specified access form.
216
217 Generic function for parsing a header in any supported access pattern.
218 This provides a unified interface for all parsing operations.
219
220 @param t The header field
221 @param form The desired access form
222 @return Result containing parsed value or parse error *)
223val parse_as : t -> Value.access_form -> (Value.parsed_value, Value.parse_error) result
224
225(** Utility functions for working with header lists *)
226
227(** Find header by name and parse as Text form.
228 @param headers List of header fields to search
229 @param name Header field name to find
230 @return Parsed text value if found and valid, None otherwise *)
231val find_and_parse_as_text : t list -> string -> string option
232
233(** Find header by name and parse as addresses.
234 @param headers List of header fields to search
235 @param name Header field name to find
236 @return List of parsed addresses if found and valid, None otherwise *)
237val find_and_parse_as_addresses : t list -> string -> Address.t list option
238
239(** Find header by name and parse as message IDs.
240 @param headers List of header fields to search
241 @param name Header field name to find
242 @return List of parsed message IDs if found and valid, None otherwise *)
243val find_and_parse_as_message_ids : t list -> string -> string list option
244
245(** Find header by name and parse as date.
246 @param headers List of header fields to search
247 @param name Header field name to find
248 @return Parsed date if found and valid, None otherwise *)
249val find_and_parse_as_date : t list -> string -> Jmap.Date.t option