Skip to content

Validate SMTP SIZE using finalized transmitted content #748

Description

@bbottema

Part of #722 — original step 9 of the SMTP robustness plan, planned for 10.0.0.

Why

An email can fit the application's own size limit and still exceed the SMTP server's limit. Check the actual prepared SMTP content before submission, so a known mismatch does not waste a large transfer. Keep the measured size and the connected server's advertised maximum on the submission receipt for troubleshooting and per-email observer reporting.

Implemented for 10.0.0 (unreleased)

  • Automatically check the managed Angus send path, after Angus's optional 8-bit conversion and before MAIL FROM. No builder setting, configuration property or enum.
  • Add nullable Long getMessageSize() and Long getServerMaximumMessageSize() to MailSubmissionReceipt, carried through MailTransportResult. Retain known facts on failure receipts; unknown values remain absent. Do not add a separate declared-SIZE field.
  • Count RFC 1870 message octets, including canonical CRLF and any required final CRLF, excluding dot-stuffing and the DATA terminator. Use a counting stream, not another whole-message buffer or disk spool. Preserve exact/protected bytes.
  • Reject above a reliable positive advertised limit; equality is allowed. Missing, zero, malformed, overflowing or contradictory limits do not establish a usable maximum. Missing SIZE does not prevent sending.
  • Add SIZE automatically when advertised, preserving a single valid explicit advanced SIZE declaration and all unrelated parameters. Reject malformed/duplicate declarations before submission.
  • Read operational SIZE facts from the actual selected connection's complete successful EHLO response, including post-STARTTLS discovery. Clear stale connection and attempt state; do not use a separate probe as a send prerequisite.
  • Keep operational SIZE parsing independent of bounded probe diagnostics. A 64 KiB escaped-text budget per capability snapshot limits reporting, not sending; omitted diagnostic snapshots cannot hide a later SIZE advertisement or conflict.
  • Return a normal compatibility failure and receipt for local rejection: no submitted recipients, fabricated SMTP response, ENVID/REQUIRETLS use, or automatic retry. Keep healthy pooled connections reusable.
  • Keep the existing application withMaximumEmailSize(...) limit and rehearsal's rendered EML size distinct. Data sources must provide stable, repeatable content throughout an attempt.
  • Do not replace caller-owned transports. CustomMailer and other providers retain ownership; size facts remain absent unless their adapter can report them reliably. Logging-only mode does not invent SMTP facts.

The provider-level research confirmed Angus 2.0.5 neither supplies SIZE automatically nor compares the message with the advertised maximum, and its optional MIME conversion changes the serialized size. The managed pre-MAIL hook is therefore the measurement boundary.

Verification and acceptance

  • Exact counts and MAIL parameters for line endings, dot transparency, headers, Unicode, attachments and optional 8-bit conversion.

  • Below/equal/above limits; missing, parameterless, zero, malformed, overflowing and duplicate SIZE advertisements.

  • STARTTLS capability changes, reconnects, mixed-server clusters and pooled attempt isolation.

  • Composed, exact, DKIM, S/MIME and OpenPGP content preservation.

  • No submission commands on local rejection; healthy lease reuse and accurate failure/observer receipts.

  • Sync/async sends, batches, open connections, cancellation/deadlines and measurement failures.

  • Immutable result propagation, nullable unknowns, compatible constructors and receipt serialization.

  • Bounded large-stream tests without benchmarks or extra whole-message buffers.

  • Java 11, modern-JDK non-live reactor, classpath/JPMS and applicable Spring/CLI regressions.

  • Website examples/output, migration guidance for changed released behavior, release notes and architecture documentation.

  • Coding-guide audit, license-header cleanup and website checks/build/internal links.

  • Maintainer review and acceptance, followed by selective semantic commits and push of the library and matching website documentation.

Implementation and website documentation are accepted, committed and pushed to the 10.0.0 development branches. This completes original step 9 and Phase 4 of #722; it is not a 10.0.0 release. The synthetic performance audit and any opt-in/opt-out API decision continue separately in #749. Automatic retries, altered-content fallback, parked PIPELINING/CHUNKING (#699) and the #747 conformance suite remain outside this issue.

References

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions