fix: surface SMTP failures from gmail share endpoint to UI#5164
fix: surface SMTP failures from gmail share endpoint to UI#5164mengw15 wants to merge 7 commits into
Conversation
`GmailResource.sendEmailRequest` discarded the `Either[String, Unit]`
result from `sendEmail`. The method itself returned `Unit` and JAX-RS
sent `204 No Content` regardless of outcome, so any SMTP failure
(invalid credentials, network error, etc.) was logged server-side but
the HTTP layer reported success. The frontend's `next:` callback fired
and showed a green "Email sent successfully" toast even though no
mail had been delivered.
Pattern-match the `Either` and throw `WebApplicationException(error,
BAD_GATEWAY)` on `Left`, matching the codebase convention in
`AdminUserResource` / `UserResource`. JAX-RS converts the exception
into an HTTP 502, which triggers the frontend's `error:` callback.
The frontend `error:` branch in `gmail.service.ts` previously only
`console.error`'d, so users still saw no feedback on failure. Add a
`notificationService.error(...)` call mirroring the existing
`notifyUnauthorizedLogin` error handler in the same file, so the user
sees a red toast on failure. The user-facing message is generic
("Failed to send email. Please try again or contact admin.") rather
than the raw SMTP error to avoid exposing protocol-level details to
end users; the specific SMTP error stays in the backend log and the
browser console for debugging.
Add `gmail.service.spec.ts` (Vitest + `HttpClientTestingModule`)
covering both the success-toast and error-toast contracts. No backend
test added: `GmailResource` lacks a JAX-RS controller harness, and
building one would require refactoring the companion-object
`sendEmail` out as an injectable dependency — disproportionate to a
five-line fix.
Closes apache#5161.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #5164 +/- ##
============================================
+ Coverage 43.66% 43.72% +0.05%
Complexity 2218 2218
============================================
Files 1049 1049
Lines 40580 40586 +6
Branches 4324 4327 +3
============================================
+ Hits 17719 17745 +26
+ Misses 21766 21731 -35
- Partials 1095 1110 +15
*This pull request uses carry forward flags. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
|
let's add tests to cover changes! need to have backend tests |
There was a problem hiding this comment.
Pull request overview
This PR ensures SMTP/send failures from the /gmail/send backend endpoint are surfaced as HTTP errors so the Angular UI can display an error toast instead of falsely reporting success.
Changes:
- Backend: handle
sendEmail’sEitherresult and translate failures into an HTTP 502 response. - Frontend: show a user-facing error notification on failed
/gmail/sendrequests (and log details to console). - Frontend tests: add a Vitest spec covering both success (2xx) and failure (502) toast behavior.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| amber/src/main/scala/org/apache/texera/web/resource/GmailResource.scala | Maps sendEmail failures to HTTP errors (502) instead of always returning 204. |
| frontend/src/app/common/service/gmail/gmail.service.ts | Adds an error toast in the HTTP error callback for send email requests. |
| frontend/src/app/common/service/gmail/gmail.service.spec.ts | Adds unit tests validating success/error notifications for the send email request. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Address review feedback from apache#5164: `sendEmail` returns `Left("Invalid email format")` for client-side validation failures and `Left("Failed to send email: ...")` for SMTP / `Transport.send` failures. Mapping both to 502 made validation errors look like upstream/gateway failures. Match on the validation message explicitly and throw `BadRequestException` (400); reserve 502 for the SMTP/Transport path. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Validates the BadRequest mapping added in the prior commit: `sendEmailRequest` invoked with a receiver that fails `isValidEmail` throws `BadRequestException` with HTTP status 400. Calls the resource method directly with a constructed `SessionUser`, matching the style used by `WorkflowResourceSpec` — no `ResourceExtension` or auth-provider scaffolding needed. The 502 SMTP-failure path is not covered here; it would require either real SMTP failure injection or a fake SMTP server, both out of scope for this fix. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds a deterministic test for the `Left(error) => 502` mapping in
`sendEmailRequest`. In the test environment `UserSystemConfig.gmail`
defaults to "", so `createMimeMessage`'s `new InternetAddress(senderGmail)`
raises an `AddressException` immediately — with no network or SMTP
contact — `sendEmail` catches it and returns `Left("Failed to send
email: ...")`, and the resource throws `WebApplicationException` with
HTTP 502. The spec runs in ~400ms.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
What changes were proposed in this PR?
GmailResource.sendEmailRequestdiscarded theEither[String, Unit]returned bysendEmail. The endpoint itself was typedUnit, so JAX-RS responded204 No Contentregardless of outcome — any SMTP failure (invalid credentials, network error, etc.) was logged server-side but the HTTP layer reported success, and the frontend'snext:callback fired a green "Email sent successfully" toast even though no mail was delivered.This PR closes that gap in two layers:
Backend (
GmailResource.scala) — pattern-match theEitherand throwWebApplicationException(error, Response.Status.BAD_GATEWAY)onLeft. JAX-RS converts the exception into an HTTP 502, which triggers Angular'serror:callback on the frontend side. This matches the existing codebase convention inAdminUserResource(Email already exists, 409) andUserResource(User not found, 404).Frontend (
gmail.service.ts) — the existingerror:branch onlyconsole.error'd. Add anotificationService.error(...)call mirroring the existingnotifyUnauthorizedLoginerror handler in the same file (lines 56–61). The user-facing toast uses a generic message ("Failed to send email. Please try again or contact admin.") rather than the raw SMTP error, to avoid exposing protocol-level details like535-5.7.8 Username and Password not acceptedto end users; the specific SMTP error continues to land in the backend log and the browser console for debugging.Any related issues, documentation, discussions?
Closes #5161.
How was this PR tested?
Added
gmail.service.spec.ts(Vitest +HttpClientTestingModule) covering both contracts:notificationService.success("Email sent successfully")firesnotificationService.error("Failed to send email. ...")firesNo backend test added:
GmailResourcehas no JAX-RS controller test harness, and building one would require refactoringsendEmailout of the companion object into an injectable dependency — disproportionate to a five-line fix.Verified locally:
sbt "WorkflowExecutionService/scalafmtCheck" "WorkflowExecutionService/compile"— clean.yarn test --include='**/gmail.service.spec.ts'— 2 passed.yarn prettier --check src/app/common/service/gmail/gmail.service.spec.ts— clean.Manual verification path (for reviewers reproducing the issue's repro):
USER_SYS_GOOGLE_SMTP_GMAIL/USER_SYS_GOOGLE_SMTP_PASSWORD.Failed to send email: 535-5.7.8 Username and Password not accepted...(unchanged).Send email error: ...(the specific SMTP error).Was this PR authored or co-authored using generative AI tooling?
Generated-by: Claude Code (claude-opus-4-7)