Skip to content

1.12.0

Choose a tag to compare

@odrobnik odrobnik released this 21 Sep 07:57
· 7 commits to main since this release
62102d7

Highlights

SwiftMail 1.12.0 adds a parser for Outlook .msg (#237), so mail saved as files parses the same on either platform instead of only where it was saved as .eml. Around it, this release is mostly correctness in how headers and parameters are written and read (#226, #230, #233), and better diagnostics when a server refuses something (#221, #227, #231).

One behavior change is worth reading before upgrading: Message.bodies, .attachments and .cids no longer reach inside an attached message/rfc822. It affects IMAP-fetched messages too, not only .msg.

Changes

Outlook .msg parsing (#237)

  • New MSGParser.parse(_:) and Message(msgData:), producing the same Message an .eml does, so parts, attachments, addresses and dates keep working downstream.
  • Outlook usually stores no HTML at all — the rich body is PR_RTF_COMPRESSED, and what that decompresses to is normally the original HTML encapsulated in RTF. Recovering it needs LZFu decompression (MS-OXRTFCP) and de-encapsulation (MS-OXRTFEX), both implemented here.
  • The body is classified after decompression and never rendered: \fromhtml1 becomes a text/html part, \fromtext is dropped as a duplicate of PR_BODY, and a genuinely rich-text body is passed through as application/rtf for a consumer to render.
  • Embedded messages are followed recursively and nested under their parent's section. New Message.embeddedMessages returns the immediate children, each renumbered as though parsed on its own, so the same code reads a forwarded message at any depth.
  • Attachments come with their filename, MIME type and bytes. Inline versus attachment is decided by ATT_MHTML_REF in PR_ATTACH_FLAGS, not by the presence of a Content-ID — Outlook gives almost every attachment an ID.
  • Behavior change: Message.bodies, .attachments and .cids no longer reach inside an attached message/rfc822. An attached message is itself one part; what is nested under it belongs to that message and is reached through embeddedMessages. Previously a mail forwarding an HTML message but writing only plain text itself reported the forwarded HTML as its own body, and forwarded attachments were counted twice.
  • The container reader treats its input as hostile: sector numbers are range-checked, chain walks carry visited sets, declared sizes are not trusted past the bytes present, and embedded-message recursion is depth-capped.
  • Closes #235.

Header and parameter encoding (#226, #230, #233)

  • Header values and display names that cannot be written literally are now encoded rather than emitted raw (#226, supersedes #215).
  • MIME parameters are encoded, and parameter parsing is anchored to the RFC 2045 grammar (#230, supersedes #216).
  • RFC 2231 continuations are read in one pass, and every charset the platform names is honored, fixing two regressions from #230 (#233).

Diagnostics and failure reporting

  • SEARCH returning BADCHARSET is surfaced as a typed error, and response codes are kept in search failures (#227).
  • SMTP login() failures carry the server's reply (#231).
  • The SASL mechanism is judged after the channel is prepared rather than against a cleared snapshot (#221).
  • An authenticated IMAP session now requires a live channel (#224, supersedes #223).

API surface

  • Validated partial IMAP body part fetching (#228, supersedes #219).
  • Reply-To is exposed in MessageInfo metadata (#232, resolves #217).
  • supportsMove is exposed, mirroring supportsUIDPlus (#225, supersedes #214).
  • Gmail attributes are exposed on named IMAP connections (#220).

Other

  • SEARCH sends CHARSET UTF-8 when a criterion carries non-ASCII text (#222).
  • ProcessInfo.processInfo.hostName is no longer called, for privacy (#229, supersedes #218).
  • Test fix: the fetched message count is required before indexing in header fallback tests (#234).

Full changelog: 1.11.0...1.12.0