feat(tests): Port CMD-06 RSET, SEC-06 IP Reputation, and ERR-01 Syntax Error tests
- Ported CMD-06 RSET Command tests with 8 passing tests covering transaction resets and recipient clearing. - Ported SEC-06 IP Reputation tests with 7 passing tests validating infrastructure and legitimate traffic acceptance. - Ported ERR-01 Syntax Error tests with 10 passing tests for handling invalid commands and syntax errors. - Updated README files to reflect the new test statuses and coverage. - Added detailed test cases for handling invalid sequences in ERR-02 tests.
This commit is contained in:
225
test/suite/smtpserver_commands/test.cmd-06.rset-command.test.ts
Normal file
225
test/suite/smtpserver_commands/test.cmd-06.rset-command.test.ts
Normal file
@@ -0,0 +1,225 @@
|
||||
/**
|
||||
* CMD-06: RSET Command Tests
|
||||
* Tests SMTP RSET command for transaction reset
|
||||
*/
|
||||
|
||||
import { assert, assertEquals, assertMatch } from '@std/assert';
|
||||
import { startTestServer, stopTestServer, type ITestServer } from '../../helpers/server.loader.ts';
|
||||
import {
|
||||
connectToSmtp,
|
||||
waitForGreeting,
|
||||
sendSmtpCommand,
|
||||
closeSmtpConnection,
|
||||
} from '../../helpers/utils.ts';
|
||||
|
||||
const TEST_PORT = 25259;
|
||||
let testServer: ITestServer;
|
||||
|
||||
Deno.test({
|
||||
name: 'CMD-06: Setup - Start SMTP server',
|
||||
async fn() {
|
||||
testServer = await startTestServer({ port: TEST_PORT });
|
||||
assert(testServer, 'Test server should be created');
|
||||
},
|
||||
sanitizeResources: false,
|
||||
sanitizeOps: false,
|
||||
});
|
||||
|
||||
Deno.test({
|
||||
name: 'CMD-06: RSET - resets transaction after MAIL FROM',
|
||||
async fn() {
|
||||
const conn = await connectToSmtp('localhost', TEST_PORT);
|
||||
|
||||
try {
|
||||
await waitForGreeting(conn);
|
||||
await sendSmtpCommand(conn, 'EHLO test.example.com', '250');
|
||||
await sendSmtpCommand(conn, 'MAIL FROM:<sender@example.com>', '250');
|
||||
|
||||
// Send RSET
|
||||
const rsetResponse = await sendSmtpCommand(conn, 'RSET', '250');
|
||||
assert(rsetResponse.includes('250'), 'RSET should respond with 250 OK');
|
||||
|
||||
// After RSET, should be able to send new MAIL FROM
|
||||
const mailFromResponse = await sendSmtpCommand(conn, 'MAIL FROM:<newsender@example.com>', '250');
|
||||
assert(mailFromResponse.includes('250'), 'Should accept MAIL FROM after RSET');
|
||||
|
||||
await sendSmtpCommand(conn, 'QUIT', '221');
|
||||
console.log('✓ RSET successfully resets transaction after MAIL FROM');
|
||||
} finally {
|
||||
try {
|
||||
conn.close();
|
||||
} catch {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
},
|
||||
sanitizeResources: false,
|
||||
sanitizeOps: false,
|
||||
});
|
||||
|
||||
Deno.test({
|
||||
name: 'CMD-06: RSET - resets transaction after RCPT TO',
|
||||
async fn() {
|
||||
const conn = await connectToSmtp('localhost', TEST_PORT);
|
||||
|
||||
try {
|
||||
await waitForGreeting(conn);
|
||||
await sendSmtpCommand(conn, 'EHLO test.example.com', '250');
|
||||
await sendSmtpCommand(conn, 'MAIL FROM:<sender@example.com>', '250');
|
||||
await sendSmtpCommand(conn, 'RCPT TO:<recipient@example.com>', '250');
|
||||
|
||||
// Send RSET
|
||||
const rsetResponse = await sendSmtpCommand(conn, 'RSET', '250');
|
||||
assert(rsetResponse.includes('250'), 'RSET should respond with 250 OK');
|
||||
|
||||
// After RSET, RCPT TO should fail (need MAIL FROM first)
|
||||
const rcptToResponse = await sendSmtpCommand(conn, 'RCPT TO:<newrecipient@example.com>');
|
||||
assertMatch(rcptToResponse, /^503/, 'Should reject RCPT TO without MAIL FROM after RSET');
|
||||
|
||||
await sendSmtpCommand(conn, 'QUIT', '221');
|
||||
console.log('✓ RSET clears transaction state requiring new MAIL FROM');
|
||||
} finally {
|
||||
try {
|
||||
conn.close();
|
||||
} catch {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
},
|
||||
sanitizeResources: false,
|
||||
sanitizeOps: false,
|
||||
});
|
||||
|
||||
Deno.test({
|
||||
name: 'CMD-06: RSET - handles multiple consecutive RSET commands',
|
||||
async fn() {
|
||||
const conn = await connectToSmtp('localhost', TEST_PORT);
|
||||
|
||||
try {
|
||||
await waitForGreeting(conn);
|
||||
await sendSmtpCommand(conn, 'EHLO test.example.com', '250');
|
||||
await sendSmtpCommand(conn, 'MAIL FROM:<sender@example.com>', '250');
|
||||
|
||||
// Send multiple RSETs
|
||||
const rset1 = await sendSmtpCommand(conn, 'RSET', '250');
|
||||
assert(rset1.includes('250'), 'First RSET should succeed');
|
||||
|
||||
const rset2 = await sendSmtpCommand(conn, 'RSET', '250');
|
||||
assert(rset2.includes('250'), 'Second RSET should succeed');
|
||||
|
||||
const rset3 = await sendSmtpCommand(conn, 'RSET', '250');
|
||||
assert(rset3.includes('250'), 'Third RSET should succeed');
|
||||
|
||||
await sendSmtpCommand(conn, 'QUIT', '221');
|
||||
console.log('✓ Multiple consecutive RSET commands work (idempotent)');
|
||||
} finally {
|
||||
try {
|
||||
conn.close();
|
||||
} catch {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
},
|
||||
sanitizeResources: false,
|
||||
sanitizeOps: false,
|
||||
});
|
||||
|
||||
Deno.test({
|
||||
name: 'CMD-06: RSET - works without active transaction',
|
||||
async fn() {
|
||||
const conn = await connectToSmtp('localhost', TEST_PORT);
|
||||
|
||||
try {
|
||||
await waitForGreeting(conn);
|
||||
await sendSmtpCommand(conn, 'EHLO test.example.com', '250');
|
||||
|
||||
// Send RSET without any transaction
|
||||
const rsetResponse = await sendSmtpCommand(conn, 'RSET', '250');
|
||||
assert(rsetResponse.includes('250'), 'RSET should work even without active transaction');
|
||||
|
||||
await sendSmtpCommand(conn, 'QUIT', '221');
|
||||
console.log('✓ RSET works without active transaction');
|
||||
} finally {
|
||||
try {
|
||||
conn.close();
|
||||
} catch {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
},
|
||||
sanitizeResources: false,
|
||||
sanitizeOps: false,
|
||||
});
|
||||
|
||||
Deno.test({
|
||||
name: 'CMD-06: RSET - clears all recipients',
|
||||
async fn() {
|
||||
const conn = await connectToSmtp('localhost', TEST_PORT);
|
||||
|
||||
try {
|
||||
await waitForGreeting(conn);
|
||||
await sendSmtpCommand(conn, 'EHLO test.example.com', '250');
|
||||
await sendSmtpCommand(conn, 'MAIL FROM:<sender@example.com>', '250');
|
||||
|
||||
// Add multiple recipients
|
||||
await sendSmtpCommand(conn, 'RCPT TO:<recipient1@example.com>', '250');
|
||||
await sendSmtpCommand(conn, 'RCPT TO:<recipient2@example.com>', '250');
|
||||
await sendSmtpCommand(conn, 'RCPT TO:<recipient3@example.com>', '250');
|
||||
|
||||
// Send RSET
|
||||
const rsetResponse = await sendSmtpCommand(conn, 'RSET', '250');
|
||||
assert(rsetResponse.includes('250'), 'RSET should respond with 250 OK');
|
||||
|
||||
// After RSET, DATA should fail (no recipients)
|
||||
const dataResponse = await sendSmtpCommand(conn, 'DATA');
|
||||
assertMatch(dataResponse, /^503/, 'DATA should fail without recipients after RSET');
|
||||
|
||||
await sendSmtpCommand(conn, 'QUIT', '221');
|
||||
console.log('✓ RSET clears all recipients from transaction');
|
||||
} finally {
|
||||
try {
|
||||
conn.close();
|
||||
} catch {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
},
|
||||
sanitizeResources: false,
|
||||
sanitizeOps: false,
|
||||
});
|
||||
|
||||
Deno.test({
|
||||
name: 'CMD-06: RSET - ignores parameters',
|
||||
async fn() {
|
||||
const conn = await connectToSmtp('localhost', TEST_PORT);
|
||||
|
||||
try {
|
||||
await waitForGreeting(conn);
|
||||
await sendSmtpCommand(conn, 'EHLO test.example.com', '250');
|
||||
|
||||
// Send RSET with parameters (should be ignored)
|
||||
const rsetResponse = await sendSmtpCommand(conn, 'RSET ignored parameter', '250');
|
||||
assert(rsetResponse.includes('250'), 'RSET should ignore parameters and respond with 250 OK');
|
||||
|
||||
await sendSmtpCommand(conn, 'QUIT', '221');
|
||||
console.log('✓ RSET ignores parameters as per RFC');
|
||||
} finally {
|
||||
try {
|
||||
conn.close();
|
||||
} catch {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
},
|
||||
sanitizeResources: false,
|
||||
sanitizeOps: false,
|
||||
});
|
||||
|
||||
Deno.test({
|
||||
name: 'CMD-06: Cleanup - Stop SMTP server',
|
||||
async fn() {
|
||||
await stopTestServer(testServer);
|
||||
},
|
||||
sanitizeResources: false,
|
||||
sanitizeOps: false,
|
||||
});
|
||||
Reference in New Issue
Block a user