Repository navigation
[DT-4263][2/7] Add an email sends endpoint for the Admin Console email log - #3142
Open
kevinmarete wants to merge 9 commits into
Open
kevinmarete wants to merge 9 commits into
kevinmarete wants to merge 9 commits into
Conversation
kevinmarete
force-pushed
the
km-dt-4263-email-sends
branch
from
October 10, 2026 01:09
162bef3 to
7617930
Compare
…l log Each recipient of an email gets its own email_entity row, so the email log lists one send many times. GET /api/mail/sends groups rows of one type and entity reference created within 10 minutes of each other into a send, with its recipient count and names, paged by send. /api/mail/summary is unchanged because the deployed Email Log page still reads it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The page of sends is chosen before recipients are joined to users and aggregated, so each request only builds JSON for its own page. Each send lists at most 100 recipients, ordered by name, while recipientCount still counts them all. Also renames the shared page cap, documents what sendId is, and gives the grouping test distinct names so it checks the order. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A recipient's second email of the same type and reference now starts a new send, so emails re-sent every few minutes no longer merge into one, and emails with no entity reference are each a send of their own. The default end date now uses the server's time zone, like explicit dates. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Splitting sends per recipient occurrence misgrouped overlapping batches; send ids recorded at write time will replace the heuristic, so it goes back to the 10-minute gap. Each recipient now says whether SendGrid accepted the email, and a send with no listed recipients is kept rather than dropped from the page. Also pins a create-date test to UTC, which failed between 8pm and midnight Eastern. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A user with more than one email in a send is now listed and counted once, delivered if any of their emails was. Also documents that delivered is false everywhere when notifications are off, and drops a redundant aggregate and a comment that restated a type name. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Rows that share a send_id, type and reference are now one send however long it took to write them, and rows from different requests stay apart however close together. Rows written before send ids keep the 10-minute gap rule. Each send is identified by its first row instead of a made-up key that could collide with a real entity reference. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
An interface constant on the DAO is a Sonar warning (S1214), so the cap now lives in EmailService and is always passed to the query. Also covers the sends endpoint's default end and a negative offset. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
kevinmarete
force-pushed
the
km-dt-4263-email-sends
branch
from
October 10, 2026 01:22
7617930 to
083c4ad
Compare
|
The email log needs it to keep a send whose first email falls just before the chosen range but whose others fall inside it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
It comes from date_sent, set when SendGrid's API accepts the email; consent records nothing about delivery to the inbox. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
kevinmarete
marked this pull request as ready for review
October 10, 2026 05:04
kevinmarete
requested review from
fboulnois,
otchet-broad and
rushtong
and removed request for
a team
October 10, 2026 05:04
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.



Addresses
https://broadworkbench.atlassian.net/browse/DT-4263
Security risk: low — a new admin-only read endpoint; it adds recipients' display names to data
/api/mail/rangealready returns to admins.Summary
Each recipient of an email gets its own
email_entityrow, so the Email Log shows a digest sent to 87 people as 87 rows.GET /api/mail/sendsreturns one entry per send instead, with its recipient count and names, for the grouped Email Log agreed on DT-4084.send_idper request. A send is the rows sharing asend_id, email type and entity reference. Rows written before [DT-4263][1/7] Record a send id on each email row #3149 have nosend_id, so for them a send is the rows of one type and reference each created no more than 10 minutes after the previous one.start,end,limit(capped at 1000) andoffsetas/api/mail/summary, paged by send, newest first. Each send lists up to 100 recipients by name, each markedsentor not (SendGrid accepted it; nothing records inbox delivery);recipientCountcounts them all./api/mail/summaryis unchanged: the deployed Email Log page still reads it, until part 3 moves the page to/sends.Reading the query
in_range: the rows in the date range.lone_idis set only on an older row with neither asend_idnor an entity reference, so it partitions alone.flagged: per type, reference,lone_idandsend_id,starts_send = 1on the first row. Rows with asend_idnever start another; older rows do after a gap of more than 10 minutes.numbered: a running sum ofstarts_send, so every row of one send shares asend_number.grouped: each row getssend_row_id, the smallest email id in its send, which identifies the send from here on.page: one row per send with its time and distinct recipient count, then this request'sOFFSET/LIMIT.named: the page's rows joined tousers, one row per recipient, ordered by display name,sentif SendGrid accepted any of their copies.SELECTbuilds each send's recipients from its first 100 names.Example: two NEW_STUDY_DIGEST rows from one daily job share a
send_id30 minutes apart, so they're one send. Two NEW_DAR rows forDAR-1from different requests a minute apart have differentsend_ids, so they're two.The default
endis now the start of tomorrow in the server's time zone, the same zone explicit dates are read in; this also applies to/rangeand/summary, and changes nothing where the server runs in UTC.The 10-minute cutoff hasn't been measured against dev data yet. A send that crosses the range's start or end is split there.
Have you read CONTRIBUTING.md lately? If not, do that first.
🤖 Generated with Claude Code