delivery-tracker.test.js 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. import assert from 'node:assert/strict';
  2. import { mkdtempSync } from 'node:fs';
  3. import { tmpdir } from 'node:os';
  4. import path from 'node:path';
  5. import { test } from 'node:test';
  6. import {
  7. extractQueueIdFromSmtpResponse,
  8. parsePostfixLogLine
  9. } from '../src/delivery-tracker.js';
  10. import {
  11. createDomain,
  12. createUser,
  13. initDatabase,
  14. listSendEvents,
  15. logSendEvent,
  16. updateSendEventDelivery
  17. } from '../src/db.js';
  18. test('extracts postfix queue ids from SMTP queue responses', () => {
  19. assert.equal(extractQueueIdFromSmtpResponse('250 2.0.0 Ok: queued as 1DAEBC3EC8'), '1DAEBC3EC8');
  20. assert.equal(extractQueueIdFromSmtpResponse('250 OK queued as ABC123'), 'ABC123');
  21. assert.equal(extractQueueIdFromSmtpResponse('250 message accepted'), '');
  22. });
  23. test('parses postfix delivery status lines', () => {
  24. const event = parsePostfixLogLine(
  25. 'Jul 08 04:15:21 in postfix/smtp[300]: 1DAEBC3EC8: to=<recipient@example.net>, relay=mx.example.net[203.0.113.25]:25, delay=3.4, delays=0.04/0.11/1.7/1.6, dsn=2.0.0, status=sent (250 OK: queued as.)'
  26. );
  27. assert.equal(event.queueId, '1DAEBC3EC8');
  28. assert.equal(event.recipient, 'recipient@example.net');
  29. assert.equal(event.relay, 'mx.example.net[203.0.113.25]:25');
  30. assert.equal(event.dsn, '2.0.0');
  31. assert.equal(event.status, 'sent');
  32. assert.equal(event.response, '250 OK: queued as.');
  33. });
  34. test('updates send events from postfix delivery attempts', () => {
  35. initDatabase(tempDataDir(), 'test-secret');
  36. const user = createUser({ username: 'alice', email: 'alice@example.com', password: 'password123' });
  37. const domain = createDomain(user.id, domainFixture('sender.example.com'));
  38. logSendEvent({
  39. userId: user.id,
  40. domainId: domain.id,
  41. sender: 'noreply@sender.example.com',
  42. recipients: ['recipient@example.net'],
  43. subject: 'Tracked',
  44. status: 'queued',
  45. detail: '250 2.0.0 Ok: queued as 1DAEBC3EC8'
  46. });
  47. const updated = updateSendEventDelivery('1DAEBC3EC8', {
  48. at: '2026-07-08T04:15:21.000Z',
  49. queueId: '1DAEBC3EC8',
  50. recipient: 'recipient@example.net',
  51. relay: 'mx.example.net[203.0.113.25]:25',
  52. dsn: '2.0.0',
  53. status: 'sent',
  54. response: '250 OK: queued as.',
  55. raw: 'raw postfix line'
  56. });
  57. assert.equal(updated, true);
  58. const [event] = listSendEvents(user.id);
  59. assert.equal(event.queueId, '1DAEBC3EC8');
  60. assert.equal(event.status, 'sent');
  61. assert.equal(event.deliveredAt, '2026-07-08T04:15:21.000Z');
  62. assert.equal(event.deliveryAttempts.length, 1);
  63. assert.equal(event.deliveryAttempts[0].status, 'sent');
  64. assert.equal(event.deliveryAttempts[0].recipient, 'recipient@example.net');
  65. updateSendEventDelivery('1DAEBC3EC8', {
  66. at: '2026-07-08T04:15:21.000Z',
  67. queueId: '1DAEBC3EC8',
  68. recipient: 'recipient@example.net',
  69. relay: 'mx.example.net[203.0.113.25]:25',
  70. dsn: '2.0.0',
  71. status: 'sent',
  72. response: '250 OK: queued as.',
  73. raw: 'raw postfix line'
  74. });
  75. assert.equal(listSendEvents(user.id)[0].deliveryAttempts.length, 1);
  76. });
  77. function domainFixture(domain) {
  78. return {
  79. domain,
  80. selector: 'mh202607',
  81. verificationToken: 'token',
  82. dkimPublic: 'public',
  83. dkimPrivate: 'private',
  84. senderHost: `mail.${domain}`,
  85. sendingIp: '127.0.0.1',
  86. spfExtra: '',
  87. dmarcPolicy: 'none',
  88. dmarcRua: ''
  89. };
  90. }
  91. function tempDataDir() {
  92. return mkdtempSync(path.join(tmpdir(), 'mailhub-test-'));
  93. }