@bernierllc/sender-identity-verification 1.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/.env.test +8 -0
- package/.eslintrc.js +30 -0
- package/README.md +376 -0
- package/__tests__/SenderIdentityVerification.test.ts +461 -0
- package/__tests__/__mocks__/fetch-mock.ts +156 -0
- package/__tests__/additional-coverage.test.ts +129 -0
- package/__tests__/additional-error-coverage.test.ts +483 -0
- package/__tests__/branch-coverage.test.ts +509 -0
- package/__tests__/config.test.ts +119 -0
- package/__tests__/error-handling.test.ts +321 -0
- package/__tests__/final-branch-coverage.test.ts +372 -0
- package/__tests__/integration.real-api.test.ts +295 -0
- package/__tests__/providers.test.ts +331 -0
- package/__tests__/service-coverage.test.ts +412 -0
- package/dist/SenderIdentityVerification.d.ts +72 -0
- package/dist/SenderIdentityVerification.js +643 -0
- package/dist/config.d.ts +31 -0
- package/dist/config.js +38 -0
- package/dist/errors.d.ts +27 -0
- package/dist/errors.js +61 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +21 -0
- package/dist/providers/MailgunProvider.d.ts +13 -0
- package/dist/providers/MailgunProvider.js +35 -0
- package/dist/providers/SESProvider.d.ts +12 -0
- package/dist/providers/SESProvider.js +47 -0
- package/dist/providers/SMTPProvider.d.ts +12 -0
- package/dist/providers/SMTPProvider.js +30 -0
- package/dist/providers/SendGridProvider.d.ts +19 -0
- package/dist/providers/SendGridProvider.js +98 -0
- package/dist/templates/verification-email.d.ts +9 -0
- package/dist/templates/verification-email.js +67 -0
- package/dist/types.d.ts +139 -0
- package/dist/types.js +33 -0
- package/dist/utils/domain-extractor.d.ts +4 -0
- package/dist/utils/domain-extractor.js +20 -0
- package/jest.config.cjs +33 -0
- package/package.json +60 -0
- package/src/SenderIdentityVerification.ts +796 -0
- package/src/config.ts +81 -0
- package/src/errors.ts +64 -0
- package/src/global.d.ts +24 -0
- package/src/index.ts +24 -0
- package/src/providers/MailgunProvider.ts +35 -0
- package/src/providers/SESProvider.ts +51 -0
- package/src/providers/SMTPProvider.ts +29 -0
- package/src/providers/SendGridProvider.ts +108 -0
- package/src/templates/verification-email.ts +67 -0
- package/src/types.ts +163 -0
- package/src/utils/domain-extractor.ts +18 -0
- package/tsconfig.json +22 -0
|
@@ -0,0 +1,412 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright (c) 2025 Bernier LLC
|
|
3
|
+
|
|
4
|
+
This file is licensed to the client under a limited-use license.
|
|
5
|
+
The client may use and modify this code *only within the scope of the project it was delivered for*.
|
|
6
|
+
Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { SenderIdentityVerification } from '../src/SenderIdentityVerification';
|
|
10
|
+
import { SenderIdentityConfig } from '../src/config';
|
|
11
|
+
import { EmailProvider, SenderStatus, IEmailDomainVerification, DomainVerificationStatus } from '../src/types';
|
|
12
|
+
|
|
13
|
+
describe('Service Coverage Tests', () => {
|
|
14
|
+
let service: SenderIdentityVerification;
|
|
15
|
+
let config: SenderIdentityConfig;
|
|
16
|
+
|
|
17
|
+
beforeEach(() => {
|
|
18
|
+
config = {
|
|
19
|
+
emailSenderConfig: {
|
|
20
|
+
provider: 'smtp'
|
|
21
|
+
},
|
|
22
|
+
domainVerificationConfig: {},
|
|
23
|
+
verificationBaseUrl: 'https://example.com',
|
|
24
|
+
verificationFromEmail: 'verify@example.com',
|
|
25
|
+
verificationFromName: 'Verification Service'
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
service = new SenderIdentityVerification(config);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
describe('Domain Verification Integration', () => {
|
|
32
|
+
it('should block sender creation when domain is not verified', async () => {
|
|
33
|
+
const mockDomainVerification: IEmailDomainVerification = {
|
|
34
|
+
getDomainStatus: async (domain: string): Promise<DomainVerificationStatus> => {
|
|
35
|
+
return {
|
|
36
|
+
isVerified: false,
|
|
37
|
+
domain
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
const configWithDomain: SenderIdentityConfig = {
|
|
43
|
+
...config,
|
|
44
|
+
domainVerificationConfig: {
|
|
45
|
+
instance: mockDomainVerification
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
const serviceWithDomain = new SenderIdentityVerification(configWithDomain);
|
|
50
|
+
|
|
51
|
+
const result = await serviceWithDomain.createSender({
|
|
52
|
+
email: 'test@unverified-domain.com',
|
|
53
|
+
name: 'Test User',
|
|
54
|
+
provider: EmailProvider.SMTP
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
expect(result.success).toBe(false);
|
|
58
|
+
expect(result.error).toContain('not verified');
|
|
59
|
+
expect(result.errors).toContain('Domain verification required');
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it('should allow sender creation when domain is verified', async () => {
|
|
63
|
+
const mockDomainVerification: IEmailDomainVerification = {
|
|
64
|
+
getDomainStatus: async (domain: string): Promise<DomainVerificationStatus> => {
|
|
65
|
+
return {
|
|
66
|
+
isVerified: true,
|
|
67
|
+
domain
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
const configWithDomain: SenderIdentityConfig = {
|
|
73
|
+
...config,
|
|
74
|
+
domainVerificationConfig: {
|
|
75
|
+
instance: mockDomainVerification
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
const serviceWithDomain = new SenderIdentityVerification(configWithDomain);
|
|
80
|
+
|
|
81
|
+
const result = await serviceWithDomain.createSender({
|
|
82
|
+
email: 'test@verified-domain.com',
|
|
83
|
+
name: 'Test User',
|
|
84
|
+
provider: EmailProvider.SMTP
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
expect(result.success).toBe(true);
|
|
88
|
+
expect(result.data).toBeDefined();
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
describe('Duplicate Sender Detection', () => {
|
|
93
|
+
it('should prevent creating duplicate sender with same email', async () => {
|
|
94
|
+
const createResult1 = await service.createSender({
|
|
95
|
+
email: 'duplicate@example.com',
|
|
96
|
+
name: 'User One',
|
|
97
|
+
provider: EmailProvider.SMTP
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
expect(createResult1.success).toBe(true);
|
|
101
|
+
|
|
102
|
+
const createResult2 = await service.createSender({
|
|
103
|
+
email: 'duplicate@example.com',
|
|
104
|
+
name: 'User Two',
|
|
105
|
+
provider: EmailProvider.SMTP
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
expect(createResult2.success).toBe(false);
|
|
109
|
+
expect(createResult2.error).toContain('already exists');
|
|
110
|
+
});
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
describe('Token Expiration Handling', () => {
|
|
114
|
+
it('should handle expired verification tokens', async () => {
|
|
115
|
+
const createResult = await service.createSender({
|
|
116
|
+
email: 'expiry-test@example.com',
|
|
117
|
+
name: 'Test User',
|
|
118
|
+
provider: EmailProvider.SMTP
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
if (!createResult.success || !createResult.data) {
|
|
122
|
+
throw new Error('Setup failed');
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const sender = createResult.data;
|
|
126
|
+
|
|
127
|
+
// Manually set expiration to past date
|
|
128
|
+
sender.verificationExpiresAt = new Date(Date.now() - 1000); // 1 second ago
|
|
129
|
+
sender.status = SenderStatus.VERIFICATION_SENT;
|
|
130
|
+
|
|
131
|
+
if (sender.verificationToken) {
|
|
132
|
+
const result = await service.verifySender(sender.verificationToken);
|
|
133
|
+
|
|
134
|
+
expect(result.success).toBe(false);
|
|
135
|
+
expect(result.status).toBe(SenderStatus.EXPIRED);
|
|
136
|
+
expect(result.errors).toContain('Token expired');
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
describe('Locked Sender Handling', () => {
|
|
142
|
+
it('should prevent verification of locked senders', async () => {
|
|
143
|
+
const createResult = await service.createSender({
|
|
144
|
+
email: 'locked-test@example.com',
|
|
145
|
+
name: 'Test User',
|
|
146
|
+
provider: EmailProvider.SMTP
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
if (!createResult.success || !createResult.data) {
|
|
150
|
+
throw new Error('Setup failed');
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const sender = createResult.data;
|
|
154
|
+
|
|
155
|
+
// Manually lock the sender
|
|
156
|
+
sender.status = SenderStatus.LOCKED;
|
|
157
|
+
|
|
158
|
+
if (sender.verificationToken) {
|
|
159
|
+
const result = await service.verifySender(sender.verificationToken);
|
|
160
|
+
|
|
161
|
+
expect(result.success).toBe(false);
|
|
162
|
+
expect(result.status).toBe(SenderStatus.LOCKED);
|
|
163
|
+
expect(result.errors).toContain('Account locked');
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
describe('Soft Delete Functionality', () => {
|
|
169
|
+
it('should soft delete sender and set deletedAt', async () => {
|
|
170
|
+
const createResult = await service.createSender({
|
|
171
|
+
email: 'soft-delete@example.com',
|
|
172
|
+
name: 'Test User',
|
|
173
|
+
provider: EmailProvider.SMTP
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
if (!createResult.success || !createResult.data) {
|
|
177
|
+
throw new Error('Setup failed');
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const senderId = createResult.data.id;
|
|
181
|
+
|
|
182
|
+
const deleteResult = await service.deleteSender(senderId);
|
|
183
|
+
|
|
184
|
+
expect(deleteResult.success).toBe(true);
|
|
185
|
+
|
|
186
|
+
// Verify sender was soft deleted by checking it's removed from map
|
|
187
|
+
const getResult = await service.getSender(senderId);
|
|
188
|
+
expect(getResult.success).toBe(false);
|
|
189
|
+
});
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
describe('Default Sender Management', () => {
|
|
193
|
+
it('should set sender as default', async () => {
|
|
194
|
+
const createResult = await service.createSender({
|
|
195
|
+
email: 'default-test@example.com',
|
|
196
|
+
name: 'Default User',
|
|
197
|
+
provider: EmailProvider.SMTP,
|
|
198
|
+
isDefault: true,
|
|
199
|
+
skipVerification: true
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
expect(createResult.success).toBe(true);
|
|
203
|
+
expect(createResult.data?.isDefault).toBe(true);
|
|
204
|
+
|
|
205
|
+
// Manually verify the sender (needed for getDefaultSender)
|
|
206
|
+
if (createResult.data) {
|
|
207
|
+
createResult.data.status = SenderStatus.VERIFIED;
|
|
208
|
+
createResult.data.verifiedAt = new Date();
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
const defaultResult = await service.getDefaultSender(EmailProvider.SMTP);
|
|
212
|
+
|
|
213
|
+
expect(defaultResult.success).toBe(true);
|
|
214
|
+
expect(defaultResult.data?.email).toBe('default-test@example.com');
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
it('should unset previous default when setting new default', async () => {
|
|
218
|
+
const oldResult = await service.createSender({
|
|
219
|
+
email: 'old-default@example.com',
|
|
220
|
+
name: 'Old Default',
|
|
221
|
+
provider: EmailProvider.SMTP,
|
|
222
|
+
isDefault: true,
|
|
223
|
+
skipVerification: true
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
if (oldResult.data) {
|
|
227
|
+
oldResult.data.status = SenderStatus.VERIFIED;
|
|
228
|
+
oldResult.data.verifiedAt = new Date();
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
const newResult = await service.createSender({
|
|
232
|
+
email: 'new-default@example.com',
|
|
233
|
+
name: 'New Default',
|
|
234
|
+
provider: EmailProvider.SMTP,
|
|
235
|
+
isDefault: true,
|
|
236
|
+
skipVerification: true
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
if (newResult.data) {
|
|
240
|
+
newResult.data.status = SenderStatus.VERIFIED;
|
|
241
|
+
newResult.data.verifiedAt = new Date();
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
const defaultResult = await service.getDefaultSender(EmailProvider.SMTP);
|
|
245
|
+
|
|
246
|
+
expect(defaultResult.success).toBe(true);
|
|
247
|
+
expect(defaultResult.data?.email).toBe('new-default@example.com');
|
|
248
|
+
});
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
describe('List Filtering', () => {
|
|
252
|
+
beforeEach(async () => {
|
|
253
|
+
await service.createSender({
|
|
254
|
+
email: 'active@example.com',
|
|
255
|
+
name: 'Active User',
|
|
256
|
+
provider: EmailProvider.SMTP
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
await service.createSender({
|
|
260
|
+
email: 'sendgrid@example.com',
|
|
261
|
+
name: 'SendGrid User',
|
|
262
|
+
provider: EmailProvider.SENDGRID
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
const createResult = await service.createSender({
|
|
266
|
+
email: 'verified@example.com',
|
|
267
|
+
name: 'Verified User',
|
|
268
|
+
provider: EmailProvider.SMTP
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
if (createResult.success && createResult.data) {
|
|
272
|
+
const sender = createResult.data;
|
|
273
|
+
sender.status = SenderStatus.VERIFIED;
|
|
274
|
+
sender.verifiedAt = new Date();
|
|
275
|
+
}
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
it('should filter by provider', async () => {
|
|
279
|
+
const result = await service.listSenders({ provider: EmailProvider.SMTP });
|
|
280
|
+
|
|
281
|
+
expect(result.success).toBe(true);
|
|
282
|
+
expect(result.data).toBeDefined();
|
|
283
|
+
expect(result.data!.length).toBeGreaterThan(0);
|
|
284
|
+
expect(result.data!.every(s => s.provider === EmailProvider.SMTP)).toBe(true);
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
it('should filter by status', async () => {
|
|
288
|
+
const result = await service.listSenders({ status: SenderStatus.VERIFIED });
|
|
289
|
+
|
|
290
|
+
expect(result.success).toBe(true);
|
|
291
|
+
expect(result.data).toBeDefined();
|
|
292
|
+
expect(result.data!.every(s => s.status === SenderStatus.VERIFIED)).toBe(true);
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
it('should filter by isActive', async () => {
|
|
296
|
+
const result = await service.listSenders({ isActive: true });
|
|
297
|
+
|
|
298
|
+
expect(result.success).toBe(true);
|
|
299
|
+
expect(result.data).toBeDefined();
|
|
300
|
+
expect(result.data!.every(s => s.isActive === true)).toBe(true);
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
it('should filter by domain', async () => {
|
|
304
|
+
const result = await service.listSenders({ domain: 'example.com' });
|
|
305
|
+
|
|
306
|
+
expect(result.success).toBe(true);
|
|
307
|
+
expect(result.data).toBeDefined();
|
|
308
|
+
expect(result.data!.every(s => s.domain === 'example.com')).toBe(true);
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
it('should apply limit and offset', async () => {
|
|
312
|
+
const result1 = await service.listSenders({ limit: 1 });
|
|
313
|
+
expect(result1.data!.length).toBeLessThanOrEqual(1);
|
|
314
|
+
|
|
315
|
+
const result2 = await service.listSenders({ offset: 1, limit: 10 });
|
|
316
|
+
expect(result2.success).toBe(true);
|
|
317
|
+
});
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
describe('Compliance Checking', () => {
|
|
321
|
+
it('should check compliance for verified sender', async () => {
|
|
322
|
+
const createResult = await service.createSender({
|
|
323
|
+
email: 'compliance@example.com',
|
|
324
|
+
name: 'Compliance User',
|
|
325
|
+
provider: EmailProvider.SMTP
|
|
326
|
+
});
|
|
327
|
+
|
|
328
|
+
if (!createResult.success || !createResult.data) {
|
|
329
|
+
throw new Error('Setup failed');
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
const sender = createResult.data;
|
|
333
|
+
sender.status = SenderStatus.VERIFIED;
|
|
334
|
+
sender.verifiedAt = new Date();
|
|
335
|
+
|
|
336
|
+
const result = await service.checkCompliance(sender.id);
|
|
337
|
+
|
|
338
|
+
expect(result.success).toBe(true);
|
|
339
|
+
expect(result.data).toBeDefined();
|
|
340
|
+
});
|
|
341
|
+
});
|
|
342
|
+
|
|
343
|
+
describe('Update Sender', () => {
|
|
344
|
+
it('should update sender name and reply-to', async () => {
|
|
345
|
+
const createResult = await service.createSender({
|
|
346
|
+
email: 'update-test@example.com',
|
|
347
|
+
name: 'Original Name',
|
|
348
|
+
provider: EmailProvider.SMTP
|
|
349
|
+
});
|
|
350
|
+
|
|
351
|
+
if (!createResult.success || !createResult.data) {
|
|
352
|
+
throw new Error('Setup failed');
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
const senderId = createResult.data.id;
|
|
356
|
+
|
|
357
|
+
const updateResult = await service.updateSender(senderId, {
|
|
358
|
+
name: 'Updated Name',
|
|
359
|
+
replyToEmail: 'reply@example.com',
|
|
360
|
+
replyToName: 'Reply Name'
|
|
361
|
+
});
|
|
362
|
+
|
|
363
|
+
expect(updateResult.success).toBe(true);
|
|
364
|
+
expect(updateResult.data?.name).toBe('Updated Name');
|
|
365
|
+
expect(updateResult.data?.replyToEmail).toBe('reply@example.com');
|
|
366
|
+
expect(updateResult.data?.replyToName).toBe('Reply Name');
|
|
367
|
+
});
|
|
368
|
+
|
|
369
|
+
it('should update isDefault flag', async () => {
|
|
370
|
+
const createResult = await service.createSender({
|
|
371
|
+
email: 'default-update@example.com',
|
|
372
|
+
name: 'Test User',
|
|
373
|
+
provider: EmailProvider.SMTP,
|
|
374
|
+
isDefault: false
|
|
375
|
+
});
|
|
376
|
+
|
|
377
|
+
if (!createResult.success || !createResult.data) {
|
|
378
|
+
throw new Error('Setup failed');
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
const senderId = createResult.data.id;
|
|
382
|
+
|
|
383
|
+
const updateResult = await service.updateSender(senderId, {
|
|
384
|
+
isDefault: true
|
|
385
|
+
});
|
|
386
|
+
|
|
387
|
+
expect(updateResult.success).toBe(true);
|
|
388
|
+
expect(updateResult.data?.isDefault).toBe(true);
|
|
389
|
+
});
|
|
390
|
+
|
|
391
|
+
it('should update isActive flag', async () => {
|
|
392
|
+
const createResult = await service.createSender({
|
|
393
|
+
email: 'active-update@example.com',
|
|
394
|
+
name: 'Test User',
|
|
395
|
+
provider: EmailProvider.SMTP
|
|
396
|
+
});
|
|
397
|
+
|
|
398
|
+
if (!createResult.success || !createResult.data) {
|
|
399
|
+
throw new Error('Setup failed');
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
const senderId = createResult.data.id;
|
|
403
|
+
|
|
404
|
+
const updateResult = await service.updateSender(senderId, {
|
|
405
|
+
isActive: false
|
|
406
|
+
});
|
|
407
|
+
|
|
408
|
+
expect(updateResult.success).toBe(true);
|
|
409
|
+
expect(updateResult.data?.isActive).toBe(false);
|
|
410
|
+
});
|
|
411
|
+
});
|
|
412
|
+
});
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { SenderIdentity, EmailProvider, CreateSenderInput, UpdateSenderInput, VerificationResult, ComplianceCheckResult, ListSendersOptions, SenderIdentityResult } from './types.js';
|
|
2
|
+
import { SenderIdentityConfig } from './config.js';
|
|
3
|
+
/**
|
|
4
|
+
* Sender identity verification service
|
|
5
|
+
*/
|
|
6
|
+
export declare class SenderIdentityVerification {
|
|
7
|
+
private config;
|
|
8
|
+
private senders;
|
|
9
|
+
private emailSender?;
|
|
10
|
+
private domainVerification?;
|
|
11
|
+
private cryptoUtils?;
|
|
12
|
+
private logger?;
|
|
13
|
+
private emailValidator?;
|
|
14
|
+
private neverhub?;
|
|
15
|
+
constructor(config: SenderIdentityConfig);
|
|
16
|
+
/**
|
|
17
|
+
* Initialize service and register with NeverHub
|
|
18
|
+
*/
|
|
19
|
+
initialize(): Promise<void>;
|
|
20
|
+
/**
|
|
21
|
+
* Create a new sender identity
|
|
22
|
+
*/
|
|
23
|
+
createSender(input: CreateSenderInput): Promise<SenderIdentityResult<SenderIdentity>>;
|
|
24
|
+
/**
|
|
25
|
+
* Send verification email to sender
|
|
26
|
+
*/
|
|
27
|
+
sendVerificationEmail(sender: SenderIdentity): Promise<SenderIdentityResult<void>>;
|
|
28
|
+
/**
|
|
29
|
+
* Verify sender email with token
|
|
30
|
+
*/
|
|
31
|
+
verifySender(token: string): Promise<VerificationResult>;
|
|
32
|
+
/**
|
|
33
|
+
* Verify sender with email provider
|
|
34
|
+
*/
|
|
35
|
+
private verifyWithProvider;
|
|
36
|
+
/**
|
|
37
|
+
* Get sender by ID
|
|
38
|
+
*/
|
|
39
|
+
getSender(senderId: string): Promise<SenderIdentityResult<SenderIdentity>>;
|
|
40
|
+
/**
|
|
41
|
+
* List senders
|
|
42
|
+
*/
|
|
43
|
+
listSenders(options?: ListSendersOptions): Promise<SenderIdentityResult<SenderIdentity[]>>;
|
|
44
|
+
/**
|
|
45
|
+
* Update sender
|
|
46
|
+
*/
|
|
47
|
+
updateSender(senderId: string, input: UpdateSenderInput): Promise<SenderIdentityResult<SenderIdentity>>;
|
|
48
|
+
/**
|
|
49
|
+
* Delete sender
|
|
50
|
+
*/
|
|
51
|
+
deleteSender(senderId: string): Promise<SenderIdentityResult<void>>;
|
|
52
|
+
/**
|
|
53
|
+
* Check provider compliance for sender
|
|
54
|
+
*/
|
|
55
|
+
checkCompliance(senderId: string): Promise<SenderIdentityResult<ComplianceCheckResult>>;
|
|
56
|
+
/**
|
|
57
|
+
* Get default sender for provider
|
|
58
|
+
*/
|
|
59
|
+
getDefaultSender(provider: EmailProvider): Promise<SenderIdentityResult<SenderIdentity>>;
|
|
60
|
+
/**
|
|
61
|
+
* Resend verification email
|
|
62
|
+
*/
|
|
63
|
+
resendVerification(senderId: string): Promise<SenderIdentityResult<void>>;
|
|
64
|
+
private generateSenderId;
|
|
65
|
+
private fallbackGenerateToken;
|
|
66
|
+
private isValidEmail;
|
|
67
|
+
private findSenderByEmail;
|
|
68
|
+
private findSenderByToken;
|
|
69
|
+
private unsetOtherDefaults;
|
|
70
|
+
private loadSendersFromDatabase;
|
|
71
|
+
private saveSenderToDatabase;
|
|
72
|
+
}
|