Skip to content

v2.21.0

Choose a tag to compare

@kiki830621 kiki830621 released this 16 Jul 02:03

Added

  • get_special_mailboxes per-account mode now also returns a <type>_path field
    for each present special mailbox — the FULL mailbox path (drafts_path
    "[Gmail]/草稿") matching the mailbox field search_emails returns, so a
    consumer can compare full-path == full-path directly instead of the #109
    leaf-suffix heuristic. Built by an AppleScript container-walk that joins parent
    mailbox names with / up to the account boundary (reproducing
    MailboxURL.mailboxPath); a top-level mailbox's path equals its leaf
    (inbox_path "收件匣"). Purely additive — the leaf <type> field is unchanged,
    and a walk failure omits only that _path key. The result tuple appends the 5
    paths after the 5 leaf names, preserving the #179 fixed-tuple positions
    ([matchedId, matchedName, matchCount, n0…n4, p0…p4]). (#268)
  • to / cc / bcc accept RFC 5322 mailbox form (Name <email>) — recipients can display a person's name (#251). Previously the recipient parameters were documented as bare addresses; a Name <email> string happened to pass the boundary validation (single @) and flowed unparsed into AppleScript, while a legal name containing @ was mis-rejected by the same check. Now a new parseRecipient boundary parser splits the mailbox form; validation applies to the addr-spec part; the legacy AppleScript path emits native {name, address} recipient properties (Mail displays the person's name — this also silently benefits reply_email's cc_additional and forward_email's to, which share the fragment builder); and display-name recipients on compose_email / create_draft become a named mailto-ineligibility (the mailto URL carries addr-spec only per RFC 6068) — the same disclosed legacy-path trade-off as a custom from_address: names shown natively, body wrapped + disclosed; with require_wrapper_free: true, a clean refusal names the drop-the-names alternative. Bare-address calls are byte-identical. Contacts-based auto-naming stays a follow-up on the issue. Verify round (PR #262) hardened the parser: an unquoted name containing </> (e.g. the multi-angle Alice <a@x> <b@y>) is rejected at the boundary instead of silently reinterpreted as a send to the last address (RFC 5322 makes angles specials, forbidden in unquoted atoms; quoted names keep them), and the bare-angle form <a@b.c> normalizes to the bare address.
  • redirect_email recipient parity with #251 (#263). The shared boundary validation relaxed by #251 let Name <email> reach the redirect script builder, which passed the whole string as the AppleScript address (Mail's display-name fallback — no mis-send, but malformed-downstream). The builder now delegates to the shared name-aware recipientFragment: canonical (unpadded) bare addresses stay byte-identical (the #135 golden is untouched; a whitespace-padded bare address is now trimmed, matching validation and compose/reply/forward), mailbox-form recipients get the native {name, address} pair — compose/reply/forward/redirect now behave identically. Well-formed multi-angle inputs (two addr-specs, e.g. Alice <a@x> <b@y>) stay rejected at the shared boundary (#251 regression lock added for redirect); a malformed one-@ multi-angle input still passes the lite validator and lands as a Mail-level-invalid address (no mis-send) — shared-boundary hardening tracked as #265.

Fixed

  • Recipient parser hardening — malformed multi-angle rejection + quoted-pair decoding (#265, #266). The shared validateEmailAddresses boundary now rejects a recipient that parseRecipient could not cleanly split (name resolves to nil) yet still carries a matched <...> pair — the single-@ malformed multi-angle case (Alice <not-an-email> <bob@x>) that previously slipped the atCount check and landed whole in the AppleScript address. A clean bare addr-spec and the normalized bare-angle form (<a@b.c>a@b.c) are unaffected; the pathological quoted-local-part literally containing a matched angle pair ("a<b>"@x) is explicitly unsupported. Separately, quoted display names now decode RFC 5322 quoted-pairs (\"", \\\) so the native recipient name carries the intended value rather than the backslash-escaped source form (#266). The parser uses a simple outer-quote heuristic (a name that both starts and ends with "), so a terminal escaped quote ("x\") is still classified as quoted and decoded; the decoded value is re-escaped for AppleScript backslash-first, so the emitted recipient literal is always balanced (no injection). A residual note: single-unmatched-angle malformed recipients (<a@x, a@x>) are not caught by the matched-pair boundary reject and land as Mail-level-invalid addresses (no mis-send) — tracked as #270.
  • Test isolation — awaited seam teardown (#267). The three RecipientDisplayNameTests seam-reset sites migrated from a detached defer { Task { … } } (which could reset the process-wide MailController.shared singleton after the next test started) to addTeardownBlock, which XCTest awaits.