import { tap, expect } from '@git.zone/tstest/tapbundle'; import * as plugins from '../ts/plugins.js'; import * as paths from '../ts/paths.js'; import { createSmtpServer } from '../ts/mail/delivery/smtpserver/index.js'; import { UnifiedEmailServer } from '../ts/mail/routing/classes.unified.email.server.js'; import { Email } from '../ts/mail/core/classes.email.js'; import type { ISmtpServerOptions } from '../ts/mail/delivery/interfaces.js'; /** * Tests for the SMTP server class */ tap.test('verify SMTP server initialization', async () => { // Mock email server const mockEmailServer = { processEmailByMode: async () => new Email({ from: 'test@example.com', to: 'recipient@example.com', subject: 'Test Email', text: 'This is a test email' }) } as any; // Create test configuration const options: ISmtpServerOptions = { port: 2525, // Use a high port for testing hostname: 'test.example.com', key: '-----BEGIN RSA PRIVATE KEY-----\nMIIEpAIBAAKCAQEAxzYIwlfnr7AK2v6E+c2oYD7nAIXIIvDuvVvZ8R9kyxXIzTXB\nj5D1AgntqKS3bFR1XT8hCVeXjuLKPBvXbhVjG15gXlXxpNiFi1ZcphJvs4zB/Vh7\nZv2ALt3anSIwsJ2rZA/R/GqdJPkHvYf/GMTDLw0YllR0YOevErnRIIM5S58Lj2nT\nCr5v5hK1Gl9mWwRkFQKkWVl2UXt/JX6C7Z6UyJXMZSnoG0Kw6GQje41K5r0Zdzrh\nrGfmb9wSDUn9sZGX6il+oMiYz7UgQkPEzGUZEJxKJwxy8ZgPdSgbvYq4WwPwbBUJ\nlpw0gt5i6HOS7CphRama+zAf5LvfSLoLXSP5JwIDAQABAoIBAQC8C5Ge6wS4LuH9\ntbZFPwjdGHXL+QT2fOFxPBrE7PkeY8UXD7G5Yei6iqqCxJh8nhLQ3DoayhZM69hO\nePOV1Z/LDERCnGel15WKQ1QJ1HZ+JQXnfQrE1Mi9QrXO5bVFtnXIr0mZ+AzwoUmn\nK5fYCvaL3xDZPDzOYL5kZG2hQKgbywGKZoQx16G0dSEhlAHbK9z6XmPRrbUKGzB8\nqV7QGbL7BUTQs5JW/8LpkYr5C0q5THtUVb9mHNR3jPf9WTPQ0D3lxcbLS4PQ8jQ/\nL/GcuHGmsXhe2Unw3w2wpuJKPeHKz4rBNIvaSjIZl9/dIKM88JYQTiIGKErxsC0e\nkczQMp6BAoGBAO0zUN8H7ynXGNNtK/tJo0lI3qg1ZKgr+0CU2L5eU8Bn1oJ1JkCI\nWD3p36NdECx5tGexm9U6MN+HzKYUjnQ6LKzbHQGLZqzF5IL5axXgCn8w4BM+6Ixm\ny8kQgsTKlKRMXIn8RZCmXNnc7v0FhBgpDxPmm7ZUuOPrInd8Ph4mEsePAoGBANb4\n3/izAHnLEp3/sTOZpfWBnDcvEHCG7/JAX0TDRW1FpXiTHpvDV1j3XU3EvLl7WRJ1\nB+B8h/Z6kQtUUxQ3I+zxuQIkQYI8qPu+xhQ8gb5AIO5CMX09+xKUgYjQtm7kYs7W\nL0LD9u3hkGsJk2wfVvMJKb3OSIHeTwRzFCzGX995AoGADkLB8eu/FKAIfwRPCHVE\nsfwMtqjkj2XJ9FeNcRQ5g/Tf8OGnCGEzBwXb05wJVrXUgXp4dBaqYTdAKj8uLEvd\nmi9t/LzR+33cGUdAQHItxcKbsMv00TyNRQUvZFZ7ZEY8aBkv5uZfvJHZ5iQ8C7+g\nHGXNfVGXGPutz/KN6X25CLECgYEAjVLK0MkXzLxCYJRDIhB1TpQVXjpxYUP2Vxls\nSSxfeYqkJPgNvYiHee33xQ8+TP1y9WzkWh+g2AbGmwTuKKL6CvQS9gKVvqqaFB7y\nKrkR13MTPJKvHHdQYKGQqQGgHKh0kGFCC0+PoVwtYs/XU1KpZCE16nNgXrOvTYNN\nHxESa+kCgYB7WOcawTp3WdKP8JbolxIfxax7Kd4QkZhY7dEb4JxBBYXXXpv/NHE9\npcJw4eKDyY+QE2AHPu3+fQYzXopaaTGRpB+ynEfYfD2hW+HnOWfWu/lFJbiwBn/S\nwRsYzSWiLtNplKNFRrsSoMWlh8GOTUpZ7FMLXWhE4rE9NskQBbYq8g==\n-----END RSA PRIVATE KEY-----', cert: '-----BEGIN CERTIFICATE-----\nMIIDazCCAlOgAwIBAgIUcmAewXEYwtzbZmZAJ5inMogKSbowDQYJKoZIhvcNAQEL\nBQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM\nGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yNDAyMjAwODM4MzRaFw0yNTAy\nMTkwODM4MzRaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEw\nHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggEiMA0GCSqGSIb3DQEB\nAQUAA4IBDwAwggEKAoIBAQDHNgjCV+evsAra/oT5zahgPucAhcgi8O69W9nxH2TL\nFcjNNcGPkPUCCe2opLdsVHVdPyEJV5eO4so8G9duFWMbXmBeVfGk2IWLVlymEm+z\njMH9WHtm/YAu3dqdIjCwnatED9H8ap0k+Qd9h/8YxMMvDRiWVHRg568SudEggzlL\nnwuPadMKvm/mErUaX2ZbBGQVAqRZWXZRe38lfoLtnpTIlcxlKegbQrDoZCN7jUrm\nvRl3OuGsZ+Zv3BINSf2xkZfqKX6gyJjPtSBCQ8TMZRkQnEonDHLxmA91KBu9irhb\nA/BsFQmWnDSC3mLoc5LsKmFFqZr7MB/ku99IugtdI/knAgMBAAGjUzBRMB0GA1Ud\nDgQWBBQryyWLuN22OqU1r9HIt2tMLBk42DAfBgNVHSMEGDAWgBQryyWLuN22OqU1\nr9HIt2tMLBk42DAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAe\nCeXQZlXJ2xLnDoOoKY3BpodErNmAwygGYxwDCU0xPbpUMPrQhLI80JlZmfy58gT/\n0ZbULS+srShfEsFnBLmzWLGXDvA/IKCQyTmCQwbPeELGXF6h4URMb+lQL7WL9tY0\nuUg2dA+7CtYokIrOkGqUitPK3yvVhxugkf51WIgKMACZDibOQSWrV5QO2vHOAaO9\nePzRGGl3+Ebmcs3+5w1fI6OLsIZH10lfEnC83C0lO8tIJlGsXMQkCjAcX22rT0rc\nAcxLm07H4EwMwgOAJUkuDjD3y4+KH91jKWF8bhaLZooFB8lccNnaCRiuZRnXlvmf\nM7uVlLGwlj5R9iHd+0dP\n-----END CERTIFICATE-----' }; // Create SMTP server instance const smtpServer = createSmtpServer(mockEmailServer, options); // Verify instance was created correctly expect(smtpServer).toBeTruthy(); // Test that the listen method exists and is callable expect(typeof smtpServer.listen === 'function').toBeTruthy(); // Test that the close method exists expect(typeof smtpServer.close === 'function').toBeTruthy(); }); tap.test('verify SMTP server listen method - skipping test that accesses private properties', async (tools) => { tools.skip('Skipping test that accesses private properties'); // Mock email server const mockEmailServer = { processEmailByMode: async () => new Email({ from: 'test@example.com', to: 'recipient@example.com', subject: 'Test Email', text: 'This is a test email' }) } as any; // Create test configuration without certificates (will use self-signed) const options: ISmtpServerOptions = { port: 2526, // Use a different port for this test hostname: 'test.example.com', connectionTimeout: 5000 // Short timeout for tests }; // Create SMTP server instance const smtpServer = createSmtpServer(mockEmailServer, options); // Test that server was created expect(smtpServer).toBeTruthy(); expect(smtpServer).toHaveProperty('server'); // Mock server methods to avoid actual networking let listenCalled = false; let closeCalled = false; if (smtpServer.server) { const originalListen = smtpServer.server.listen; const originalClose = smtpServer.server.close; smtpServer.server.listen = function(port, callback) { listenCalled = true; if (callback) callback(); return this; }; smtpServer.server.close = function(callback) { closeCalled = true; if (callback) callback(null); return this; }; try { // Test listen method await smtpServer.listen(); expect(listenCalled).toBeTruthy(); // Test close method await smtpServer.close(); expect(closeCalled).toBeTruthy(); } finally { // Restore original methods smtpServer.server.listen = originalListen; smtpServer.server.close = originalClose; } } }); tap.test('verify SMTP server error handling - skipping test that accesses private properties', async (tools) => { tools.skip('Skipping test that accesses private properties'); // Mock email server const mockEmailServer = { processEmailByMode: async () => new Email({ from: 'test@example.com', to: 'recipient@example.com', subject: 'Test Email', text: 'This is a test email' }) } as any; // Create test configuration without certificates const options: ISmtpServerOptions = { port: 2527, // Use port that should work hostname: 'test.example.com' }; // Create SMTP server instance const smtpServer = createSmtpServer(mockEmailServer, options); // Test error handling by mocking the server's error event if (smtpServer.server) { const originalListen = smtpServer.server.listen; const originalOn = smtpServer.server.on; const originalOnce = smtpServer.server.once; let errorCallback: (err: Error) => void; let listeningCallback: () => void; smtpServer.server.listen = function(port, callback) { // Simulate error after a delay setTimeout(() => { if (errorCallback) { errorCallback(new Error('EACCES: Permission denied')); } }, 10); return this; }; smtpServer.server.on = function(event: string, callback: any) { if (event === 'error') { errorCallback = callback; } return originalOn.call(this, event, callback); }; smtpServer.server.once = function(event: string, callback: any) { if (event === 'listening') { listeningCallback = callback; } return originalOnce.call(this, event, callback); }; try { // This should fail with an error await smtpServer.listen().catch(error => { // Expect an error expect(error).toBeTruthy(); expect(error.message).toContain('EACCES'); }); } finally { // Restore original methods smtpServer.server.listen = originalListen; smtpServer.server.on = originalOn as any; smtpServer.server.once = originalOnce as any; } } }); tap.test('stop', async () => { await tap.stopForcefully(); }); export default tap.start();