fix: apply unread/starred filters in mailbox queries

This commit is contained in:
Linus Rath
2026-05-08 00:50:27 +02:00
parent 29b06a3a4f
commit 71ff8930a2
2 changed files with 31 additions and 1 deletions
+18
View File
@@ -90,6 +90,24 @@ describe('email operations', () => {
const call = mockRequest.mock.calls[0][0][0];
expect(call[1].filter).toEqual({ inMailbox: 'mb-1', hasKeyword: '$flagged' });
});
it('should AND-wrap a FilterOperator instead of spreading it', async () => {
mockRequest.mockResolvedValue({
methodResponses: [['Email/query', { ids: [], total: 0 }, '0']],
});
const userFilter = {
operator: 'AND',
conditions: [{ inMailbox: 'mb-1' }, { notKeyword: '$seen' }],
};
await queryEmails('mb-1', { filter: userFilter });
const call = mockRequest.mock.calls[0][0][0];
expect(call[1].filter).toEqual({
operator: 'AND',
conditions: [{ inMailbox: 'mb-1' }, userFilter],
});
});
});
describe('getEmails', () => {
+13 -1
View File
@@ -93,10 +93,22 @@ export async function queryEmails(
},
): Promise<{ ids: string[]; total: number }> {
const accountId = jmapClient.accountId;
const inMailbox = { inMailbox: mailboxId };
const userFilter = options?.filter;
// JMAP filters are either a FilterCondition or a FilterOperator (operator +
// conditions) — never both. Spreading a FilterOperator next to `inMailbox`
// produces a hybrid object that servers reduce to the FilterCondition,
// silently dropping the operator's conditions (e.g. the "unread" toggle).
const filter =
!userFilter || Object.keys(userFilter).length === 0
? inMailbox
: 'operator' in userFilter
? { operator: 'AND', conditions: [inMailbox, userFilter] }
: { ...inMailbox, ...userFilter };
const res = await jmapClient.request([
['Email/query', {
accountId,
filter: { inMailbox: mailboxId, ...options?.filter },
filter,
sort: options?.sort ?? [{ property: 'receivedAt', isAscending: false }],
position: options?.position ?? 0,
limit: options?.limit ?? 50,