Files
selfphoneng/scripts/e2e/smtp-sink.mjs
T
iamdoubz 8d752ba705 voicemail: index messages, live event, email with the recording
services/voicemail.ts rescans a mailbox on Asterisk's MessageWaiting event
(and every mailbox on AMI connect) instead of watching files, upserts
voicemail_messages by msg_id, marks vanished ones deleted, sends
voicemail.new to the owner only, and emails the wav. Delete-after-email
uses AMI VoicemailRemove, and only when the audio was attached. Asterisk
24 has VoicemailMove/VoicemailRemove, so 04 §5.6 drops the renumbering
plan. New VOICEMAIL_DIR setting; e2e m4-t2 checks the email arrives
within 10 s with a playable attachment (SMTP sink shared with m3-t4).

Task: M4-T2
2026-10-17 22:33:52 -05:00

37 lines
1.2 KiB
JavaScript

// SPDX-License-Identifier: AGPL-3.0-or-later
// Just enough SMTP for nodemailer: no auth, no TLS, keeps every message (raw RFC 5322 text).
import { createServer } from 'node:net';
export async function smtpSink(port = 2525) {
const mails = [];
const server = createServer((sock) => {
let data = false;
let buf = '';
let msg = '';
sock.write('220 sink ESMTP\r\n');
sock.on('data', (d) => {
buf += d;
let i;
while ((i = buf.indexOf('\r\n')) >= 0) {
const line = buf.slice(0, i);
buf = buf.slice(i + 2);
if (data) {
if (line === '.') {
data = false;
mails.push(msg);
msg = '';
sock.write('250 ok\r\n');
} else msg += line.replace(/^\.\./, '.') + '\n';
} else if (/^EHLO/i.test(line)) sock.write('250-sink\r\n250 OK\r\n');
else if (/^DATA/i.test(line)) {
data = true;
sock.write('354 go\r\n');
} else if (/^QUIT/i.test(line)) sock.end('221 bye\r\n');
else sock.write('250 ok\r\n');
}
});
});
await new Promise((r) => server.listen(port, '127.0.0.1', r));
return { mails, server };
}