This commit is contained in:
2025-05-23 19:03:44 +00:00
parent 7d28d23bbd
commit 1b141ec8f3
101 changed files with 30736 additions and 374 deletions

View File

@ -52,49 +52,53 @@ tap.test('verify SMTP server listen method', async () => {
})
} as any;
// Create test configuration with a different port
// 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',
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/YAu3dqdIjCwnatEA9H8ap0k+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-----',
connectionTimeout: 5000 // Short timeout for tests
};
// Create SMTP server instance
const smtpServer = createSmtpServer(mockEmailServer, options);
// Mock net.Server.listen and net.Server.close to avoid actual networking
const originalListen = smtpServer.server.listen;
const originalClose = smtpServer.server.close;
// Test that server was created
expect(smtpServer).toBeTruthy();
expect(smtpServer).toHaveProperty('server');
smtpServer.server.listen = function(port, callback) {
// Call the original without actually binding
if (callback) callback();
return this;
};
// Mock server methods to avoid actual networking
let listenCalled = false;
let closeCalled = false;
smtpServer.server.close = function(callback) {
if (callback) callback(null);
return this;
};
try {
// Test listen method
await smtpServer.listen();
if (smtpServer.server) {
const originalListen = smtpServer.server.listen;
const originalClose = smtpServer.server.close;
// Should get here without error
expect(true).toBeTruthy();
smtpServer.server.listen = function(port, callback) {
listenCalled = true;
if (callback) callback();
return this;
};
// Test close method
await smtpServer.close();
smtpServer.server.close = function(callback) {
closeCalled = true;
if (callback) callback(null);
return this;
};
// Should get here without error
expect(true).toBeTruthy();
} finally {
// Restore original methods
smtpServer.server.listen = originalListen;
smtpServer.server.close = originalClose;
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;
}
}
});
@ -109,55 +113,61 @@ tap.test('verify SMTP server error handling', async () => {
})
} as any;
// Create test configuration with an invalid port
// Create test configuration without certificates
const options: ISmtpServerOptions = {
port: 0, // Invalid port
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/YAu3dqdIjCwnatEA9H8ap0k+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-----'
port: 2527, // Use port that should work
hostname: 'test.example.com'
};
// Create SMTP server instance
const smtpServer = createSmtpServer(mockEmailServer, options);
// Mock server.listen to simulate an error
const originalListen = smtpServer.server.listen;
const originalOn = smtpServer.server.on;
let errorCallback: (err: Error) => void;
smtpServer.server.listen = function(port, callback) {
// Don't call the callback - instead trigger the error event
setTimeout(() => {
if (errorCallback) {
errorCallback(new Error('EACCES: Permission denied'));
// 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;
}
}, 10);
return this;
};
smtpServer.server.on = function(event: string, callback: any) {
if (event === 'error') {
errorCallback = callback;
}
return this;
};
try {
// This should fail with an error
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 {
await smtpServer.listen();
// Should not reach here
expect(false).toBeTruthy();
} catch (error) {
// Expect an error
expect(error).toBeTruthy();
expect(error.message.includes('EACCES')).toBeTruthy();
// 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;
}
} finally {
// Restore original methods
smtpServer.server.listen = originalListen;
smtpServer.server.on = originalOn as any;
}
});