feat: admin mail queue management and test-send endpoints#335
Merged
Conversation
Adds admin endpoints to inspect and manage the email outbox and to send preview/test mail, plus the supporting Common/Cron changes: - Common: EmailOutboxPayloadKeys.Preview flag and EmailOutboxMessage.ForPreview factory (always-deliver, no coalescing). - Cron: EmailOutboxDispatcher renders a flagged preview message with a dummy link, touching no request row and minting no token. - API (Admin, /admin/email): list (paginated, $filter/$orderby), stats, requeue, cancel, delete, single test send, and bulk requeue/cancel/delete. Requeue/cancel guard on status via ExecuteUpdate so they race safely against in-flight Cron sends. No DB migration (reuses the existing table).
|
Ready to review this PR? Stage has broken it down into 4 individual chapters for you:
Chapters generated by Stage for commit ed0349a on Jul 6, 2026 12:31pm UTC. |
Contributor
There was a problem hiding this comment.
Pull request overview
This PR adds an admin-only API surface for inspecting and managing the durable email outbox (queue), plus a safe “preview/test send” flow that exercises the real provider/templates without touching request rows or minting any tokens.
Changes:
- Add an outbox preview flag +
EmailOutboxMessage.ForPreview(...)factory to enqueue always-delivered test messages. - Extend the Cron outbox dispatcher with a preview send path that renders real templates using placeholder data/links.
- Add
/admin/email/*endpoints for listing outbox rows, fetching per-status stats, and performing single/bulk requeue/cancel/delete operations, plus a/admin/email/testenqueue endpoint.
Reviewed changes
Copilot reviewed 16 out of 16 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| Cron/Services/Email/Outbox/EmailOutboxDispatcher.cs | Adds a preview/test dispatch path that bypasses request-row lookup and token minting. |
| Common/OpenShockDb/Models/EmailOutboxMessage.cs | Introduces ForPreview(...) factory for admin-enqueued preview messages. |
| Common/OpenShockDb/Keys/EmailOutboxPayloadKeys.cs | Adds the Preview payload key constant and documentation. |
| Common.Tests/OpenShockDb/EmailOutboxMessageTests.cs | Adds a unit test ensuring preview messages are flagged and never coalesced. |
| API/Controller/Admin/EmailOutboxTestSend.cs | Adds POST /admin/email/test endpoint to enqueue preview/test emails. |
| API/Controller/Admin/EmailOutboxStats.cs | Adds GET /admin/email/outbox/stats endpoint returning per-status counts. |
| API/Controller/Admin/EmailOutboxRequeue.cs | Adds POST /admin/email/outbox/{id}/requeue guarded requeue via ExecuteUpdate. |
| API/Controller/Admin/EmailOutboxList.cs | Adds GET /admin/email/outbox paginated listing with filter/order support. |
| API/Controller/Admin/EmailOutboxDelete.cs | Adds DELETE /admin/email/outbox/{id} to permanently delete an outbox row. |
| API/Controller/Admin/EmailOutboxCancel.cs | Adds POST /admin/email/outbox/{id}/cancel to mark pending rows as skipped. |
| API/Controller/Admin/EmailOutboxBulk.cs | Adds bulk requeue/cancel/delete endpoints with requested/affected counts. |
| API/Controller/Admin/DTOs/SendTestEmailDto.cs | Adds request DTO for test-send (type + recipient + optional name). |
| API/Controller/Admin/DTOs/EmailOutboxStatsDto.cs | Adds response DTO for outbox per-status stats. |
| API/Controller/Admin/DTOs/EmailOutboxMessageDto.cs | Adds response DTO exposing outbox row fields to admins. |
| API/Controller/Admin/DTOs/EmailOutboxBulkResultDto.cs | Adds response DTO for bulk operations (requested vs affected). |
| API/Controller/Admin/DTOs/EmailOutboxBulkRequest.cs | Adds request DTO holding the set of ids for bulk operations. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Adds admin API endpoints to inspect and manage the email outbox (the durable mail queue) and to send preview/test mail, plus the supporting Common/Cron changes.
Common
EmailOutboxPayloadKeys.Previewflag andEmailOutboxMessage.ForPreview(type, recipient, name)factory — always-delivered (no coalescing).Cron
EmailOutboxDispatcherrenders a flagged preview message with the chosen template and a dummy link, touching no request row and minting no token — so a test send is safe to any address and flows through the normal durable pipeline.API —
Adminrole, under/admin/emailGET /email/outbox— paginated list ($filter/$orderby/$offset/$limit, same convention as the users list; enum filtering likestatus eq 'Failed')GET /email/outbox/stats— per-status countsPOST /email/outbox/{id}/requeue·/cancel·DELETE /email/outbox/{id}POST /email/test— enqueues a preview sendPOST /email/outbox/bulk/requeue·/bulk/cancel·/bulk/delete— bulk variants (return requested/affected counts)Requeue/cancel guard on status via
ExecuteUpdate, sidestepping theAttemptCountconcurrency token and racing safely against in-flight Cron sends (missing → 404, ineligible → 409).Notes
email_outboxtable; preview is an existingEmailType+ a payload flag.Testing
Common.Tests(incl. a newForPreviewtest) andCron.Testspass.Pending→ Cron flips toSent; force-fail → requeue.The admin frontend page that drives these endpoints is in a separate PR on the frontend repo.