import * as plugins from '../../plugins.js'; import { EventEmitter } from 'node:events'; import * as net from 'node:net'; import * as tls from 'node:tls'; import { logger } from '../../logger.js'; import { SecurityLogger, SecurityLogLevel, SecurityEventType } from '../../security/index.js'; import { UnifiedDeliveryQueue } from './classes.delivery.queue.js'; /** * Delivery status enumeration */ export var DeliveryStatus; (function (DeliveryStatus) { DeliveryStatus["PENDING"] = "pending"; DeliveryStatus["DELIVERING"] = "delivering"; DeliveryStatus["DELIVERED"] = "delivered"; DeliveryStatus["DEFERRED"] = "deferred"; DeliveryStatus["FAILED"] = "failed"; })(DeliveryStatus || (DeliveryStatus = {})); /** * Handles delivery for all email processing modes */ export class MultiModeDeliverySystem extends EventEmitter { queue; options; stats; deliveryTimes = []; activeDeliveries = new Set(); running = false; throttled = false; rateLimitLastCheck = Date.now(); rateLimitCounter = 0; emailServer; /** * Create a new multi-mode delivery system * @param queue Unified delivery queue * @param options Delivery options * @param emailServer Optional reference to unified email server for SmtpClient access */ constructor(queue, options, emailServer) { super(); this.queue = queue; this.emailServer = emailServer; // Set default options this.options = { connectionPoolSize: options.connectionPoolSize || 10, socketTimeout: options.socketTimeout || 30000, // 30 seconds concurrentDeliveries: options.concurrentDeliveries || 10, sendTimeout: options.sendTimeout || 60000, // 1 minute verifyCertificates: options.verifyCertificates !== false, // Default to true tlsMinVersion: options.tlsMinVersion || 'TLSv1.2', forwardHandler: options.forwardHandler || { deliver: this.handleForwardDelivery.bind(this) }, deliveryHandler: options.deliveryHandler || { deliver: this.handleMtaDelivery.bind(this) }, processHandler: options.processHandler || { deliver: this.handleProcessDelivery.bind(this) }, 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 () => { }) }; // Initialize statistics this.stats = { activeDeliveries: 0, totalSuccessful: 0, totalFailed: 0, avgDeliveryTime: 0, byMode: { forward: { successful: 0, failed: 0 }, mta: { successful: 0, failed: 0 }, process: { successful: 0, failed: 0 } }, rateLimiting: { currentRate: 0, globalLimit: this.options.globalRateLimit, throttled: 0 } }; // Set up event listeners this.queue.on('itemsReady', this.processItems.bind(this)); } /** * Start the delivery system */ async start() { logger.log('info', 'Starting MultiModeDeliverySystem'); if (this.running) { logger.log('warn', 'MultiModeDeliverySystem is already running'); return; } this.running = true; // Emit started event this.emit('started'); logger.log('info', 'MultiModeDeliverySystem started successfully'); } /** * Stop the delivery system */ async stop() { logger.log('info', 'Stopping MultiModeDeliverySystem'); if (!this.running) { logger.log('warn', 'MultiModeDeliverySystem is already stopped'); return; } this.running = false; // Wait for active deliveries to complete if (this.activeDeliveries.size > 0) { logger.log('info', `Waiting for ${this.activeDeliveries.size} active deliveries to complete`); // Wait for a maximum of 30 seconds await new Promise(resolve => { const checkInterval = setInterval(() => { if (this.activeDeliveries.size === 0) { clearInterval(checkInterval); clearTimeout(forceTimeout); resolve(); } }, 1000); // Force resolve after 30 seconds const forceTimeout = setTimeout(() => { clearInterval(checkInterval); resolve(); }, 30000); }); } // Emit stopped event this.emit('stopped'); logger.log('info', 'MultiModeDeliverySystem stopped successfully'); } /** * Process ready items from the queue * @param items Queue items ready for processing */ async processItems(items) { if (!this.running) { return; } // Check if we're already at max concurrent deliveries if (this.activeDeliveries.size >= this.options.concurrentDeliveries) { logger.log('debug', `Already at max concurrent deliveries (${this.activeDeliveries.size})`); return; } // Check rate limiting if (this.checkRateLimit()) { logger.log('debug', 'Rate limit exceeded, throttling deliveries'); return; } // Calculate how many more deliveries we can start const availableSlots = this.options.concurrentDeliveries - this.activeDeliveries.size; const itemsToProcess = items.slice(0, availableSlots); if (itemsToProcess.length === 0) { return; } logger.log('info', `Processing ${itemsToProcess.length} items for delivery`); // Process each item for (const item of itemsToProcess) { // Mark as processing await this.queue.markProcessing(item.id); // Add to active deliveries this.activeDeliveries.add(item.id); this.stats.activeDeliveries = this.activeDeliveries.size; // Deliver asynchronously this.deliverItem(item).catch(err => { logger.log('error', `Unhandled error in delivery: ${err.message}`); }); } // Update statistics this.emit('statsUpdated', this.stats); } /** * Deliver an item from the queue * @param item Queue item to deliver */ async deliverItem(item) { const startTime = Date.now(); try { // Call delivery start hook await this.options.onDeliveryStart(item); // Emit delivery start event this.emit('deliveryStart', item); logger.log('info', `Starting delivery of item ${item.id}, mode: ${item.processingMode}`); // Choose the appropriate handler based on mode let result; switch (item.processingMode) { case 'forward': result = await this.options.forwardHandler.deliver(item); break; case 'mta': result = await this.options.deliveryHandler.deliver(item); break; case 'process': result = await this.options.processHandler.deliver(item); break; default: throw new Error(`Unknown processing mode: ${item.processingMode}`); } // Mark as delivered await this.queue.markDelivered(item.id); // Update statistics this.stats.totalSuccessful++; this.stats.byMode[item.processingMode].successful++; // Calculate delivery time const deliveryTime = Date.now() - startTime; this.deliveryTimes.push(deliveryTime); this.updateDeliveryTimeStats(); // Call delivery success hook await this.options.onDeliverySuccess(item, result); // Emit delivery success event this.emit('deliverySuccess', item, result); logger.log('info', `Item ${item.id} delivered successfully in ${deliveryTime}ms`); SecurityLogger.getInstance().logEvent({ level: SecurityLogLevel.INFO, type: SecurityEventType.EMAIL_DELIVERY, message: 'Email delivery successful', details: { itemId: item.id, mode: item.processingMode, routeName: item.route?.name || 'unknown', deliveryTime }, success: true }); } catch (error) { // Calculate delivery attempt time even for failures const deliveryTime = Date.now() - startTime; // Mark as failed await this.queue.markFailed(item.id, error.message); // Update statistics this.stats.totalFailed++; this.stats.byMode[item.processingMode].failed++; // 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; // 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}`); SecurityLogger.getInstance().logEvent({ level: SecurityLogLevel.ERROR, type: SecurityEventType.EMAIL_DELIVERY, message: 'Email delivery failed', details: { itemId: item.id, mode: item.processingMode, routeName: item.route?.name || 'unknown', error: error.message, deliveryTime }, success: false }); } finally { // Remove from active deliveries this.activeDeliveries.delete(item.id); this.stats.activeDeliveries = this.activeDeliveries.size; // Update statistics this.emit('statsUpdated', this.stats); } } /** * Default handler for forward mode delivery * @param item Queue item */ async handleForwardDelivery(item) { logger.log('info', `Forward delivery for item ${item.id}`); const email = item.processingResult; const route = item.route; // Get target server information const targetServer = route?.action.forward?.host; const targetPort = route?.action.forward?.port || 25; const useTls = false; // TLS configuration can be enhanced later if (!targetServer) { throw new Error('No target server configured for forward mode'); } logger.log('info', `Forwarding email to ${targetServer}:${targetPort}, TLS: ${useTls}`); try { // Get SMTP client from email server if available if (!this.emailServer) { // Fall back to raw socket implementation if no email server logger.log('warn', 'No email server available, falling back to raw socket implementation'); return this.handleForwardDeliveryLegacy(item); } // Get SMTP client from UnifiedEmailServer const smtpClient = this.emailServer.getSmtpClient(targetServer, targetPort); // Apply DKIM signing if configured in the route if (item.route?.action.options?.mtaOptions?.dkimSign) { await this.applyDkimSigning(email, item.route.action.options.mtaOptions); } // Send the email using SmtpClient const result = await smtpClient.sendMail(email); if (result.success) { logger.log('info', `Email forwarded successfully to ${targetServer}:${targetPort}`); return { targetServer: targetServer, targetPort: targetPort, recipients: result.acceptedRecipients.length, messageId: result.messageId, rejectedRecipients: result.rejectedRecipients }; } else { throw new Error(result.error?.message || 'Failed to forward email'); } } catch (error) { logger.log('error', `Failed to forward email: ${error.message}`); throw error; } } /** * Legacy forward delivery using raw sockets (fallback) * @param item Queue item */ async handleForwardDeliveryLegacy(item) { const email = item.processingResult; const route = item.route; // Get target server information const targetServer = route?.action.forward?.host; const targetPort = route?.action.forward?.port || 25; const useTls = false; // TLS configuration can be enhanced later if (!targetServer) { throw new Error('No target server configured for forward mode'); } // Create a socket connection to the target server const socket = new net.Socket(); // Set timeout socket.setTimeout(this.options.socketTimeout); try { // Connect to the target server await new Promise((resolve, reject) => { // Handle connection events socket.on('connect', () => { logger.log('debug', `Connected to ${targetServer}:${targetPort}`); resolve(); }); socket.on('timeout', () => { reject(new Error(`Connection timeout to ${targetServer}:${targetPort}`)); }); socket.on('error', (err) => { reject(new Error(`Connection error to ${targetServer}:${targetPort}: ${err.message}`)); }); // Connect to the server socket.connect({ host: targetServer, port: targetPort }); }); // Send EHLO await this.smtpCommand(socket, `EHLO ${route?.action.options?.mtaOptions?.domain || 'localhost'}`); // Start TLS if required if (useTls) { await this.smtpCommand(socket, 'STARTTLS'); // Upgrade to TLS const tlsSocket = await this.upgradeTls(socket, targetServer); // Send EHLO again after STARTTLS await this.smtpCommand(tlsSocket, `EHLO ${route?.action.options?.mtaOptions?.domain || 'localhost'}`); // Use tlsSocket for remaining commands return this.completeSMTPExchange(tlsSocket, email, route); } // Complete the SMTP exchange return this.completeSMTPExchange(socket, email, route); } catch (error) { logger.log('error', `Failed to forward email: ${error.message}`); // Close the connection socket.destroy(); throw error; } } /** * Complete the SMTP exchange after connection and initial setup * @param socket Network socket * @param email Email to send * @param rule Domain rule */ async completeSMTPExchange(socket, email, route) { try { // Authenticate if credentials provided if (route?.action?.forward?.auth?.user && route?.action?.forward?.auth?.pass) { // Send AUTH LOGIN await this.smtpCommand(socket, 'AUTH LOGIN'); // Send username (base64) const username = Buffer.from(route.action.forward.auth.user).toString('base64'); await this.smtpCommand(socket, username); // Send password (base64) const password = Buffer.from(route.action.forward.auth.pass).toString('base64'); await this.smtpCommand(socket, password); } // Send MAIL FROM await this.smtpCommand(socket, `MAIL FROM:<${email.from}>`); // Send RCPT TO for each recipient for (const recipient of email.getAllRecipients()) { await this.smtpCommand(socket, `RCPT TO:<${recipient}>`); } // Send DATA await this.smtpCommand(socket, 'DATA'); // Send email content (simplified) const emailContent = await this.getFormattedEmail(email); await this.smtpData(socket, emailContent); // Send QUIT await this.smtpCommand(socket, 'QUIT'); // Close the connection socket.end(); logger.log('info', `Email forwarded successfully to ${route?.action?.forward?.host}:${route?.action?.forward?.port || 25}`); return { targetServer: route?.action?.forward?.host, targetPort: route?.action?.forward?.port || 25, recipients: email.getAllRecipients().length }; } catch (error) { logger.log('error', `Failed to forward email: ${error.message}`); // Close the connection socket.destroy(); throw error; } } /** * Default handler for MTA mode delivery * @param item Queue item */ async handleMtaDelivery(item) { logger.log('info', `MTA delivery for item ${item.id}`); const email = item.processingResult; const route = item.route; try { // Apply DKIM signing if configured in the route if (item.route?.action.options?.mtaOptions?.dkimSign) { await this.applyDkimSigning(email, item.route.action.options.mtaOptions); } // In a full implementation, this would use the MTA service // For now, we'll simulate a successful delivery logger.log('info', `Email processed by MTA: ${email.subject} to ${email.getAllRecipients().join(', ')}`); // Note: The MTA implementation would handle actual local delivery // Simulate successful delivery return { recipients: email.getAllRecipients().length, subject: email.subject, dkimSigned: !!item.route?.action.options?.mtaOptions?.dkimSign }; } catch (error) { logger.log('error', `Failed to process email in MTA mode: ${error.message}`); throw error; } } /** * Default handler for process mode delivery * @param item Queue item */ async handleProcessDelivery(item) { logger.log('info', `Process delivery for item ${item.id}`); const email = item.processingResult; const route = item.route; try { // Apply content scanning if enabled if (route?.action.options?.contentScanning && route?.action.options?.scanners && route.action.options.scanners.length > 0) { logger.log('info', 'Performing content scanning'); // Apply each scanner for (const scanner of route.action.options.scanners) { switch (scanner.type) { case 'spam': logger.log('info', 'Scanning for spam content'); // Implement spam scanning break; case 'virus': logger.log('info', 'Scanning for virus content'); // Implement virus scanning break; case 'attachment': logger.log('info', 'Scanning attachments'); // Check for blocked extensions if (scanner.blockedExtensions && scanner.blockedExtensions.length > 0) { for (const attachment of email.attachments) { const ext = this.getFileExtension(attachment.filename); if (scanner.blockedExtensions.includes(ext)) { if (scanner.action === 'reject') { throw new Error(`Blocked attachment type: ${ext}`); } else { // tag email.addHeader('X-Attachment-Warning', `Potentially unsafe attachment: ${attachment.filename}`); } } } } break; } } } // Apply transformations if defined if (route?.action.options?.transformations && route?.action.options?.transformations.length > 0) { logger.log('info', 'Applying email transformations'); for (const transform of route.action.options.transformations) { switch (transform.type) { case 'addHeader': if (transform.header && transform.value) { email.addHeader(transform.header, transform.value); } break; } } } // Apply DKIM signing if configured (after all transformations) if (item.route?.action.options?.mtaOptions?.dkimSign || item.route?.action.process?.dkim) { await this.applyDkimSigning(email, item.route.action.options?.mtaOptions || {}); } logger.log('info', `Email successfully processed in store-and-forward mode`); // Simulate successful delivery return { recipients: email.getAllRecipients().length, subject: email.subject, scanned: !!route?.action.options?.contentScanning, transformed: !!(route?.action.options?.transformations && route?.action.options?.transformations.length > 0), dkimSigned: !!(item.route?.action.options?.mtaOptions?.dkimSign || item.route?.action.process?.dkim) }; } catch (error) { logger.log('error', `Failed to process email: ${error.message}`); throw error; } } /** * Get file extension from filename */ getFileExtension(filename) { return filename.substring(filename.lastIndexOf('.')).toLowerCase(); } /** * Apply DKIM signing to an email */ async applyDkimSigning(email, mtaOptions) { if (!this.emailServer) { logger.log('warn', 'Cannot apply DKIM signing without email server reference'); return; } const domainName = mtaOptions.dkimOptions?.domainName || email.from.split('@')[1]; const keySelector = mtaOptions.dkimOptions?.keySelector || 'default'; try { // Ensure DKIM keys exist for the domain await this.emailServer.dkimCreator.handleDKIMKeysForDomain(domainName); // Convert Email to raw format for signing const rawEmail = email.toRFC822String(); // Sign the email const dkimPrivateKey = (await this.emailServer.dkimCreator.readDKIMKeys(domainName)).privateKey; const signResult = await plugins.dkimSign(rawEmail, { signingDomain: domainName, selector: keySelector, privateKey: dkimPrivateKey, canonicalization: 'relaxed/relaxed', algorithm: 'rsa-sha256', signTime: new Date(), signatureData: [ { signingDomain: domainName, selector: keySelector, privateKey: dkimPrivateKey, algorithm: 'rsa-sha256', canonicalization: 'relaxed/relaxed' } ] }); // Add the DKIM-Signature header to the email if (signResult.signatures) { email.addHeader('DKIM-Signature', signResult.signatures); logger.log('info', `Successfully added DKIM signature for ${domainName}`); } } catch (error) { logger.log('error', `Failed to apply DKIM signature: ${error.message}`); // Don't throw - allow email to be sent without DKIM if signing fails } } /** * Format email for SMTP transmission * @param email Email to format */ async getFormattedEmail(email) { // This is a simplified implementation // In a full implementation, this would use proper MIME formatting let content = ''; // Add headers content += `From: ${email.from}\r\n`; content += `To: ${email.to.join(', ')}\r\n`; content += `Subject: ${email.subject}\r\n`; // Add additional headers for (const [name, value] of Object.entries(email.headers || {})) { content += `${name}: ${value}\r\n`; } // Add content type for multipart if (email.attachments && email.attachments.length > 0) { const boundary = `----_=_NextPart_${Math.random().toString(36).substr(2)}`; content += `MIME-Version: 1.0\r\n`; content += `Content-Type: multipart/mixed; boundary="${boundary}"\r\n`; content += `\r\n`; // Add text part content += `--${boundary}\r\n`; content += `Content-Type: text/plain; charset="UTF-8"\r\n`; content += `\r\n`; content += `${email.text}\r\n`; // Add HTML part if present if (email.html) { content += `--${boundary}\r\n`; content += `Content-Type: text/html; charset="UTF-8"\r\n`; content += `\r\n`; content += `${email.html}\r\n`; } // Add attachments for (const attachment of email.attachments) { content += `--${boundary}\r\n`; content += `Content-Type: ${attachment.contentType || 'application/octet-stream'}; name="${attachment.filename}"\r\n`; content += `Content-Disposition: attachment; filename="${attachment.filename}"\r\n`; content += `Content-Transfer-Encoding: base64\r\n`; content += `\r\n`; // Add base64 encoded content const base64Content = attachment.content.toString('base64'); // Split into lines of 76 characters for (let i = 0; i < base64Content.length; i += 76) { content += base64Content.substring(i, i + 76) + '\r\n'; } } // End boundary content += `--${boundary}--\r\n`; } else { // Simple email with just text content += `Content-Type: text/plain; charset="UTF-8"\r\n`; content += `\r\n`; content += `${email.text}\r\n`; } return content; } /** * Send SMTP command and wait for response * @param socket Socket connection * @param command SMTP command to send */ async smtpCommand(socket, command) { return new Promise((resolve, reject) => { const onData = (data) => { const response = data.toString().trim(); // Clean up listeners socket.removeListener('data', onData); socket.removeListener('error', onError); socket.removeListener('timeout', onTimeout); // Check response code if (response.charAt(0) === '2' || response.charAt(0) === '3') { resolve(response); } else { reject(new Error(`SMTP error: ${response}`)); } }; const onError = (err) => { // Clean up listeners socket.removeListener('data', onData); socket.removeListener('error', onError); socket.removeListener('timeout', onTimeout); reject(err); }; const onTimeout = () => { // Clean up listeners socket.removeListener('data', onData); socket.removeListener('error', onError); socket.removeListener('timeout', onTimeout); reject(new Error('SMTP command timeout')); }; // Set up listeners socket.once('data', onData); socket.once('error', onError); socket.once('timeout', onTimeout); // Send command socket.write(command + '\r\n'); }); } /** * Send SMTP DATA command with content * @param socket Socket connection * @param data Email content to send */ async smtpData(socket, data) { return new Promise((resolve, reject) => { const onData = (responseData) => { const response = responseData.toString().trim(); // Clean up listeners socket.removeListener('data', onData); socket.removeListener('error', onError); socket.removeListener('timeout', onTimeout); // Check response code if (response.charAt(0) === '2') { resolve(response); } else { reject(new Error(`SMTP error: ${response}`)); } }; const onError = (err) => { // Clean up listeners socket.removeListener('data', onData); socket.removeListener('error', onError); socket.removeListener('timeout', onTimeout); reject(err); }; const onTimeout = () => { // Clean up listeners socket.removeListener('data', onData); socket.removeListener('error', onError); socket.removeListener('timeout', onTimeout); reject(new Error('SMTP data timeout')); }; // Set up listeners socket.once('data', onData); socket.once('error', onError); socket.once('timeout', onTimeout); // Send data and end with CRLF.CRLF socket.write(data + '\r\n.\r\n'); }); } /** * Upgrade socket to TLS * @param socket Socket connection * @param hostname Target hostname for TLS */ async upgradeTls(socket, hostname) { return new Promise((resolve, reject) => { const tlsOptions = { socket, servername: hostname, rejectUnauthorized: this.options.verifyCertificates, minVersion: this.options.tlsMinVersion }; const tlsSocket = tls.connect(tlsOptions); tlsSocket.once('secureConnect', () => { resolve(tlsSocket); }); tlsSocket.once('error', (err) => { reject(new Error(`TLS error: ${err.message}`)); }); tlsSocket.setTimeout(this.options.socketTimeout); tlsSocket.once('timeout', () => { reject(new Error('TLS connection timeout')); }); }); } /** * Update delivery time statistics */ updateDeliveryTimeStats() { if (this.deliveryTimes.length === 0) return; // Keep only the last 1000 delivery times if (this.deliveryTimes.length > 1000) { this.deliveryTimes = this.deliveryTimes.slice(-1000); } // Calculate average const sum = this.deliveryTimes.reduce((acc, time) => acc + time, 0); this.stats.avgDeliveryTime = sum / this.deliveryTimes.length; } /** * Check if rate limit is exceeded * @returns True if rate limited, false otherwise */ checkRateLimit() { const now = Date.now(); const elapsed = now - this.rateLimitLastCheck; // Reset counter if more than a minute has passed if (elapsed >= 60000) { this.rateLimitLastCheck = now; this.rateLimitCounter = 0; this.throttled = false; this.stats.rateLimiting.currentRate = 0; return false; } // Check if we're already throttled if (this.throttled) { return true; } // Increment counter this.rateLimitCounter++; // Calculate current rate (emails per minute) const rate = (this.rateLimitCounter / elapsed) * 60000; this.stats.rateLimiting.currentRate = rate; // Check if rate limit is exceeded if (rate > this.options.globalRateLimit) { this.throttled = true; this.stats.rateLimiting.throttled++; // Schedule throttle reset const resetDelay = 60000 - elapsed; setTimeout(() => { this.throttled = false; this.rateLimitLastCheck = Date.now(); this.rateLimitCounter = 0; this.stats.rateLimiting.currentRate = 0; }, resetDelay); return true; } return false; } /** * Update delivery options * @param options New options */ updateOptions(options) { this.options = { ...this.options, ...options }; // Update rate limit statistics if (options.globalRateLimit) { this.stats.rateLimiting.globalLimit = options.globalRateLimit; } logger.log('info', 'MultiModeDeliverySystem options updated'); } /** * Get delivery statistics */ getStats() { return { ...this.stats }; } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5kZWxpdmVyeS5zeXN0ZW0uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90cy9tYWlsL2RlbGl2ZXJ5L2NsYXNzZXMuZGVsaXZlcnkuc3lzdGVtLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sa0JBQWtCLENBQUM7QUFDNUMsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUMzQyxPQUFPLEtBQUssR0FBRyxNQUFNLFVBQVUsQ0FBQztBQUNoQyxPQUFPLEtBQUssR0FBRyxNQUFNLFVBQVUsQ0FBQztBQUNoQyxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDekMsT0FBTyxFQUNMLGNBQWMsRUFDZCxnQkFBZ0IsRUFDaEIsaUJBQWlCLEVBQ2xCLE1BQU0seUJBQXlCLENBQUM7QUFDakMsT0FBTyxFQUFFLG9CQUFvQixFQUFtQixNQUFNLDZCQUE2QixDQUFDO0FBS3BGOztHQUVHO0FBQ0gsTUFBTSxDQUFOLElBQVksY0FNWDtBQU5ELFdBQVksY0FBYztJQUN4QixxQ0FBbUIsQ0FBQTtJQUNuQiwyQ0FBeUIsQ0FBQTtJQUN6Qix5Q0FBdUIsQ0FBQTtJQUN2Qix1Q0FBcUIsQ0FBQTtJQUNyQixtQ0FBaUIsQ0FBQTtBQUNuQixDQUFDLEVBTlcsY0FBYyxLQUFkLGNBQWMsUUFNekI7QUEyRUQ7O0dBRUc7QUFDSCxNQUFNLE9BQU8sdUJBQXdCLFNBQVEsWUFBWTtJQUMvQyxLQUFLLENBQXVCO0lBQzVCLE9BQU8sQ0FBc0M7SUFDN0MsS0FBSyxDQUFpQjtJQUN0QixhQUFhLEdBQWEsRUFBRSxDQUFDO0lBQzdCLGdCQUFnQixHQUFnQixJQUFJLEdBQUcsRUFBRSxDQUFDO0lBQzFDLE9BQU8sR0FBWSxLQUFLLENBQUM7SUFDekIsU0FBUyxHQUFZLEtBQUssQ0FBQztJQUMzQixrQkFBa0IsR0FBVyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7SUFD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