feat: Implement Deno-native STARTTLS handler and connection wrapper

- Refactored STARTTLS implementation to use Deno's native TLS via Deno.startTls().
- Introduced ConnectionWrapper to provide a Node.js net.Socket-compatible interface for Deno.Conn and Deno.TlsConn.
- Updated TlsHandler to utilize the new STARTTLS implementation.
- Added comprehensive SMTP authentication tests for PLAIN and LOGIN mechanisms.
- Implemented rate limiting tests for SMTP server connections and commands.
- Enhanced error handling and logging throughout the STARTTLS and connection upgrade processes.
This commit is contained in:
2025-10-28 18:51:33 +00:00
parent 9cd15342e0
commit 6523c55516
14 changed files with 1328 additions and 429 deletions

View File

@@ -112,7 +112,24 @@ export class CommandHandler implements ICommandHandler {
}
return;
}
// RFC 5321 Section 4.5.3.1.4: Command lines must not exceed 512 octets
// (including CRLF, but we already stripped it)
if (commandLine.length > 510) {
SmtpLogger.debug(`Command line too long: ${commandLine.length} bytes`, {
sessionId: session.id,
remoteAddress: session.remoteAddress
});
// Record error for rate limiting
const emailServer = this.smtpServer.getEmailServer();
const rateLimiter = emailServer.getRateLimiter();
rateLimiter.recordError(session.remoteAddress);
this.sendResponse(socket, `${SmtpResponseCode.SYNTAX_ERROR_PARAMETERS} Command line too long`);
return;
}
// Handle command pipelining (RFC 2920)
// Multiple commands can be sent in a single TCP packet
if (commandLine.includes('\r\n') || commandLine.includes('\n')) {
@@ -849,8 +866,9 @@ export class CommandHandler implements ICommandHandler {
return;
}
// Check if TLS is required for authentication
if (!session.useTLS) {
// Check if TLS is required for authentication (default: true)
const requireTLS = this.smtpServer.getOptions().auth.requireTLS !== false;
if (requireTLS && !session.useTLS) {
this.sendResponse(socket, `${SmtpResponseCode.AUTH_FAILED} Authentication requires TLS`);
return;
}