Handle SMTP 550 recipient-rejected errors with structured SmtpSendException

- Add SmtpSendException with smtpCode/smtpResponse/isRecipientRejected()
- smtpSend() $expect closure throws SmtpSendException (with code) instead of RuntimeException
- SmtpRelay::send() re-throws SmtpSendException so callers can inspect it
- request-access.php (new): catch 550 → roll back token+approval, return HTTP 422 with FR user message
- request-access.php (resend): catch 550 → HTTP 422 instead of silently claiming success
- StudentEmail::sendConfirmation(): catch SmtpSendException → log+false (submission not aborted)
- admin/actions/access-request.php: catch SmtpSendException post-approval → flash warning (recipient-rejected vs transient)
This commit is contained in:
Pontoporeia
2026-04-30 12:40:14 +02:00
parent 8d115dc965
commit 89b7ab476e
5 changed files with 103 additions and 6 deletions

10
TODO.md
View File

@@ -106,6 +106,16 @@
- [x] Minimal horizontal padding inside columns (`var(--space-2xs)`)
- [x] Align all column headings to the same baseline row (2-row grid via `display: contents`)
## SMTP 550 recipient-rejected handling
- [x] Add `SmtpSendException` — carries `smtpCode` + `smtpResponse`; `isRecipientRejected()` for 550554
- [x] `smtpSend()` `$expect` closure throws `SmtpSendException` (with code) instead of plain `RuntimeException`
- [x] `SmtpRelay::send()` re-throws `SmtpSendException` so callers can react
- [x] `request-access.php` (new auto-approve): catch 550 → roll back token + approval, return HTTP 422 with user-facing message
- [x] `request-access.php` (resend path): catch 550 → return HTTP 422 instead of silent "access approved"
- [x] `StudentEmail::sendConfirmation()`: catch `SmtpSendException` → log + return false (submission must not be aborted)
- [x] `admin/actions/access-request.php`: catch `SmtpSendException` after approval → flash warning distinguishing recipient-rejected vs transient
## CSS refactor
- [x] Move semantic HTML element baseline styles into common.css