This commit is contained in:
2025-05-21 00:12:49 +00:00
parent 5c85188183
commit b1890f59ee
27 changed files with 2096 additions and 705 deletions

View File

@ -12,6 +12,17 @@ import { UnifiedDeliveryQueue, type IQueueItem } from './classes.delivery.queue.
import type { Email } from '../core/classes.email.js';
import type { IDomainRule } from '../routing/classes.email.config.js';
/**
* Delivery status enumeration
*/
export enum DeliveryStatus {
PENDING = 'pending',
DELIVERING = 'delivering',
DELIVERED = 'delivered',
DEFERRED = 'deferred',
FAILED = 'failed'
}
/**
* Delivery handler interface
*/
@ -44,6 +55,12 @@ export interface IMultiModeDeliveryOptions {
globalRateLimit?: number;
perPatternRateLimit?: Record<string, number>;
// Bounce handling
processBounces?: boolean;
bounceHandler?: {
processSmtpFailure: (recipient: string, smtpResponse: string, options: any) => Promise<any>;
};
// Event hooks
onDeliveryStart?: (item: IQueueItem) => Promise<void>;
onDeliverySuccess?: (item: IQueueItem, result: any) => Promise<void>;
@ -122,6 +139,8 @@ export class MultiModeDeliverySystem extends EventEmitter {
},
globalRateLimit: options.globalRateLimit || 100, // 100 emails per minute
perPatternRateLimit: options.perPatternRateLimit || {},
processBounces: options.processBounces !== false, // Default to true
bounceHandler: options.bounceHandler || null,
onDeliveryStart: options.onDeliveryStart || (async () => {}),
onDeliverySuccess: options.onDeliverySuccess || (async () => {}),
onDeliveryFailed: options.onDeliveryFailed || (async () => {})
@ -345,6 +364,36 @@ export class MultiModeDeliverySystem extends EventEmitter {
// Call delivery failed hook
await this.options.onDeliveryFailed(item, error.message);
// Process as bounce if enabled and we have a bounce handler
if (this.options.processBounces && this.options.bounceHandler) {
try {
const email = item.processingResult as Email;
// Extract recipient and error message
// For multiple recipients, we'd need more sophisticated parsing
const recipient = email.to.length > 0 ? email.to[0] : '';
if (recipient) {
logger.log('info', `Processing delivery failure as bounce for recipient ${recipient}`);
// Process SMTP failure through bounce handler
await this.options.bounceHandler.processSmtpFailure(
recipient,
error.message,
{
sender: email.from,
originalEmailId: item.id,
headers: email.headers
}
);
logger.log('info', `Bounce record created for failed delivery to ${recipient}`);
}
} catch (bounceError) {
logger.log('error', `Failed to process bounce: ${bounceError.message}`);
}
}
// Emit delivery failed event
this.emit('deliveryFailed', item, error);
logger.log('error', `Item ${item.id} delivery failed: ${error.message}`);