platformservice/ts/errors/reputation.errors.ts
2025-05-08 12:46:10 +00:00

352 lines
8.3 KiB
TypeScript

import {
PlatformError,
OperationError,
ResourceError
} from './base.errors.js';
import type { IErrorContext } from './base.errors.js';
import {
REPUTATION_CHECK_ERROR,
REPUTATION_DATA_ERROR,
REPUTATION_BLOCKLIST_ERROR,
REPUTATION_UPDATE_ERROR,
WARMUP_ALLOCATION_ERROR,
WARMUP_LIMIT_EXCEEDED,
WARMUP_SCHEDULE_ERROR
} from './error.codes.js';
/**
* Base class for reputation-related errors
*/
export class ReputationError extends OperationError {
/**
* Creates a new reputation error
*
* @param message Error message
* @param code Error code
* @param context Additional context
*/
constructor(
message: string,
code: string,
context: IErrorContext = {}
) {
super(message, code, context);
}
}
/**
* Error class for reputation check errors
*/
export class ReputationCheckError extends ReputationError {
/**
* Creates a new reputation check error
*
* @param message Error message
* @param context Additional context
*/
constructor(
message: string,
context: IErrorContext = {}
) {
super(message, REPUTATION_CHECK_ERROR, context);
}
/**
* Creates an instance for an IP reputation check error
*
* @param ip IP address
* @param provider Reputation provider
* @param originalError Original error
* @param context Additional context
*/
public static ipCheckFailed(
ip: string,
provider: string,
originalError?: Error,
context: IErrorContext = {}
): ReputationCheckError {
const errorMsg = originalError ? `: ${originalError.message}` : '';
return new ReputationCheckError(
`Failed to check reputation for IP ${ip} with provider ${provider}${errorMsg}`,
{
...context,
data: {
...context.data,
ip,
provider,
originalError: originalError ? {
message: originalError.message,
stack: originalError.stack
} : undefined
}
}
);
}
/**
* Creates an instance for a domain reputation check error
*
* @param domain Domain
* @param provider Reputation provider
* @param originalError Original error
* @param context Additional context
*/
public static domainCheckFailed(
domain: string,
provider: string,
originalError?: Error,
context: IErrorContext = {}
): ReputationCheckError {
const errorMsg = originalError ? `: ${originalError.message}` : '';
return new ReputationCheckError(
`Failed to check reputation for domain ${domain} with provider ${provider}${errorMsg}`,
{
...context,
data: {
...context.data,
domain,
provider,
originalError: originalError ? {
message: originalError.message,
stack: originalError.stack
} : undefined
}
}
);
}
}
/**
* Error class for reputation data errors
*/
export class ReputationDataError extends ReputationError {
/**
* Creates a new reputation data error
*
* @param message Error message
* @param context Additional context
*/
constructor(
message: string,
context: IErrorContext = {}
) {
super(message, REPUTATION_DATA_ERROR, context);
}
/**
* Creates an instance for a data access error
*
* @param entity Entity type (domain, ip)
* @param entityId Entity identifier
* @param operation Operation that failed (read, write, update)
* @param originalError Original error
* @param context Additional context
*/
public static dataAccessFailed(
entity: string,
entityId: string,
operation: string,
originalError?: Error,
context: IErrorContext = {}
): ReputationDataError {
const errorMsg = originalError ? `: ${originalError.message}` : '';
return new ReputationDataError(
`Failed to ${operation} reputation data for ${entity} ${entityId}${errorMsg}`,
{
...context,
data: {
...context.data,
entity,
entityId,
operation,
originalError: originalError ? {
message: originalError.message,
stack: originalError.stack
} : undefined
}
}
);
}
}
/**
* Error class for blocklist-related errors
*/
export class BlocklistError extends ReputationError {
/**
* Creates a new blocklist error
*
* @param message Error message
* @param context Additional context
*/
constructor(
message: string,
context: IErrorContext = {}
) {
super(message, REPUTATION_BLOCKLIST_ERROR, context);
}
/**
* Creates an instance for an entity found on a blocklist
*
* @param entity Entity type (domain, ip)
* @param entityId Entity identifier
* @param blocklist Blocklist name
* @param reason Reason for listing (if available)
* @param context Additional context
*/
public static entityBlocked(
entity: string,
entityId: string,
blocklist: string,
reason?: string,
context: IErrorContext = {}
): BlocklistError {
const reasonText = reason ? ` (${reason})` : '';
return new BlocklistError(
`${entity.charAt(0).toUpperCase() + entity.slice(1)} ${entityId} is listed on blocklist ${blocklist}${reasonText}`,
{
...context,
data: {
...context.data,
entity,
entityId,
blocklist,
reason
},
userMessage: `The ${entity} ${entityId} is on a blocklist. This may affect email deliverability.`
}
);
}
}
/**
* Error class for reputation update errors
*/
export class ReputationUpdateError extends ReputationError {
/**
* Creates a new reputation update error
*
* @param message Error message
* @param context Additional context
*/
constructor(
message: string,
context: IErrorContext = {}
) {
super(message, REPUTATION_UPDATE_ERROR, context);
}
}
/**
* Error class for IP warmup allocation errors
*/
export class WarmupAllocationError extends ReputationError {
/**
* Creates a new warmup allocation error
*
* @param message Error message
* @param context Additional context
*/
constructor(
message: string,
context: IErrorContext = {}
) {
super(message, WARMUP_ALLOCATION_ERROR, context);
}
/**
* Creates an instance for no available IPs
*
* @param domain Domain requesting an IP
* @param policy Allocation policy that was used
* @param context Additional context
*/
public static noAvailableIps(
domain: string,
policy: string,
context: IErrorContext = {}
): WarmupAllocationError {
return new WarmupAllocationError(
`No available IPs for domain ${domain} using ${policy} allocation policy`,
{
...context,
data: {
...context.data,
domain,
policy
},
userMessage: `No available sending IPs for ${domain}.`
}
);
}
}
/**
* Error class for IP warmup limit exceeded errors
*/
export class WarmupLimitError extends ResourceError {
/**
* Creates a new warmup limit error
*
* @param message Error message
* @param context Additional context
*/
constructor(
message: string,
context: IErrorContext = {}
) {
super(message, WARMUP_LIMIT_EXCEEDED, context);
}
/**
* Creates an instance for daily sending limit exceeded
*
* @param ip IP address
* @param domain Domain
* @param limit Daily limit
* @param sent Number of emails sent
* @param context Additional context
*/
public static dailyLimitExceeded(
ip: string,
domain: string,
limit: number,
sent: number,
context: IErrorContext = {}
): WarmupLimitError {
return new WarmupLimitError(
`Daily sending limit exceeded for IP ${ip} and domain ${domain}: ${sent}/${limit}`,
{
...context,
data: {
...context.data,
ip,
domain,
limit,
sent
},
userMessage: `Daily sending limit reached for ${domain}.`
}
);
}
}
/**
* Error class for IP warmup schedule errors
*/
export class WarmupScheduleError extends ReputationError {
/**
* Creates a new warmup schedule error
*
* @param message Error message
* @param context Additional context
*/
constructor(
message: string,
context: IErrorContext = {}
) {
super(message, WARMUP_SCHEDULE_ERROR, context);
}
}