import * as plugins from '../../plugins.js'; /** * Email status in the cache */ export type TCachedEmailStatus = 'pending' | 'processing' | 'queued' | 'delivered' | 'failed' | 'deferred' | 'stored' | 'accepted' | 'flagged' | 'rejected'; /** * Direction of an accepted email: 'inbound' = received from a remote peer, * 'outbound' = locally submitted for delivery. */ export type TCachedEmailDirection = 'inbound' | 'outbound'; export type TCachedEmailSecurityDisposition = 'accepted' | 'flagged' | 'rejected'; export interface ICachedEmailListFilter { direction?: TCachedEmailDirection; recipientDomain?: string; search?: string; from?: number; to?: number; } export interface ICachedEmailTrafficBucket { bucketStart: number; sent: number; received: number; failed: number; } export type TCachedEmailSmtpDeliveryPhase = 'connect' | 'greeting' | 'ehlo' | 'starttls' | 'tls_handshake' | 'post_tls_ehlo' | 'auth' | 'mail_from' | 'rcpt_to' | 'data_command' | 'message_body' | 'final_response' | 'rset' | 'quit' | 'unknown'; export interface ICachedEmailSmtpTransaction { id: string; queueItemId: string; queueAttempt: number; targetHost: string; targetPort: number; recipientDomain?: string; recipients: string[]; startedAt: string; completedAt: string; durationMs: number; outcome: 'succeeded' | 'failed'; retryable: boolean; errorType?: string; smtpCode?: number; recipientResults?: Array<{ recipient: string; accepted: boolean; responseCode: number; }>; failurePhase?: TCachedEmailSmtpDeliveryPhase; error?: string; outboundAuthentication?: ICachedEmailOutboundAuthenticationCheck; transcript: Array<{ timestampMs: number; phase: TCachedEmailSmtpDeliveryPhase; direction: 'client' | 'server' | 'system'; text: string; responseCode?: number; }>; } export interface ICachedEmailOutboundAuthenticationCheck { state: 'pending' | 'completed' | 'indeterminate' | 'not-evaluated'; overall: 'pass' | 'fail' | 'indeterminate'; checkedAt: string; signedMessageSha256?: string; error?: string; identity?: { sourceIp: string; addressFamily: 'ipv4' | 'ipv6'; heloDomain: string; receiverHostname: string; envelopeFrom: string; dkimDomain?: string; dkimSelector?: string; }; dkim?: Array<{ is_valid: boolean; domain: string | null; selector: string | null; status: string; details: string | null; }>; spf?: { result: string; domain: string; ip: string; explanation: string | null; } | null; dmarc?: { passed: boolean; policy: string; domain: string; dkim_result: string; spf_result: string; action: string; details: string | null; } | null; } /** * CachedEmail - Stores email queue items in the cache * * Used for persistent email queue storage, tracking delivery status, * and maintaining email history for the configured TTL period. */ export declare class CachedEmail extends plugins.smartdata.SmartdataCachedDocument { /** * Unique identifier for this email */ id: string; /** * Email message ID (RFC 822 Message-ID header) */ messageId: string; /** * Sender email address (envelope from) */ from: string; /** * Recipient email addresses */ to: string[]; /** * CC recipients */ cc: string[]; /** * BCC recipients */ bcc: string[]; /** * Email subject */ subject: string; /** Legacy inline RFC822 content. New messages use rawContentObjectKey. */ rawContent?: string; /** SmartBucket object key containing the raw RFC822 message. */ rawContentObjectKey?: string; /** Raw RFC822 message size in bytes. */ rawContentSize: number; /** Resolved outbound identity id that scopes a service-mail replay key. */ submissionCredentialId?: string; /** Caller-supplied replay key. It must remain absent for non-idempotent mail. */ submissionIdempotencyKey?: string; /** Digest of the exact authenticated outbound submission semantics. */ submissionDigest?: string; /** Bounded durable SMTP transaction history copied from SmartMTA. */ smtpTransactions: ICachedEmailSmtpTransaction[]; /** * Current status of the email */ status: TCachedEmailStatus; /** Attachment count derived from the parsed message at acceptance. */ attachmentCount?: number; /** JSON-serialized inbound SPF/DKIM/DMARC verdicts from the SMTP session. */ inboundSecurityResults?: string; /** Authentication disposition, kept separate from delivery/lifecycle status. */ inboundSecurityDisposition?: TCachedEmailSecurityDisposition; /** * Number of delivery attempts */ attempts: number; /** * Maximum number of delivery attempts */ maxAttempts: number; /** * Timestamp for next delivery attempt. * For SmartMTA-managed deliveries this is a RECOVERY LEASE (SmartMTA's retry * time + grace), used by the spool to detect a silently dead queue — it is * NOT the user-facing retry schedule; that lives in smartMtaNextAttempt. */ nextAttempt: Date; /** * SmartMTA's actual next scheduled retry (display value for the ops UI). * Only set while the delivery is deferred inside the SmartMTA queue. */ smartMtaNextAttempt?: Date; /** * Last error message if delivery failed */ lastError: string; /** * Timestamp when the email was successfully delivered */ deliveredAt: Date; /** * Sender domain (for querying/filtering) */ senderDomain: string; /** * Direction of the accepted message (inbound receipt vs local submission) */ direction: TCachedEmailDirection; /** * Lowercased recipient domains (for querying/filtering) */ recipientDomains: string[]; /** * Epoch ms when the message was accepted (for newest-first listings) */ acceptedAt: number; /** * Priority level (higher = more important) */ priority: number; /** * JSON-serialized route data */ routeData: string; /** * DKIM signature status */ dkimSigned: boolean; constructor(); createSavableObject(): Promise; static findBySubmissionIdempotencyKey(credentialIdArg: string, idempotencyKeyArg: string): Promise; /** * Create a new CachedEmail with a unique ID */ static createNew(): CachedEmail; /** * Find an email by ID */ static findById(id: string): Promise; /** * Find all emails with a specific status */ static findByStatus(status: TCachedEmailStatus): Promise; /** * Find all emails pending delivery (status = pending and nextAttempt <= now) */ static findPendingForDelivery(limit?: number): Promise; static findQueuedForRecovery(limit?: number): Promise; private static findLimited; private static getNativeCollection; private static buildListQuery; /** * Find the most recently accepted emails, newest first. */ static findRecent(limit?: number, filter?: ICachedEmailListFilter): Promise; static findOldestAcceptedAt(filterArg: ICachedEmailListFilter, cutoffArg: number): Promise; static aggregateEmailLogTraffic(filterArg: ICachedEmailListFilter, windowStartArg: number, windowEndArg: number, bucketSizeMsArg: number): Promise; static findRecentSecurityCandidates(limitArg: number, cutoffArg: number): Promise; /** * Find emails addressed to a recipient domain */ static findByRecipientDomain(domain: string): Promise; /** * Find emails by sender domain */ static findBySenderDomain(domain: string): Promise; /** * Mark as delivered */ markDelivered(): void; /** * Mark as terminally stored (catch-all inbound): visible in the email log, * pruned after the retention window. */ markStored(retentionMs: number): void; /** * Mark as failed with error */ markFailed(error: string): void; appendSmtpTransaction(transactionArg: ICachedEmailSmtpTransaction): void; /** * Increment attempt counter and schedule next attempt */ scheduleRetry(delayMs?: number): void; /** * Extract sender domain from email address */ updateSenderDomain(): void; /** * Derive recipient domains from the recipient address list */ updateRecipientDomains(): void; }