feat(email): multipart HTML+plaintext for RI exchange pending approval (closes #296) - #813
Conversation
|
@coderabbitai review |
|
Warning Review limit reachedYou’ve reached a temporary PR review limit under our Fair Usage Limits Policy. Next review available in: 3 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (6)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
✅ Actions performedReview triggered.
|
|
@coderabbitai full review |
✅ Actions performedFull review triggered. |
|
@coderabbitai review |
Rate Limit Exceeded
|
|
@coderabbitai full review Generated by Claude Code |
|
🧠 Learnings used✅ Action performedFull review finished. |
|
Rebased onto The conflict overlapped the multipart-HTML work in this PR with the base-branch hardening from #1015 / #1036 (stop broadcasting RI-exchange approval tokens via the SNS topic). The resolution preserves both intents:
Test update: the base-branch SMTP no-recipient coverage test previously asserted Verification: @coderabbitai full review |
|
🧠 Learnings used✅ Action performedFull review finished. |
|
@coderabbitai full review |
✅ Action performedFull review finished. |
|
@coderabbitai review |
✅ Action performedReview finished.
|
|
@coderabbitai review |
✅ Action performedReview finished.
|
|
@coderabbitai review |
✅ Action performedReview finished.
|
|
@coderabbitai review |
✅ Action performedReview finished.
|
#296) Mirror the purchaseApprovalRequestHTMLTemplate pattern for the SendRIExchangePendingApproval flow: - Add riExchangePendingApprovalHTMLTemplate: inline-styled table of exchanges with per-row Approve/Reject CTA buttons, summary block, optional requested-by line, configurable cancellation-window note, and skipped-exchanges section. - Extend riExchangePendingApprovalTemplate (plaintext): labelled Approve/Reject URLs (replacing bracket notation), optional requested-by block, configurable cancellation-window note. - Extend RIExchangeNotificationData with RequestedByName, RequestedByEmail, RequestedAt, CancellationWindowNote fields alongside the RecipientEmail/CCEmails targeting fields. - Add RenderRIExchangePendingApprovalEmailHTML renderer. - Add sendRIExchangePendingApprovalVia helper (shared by Sender and SMTPSender, non-fatal HTML degrade on render error), now CC-aware. - Sender.SendRIExchangePendingApproval: requires RecipientEmail and routes through targeted SES multipart (SendToEmailWithCCMultipart), never broadcasting approval tokens via the SNS topic. - SMTPSender.SendRIExchangePendingApproval: resolves RecipientEmail (falling back to the static notify address), fails loud with ErrNoRecipient when neither is configured, then sends multipart. - 7 new test cases covering both halves, empty/custom cancellation notes, missing requested-by, and skipped-exchanges rendering. Rebased onto feat/multicloud-web-frontend: reconciled with the #1015 / multipart send now preserves that fail-loud, targeted-SES contract instead of falling back to the SNS broadcast topic. Updated the SMTP no-recipient coverage test to assert ErrNoRecipient accordingly.
… renderer Add two tests missing from the #296 wave: - TestRenderRIExchangePendingApprovalEmailHTML_EscapesHostilePayload: feeds <script>alert('xss')</script> into RequestedByName, CancellationWindowNote, and Skipped.Reason and asserts the literal tag is absent from the rendered HTML (html/template auto-escaping). - TestRenderRIExchangePendingApprovalEmail_PlainTextVerbatim: feeds O'Brien & Co and a plus-addressed email into the plain-text renderer and asserts no ' / & entity encoding appears (text/template emits values verbatim). Also replace em-dash with double-hyphen in the HTML template comment (style rule).
Use %q for MIME boundary field (correct quoting, satisfies gocritic), replace British spellings (labelled->labeled, honoured->honored) in PR- added comments. All new lint findings introduced by the multipart feature are cleared; pre-existing issues in untouched code paths are unchanged.
Summary
riExchangePendingApprovalHTMLTemplate: inline-styled exchange table with per-row Approve/Reject CTA buttons, summary block, optional requested-by line, configurable cancellation-window note, and skipped-exchanges section -- mirrorspurchaseApprovalRequestHTMLTemplate(PR feat(email): styled approve/cancel buttons + rec summary block (#287) #298).riExchangePendingApprovalTemplatewith labelledApprove:/Reject:URLs (replacing bracket notation), optional requested-by block, and configurable cancellation-window note.RIExchangeNotificationDatawithRequestedByName,RequestedByEmail,RequestedAt,CancellationWindowNotefields (backward-compatible zero values).sendRIExchangePendingApprovalViaprivate helper (shared bySenderandSMTPSender; HTML degrade on render error is non-fatal, matchingsendPurchaseApprovalRequestVia's contract).SMTPSender.SendRIExchangePendingApprovaldelegates to the helper (sends tos.notifyEmail).Sender.SendRIExchangePendingApprovaluses the direct SES multipart path whenemailAddress+fromEmailare configured; falls back to SNS broadcast for topic-only deployments.Test plan
go build ./...passesgo test github.com/LeanerCloud/CUDly/internal/email/...-- 322 tests pass (7 new)TestRenderRIExchangePendingApprovalEmail_Issue296-- plain-text carries requested-by, labelled URLs, custom noteTestRenderRIExchangePendingApprovalEmail_NoRequestedBy-- omits block + falls back to generic noteTestRenderRIExchangePendingApprovalEmailHTML_Issue296-- approve/reject hrefs, inline green button style, table cellsTestRenderRIExchangePendingApprovalEmailHTML_DefaultCancellationNote-- generic 6-hour note when field emptyTestRenderRIExchangePendingApprovalEmailHTML_SkippedBlock-- skipped list renders