# 2.0 IMAP Modified-Base64 Payload
Commit 46 adds `base64-ng-imap`, a bounded implementation of the modified
Base64 payload transform specified by RFC 3501 Section 5.1.3.
## Exact Scope
This is **not a complete IMAP modified UTF-7 mailbox codec**. Encoding accepts
octets the caller has already converted to UTF-16BE. Decoding returns those
UTF-16BE octets. The API does not:
- convert Unicode or validate scalar and surrogate relationships;
- choose direct printable ASCII versus shifted representation;
- encode the direct ampersand spelling `&-`;
- emit or parse surrounding `&...-` shift delimiters; or
- parse complete IMAP mailbox names or protocol commands.
RFC 3501 is obsolete and was replaced by RFC 9051. This companion exists for
legacy IMAP4rev1 interoperability and makes no current IMAP4rev2 conformance
claim.
## Wire Contract
The transform consumes the shared validated
`IMAP_MUTF7_ALPHABET_NO_PAD` specification. It preserves ordinary Base64 bit
grouping, replaces `/` with `,`, forbids `=` padding, and rejects malformed or
noncanonical final quanta. UTF-16BE storage must have an even byte length;
surrogate semantics remain outside this byte transform.
Every operation takes `ImapPayloadLimits`, which independently bounds input,
output, and work before completion. One-shot destination methods validate and
size before writing, so every error leaves the caller buffer unchanged.
Allocated decoding validates and computes exact output size before reserving.
Incremental states are heapless and expose exact consumed/produced progress.
They latch failures until `reset` or `clear`. Previously emitted ordinary bytes
cannot be retracted if finalization later finds a malformed tail or odd decoded
length, so callers requiring rollback must use a one-shot method or stage the
incremental output privately.
## Security Boundary
This is an ordinary public-data API. It is not constant-time-oriented secret
processing, does not wipe caller output, and deliberately provides ordinary
input positions where the shared decoder can identify one. Secret-bearing
material must use the core `secret::*` boundary rather than this legacy
protocol transform.
## Evidence
- The exact RFC Editor bytes, reviewed erratum 261, and requirement mapping are
locked under `rfc/` and excluded from every published package.
- RFC 3501 payload vectors cover `台北` and `日本語` after independent UTF-16BE
conversion.
- Every even payload length through 258 bytes round-trips, while malformed
alphabets, padding, canonical tails, odd storage, limits, and transactional
errors are exercised directly.
- Incremental encode and decode run with one-byte input and output fragments.
- Python's standard-library Base64 is an independent payload oracle after the
specified alphabet and padding transform.
- Where available, `iconv` `UTF-7-IMAP` verifies the complete RFC mailbox
example; this does not broaden the crate's payload-only API claim.
- `fuzz/fuzz_targets/imap_payload.rs` checks round trips and canonical
decode/re-encode identity over arbitrary bytes and malformed payloads.
Run the focused gate with:
```sh
scripts/check-2.0-imap.sh
```