Data::JSEmail - Convert between RFC 5322 messages and the RFC 8621 Email format DESCRIPTION Data::JSEmail provides bidirectional conversion between RFC 5322 / MIME messages and the JSON Email object defined by RFC 8621 (JMAP for Mail). Parsing decomposes a message into the RFC 8621 representation: the typed convenience properties (from, to, subject, sentAt and so on), the raw headers, the bodyStructure tree, and the textBody / htmlBody / attachments lists derived from it, with decoded content in bodyValues. Building goes the other way, taking an Email/set create object and producing a message. Header precedence follows RFC 8621 and matches Cyrus: header:* properties win, then the convenience properties, then defaults. Parsing and building are handled by Email::MIME. FUNCTIONS Nothing is exported; call the functions fully qualified. Data::JSEmail::parse($rfc822, $id?) Parse an RFC 5322 message and return an RFC 8621 Email hashref. $id becomes the returned object's "id" and is used to construct the blobId of each body part ("m-$id-$partId"). It defaults to the SHA-256 hex digest of $rfc822. The returned hashref has these RFC 8621 Email properties: id, size, from, to, cc, bcc, sender, replyTo, subject, sentAt, messageId, inReplyTo, references, preview, hasAttachment, headers, bodyStructure, bodyValues, textBody, htmlBody and attachments. Data::JSEmail::make($args, $getblob, $defaults_cb?) Build an RFC 5322 message from an RFC 8621 Email/set create object. Returns the message as a string with CRLF line endings. $args is the create object: the convenience properties, any header:* overrides, bodyValues, and textBody / htmlBody / attachments (or a full bodyStructure). $getblob is a callback invoked as $getblob->($blobId) for each part that references one. It must return a two element list of ($type, $content). $defaults_cb is an optional callback invoked as $defaults_cb->($name) to supply a header that neither a header:* property nor a convenience property provided. It defaults to default_header_defaults below. Data::JSEmail::default_header_defaults($name) The default $defaults_cb. Returns a current date for "date" and a freshly generated address for "message-id"; undef for anything else. Callers supplying their own callback can fall back to this one for the names they do not handle themselves. EXAMPLE use Data::JSEmail; # message -> RFC 8621 Email my $email = Data::JSEmail::parse($rfc822); print $email->{subject}; print $email->{bodyValues}{ $email->{textBody}[0]{partId} }{value}; # RFC 8621 Email/set create -> message my $rfc822 = Data::JSEmail::make({ from => [{ name => 'Alice', email => 'alice@example.com' }], to => [{ name => 'Bob', email => 'bob@example.com' }], subject => 'Hello', bodyValues => { 1 => { value => "Hi there.\n" } }, textBody => [{ partId => '1', type => 'text/plain' }], }, sub { my $blobId = shift; return $store->fetch($blobId) }); SPECIFICATIONS RFC 5322 - Internet Message Format RFC 8620 - The JSON Meta Application Protocol (JMAP) RFC 8621 - JMAP for Mail AUTHOR Bron Gondwana LICENSE Copyright 2026 Fastmail Pty Ltd. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself; that is, either the GNU General Public License as published by the Free Software Foundation (version 1, or at your option any later version), or the Artistic License. See http://dev.perl.org/licenses/ and the LICENSE file included with this distribution for more information.