Repository navigation
Expose per-recipient SMTP replies and retry guidance #723
Description
Part of #722, phase 1 of 03_SMTP_ROBUSTNESS_IMPROVEMENT_PLAN. Extends the unreleased submission-result API from #710.
Why
A failed send does not necessarily mean that no mail was accepted. Mixed recipients can receive different SMTP replies, and losing the final DATA reply leaves acceptance uncertain. Applications need those facts to decide whether to retry the whole message, retry particular recipients, or ask for human review.
Angus also deliberately throws reporting exceptions when mail.smtp.reportsuccess=true, even after complete acceptance. Simple Java Mail currently misclassifies that successful transaction; this phase corrects it.
Scope
- Add immutable recipient results in envelope order, with original/mailbox addresses, final submission disposition, RCPT-attempt knowledge, the observed primary reply and text, and an optional enhanced status.
- Retain existing accepted, valid-unsent and invalid recipient getters as immutable compatibility views.
- Derive conservative transaction-level retry guidance and a known-retryable recipient list. Never resend automatically or imply exactly-once delivery.
- Extract provider exception types structurally; normalize genuine success-reporting exceptions only when the whole transaction was accepted.
- Keep original provider failures, missing replies, unknown final acceptance, custom mailers and third-party adapters intact.
- Keep captured facts local to one attempt, including pooled async sends, simple batches, open connections and observers.
Acceptance
- All-success reporting mode returns success.
- Mixed 2xx/4xx/5xx RCPT results, final rejection and final-reply loss remain distinct.
- Enhanced-status parsing rejects malformed or conflicting status text.
- Ordered recipient results agree with compatibility views and remain immutable.
- Retry guidance excludes permanent rejection and flags duplicate risk.
- Actual pooled SMTP tests cover concurrency, reuse, invalidation and recovery.
- Classpath/JPMS consumers and incomplete third-party provider results remain supported.
- Existing submission-result documentation explains the API and its limits.
Phase 1 is complete and accepted. The implementation was committed as f79c66c6 and is already on the pushed codex/10.0.0 branch, with documentation included. Closing this leftover tracking item does not introduce new Phase 1 work. The changes remain unreleased until 10.0.0 ships; later steps are tracked under #722.
Metadata
Metadata
Assignees
Labels
Projects
- StatusShow more project fieldsDone
Activity
feat(smtp): preserve recipient replies and retry guidance (#723)
docs(smtp): record accepted work and deferred cancellation
docs(smtp): explain send results and async backpressure
bbottema commentedon Sep 17, 2026
This was already accepted and pushed for 10.0.0; closing the leftover tracking issue.
Use
receipt.getRecipientResults()for each recipient's observed reply and disposition, andreceipt.getRetryDisposition()/getRetryableRecipients()for conservative retry guidance. A missing final DATA reply remains uncertain and can mean duplicate risk; no automatic retry is performed.Usage and sample output. The remaining roadmap stays under #722.