BREAKING CHANGE(mta): migrate internal MTA to @push.rocks/smartmta and remove legacy mail/deliverability implementation

This commit is contained in:
2026-02-11 16:32:49 +00:00
parent 048f038e36
commit 530ebbf3e4
276 changed files with 1661 additions and 91193 deletions

View File

@@ -1,7 +1,7 @@
import { tap, expect } from '@git.zone/tstest/tapbundle';
import * as errors from '../ts/errors/index.js';
import {
PlatformError,
PlatformError,
ValidationError,
NetworkError,
ResourceError,
@@ -12,19 +12,6 @@ import {
ErrorCategory,
ErrorRecoverability
} from '../ts/errors/error.codes.js';
import {
EmailServiceError,
EmailTemplateError,
EmailValidationError,
EmailSendError,
EmailReceiveError
} from '../ts/errors/email.errors.js';
import {
MtaConnectionError,
MtaAuthenticationError,
MtaDeliveryError,
MtaConfigurationError
} from '../ts/errors/mta.errors.js';
import {
ErrorHandler
} from '../ts/errors/error-handler.js';
@@ -75,126 +62,6 @@ tap.test('Base error classes should set properties correctly', async () => {
expect(resourceError.category).toEqual(ErrorCategory.RESOURCE);
});
// Test 7: Error withRetry() method
tap.test('PlatformError withRetry creates new instance with retry info', async () => {
const originalError = new EmailSendError('Send failed', {
data: { someData: true }
});
const retryError = originalError.withRetry(3, 1, 1000);
// Verify it's a new instance
expect(retryError === originalError).toEqual(false);
expect(retryError).toBeInstanceOf(EmailSendError);
// Verify original data is preserved
expect(retryError.context?.data?.someData).toEqual(true);
// Verify retry info is added
expect(retryError.context?.retry?.maxRetries).toEqual(3);
expect(retryError.context?.retry?.currentRetry).toEqual(1);
expect(retryError.context?.retry?.retryDelay).toEqual(1000);
expect(retryError.context?.retry?.nextRetryAt).toBeTypeofNumber();
});
// Test email error classes
tap.test('Email error classes should be properly constructed', async () => {
try {
// Test EmailServiceError
const emailServiceError = new EmailServiceError('Email service error', {
component: 'EmailService',
operation: 'sendEmail'
});
expect(emailServiceError.code).toEqual('EMAIL_SERVICE_ERROR');
expect(emailServiceError.name).toEqual('EmailServiceError');
// Test EmailTemplateError
const templateError = new EmailTemplateError('Template not found: welcome_email', {
data: { templateId: 'welcome_email' }
});
expect(templateError.code).toEqual('EMAIL_TEMPLATE_ERROR');
expect(templateError.context.data?.templateId).toEqual('welcome_email');
// Test EmailSendError with permanent flag
const permanentError = EmailSendError.permanent(
'Invalid recipient: user@example.com',
{ data: { details: 'DNS not found', recipient: 'user@example.com' } }
);
expect(permanentError.code).toEqual('EMAIL_SEND_ERROR');
expect(permanentError.isPermanent()).toEqual(true);
expect(permanentError.context.data?.permanent).toEqual(true);
// Test EmailSendError with temporary flag and retry
const tempError = EmailSendError.temporary(
'Server busy',
3,
0,
1000,
{ data: { server: 'smtp.example.com' } }
);
expect(tempError.isPermanent()).toEqual(false);
expect(tempError.context.data?.permanent).toEqual(false);
expect(tempError.context.retry?.maxRetries).toEqual(3);
expect(tempError.shouldRetry()).toEqual(true);
} catch (error) {
console.error('Test failed with error:', error);
throw error;
}
});
// Test MTA error classes
tap.test('MTA error classes should be properly constructed', async () => {
try {
// Test MtaConnectionError
const dnsError = MtaConnectionError.dnsError('mail.example.com', new Error('DNS lookup failed'));
expect(dnsError.code).toEqual('MTA_CONNECTION_ERROR');
expect(dnsError.category).toEqual(ErrorCategory.CONNECTIVITY);
expect(dnsError.context.data?.hostname).toEqual('mail.example.com');
// Test MtaTimeoutError via MtaConnectionError.timeout
const timeoutError = MtaConnectionError.timeout('mail.example.com', 25, 30000);
expect(timeoutError.code).toEqual('MTA_CONNECTION_ERROR');
expect(timeoutError.context.data?.timeout).toEqual(30000);
// Test MtaAuthenticationError
const authError = MtaAuthenticationError.invalidCredentials('mail.example.com', 'user@example.com');
expect(authError.code).toEqual('MTA_AUTHENTICATION_ERROR');
expect(authError.category).toEqual(ErrorCategory.AUTHENTICATION);
expect(authError.context.data?.username).toEqual('user@example.com');
// Test MtaDeliveryError
const permDeliveryError = MtaDeliveryError.permanent(
'User unknown',
'nonexistent@example.com',
'550',
'550 5.1.1 User unknown',
{}
);
expect(permDeliveryError.code).toEqual('MTA_DELIVERY_ERROR');
expect(permDeliveryError.isPermanent()).toEqual(true);
expect(permDeliveryError.getRecipientAddress()).toEqual('nonexistent@example.com');
expect(permDeliveryError.getStatusCode()).toEqual('550');
// Test temporary delivery error with retry
const tempDeliveryError = MtaDeliveryError.temporary(
'Mailbox temporarily unavailable',
'user@example.com',
'450',
'450 4.2.1 Mailbox temporarily unavailable',
3,
1,
5000
);
expect(tempDeliveryError.isPermanent()).toEqual(false);
expect(tempDeliveryError.shouldRetry()).toEqual(true);
expect(tempDeliveryError.context.retry?.currentRetry).toEqual(1);
expect(tempDeliveryError.context.retry?.maxRetries).toEqual(3);
} catch (error) {
console.error('MTA test failed with error:', error);
throw error;
}
});
// Test error handler utility
tap.test('ErrorHandler should properly handle and format errors', async () => {
// Configure error handler
@@ -291,7 +158,6 @@ tap.test('ErrorHandler should properly handle and format errors', async () => {
// Test retry utilities
tap.test('Error retry utilities should work correctly', async () => {
let attempts = 0;
const start = Date.now();
try {
await errors.retry(
@@ -383,7 +249,7 @@ tap.test('Error handling can be combined with retry for robust operations', asyn
// Reset and test failure case
flaky.reset();
try {
await errors.retry(
() => flaky(5, 'never reached'),
@@ -405,4 +271,4 @@ tap.test('stop', async () => {
await tap.stopForcefully();
});
export default tap.start();
export default tap.start();