import assert from 'node:assert/strict'; import { spawn } from 'node:child_process'; import { mkdtempSync } from 'node:fs'; import net from 'node:net'; import { tmpdir } from 'node:os'; import path from 'node:path'; import { test } from 'node:test'; test('instruments tracked API HTML before DKIM and supports per-send opt-out', async () => { const relay = await startFakeSmtpServer(); const port = await freePort(); const dataDir = mkdtempSync(path.join(tmpdir(), 'mailhub-send-tracking-')); const child = spawn(process.execPath, ['src/server.js'], { cwd: process.cwd(), env: { ...process.env, PORT: String(port), DATA_DIR: dataDir, APP_BASE_URL: `http://127.0.0.1:${port}`, ADMIN_PASSWORD: 'password123', SESSION_SECRET: 'session-secret', TRACKING_SECRET: 'tracking-secret', SMTP_HOST: '127.0.0.1', SMTP_PORT: String(relay.port), SMTP_HELO: 'mail.track-send.example', SEND_REQUIRES_VERIFIED: 'false', SUBMISSION_ENABLED: 'false', IMAP_ENABLED: 'false', POP3_ENABLED: 'false', WEBHOOK_WORKER_ENABLED: '0', DNS_AUTO_CHECK_ENABLED: 'false', DELIVERY_TRACKING_ENABLED: 'false' }, stdio: ['ignore', 'pipe', 'pipe'] }); try { await waitForOutput(child, 'MailHub listening'); const baseUrl = `http://127.0.0.1:${port}`; const cookie = await login(baseUrl); const domainResponse = await fetch(`${baseUrl}/api/domains`, { method: 'POST', headers: { 'Content-Type': 'application/json', Cookie: cookie }, body: JSON.stringify({ domain: 'track-send.example' }) }); assert.equal(domainResponse.status, 201); const settings = await fetch(`${baseUrl}/api/admin/settings`, { method: 'PATCH', headers: { 'Content-Type': 'application/json', Cookie: cookie }, body: JSON.stringify({ engagementTrackingEnabled: true }) }); assert.equal(settings.status, 200); assert.equal((await settings.json()).settings.engagementTrackingEnabled, true); const tracked = await sendHtml(baseUrl, cookie, { subject: 'Tracked HTML', html: '
Reset' }); assert.equal(tracked.eventId > 0, true); assert.deepEqual(tracked.tracking, { enabled: true, opens: true, clicks: true, messageLevel: false }); await waitFor(() => relay.messages.length === 1); const trackedMessage = relay.messages[0]; assert.match(trackedMessage, /^DKIM-Signature:/m); const trackedHtml = decodeHtmlPart(trackedMessage); assert.match(trackedHtml, new RegExp(`${escapeRegExp(baseUrl)}/t/o/[A-Za-z0-9_-]+\\.gif`)); assert.match(trackedHtml, new RegExp(`${escapeRegExp(baseUrl)}/t/c/[A-Za-z0-9_-]+`)); assert.equal(trackedHtml.includes('token=secret'), false); const optedOut = await sendHtml(baseUrl, cookie, { subject: 'Untracked HTML', html: 'Private', tracking: { opens: false, clicks: false } }); assert.deepEqual(optedOut.tracking, { enabled: false, opens: false, clicks: false, messageLevel: false }); await waitFor(() => relay.messages.length === 2); const untrackedHtml = decodeHtmlPart(relay.messages[1]); assert.match(untrackedHtml, /https:\/\/example\.net\/private/); assert.equal(untrackedHtml.includes('/t/o/'), false); assert.equal(untrackedHtml.includes('/t/c/'), false); const noTrackableLinks = await sendHtml(baseUrl, cookie, { subject: 'No trackable links', html: 'No links here.
', tracking: { opens: false, clicks: true } }); assert.deepEqual(noTrackableLinks.tracking, { enabled: false, opens: false, clicks: false, messageLevel: false }); await waitFor(() => relay.messages.length === 3); const noTrackableLinksHtml = decodeHtmlPart(relay.messages[2]); assert.equal(noTrackableLinksHtml.includes('/t/c/'), false); const events = await fetch(`${baseUrl}/api/events`, { headers: { Cookie: cookie } }).then((response) => response.json()); assert.equal(events.events.length, 3); assert.equal(events.events.every((event) => event.status === 'queued'), true); assert.equal(events.events.find((event) => event.subject === 'Tracked HTML').tracking.enabled, true); assert.equal(events.events.find((event) => event.subject === 'No trackable links').tracking.enabled, false); } finally { child.kill('SIGTERM'); await waitForExit(child, 1000); await relay.close(); } }); test('API sends configured deliverability headers without changing the default envelope sender', async () => { const relay = await startFakeSmtpServer(); const port = await freePort(); const dataDir = mkdtempSync(path.join(tmpdir(), 'mailhub-send-headers-')); const child = spawn(process.execPath, ['src/server.js'], { cwd: process.cwd(), env: { ...process.env, PORT: String(port), DATA_DIR: dataDir, APP_BASE_URL: `http://127.0.0.1:${port}`, ADMIN_PASSWORD: 'password123', SESSION_SECRET: 'session-secret', TRACKING_SECRET: 'tracking-secret', SMTP_HOST: '127.0.0.1', SMTP_PORT: String(relay.port), SMTP_HELO: 'mail.headers.example', SEND_REQUIRES_VERIFIED: 'false', SUBMISSION_ENABLED: 'false', IMAP_ENABLED: 'false', POP3_ENABLED: 'false', WEBHOOK_WORKER_ENABLED: '0', DNS_AUTO_CHECK_ENABLED: 'false', DELIVERY_TRACKING_ENABLED: 'false' }, stdio: ['ignore', 'pipe', 'pipe'] }); try { await waitForOutput(child, 'MailHub listening'); const baseUrl = `http://127.0.0.1:${port}`; const cookie = await login(baseUrl); const domainResponse = await fetch(`${baseUrl}/api/domains`, { method: 'POST', headers: { 'Content-Type': 'application/json', Cookie: cookie }, body: JSON.stringify({ domain: 'headers.example' }) }); assert.equal(domainResponse.status, 201); const settings = await fetch(`${baseUrl}/api/admin/settings`, { method: 'PATCH', headers: { 'Content-Type': 'application/json', Cookie: cookie }, body: JSON.stringify({ listUnsubscribeMailto: 'unsubscribe@headers.example', listUnsubscribeUrl: 'https://headers.example/unsubscribe/{eventId}/{recipient}', listUnsubscribePostEnabled: true, feedbackIdEnabled: true, reportAbuseTo: 'abuse@headers.example', csaComplaintsTo: 'csa@headers.example', bounceAddress: 'bounce@headers.example', bounceEnvelopeEnabled: false }) }); assert.equal(settings.status, 200); const settingsPayload = await settings.json(); assert.equal(settingsPayload.settings.listUnsubscribePostEnabled, true); assert.equal(settingsPayload.settings.bounceEnvelopeEnabled, false); await sendHtml(baseUrl, cookie, { from: 'noreply@headers.example', to: 'reader@example.net', subject: 'Headers', html: 'Hello
' }); await waitFor(() => relay.messages.length === 1); const rawMessage = relay.messages[0]; assert.match(rawMessage, /^List-Unsubscribe:Hello again
' }); await waitFor(() => relay.messages.length === 2); assert.ok(relay.commands.some((command) => command === 'MAIL FROM: