My agentic slop goes here. Not intended for anyone else!
1# JMAP Email Types JSON Implementation
2
3This document summarizes the JSON serialization and deserialization functionality added to the JMAP Email types implementation.
4
5## Overview
6
7JSON support has been added to the core email types in `jmap-email/jmap_email_types.ml` to enable proper serialization and parsing of JMAP email objects according to RFC 8621.
8
9## Implemented Types
10
11### 1. Email_address
12- **to_json**: Converts email addresses to JSON with `email` (required) and `name` (optional) fields
13- **of_json**: Parses JSON objects into email address structures
14- Handles both named (`{"name": "John Doe", "email": "john@example.com"}`) and unnamed (`{"email": "jane@example.com"}`) addresses
15
16### 2. Email_header
17- **to_json**: Converts header fields to JSON with `name` and `value` fields
18- **of_json**: Parses JSON objects into header field structures
19- Example: `{"name": "Subject", "value": "Important Message"}`
20
21### 3. Email_body_part
22- **to_json**: Converts body parts to comprehensive JSON representation including:
23 - Basic fields: `partId`, `blobId`, `size`, `headers`, `type`
24 - Optional fields: `name`, `charset`, `disposition`, `cid`, `language`, `location`
25 - Nested structures: `subParts` for multipart content
26 - Extension fields: `other_headers` for custom headers
27- **of_json**: Parses complex JSON structures back into body part objects
28- Handles recursive parsing for nested multipart structures
29
30### 4. Keywords
31- **to_json**: Converts keyword sets to JMAP wire format (object with boolean values)
32- **of_json**: Parses JMAP keyword objects back into keyword lists
33- Supports all JMAP standard keywords and custom keywords
34- Example: `{"$seen": true, "$flagged": false, "custom-label": true}`
35
36### 5. Email
37- **to_json**: Converts complete email objects to JSON with all present fields:
38 - Metadata: `id`, `blobId`, `threadId`, `size`, `receivedAt`
39 - Addressing: `from`, `to`, `cc`, `mailboxIds`
40 - Content: `subject`, `preview`, `hasAttachment`
41 - Structure: `textBody`, `htmlBody`, `attachments`
42 - Keywords and message IDs
43- **of_json**: Parses comprehensive email JSON into email objects
44- Handles optional fields correctly (present vs null vs missing)
45
46## Key Features
47
48### Type Safety
49- All functions use OCaml's strong type system to ensure correctness
50- Proper error handling with descriptive failure messages
51- Optional field handling that respects JMAP semantics
52
53### JMAP Compliance
54- Follows RFC 8621 JSON structure specifications exactly
55- Handles JMAP-specific data types (dates as floats, boolean maps, etc.)
56- Supports all standard and extended JMAP email properties
57
58### Robustness
59- Handles nested and recursive structures (body parts with sub-parts)
60- Proper handling of optional vs. null vs. missing fields
61- Extension field support for future JMAP enhancements
62
63## Testing
64
65Comprehensive test suite included in `jmap-email/test_email_json.ml`:
66
67### Test Coverage
681. **Round-trip testing**: JSON → OCaml → JSON conversion verification
692. **Field handling**: Optional, null, and missing field scenarios
703. **Complex structures**: Nested body parts, multiple addresses, keyword sets
714. **Real-world examples**: RFC-compliant JMAP email JSON parsing
725. **Edge cases**: Empty lists, minimal vs. full email objects
73
74### Test Types
75- Unit tests for individual type conversions
76- Integration tests with realistic JMAP email examples
77- Round-trip verification to ensure data preservation
78- Property-based testing for JSON field ordering independence
79
80## Usage Examples
81
82### Basic Email Address Parsing
83```ocaml
84let json = `Assoc [("name", `String "John Doe"); ("email", `String "john@example.com")]
85let addr = Email_address.of_json json
86let back_to_json = Email_address.to_json addr
87```
88
89### Complete Email Object Handling
90```ocaml
91let email_json = Yojson.Safe.from_string {|
92 {
93 "id": "M123",
94 "subject": "Test",
95 "from": [{"name": "Alice", "email": "alice@example.com"}],
96 "keywords": {"$seen": true, "$flagged": false}
97 }
98|}
99let email = Email.of_json email_json
100let roundtrip = Email.to_json email
101```
102
103### Body Part Structure Parsing
104```ocaml
105let body_part_json = Yojson.Safe.from_string {|
106 {
107 "partId": "1",
108 "type": "text/plain",
109 "size": 1024,
110 "headers": [{"name": "Content-Type", "value": "text/plain"}],
111 "charset": "utf-8"
112 }
113|}
114let part = Email_body_part.of_json body_part_json
115```
116
117## Implementation Notes
118
119- Uses manual JSON handling for precise control over structure
120- Leverages Yojson.Safe for JSON processing
121- Hashtbl used for ID maps and keyword storage as per JMAP library patterns
122- Date handling uses float values per JMAP specification
123- Error messages are descriptive for debugging JSON structure issues
124
125This implementation provides a solid foundation for JMAP email processing with full JSON serialization support.