import { Smartmail } from './smartmail.classes.smartmail.js'; import { type IWireMessage, type IMailSendRequest, type IMailSendResponse, type IMailboxListRequest, type IMailboxListResponse, type IMailFetchRequest, type IMailFetchResponse, type IMailStatusRequest, type IMailStatusResponse, type ISettingsUpdateRequest, type ISettingsUpdateResponse, type IWireSettings, type TWireMessage, createMessageId, createTimestamp, } from './smartmail.wire.js'; /** * Handler functions for different wire message types */ export interface IWireHandlers { /** Handler for mail send requests */ onMailSend?: ( email: Smartmail, options?: IMailSendRequest['options'] ) => Promise; /** Handler for mailbox list requests */ onMailboxList?: ( mailbox: string, options?: { limit?: number; offset?: number } ) => Promise; /** Handler for mail fetch requests */ onMailFetch?: (mailbox: string, emailId: string) => Promise; /** Handler for mail status requests */ onMailStatus?: (deliveryId: string) => Promise; /** Handler for settings update requests */ onSettingsUpdate?: (settings: IWireSettings) => Promise; } /** * WireParser is used by the SMTP service to parse and handle incoming wire messages. * It provides a handler-based approach for processing different message types. */ export class WireParser { private handlers: IWireHandlers; constructor(handlers: IWireHandlers = {}) { this.handlers = handlers; } /** * Parse a wire message from JSON string * @param json The JSON string to parse * @returns Parsed wire message */ public parse(json: string): TWireMessage { return JSON.parse(json) as TWireMessage; } /** * Handle an incoming wire message and return the response * @param message The wire message to handle * @returns Promise resolving to the response message */ public async handle(message: TWireMessage): Promise { switch (message.type) { case 'mail.send': return this.handleMailSend(message); case 'mailbox.list': return this.handleMailboxList(message); case 'mail.fetch': return this.handleMailFetch(message); case 'mail.status': return this.handleMailStatus(message); case 'settings.update': return this.handleSettingsUpdate(message); default: return this.createErrorResponse(message, 'Unknown message type'); } } /** * Parse and handle in one step (convenience method) * @param json The JSON string to parse and handle * @returns Promise resolving to JSON response string */ public async parseAndHandle(json: string): Promise { const message = this.parse(json); const response = await this.handle(message); return JSON.stringify(response); } /** * Handle mail send request */ private async handleMailSend(message: IMailSendRequest): Promise { if (!this.handlers.onMailSend) { return { type: 'mail.send.response', messageId: message.messageId, timestamp: createTimestamp(), success: false, error: 'Mail send not supported', }; } try { const email = Smartmail.fromObject(message.email); return await this.handlers.onMailSend(email, message.options); } catch (error) { return { type: 'mail.send.response', messageId: message.messageId, timestamp: createTimestamp(), success: false, error: error instanceof Error ? error.message : 'Unknown error', }; } } /** * Handle mailbox list request */ private async handleMailboxList(message: IMailboxListRequest): Promise { if (!this.handlers.onMailboxList) { return { type: 'mailbox.list.response', messageId: message.messageId, timestamp: createTimestamp(), mailbox: message.mailbox, emails: [], total: 0, }; } try { return await this.handlers.onMailboxList(message.mailbox, { limit: message.limit, offset: message.offset, }); } catch (error) { return { type: 'mailbox.list.response', messageId: message.messageId, timestamp: createTimestamp(), mailbox: message.mailbox, emails: [], total: 0, }; } } /** * Handle mail fetch request */ private async handleMailFetch(message: IMailFetchRequest): Promise { if (!this.handlers.onMailFetch) { return { type: 'mail.fetch.response', messageId: message.messageId, timestamp: createTimestamp(), email: null, }; } try { return await this.handlers.onMailFetch(message.mailbox, message.emailId); } catch (error) { return { type: 'mail.fetch.response', messageId: message.messageId, timestamp: createTimestamp(), email: null, }; } } /** * Handle mail status request */ private async handleMailStatus(message: IMailStatusRequest): Promise { if (!this.handlers.onMailStatus) { return { type: 'mail.status.response', messageId: message.messageId, timestamp: createTimestamp(), deliveryId: message.deliveryId, status: 'failed', error: 'Mail status not supported', }; } try { return await this.handlers.onMailStatus(message.deliveryId); } catch (error) { return { type: 'mail.status.response', messageId: message.messageId, timestamp: createTimestamp(), deliveryId: message.deliveryId, status: 'failed', error: error instanceof Error ? error.message : 'Unknown error', }; } } /** * Handle settings update request */ private async handleSettingsUpdate( message: ISettingsUpdateRequest ): Promise { if (!this.handlers.onSettingsUpdate) { return { type: 'settings.update.response', messageId: message.messageId, timestamp: createTimestamp(), success: false, error: 'Settings update not supported', }; } try { return await this.handlers.onSettingsUpdate(message.settings); } catch (error) { return { type: 'settings.update.response', messageId: message.messageId, timestamp: createTimestamp(), success: false, error: error instanceof Error ? error.message : 'Unknown error', }; } } /** * Creates an error response for unknown message types */ private createErrorResponse(message: IWireMessage, error: string): IWireMessage { return { type: `${message.type}.response`, messageId: message.messageId, timestamp: createTimestamp(), }; } }