fix(types): Fix TypeScript build errors and improve API type safety across platformservice interfaces
This commit is contained in:
parent
4624fdbe10
commit
39b634b6bb
31
changelog.md
31
changelog.md
@ -1,5 +1,36 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 2025-05-08 - 2.8.9 - fix(types)
|
||||||
|
Fix TypeScript build errors and improve API type safety across platformservice interfaces
|
||||||
|
|
||||||
|
- Fixed interface placement in EmailService and MtaConnector classes
|
||||||
|
- Aligned DeliveryStatus enum and updated ApiManager handlers with proper type-safe signatures
|
||||||
|
- Added comprehensive TypeScript interfaces for ISendEmailOptions, ITemplateContext, IValidateEmailOptions, IValidationResult, and IEmailServiceStats
|
||||||
|
- Removed circular dependencies in type definitions and added proper type assertions
|
||||||
|
- Improved test stability by handling race conditions in SenderReputationMonitor and IPWarmupManager; external DNS lookups are disabled under test environment
|
||||||
|
|
||||||
|
## 2025-05-08 - 2.8.8 - fix(types): Fix TypeScript build errors and improve API interfaces
|
||||||
|
Fix TypeScript build errors caused by interface placement and improve API type alignment
|
||||||
|
|
||||||
|
- Fixed interface placement in EmailService and MtaConnector classes
|
||||||
|
- Aligned DeliveryStatus enum with EmailSendJob implementation
|
||||||
|
- Added proper method signatures for API endpoint handlers in ApiManager class
|
||||||
|
- Updated getStats and checkEmailStatus methods to conform to API contracts
|
||||||
|
- Implemented type-safe return values for all API methods
|
||||||
|
- Fixed circular dependencies in type definitions
|
||||||
|
- Added proper type assertion where needed to satisfy TypeScript compiler
|
||||||
|
|
||||||
|
## 2025-05-08 - 2.8.7 - feat(types): Add comprehensive TypeScript interfaces for API types
|
||||||
|
Improve type safety across the platform by adding detailed TypeScript interfaces for APIs
|
||||||
|
|
||||||
|
- Added ISendEmailOptions interface with complete documentation for email sending options
|
||||||
|
- Created ITemplateContext interface for email template rendering with full type safety
|
||||||
|
- Added IValidateEmailOptions and IValidationResult interfaces for email validation
|
||||||
|
- Improved IEmailServiceStats interface with detailed statistics types
|
||||||
|
- Added IEmailStatusResponse and IEmailStatusDetails interfaces for MTA status checking
|
||||||
|
- Updated sendEmail and other methods to use these new interfaces instead of 'any'
|
||||||
|
- Removed need for type assertions in various components
|
||||||
|
|
||||||
## 2025-05-08 - 2.8.6 - fix(tests)
|
## 2025-05-08 - 2.8.6 - fix(tests)
|
||||||
fix: Improve test stability by handling race conditions in SenderReputationMonitor and IPWarmupManager. Disable filesystem operations and external DNS lookups during tests by checking NODE_ENV, add proper cleanup of singleton instances and active timeouts to ensure consistent test environment.
|
fix: Improve test stability by handling race conditions in SenderReputationMonitor and IPWarmupManager. Disable filesystem operations and external DNS lookups during tests by checking NODE_ENV, add proper cleanup of singleton instances and active timeouts to ensure consistent test environment.
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@serve.zone/platformservice",
|
"name": "@serve.zone/platformservice",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "2.8.6",
|
"version": "2.8.8",
|
||||||
"description": "A multifaceted platform service handling mail, SMS, letter delivery, and AI services.",
|
"description": "A multifaceted platform service handling mail, SMS, letter delivery, and AI services.",
|
||||||
"main": "dist_ts/index.js",
|
"main": "dist_ts/index.js",
|
||||||
"typings": "dist_ts/index.d.ts",
|
"typings": "dist_ts/index.d.ts",
|
||||||
|
@ -2,6 +2,16 @@
|
|||||||
|
|
||||||
## Latest Changes
|
## Latest Changes
|
||||||
|
|
||||||
|
### API Type Safety Improvements
|
||||||
|
- [x] Create comprehensive TypeScript interfaces for all API methods
|
||||||
|
- [x] Replace any types with specific interfaces in EmailService and MtaConnector
|
||||||
|
- [x] Align interface types with their implementations
|
||||||
|
- [x] Document all interface properties with detailed JSDoc comments
|
||||||
|
- [x] Use type imports to ensure consistency between services
|
||||||
|
- [x] Fix TypeScript build errors from interface placements
|
||||||
|
- [x] Add proper method signatures for API endpoint handlers
|
||||||
|
- [x] Implement type-safe API responses
|
||||||
|
|
||||||
### Test Stability Improvements
|
### Test Stability Improvements
|
||||||
- [x] Fix race conditions in SenderReputationMonitor tests
|
- [x] Fix race conditions in SenderReputationMonitor tests
|
||||||
- [x] Disable filesystem operations during tests to prevent race conditions
|
- [x] Disable filesystem operations during tests to prevent race conditions
|
||||||
@ -9,6 +19,27 @@
|
|||||||
- [x] Ensure all tests properly clean up shared resources
|
- [x] Ensure all tests properly clean up shared resources
|
||||||
- [x] Set consistent test environment with NODE_ENV=test
|
- [x] Set consistent test environment with NODE_ENV=test
|
||||||
|
|
||||||
|
### Error Handling Improvements
|
||||||
|
- [ ] Add structured error types for better error reporting
|
||||||
|
- [ ] Implement consistent error handling patterns across services
|
||||||
|
- [ ] Add detailed error context for debugging
|
||||||
|
- [ ] Create retry mechanisms for transient failures
|
||||||
|
- [ ] Improve error logging with structured data
|
||||||
|
|
||||||
|
### Configuration Interface Standardization
|
||||||
|
- [ ] Define consistent configuration interfaces across services
|
||||||
|
- [ ] Implement validation for all configuration objects
|
||||||
|
- [ ] Add default values for optional configuration
|
||||||
|
- [ ] Create documentation for all configuration options
|
||||||
|
- [ ] Add migration helpers for configuration format changes
|
||||||
|
|
||||||
|
### Logging Enhancements
|
||||||
|
- [ ] Implement structured logging throughout the codebase
|
||||||
|
- [ ] Add context information to all log messages
|
||||||
|
- [ ] Create consistent log levels and usage patterns
|
||||||
|
- [ ] Add correlation IDs for request tracking
|
||||||
|
- [ ] Implement log filtering and sampling options
|
||||||
|
|
||||||
### Mailgun Removal
|
### Mailgun Removal
|
||||||
- [x] Remove Mailgun integration from keywords in package.json and npmextra.json
|
- [x] Remove Mailgun integration from keywords in package.json and npmextra.json
|
||||||
- [x] Update EmailService comments to remove mentions of Mailgun
|
- [x] Update EmailService comments to remove mentions of Mailgun
|
||||||
|
@ -3,6 +3,6 @@
|
|||||||
*/
|
*/
|
||||||
export const commitinfo = {
|
export const commitinfo = {
|
||||||
name: '@serve.zone/platformservice',
|
name: '@serve.zone/platformservice',
|
||||||
version: '2.8.6',
|
version: '2.8.9',
|
||||||
description: 'A multifaceted platform service handling mail, SMS, letter delivery, and AI services.'
|
description: 'A multifaceted platform service handling mail, SMS, letter delivery, and AI services.'
|
||||||
}
|
}
|
||||||
|
165
ts/errors/error.codes.ts
Normal file
165
ts/errors/error.codes.ts
Normal file
@ -0,0 +1,165 @@
|
|||||||
|
/**
|
||||||
|
* Platform Service Error Codes
|
||||||
|
*
|
||||||
|
* This file contains all error codes used across the platform service.
|
||||||
|
*
|
||||||
|
* Format: PREFIX_ERROR_TYPE
|
||||||
|
* - PREFIX: Component/domain prefix (e.g., EMAIL, MTA, SMS)
|
||||||
|
* - ERROR_TYPE: Specific error type within the domain
|
||||||
|
*/
|
||||||
|
|
||||||
|
// General platform errors (PLATFORM_*)
|
||||||
|
export const PLATFORM_INITIALIZATION_ERROR = 'PLATFORM_INITIALIZATION_ERROR';
|
||||||
|
export const PLATFORM_CONFIGURATION_ERROR = 'PLATFORM_CONFIGURATION_ERROR';
|
||||||
|
export const PLATFORM_OPERATION_ERROR = 'PLATFORM_OPERATION_ERROR';
|
||||||
|
export const PLATFORM_NOT_IMPLEMENTED = 'PLATFORM_NOT_IMPLEMENTED';
|
||||||
|
export const PLATFORM_NOT_SUPPORTED = 'PLATFORM_NOT_SUPPORTED';
|
||||||
|
export const PLATFORM_SERVICE_UNAVAILABLE = 'PLATFORM_SERVICE_UNAVAILABLE';
|
||||||
|
|
||||||
|
// Email service errors (EMAIL_*)
|
||||||
|
export const EMAIL_SERVICE_ERROR = 'EMAIL_SERVICE_ERROR';
|
||||||
|
export const EMAIL_TEMPLATE_ERROR = 'EMAIL_TEMPLATE_ERROR';
|
||||||
|
export const EMAIL_VALIDATION_ERROR = 'EMAIL_VALIDATION_ERROR';
|
||||||
|
export const EMAIL_SEND_ERROR = 'EMAIL_SEND_ERROR';
|
||||||
|
export const EMAIL_RECEIVE_ERROR = 'EMAIL_RECEIVE_ERROR';
|
||||||
|
export const EMAIL_ATTACHMENT_ERROR = 'EMAIL_ATTACHMENT_ERROR';
|
||||||
|
export const EMAIL_PARSE_ERROR = 'EMAIL_PARSE_ERROR';
|
||||||
|
export const EMAIL_RATE_LIMIT_EXCEEDED = 'EMAIL_RATE_LIMIT_EXCEEDED';
|
||||||
|
|
||||||
|
// MTA-specific errors (MTA_*)
|
||||||
|
export const MTA_CONNECTION_ERROR = 'MTA_CONNECTION_ERROR';
|
||||||
|
export const MTA_AUTHENTICATION_ERROR = 'MTA_AUTHENTICATION_ERROR';
|
||||||
|
export const MTA_DELIVERY_ERROR = 'MTA_DELIVERY_ERROR';
|
||||||
|
export const MTA_CONFIGURATION_ERROR = 'MTA_CONFIGURATION_ERROR';
|
||||||
|
export const MTA_DNS_ERROR = 'MTA_DNS_ERROR';
|
||||||
|
export const MTA_TIMEOUT_ERROR = 'MTA_TIMEOUT_ERROR';
|
||||||
|
export const MTA_PROTOCOL_ERROR = 'MTA_PROTOCOL_ERROR';
|
||||||
|
|
||||||
|
// Bounce management errors (BOUNCE_*)
|
||||||
|
export const BOUNCE_PROCESSING_ERROR = 'BOUNCE_PROCESSING_ERROR';
|
||||||
|
export const BOUNCE_STORAGE_ERROR = 'BOUNCE_STORAGE_ERROR';
|
||||||
|
export const BOUNCE_CLASSIFICATION_ERROR = 'BOUNCE_CLASSIFICATION_ERROR';
|
||||||
|
|
||||||
|
// Email authentication errors (AUTH_*)
|
||||||
|
export const AUTH_SPF_ERROR = 'AUTH_SPF_ERROR';
|
||||||
|
export const AUTH_DKIM_ERROR = 'AUTH_DKIM_ERROR';
|
||||||
|
export const AUTH_DMARC_ERROR = 'AUTH_DMARC_ERROR';
|
||||||
|
export const AUTH_KEY_ERROR = 'AUTH_KEY_ERROR';
|
||||||
|
|
||||||
|
// Content scanning errors (SCAN_*)
|
||||||
|
export const SCAN_ANALYSIS_ERROR = 'SCAN_ANALYSIS_ERROR';
|
||||||
|
export const SCAN_MALWARE_DETECTED = 'SCAN_MALWARE_DETECTED';
|
||||||
|
export const SCAN_PHISHING_DETECTED = 'SCAN_PHISHING_DETECTED';
|
||||||
|
export const SCAN_CONTENT_REJECTED = 'SCAN_CONTENT_REJECTED';
|
||||||
|
|
||||||
|
// IP and reputation errors (REPUTATION_*)
|
||||||
|
export const REPUTATION_CHECK_ERROR = 'REPUTATION_CHECK_ERROR';
|
||||||
|
export const REPUTATION_DATA_ERROR = 'REPUTATION_DATA_ERROR';
|
||||||
|
export const REPUTATION_BLOCKLIST_ERROR = 'REPUTATION_BLOCKLIST_ERROR';
|
||||||
|
export const REPUTATION_UPDATE_ERROR = 'REPUTATION_UPDATE_ERROR';
|
||||||
|
|
||||||
|
// IP warmup errors (WARMUP_*)
|
||||||
|
export const WARMUP_ALLOCATION_ERROR = 'WARMUP_ALLOCATION_ERROR';
|
||||||
|
export const WARMUP_LIMIT_EXCEEDED = 'WARMUP_LIMIT_EXCEEDED';
|
||||||
|
export const WARMUP_SCHEDULE_ERROR = 'WARMUP_SCHEDULE_ERROR';
|
||||||
|
|
||||||
|
// Network and connectivity errors (NETWORK_*)
|
||||||
|
export const NETWORK_CONNECTION_ERROR = 'NETWORK_CONNECTION_ERROR';
|
||||||
|
export const NETWORK_TIMEOUT = 'NETWORK_TIMEOUT';
|
||||||
|
export const NETWORK_DNS_ERROR = 'NETWORK_DNS_ERROR';
|
||||||
|
export const NETWORK_TLS_ERROR = 'NETWORK_TLS_ERROR';
|
||||||
|
|
||||||
|
// Queue and processing errors (QUEUE_*)
|
||||||
|
export const QUEUE_FULL_ERROR = 'QUEUE_FULL_ERROR';
|
||||||
|
export const QUEUE_PROCESSING_ERROR = 'QUEUE_PROCESSING_ERROR';
|
||||||
|
export const QUEUE_PERSISTENCE_ERROR = 'QUEUE_PERSISTENCE_ERROR';
|
||||||
|
export const QUEUE_ITEM_NOT_FOUND = 'QUEUE_ITEM_NOT_FOUND';
|
||||||
|
|
||||||
|
// DcRouter errors (DCR_*)
|
||||||
|
export const DCR_ROUTING_ERROR = 'DCR_ROUTING_ERROR';
|
||||||
|
export const DCR_CONFIGURATION_ERROR = 'DCR_CONFIGURATION_ERROR';
|
||||||
|
export const DCR_PROXY_ERROR = 'DCR_PROXY_ERROR';
|
||||||
|
export const DCR_DOMAIN_ERROR = 'DCR_DOMAIN_ERROR';
|
||||||
|
|
||||||
|
// SMS service errors (SMS_*)
|
||||||
|
export const SMS_SERVICE_ERROR = 'SMS_SERVICE_ERROR';
|
||||||
|
export const SMS_SEND_ERROR = 'SMS_SEND_ERROR';
|
||||||
|
export const SMS_VALIDATION_ERROR = 'SMS_VALIDATION_ERROR';
|
||||||
|
export const SMS_RATE_LIMIT_EXCEEDED = 'SMS_RATE_LIMIT_EXCEEDED';
|
||||||
|
|
||||||
|
// Storage errors (STORAGE_*)
|
||||||
|
export const STORAGE_WRITE_ERROR = 'STORAGE_WRITE_ERROR';
|
||||||
|
export const STORAGE_READ_ERROR = 'STORAGE_READ_ERROR';
|
||||||
|
export const STORAGE_DELETE_ERROR = 'STORAGE_DELETE_ERROR';
|
||||||
|
export const STORAGE_QUOTA_EXCEEDED = 'STORAGE_QUOTA_EXCEEDED';
|
||||||
|
|
||||||
|
// Rule management errors (RULE_*)
|
||||||
|
export const RULE_VALIDATION_ERROR = 'RULE_VALIDATION_ERROR';
|
||||||
|
export const RULE_EXECUTION_ERROR = 'RULE_EXECUTION_ERROR';
|
||||||
|
export const RULE_NOT_FOUND = 'RULE_NOT_FOUND';
|
||||||
|
|
||||||
|
// Type definitions for error severity
|
||||||
|
export enum ErrorSeverity {
|
||||||
|
/** Critical errors that require immediate attention */
|
||||||
|
CRITICAL = 'CRITICAL',
|
||||||
|
|
||||||
|
/** High-impact errors that may affect service functioning */
|
||||||
|
HIGH = 'HIGH',
|
||||||
|
|
||||||
|
/** Medium-impact errors that cause partial degradation */
|
||||||
|
MEDIUM = 'MEDIUM',
|
||||||
|
|
||||||
|
/** Low-impact errors that have minimal or local impact */
|
||||||
|
LOW = 'LOW',
|
||||||
|
|
||||||
|
/** Informational errors that are not problematic */
|
||||||
|
INFO = 'INFO'
|
||||||
|
}
|
||||||
|
|
||||||
|
// Type definitions for error categories
|
||||||
|
export enum ErrorCategory {
|
||||||
|
/** Errors related to configuration */
|
||||||
|
CONFIGURATION = 'CONFIGURATION',
|
||||||
|
|
||||||
|
/** Errors related to network connectivity */
|
||||||
|
CONNECTIVITY = 'CONNECTIVITY',
|
||||||
|
|
||||||
|
/** Errors related to authentication/authorization */
|
||||||
|
AUTHENTICATION = 'AUTHENTICATION',
|
||||||
|
|
||||||
|
/** Errors related to data validation */
|
||||||
|
VALIDATION = 'VALIDATION',
|
||||||
|
|
||||||
|
/** Errors related to resource availability */
|
||||||
|
RESOURCE = 'RESOURCE',
|
||||||
|
|
||||||
|
/** Errors related to service operations */
|
||||||
|
OPERATION = 'OPERATION',
|
||||||
|
|
||||||
|
/** Errors related to third-party integrations */
|
||||||
|
INTEGRATION = 'INTEGRATION',
|
||||||
|
|
||||||
|
/** Errors related to security */
|
||||||
|
SECURITY = 'SECURITY',
|
||||||
|
|
||||||
|
/** Errors related to data storage */
|
||||||
|
STORAGE = 'STORAGE',
|
||||||
|
|
||||||
|
/** Errors that don't fit into other categories */
|
||||||
|
OTHER = 'OTHER'
|
||||||
|
}
|
||||||
|
|
||||||
|
// Type definitions for error recoverability
|
||||||
|
export enum ErrorRecoverability {
|
||||||
|
/** Error cannot be automatically recovered from */
|
||||||
|
NON_RECOVERABLE = 'NON_RECOVERABLE',
|
||||||
|
|
||||||
|
/** Error might be recoverable with retry */
|
||||||
|
MAYBE_RECOVERABLE = 'MAYBE_RECOVERABLE',
|
||||||
|
|
||||||
|
/** Error is definitely recoverable with retries */
|
||||||
|
RECOVERABLE = 'RECOVERABLE',
|
||||||
|
|
||||||
|
/** Error is transient and should resolve without action */
|
||||||
|
TRANSIENT = 'TRANSIENT'
|
||||||
|
}
|
@ -5,6 +5,10 @@ import { logger } from '../../logger.js';
|
|||||||
// Import MTA classes
|
// Import MTA classes
|
||||||
import { MtaService } from './classes.mta.js';
|
import { MtaService } from './classes.mta.js';
|
||||||
import { Email as MtaEmail } from '../core/classes.email.js';
|
import { Email as MtaEmail } from '../core/classes.email.js';
|
||||||
|
import { DeliveryStatus } from './classes.emailsendjob.js';
|
||||||
|
|
||||||
|
// Re-export for use in index.ts
|
||||||
|
export { DeliveryStatus };
|
||||||
|
|
||||||
// Import Email types
|
// Import Email types
|
||||||
export interface IEmailOptions {
|
export interface IEmailOptions {
|
||||||
@ -19,14 +23,6 @@ export interface IEmailOptions {
|
|||||||
headers?: { [key: string]: string };
|
headers?: { [key: string]: string };
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reuse the DeliveryStatus from the email send job
|
|
||||||
export enum DeliveryStatus {
|
|
||||||
PENDING = 'pending',
|
|
||||||
PROCESSING = 'processing',
|
|
||||||
DELIVERED = 'delivered',
|
|
||||||
DEFERRED = 'deferred',
|
|
||||||
FAILED = 'failed'
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reuse the IAttachment interface
|
// Reuse the IAttachment interface
|
||||||
export interface IAttachment {
|
export interface IAttachment {
|
||||||
@ -37,6 +33,66 @@ export interface IAttachment {
|
|||||||
encoding?: string;
|
encoding?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Email status details
|
||||||
|
*/
|
||||||
|
export interface IEmailStatusDetails {
|
||||||
|
/** Number of delivery attempts */
|
||||||
|
attempts?: number;
|
||||||
|
/** Timestamp of last delivery attempt */
|
||||||
|
lastAttempt?: Date;
|
||||||
|
/** Timestamp of next scheduled attempt */
|
||||||
|
nextAttempt?: Date;
|
||||||
|
/** Error message if delivery failed */
|
||||||
|
error?: string;
|
||||||
|
/** Message explaining the status */
|
||||||
|
message?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Email status response
|
||||||
|
*/
|
||||||
|
export interface IEmailStatusResponse {
|
||||||
|
/** Current status of the email */
|
||||||
|
status: DeliveryStatus | 'unknown' | 'error';
|
||||||
|
/** Additional status details */
|
||||||
|
details?: IEmailStatusDetails;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Options for sending an email via MTA
|
||||||
|
*/
|
||||||
|
export interface ISendEmailOptions {
|
||||||
|
/** Whether to use MIME format conversion */
|
||||||
|
useMimeFormat?: boolean;
|
||||||
|
/** Whether to track clicks */
|
||||||
|
trackClicks?: boolean;
|
||||||
|
/** Whether to track opens */
|
||||||
|
trackOpens?: boolean;
|
||||||
|
/** Message priority (1-5, where 1 is highest) */
|
||||||
|
priority?: number;
|
||||||
|
/** Message scheduling options */
|
||||||
|
schedule?: {
|
||||||
|
/** Time to send the email */
|
||||||
|
sendAt?: Date | string;
|
||||||
|
/** Time the message expires */
|
||||||
|
expireAt?: Date | string;
|
||||||
|
};
|
||||||
|
/** DKIM signing options */
|
||||||
|
dkim?: {
|
||||||
|
/** Whether to sign the message */
|
||||||
|
sign?: boolean;
|
||||||
|
/** Domain to use for signing */
|
||||||
|
domain?: string;
|
||||||
|
/** Key selector to use */
|
||||||
|
selector?: string;
|
||||||
|
};
|
||||||
|
/** Additional headers */
|
||||||
|
headers?: Record<string, string>;
|
||||||
|
/** Message tags for categorization */
|
||||||
|
tags?: string[];
|
||||||
|
}
|
||||||
|
|
||||||
export class MtaConnector {
|
export class MtaConnector {
|
||||||
public emailRef: EmailService;
|
public emailRef: EmailService;
|
||||||
private mtaService: MtaService;
|
private mtaService: MtaService;
|
||||||
@ -46,6 +102,13 @@ export class MtaConnector {
|
|||||||
this.mtaService = mtaService || this.emailRef.mtaService;
|
this.mtaService = mtaService || this.emailRef.mtaService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send an email using the MTA service
|
||||||
|
* @param smartmail The email to send
|
||||||
|
* @param toAddresses Recipients (comma-separated or array)
|
||||||
|
* @param options Additional options
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send an email using the MTA service
|
* Send an email using the MTA service
|
||||||
* @param smartmail The email to send
|
* @param smartmail The email to send
|
||||||
@ -55,7 +118,7 @@ export class MtaConnector {
|
|||||||
public async sendEmail(
|
public async sendEmail(
|
||||||
smartmail: plugins.smartmail.Smartmail<any>,
|
smartmail: plugins.smartmail.Smartmail<any>,
|
||||||
toAddresses: string | string[],
|
toAddresses: string | string[],
|
||||||
options: any = {}
|
options: ISendEmailOptions = {}
|
||||||
): Promise<string> {
|
): Promise<string> {
|
||||||
// Check if recipients are on the suppression list
|
// Check if recipients are on the suppression list
|
||||||
const recipients = Array.isArray(toAddresses)
|
const recipients = Array.isArray(toAddresses)
|
||||||
@ -101,7 +164,7 @@ export class MtaConnector {
|
|||||||
const emailOptions: Record<string, any> = { ...options };
|
const emailOptions: Record<string, any> = { ...options };
|
||||||
|
|
||||||
// Check if we should use MIME format
|
// Check if we should use MIME format
|
||||||
const useMimeFormat = options.useMimeFormat ?? true;
|
const useMimeFormat = options.useMimeFormat !== false; // Default to true
|
||||||
|
|
||||||
if (useMimeFormat) {
|
if (useMimeFormat) {
|
||||||
// Use smartmail's MIME conversion for improved handling
|
// Use smartmail's MIME conversion for improved handling
|
||||||
@ -521,28 +584,28 @@ export class MtaConnector {
|
|||||||
/**
|
/**
|
||||||
* Check the status of a sent email
|
* Check the status of a sent email
|
||||||
* @param emailId The email ID to check
|
* @param emailId The email ID to check
|
||||||
|
* @returns Current status and details
|
||||||
*/
|
*/
|
||||||
public async checkEmailStatus(emailId: string): Promise<{
|
public async checkEmailStatus(emailId: string): Promise<IEmailStatusResponse> {
|
||||||
status: string;
|
|
||||||
details?: any;
|
|
||||||
}> {
|
|
||||||
try {
|
try {
|
||||||
const status = this.mtaService.getEmailStatus(emailId);
|
const status = this.mtaService.getEmailStatus(emailId);
|
||||||
|
|
||||||
if (!status) {
|
if (!status) {
|
||||||
return {
|
return {
|
||||||
status: 'unknown',
|
status: 'unknown' as const,
|
||||||
details: { message: 'Email not found' }
|
details: { message: 'Email not found' }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
status: status.status,
|
// Use type assertion to ensure this passes type check
|
||||||
|
status: status.status as DeliveryStatus,
|
||||||
details: {
|
details: {
|
||||||
attempts: status.attempts,
|
attempts: status.attempts,
|
||||||
lastAttempt: status.lastAttempt,
|
lastAttempt: status.lastAttempt,
|
||||||
nextAttempt: status.nextAttempt,
|
nextAttempt: status.nextAttempt,
|
||||||
error: status.error?.message
|
error: status.error?.message,
|
||||||
|
message: `Status: ${status.status}${status.error ? `, Error: ${status.error.message}` : ''}`
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -554,7 +617,7 @@ export class MtaConnector {
|
|||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
status: 'error',
|
status: 'error' as const,
|
||||||
details: { message: error.message }
|
details: { message: error.message }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -65,8 +65,18 @@ export class ApiManager {
|
|||||||
new plugins.typedrequest.TypedHandler('checkEmailStatus', async (requestData) => {
|
new plugins.typedrequest.TypedHandler('checkEmailStatus', async (requestData) => {
|
||||||
// If MTA is enabled, use it to check status
|
// If MTA is enabled, use it to check status
|
||||||
if (this.emailRef.mtaConnector) {
|
if (this.emailRef.mtaConnector) {
|
||||||
const status = await this.emailRef.mtaConnector.checkEmailStatus(requestData.emailId);
|
const detailedStatus = await this.emailRef.mtaConnector.checkEmailStatus(requestData.emailId);
|
||||||
return status;
|
|
||||||
|
// Convert to the expected API response format
|
||||||
|
const apiResponse: plugins.servezoneInterfaces.platformservice.mta.IReq_CheckEmailStatus['response'] = {
|
||||||
|
status: detailedStatus.status.toString(), // Convert enum to string
|
||||||
|
details: {
|
||||||
|
message: detailedStatus.details?.message ||
|
||||||
|
(detailedStatus.details?.error ? `Error: ${detailedStatus.details.error}` :
|
||||||
|
`Status: ${detailedStatus.status}`)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return apiResponse;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Status tracking not available if MTA is not configured
|
// Status tracking not available if MTA is not configured
|
||||||
|
@ -24,6 +24,107 @@ export interface IEmailConstructorOptions {
|
|||||||
loadTemplatesFromDir?: boolean;
|
loadTemplatesFromDir?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Options for sending an email
|
||||||
|
* @see ISendEmailOptions in MtaConnector
|
||||||
|
*/
|
||||||
|
export type ISendEmailOptions = import('../delivery/classes.connector.mta.js').ISendEmailOptions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Template context data for email templates
|
||||||
|
* @see ITemplateContext in TemplateManager
|
||||||
|
*/
|
||||||
|
export type ITemplateContext = import('../core/classes.templatemanager.js').ITemplateContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validation options for email addresses
|
||||||
|
* Compatible with EmailValidator.validate options
|
||||||
|
*/
|
||||||
|
export interface IValidateEmailOptions {
|
||||||
|
/** Check MX records for the domain */
|
||||||
|
checkMx?: boolean;
|
||||||
|
/** Check if the domain is disposable (temporary email) */
|
||||||
|
checkDisposable?: boolean;
|
||||||
|
/** Check if the email is a role account (e.g., info@, support@) */
|
||||||
|
checkRole?: boolean;
|
||||||
|
/** Only check syntax without DNS lookups */
|
||||||
|
checkSyntaxOnly?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Result of email validation
|
||||||
|
* @see IEmailValidationResult from EmailValidator
|
||||||
|
*/
|
||||||
|
export type IValidationResult = import('../core/classes.emailvalidator.js').IEmailValidationResult;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Email service statistics
|
||||||
|
*/
|
||||||
|
export interface IEmailServiceStats {
|
||||||
|
/** Active email providers */
|
||||||
|
activeProviders: string[];
|
||||||
|
/** MTA statistics, if MTA is active */
|
||||||
|
mta?: {
|
||||||
|
/** Service start time */
|
||||||
|
startTime: Date;
|
||||||
|
/** Total emails received */
|
||||||
|
emailsReceived: number;
|
||||||
|
/** Total emails sent */
|
||||||
|
emailsSent: number;
|
||||||
|
/** Total emails that failed to send */
|
||||||
|
emailsFailed: number;
|
||||||
|
/** Active SMTP connections */
|
||||||
|
activeConnections: number;
|
||||||
|
/** Current email queue size */
|
||||||
|
queueSize: number;
|
||||||
|
/** Certificate information */
|
||||||
|
certificateInfo?: {
|
||||||
|
/** Domain for the certificate */
|
||||||
|
domain: string;
|
||||||
|
/** Certificate expiration date */
|
||||||
|
expiresAt: Date;
|
||||||
|
/** Days until certificate expires */
|
||||||
|
daysUntilExpiry: number;
|
||||||
|
};
|
||||||
|
/** IP warmup information */
|
||||||
|
warmupInfo?: {
|
||||||
|
/** Whether IP warmup is enabled */
|
||||||
|
enabled: boolean;
|
||||||
|
/** Number of active IPs */
|
||||||
|
activeIPs: number;
|
||||||
|
/** Number of IPs in warmup phase */
|
||||||
|
inWarmupPhase: number;
|
||||||
|
/** Number of IPs that completed warmup */
|
||||||
|
completedWarmup: number;
|
||||||
|
};
|
||||||
|
/** Reputation monitoring information */
|
||||||
|
reputationInfo?: {
|
||||||
|
/** Whether reputation monitoring is enabled */
|
||||||
|
enabled: boolean;
|
||||||
|
/** Number of domains being monitored */
|
||||||
|
monitoredDomains: number;
|
||||||
|
/** Average reputation score across domains */
|
||||||
|
averageScore: number;
|
||||||
|
/** Number of domains with reputation issues */
|
||||||
|
domainsWithIssues: number;
|
||||||
|
};
|
||||||
|
/** Rate limiting information */
|
||||||
|
rateLimiting?: {
|
||||||
|
/** Global rate limit statistics */
|
||||||
|
global: {
|
||||||
|
/** Current available tokens */
|
||||||
|
availableTokens: number;
|
||||||
|
/** Maximum tokens per period */
|
||||||
|
maxTokens: number;
|
||||||
|
/** Current consumption rate */
|
||||||
|
consumptionRate: number;
|
||||||
|
/** Number of rate limiting events */
|
||||||
|
rateLimitEvents: number;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Email service with MTA support
|
* Email service with MTA support
|
||||||
*/
|
*/
|
||||||
@ -136,7 +237,7 @@ export class EmailService {
|
|||||||
public async sendEmail(
|
public async sendEmail(
|
||||||
email: plugins.smartmail.Smartmail<any>,
|
email: plugins.smartmail.Smartmail<any>,
|
||||||
to: string | string[],
|
to: string | string[],
|
||||||
options: any = {}
|
options: ISendEmailOptions = {}
|
||||||
): Promise<string> {
|
): Promise<string> {
|
||||||
// Determine which connector to use
|
// Determine which connector to use
|
||||||
if (this.config.useMta && this.mtaConnector) {
|
if (this.config.useMta && this.mtaConnector) {
|
||||||
@ -156,8 +257,8 @@ export class EmailService {
|
|||||||
public async sendTemplateEmail(
|
public async sendTemplateEmail(
|
||||||
templateId: string,
|
templateId: string,
|
||||||
to: string | string[],
|
to: string | string[],
|
||||||
context: any = {},
|
context: ITemplateContext = {},
|
||||||
options: any = {}
|
options: ISendEmailOptions = {}
|
||||||
): Promise<string> {
|
): Promise<string> {
|
||||||
try {
|
try {
|
||||||
// Get email from template
|
// Get email from template
|
||||||
@ -183,28 +284,35 @@ export class EmailService {
|
|||||||
*/
|
*/
|
||||||
public async validateEmail(
|
public async validateEmail(
|
||||||
email: string,
|
email: string,
|
||||||
options: {
|
options: IValidateEmailOptions = {}
|
||||||
checkMx?: boolean;
|
): Promise<IValidationResult> {
|
||||||
checkDisposable?: boolean;
|
|
||||||
checkRole?: boolean;
|
|
||||||
} = {}
|
|
||||||
): Promise<any> {
|
|
||||||
return this.emailValidator.validate(email, options);
|
return this.emailValidator.validate(email, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get email service statistics
|
* Get email service statistics
|
||||||
|
* @returns Service statistics in the format expected by the API
|
||||||
*/
|
*/
|
||||||
public getStats() {
|
public getStats(): plugins.servezoneInterfaces.platformservice.mta.IReq_GetEMailStats['response'] {
|
||||||
const stats: any = {
|
// First generate detailed internal stats
|
||||||
|
const detailedStats: IEmailServiceStats = {
|
||||||
activeProviders: []
|
activeProviders: []
|
||||||
};
|
};
|
||||||
|
|
||||||
if (this.config.useMta) {
|
if (this.config.useMta) {
|
||||||
stats.activeProviders.push('mta');
|
detailedStats.activeProviders.push('mta');
|
||||||
stats.mta = this.mtaService.getStats();
|
detailedStats.mta = this.mtaService.getStats();
|
||||||
}
|
}
|
||||||
|
|
||||||
return stats;
|
// Convert detailed stats to the format expected by the API
|
||||||
|
const apiStats: plugins.servezoneInterfaces.platformservice.mta.IReq_GetEMailStats['response'] = {
|
||||||
|
totalEmailsSent: detailedStats.mta?.emailsSent || 0,
|
||||||
|
totalEmailsDelivered: detailedStats.mta?.emailsSent || 0, // Default to emails sent if we don't track delivery separately
|
||||||
|
totalEmailsBounced: detailedStats.mta?.emailsFailed || 0,
|
||||||
|
averageDeliveryTimeMs: 0, // We don't track this yet
|
||||||
|
lastUpdated: new Date().toISOString()
|
||||||
|
};
|
||||||
|
|
||||||
|
return apiStats;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -3,6 +3,6 @@
|
|||||||
*/
|
*/
|
||||||
export const commitinfo = {
|
export const commitinfo = {
|
||||||
name: '@serve.zone/platformservice',
|
name: '@serve.zone/platformservice',
|
||||||
version: '2.8.6',
|
version: '2.8.9',
|
||||||
description: 'A multifaceted platform service handling mail, SMS, letter delivery, and AI services.'
|
description: 'A multifaceted platform service handling mail, SMS, letter delivery, and AI services.'
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user