@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.
Files changed (51) hide show
  1. package/.env.test +8 -0
  2. package/.eslintrc.js +30 -0
  3. package/README.md +376 -0
  4. package/__tests__/SenderIdentityVerification.test.ts +461 -0
  5. package/__tests__/__mocks__/fetch-mock.ts +156 -0
  6. package/__tests__/additional-coverage.test.ts +129 -0
  7. package/__tests__/additional-error-coverage.test.ts +483 -0
  8. package/__tests__/branch-coverage.test.ts +509 -0
  9. package/__tests__/config.test.ts +119 -0
  10. package/__tests__/error-handling.test.ts +321 -0
  11. package/__tests__/final-branch-coverage.test.ts +372 -0
  12. package/__tests__/integration.real-api.test.ts +295 -0
  13. package/__tests__/providers.test.ts +331 -0
  14. package/__tests__/service-coverage.test.ts +412 -0
  15. package/dist/SenderIdentityVerification.d.ts +72 -0
  16. package/dist/SenderIdentityVerification.js +643 -0
  17. package/dist/config.d.ts +31 -0
  18. package/dist/config.js +38 -0
  19. package/dist/errors.d.ts +27 -0
  20. package/dist/errors.js +61 -0
  21. package/dist/index.d.ts +4 -0
  22. package/dist/index.js +21 -0
  23. package/dist/providers/MailgunProvider.d.ts +13 -0
  24. package/dist/providers/MailgunProvider.js +35 -0
  25. package/dist/providers/SESProvider.d.ts +12 -0
  26. package/dist/providers/SESProvider.js +47 -0
  27. package/dist/providers/SMTPProvider.d.ts +12 -0
  28. package/dist/providers/SMTPProvider.js +30 -0
  29. package/dist/providers/SendGridProvider.d.ts +19 -0
  30. package/dist/providers/SendGridProvider.js +98 -0
  31. package/dist/templates/verification-email.d.ts +9 -0
  32. package/dist/templates/verification-email.js +67 -0
  33. package/dist/types.d.ts +139 -0
  34. package/dist/types.js +33 -0
  35. package/dist/utils/domain-extractor.d.ts +4 -0
  36. package/dist/utils/domain-extractor.js +20 -0
  37. package/jest.config.cjs +33 -0
  38. package/package.json +60 -0
  39. package/src/SenderIdentityVerification.ts +796 -0
  40. package/src/config.ts +81 -0
  41. package/src/errors.ts +64 -0
  42. package/src/global.d.ts +24 -0
  43. package/src/index.ts +24 -0
  44. package/src/providers/MailgunProvider.ts +35 -0
  45. package/src/providers/SESProvider.ts +51 -0
  46. package/src/providers/SMTPProvider.ts +29 -0
  47. package/src/providers/SendGridProvider.ts +108 -0
  48. package/src/templates/verification-email.ts +67 -0
  49. package/src/types.ts +163 -0
  50. package/src/utils/domain-extractor.ts +18 -0
  51. package/tsconfig.json +22 -0
package/dist/config.js ADDED
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ /*
3
+ Copyright (c) 2025 Bernier LLC
4
+
5
+ This file is licensed to the client under a limited-use license.
6
+ The client may use and modify this code *only within the scope of the project it was delivered for*.
7
+ Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.loadConfigFromEnv = loadConfigFromEnv;
11
+ /**
12
+ * Load configuration from environment variables
13
+ */
14
+ function loadConfigFromEnv(overrides = {}) {
15
+ const config = {
16
+ verificationBaseUrl: process.env.SENDER_VERIFICATION_BASE_URL || overrides.verificationBaseUrl || '',
17
+ verificationFromEmail: process.env.SENDER_VERIFICATION_FROM_EMAIL || overrides.verificationFromEmail || 'noreply@example.com',
18
+ verificationFromName: process.env.SENDER_VERIFICATION_FROM_NAME || overrides.verificationFromName || 'Email Verification',
19
+ sendgridApiKey: process.env.SENDGRID_API_KEY || overrides.sendgridApiKey,
20
+ mailgunApiKey: process.env.MAILGUN_API_KEY || overrides.mailgunApiKey,
21
+ sesAccessKey: process.env.AWS_SES_ACCESS_KEY || overrides.sesAccessKey,
22
+ sesSecretKey: process.env.AWS_SES_SECRET_KEY || overrides.sesSecretKey,
23
+ sesRegion: process.env.AWS_SES_REGION || overrides.sesRegion || 'us-east-1',
24
+ databaseUrl: process.env.DATABASE_URL || overrides.databaseUrl,
25
+ emailSenderConfig: overrides.emailSenderConfig || {},
26
+ domainVerificationConfig: overrides.domainVerificationConfig || {},
27
+ retryConfig: overrides.retryConfig
28
+ };
29
+ // Log configuration (without sensitive data)
30
+ console.log('⚙️ Sender Identity Verification Configuration:');
31
+ console.log(` └── Verification Base URL: ${config.verificationBaseUrl || '(not set)'}`);
32
+ console.log(` └── From Email: ${config.verificationFromEmail}`);
33
+ console.log(` └── SendGrid: ${config.sendgridApiKey ? '***configured***' : '(not set)'}`);
34
+ console.log(` └── Mailgun: ${config.mailgunApiKey ? '***configured***' : '(not set)'}`);
35
+ console.log(` └── SES: ${config.sesAccessKey ? '***configured***' : '(not set)'}`);
36
+ console.log(` └── Database: ${config.databaseUrl ? '***configured***' : '(not set)'}`);
37
+ return config;
38
+ }
@@ -0,0 +1,27 @@
1
+ import { SenderIdentityResult } from './types.js';
2
+ /**
3
+ * Sender error codes
4
+ */
5
+ export declare enum SenderErrorCode {
6
+ SENDER_NOT_FOUND = "SENDER_NOT_FOUND",
7
+ SENDER_ALREADY_EXISTS = "SENDER_ALREADY_EXISTS",
8
+ SENDER_LOCKED = "SENDER_LOCKED",
9
+ VERIFICATION_EXPIRED = "VERIFICATION_EXPIRED",
10
+ VERIFICATION_FAILED = "VERIFICATION_FAILED",
11
+ DOMAIN_NOT_VERIFIED = "DOMAIN_NOT_VERIFIED",
12
+ PROVIDER_ERROR = "PROVIDER_ERROR",
13
+ INVALID_EMAIL = "INVALID_EMAIL",
14
+ RATE_LIMIT_EXCEEDED = "RATE_LIMIT_EXCEEDED"
15
+ }
16
+ /**
17
+ * Custom error class for sender verification errors
18
+ */
19
+ export declare class SenderVerificationError extends Error {
20
+ code: SenderErrorCode;
21
+ details?: unknown | undefined;
22
+ constructor(message: string, code: SenderErrorCode, details?: unknown | undefined);
23
+ }
24
+ /**
25
+ * Error handling wrapper
26
+ */
27
+ export declare function handleSenderError(error: unknown): SenderIdentityResult<never>;
package/dist/errors.js ADDED
@@ -0,0 +1,61 @@
1
+ "use strict";
2
+ /*
3
+ Copyright (c) 2025 Bernier LLC
4
+
5
+ This file is licensed to the client under a limited-use license.
6
+ The client may use and modify this code *only within the scope of the project it was delivered for*.
7
+ Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.SenderVerificationError = exports.SenderErrorCode = void 0;
11
+ exports.handleSenderError = handleSenderError;
12
+ /**
13
+ * Sender error codes
14
+ */
15
+ var SenderErrorCode;
16
+ (function (SenderErrorCode) {
17
+ SenderErrorCode["SENDER_NOT_FOUND"] = "SENDER_NOT_FOUND";
18
+ SenderErrorCode["SENDER_ALREADY_EXISTS"] = "SENDER_ALREADY_EXISTS";
19
+ SenderErrorCode["SENDER_LOCKED"] = "SENDER_LOCKED";
20
+ SenderErrorCode["VERIFICATION_EXPIRED"] = "VERIFICATION_EXPIRED";
21
+ SenderErrorCode["VERIFICATION_FAILED"] = "VERIFICATION_FAILED";
22
+ SenderErrorCode["DOMAIN_NOT_VERIFIED"] = "DOMAIN_NOT_VERIFIED";
23
+ SenderErrorCode["PROVIDER_ERROR"] = "PROVIDER_ERROR";
24
+ SenderErrorCode["INVALID_EMAIL"] = "INVALID_EMAIL";
25
+ SenderErrorCode["RATE_LIMIT_EXCEEDED"] = "RATE_LIMIT_EXCEEDED";
26
+ })(SenderErrorCode || (exports.SenderErrorCode = SenderErrorCode = {}));
27
+ /**
28
+ * Custom error class for sender verification errors
29
+ */
30
+ class SenderVerificationError extends Error {
31
+ constructor(message, code, details) {
32
+ super(message);
33
+ this.code = code;
34
+ this.details = details;
35
+ this.name = 'SenderVerificationError';
36
+ Object.setPrototypeOf(this, SenderVerificationError.prototype);
37
+ }
38
+ }
39
+ exports.SenderVerificationError = SenderVerificationError;
40
+ /**
41
+ * Error handling wrapper
42
+ */
43
+ function handleSenderError(error) {
44
+ if (error instanceof SenderVerificationError) {
45
+ return {
46
+ success: false,
47
+ error: error.message,
48
+ errors: [error.code]
49
+ };
50
+ }
51
+ if (error instanceof Error) {
52
+ return {
53
+ success: false,
54
+ error: error.message
55
+ };
56
+ }
57
+ return {
58
+ success: false,
59
+ error: 'Unknown error occurred'
60
+ };
61
+ }
@@ -0,0 +1,4 @@
1
+ export { SenderIdentityVerification } from './SenderIdentityVerification.js';
2
+ export { SenderIdentityConfig, loadConfigFromEnv } from './config.js';
3
+ export { SenderVerificationError, SenderErrorCode, handleSenderError } from './errors.js';
4
+ export { SenderIdentity, SenderStatus, EmailProvider, CreateSenderInput, UpdateSenderInput, VerificationResult, ComplianceCheckResult, ListSendersOptions, SenderIdentityResult, DomainVerificationStatus, IEmailDomainVerification } from './types.js';
package/dist/index.js ADDED
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ /*
3
+ Copyright (c) 2025 Bernier LLC
4
+
5
+ This file is licensed to the client under a limited-use license.
6
+ The client may use and modify this code *only within the scope of the project it was delivered for*.
7
+ Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.EmailProvider = exports.SenderStatus = exports.handleSenderError = exports.SenderErrorCode = exports.SenderVerificationError = exports.loadConfigFromEnv = exports.SenderIdentityVerification = void 0;
11
+ var SenderIdentityVerification_js_1 = require("./SenderIdentityVerification.js");
12
+ Object.defineProperty(exports, "SenderIdentityVerification", { enumerable: true, get: function () { return SenderIdentityVerification_js_1.SenderIdentityVerification; } });
13
+ var config_js_1 = require("./config.js");
14
+ Object.defineProperty(exports, "loadConfigFromEnv", { enumerable: true, get: function () { return config_js_1.loadConfigFromEnv; } });
15
+ var errors_js_1 = require("./errors.js");
16
+ Object.defineProperty(exports, "SenderVerificationError", { enumerable: true, get: function () { return errors_js_1.SenderVerificationError; } });
17
+ Object.defineProperty(exports, "SenderErrorCode", { enumerable: true, get: function () { return errors_js_1.SenderErrorCode; } });
18
+ Object.defineProperty(exports, "handleSenderError", { enumerable: true, get: function () { return errors_js_1.handleSenderError; } });
19
+ var types_js_1 = require("./types.js");
20
+ Object.defineProperty(exports, "SenderStatus", { enumerable: true, get: function () { return types_js_1.SenderStatus; } });
21
+ Object.defineProperty(exports, "EmailProvider", { enumerable: true, get: function () { return types_js_1.EmailProvider; } });
@@ -0,0 +1,13 @@
1
+ import { SenderIdentity, SenderIdentityResult } from '../types.js';
2
+ /**
3
+ * Mailgun provider for sender verification
4
+ * Note: Mailgun doesn't have sender-level verification, only domain verification
5
+ */
6
+ export declare class MailgunProvider {
7
+ constructor(_apiKey: string);
8
+ /**
9
+ * Verify sender with Mailgun
10
+ * Mailgun only verifies domains, not individual senders
11
+ */
12
+ verifySender(_sender: SenderIdentity): Promise<SenderIdentityResult<Record<string, unknown>>>;
13
+ }
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ /*
3
+ Copyright (c) 2025 Bernier LLC
4
+
5
+ This file is licensed to the client under a limited-use license.
6
+ The client may use and modify this code *only within the scope of the project it was delivered for*.
7
+ Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.MailgunProvider = void 0;
11
+ /**
12
+ * Mailgun provider for sender verification
13
+ * Note: Mailgun doesn't have sender-level verification, only domain verification
14
+ */
15
+ class MailgunProvider {
16
+ constructor(_apiKey) {
17
+ // apiKey parameter reserved for future Mailgun API integration
18
+ void _apiKey;
19
+ }
20
+ /**
21
+ * Verify sender with Mailgun
22
+ * Mailgun only verifies domains, not individual senders
23
+ */
24
+ async verifySender(_sender) {
25
+ // Mailgun doesn't require individual sender verification
26
+ // Domain verification is handled by @bernierllc/email-domain-verification
27
+ return {
28
+ success: true,
29
+ data: {
30
+ note: 'Mailgun does not require individual sender verification'
31
+ }
32
+ };
33
+ }
34
+ }
35
+ exports.MailgunProvider = MailgunProvider;
@@ -0,0 +1,12 @@
1
+ import { SenderIdentity, SenderIdentityResult } from '../types.js';
2
+ /**
3
+ * AWS SES provider for sender verification
4
+ */
5
+ export declare class SESProvider {
6
+ constructor(_accessKey: string, _secretKey: string, _region: string);
7
+ /**
8
+ * Verify sender with AWS SES
9
+ * TODO: Implement AWS SDK integration for SES VerifyEmailIdentity
10
+ */
11
+ verifySender(_sender: SenderIdentity): Promise<SenderIdentityResult<Record<string, unknown>>>;
12
+ }
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ /*
3
+ Copyright (c) 2025 Bernier LLC
4
+
5
+ This file is licensed to the client under a limited-use license.
6
+ The client may use and modify this code *only within the scope of the project it was delivered for*.
7
+ Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.SESProvider = void 0;
11
+ /**
12
+ * AWS SES provider for sender verification
13
+ */
14
+ class SESProvider {
15
+ constructor(_accessKey, _secretKey, _region) {
16
+ // Parameters reserved for future AWS SDK integration
17
+ void _accessKey;
18
+ void _secretKey;
19
+ void _region;
20
+ }
21
+ /**
22
+ * Verify sender with AWS SES
23
+ * TODO: Implement AWS SDK integration for SES VerifyEmailIdentity
24
+ */
25
+ async verifySender(_sender) {
26
+ try {
27
+ // TODO: Call SES VerifyEmailIdentity API
28
+ // For now, return success (stub implementation)
29
+ // Real implementation would use AWS SDK:
30
+ // const ses = new SES({ region: this.region, credentials: {...} });
31
+ // await ses.verifyEmailIdentity({ EmailAddress: sender.email });
32
+ return {
33
+ success: true,
34
+ data: {
35
+ note: 'SES verification stubbed - AWS SDK integration pending'
36
+ }
37
+ };
38
+ }
39
+ catch (error) {
40
+ return {
41
+ success: false,
42
+ error: error instanceof Error ? error.message : 'SES verification failed'
43
+ };
44
+ }
45
+ }
46
+ }
47
+ exports.SESProvider = SESProvider;
@@ -0,0 +1,12 @@
1
+ import { SenderIdentity, SenderIdentityResult } from '../types.js';
2
+ /**
3
+ * SMTP provider for sender verification
4
+ * Note: SMTP doesn't require provider-level verification
5
+ */
6
+ export declare class SMTPProvider {
7
+ /**
8
+ * Verify sender with SMTP
9
+ * SMTP doesn't require provider verification - just email validation
10
+ */
11
+ verifySender(_sender: SenderIdentity): Promise<SenderIdentityResult<Record<string, unknown>>>;
12
+ }
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ /*
3
+ Copyright (c) 2025 Bernier LLC
4
+
5
+ This file is licensed to the client under a limited-use license.
6
+ The client may use and modify this code *only within the scope of the project it was delivered for*.
7
+ Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.SMTPProvider = void 0;
11
+ /**
12
+ * SMTP provider for sender verification
13
+ * Note: SMTP doesn't require provider-level verification
14
+ */
15
+ class SMTPProvider {
16
+ /**
17
+ * Verify sender with SMTP
18
+ * SMTP doesn't require provider verification - just email validation
19
+ */
20
+ async verifySender(_sender) {
21
+ // SMTP doesn't require provider-level verification
22
+ return {
23
+ success: true,
24
+ data: {
25
+ note: 'SMTP does not require provider-level verification'
26
+ }
27
+ };
28
+ }
29
+ }
30
+ exports.SMTPProvider = SMTPProvider;
@@ -0,0 +1,19 @@
1
+ import { SenderIdentity, SenderIdentityResult } from '../types.js';
2
+ /**
3
+ * SendGrid provider for sender verification
4
+ */
5
+ export declare class SendGridProvider {
6
+ private apiKey;
7
+ constructor(apiKey: string);
8
+ /**
9
+ * Verify sender with SendGrid
10
+ */
11
+ verifySender(sender: SenderIdentity): Promise<SenderIdentityResult<{
12
+ providerId: string;
13
+ metadata: Record<string, unknown>;
14
+ }>>;
15
+ /**
16
+ * Make SendGrid API request
17
+ */
18
+ private sendGridRequest;
19
+ }
@@ -0,0 +1,98 @@
1
+ "use strict";
2
+ /*
3
+ Copyright (c) 2025 Bernier LLC
4
+
5
+ This file is licensed to the client under a limited-use license.
6
+ The client may use and modify this code *only within the scope of the project it was delivered for*.
7
+ Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.SendGridProvider = void 0;
11
+ /**
12
+ * SendGrid provider for sender verification
13
+ */
14
+ class SendGridProvider {
15
+ constructor(apiKey) {
16
+ this.apiKey = apiKey;
17
+ }
18
+ /**
19
+ * Verify sender with SendGrid
20
+ */
21
+ async verifySender(sender) {
22
+ try {
23
+ if (!this.apiKey) {
24
+ return {
25
+ success: false,
26
+ error: 'SendGrid API key not configured'
27
+ };
28
+ }
29
+ // Create verified sender in SendGrid
30
+ const response = await this.sendGridRequest('POST', '/verified_senders', {
31
+ nickname: sender.name,
32
+ from_email: sender.email,
33
+ from_name: sender.name,
34
+ reply_to: sender.replyToEmail,
35
+ reply_to_name: sender.replyToName,
36
+ address: '123 Main St',
37
+ city: 'Anytown',
38
+ state: 'CA', // Must be 2-character state code per SendGrid API requirements
39
+ zip: '12345',
40
+ country: 'US'
41
+ });
42
+ if (!response.success) {
43
+ return {
44
+ success: false,
45
+ error: 'SendGrid verification failed',
46
+ errors: [response.error || 'Unknown SendGrid error']
47
+ };
48
+ }
49
+ return {
50
+ success: true,
51
+ data: {
52
+ providerId: response.data?.id || '',
53
+ metadata: response.data || {}
54
+ }
55
+ };
56
+ }
57
+ catch (error) {
58
+ return {
59
+ success: false,
60
+ error: error instanceof Error ? error.message : 'SendGrid verification failed'
61
+ };
62
+ }
63
+ }
64
+ /**
65
+ * Make SendGrid API request
66
+ */
67
+ async sendGridRequest(method, path, body) {
68
+ try {
69
+ const response = await fetch(`https://api.sendgrid.com/v3${path}`, {
70
+ method,
71
+ headers: {
72
+ 'Authorization': `Bearer ${this.apiKey}`,
73
+ 'Content-Type': 'application/json'
74
+ },
75
+ body: body ? JSON.stringify(body) : undefined
76
+ });
77
+ const data = await response.json();
78
+ if (!response.ok) {
79
+ return {
80
+ success: false,
81
+ error: data.errors?.[0]?.message || 'SendGrid API error',
82
+ errors: data.errors?.map((e) => e.message)
83
+ };
84
+ }
85
+ return {
86
+ success: true,
87
+ data: data
88
+ };
89
+ }
90
+ catch (error) {
91
+ return {
92
+ success: false,
93
+ error: error instanceof Error ? error.message : 'SendGrid request failed'
94
+ };
95
+ }
96
+ }
97
+ }
98
+ exports.SendGridProvider = SendGridProvider;
@@ -0,0 +1,9 @@
1
+ import { SenderIdentity } from '../types.js';
2
+ /**
3
+ * Build HTML verification email
4
+ */
5
+ export declare function buildVerificationEmailHtml(sender: SenderIdentity, verificationUrl: string): string;
6
+ /**
7
+ * Build plain text verification email
8
+ */
9
+ export declare function buildVerificationEmailText(sender: SenderIdentity, verificationUrl: string): string;
@@ -0,0 +1,67 @@
1
+ "use strict";
2
+ /*
3
+ Copyright (c) 2025 Bernier LLC
4
+
5
+ This file is licensed to the client under a limited-use license.
6
+ The client may use and modify this code *only within the scope of the project it was delivered for*.
7
+ Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.buildVerificationEmailHtml = buildVerificationEmailHtml;
11
+ exports.buildVerificationEmailText = buildVerificationEmailText;
12
+ /**
13
+ * Build HTML verification email
14
+ */
15
+ function buildVerificationEmailHtml(sender, verificationUrl) {
16
+ return `
17
+ <!DOCTYPE html>
18
+ <html>
19
+ <head>
20
+ <style>
21
+ body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; }
22
+ .container { max-width: 600px; margin: 0 auto; padding: 20px; }
23
+ .button { background-color: #007bff; color: white; padding: 12px 24px; text-decoration: none; border-radius: 4px; display: inline-block; margin: 20px 0; }
24
+ .footer { margin-top: 40px; padding-top: 20px; border-top: 1px solid #ddd; font-size: 12px; color: #666; }
25
+ </style>
26
+ </head>
27
+ <body>
28
+ <div class="container">
29
+ <h1>Verify Your Sender Email Address</h1>
30
+ <p>Hello ${sender.name},</p>
31
+ <p>You've added <strong>${sender.email}</strong> as a sender email address for ${sender.provider}.</p>
32
+ <p>To complete the verification process, please click the button below:</p>
33
+ <a href="${verificationUrl}" class="button">Verify Email Address</a>
34
+ <p>Or copy and paste this URL into your browser:</p>
35
+ <p>${verificationUrl}</p>
36
+ <p><strong>This link will expire in 24 hours.</strong></p>
37
+ <div class="footer">
38
+ <p>If you didn't request this verification, please ignore this email.</p>
39
+ <p>Sender ID: ${sender.id}</p>
40
+ </div>
41
+ </div>
42
+ </body>
43
+ </html>
44
+ `;
45
+ }
46
+ /**
47
+ * Build plain text verification email
48
+ */
49
+ function buildVerificationEmailText(sender, verificationUrl) {
50
+ return `
51
+ Verify Your Sender Email Address
52
+
53
+ Hello ${sender.name},
54
+
55
+ You've added ${sender.email} as a sender email address for ${sender.provider}.
56
+
57
+ To complete the verification process, please visit:
58
+
59
+ ${verificationUrl}
60
+
61
+ This link will expire in 24 hours.
62
+
63
+ If you didn't request this verification, please ignore this email.
64
+
65
+ Sender ID: ${sender.id}
66
+ `.trim();
67
+ }
@@ -0,0 +1,139 @@
1
+ /**
2
+ * Sender identity record
3
+ */
4
+ export interface SenderIdentity {
5
+ id: string;
6
+ email: string;
7
+ name: string;
8
+ replyToEmail?: string;
9
+ replyToName?: string;
10
+ domain: string;
11
+ provider: EmailProvider;
12
+ status: SenderStatus;
13
+ isDefault: boolean;
14
+ isActive: boolean;
15
+ verifiedAt?: Date;
16
+ verificationToken?: string;
17
+ verificationSentAt?: Date;
18
+ verificationExpiresAt?: Date;
19
+ verificationAttempts: number;
20
+ providerSenderId?: string;
21
+ providerMetadata?: Record<string, unknown>;
22
+ lastValidated?: Date;
23
+ validationErrors?: string[];
24
+ createdAt: Date;
25
+ updatedAt: Date;
26
+ deletedAt?: Date;
27
+ }
28
+ /**
29
+ * Sender status enum
30
+ */
31
+ export declare enum SenderStatus {
32
+ PENDING = "pending",// Created, awaiting verification
33
+ VERIFICATION_SENT = "verification_sent",// Verification email sent
34
+ VERIFIED = "verified",// Email verified, ready to use
35
+ FAILED = "failed",// Verification failed
36
+ EXPIRED = "expired",// Verification token expired
37
+ LOCKED = "locked",// Too many failed attempts
38
+ INACTIVE = "inactive"
39
+ }
40
+ /**
41
+ * Email provider enum
42
+ */
43
+ export declare enum EmailProvider {
44
+ SENDGRID = "sendgrid",
45
+ MAILGUN = "mailgun",
46
+ SES = "ses",
47
+ SMTP = "smtp"
48
+ }
49
+ /**
50
+ * Sender creation input
51
+ */
52
+ export interface CreateSenderInput {
53
+ email: string;
54
+ name: string;
55
+ replyToEmail?: string;
56
+ replyToName?: string;
57
+ provider: EmailProvider;
58
+ isDefault?: boolean;
59
+ skipVerification?: boolean;
60
+ }
61
+ /**
62
+ * Sender update input
63
+ */
64
+ export interface UpdateSenderInput {
65
+ name?: string;
66
+ replyToEmail?: string;
67
+ replyToName?: string;
68
+ isDefault?: boolean;
69
+ isActive?: boolean;
70
+ }
71
+ /**
72
+ * Verification result
73
+ */
74
+ export interface VerificationResult {
75
+ success: boolean;
76
+ senderId: string;
77
+ status: SenderStatus;
78
+ message: string;
79
+ verifiedAt?: Date;
80
+ errors?: string[];
81
+ }
82
+ /**
83
+ * Provider compliance check result
84
+ */
85
+ export interface ComplianceCheckResult {
86
+ isCompliant: boolean;
87
+ checks: {
88
+ domainVerified: boolean;
89
+ spfValid: boolean;
90
+ dkimValid: boolean;
91
+ emailFormat: boolean;
92
+ };
93
+ errors: string[];
94
+ warnings: string[];
95
+ }
96
+ /**
97
+ * Sender list options
98
+ */
99
+ export interface ListSendersOptions {
100
+ provider?: EmailProvider;
101
+ status?: SenderStatus;
102
+ isActive?: boolean;
103
+ domain?: string;
104
+ limit?: number;
105
+ offset?: number;
106
+ }
107
+ /**
108
+ * Package result wrapper
109
+ */
110
+ export interface SenderIdentityResult<T = unknown> {
111
+ success: boolean;
112
+ data?: T;
113
+ error?: string;
114
+ errors?: string[];
115
+ }
116
+ /**
117
+ * Domain verification status (interface for missing @bernierllc/email-domain-verification)
118
+ * TODO: Replace with actual import when email-domain-verification package is available
119
+ */
120
+ export interface DomainVerificationStatus {
121
+ isVerified: boolean;
122
+ domain: string;
123
+ verificationUrl?: string;
124
+ dnsRecords?: {
125
+ spf?: {
126
+ isValid: boolean;
127
+ };
128
+ dkim?: {
129
+ isValid: boolean;
130
+ };
131
+ };
132
+ }
133
+ /**
134
+ * Email domain verification interface (stub for missing dependency)
135
+ * TODO: Replace with actual @bernierllc/email-domain-verification when available
136
+ */
137
+ export interface IEmailDomainVerification {
138
+ getDomainStatus(domain: string): Promise<DomainVerificationStatus>;
139
+ }