mirror of
https://github.com/bulwarkmail/webmail.git
synced 2026-11-04 08:15:41 +00:00
fix: show the inbox in the demo when a category tab filters on a header
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { DemoJMAPClient } from '@/lib/demo/demo-client';
|
||||
|
||||
// A `header` condition used to be ignored, so it matched every message. The
|
||||
// category tabs' Promotions rule has one, which left the default tab (NOT all
|
||||
// the other tabs) empty on an Inbox full of mail.
|
||||
describe('DemoJMAPClient header filter', () => {
|
||||
async function inboxOf(client: DemoJMAPClient) {
|
||||
return (await client.getMailboxes()).find((m) => m.role === 'inbox')!;
|
||||
}
|
||||
|
||||
it('matches only messages that carry the header', async () => {
|
||||
const client = new DemoJMAPClient();
|
||||
const inbox = await inboxOf(client);
|
||||
const all = await client.getEmails(inbox.id, undefined, 500);
|
||||
const listed = await client.getEmails(inbox.id, undefined, 500, 0, undefined, false, { header: ['List-Id'] });
|
||||
|
||||
expect(listed.total).toBeGreaterThan(0);
|
||||
expect(listed.total).toBeLessThan(all.total);
|
||||
for (const e of listed.emails) {
|
||||
expect(Object.keys(e.headers ?? {}).map((h) => h.toLowerCase())).toContain('list-id');
|
||||
}
|
||||
});
|
||||
|
||||
it('compares the value when the condition has one', async () => {
|
||||
const client = new DemoJMAPClient();
|
||||
const inbox = await inboxOf(client);
|
||||
const hit = await client.getEmails(inbox.id, undefined, 500, 0, undefined, false, { header: ['list-id', 'BEACON.meridianlabs'] });
|
||||
const miss = await client.getEmails(inbox.id, undefined, 500, 0, undefined, false, { header: ['List-Id', 'no-such-list'] });
|
||||
|
||||
expect(hit.total).toBeGreaterThan(0);
|
||||
expect(miss.total).toBe(0);
|
||||
});
|
||||
|
||||
it('leaves mail in a default tab that excludes a header rule', async () => {
|
||||
const client = new DemoJMAPClient();
|
||||
const inbox = await inboxOf(client);
|
||||
const primary = await client.getEmails(inbox.id, undefined, 500, 0, undefined, false, {
|
||||
operator: 'NOT',
|
||||
conditions: [{ operator: 'OR', conditions: [{ from: 'mailchimp' }, { header: ['List-Unsubscribe'] }] }],
|
||||
});
|
||||
|
||||
expect(primary.total).toBeGreaterThan(0);
|
||||
});
|
||||
});
|
||||
+13
-2
@@ -523,8 +523,9 @@ export class DemoJMAPClient implements IJMAPClient {
|
||||
/**
|
||||
* Minimal JMAP filter evaluator for demo mode: supports the conditions the
|
||||
* message-list category tabs and the folder-less search scopes use
|
||||
* (hasKeyword / notKeyword / from / text / inMailbox / inMailboxOtherThan
|
||||
* and AND / OR / NOT operators). Unknown conditions are ignored.
|
||||
* (hasKeyword / notKeyword / from / text / header / inMailbox /
|
||||
* inMailboxOtherThan and AND / OR / NOT operators). Unknown conditions are
|
||||
* ignored.
|
||||
*/
|
||||
private matchesFilter(e: Email, filter: Record<string, unknown>): boolean {
|
||||
if (typeof filter.operator === 'string') {
|
||||
@@ -564,6 +565,16 @@ export class DemoJMAPClient implements IJMAPClient {
|
||||
const bodyText = Object.values(e.bodyValues || {}).map(v => v.value).join(' ').toLowerCase();
|
||||
if (!bodyText.includes(q)) return false;
|
||||
}
|
||||
// RFC 8621 4.4.1: [name] tests that the header exists, [name, value] that
|
||||
// its value contains the text. Ignoring it would match every message.
|
||||
if (Array.isArray(filter.header) && typeof filter.header[0] === 'string') {
|
||||
const wanted = filter.header[0].toLowerCase();
|
||||
const text = typeof filter.header[1] === 'string' ? filter.header[1].toLowerCase() : null;
|
||||
const match = Object.entries(e.headers ?? {}).some(([name, value]) =>
|
||||
name.toLowerCase() === wanted
|
||||
&& (text === null || (Array.isArray(value) ? value : [value]).some(v => String(v).toLowerCase().includes(text))));
|
||||
if (!match) return false;
|
||||
}
|
||||
if (typeof filter.inMailbox === 'string' && !e.mailboxIds[filter.inMailbox]) return false;
|
||||
if (Array.isArray(filter.inMailboxOtherThan)) {
|
||||
const excluded = new Set(filter.inMailboxOtherThan as string[]);
|
||||
|
||||
Reference in New Issue
Block a user