253 lines
6.8 KiB
TypeScript
253 lines
6.8 KiB
TypeScript
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<any>,
|
|
options?: IMailSendRequest['options']
|
|
) => Promise<IMailSendResponse>;
|
|
|
|
/** Handler for mailbox list requests */
|
|
onMailboxList?: (
|
|
mailbox: string,
|
|
options?: { limit?: number; offset?: number }
|
|
) => Promise<IMailboxListResponse>;
|
|
|
|
/** Handler for mail fetch requests */
|
|
onMailFetch?: (mailbox: string, emailId: string) => Promise<IMailFetchResponse>;
|
|
|
|
/** Handler for mail status requests */
|
|
onMailStatus?: (deliveryId: string) => Promise<IMailStatusResponse>;
|
|
|
|
/** Handler for settings update requests */
|
|
onSettingsUpdate?: (settings: IWireSettings) => Promise<ISettingsUpdateResponse>;
|
|
}
|
|
|
|
/**
|
|
* 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<IWireMessage> {
|
|
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<string> {
|
|
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<IMailSendResponse> {
|
|
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<IMailboxListResponse> {
|
|
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<IMailFetchResponse> {
|
|
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<IMailStatusResponse> {
|
|
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<ISettingsUpdateResponse> {
|
|
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(),
|
|
};
|
|
}
|
|
}
|