Every refused request says why, not just campaign calls

FixEmailService
Shipped
September 16, 2026 at 5:38 PM UTC
Author
Kamo
Commit
7e58d55

2a72597 gave the campaign controllers the member's sentence instead of "Bad Request". The same loss happened everywhere else in EmailService that refuses with a ResponseStatusException: - Contacts: ContactRestController refuses with "VIEW_CONTACTS required", "No organization in session", "The organization's default book cannot be deleted"…, and the contacts screen showed "Forbidden" / "Conflict". - Aliases, shared mailboxes and mailboxes: KamoMailDomainValidator refuses an address outside the organization's verified domain with a sentence naming the domain. The three create endpoints caught it as a generic Exception and answered 500 with the exception's own text ("403 FORBIDDEN \"Email address must…\""). CampaignErrorAdvice becomes StatusReasonAdvice and applies to every controller. It still shows only a ResponseStatusException's reason, text written to be read; every other exception keeps Boot's default body (server.error.include-message stays never). The body carries the sentence as both error and message, since the contacts client reads message first and the mailbox and campaign clients read error. The three create endpoints now let a ResponseStatusException through their catch-all, so it reaches the advice with its own status. StatusReasonAdviceTest runs the real controllers on an embedded server through Boot's error handling: a campaign refusal, a contacts right, and an alias on the wrong domain (403 with the domain, where it was a 500). 1561 tests: only TransactionalSendRatchetTest fails, as it does on main.

All changes

Like what you see shipping?

All of it arrives in your workspace on its own. Start on the free plan and read this page again in a month.

Start Free ForeverView Pricing