This commit is contained in:
Philipp Kunz 2025-05-23 08:17:34 +00:00
parent 7344bf0f70
commit 53f5e30b23
3 changed files with 45 additions and 11 deletions

View File

@ -210,7 +210,7 @@ export class CommandHandler implements ICommandHandler {
break;
case SmtpCommand.QUIT:
this.handleQuit(socket);
this.handleQuit(socket, args);
break;
case SmtpCommand.STARTTLS:
@ -734,7 +734,13 @@ export class CommandHandler implements ICommandHandler {
* Handle QUIT command
* @param socket - Client socket
*/
public handleQuit(socket: plugins.net.Socket | plugins.tls.TLSSocket): void {
public handleQuit(socket: plugins.net.Socket | plugins.tls.TLSSocket, args?: string): void {
// QUIT command should not have any parameters
if (args && args.trim().length > 0) {
this.sendResponse(socket, `${SmtpResponseCode.SYNTAX_ERROR_PARAMETERS} Syntax error in parameters`);
return;
}
// Get the session for this socket
const session = this.smtpServer.getSessionManager().getSession(socket);

View File

@ -145,10 +145,10 @@ export const SMTP_PATTERNS = {
// Match parameter format: "PARAM=VALUE"
PARAM: /\s+([A-Za-z0-9][A-Za-z0-9\-]*)(?:=([^\s]+))?/g,
// Match email address format - made much more permissive
// This only does very basic format validation to avoid rejecting valid addresses
// According to RFC 5321, we should accept a wide variety of sender formats
EMAIL: /^[^\s@]+(@[^\s@]+\.[^\s@]+)?$/,
// Match email address format - basic validation
// This pattern rejects common invalid formats while being permissive for edge cases
// Checks: no spaces, has @, has domain with dot, no double dots, proper domain format
EMAIL: /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
// Match end of DATA marker: \r\n.\r\n or just .\r\n at the start of a line (to handle various client implementations)
END_DATA: /(\r\n\.\r\n$)|(\n\.\r\n$)|(\r\n\.\n$)|(\n\.\n$)|^\.(\r\n|\n)$/,

View File

@ -100,7 +100,35 @@ export function isValidEmail(email: string): boolean {
return false;
}
return SMTP_PATTERNS.EMAIL.test(email);
// Basic pattern check
if (!SMTP_PATTERNS.EMAIL.test(email)) {
return false;
}
// Additional validation for common invalid patterns
const [localPart, domain] = email.split('@');
// Check for double dots
if (email.includes('..')) {
return false;
}
// Check domain doesn't start or end with dot
if (domain && (domain.startsWith('.') || domain.endsWith('.'))) {
return false;
}
// Check local part length (max 64 chars per RFC)
if (localPart && localPart.length > 64) {
return false;
}
// Check domain length (max 253 chars per RFC - accounting for trailing dot)
if (domain && domain.length > 253) {
return false;
}
return true;
}
/**
@ -160,7 +188,7 @@ export function validateMailFrom(args: string): {
// During testing, we should validate the email format
// Check for basic email format (something@somewhere)
if (!SMTP_PATTERNS.EMAIL.test(emailPart)) {
if (!isValidEmail(emailPart)) {
return { isValid: false, errorMessage: 'Invalid email address format' };
}
@ -185,7 +213,7 @@ export function validateMailFrom(args: string): {
// Tests expect us to reject formats without angle brackets
// For better compliance with tests, check if the argument might contain an email without brackets
if (SMTP_PATTERNS.EMAIL.test(cleanArgs)) {
if (isValidEmail(cleanArgs)) {
return { isValid: false, errorMessage: 'Invalid syntax - angle brackets required' };
}
@ -236,7 +264,7 @@ export function validateRcptTo(args: string): {
// During testing, we should validate the email format
// Check for basic email format (something@somewhere)
if (!SMTP_PATTERNS.EMAIL.test(emailPart)) {
if (!isValidEmail(emailPart)) {
return { isValid: false, errorMessage: 'Invalid email address format' };
}
@ -261,7 +289,7 @@ export function validateRcptTo(args: string): {
// Tests expect us to reject formats without angle brackets
// For better compliance with tests, check if the argument might contain an email without brackets
if (SMTP_PATTERNS.EMAIL.test(cleanArgs)) {
if (isValidEmail(cleanArgs)) {
return { isValid: false, errorMessage: 'Invalid syntax - angle brackets required' };
}