Skip to content

Expose BODYSTRUCTURE octet count as MessagePart.size#184

Merged
odrobnik merged 1 commit into
Cocoanetics:mainfrom
appinteractive:feat/messagepart-size
Jul 17, 2026
Merged

Expose BODYSTRUCTURE octet count as MessagePart.size#184
odrobnik merged 1 commit into
Cocoanetics:mainfrom
appinteractive:feat/messagepart-size

Conversation

@appinteractive

Copy link
Copy Markdown
Contributor

What

BODYSTRUCTURE reports each body part's size in octets, but the value was dropped when building MessagePart from a parsed BodyStructure. This carries it through as a new optional property:

/// The size of the part body in octets, as reported by BODYSTRUCTURE (if any)
public let size: Int?

NIOIMAP parses a missing/zero field as 0, which is surfaced as nil.

Why

With part sizes available from the envelope/structure fetch alone, clients can show size labels and enforce download caps (e.g. skip auto-fetching a 40 MB scan for a thumbnail) without fetching any part bytes. We use this in a mail client that builds an attachment metadata index from BODYSTRUCTURE during sync.

Changes

  • MessagePart: new size: Int? property, threaded through both public initializers and the Codable implementation (encoded with encodeIfPresent, so existing archives decode fine).
  • MessagePart+BodyStructure: read fields.octetCount when flattening singleparts; > 0 becomes the size, otherwise nil.
  • New MessagePartSizeTests: singlepart carries the octet count, zero yields nil, multipart children each carry their own size.

Note: the size is the encoded (transfer-encoding) octet count per RFC 3501 — for base64 parts roughly 4/3 of the decoded file size. Documented as "as reported by BODYSTRUCTURE" to keep that semantic.

BODYSTRUCTURE reports each part's body size in octets, but the value was
dropped when building MessagePart from a BodyStructure. Carry it through
as an optional size property (nil when the server reports 0/absent) so
clients can show size labels and apply download caps without fetching
part bytes.
@appinteractive
appinteractive marked this pull request as ready for review July 16, 2026 09:09

@odrobnik odrobnik left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Request changes: the new conversion drops a legitimate BODYSTRUCTURE octet count of zero. In the pinned NIOIMAP 0.3.0 parser, body-fld-octets is required and parsed as an unsigned number; a missing field makes the body structure invalid and never reaches this converter, while 0 is preserved as a valid reported size. The model should retain 0 so callers can distinguish a known-empty part from unavailable size metadata. The remaining construction, recursion, and Codable paths inspected are consistent. Builds and tests were not run, per review instructions.

Findings:

  • MEDIUM Sources/SwiftMail/IMAP/Models/MessagePart+BodyStructure.swift:45 — When an IMAP server reports a valid empty MIME part with body-fld-octets equal to 0, this branch stores nil instead of the reported zero. A client using size to show exact metadata or to allow only known-within-cap downloads then treats the empty part as unknown-size and may hide its size or refuse to fetch it. NIOIMAP 0.3.0 does not use zero as a missing-field sentinel: the octet field is mandatory in its parser, and a missing value produces an invalid BODYSTRUCTURE that is ignored by SwiftMail's handlers.

Comment thread Sources/SwiftMail/IMAP/Models/MessagePart+BodyStructure.swift
odrobnik added a commit that referenced this pull request Jul 17, 2026
body-fld-octets is mandatory in BODYSTRUCTURE, so NIOIMAP 0.3.0 never
uses 0 as a missing-field sentinel: a missing value makes the body
structure invalid and never reaches this converter. Collapsing 0 to nil
made a known-empty part indistinguishable from unavailable size
metadata, so callers showing exact sizes or enforcing download caps
would wrongly treat empty parts as unknown-size.

Addresses review feedback on #184.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
odrobnik added a commit that referenced this pull request Jul 17, 2026
Expose BODYSTRUCTURE octet count as MessagePart.size (supersedes #184)
@odrobnik
odrobnik merged commit c03ba9f into Cocoanetics:main Jul 17, 2026
6 checks passed
@odrobnik

Copy link
Copy Markdown
Contributor

Thanks @appinteractive for the contribution — exposing the BODYSTRUCTURE octet count is a great addition! 🙏

We took care of the review nitpick (a reported octet count of 0 was collapsed to nil; since body-fld-octets is mandatory in the parser, zero is a legitimate size of an empty part and is now preserved) in #187, which carries your commit as-is with main merged in. Once #187 lands, this PR will automatically show as merged.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants