Serve smart folders and labels as messages, not as index rows

FixEmailService
Shipped
August 30, 2026 at 8:22 PM UTC
Author
Kamo
Commit
7daab4b

Both endpoints answered out of email_metadata.search_index and handed the client what the table holds. A smart folder returned SearchIndexEntity — messageUid, fromEmail, isRead — where the message list renders EmailMessage: uid, from, seen. A label was worse, returning message_labels join rows, which carry a member, a folder, a UID and a label id and no subject, sender or date at all. Neither could have painted a row. The label endpoint had no caller, so nothing ever said so. IndexedEnvelopes now holds the one mapping, lifted out of IndexedMessageListService where it was private to the folder listing. It takes the folder off the row rather than from the caller: a folder listing knows its own folder, a smart folder emphatically does not — its results span every folder the member has indexed, and every action the client offers on a row addresses the message by folder + UID. Two silent failures go with it. An unrecognised condition field was skipped rather than refused, so a typo in "from_email" turned "mail from my accountant" into all my mail and reported success — the one way a filter must never fail. And POST with no conditions serialised null into the column as the four characters "null", which parses as JSON, fails as a condition list, and turns every later read of that folder into an error traceable to nothing. Both are 400s now, as is a query whose saved conditions cannot be read; those were 500s, and none of them is our fault. Verified: mvn test, 464 pass (459 before, 5 new for the mapping).

All changes

Like what you see shipping?

Every one of these updates lands in your workspace automatically. Start free and watch it grow week after week.

Start Free ForeverView Pricing