Files
ElyOffice/tasks/reviews/C12.2-r2.md
T
ZacharyZhang-NYandClaude Opus 5.5 fe90221c11 C12.2: read and write MIME by the tree
The reader walks the MIME tree with its container context: alternative
picks versions, related finds its root by start, attached multiparts
stay whole, digest children are messages. Nesting deeper than 64
levels, counting enclosed messages, is refused, and over-deep parse
results are taken apart iteratively so dropping them cannot overflow
the stack. Composite parts with a Content-ID are cid targets.

The writer keeps attachment parameters and Content-IDs, writes
multipart and message attachments unencoded, and makes its own
Message-ID. SMTP adds BODY=8BITMIME for 8-bit bodies and SMTPUTF8
when any header block at any depth is 8-bit.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-19 17:35:05 -04:00

5.9 KiB

FAIL

  • crates/ely-mail-engine/src/mime/walk.rs:43 — [P1] Unbounded MIME traversal can abort the application. A valid 138,017-byte message containing 2,048 nested multipart/mixed containers parses into 2,049 parts successfully, but read then overflows the stack and terminates the Windows test process with 0xc00000fd. This is a process abort, not a recoverable Error::Mime, and the mail engine runs inside the application. Replace recursive traversal with an explicit stack, or enforce a checked nesting limit that returns an error before exhausting the stack. Add a regression covering deeply nested input. Reproduced in .work/C12.2-r2/depth.log; the existing 46-test mail-engine suite passes.

  • Cargo.toml:62 — [P2] The mail-parser dependency omits full_encoding, whose default is disabled. Its multibyte charset decoders consequently use lossy UTF-8 conversion. A valid Subject: =?GB2312?B?1tDOxA==?= and a text/plain body declaring charset=gb2312 with base64 1tDOxA== both read as four replacement characters instead of 中文, without a decoding warning. Enable the dependency's charset support and test multibyte encoded headers and bodies. The same isolated probe passes when only mail-parser/full_encoding is enabled; see .work/C12.2-r2/encoding-before.log and encoding-feature.log.

  • crates/ely-mail-engine/src/mime/walk.rs:133 — [P2] Preserving text attachment octets now loses the charset needed to interpret those octets. leaf discards all Content-Type parameters. Reading a text/plain; charset=iso-8859-1 attachment containing Caf=E9, copying its returned Part into Draft.attachments, and building it emits Content-Type: text/plain with the Latin-1 bytes unchanged. Parsing the forwarded attachment yields Caf�. Without the charset, the declared default is US-ASCII (RFC 2046 §4.1.2). Preserve and serialize the parameters required to interpret attachment bytes, and test the recipient's decoded attachment text after forwarding. The existing byte-equality regression cannot detect this loss. Reproduced in .work/C12.2-r2/probes.log.

  • crates/ely-mail-engine/src/mime.rs:159 — [P2] Multipart attachments returned by read cannot be forwarded as valid MIME. Their bytes include the entity headers, but build treats those bytes as a binary leaf: an attached multipart/alternative becomes Content-Type: multipart/alternative without a boundary, followed by a base64 encoding of its original headers and body. The recipient parser sees a binary leaf instead of the original multipart structure. Base64 transfer encoding is prohibited on multipart entities (RFC 2045 §6.4). Serialize these attachments as complete MIME entities with their boundary and children and a permitted transfer encoding. Add a read/build/parse regression for the attached multipart covered by round 1. Reproduced in .work/C12.2-r2/probes.log.

  • crates/ely-mail-engine/src/mime/walk.rs:104 — [P2] The round 1 related-disposition fix still excludes the related root. A multipart/related with type="text/html" whose first child is text/html with Content-Disposition: attachment; filename=body.html returns html: None and treats the root as an attachment, because related sends it through body's attachment guard. Related processing must ignore the disposition type for the root as well as its sibling resources (RFC 2387 §4). Carry that container context into root selection, while preserving the rules for the root's descendants, and add this root-disposition regression. Reproduced in .work/C12.2-r2/related.log.

  • crates/ely-mail-engine/src/mime/walk.rs:114 — [P2] A multipart related resource loses its own entity, Content-ID and filename. With an HTML root and a sibling multipart/alternative carrying Content-ID: <entity@example.com> and filename=entity.mime, resource recursively flattens the sibling before inspecting its metadata. The result has no inline target for entity@example.com; only an unnamed text/plain descendant remains in attachments. The compound resource can neither be resolved by its CID nor saved with its original contents. Related processing must retain the correspondence between an entity, its headers and its Content-ID (RFC 2387 §6.1). Preserve the resource entity and metadata when traversing composite resources, and add this regression. Reproduced in .work/C12.2-r2/related.log.

  • crates/ely-mail-engine/src/mime/walk.rs:45 — [P2] The claimed non-related CID handling is bypassed for text/plain and text/html parts. In multipart/mixed, a plain body followed by a text/html resource with Content-ID: <frame@example.com> and inline disposition returns that resource as Mail.html, with an empty inline list. Its Content-ID and original part bytes are unavailable to callers, so a CID link to it cannot be resolved. This contradicts C12.2's explicit claim that non-attachment CID parts outside related containers become CID targets. Classify text resources using their container context before consuming them as body strings, and test text CID targets as well as binary images. Reproduced in .work/C12.2-r2/related.log.

  • crates/ely-mail-engine/src/mime/walk.rs:170 — [P2] Unrecognized disposition types are silently treated as inline body text. A multipart/mixed containing plain body followed by text/plain with Content-Disposition: x-file; filename=file.txt and private attachment reads as text: Some("body\nprivate attachment") with zero attachments. Unrecognized disposition types should be handled as attachments, retaining their filename (RFC 2183 §2.8). Apply that classification outside the related-container override and add an unknown-disposition regression. Reproduced in .work/C12.2-r2/probes.log.