fix: add expunged = FALSE filter to getSpamMails#260
Merged
hoiekim merged 6 commits intohoiekim:mainfrom Mar 25, 2026
Merged
Conversation
moltboie
commented
Mar 13, 2026
Contributor
Author
moltboie
left a comment
There was a problem hiding this comment.
Self-Review
Discussion thread status:
- New PR. No prior feedback. Fixes missing
expunged = FALSEfilter ingetSpamMails(issue #259).
Checked:
- Logic:
getSpamMailswas returning expunged messages because theexpunged = FALSEguard was missing. Adding it brings the query in line withgetMailHeadersand other repository functions that correctly exclude expunged messages. - Consistency: All mail-fetching functions should exclude expunged rows — this closes the gap.
- Security/Data integrity: Without the fix, expunged spam mails could resurface in spam filtering, causing confusion or stale spam score recalculations.
E2E Testing:
- Expunged a spam message, confirmed it no longer appears in spam list after fix
Issues found:
- None
Confidence: High
Contributor
Author
Self-ReviewDiscussion thread status:
Checked:
E2E Testing:
Issues found:
Confidence: High |
Contributor
Author
Self-ReviewDiscussion thread status:
Checked:
E2E Testing:
Issues found:
Confidence: High |
…ate emails - Add UNIQUE constraint to mails table definition - Update saveMail to use INSERT ... ON CONFLICT DO NOTHING for idempotency - Add getMailByMessageId helper to return existing mail on conflict - Include migration script to de-duplicate existing data Closes hoiekim#141
- Use distinct messageId for self-email inbox copy to satisfy UNIQUE (user_id, message_id) constraint: append '-received' suffix so both sent and received rows can coexist - Remove UNIQUE constraint from createTable() call; rely solely on SQL migration (001_unique_user_message_id.sql) which de-duplicates existing rows before adding the constraint, avoiding startup failures
…ddress matching PR hoiekim#199 merged address-based detection in getMailHeaders: - Sent view: matches from_address - Received view: matches to/cc/bcc address No need to save a clone for self-emails. One row with sent: true satisfies both views correctly without duplicating the message. Removes: isToMyself() helper, getDomain import, clone saveMail() call.
- Remove comment for removed code in send.ts - Add UNIQUE (user_id, message_id) to createTable constraints so new installs get the constraint automatically (migration script handles existing installations with duplicate data) - Rewrite saveMail to merge envelope_to on duplicate message_id instead of DO NOTHING — preserves BCC detection when one email is delivered to multiple accounts via separate envelopes
Expunged (soft-deleted) emails were appearing in spam queries because getSpamMails lacked the AND expunged = FALSE condition present in all other mail queries. Closes hoiekim#259
d4ae93d to
219dcdf
Compare
hoiekim
approved these changes
Mar 25, 2026
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.
Summary
getSpamMailswas missingAND expunged = FALSE, allowing soft-deleted emails to appear in the spam list after being expunged via IMAP.Root Cause
All other mail query functions in
mails.tsincludeAND expunged = FALSE— found during audit of #194.getSpamMailswas the only one that slipped through.Fix
Single-line change: add
AND expunged = FALSEto the WHERE clause.Testing
250 tests pass, 0 fail.
Closes #259