181 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			181 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| /**
 | |
|  * SMTP Server Constants
 | |
|  * This file contains all constants and enums used by the SMTP server
 | |
|  */
 | |
| 
 | |
| import { SmtpState } from '../interfaces.ts';
 | |
| 
 | |
| // Re-export SmtpState enum from the main interfaces file
 | |
| export { SmtpState };
 | |
| 
 | |
| /**
 | |
|  * SMTP Response Codes
 | |
|  * Based on RFC 5321 and common SMTP practice
 | |
|  */
 | |
| export enum SmtpResponseCode {
 | |
|   // Success codes (2xx)
 | |
|   SUCCESS = 250,                    // Requested mail action okay, completed
 | |
|   SYSTEM_STATUS = 211,              // System status, or system help reply
 | |
|   HELP_MESSAGE = 214,               // Help message
 | |
|   SERVICE_READY = 220,              // <domain> Service ready
 | |
|   SERVICE_CLOSING = 221,            // <domain> Service closing transmission channel
 | |
|   AUTHENTICATION_SUCCESSFUL = 235,  // Authentication successful
 | |
|   OK = 250,                         // Requested mail action okay, completed
 | |
|   FORWARD = 251,                    // User not local; will forward to <forward-path>
 | |
|   CANNOT_VRFY = 252,                // Cannot VRFY user, but will accept message and attempt delivery
 | |
|   
 | |
|   // Intermediate codes (3xx)
 | |
|   MORE_INFO_NEEDED = 334,           // Server challenge for authentication
 | |
|   START_MAIL_INPUT = 354,           // Start mail input; end with <CRLF>.<CRLF>
 | |
|   
 | |
|   // Temporary error codes (4xx)
 | |
|   SERVICE_NOT_AVAILABLE = 421,      // <domain> Service not available, closing transmission channel
 | |
|   MAILBOX_TEMPORARILY_UNAVAILABLE = 450, // Requested mail action not taken: mailbox unavailable
 | |
|   LOCAL_ERROR = 451,                // Requested action aborted: local error in processing
 | |
|   INSUFFICIENT_STORAGE = 452,       // Requested action not taken: insufficient system storage
 | |
|   TLS_UNAVAILABLE_TEMP = 454,       // TLS not available due to temporary reason
 | |
|   
 | |
|   // Permanent error codes (5xx)
 | |
|   SYNTAX_ERROR = 500,               // Syntax error, command unrecognized
 | |
|   SYNTAX_ERROR_PARAMETERS = 501,    // Syntax error in parameters or arguments
 | |
|   COMMAND_NOT_IMPLEMENTED = 502,    // Command not implemented
 | |
|   BAD_SEQUENCE = 503,               // Bad sequence of commands
 | |
|   COMMAND_PARAMETER_NOT_IMPLEMENTED = 504, // Command parameter not implemented
 | |
|   AUTH_REQUIRED = 530,              // Authentication required
 | |
|   AUTH_FAILED = 535,                // Authentication credentials invalid
 | |
|   MAILBOX_UNAVAILABLE = 550,        // Requested action not taken: mailbox unavailable
 | |
|   USER_NOT_LOCAL = 551,             // User not local; please try <forward-path>
 | |
|   EXCEEDED_STORAGE = 552,           // Requested mail action aborted: exceeded storage allocation
 | |
|   MAILBOX_NAME_INVALID = 553,       // Requested action not taken: mailbox name not allowed
 | |
|   TRANSACTION_FAILED = 554,         // Transaction failed
 | |
|   MAIL_RCPT_PARAMETERS_INVALID = 555, // MAIL FROM/RCPT TO parameters not recognized or not implemented
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * SMTP Command Types
 | |
|  */
 | |
| export enum SmtpCommand {
 | |
|   HELO = 'HELO',
 | |
|   EHLO = 'EHLO',
 | |
|   MAIL_FROM = 'MAIL',
 | |
|   RCPT_TO = 'RCPT',
 | |
|   DATA = 'DATA',
 | |
|   RSET = 'RSET',
 | |
|   NOOP = 'NOOP',
 | |
|   QUIT = 'QUIT',
 | |
|   STARTTLS = 'STARTTLS',
 | |
|   AUTH = 'AUTH',
 | |
|   HELP = 'HELP',
 | |
|   VRFY = 'VRFY',
 | |
|   EXPN = 'EXPN',
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Security log event types
 | |
|  */
 | |
| export enum SecurityEventType {
 | |
|   CONNECTION = 'connection',
 | |
|   AUTHENTICATION = 'authentication',
 | |
|   COMMAND = 'command',
 | |
|   DATA = 'data',
 | |
|   IP_REPUTATION = 'ip_reputation',
 | |
|   TLS_NEGOTIATION = 'tls_negotiation',
 | |
|   DKIM = 'dkim',
 | |
|   SPF = 'spf',
 | |
|   DMARC = 'dmarc',
 | |
|   EMAIL_VALIDATION = 'email_validation',
 | |
|   SPAM = 'spam',
 | |
|   ACCESS_CONTROL = 'access_control',
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Security log levels
 | |
|  */
 | |
| export enum SecurityLogLevel {
 | |
|   DEBUG = 'debug',
 | |
|   INFO = 'info',
 | |
|   WARN = 'warn',
 | |
|   ERROR = 'error',
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * SMTP Server Defaults
 | |
|  */
 | |
| export const SMTP_DEFAULTS = {
 | |
|   // Default timeouts in milliseconds
 | |
|   CONNECTION_TIMEOUT: 30000,       // 30 seconds
 | |
|   SOCKET_TIMEOUT: 300000,          // 5 minutes
 | |
|   DATA_TIMEOUT: 60000,             // 1 minute
 | |
|   CLEANUP_INTERVAL: 5000,          // 5 seconds
 | |
|   
 | |
|   // Default limits
 | |
|   MAX_CONNECTIONS: 100,
 | |
|   MAX_RECIPIENTS: 100,
 | |
|   MAX_MESSAGE_SIZE: 10485760,      // 10MB
 | |
|   
 | |
|   // Default ports
 | |
|   SMTP_PORT: 25,
 | |
|   SUBMISSION_PORT: 587,
 | |
|   SECURE_PORT: 465,
 | |
|   
 | |
|   // Default hostname
 | |
|   HOSTNAME: 'mail.lossless.one',
 | |
|   
 | |
|   // CRLF line ending required by SMTP protocol
 | |
|   CRLF: '\r\n',
 | |
| };
 | |
| 
 | |
| /**
 | |
|  * SMTP Command Patterns
 | |
|  * Regular expressions for parsing SMTP commands
 | |
|  */
 | |
| export const SMTP_PATTERNS = {
 | |
|   // Match EHLO/HELO command: "EHLO example.com"
 | |
|   // Made very permissive to handle various client implementations
 | |
|   EHLO: /^(?:EHLO|HELO)\s+(.+)$/i,
 | |
|   
 | |
|   // Match MAIL FROM command: "MAIL FROM:<user@example.com> [PARAM=VALUE]"
 | |
|   // Made more permissive with whitespace and parameter formats
 | |
|   MAIL_FROM: /^MAIL\s+FROM\s*:\s*<([^>]*)>((?:\s+[a-zA-Z0-9][a-zA-Z0-9\-]*(?:=[^\s]+)?)*)$/i,
 | |
|   
 | |
|   // Match RCPT TO command: "RCPT TO:<user@example.com> [PARAM=VALUE]"
 | |
|   // Made more permissive with whitespace and parameter formats
 | |
|   RCPT_TO: /^RCPT\s+TO\s*:\s*<([^>]*)>((?:\s+[a-zA-Z0-9][a-zA-Z0-9\-]*(?:=[^\s]+)?)*)$/i,
 | |
|   
 | |
|   // Match parameter format: "PARAM=VALUE"
 | |
|   PARAM: /\s+([A-Za-z0-9][A-Za-z0-9\-]*)(?:=([^\s]+))?/g,
 | |
|   
 | |
|   // 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)$/,
 | |
| };
 | |
| 
 | |
| /**
 | |
|  * SMTP Extension List
 | |
|  * These extensions are advertised in the EHLO response
 | |
|  */
 | |
| export const SMTP_EXTENSIONS = {
 | |
|   // Basic extensions (RFC 1869)
 | |
|   PIPELINING: 'PIPELINING',
 | |
|   SIZE: 'SIZE',
 | |
|   EIGHTBITMIME: '8BITMIME',
 | |
|   
 | |
|   // Security extensions
 | |
|   STARTTLS: 'STARTTLS',
 | |
|   AUTH: 'AUTH',
 | |
|   
 | |
|   // Additional extensions
 | |
|   ENHANCEDSTATUSCODES: 'ENHANCEDSTATUSCODES',
 | |
|   HELP: 'HELP',
 | |
|   CHUNKING: 'CHUNKING',
 | |
|   DSN: 'DSN',
 | |
|   
 | |
|   // Format an extension with a parameter
 | |
|   formatExtension(name: string, parameter?: string | number): string {
 | |
|     return parameter !== undefined ? `${name} ${parameter}` : name;
 | |
|   }
 | |
| }; |