@astralibx/email-account-manager 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +118 -0
- package/dist/index.d.mts +1049 -0
- package/dist/index.d.ts +1049 -0
- package/dist/index.js +3044 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +2999 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +68 -0
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,1049 @@
|
|
|
1
|
+
import { Router } from 'express';
|
|
2
|
+
import * as mongoose from 'mongoose';
|
|
3
|
+
import { Connection, Model, HydratedDocument, Schema, Types } from 'mongoose';
|
|
4
|
+
import { Redis } from 'ioredis';
|
|
5
|
+
import { LogAdapter, AlxError } from '@astralibx/core';
|
|
6
|
+
export { LogAdapter } from '@astralibx/core';
|
|
7
|
+
import { Job } from 'bullmq';
|
|
8
|
+
|
|
9
|
+
interface WarmupPhase {
|
|
10
|
+
days: [number, number];
|
|
11
|
+
dailyLimit: number;
|
|
12
|
+
delayMinMs: number;
|
|
13
|
+
delayMaxMs: number;
|
|
14
|
+
}
|
|
15
|
+
interface EmailAccountManagerConfig {
|
|
16
|
+
db: {
|
|
17
|
+
connection: Connection;
|
|
18
|
+
collectionPrefix?: string;
|
|
19
|
+
};
|
|
20
|
+
redis: {
|
|
21
|
+
connection: Redis;
|
|
22
|
+
keyPrefix?: string;
|
|
23
|
+
};
|
|
24
|
+
logger?: LogAdapter;
|
|
25
|
+
options?: {
|
|
26
|
+
warmup?: {
|
|
27
|
+
defaultSchedule: WarmupPhase[];
|
|
28
|
+
};
|
|
29
|
+
healthDefaults?: {
|
|
30
|
+
minScore?: number;
|
|
31
|
+
maxBounceRate?: number;
|
|
32
|
+
maxConsecutiveErrors?: number;
|
|
33
|
+
};
|
|
34
|
+
ses?: {
|
|
35
|
+
enabled: boolean;
|
|
36
|
+
validateSignature?: boolean;
|
|
37
|
+
allowedTopicArns?: string[];
|
|
38
|
+
};
|
|
39
|
+
unsubscribe?: {
|
|
40
|
+
builtin?: {
|
|
41
|
+
enabled: boolean;
|
|
42
|
+
secret: string;
|
|
43
|
+
baseUrl: string;
|
|
44
|
+
tokenExpiryDays?: number;
|
|
45
|
+
};
|
|
46
|
+
generateUrl?: (email: string, accountId: string) => string;
|
|
47
|
+
};
|
|
48
|
+
queues?: {
|
|
49
|
+
sendQueueName?: string;
|
|
50
|
+
approvalQueueName?: string;
|
|
51
|
+
};
|
|
52
|
+
};
|
|
53
|
+
hooks?: {
|
|
54
|
+
onAccountDisabled?: (info: {
|
|
55
|
+
accountId: string;
|
|
56
|
+
reason: string;
|
|
57
|
+
}) => void;
|
|
58
|
+
onWarmupComplete?: (info: {
|
|
59
|
+
accountId: string;
|
|
60
|
+
email: string;
|
|
61
|
+
}) => void;
|
|
62
|
+
onHealthDegraded?: (info: {
|
|
63
|
+
accountId: string;
|
|
64
|
+
healthScore: number;
|
|
65
|
+
}) => void;
|
|
66
|
+
onSend?: (info: {
|
|
67
|
+
accountId: string;
|
|
68
|
+
email: string;
|
|
69
|
+
messageId?: string;
|
|
70
|
+
}) => void;
|
|
71
|
+
onSendError?: (info: {
|
|
72
|
+
accountId: string;
|
|
73
|
+
email: string;
|
|
74
|
+
error: string;
|
|
75
|
+
}) => void;
|
|
76
|
+
onBounce?: (info: {
|
|
77
|
+
accountId: string;
|
|
78
|
+
email: string;
|
|
79
|
+
bounceType: string;
|
|
80
|
+
provider: string;
|
|
81
|
+
}) => void;
|
|
82
|
+
onUnsubscribe?: (info: {
|
|
83
|
+
email: string;
|
|
84
|
+
accountId?: string;
|
|
85
|
+
}) => void;
|
|
86
|
+
onDelivery?: (info: {
|
|
87
|
+
accountId: string;
|
|
88
|
+
email: string;
|
|
89
|
+
}) => void;
|
|
90
|
+
onComplaint?: (info: {
|
|
91
|
+
accountId: string;
|
|
92
|
+
email: string;
|
|
93
|
+
}) => void;
|
|
94
|
+
onOpen?: (info: {
|
|
95
|
+
accountId: string;
|
|
96
|
+
email: string;
|
|
97
|
+
timestamp: Date;
|
|
98
|
+
}) => void;
|
|
99
|
+
onClick?: (info: {
|
|
100
|
+
accountId: string;
|
|
101
|
+
email: string;
|
|
102
|
+
link: string;
|
|
103
|
+
}) => void;
|
|
104
|
+
onDraftCreated?: (info: {
|
|
105
|
+
draftId: string;
|
|
106
|
+
to: string;
|
|
107
|
+
subject: string;
|
|
108
|
+
}) => void;
|
|
109
|
+
onDraftApproved?: (info: {
|
|
110
|
+
draftId: string;
|
|
111
|
+
to: string;
|
|
112
|
+
scheduledAt?: Date;
|
|
113
|
+
}) => void;
|
|
114
|
+
onDraftRejected?: (info: {
|
|
115
|
+
draftId: string;
|
|
116
|
+
to: string;
|
|
117
|
+
reason?: string;
|
|
118
|
+
}) => void;
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
interface DevModeSettings {
|
|
123
|
+
enabled: boolean;
|
|
124
|
+
testEmails: string[];
|
|
125
|
+
}
|
|
126
|
+
interface ImapSettings {
|
|
127
|
+
enabled: boolean;
|
|
128
|
+
pollIntervalMs: number;
|
|
129
|
+
searchSince: 'last_check' | 'last_24h' | 'last_7d';
|
|
130
|
+
bounceSenders: string[];
|
|
131
|
+
}
|
|
132
|
+
interface SesSettings {
|
|
133
|
+
configurationSet?: string;
|
|
134
|
+
trackOpens: boolean;
|
|
135
|
+
trackClicks: boolean;
|
|
136
|
+
}
|
|
137
|
+
interface ApprovalSendWindow {
|
|
138
|
+
timezone: string;
|
|
139
|
+
startHour: number;
|
|
140
|
+
endHour: number;
|
|
141
|
+
}
|
|
142
|
+
interface ApprovalSettings {
|
|
143
|
+
enabled: boolean;
|
|
144
|
+
defaultMode: 'manual' | 'auto';
|
|
145
|
+
autoApproveDelayMs: number;
|
|
146
|
+
sendWindow: ApprovalSendWindow;
|
|
147
|
+
spreadStrategy: 'random' | 'even';
|
|
148
|
+
maxSpreadMinutes: number;
|
|
149
|
+
}
|
|
150
|
+
interface UnsubscribePageSettings {
|
|
151
|
+
companyName: string;
|
|
152
|
+
logoUrl?: string;
|
|
153
|
+
accentColor?: string;
|
|
154
|
+
}
|
|
155
|
+
interface QueueSettings {
|
|
156
|
+
sendConcurrency: number;
|
|
157
|
+
sendAttempts: number;
|
|
158
|
+
sendBackoffMs: number;
|
|
159
|
+
approvalConcurrency: number;
|
|
160
|
+
approvalAttempts: number;
|
|
161
|
+
approvalBackoffMs: number;
|
|
162
|
+
}
|
|
163
|
+
interface GlobalSettings {
|
|
164
|
+
_id: 'global';
|
|
165
|
+
timezone: string;
|
|
166
|
+
devMode: DevModeSettings;
|
|
167
|
+
imap: ImapSettings;
|
|
168
|
+
ses: SesSettings;
|
|
169
|
+
approval: ApprovalSettings;
|
|
170
|
+
unsubscribePage: UnsubscribePageSettings;
|
|
171
|
+
queues: QueueSettings;
|
|
172
|
+
updatedAt: Date;
|
|
173
|
+
}
|
|
174
|
+
type UpdateGlobalSettingsInput = Partial<Omit<GlobalSettings, '_id' | 'updatedAt'>>;
|
|
175
|
+
|
|
176
|
+
interface IGlobalSettings extends Omit<GlobalSettings, '_id'> {
|
|
177
|
+
_id: string;
|
|
178
|
+
}
|
|
179
|
+
type GlobalSettingsDocument = HydratedDocument<IGlobalSettings>;
|
|
180
|
+
interface GlobalSettingsStatics {
|
|
181
|
+
getSettings(): Promise<GlobalSettingsDocument>;
|
|
182
|
+
updateSettings(partial: Partial<Omit<GlobalSettings, '_id' | 'updatedAt'>>): Promise<GlobalSettingsDocument>;
|
|
183
|
+
}
|
|
184
|
+
type GlobalSettingsModel = Model<IGlobalSettings> & GlobalSettingsStatics;
|
|
185
|
+
interface CreateGlobalSettingsSchemaOptions {
|
|
186
|
+
collectionName?: string;
|
|
187
|
+
}
|
|
188
|
+
declare function createGlobalSettingsSchema(options?: CreateGlobalSettingsSchemaOptions): Schema<IGlobalSettings, Model<IGlobalSettings, any, any, any, mongoose.Document<unknown, any, IGlobalSettings, any, {}> & IGlobalSettings & Required<{
|
|
189
|
+
_id: string;
|
|
190
|
+
}> & {
|
|
191
|
+
__v: number;
|
|
192
|
+
}, any>, {}, {}, {}, {}, mongoose.DefaultSchemaOptions, IGlobalSettings, mongoose.Document<unknown, {}, mongoose.FlatRecord<IGlobalSettings>, {}, mongoose.DefaultSchemaOptions> & mongoose.FlatRecord<IGlobalSettings> & Required<{
|
|
193
|
+
_id: string;
|
|
194
|
+
}> & {
|
|
195
|
+
__v: number;
|
|
196
|
+
}>;
|
|
197
|
+
|
|
198
|
+
declare class SettingsService {
|
|
199
|
+
private GlobalSettings;
|
|
200
|
+
private logger;
|
|
201
|
+
private cache;
|
|
202
|
+
constructor(GlobalSettings: GlobalSettingsModel, logger: LogAdapter);
|
|
203
|
+
get(): Promise<GlobalSettings>;
|
|
204
|
+
update(partial: UpdateGlobalSettingsInput): Promise<GlobalSettings>;
|
|
205
|
+
updateSection(section: string, data: unknown): Promise<GlobalSettings>;
|
|
206
|
+
invalidateCache(): void;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
declare const ACCOUNT_PROVIDER: {
|
|
210
|
+
readonly Gmail: "gmail";
|
|
211
|
+
readonly Ses: "ses";
|
|
212
|
+
};
|
|
213
|
+
type AccountProvider = (typeof ACCOUNT_PROVIDER)[keyof typeof ACCOUNT_PROVIDER];
|
|
214
|
+
declare const ACCOUNT_STATUS: {
|
|
215
|
+
readonly Active: "active";
|
|
216
|
+
readonly Disabled: "disabled";
|
|
217
|
+
readonly QuotaExceeded: "quota_exceeded";
|
|
218
|
+
readonly Error: "error";
|
|
219
|
+
readonly Warmup: "warmup";
|
|
220
|
+
};
|
|
221
|
+
type AccountStatus = (typeof ACCOUNT_STATUS)[keyof typeof ACCOUNT_STATUS];
|
|
222
|
+
declare const IDENTIFIER_STATUS: {
|
|
223
|
+
readonly Active: "active";
|
|
224
|
+
readonly Bounced: "bounced";
|
|
225
|
+
readonly Unsubscribed: "unsubscribed";
|
|
226
|
+
readonly Blocked: "blocked";
|
|
227
|
+
readonly Invalid: "invalid";
|
|
228
|
+
};
|
|
229
|
+
type IdentifierStatus = (typeof IDENTIFIER_STATUS)[keyof typeof IDENTIFIER_STATUS];
|
|
230
|
+
declare const BOUNCE_TYPE: {
|
|
231
|
+
readonly Hard: "hard";
|
|
232
|
+
readonly Soft: "soft";
|
|
233
|
+
readonly InboxFull: "inbox_full";
|
|
234
|
+
readonly InvalidEmail: "invalid_email";
|
|
235
|
+
};
|
|
236
|
+
type BounceType = (typeof BOUNCE_TYPE)[keyof typeof BOUNCE_TYPE];
|
|
237
|
+
declare const DRAFT_STATUS: {
|
|
238
|
+
readonly Pending: "pending";
|
|
239
|
+
readonly Approved: "approved";
|
|
240
|
+
readonly Rejected: "rejected";
|
|
241
|
+
readonly Queued: "queued";
|
|
242
|
+
readonly Sent: "sent";
|
|
243
|
+
readonly Failed: "failed";
|
|
244
|
+
};
|
|
245
|
+
type DraftStatus = (typeof DRAFT_STATUS)[keyof typeof DRAFT_STATUS];
|
|
246
|
+
declare const EMAIL_EVENT_TYPE: {
|
|
247
|
+
readonly Sent: "sent";
|
|
248
|
+
readonly Failed: "failed";
|
|
249
|
+
readonly Delivered: "delivered";
|
|
250
|
+
readonly Bounced: "bounced";
|
|
251
|
+
readonly Complained: "complained";
|
|
252
|
+
readonly Opened: "opened";
|
|
253
|
+
readonly Clicked: "clicked";
|
|
254
|
+
readonly Unsubscribed: "unsubscribed";
|
|
255
|
+
};
|
|
256
|
+
type EmailEventType = (typeof EMAIL_EVENT_TYPE)[keyof typeof EMAIL_EVENT_TYPE];
|
|
257
|
+
declare const SES_BOUNCE_TYPE: {
|
|
258
|
+
readonly Permanent: "Permanent";
|
|
259
|
+
readonly Transient: "Transient";
|
|
260
|
+
readonly Undetermined: "Undetermined";
|
|
261
|
+
};
|
|
262
|
+
type SesBounceType = (typeof SES_BOUNCE_TYPE)[keyof typeof SES_BOUNCE_TYPE];
|
|
263
|
+
declare const SES_COMPLAINT_TYPE: {
|
|
264
|
+
readonly Abuse: "abuse";
|
|
265
|
+
readonly AuthFailure: "auth-failure";
|
|
266
|
+
readonly Fraud: "fraud";
|
|
267
|
+
readonly NotSpam: "not-spam";
|
|
268
|
+
readonly Other: "other";
|
|
269
|
+
readonly Virus: "virus";
|
|
270
|
+
};
|
|
271
|
+
type SesComplaintType = (typeof SES_COMPLAINT_TYPE)[keyof typeof SES_COMPLAINT_TYPE];
|
|
272
|
+
declare const SNS_MESSAGE_TYPE: {
|
|
273
|
+
readonly Notification: "Notification";
|
|
274
|
+
readonly SubscriptionConfirmation: "SubscriptionConfirmation";
|
|
275
|
+
readonly UnsubscribeConfirmation: "UnsubscribeConfirmation";
|
|
276
|
+
};
|
|
277
|
+
type SnsMessageType = (typeof SNS_MESSAGE_TYPE)[keyof typeof SNS_MESSAGE_TYPE];
|
|
278
|
+
declare const SES_NOTIFICATION_TYPE: {
|
|
279
|
+
readonly Bounce: "Bounce";
|
|
280
|
+
readonly Complaint: "Complaint";
|
|
281
|
+
readonly Delivery: "Delivery";
|
|
282
|
+
readonly Send: "Send";
|
|
283
|
+
readonly Open: "Open";
|
|
284
|
+
readonly Click: "Click";
|
|
285
|
+
};
|
|
286
|
+
type SesNotificationType = (typeof SES_NOTIFICATION_TYPE)[keyof typeof SES_NOTIFICATION_TYPE];
|
|
287
|
+
|
|
288
|
+
interface IEmailIdentifier {
|
|
289
|
+
email: string;
|
|
290
|
+
status: IdentifierStatus;
|
|
291
|
+
sentCount: number;
|
|
292
|
+
bounceCount: number;
|
|
293
|
+
lastSentAt?: Date;
|
|
294
|
+
lastBouncedAt?: Date;
|
|
295
|
+
bounceType?: BounceType;
|
|
296
|
+
unsubscribedAt?: Date;
|
|
297
|
+
metadata?: Record<string, unknown>;
|
|
298
|
+
createdAt: Date;
|
|
299
|
+
updatedAt: Date;
|
|
300
|
+
}
|
|
301
|
+
type EmailIdentifierDocument = HydratedDocument<IEmailIdentifier>;
|
|
302
|
+
interface EmailIdentifierStatics {
|
|
303
|
+
findOrCreate(email: string): Promise<{
|
|
304
|
+
identifier: EmailIdentifierDocument;
|
|
305
|
+
created: boolean;
|
|
306
|
+
}>;
|
|
307
|
+
markBounced(email: string, bounceType: BounceType): Promise<EmailIdentifierDocument | null>;
|
|
308
|
+
markUnsubscribed(email: string): Promise<EmailIdentifierDocument | null>;
|
|
309
|
+
incrementSentCount(email: string): Promise<EmailIdentifierDocument | null>;
|
|
310
|
+
findByEmail(email: string): Promise<EmailIdentifierDocument | null>;
|
|
311
|
+
}
|
|
312
|
+
type EmailIdentifierModel = Model<IEmailIdentifier> & EmailIdentifierStatics;
|
|
313
|
+
interface CreateEmailIdentifierSchemaOptions {
|
|
314
|
+
collectionName?: string;
|
|
315
|
+
}
|
|
316
|
+
declare function createEmailIdentifierSchema(options?: CreateEmailIdentifierSchemaOptions): Schema<IEmailIdentifier, Model<IEmailIdentifier, any, any, any, mongoose.Document<unknown, any, IEmailIdentifier, any, {}> & IEmailIdentifier & {
|
|
317
|
+
_id: mongoose.Types.ObjectId;
|
|
318
|
+
} & {
|
|
319
|
+
__v: number;
|
|
320
|
+
}, any>, {}, {}, {}, {}, mongoose.DefaultSchemaOptions, IEmailIdentifier, mongoose.Document<unknown, {}, mongoose.FlatRecord<IEmailIdentifier>, {}, mongoose.DefaultSchemaOptions> & mongoose.FlatRecord<IEmailIdentifier> & {
|
|
321
|
+
_id: mongoose.Types.ObjectId;
|
|
322
|
+
} & {
|
|
323
|
+
__v: number;
|
|
324
|
+
}>;
|
|
325
|
+
|
|
326
|
+
declare class IdentifierService {
|
|
327
|
+
private EmailIdentifier;
|
|
328
|
+
private logger;
|
|
329
|
+
private hooks?;
|
|
330
|
+
constructor(EmailIdentifier: EmailIdentifierModel, logger: LogAdapter, hooks?: EmailAccountManagerConfig['hooks']);
|
|
331
|
+
findOrCreate(email: string): Promise<EmailIdentifierDocument>;
|
|
332
|
+
findByEmail(email: string): Promise<EmailIdentifierDocument | null>;
|
|
333
|
+
markBounced(email: string, bounceType: BounceType): Promise<void>;
|
|
334
|
+
markUnsubscribed(email: string): Promise<void>;
|
|
335
|
+
updateStatus(email: string, status: IdentifierStatus): Promise<void>;
|
|
336
|
+
incrementSentCount(email: string): Promise<void>;
|
|
337
|
+
merge(sourceEmail: string, targetEmail: string): Promise<void>;
|
|
338
|
+
list(filters?: {
|
|
339
|
+
status?: string;
|
|
340
|
+
}, page?: number, limit?: number): Promise<{
|
|
341
|
+
items: EmailIdentifierDocument[];
|
|
342
|
+
total: number;
|
|
343
|
+
}>;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
interface SmtpConfig {
|
|
347
|
+
host: string;
|
|
348
|
+
port: number;
|
|
349
|
+
user: string;
|
|
350
|
+
pass: string;
|
|
351
|
+
}
|
|
352
|
+
interface ImapConfig {
|
|
353
|
+
host: string;
|
|
354
|
+
port: number;
|
|
355
|
+
user: string;
|
|
356
|
+
pass: string;
|
|
357
|
+
}
|
|
358
|
+
interface SesConfig {
|
|
359
|
+
region: string;
|
|
360
|
+
configurationSet?: string;
|
|
361
|
+
}
|
|
362
|
+
interface HealthThresholds {
|
|
363
|
+
minScore: number;
|
|
364
|
+
maxBounceRate: number;
|
|
365
|
+
maxConsecutiveErrors: number;
|
|
366
|
+
}
|
|
367
|
+
interface AccountHealthData {
|
|
368
|
+
score: number;
|
|
369
|
+
consecutiveErrors: number;
|
|
370
|
+
bounceCount: number;
|
|
371
|
+
thresholds: HealthThresholds;
|
|
372
|
+
}
|
|
373
|
+
interface AccountWarmupData {
|
|
374
|
+
enabled: boolean;
|
|
375
|
+
startedAt?: Date;
|
|
376
|
+
completedAt?: Date;
|
|
377
|
+
currentDay: number;
|
|
378
|
+
schedule: WarmupPhase[];
|
|
379
|
+
}
|
|
380
|
+
interface AccountLimits {
|
|
381
|
+
dailyMax: number;
|
|
382
|
+
}
|
|
383
|
+
interface EmailAccount {
|
|
384
|
+
_id: string;
|
|
385
|
+
email: string;
|
|
386
|
+
senderName: string;
|
|
387
|
+
provider: AccountProvider;
|
|
388
|
+
status: AccountStatus;
|
|
389
|
+
smtp: SmtpConfig;
|
|
390
|
+
imap?: ImapConfig;
|
|
391
|
+
ses?: SesConfig;
|
|
392
|
+
limits: AccountLimits;
|
|
393
|
+
health: AccountHealthData;
|
|
394
|
+
warmup: AccountWarmupData;
|
|
395
|
+
totalEmailsSent: number;
|
|
396
|
+
lastSuccessfulSendAt?: Date;
|
|
397
|
+
createdAt: Date;
|
|
398
|
+
updatedAt: Date;
|
|
399
|
+
}
|
|
400
|
+
interface CreateEmailAccountInput {
|
|
401
|
+
email: string;
|
|
402
|
+
senderName: string;
|
|
403
|
+
provider: AccountProvider;
|
|
404
|
+
smtp: SmtpConfig;
|
|
405
|
+
imap?: ImapConfig;
|
|
406
|
+
ses?: SesConfig;
|
|
407
|
+
limits?: Partial<AccountLimits>;
|
|
408
|
+
warmup?: {
|
|
409
|
+
schedule?: WarmupPhase[];
|
|
410
|
+
};
|
|
411
|
+
health?: {
|
|
412
|
+
thresholds?: Partial<HealthThresholds>;
|
|
413
|
+
};
|
|
414
|
+
}
|
|
415
|
+
interface UpdateEmailAccountInput {
|
|
416
|
+
senderName?: string;
|
|
417
|
+
status?: AccountStatus;
|
|
418
|
+
smtp?: Partial<SmtpConfig>;
|
|
419
|
+
imap?: Partial<ImapConfig>;
|
|
420
|
+
ses?: Partial<SesConfig>;
|
|
421
|
+
limits?: Partial<AccountLimits>;
|
|
422
|
+
warmup?: Partial<AccountWarmupData>;
|
|
423
|
+
health?: {
|
|
424
|
+
thresholds?: Partial<HealthThresholds>;
|
|
425
|
+
};
|
|
426
|
+
}
|
|
427
|
+
interface AccountCapacity {
|
|
428
|
+
accountId: string;
|
|
429
|
+
email: string;
|
|
430
|
+
provider: AccountProvider;
|
|
431
|
+
dailyMax: number;
|
|
432
|
+
sentToday: number;
|
|
433
|
+
remaining: number;
|
|
434
|
+
usagePercent: number;
|
|
435
|
+
}
|
|
436
|
+
interface AccountHealth {
|
|
437
|
+
accountId: string;
|
|
438
|
+
email: string;
|
|
439
|
+
score: number;
|
|
440
|
+
consecutiveErrors: number;
|
|
441
|
+
bounceCount: number;
|
|
442
|
+
thresholds: HealthThresholds;
|
|
443
|
+
status: AccountStatus;
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
interface IEmailAccount {
|
|
447
|
+
email: string;
|
|
448
|
+
senderName: string;
|
|
449
|
+
provider: AccountProvider;
|
|
450
|
+
status: AccountStatus;
|
|
451
|
+
smtp: {
|
|
452
|
+
host: string;
|
|
453
|
+
port: number;
|
|
454
|
+
user: string;
|
|
455
|
+
pass: string;
|
|
456
|
+
};
|
|
457
|
+
imap?: {
|
|
458
|
+
host: string;
|
|
459
|
+
port: number;
|
|
460
|
+
user: string;
|
|
461
|
+
pass: string;
|
|
462
|
+
};
|
|
463
|
+
ses?: {
|
|
464
|
+
region: string;
|
|
465
|
+
configurationSet?: string;
|
|
466
|
+
};
|
|
467
|
+
limits: {
|
|
468
|
+
dailyMax: number;
|
|
469
|
+
};
|
|
470
|
+
health: {
|
|
471
|
+
score: number;
|
|
472
|
+
consecutiveErrors: number;
|
|
473
|
+
bounceCount: number;
|
|
474
|
+
thresholds: {
|
|
475
|
+
minScore: number;
|
|
476
|
+
maxBounceRate: number;
|
|
477
|
+
maxConsecutiveErrors: number;
|
|
478
|
+
};
|
|
479
|
+
};
|
|
480
|
+
warmup: {
|
|
481
|
+
enabled: boolean;
|
|
482
|
+
startedAt?: Date;
|
|
483
|
+
completedAt?: Date;
|
|
484
|
+
currentDay: number;
|
|
485
|
+
schedule: WarmupPhase[];
|
|
486
|
+
};
|
|
487
|
+
totalEmailsSent: number;
|
|
488
|
+
lastSuccessfulSendAt?: Date;
|
|
489
|
+
lastImapCheckAt?: Date;
|
|
490
|
+
createdAt: Date;
|
|
491
|
+
updatedAt: Date;
|
|
492
|
+
}
|
|
493
|
+
type EmailAccountDocument = HydratedDocument<IEmailAccount>;
|
|
494
|
+
interface EmailAccountStatics {
|
|
495
|
+
findActive(): Promise<EmailAccountDocument[]>;
|
|
496
|
+
findByProvider(provider: AccountProvider): Promise<EmailAccountDocument[]>;
|
|
497
|
+
findByEmail(email: string): Promise<EmailAccountDocument | null>;
|
|
498
|
+
getBestAvailable(): Promise<EmailAccountDocument | null>;
|
|
499
|
+
}
|
|
500
|
+
type EmailAccountModel = Model<IEmailAccount> & EmailAccountStatics;
|
|
501
|
+
interface CreateEmailAccountSchemaOptions {
|
|
502
|
+
collectionName?: string;
|
|
503
|
+
}
|
|
504
|
+
declare function createEmailAccountSchema(options?: CreateEmailAccountSchemaOptions): Schema<IEmailAccount, Model<IEmailAccount, any, any, any, mongoose.Document<unknown, any, IEmailAccount, any, {}> & IEmailAccount & {
|
|
505
|
+
_id: mongoose.Types.ObjectId;
|
|
506
|
+
} & {
|
|
507
|
+
__v: number;
|
|
508
|
+
}, any>, {}, {}, {}, {}, mongoose.DefaultSchemaOptions, IEmailAccount, mongoose.Document<unknown, {}, mongoose.FlatRecord<IEmailAccount>, {}, mongoose.DefaultSchemaOptions> & mongoose.FlatRecord<IEmailAccount> & {
|
|
509
|
+
_id: mongoose.Types.ObjectId;
|
|
510
|
+
} & {
|
|
511
|
+
__v: number;
|
|
512
|
+
}>;
|
|
513
|
+
|
|
514
|
+
interface IEmailDailyStats {
|
|
515
|
+
accountId: Types.ObjectId;
|
|
516
|
+
date: string;
|
|
517
|
+
sent: number;
|
|
518
|
+
failed: number;
|
|
519
|
+
bounced: number;
|
|
520
|
+
delivered: number;
|
|
521
|
+
complained: number;
|
|
522
|
+
opened: number;
|
|
523
|
+
clicked: number;
|
|
524
|
+
unsubscribed: number;
|
|
525
|
+
createdAt: Date;
|
|
526
|
+
updatedAt: Date;
|
|
527
|
+
}
|
|
528
|
+
type EmailDailyStatsDocument = HydratedDocument<IEmailDailyStats>;
|
|
529
|
+
interface EmailDailyStatsStatics {
|
|
530
|
+
incrementStat(accountId: string, field: string, count?: number, date?: string): Promise<EmailDailyStatsDocument>;
|
|
531
|
+
getForAccount(accountId: string, days?: number): Promise<EmailDailyStatsDocument[]>;
|
|
532
|
+
getForDate(date: string): Promise<EmailDailyStatsDocument[]>;
|
|
533
|
+
}
|
|
534
|
+
type EmailDailyStatsModel = Model<IEmailDailyStats> & EmailDailyStatsStatics;
|
|
535
|
+
interface CreateEmailDailyStatsSchemaOptions {
|
|
536
|
+
collectionName?: string;
|
|
537
|
+
}
|
|
538
|
+
declare function createEmailDailyStatsSchema(options?: CreateEmailDailyStatsSchemaOptions): Schema<IEmailDailyStats, Model<IEmailDailyStats, any, any, any, mongoose.Document<unknown, any, IEmailDailyStats, any, {}> & IEmailDailyStats & {
|
|
539
|
+
_id: Types.ObjectId;
|
|
540
|
+
} & {
|
|
541
|
+
__v: number;
|
|
542
|
+
}, any>, {}, {}, {}, {}, mongoose.DefaultSchemaOptions, IEmailDailyStats, mongoose.Document<unknown, {}, mongoose.FlatRecord<IEmailDailyStats>, {}, mongoose.DefaultSchemaOptions> & mongoose.FlatRecord<IEmailDailyStats> & {
|
|
543
|
+
_id: Types.ObjectId;
|
|
544
|
+
} & {
|
|
545
|
+
__v: number;
|
|
546
|
+
}>;
|
|
547
|
+
|
|
548
|
+
declare class HealthTracker {
|
|
549
|
+
private EmailAccount;
|
|
550
|
+
private EmailDailyStats;
|
|
551
|
+
private settings;
|
|
552
|
+
private logger;
|
|
553
|
+
private hooks?;
|
|
554
|
+
constructor(EmailAccount: EmailAccountModel, EmailDailyStats: EmailDailyStatsModel, settings: SettingsService, logger: LogAdapter, hooks?: EmailAccountManagerConfig['hooks']);
|
|
555
|
+
recordSuccess(accountId: string): Promise<void>;
|
|
556
|
+
recordError(accountId: string, error: string): Promise<void>;
|
|
557
|
+
recordBounce(accountId: string, email: string, bounceType: BounceType): Promise<void>;
|
|
558
|
+
getHealth(accountId: string): Promise<AccountHealth | null>;
|
|
559
|
+
getAllHealth(): Promise<AccountHealth[]>;
|
|
560
|
+
private toAccountHealth;
|
|
561
|
+
private getTodayDateString;
|
|
562
|
+
private incrementDailyStat;
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
interface WarmupStatus {
|
|
566
|
+
accountId: string;
|
|
567
|
+
email: string;
|
|
568
|
+
enabled: boolean;
|
|
569
|
+
currentDay: number;
|
|
570
|
+
startedAt?: Date;
|
|
571
|
+
completedAt?: Date;
|
|
572
|
+
currentPhase: WarmupPhase | null;
|
|
573
|
+
dailyLimit: number;
|
|
574
|
+
delayRange: {
|
|
575
|
+
min: number;
|
|
576
|
+
max: number;
|
|
577
|
+
};
|
|
578
|
+
}
|
|
579
|
+
declare class WarmupManager {
|
|
580
|
+
private EmailAccount;
|
|
581
|
+
private config;
|
|
582
|
+
private logger;
|
|
583
|
+
private hooks?;
|
|
584
|
+
constructor(EmailAccount: EmailAccountModel, config: EmailAccountManagerConfig, logger: LogAdapter, hooks?: EmailAccountManagerConfig['hooks']);
|
|
585
|
+
startWarmup(accountId: string): Promise<void>;
|
|
586
|
+
completeWarmup(accountId: string): Promise<void>;
|
|
587
|
+
resetWarmup(accountId: string): Promise<void>;
|
|
588
|
+
getCurrentPhase(accountId: string): Promise<WarmupPhase | null>;
|
|
589
|
+
getRecommendedDelay(accountId: string): Promise<number>;
|
|
590
|
+
getDailyLimit(accountId: string): Promise<number>;
|
|
591
|
+
advanceDay(accountId: string): Promise<void>;
|
|
592
|
+
getStatus(accountId: string): Promise<WarmupStatus | null>;
|
|
593
|
+
updateSchedule(accountId: string, schedule: WarmupPhase[]): Promise<void>;
|
|
594
|
+
private findPhaseForDay;
|
|
595
|
+
private getMaxDay;
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
declare class CapacityManager {
|
|
599
|
+
private EmailAccount;
|
|
600
|
+
private EmailDailyStats;
|
|
601
|
+
private warmupManager;
|
|
602
|
+
private settings;
|
|
603
|
+
private logger;
|
|
604
|
+
constructor(EmailAccount: EmailAccountModel, EmailDailyStats: EmailDailyStatsModel, warmupManager: WarmupManager, settings: SettingsService, logger: LogAdapter);
|
|
605
|
+
getBestAccount(): Promise<EmailAccountDocument | null>;
|
|
606
|
+
getAccountCapacity(accountId: string): Promise<AccountCapacity>;
|
|
607
|
+
getAllCapacity(): Promise<{
|
|
608
|
+
accounts: AccountCapacity[];
|
|
609
|
+
totalRemaining: number;
|
|
610
|
+
}>;
|
|
611
|
+
private getSentToday;
|
|
612
|
+
private getDailyLimit;
|
|
613
|
+
private getTodayDateString;
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
declare class UnsubscribeService {
|
|
617
|
+
private EmailIdentifier;
|
|
618
|
+
private config;
|
|
619
|
+
private logger;
|
|
620
|
+
private hooks?;
|
|
621
|
+
constructor(EmailIdentifier: EmailIdentifierModel, config: EmailAccountManagerConfig, logger: LogAdapter, hooks?: EmailAccountManagerConfig['hooks']);
|
|
622
|
+
generateUrl(email: string, accountId?: string): string;
|
|
623
|
+
generateToken(email: string): string;
|
|
624
|
+
verifyToken(email: string, token: string): boolean;
|
|
625
|
+
handleUnsubscribe(email: string, token: string): Promise<{
|
|
626
|
+
success: boolean;
|
|
627
|
+
error?: string;
|
|
628
|
+
email?: string;
|
|
629
|
+
}>;
|
|
630
|
+
getConfirmationHtml(email: string, success: boolean): string;
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
interface QueueStats {
|
|
634
|
+
waiting: number;
|
|
635
|
+
active: number;
|
|
636
|
+
completed: number;
|
|
637
|
+
failed: number;
|
|
638
|
+
delayed: number;
|
|
639
|
+
}
|
|
640
|
+
interface SendJobData {
|
|
641
|
+
accountId: string;
|
|
642
|
+
to: string;
|
|
643
|
+
subject: string;
|
|
644
|
+
html: string;
|
|
645
|
+
text: string;
|
|
646
|
+
unsubscribeUrl?: string;
|
|
647
|
+
metadata?: Record<string, unknown>;
|
|
648
|
+
}
|
|
649
|
+
interface ApprovalJobData {
|
|
650
|
+
draftId: string;
|
|
651
|
+
scheduledAt?: string;
|
|
652
|
+
}
|
|
653
|
+
declare class QueueService {
|
|
654
|
+
private redis;
|
|
655
|
+
private config;
|
|
656
|
+
private settings;
|
|
657
|
+
private logger;
|
|
658
|
+
private sendQueue;
|
|
659
|
+
private approvalQueue;
|
|
660
|
+
private sendWorker;
|
|
661
|
+
private approvalWorker;
|
|
662
|
+
constructor(redis: Redis, config: EmailAccountManagerConfig, settings: SettingsService, logger: LogAdapter);
|
|
663
|
+
init(processors: {
|
|
664
|
+
sendProcessor: (job: Job) => Promise<void>;
|
|
665
|
+
approvalProcessor: (job: Job) => Promise<void>;
|
|
666
|
+
}): Promise<void>;
|
|
667
|
+
enqueueSend(data: SendJobData): Promise<string>;
|
|
668
|
+
enqueueApproval(data: ApprovalJobData): Promise<string>;
|
|
669
|
+
getStats(): Promise<{
|
|
670
|
+
send: QueueStats;
|
|
671
|
+
approval: QueueStats;
|
|
672
|
+
}>;
|
|
673
|
+
pause(queue: 'send' | 'approval'): Promise<void>;
|
|
674
|
+
resume(queue: 'send' | 'approval'): Promise<void>;
|
|
675
|
+
close(): Promise<void>;
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
interface SmtpSendParams {
|
|
679
|
+
accountId?: string;
|
|
680
|
+
to: string;
|
|
681
|
+
subject: string;
|
|
682
|
+
html: string;
|
|
683
|
+
text?: string;
|
|
684
|
+
metadata?: Record<string, unknown>;
|
|
685
|
+
}
|
|
686
|
+
interface SmtpSendResult {
|
|
687
|
+
success: boolean;
|
|
688
|
+
messageId?: string;
|
|
689
|
+
error?: string;
|
|
690
|
+
draftId?: string;
|
|
691
|
+
}
|
|
692
|
+
declare class SmtpService {
|
|
693
|
+
private EmailAccount;
|
|
694
|
+
private capacityManager;
|
|
695
|
+
private healthTracker;
|
|
696
|
+
private identifierService;
|
|
697
|
+
private unsubscribeService;
|
|
698
|
+
private queueService;
|
|
699
|
+
private settings;
|
|
700
|
+
private config;
|
|
701
|
+
private logger;
|
|
702
|
+
private hooks?;
|
|
703
|
+
private devRoundRobinIndex;
|
|
704
|
+
private transporterPool;
|
|
705
|
+
constructor(EmailAccount: EmailAccountModel, capacityManager: CapacityManager, healthTracker: HealthTracker, identifierService: IdentifierService, unsubscribeService: UnsubscribeService, queueService: QueueService, settings: SettingsService, config: EmailAccountManagerConfig, logger: LogAdapter, hooks?: EmailAccountManagerConfig['hooks']);
|
|
706
|
+
send(params: SmtpSendParams): Promise<SmtpSendResult>;
|
|
707
|
+
testConnection(accountId: string): Promise<{
|
|
708
|
+
success: boolean;
|
|
709
|
+
error?: string;
|
|
710
|
+
}>;
|
|
711
|
+
executeSend(accountId: string, to: string, subject: string, html: string, text: string, unsubscribeUrl?: string): Promise<SmtpSendResult>;
|
|
712
|
+
closeAll(): void;
|
|
713
|
+
private getOrCreateTransporter;
|
|
714
|
+
private createTransporter;
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
interface EmailDraft {
|
|
718
|
+
_id: string;
|
|
719
|
+
to: string;
|
|
720
|
+
subject: string;
|
|
721
|
+
htmlBody: string;
|
|
722
|
+
textBody?: string;
|
|
723
|
+
accountId: string;
|
|
724
|
+
status: DraftStatus;
|
|
725
|
+
approvedAt?: Date;
|
|
726
|
+
rejectedAt?: Date;
|
|
727
|
+
rejectionReason?: string;
|
|
728
|
+
sentAt?: Date;
|
|
729
|
+
scheduledAt?: Date;
|
|
730
|
+
failureReason?: string;
|
|
731
|
+
metadata?: Record<string, unknown>;
|
|
732
|
+
createdAt: Date;
|
|
733
|
+
updatedAt: Date;
|
|
734
|
+
}
|
|
735
|
+
interface CreateDraftInput {
|
|
736
|
+
to: string;
|
|
737
|
+
subject: string;
|
|
738
|
+
htmlBody: string;
|
|
739
|
+
textBody?: string;
|
|
740
|
+
accountId: string;
|
|
741
|
+
scheduledAt?: Date;
|
|
742
|
+
metadata?: Record<string, unknown>;
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
interface IEmailDraft {
|
|
746
|
+
to: string;
|
|
747
|
+
subject: string;
|
|
748
|
+
htmlBody: string;
|
|
749
|
+
textBody?: string;
|
|
750
|
+
accountId: Types.ObjectId;
|
|
751
|
+
status: DraftStatus;
|
|
752
|
+
approvedAt?: Date;
|
|
753
|
+
rejectedAt?: Date;
|
|
754
|
+
rejectionReason?: string;
|
|
755
|
+
sentAt?: Date;
|
|
756
|
+
scheduledAt?: Date;
|
|
757
|
+
failureReason?: string;
|
|
758
|
+
metadata?: Record<string, unknown>;
|
|
759
|
+
createdAt: Date;
|
|
760
|
+
updatedAt: Date;
|
|
761
|
+
}
|
|
762
|
+
type EmailDraftDocument = HydratedDocument<IEmailDraft>;
|
|
763
|
+
interface EmailDraftStatics {
|
|
764
|
+
findPending(limit?: number): Promise<EmailDraftDocument[]>;
|
|
765
|
+
findByStatus(status: DraftStatus, limit?: number): Promise<EmailDraftDocument[]>;
|
|
766
|
+
countByStatus(): Promise<Record<string, number>>;
|
|
767
|
+
}
|
|
768
|
+
type EmailDraftModel = Model<IEmailDraft> & EmailDraftStatics;
|
|
769
|
+
interface CreateEmailDraftSchemaOptions {
|
|
770
|
+
collectionName?: string;
|
|
771
|
+
}
|
|
772
|
+
declare function createEmailDraftSchema(options?: CreateEmailDraftSchemaOptions): Schema<IEmailDraft, Model<IEmailDraft, any, any, any, mongoose.Document<unknown, any, IEmailDraft, any, {}> & IEmailDraft & {
|
|
773
|
+
_id: Types.ObjectId;
|
|
774
|
+
} & {
|
|
775
|
+
__v: number;
|
|
776
|
+
}, any>, {}, {}, {}, {}, mongoose.DefaultSchemaOptions, IEmailDraft, mongoose.Document<unknown, {}, mongoose.FlatRecord<IEmailDraft>, {}, mongoose.DefaultSchemaOptions> & mongoose.FlatRecord<IEmailDraft> & {
|
|
777
|
+
_id: Types.ObjectId;
|
|
778
|
+
} & {
|
|
779
|
+
__v: number;
|
|
780
|
+
}>;
|
|
781
|
+
|
|
782
|
+
declare class ApprovalService {
|
|
783
|
+
private EmailDraft;
|
|
784
|
+
private queueService;
|
|
785
|
+
private settings;
|
|
786
|
+
private logger;
|
|
787
|
+
private hooks?;
|
|
788
|
+
constructor(EmailDraft: EmailDraftModel, queueService: QueueService, settings: SettingsService, logger: LogAdapter, hooks?: EmailAccountManagerConfig['hooks']);
|
|
789
|
+
createDraft(input: CreateDraftInput): Promise<EmailDraftDocument>;
|
|
790
|
+
approve(draftId: string): Promise<void>;
|
|
791
|
+
reject(draftId: string, reason?: string): Promise<void>;
|
|
792
|
+
bulkApprove(draftIds: string[]): Promise<void>;
|
|
793
|
+
bulkReject(draftIds: string[], reason?: string): Promise<void>;
|
|
794
|
+
sendNow(draftId: string): Promise<void>;
|
|
795
|
+
updateContent(draftId: string, content: {
|
|
796
|
+
subject?: string;
|
|
797
|
+
htmlBody?: string;
|
|
798
|
+
textBody?: string;
|
|
799
|
+
}): Promise<EmailDraftDocument>;
|
|
800
|
+
getDrafts(filters?: {
|
|
801
|
+
status?: string;
|
|
802
|
+
}, page?: number, limit?: number): Promise<{
|
|
803
|
+
items: EmailDraftDocument[];
|
|
804
|
+
total: number;
|
|
805
|
+
}>;
|
|
806
|
+
getDraftById(draftId: string): Promise<EmailDraftDocument | null>;
|
|
807
|
+
countByStatus(): Promise<Record<string, number>>;
|
|
808
|
+
private calculateScheduledTime;
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
declare class ImapBounceChecker {
|
|
812
|
+
private EmailAccount;
|
|
813
|
+
private healthTracker;
|
|
814
|
+
private identifierService;
|
|
815
|
+
private settings;
|
|
816
|
+
private logger;
|
|
817
|
+
private hooks?;
|
|
818
|
+
private polling;
|
|
819
|
+
constructor(EmailAccount: EmailAccountModel, healthTracker: HealthTracker, identifierService: IdentifierService, settings: SettingsService, logger: LogAdapter, hooks?: EmailAccountManagerConfig['hooks']);
|
|
820
|
+
start(): Promise<void>;
|
|
821
|
+
stop(): void;
|
|
822
|
+
checkNow(): Promise<void>;
|
|
823
|
+
checkAccount(accountId: string): Promise<{
|
|
824
|
+
bouncesFound: number;
|
|
825
|
+
}>;
|
|
826
|
+
private classifyBounce;
|
|
827
|
+
private getSearchDate;
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
interface EmailIdentifier {
|
|
831
|
+
_id: string;
|
|
832
|
+
email: string;
|
|
833
|
+
status: IdentifierStatus;
|
|
834
|
+
sentCount: number;
|
|
835
|
+
bounceCount: number;
|
|
836
|
+
lastSentAt?: Date;
|
|
837
|
+
lastBouncedAt?: Date;
|
|
838
|
+
bounceType?: BounceType;
|
|
839
|
+
unsubscribedAt?: Date;
|
|
840
|
+
metadata?: Record<string, unknown>;
|
|
841
|
+
createdAt: Date;
|
|
842
|
+
updatedAt: Date;
|
|
843
|
+
}
|
|
844
|
+
interface CreateIdentifierInput {
|
|
845
|
+
email: string;
|
|
846
|
+
status?: IdentifierStatus;
|
|
847
|
+
metadata?: Record<string, unknown>;
|
|
848
|
+
}
|
|
849
|
+
interface UpdateIdentifierInput {
|
|
850
|
+
status?: IdentifierStatus;
|
|
851
|
+
bounceType?: BounceType;
|
|
852
|
+
metadata?: Record<string, unknown>;
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
interface EmailEvent {
|
|
856
|
+
type: EmailEventType;
|
|
857
|
+
accountId: string;
|
|
858
|
+
email: string;
|
|
859
|
+
provider: AccountProvider;
|
|
860
|
+
bounceType?: BounceType;
|
|
861
|
+
link?: string;
|
|
862
|
+
timestamp: Date;
|
|
863
|
+
metadata?: Record<string, unknown>;
|
|
864
|
+
}
|
|
865
|
+
interface SnsMessage {
|
|
866
|
+
Type: SnsMessageType;
|
|
867
|
+
MessageId: string;
|
|
868
|
+
TopicArn: string;
|
|
869
|
+
Subject?: string;
|
|
870
|
+
Message: string;
|
|
871
|
+
Timestamp: string;
|
|
872
|
+
SignatureVersion: string;
|
|
873
|
+
Signature: string;
|
|
874
|
+
SigningCertURL: string;
|
|
875
|
+
SubscribeURL?: string;
|
|
876
|
+
UnsubscribeURL?: string;
|
|
877
|
+
Token?: string;
|
|
878
|
+
}
|
|
879
|
+
interface SesBounceRecipient {
|
|
880
|
+
emailAddress: string;
|
|
881
|
+
action?: string;
|
|
882
|
+
status?: string;
|
|
883
|
+
diagnosticCode?: string;
|
|
884
|
+
}
|
|
885
|
+
interface SesComplaintRecipient {
|
|
886
|
+
emailAddress: string;
|
|
887
|
+
}
|
|
888
|
+
interface SesMailPayload {
|
|
889
|
+
messageId: string;
|
|
890
|
+
timestamp: string;
|
|
891
|
+
source: string;
|
|
892
|
+
sourceArn?: string;
|
|
893
|
+
sendingAccountId?: string;
|
|
894
|
+
destination: string[];
|
|
895
|
+
headersTruncated?: boolean;
|
|
896
|
+
headers?: Array<{
|
|
897
|
+
name: string;
|
|
898
|
+
value: string;
|
|
899
|
+
}>;
|
|
900
|
+
commonHeaders?: {
|
|
901
|
+
from?: string[];
|
|
902
|
+
to?: string[];
|
|
903
|
+
subject?: string;
|
|
904
|
+
messageId?: string;
|
|
905
|
+
};
|
|
906
|
+
}
|
|
907
|
+
interface SesBounce {
|
|
908
|
+
bounceType: SesBounceType;
|
|
909
|
+
bounceSubType: string;
|
|
910
|
+
bouncedRecipients: SesBounceRecipient[];
|
|
911
|
+
timestamp: string;
|
|
912
|
+
feedbackId?: string;
|
|
913
|
+
remoteMtaIp?: string;
|
|
914
|
+
reportingMTA?: string;
|
|
915
|
+
}
|
|
916
|
+
interface SesComplaint {
|
|
917
|
+
complainedRecipients: SesComplaintRecipient[];
|
|
918
|
+
timestamp: string;
|
|
919
|
+
complaintFeedbackType?: SesComplaintType;
|
|
920
|
+
feedbackId?: string;
|
|
921
|
+
userAgent?: string;
|
|
922
|
+
arrivalDate?: string;
|
|
923
|
+
}
|
|
924
|
+
interface SesDelivery {
|
|
925
|
+
timestamp: string;
|
|
926
|
+
processingTimeMillis: number;
|
|
927
|
+
recipients: string[];
|
|
928
|
+
smtpResponse: string;
|
|
929
|
+
reportingMTA?: string;
|
|
930
|
+
}
|
|
931
|
+
interface SesOpen {
|
|
932
|
+
ipAddress: string;
|
|
933
|
+
timestamp: string;
|
|
934
|
+
userAgent: string;
|
|
935
|
+
}
|
|
936
|
+
interface SesClick {
|
|
937
|
+
ipAddress: string;
|
|
938
|
+
timestamp: string;
|
|
939
|
+
userAgent: string;
|
|
940
|
+
link: string;
|
|
941
|
+
linkTags?: Record<string, string[]>;
|
|
942
|
+
}
|
|
943
|
+
interface SesNotification {
|
|
944
|
+
notificationType: SesNotificationType;
|
|
945
|
+
mail: SesMailPayload;
|
|
946
|
+
bounce?: SesBounce;
|
|
947
|
+
complaint?: SesComplaint;
|
|
948
|
+
delivery?: SesDelivery;
|
|
949
|
+
open?: SesOpen;
|
|
950
|
+
click?: SesClick;
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
declare class AlxAccountError extends AlxError {
|
|
954
|
+
readonly code: string;
|
|
955
|
+
constructor(message: string, code: string);
|
|
956
|
+
}
|
|
957
|
+
declare class ConfigValidationError extends AlxAccountError {
|
|
958
|
+
readonly field: string;
|
|
959
|
+
constructor(message: string, field: string);
|
|
960
|
+
}
|
|
961
|
+
declare class AccountDisabledError extends AlxAccountError {
|
|
962
|
+
readonly accountId: string;
|
|
963
|
+
readonly reason: string;
|
|
964
|
+
constructor(accountId: string, reason: string);
|
|
965
|
+
}
|
|
966
|
+
declare class NoAvailableAccountError extends AlxAccountError {
|
|
967
|
+
constructor();
|
|
968
|
+
}
|
|
969
|
+
declare class SmtpConnectionError extends AlxAccountError {
|
|
970
|
+
readonly accountId: string;
|
|
971
|
+
readonly originalError: Error;
|
|
972
|
+
constructor(accountId: string, originalError: Error);
|
|
973
|
+
}
|
|
974
|
+
declare class InvalidTokenError extends AlxAccountError {
|
|
975
|
+
readonly tokenType: 'unsubscribe';
|
|
976
|
+
constructor(tokenType: 'unsubscribe');
|
|
977
|
+
}
|
|
978
|
+
declare class QuotaExceededError extends AlxAccountError {
|
|
979
|
+
readonly accountId: string;
|
|
980
|
+
readonly dailyMax: number;
|
|
981
|
+
readonly currentSent: number;
|
|
982
|
+
constructor(accountId: string, dailyMax: number, currentSent: number);
|
|
983
|
+
}
|
|
984
|
+
declare class SnsSignatureError extends AlxAccountError {
|
|
985
|
+
constructor();
|
|
986
|
+
}
|
|
987
|
+
declare class AccountNotFoundError extends AlxAccountError {
|
|
988
|
+
readonly accountId: string;
|
|
989
|
+
constructor(accountId: string);
|
|
990
|
+
}
|
|
991
|
+
declare class DraftNotFoundError extends AlxAccountError {
|
|
992
|
+
readonly draftId: string;
|
|
993
|
+
constructor(draftId: string);
|
|
994
|
+
}
|
|
995
|
+
|
|
996
|
+
declare function validateConfig(raw: unknown): void;
|
|
997
|
+
|
|
998
|
+
interface WebhookProcessResult {
|
|
999
|
+
processed: boolean;
|
|
1000
|
+
type?: string;
|
|
1001
|
+
error?: string;
|
|
1002
|
+
}
|
|
1003
|
+
declare class SesWebhookHandler {
|
|
1004
|
+
private healthTracker;
|
|
1005
|
+
private identifierService;
|
|
1006
|
+
private EmailAccount;
|
|
1007
|
+
private config;
|
|
1008
|
+
private logger;
|
|
1009
|
+
private hooks?;
|
|
1010
|
+
constructor(healthTracker: HealthTracker, identifierService: IdentifierService, EmailAccount: EmailAccountModel, config: EmailAccountManagerConfig, logger: LogAdapter, hooks?: EmailAccountManagerConfig['hooks']);
|
|
1011
|
+
handleSnsMessage(body: unknown): Promise<WebhookProcessResult>;
|
|
1012
|
+
private handleSubscriptionConfirmation;
|
|
1013
|
+
private processNotification;
|
|
1014
|
+
private processBounce;
|
|
1015
|
+
private processComplaint;
|
|
1016
|
+
private validateSignature;
|
|
1017
|
+
private fetchCertificate;
|
|
1018
|
+
private parseBody;
|
|
1019
|
+
private findAccountIdBySource;
|
|
1020
|
+
}
|
|
1021
|
+
|
|
1022
|
+
interface EmailAccountManager {
|
|
1023
|
+
routes: Router;
|
|
1024
|
+
webhookRoutes: {
|
|
1025
|
+
ses: Router;
|
|
1026
|
+
};
|
|
1027
|
+
unsubscribeRoutes: Router;
|
|
1028
|
+
accounts: {
|
|
1029
|
+
model: any;
|
|
1030
|
+
create: (data: any) => Promise<any>;
|
|
1031
|
+
findById: (id: string) => Promise<any>;
|
|
1032
|
+
update: (id: string, data: any) => Promise<any>;
|
|
1033
|
+
remove: (id: string) => Promise<any>;
|
|
1034
|
+
};
|
|
1035
|
+
capacity: CapacityManager;
|
|
1036
|
+
health: HealthTracker;
|
|
1037
|
+
warmup: WarmupManager;
|
|
1038
|
+
smtp: SmtpService;
|
|
1039
|
+
imap: ImapBounceChecker;
|
|
1040
|
+
approval: ApprovalService;
|
|
1041
|
+
unsubscribe: UnsubscribeService;
|
|
1042
|
+
identifiers: IdentifierService;
|
|
1043
|
+
queues: QueueService;
|
|
1044
|
+
settings: SettingsService;
|
|
1045
|
+
destroy(): Promise<void>;
|
|
1046
|
+
}
|
|
1047
|
+
declare function createEmailAccountManager(config: EmailAccountManagerConfig): EmailAccountManager;
|
|
1048
|
+
|
|
1049
|
+
export { ACCOUNT_PROVIDER, ACCOUNT_STATUS, type AccountCapacity, AccountDisabledError, type AccountHealth, type AccountHealthData, type AccountLimits, AccountNotFoundError, type AccountProvider, type AccountStatus, type AccountWarmupData, AlxAccountError, type ApprovalJobData, type ApprovalSendWindow, ApprovalService, type ApprovalSettings, BOUNCE_TYPE, type BounceType, CapacityManager, ConfigValidationError, type CreateDraftInput, type CreateEmailAccountInput, type CreateEmailAccountSchemaOptions, type CreateEmailDailyStatsSchemaOptions, type CreateEmailDraftSchemaOptions, type CreateEmailIdentifierSchemaOptions, type CreateGlobalSettingsSchemaOptions, type CreateIdentifierInput, DRAFT_STATUS, type DevModeSettings, DraftNotFoundError, type DraftStatus, EMAIL_EVENT_TYPE, type EmailAccount, type EmailAccountDocument, type EmailAccountManager, type EmailAccountManagerConfig, type EmailAccountModel, type EmailAccountStatics, type EmailDailyStatsDocument, type EmailDailyStatsModel, type EmailDailyStatsStatics, type EmailDraft, type EmailDraftDocument, type EmailDraftModel, type EmailDraftStatics, type EmailEvent, type EmailEventType, type EmailIdentifier, type EmailIdentifierDocument, type EmailIdentifierModel, type EmailIdentifierStatics, type GlobalSettings, type GlobalSettingsDocument, type GlobalSettingsModel, type GlobalSettingsStatics, type HealthThresholds, HealthTracker, IDENTIFIER_STATUS, type IEmailAccount, type IEmailDailyStats, type IEmailDraft, type IEmailIdentifier, type IGlobalSettings, IdentifierService, type IdentifierStatus, ImapBounceChecker, type ImapConfig, type ImapSettings, InvalidTokenError, NoAvailableAccountError, QueueService, type QueueSettings, type QueueStats, QuotaExceededError, SES_BOUNCE_TYPE, SES_COMPLAINT_TYPE, SES_NOTIFICATION_TYPE, SNS_MESSAGE_TYPE, type SendJobData, type SesBounce, type SesBounceRecipient, type SesBounceType, type SesClick, type SesComplaint, type SesComplaintRecipient, type SesComplaintType, type SesConfig, type SesDelivery, type SesMailPayload, type SesNotification, type SesNotificationType, type SesOpen, type SesSettings, SesWebhookHandler, SettingsService, type SmtpConfig, SmtpConnectionError, type SmtpSendParams, type SmtpSendResult, SmtpService, type SnsMessage, type SnsMessageType, SnsSignatureError, type UnsubscribePageSettings, UnsubscribeService, type UpdateEmailAccountInput, type UpdateGlobalSettingsInput, type UpdateIdentifierInput, WarmupManager, type WarmupPhase, type WarmupStatus, type WebhookProcessResult, createEmailAccountManager, createEmailAccountSchema, createEmailDailyStatsSchema, createEmailDraftSchema, createEmailIdentifierSchema, createGlobalSettingsSchema, validateConfig };
|