|
5 | 5 |
|
6 | 6 | import { afterEach, describe, expect, test } from 'bun:test'; |
7 | 7 | import type { Hono } from 'hono'; |
8 | | -import { now, type Client } from '@outreachgraph/db'; |
9 | | -import { recordReplyCheck } from '@outreachgraph/pipeline'; |
| 8 | +import { now, queryAll, type Client } from '@outreachgraph/db'; |
| 9 | +import { recordReplyCheck, sweepBlacklists } from '@outreachgraph/pipeline'; |
10 | 10 | import { generateSecretKey, parseSecretKey } from '@outreachgraph/secrets'; |
11 | 11 | import { createApp } from './app'; |
12 | 12 | import type { AppEnv, RequestActor } from './context'; |
@@ -137,6 +137,51 @@ describe('GET /mailboxes', () => { |
137 | 137 | expect(body.mailboxes.find((m) => m.id === ana.id)!.repliesError).toBeNull(); |
138 | 138 | }); |
139 | 139 |
|
| 140 | + test('the daily blocklist sweep records a listing, alerts once, and drops health', async () => { |
| 141 | + const { app, db } = await harness('mailboxes-blocklist'); |
| 142 | + await call(app, 'PUT', '/integrations/email', { |
| 143 | + host: 'mail.acme.test', |
| 144 | + port: 587, |
| 145 | + secure: false, |
| 146 | + username: 'cy@acme.test', |
| 147 | + password: 'pw', |
| 148 | + fromEmail: 'cy@acme.test', |
| 149 | + imapHost: 'mail.acme.test', |
| 150 | + skipVerification: true, |
| 151 | + }); |
| 152 | + |
| 153 | + const resolve4 = async (name: string): Promise<string[]> => { |
| 154 | + if (name === 'acme.test.dbl.spamhaus.org') return ['127.0.1.2']; |
| 155 | + throw Object.assign(new Error('not found'), { code: 'ENOTFOUND' }); |
| 156 | + }; |
| 157 | + const before = ( |
| 158 | + (await (await call(app, 'GET', '/mailboxes')).json()) as { mailboxes: MailboxJson[] } |
| 159 | + ).mailboxes[0]!; |
| 160 | + |
| 161 | + const swept = await sweepBlacklists(db, SEED.workspaceId, { deps: { resolve4 } }); |
| 162 | + expect(swept).toEqual({ checked: 1, listed: 1 }); |
| 163 | + |
| 164 | + const after = ( |
| 165 | + (await (await call(app, 'GET', '/mailboxes')).json()) as { |
| 166 | + mailboxes: Array<MailboxJson & { blacklistedOn: string[] }>; |
| 167 | + } |
| 168 | + ).mailboxes[0]!; |
| 169 | + expect(after.blacklistedOn).toEqual(['Spamhaus DBL']); |
| 170 | + expect(after.healthIssues[0]).toContain('Spamhaus DBL'); |
| 171 | + expect(after.healthScore).toBeLessThan(before.healthScore); |
| 172 | + |
| 173 | + // Checked today: the next sweep leaves it alone, so no second alert. |
| 174 | + expect(await sweepBlacklists(db, SEED.workspaceId, { deps: { resolve4 } })).toEqual({ |
| 175 | + checked: 0, |
| 176 | + listed: 0, |
| 177 | + }); |
| 178 | + const alerts = await queryAll<{ message: string }>( |
| 179 | + db, |
| 180 | + `SELECT message FROM workflow_events WHERE message LIKE '%is listed on%'`, |
| 181 | + ); |
| 182 | + expect(alerts).toHaveLength(1); |
| 183 | + }); |
| 184 | + |
140 | 185 | test('404s the DNS report for a mailbox in another workspace', async () => { |
141 | 186 | const { app } = await harness('mailboxes-dns-404'); |
142 | 187 | expect((await call(app, 'GET', '/mailboxes/ita_nope/dns')).status).toBe(404); |
|
0 commit comments