@bernierllc/email-sender-manager 1.0.1
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/LICENSE +5 -0
- package/README.md +466 -0
- package/dist/__tests__/manager.test.d.ts +2 -0
- package/dist/__tests__/manager.test.d.ts.map +1 -0
- package/dist/__tests__/manager.test.js +344 -0
- package/dist/__tests__/manager.test.js.map +1 -0
- package/dist/__tests__/mocks/mock-database.d.ts +15 -0
- package/dist/__tests__/mocks/mock-database.d.ts.map +1 -0
- package/dist/__tests__/mocks/mock-database.js +219 -0
- package/dist/__tests__/mocks/mock-database.js.map +1 -0
- package/dist/__tests__/selection/selector.test.d.ts +2 -0
- package/dist/__tests__/selection/selector.test.d.ts.map +1 -0
- package/dist/__tests__/selection/selector.test.js +351 -0
- package/dist/__tests__/selection/selector.test.js.map +1 -0
- package/dist/__tests__/utils/domain-utils.test.d.ts +2 -0
- package/dist/__tests__/utils/domain-utils.test.d.ts.map +1 -0
- package/dist/__tests__/utils/domain-utils.test.js +91 -0
- package/dist/__tests__/utils/domain-utils.test.js.map +1 -0
- package/dist/__tests__/utils/validation-utils.test.d.ts +2 -0
- package/dist/__tests__/utils/validation-utils.test.d.ts.map +1 -0
- package/dist/__tests__/utils/validation-utils.test.js +117 -0
- package/dist/__tests__/utils/validation-utils.test.js.map +1 -0
- package/dist/database/bootstrap.d.ts +35 -0
- package/dist/database/bootstrap.d.ts.map +1 -0
- package/dist/database/bootstrap.js +183 -0
- package/dist/database/bootstrap.js.map +1 -0
- package/dist/database/schema.d.ts +13 -0
- package/dist/database/schema.d.ts.map +1 -0
- package/dist/database/schema.js +72 -0
- package/dist/database/schema.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/dist/manager.d.ts +85 -0
- package/dist/manager.d.ts.map +1 -0
- package/dist/manager.js +469 -0
- package/dist/manager.js.map +1 -0
- package/dist/selection/selector.d.ts +27 -0
- package/dist/selection/selector.d.ts.map +1 -0
- package/dist/selection/selector.js +107 -0
- package/dist/selection/selector.js.map +1 -0
- package/dist/types.d.ts +257 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +9 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/domain-utils.d.ts +21 -0
- package/dist/utils/domain-utils.d.ts.map +1 -0
- package/dist/utils/domain-utils.js +65 -0
- package/dist/utils/domain-utils.js.map +1 -0
- package/dist/utils/validation-utils.d.ts +23 -0
- package/dist/utils/validation-utils.d.ts.map +1 -0
- package/dist/utils/validation-utils.js +148 -0
- package/dist/utils/validation-utils.js.map +1 -0
- package/package.json +49 -0
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sender configuration model
|
|
3
|
+
*/
|
|
4
|
+
export interface SenderConfiguration {
|
|
5
|
+
id: string;
|
|
6
|
+
name: string;
|
|
7
|
+
description?: string;
|
|
8
|
+
fromEmail: string;
|
|
9
|
+
fromName: string;
|
|
10
|
+
replyToEmail?: string;
|
|
11
|
+
replyToName?: string;
|
|
12
|
+
provider: string;
|
|
13
|
+
providerSenderId?: string;
|
|
14
|
+
providerMetadata?: Record<string, unknown>;
|
|
15
|
+
isVerified: boolean;
|
|
16
|
+
verificationStatus: 'pending' | 'verified' | 'failed' | 'expired';
|
|
17
|
+
lastVerifiedAt?: Date;
|
|
18
|
+
verificationError?: string;
|
|
19
|
+
isDefault: boolean;
|
|
20
|
+
isActive: boolean;
|
|
21
|
+
priority: number;
|
|
22
|
+
allowedDomains?: string[];
|
|
23
|
+
domain: string;
|
|
24
|
+
createdAt: Date;
|
|
25
|
+
updatedAt: Date;
|
|
26
|
+
createdBy: string;
|
|
27
|
+
lastModifiedBy: string;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Request to create a new sender
|
|
31
|
+
*/
|
|
32
|
+
export interface CreateSenderRequest {
|
|
33
|
+
name: string;
|
|
34
|
+
description?: string;
|
|
35
|
+
fromEmail: string;
|
|
36
|
+
fromName: string;
|
|
37
|
+
replyToEmail?: string;
|
|
38
|
+
replyToName?: string;
|
|
39
|
+
provider: string;
|
|
40
|
+
providerSenderId?: string;
|
|
41
|
+
providerMetadata?: Record<string, unknown>;
|
|
42
|
+
allowedDomains?: string[];
|
|
43
|
+
priority?: number;
|
|
44
|
+
createdBy: string;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Request to update an existing sender
|
|
48
|
+
*/
|
|
49
|
+
export interface UpdateSenderRequest {
|
|
50
|
+
name?: string;
|
|
51
|
+
description?: string;
|
|
52
|
+
fromName?: string;
|
|
53
|
+
replyToEmail?: string;
|
|
54
|
+
replyToName?: string;
|
|
55
|
+
providerSenderId?: string;
|
|
56
|
+
providerMetadata?: Record<string, unknown>;
|
|
57
|
+
isVerified?: boolean;
|
|
58
|
+
verificationStatus?: 'pending' | 'verified' | 'failed' | 'expired';
|
|
59
|
+
lastVerifiedAt?: Date;
|
|
60
|
+
verificationError?: string;
|
|
61
|
+
isDefault?: boolean;
|
|
62
|
+
isActive?: boolean;
|
|
63
|
+
priority?: number;
|
|
64
|
+
allowedDomains?: string[];
|
|
65
|
+
lastModifiedBy: string;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Options for listing senders
|
|
69
|
+
*/
|
|
70
|
+
export interface ListSendersOptions {
|
|
71
|
+
provider?: string;
|
|
72
|
+
isActive?: boolean;
|
|
73
|
+
isVerified?: boolean;
|
|
74
|
+
domain?: string;
|
|
75
|
+
offset?: number;
|
|
76
|
+
limit?: number;
|
|
77
|
+
orderBy?: 'priority' | 'createdAt' | 'name';
|
|
78
|
+
orderDirection?: 'asc' | 'desc';
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Paginated result
|
|
82
|
+
*/
|
|
83
|
+
export interface PaginatedResult<T> {
|
|
84
|
+
items: T[];
|
|
85
|
+
total: number;
|
|
86
|
+
offset: number;
|
|
87
|
+
limit: number;
|
|
88
|
+
hasMore: boolean;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Validation error
|
|
92
|
+
*/
|
|
93
|
+
export interface ValidationError {
|
|
94
|
+
field: string;
|
|
95
|
+
message: string;
|
|
96
|
+
code: string;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Validation warning
|
|
100
|
+
*/
|
|
101
|
+
export interface ValidationWarning {
|
|
102
|
+
field: string;
|
|
103
|
+
message: string;
|
|
104
|
+
code: string;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Provider validation result
|
|
108
|
+
*/
|
|
109
|
+
export interface ProviderValidationResult {
|
|
110
|
+
isVerified: boolean;
|
|
111
|
+
verificationStatus: string;
|
|
112
|
+
lastChecked: Date;
|
|
113
|
+
metadata: Record<string, unknown>;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Sender validation result
|
|
117
|
+
*/
|
|
118
|
+
export interface SenderValidationResult {
|
|
119
|
+
isValid: boolean;
|
|
120
|
+
errors: ValidationError[];
|
|
121
|
+
warnings: ValidationWarning[];
|
|
122
|
+
providerValidation?: ProviderValidationResult;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Verification result
|
|
126
|
+
*/
|
|
127
|
+
export interface VerificationResult {
|
|
128
|
+
success: boolean;
|
|
129
|
+
isVerified: boolean;
|
|
130
|
+
verificationStatus: string;
|
|
131
|
+
message?: string;
|
|
132
|
+
error?: string;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Selection options for choosing a sender
|
|
136
|
+
*/
|
|
137
|
+
export interface SelectionOptions {
|
|
138
|
+
strategy?: 'priority' | 'domain_match' | 'round_robin';
|
|
139
|
+
allowUnverified?: boolean;
|
|
140
|
+
provider?: string;
|
|
141
|
+
excludeIds?: string[];
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Domain matching rule
|
|
145
|
+
*/
|
|
146
|
+
export interface DomainMatchingRule {
|
|
147
|
+
pattern: string;
|
|
148
|
+
priority: number;
|
|
149
|
+
allowSubdomains: boolean;
|
|
150
|
+
allowParentDomains: boolean;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Bootstrap configuration
|
|
154
|
+
*/
|
|
155
|
+
export interface BootstrapConfig {
|
|
156
|
+
enabled: boolean;
|
|
157
|
+
createTables: boolean;
|
|
158
|
+
seedDefaultSenders: boolean;
|
|
159
|
+
defaultSenders: Omit<CreateSenderRequest, 'createdBy'>[];
|
|
160
|
+
environment: 'development' | 'staging' | 'production';
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Selection configuration
|
|
164
|
+
*/
|
|
165
|
+
export interface SelectionConfig {
|
|
166
|
+
strategy: 'priority' | 'domain_match' | 'round_robin' | 'custom';
|
|
167
|
+
fallbackToDefault: boolean;
|
|
168
|
+
domainMatchingRules: DomainMatchingRule[];
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Validation configuration
|
|
172
|
+
*/
|
|
173
|
+
export interface ValidationConfig {
|
|
174
|
+
requireVerification: boolean;
|
|
175
|
+
allowUnverifiedSenders: boolean;
|
|
176
|
+
validateDomainOwnership: boolean;
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Database adapter interface
|
|
180
|
+
*/
|
|
181
|
+
export interface DatabaseAdapter {
|
|
182
|
+
execute(query: string, params?: unknown[]): Promise<void>;
|
|
183
|
+
query<T = unknown>(query: string, params?: unknown[]): Promise<T[]>;
|
|
184
|
+
queryOne<T = unknown>(query: string, params?: unknown[]): Promise<T | null>;
|
|
185
|
+
transaction<T>(callback: (adapter: DatabaseAdapter) => Promise<T>): Promise<T>;
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Provider sender information
|
|
189
|
+
*/
|
|
190
|
+
export interface ProviderSender {
|
|
191
|
+
id: string;
|
|
192
|
+
email: string;
|
|
193
|
+
name: string;
|
|
194
|
+
isVerified: boolean;
|
|
195
|
+
verificationStatus: string;
|
|
196
|
+
domain: string;
|
|
197
|
+
metadata: Record<string, unknown>;
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Provider plugin interface
|
|
201
|
+
*/
|
|
202
|
+
export interface SenderProviderPlugin {
|
|
203
|
+
readonly providerId: string;
|
|
204
|
+
readonly name: string;
|
|
205
|
+
validateSender(email: string): Promise<ProviderValidationResult>;
|
|
206
|
+
getVerifiedSenders(): Promise<ProviderSender[]>;
|
|
207
|
+
syncSender(sender: SenderConfiguration): Promise<SyncResult>;
|
|
208
|
+
getCapabilities(): string[];
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Sync result
|
|
212
|
+
*/
|
|
213
|
+
export interface SyncResult {
|
|
214
|
+
success: boolean;
|
|
215
|
+
senderId: string;
|
|
216
|
+
synced: boolean;
|
|
217
|
+
message?: string;
|
|
218
|
+
error?: string;
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Bootstrap result
|
|
222
|
+
*/
|
|
223
|
+
export interface BootstrapResult {
|
|
224
|
+
success: boolean;
|
|
225
|
+
tablesCreated: boolean;
|
|
226
|
+
seedersRun: number;
|
|
227
|
+
message: string;
|
|
228
|
+
errors?: string[];
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Cleanup result
|
|
232
|
+
*/
|
|
233
|
+
export interface CleanupResult {
|
|
234
|
+
success: boolean;
|
|
235
|
+
deletedCount: number;
|
|
236
|
+
message: string;
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Sender manager configuration
|
|
240
|
+
*/
|
|
241
|
+
export interface SenderManagerConfig {
|
|
242
|
+
database: DatabaseAdapter;
|
|
243
|
+
providers?: SenderProviderPlugin[];
|
|
244
|
+
bootstrap?: Partial<BootstrapConfig>;
|
|
245
|
+
validation?: Partial<ValidationConfig>;
|
|
246
|
+
selection?: Partial<SelectionConfig>;
|
|
247
|
+
systemUser?: string;
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Route conflict information
|
|
251
|
+
*/
|
|
252
|
+
export interface RouteConflict {
|
|
253
|
+
path: string;
|
|
254
|
+
conflictingRoutes: string[];
|
|
255
|
+
reason: string;
|
|
256
|
+
}
|
|
257
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
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
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;EAME"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extract domain from email address
|
|
3
|
+
*/
|
|
4
|
+
export declare function extractDomain(email: string): string;
|
|
5
|
+
/**
|
|
6
|
+
* Check if a domain matches a pattern (supports wildcards)
|
|
7
|
+
*/
|
|
8
|
+
export declare function isDomainMatch(domain: string, pattern: string): boolean;
|
|
9
|
+
/**
|
|
10
|
+
* Validate email format
|
|
11
|
+
*/
|
|
12
|
+
export declare function isValidEmail(email: string): boolean;
|
|
13
|
+
/**
|
|
14
|
+
* Get parent domain (e.g., app.example.com -> example.com)
|
|
15
|
+
*/
|
|
16
|
+
export declare function getParentDomain(domain: string): string | null;
|
|
17
|
+
/**
|
|
18
|
+
* Check if domain is a subdomain of another
|
|
19
|
+
*/
|
|
20
|
+
export declare function isSubdomainOf(subdomain: string, parentDomain: string): boolean;
|
|
21
|
+
//# sourceMappingURL=domain-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"domain-utils.d.ts","sourceRoot":"","sources":["../../src/utils/domain-utils.ts"],"names":[],"mappings":"AAQA;;GAEG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAMnD;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAsBtE;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAGnD;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAM7D;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAE9E"}
|
|
@@ -0,0 +1,65 @@
|
|
|
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
|
+
* Extract domain from email address
|
|
10
|
+
*/
|
|
11
|
+
export function extractDomain(email) {
|
|
12
|
+
const match = email.match(/^.+@(.+)$/);
|
|
13
|
+
if (!match || !match[1]) {
|
|
14
|
+
throw new Error(`Invalid email format: ${email}`);
|
|
15
|
+
}
|
|
16
|
+
return match[1].toLowerCase();
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Check if a domain matches a pattern (supports wildcards)
|
|
20
|
+
*/
|
|
21
|
+
export function isDomainMatch(domain, pattern) {
|
|
22
|
+
const normalizedDomain = domain.toLowerCase();
|
|
23
|
+
const normalizedPattern = pattern.toLowerCase();
|
|
24
|
+
// Support glob patterns
|
|
25
|
+
if (normalizedPattern.includes('*')) {
|
|
26
|
+
const regexPattern = normalizedPattern
|
|
27
|
+
.replace(/\./g, '\\.')
|
|
28
|
+
.replace(/\*/g, '.*');
|
|
29
|
+
return new RegExp(`^${regexPattern}$`).test(normalizedDomain);
|
|
30
|
+
}
|
|
31
|
+
// Exact match
|
|
32
|
+
if (normalizedDomain === normalizedPattern)
|
|
33
|
+
return true;
|
|
34
|
+
// Subdomain match (e.g., app.example.com matches example.com)
|
|
35
|
+
if (normalizedDomain.endsWith(`.${normalizedPattern}`))
|
|
36
|
+
return true;
|
|
37
|
+
// Parent domain match (e.g., example.com matches app.example.com)
|
|
38
|
+
if (normalizedPattern.endsWith(`.${normalizedDomain}`))
|
|
39
|
+
return true;
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Validate email format
|
|
44
|
+
*/
|
|
45
|
+
export function isValidEmail(email) {
|
|
46
|
+
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
47
|
+
return emailRegex.test(email);
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Get parent domain (e.g., app.example.com -> example.com)
|
|
51
|
+
*/
|
|
52
|
+
export function getParentDomain(domain) {
|
|
53
|
+
const parts = domain.split('.');
|
|
54
|
+
if (parts.length <= 2) {
|
|
55
|
+
return null; // Already at top-level domain
|
|
56
|
+
}
|
|
57
|
+
return parts.slice(1).join('.');
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Check if domain is a subdomain of another
|
|
61
|
+
*/
|
|
62
|
+
export function isSubdomainOf(subdomain, parentDomain) {
|
|
63
|
+
return subdomain.toLowerCase().endsWith(`.${parentDomain.toLowerCase()}`);
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=domain-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"domain-utils.js","sourceRoot":"","sources":["../../src/utils/domain-utils.ts"],"names":[],"mappings":"AAAA;;;;;;EAME;AAEF;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,KAAa;IACzC,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;IACvC,IAAI,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,yBAAyB,KAAK,EAAE,CAAC,CAAC;IACpD,CAAC;IACD,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;AAChC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,MAAc,EAAE,OAAe;IAC3D,MAAM,gBAAgB,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC;IAC9C,MAAM,iBAAiB,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAEhD,wBAAwB;IACxB,IAAI,iBAAiB,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QACpC,MAAM,YAAY,GAAG,iBAAiB;aACnC,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC;aACrB,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QACxB,OAAO,IAAI,MAAM,CAAC,IAAI,YAAY,GAAG,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;IAChE,CAAC;IAED,cAAc;IACd,IAAI,gBAAgB,KAAK,iBAAiB;QAAE,OAAO,IAAI,CAAC;IAExD,8DAA8D;IAC9D,IAAI,gBAAgB,CAAC,QAAQ,CAAC,IAAI,iBAAiB,EAAE,CAAC;QAAE,OAAO,IAAI,CAAC;IAEpE,kEAAkE;IAClE,IAAI,iBAAiB,CAAC,QAAQ,CAAC,IAAI,gBAAgB,EAAE,CAAC;QAAE,OAAO,IAAI,CAAC;IAEpE,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,KAAa;IACxC,MAAM,UAAU,GAAG,4BAA4B,CAAC;IAChD,OAAO,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAChC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,MAAc;IAC5C,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAChC,IAAI,KAAK,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;QACtB,OAAO,IAAI,CAAC,CAAC,8BAA8B;IAC7C,CAAC;IACD,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,SAAiB,EAAE,YAAoB;IACnE,OAAO,SAAS,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,IAAI,YAAY,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;AAC5E,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { CreateSenderRequest, ValidationError, ValidationWarning } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Validate a create sender request
|
|
4
|
+
*/
|
|
5
|
+
export declare function validateCreateSenderRequest(request: CreateSenderRequest): {
|
|
6
|
+
errors: ValidationError[];
|
|
7
|
+
warnings: ValidationWarning[];
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Validate domain matches allowed domains
|
|
11
|
+
*/
|
|
12
|
+
export declare function validateDomainAllowed(email: string, allowedDomains?: string[]): {
|
|
13
|
+
allowed: boolean;
|
|
14
|
+
reason?: string;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Validate sender configuration before save
|
|
18
|
+
*/
|
|
19
|
+
export declare function validateSenderConfiguration(fromEmail: string, allowedDomains?: string[]): {
|
|
20
|
+
valid: boolean;
|
|
21
|
+
errors: ValidationError[];
|
|
22
|
+
};
|
|
23
|
+
//# sourceMappingURL=validation-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation-utils.d.ts","sourceRoot":"","sources":["../../src/utils/validation-utils.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,mBAAmB,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAG3F;;GAEG;AACH,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,mBAAmB,GAC3B;IAAE,MAAM,EAAE,eAAe,EAAE,CAAC;IAAC,QAAQ,EAAE,iBAAiB,EAAE,CAAA;CAAE,CAgG9D;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,MAAM,EACb,cAAc,CAAC,EAAE,MAAM,EAAE,GACxB;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAyBvC;AAED;;GAEG;AACH,wBAAgB,2BAA2B,CACzC,SAAS,EAAE,MAAM,EACjB,cAAc,CAAC,EAAE,MAAM,EAAE,GACxB;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,eAAe,EAAE,CAAA;CAAE,CAqB/C"}
|
|
@@ -0,0 +1,148 @@
|
|
|
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
|
+
import { isValidEmail, extractDomain } from './domain-utils.js';
|
|
9
|
+
/**
|
|
10
|
+
* Validate a create sender request
|
|
11
|
+
*/
|
|
12
|
+
export function validateCreateSenderRequest(request) {
|
|
13
|
+
const errors = [];
|
|
14
|
+
const warnings = [];
|
|
15
|
+
// Required fields
|
|
16
|
+
if (!request.name || request.name.trim().length === 0) {
|
|
17
|
+
errors.push({
|
|
18
|
+
field: 'name',
|
|
19
|
+
message: 'Sender name is required',
|
|
20
|
+
code: 'REQUIRED_FIELD',
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
if (!request.fromEmail || request.fromEmail.trim().length === 0) {
|
|
24
|
+
errors.push({
|
|
25
|
+
field: 'fromEmail',
|
|
26
|
+
message: 'From email is required',
|
|
27
|
+
code: 'REQUIRED_FIELD',
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
else if (!isValidEmail(request.fromEmail)) {
|
|
31
|
+
errors.push({
|
|
32
|
+
field: 'fromEmail',
|
|
33
|
+
message: 'Invalid email format',
|
|
34
|
+
code: 'INVALID_FORMAT',
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
if (!request.fromName || request.fromName.trim().length === 0) {
|
|
38
|
+
errors.push({
|
|
39
|
+
field: 'fromName',
|
|
40
|
+
message: 'From name is required',
|
|
41
|
+
code: 'REQUIRED_FIELD',
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
if (!request.provider || request.provider.trim().length === 0) {
|
|
45
|
+
errors.push({
|
|
46
|
+
field: 'provider',
|
|
47
|
+
message: 'Provider is required',
|
|
48
|
+
code: 'REQUIRED_FIELD',
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
if (!request.createdBy || request.createdBy.trim().length === 0) {
|
|
52
|
+
errors.push({
|
|
53
|
+
field: 'createdBy',
|
|
54
|
+
message: 'Created by is required',
|
|
55
|
+
code: 'REQUIRED_FIELD',
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
// Optional fields validation
|
|
59
|
+
if (request.replyToEmail && !isValidEmail(request.replyToEmail)) {
|
|
60
|
+
errors.push({
|
|
61
|
+
field: 'replyToEmail',
|
|
62
|
+
message: 'Invalid reply-to email format',
|
|
63
|
+
code: 'INVALID_FORMAT',
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
// Priority validation
|
|
67
|
+
if (request.priority !== undefined && (request.priority < 0 || !Number.isInteger(request.priority))) {
|
|
68
|
+
errors.push({
|
|
69
|
+
field: 'priority',
|
|
70
|
+
message: 'Priority must be a non-negative integer',
|
|
71
|
+
code: 'INVALID_VALUE',
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
// Allowed domains validation
|
|
75
|
+
if (request.allowedDomains) {
|
|
76
|
+
if (!Array.isArray(request.allowedDomains)) {
|
|
77
|
+
errors.push({
|
|
78
|
+
field: 'allowedDomains',
|
|
79
|
+
message: 'Allowed domains must be an array',
|
|
80
|
+
code: 'INVALID_TYPE',
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
else if (request.allowedDomains.length === 0) {
|
|
84
|
+
warnings.push({
|
|
85
|
+
field: 'allowedDomains',
|
|
86
|
+
message: 'Empty allowed domains array - sender can send from any domain',
|
|
87
|
+
code: 'EMPTY_ARRAY',
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
// Warning if no reply-to email
|
|
92
|
+
if (!request.replyToEmail && request.fromEmail) {
|
|
93
|
+
warnings.push({
|
|
94
|
+
field: 'replyToEmail',
|
|
95
|
+
message: 'No reply-to email specified - replies will go to from email',
|
|
96
|
+
code: 'MISSING_OPTIONAL',
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
return { errors, warnings };
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Validate domain matches allowed domains
|
|
103
|
+
*/
|
|
104
|
+
export function validateDomainAllowed(email, allowedDomains) {
|
|
105
|
+
if (!allowedDomains || allowedDomains.length === 0) {
|
|
106
|
+
return { allowed: true }; // No restrictions
|
|
107
|
+
}
|
|
108
|
+
try {
|
|
109
|
+
const domain = extractDomain(email);
|
|
110
|
+
const isAllowed = allowedDomains.some((allowed) => domain === allowed.toLowerCase() || domain.endsWith(`.${allowed.toLowerCase()}`));
|
|
111
|
+
if (!isAllowed) {
|
|
112
|
+
return {
|
|
113
|
+
allowed: false,
|
|
114
|
+
reason: `Domain ${domain} is not in allowed domains list: ${allowedDomains.join(', ')}`,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
return { allowed: true };
|
|
118
|
+
}
|
|
119
|
+
catch (error) {
|
|
120
|
+
return {
|
|
121
|
+
allowed: false,
|
|
122
|
+
reason: `Invalid email format: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Validate sender configuration before save
|
|
128
|
+
*/
|
|
129
|
+
export function validateSenderConfiguration(fromEmail, allowedDomains) {
|
|
130
|
+
const errors = [];
|
|
131
|
+
if (!isValidEmail(fromEmail)) {
|
|
132
|
+
errors.push({
|
|
133
|
+
field: 'fromEmail',
|
|
134
|
+
message: 'Invalid email format',
|
|
135
|
+
code: 'INVALID_FORMAT',
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
const domainCheck = validateDomainAllowed(fromEmail, allowedDomains);
|
|
139
|
+
if (!domainCheck.allowed) {
|
|
140
|
+
errors.push({
|
|
141
|
+
field: 'fromEmail',
|
|
142
|
+
message: domainCheck.reason || 'Domain not allowed',
|
|
143
|
+
code: 'DOMAIN_NOT_ALLOWED',
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
return { valid: errors.length === 0, errors };
|
|
147
|
+
}
|
|
148
|
+
//# sourceMappingURL=validation-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation-utils.js","sourceRoot":"","sources":["../../src/utils/validation-utils.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@bernierllc/email-sender-manager",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "Database-backed email sender configuration management with provider verification integration",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist",
|
|
10
|
+
"README.md",
|
|
11
|
+
"LICENSE"
|
|
12
|
+
],
|
|
13
|
+
"scripts": {
|
|
14
|
+
"build": "tsc",
|
|
15
|
+
"test": "NODE_OPTIONS=\"$NODE_OPTIONS --experimental-vm-modules\" jest --no-cache",
|
|
16
|
+
"test:watch": "NODE_OPTIONS=\"$NODE_OPTIONS --experimental-vm-modules\" jest --watch",
|
|
17
|
+
"test:coverage": "NODE_OPTIONS=\"$NODE_OPTIONS --experimental-vm-modules\" jest --coverage --no-cache",
|
|
18
|
+
"lint": "eslint src --ext .ts",
|
|
19
|
+
"clean": "rm -rf dist coverage",
|
|
20
|
+
"typecheck": "tsc --noEmit"
|
|
21
|
+
},
|
|
22
|
+
"keywords": [
|
|
23
|
+
"email",
|
|
24
|
+
"sender",
|
|
25
|
+
"configuration",
|
|
26
|
+
"database",
|
|
27
|
+
"verification",
|
|
28
|
+
"sendgrid",
|
|
29
|
+
"mailgun",
|
|
30
|
+
"email-management"
|
|
31
|
+
],
|
|
32
|
+
"author": "Bernier LLC",
|
|
33
|
+
"license": "UNLICENSED",
|
|
34
|
+
"dependencies": {},
|
|
35
|
+
"devDependencies": {
|
|
36
|
+
"@jest/globals": "^29.5.0",
|
|
37
|
+
"@types/jest": "^29.5.0",
|
|
38
|
+
"@types/node": "^18.15.0",
|
|
39
|
+
"@typescript-eslint/eslint-plugin": "^6.0.0",
|
|
40
|
+
"@typescript-eslint/parser": "^6.0.0",
|
|
41
|
+
"eslint": "^8.42.0",
|
|
42
|
+
"jest": "^29.5.0",
|
|
43
|
+
"ts-jest": "^29.0.5",
|
|
44
|
+
"typescript": "^5.0.0"
|
|
45
|
+
},
|
|
46
|
+
"publishConfig": {
|
|
47
|
+
"access": "restricted"
|
|
48
|
+
}
|
|
49
|
+
}
|