Revision history for Perl extension Data::JSEmail

0.06  2026-11-07
	- run every entry point (parse, parse_email, make) with the
	  Email::MIME globals the module is written against (STRICT_PARAMS
	  0, PRE_2231_FORM 1, GROUCHY 0) localised, so results no longer
	  depend on what the caller set; add t/globals.t
	- parse never dies on malformed MIME: a multipart whose boundary
	  never appears, or one nested or split past Email::MIME's
	  MAX_DEPTH/MAX_PARTS, becomes one application/octet-stream leaf
	  holding its content, and a part that cannot be read is an opaque
	  leaf; the rest of the message parses as before
	- one header-forms codec, public: header_value($form, $raw_values,
	  all => 0|1) (get), format_header($form, $value) (create, its
	  inverse), header_form_allowed($field, $form) (the RFC 8621 S4.1.2
	  table), header_property($headers, $prop) and
	  parse_header_property($prop); see HEADER FORMS in the POD
	- make takes header:{name}:as{form}[:all] properties directly, on the
	  Email and on body parts, and refuses forms a field does not allow;
	  names are quoted/escaped, non-ASCII names and text RFC 2047
	  encoded, groups written for asGroupedAddresses
	- make writes a Raw header:{name} value as given; it was RFC
	  2047-encoded when it had a leading space
	- make writes every convenience property through format_header:
	  sentAt is now an RFC 5322 Date (it was written in RFC 3339 form,
	  which parses back as null), and a subject that looks like an
	  encoded-word is encoded
	- parse: the convenience properties are computed from the Raw values
	  like header:{name}:as{form} (last instance, decoded once), and
	  address names are decoded once (they were decoded by Email::MIME,
	  then again by asText); add t/header-codec.t
	- make: one leaf-part encoder for bodyStructure leaves and for the
	  textBody, htmlBody and attachments shorthand.  It fixes: a non-text
	  blob leaf in bodyStructure written raw with no
	  Content-Transfer-Encoding, so the final CRLF rewrite corrupted
	  binary octets (now base64); a textBody or text leaf given by blobId
	  UTF-8 encoded a second time (blob octets are now written as they
	  are, with the charset given, or the blob type's, or us-ascii/UTF-8
	  when the octets are); a bodyValues attachment with non-ASCII text
	  dying "Wide character"; text lines over 998 octets written 7bit
	  (now quoted-printable).  header:* properties on a shorthand
	  attachment are now written on it

0.05  2026-11-07
	- flag an unknown Content-Transfer-Encoding as an encoding problem
	  (RFC 8621 S4.1.4): it came back undecoded and unflagged
	- make: keep mailboxes whose email has no '@' (RFC 8621 S4.1.2.3);
	  Email::MIME dropped them, leaving an empty From:, To:, ...
	- escape '"' and '\' in a display name; a name with a quote made a
	  broken header
	- asAddresses/asGroupedAddresses: decode a UTF-8 addr-spec once
	  (RFC 6532); it was written out double-encoded
	- add t/encoding-problem.t, t/bare-addresses.t, t/eai-addresses.t

0.04  2026-08-31
	- clarify licensing: same terms as Perl itself (Artistic License 1.0
	  or GPL version 1 or later)
	- include a LICENSE file in the distribution
	- add POD with NAME/AUTHOR/LICENSE (the module had none)
	- add a README
	- move differ.pl to contrib/ and drop it from MANIFEST; it is a
	  development helper and was being installed into blib/lib/Data/

0.03  2026-04-07
	- Restructure make() header precedence to match RFC 8621 / Cyrus:
	  1. header:* properties, 2. convenience properties, 3. defaults
	- Add defaults callback to make($args, $getblob, $defaults_cb)
	- Export default_header_defaults() for callers to defer to
	- Add bodyStructure assembly: recursive MIME tree from bodyStructure
	  property with partId/blobId leaf parts and multipart subParts
	- Handle array ref header values (for :all support)
	- Preserve raw header values from as_string (leading whitespace)
	- Add asGroupedAddresses() - RFC 8621 EmailAddressGroup[] format
	- Fix asText() for raw UTF-8 bytes
	- Fix asDate() for comments, missing seconds, leading whitespace
	- Fix asURLs() to return undef for non-URL values
	- Add Data::UUID and Sys::Hostname dependencies

0.02  2026-04-06
	- Rewrite make() for RFC 8621 Email/set create format:
	  textBody/htmlBody/bodyValues/attachments with partId and blobId
	- Add header:* overrides from top-level and body parts
	- Add body part metadata: cid, language, disposition, name
	- Add cid validation (_valid_cid: no angle brackets, no whitespace)
	- Use us-ascii for 7-bit content, UTF-8 for non-ASCII
	- Single-part messages preserve Content-ID/Language/Disposition
	- No auto-generate text/plain from htmlBody-only (match Cyrus)

0.01  2026-04-05
	- Review and fix against RFC 8621
	- Fix bodyValues to only store text/* parts
	- Fix make() Reply-To crash (array ref used as hash ref)
	- Add NFC normalization to asText
	- Add sender convenience property
	- Add isEncodingProblem/isTruncated to bodyValues
	- Add headers to body parts
	- Add Message-ID, In-Reply-To, References to make()
	- Fix asMessageIds to return undef on parse failure
	- Fix asDate to handle undef/unparseable values
	- Fix _detect_encoding to allow tab/LF/CR as valid 7bit
	- Remove unused Image::Size import
	- Add Cyrus JMAP integration tests
