import { tap, expect } from '@git.zone/tstest/tapbundle'; import { startTestServer, stopTestServer, type ITestServer } from '../../helpers/server.loader.js'; import { createSmtpClient } from '../../../ts/mail/delivery/smtpclient/index.js'; import { Email } from '../../../ts/mail/core/classes.email.js'; import * as net from 'net'; let testServer: ITestServer; tap.test('setup - start SMTP server for quota tests', async () => { testServer = await startTestServer({ port: 2563, tlsEnabled: false, authRequired: false }); expect(testServer.port).toEqual(2563); }); tap.test('CERR-05: Mailbox quota exceeded - 452 temporary', async () => { // Create server that simulates temporary quota full const quotaServer = net.createServer((socket) => { socket.write('220 Quota Test Server\r\n'); socket.on('data', (data) => { const command = data.toString().trim(); if (command.startsWith('EHLO')) { socket.write('250 OK\r\n'); } else if (command.startsWith('MAIL FROM')) { socket.write('250 OK\r\n'); } else if (command.startsWith('RCPT TO')) { socket.write('452 4.2.2 Mailbox full, try again later\r\n'); } else if (command === 'QUIT') { socket.write('221 Bye\r\n'); socket.end(); } }); }); await new Promise((resolve) => { quotaServer.listen(2564, () => resolve()); }); const smtpClient = createSmtpClient({ host: '127.0.0.1', port: 2564, secure: false, connectionTimeout: 5000 }); const email = new Email({ from: 'sender@example.com', to: 'user@example.com', subject: 'Quota Test', text: 'Testing quota errors' }); const result = await smtpClient.sendMail(email); expect(result.success).toBeFalse(); console.log('Actual error:', result.error?.message); expect(result.error?.message).toMatch(/452|mailbox|full|recipient/i); console.log('✅ 452 temporary quota error handled'); await smtpClient.close(); await new Promise((resolve) => { quotaServer.close(() => resolve()); }); }); tap.test('CERR-05: Mailbox quota exceeded - 552 permanent', async () => { // Create server that simulates permanent quota exceeded const quotaServer = net.createServer((socket) => { socket.write('220 Quota Test Server\r\n'); socket.on('data', (data) => { const command = data.toString().trim(); if (command.startsWith('EHLO')) { socket.write('250 OK\r\n'); } else if (command.startsWith('MAIL FROM')) { socket.write('250 OK\r\n'); } else if (command.startsWith('RCPT TO')) { socket.write('552 5.2.2 Mailbox quota exceeded\r\n'); } else if (command === 'QUIT') { socket.write('221 Bye\r\n'); socket.end(); } }); }); await new Promise((resolve) => { quotaServer.listen(2565, () => resolve()); }); const smtpClient = createSmtpClient({ host: '127.0.0.1', port: 2565, secure: false, connectionTimeout: 5000 }); const email = new Email({ from: 'sender@example.com', to: 'user@example.com', subject: 'Quota Test', text: 'Testing quota errors' }); const result = await smtpClient.sendMail(email); expect(result.success).toBeFalse(); console.log('Actual error:', result.error?.message); expect(result.error?.message).toMatch(/552|quota|recipient/i); console.log('✅ 552 permanent quota error handled'); await smtpClient.close(); await new Promise((resolve) => { quotaServer.close(() => resolve()); }); }); tap.test('CERR-05: System storage error - 452', async () => { // Create server that simulates system storage issue const storageServer = net.createServer((socket) => { socket.write('220 Storage Test Server\r\n'); socket.on('data', (data) => { const command = data.toString().trim(); if (command.startsWith('EHLO')) { socket.write('250 OK\r\n'); } else if (command.startsWith('MAIL FROM')) { socket.write('250 OK\r\n'); } else if (command.startsWith('RCPT TO')) { socket.write('452 4.3.1 Insufficient system storage\r\n'); } else if (command === 'QUIT') { socket.write('221 Bye\r\n'); socket.end(); } }); }); await new Promise((resolve) => { storageServer.listen(2566, () => resolve()); }); const smtpClient = createSmtpClient({ host: '127.0.0.1', port: 2566, secure: false, connectionTimeout: 5000 }); const email = new Email({ from: 'sender@example.com', to: 'user@example.com', subject: 'Storage Test', text: 'Testing storage errors' }); const result = await smtpClient.sendMail(email); expect(result.success).toBeFalse(); console.log('Actual error:', result.error?.message); expect(result.error?.message).toMatch(/452|storage|recipient/i); console.log('✅ 452 system storage error handled'); await smtpClient.close(); await new Promise((resolve) => { storageServer.close(() => resolve()); }); }); tap.test('CERR-05: Message too large - 552', async () => { // Create server that simulates message size limit const sizeServer = net.createServer((socket) => { socket.write('220 Size Test Server\r\n'); let inData = false; socket.on('data', (data) => { const lines = data.toString().split('\r\n'); lines.forEach(line => { if (!line && lines[lines.length - 1] === '') return; if (inData) { // We're in DATA mode - look for the terminating dot if (line === '.') { socket.write('552 5.3.4 Message too big for system\r\n'); inData = false; } // Otherwise, just consume the data } else { // We're in command mode if (line.startsWith('EHLO')) { socket.write('250-SIZE 1000\r\n250 OK\r\n'); } else if (line.startsWith('MAIL FROM')) { socket.write('250 OK\r\n'); } else if (line.startsWith('RCPT TO')) { socket.write('250 OK\r\n'); } else if (line === 'DATA') { socket.write('354 Send data\r\n'); inData = true; } else if (line === 'QUIT') { socket.write('221 Bye\r\n'); socket.end(); } } }); }); }); await new Promise((resolve) => { sizeServer.listen(2567, () => resolve()); }); const smtpClient = createSmtpClient({ host: '127.0.0.1', port: 2567, secure: false, connectionTimeout: 5000 }); const email = new Email({ from: 'sender@example.com', to: 'user@example.com', subject: 'Large Message Test', text: 'This is supposed to be a large message that exceeds the size limit' }); const result = await smtpClient.sendMail(email); expect(result.success).toBeFalse(); console.log('Actual error:', result.error?.message); expect(result.error?.message).toMatch(/552|big|size|data/i); console.log('✅ 552 message size error handled'); await smtpClient.close(); await new Promise((resolve) => { sizeServer.close(() => resolve()); }); }); tap.test('CERR-05: Successful email with normal server', async () => { // Test successful email send with working server const smtpClient = createSmtpClient({ host: testServer.hostname, port: testServer.port, secure: false, connectionTimeout: 5000 }); const email = new Email({ from: 'sender@example.com', to: 'user@example.com', subject: 'Normal Test', text: 'Testing normal operation' }); const result = await smtpClient.sendMail(email); expect(result.success).toBeTrue(); console.log('✅ Normal email sent successfully'); await smtpClient.close(); }); tap.test('cleanup - stop SMTP server', async () => { await stopTestServer(testServer); }); export default tap.start();