@bernierllc/email-sender 2.0.2 → 3.0.5
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 +138 -0
- package/dist/core/email-safety-manager.d.ts +30 -0
- package/dist/core/email-safety-manager.d.ts.map +1 -0
- package/dist/core/email-safety-manager.js +106 -0
- package/dist/core/email-safety-manager.js.map +1 -0
- package/dist/core/email-sender.d.ts +23 -5
- package/dist/core/email-sender.d.ts.map +1 -1
- package/dist/core/email-sender.js +55 -2
- package/dist/core/email-sender.js.map +1 -1
- package/dist/index.d.ts +5 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -1
- package/dist/index.js.map +1 -1
- package/dist/providers/sendgrid/client.d.ts +26 -0
- package/dist/providers/sendgrid/client.d.ts.map +1 -0
- package/dist/providers/sendgrid/client.js +71 -0
- package/dist/providers/sendgrid/client.js.map +1 -0
- package/dist/providers/sendgrid/converters.d.ts +19 -0
- package/dist/providers/sendgrid/converters.d.ts.map +1 -0
- package/dist/providers/sendgrid/converters.js +54 -0
- package/dist/providers/sendgrid/converters.js.map +1 -0
- package/dist/providers/sendgrid/errors.d.ts +23 -0
- package/dist/providers/sendgrid/errors.d.ts.map +1 -0
- package/dist/providers/sendgrid/errors.js +53 -0
- package/dist/providers/sendgrid/errors.js.map +1 -0
- package/dist/providers/sendgrid/index.d.ts +13 -0
- package/dist/providers/sendgrid/index.d.ts.map +1 -0
- package/dist/providers/sendgrid/index.js +39 -0
- package/dist/providers/sendgrid/index.js.map +1 -0
- package/dist/providers/sendgrid/rate-limiter.d.ts +18 -0
- package/dist/providers/sendgrid/rate-limiter.d.ts.map +1 -0
- package/dist/providers/sendgrid/rate-limiter.js +69 -0
- package/dist/providers/sendgrid/rate-limiter.js.map +1 -0
- package/dist/providers/sendgrid/safety.d.ts +32 -0
- package/dist/providers/sendgrid/safety.d.ts.map +1 -0
- package/dist/providers/sendgrid/safety.js +82 -0
- package/dist/providers/sendgrid/safety.js.map +1 -0
- package/dist/providers/sendgrid/sender-manager.d.ts +25 -0
- package/dist/providers/sendgrid/sender-manager.d.ts.map +1 -0
- package/dist/providers/sendgrid/sender-manager.js +126 -0
- package/dist/providers/sendgrid/sender-manager.js.map +1 -0
- package/dist/providers/sendgrid/template-manager.d.ts +29 -0
- package/dist/providers/sendgrid/template-manager.d.ts.map +1 -0
- package/dist/providers/sendgrid/template-manager.js +153 -0
- package/dist/providers/sendgrid/template-manager.js.map +1 -0
- package/dist/providers/sendgrid/types.d.ts +136 -0
- package/dist/providers/sendgrid/types.d.ts.map +1 -0
- package/dist/providers/sendgrid/types.js +10 -0
- package/dist/providers/sendgrid/types.js.map +1 -0
- package/dist/providers/sendgrid.d.ts +63 -2
- package/dist/providers/sendgrid.d.ts.map +1 -1
- package/dist/providers/sendgrid.js +145 -1
- package/dist/providers/sendgrid.js.map +1 -1
- package/dist/types/index.d.ts +15 -0
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +12 -3
|
@@ -0,0 +1,54 @@
|
|
|
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.SenderConverter = exports.TemplateConverter = void 0;
|
|
11
|
+
class TemplateConverter {
|
|
12
|
+
constructor(prefixEnforcer) {
|
|
13
|
+
this.prefixEnforcer = prefixEnforcer;
|
|
14
|
+
}
|
|
15
|
+
convertToProviderTemplate(data) {
|
|
16
|
+
const activeVersion = data.versions?.find(v => v.active === 1);
|
|
17
|
+
return {
|
|
18
|
+
id: data.id,
|
|
19
|
+
name: this.prefixEnforcer ? this.prefixEnforcer.removePrefix(data.name) : data.name,
|
|
20
|
+
subject: activeVersion?.subject || '',
|
|
21
|
+
htmlContent: activeVersion?.html_content || '',
|
|
22
|
+
textContent: activeVersion?.plain_content || '',
|
|
23
|
+
version: activeVersion?.name || '1.0.0',
|
|
24
|
+
active: Boolean(activeVersion),
|
|
25
|
+
createdAt: new Date(data.updated_at),
|
|
26
|
+
updatedAt: new Date(data.updated_at)
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
exports.TemplateConverter = TemplateConverter;
|
|
31
|
+
class SenderConverter {
|
|
32
|
+
convertToVerifiedSender(data) {
|
|
33
|
+
const lastVerifiedAt = data.verified ? new Date() : undefined;
|
|
34
|
+
return {
|
|
35
|
+
id: String(data.id),
|
|
36
|
+
email: data.from_email,
|
|
37
|
+
name: data.from_name || data.nickname,
|
|
38
|
+
isVerified: data.verified,
|
|
39
|
+
domain: this.extractDomain(data.from_email),
|
|
40
|
+
verificationStatus: data.verified ? 'verified' : (data.locked ? 'failed' : 'pending'),
|
|
41
|
+
createdAt: new Date(), // SendGrid API doesn't provide this
|
|
42
|
+
...(lastVerifiedAt && { lastVerifiedAt })
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
extractDomain(email) {
|
|
46
|
+
const match = email.match(/@(.+)$/);
|
|
47
|
+
return match?.[1] ?? '';
|
|
48
|
+
}
|
|
49
|
+
isDomainMatch(domain1, domain2) {
|
|
50
|
+
return domain1.toLowerCase() === domain2.toLowerCase();
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
exports.SenderConverter = SenderConverter;
|
|
54
|
+
//# sourceMappingURL=converters.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"converters.js","sourceRoot":"","sources":["../../../src/providers/sendgrid/converters.ts"],"names":[],"mappings":";AAAA;;;;;;EAME;;;AAcF,MAAa,iBAAiB;IAC5B,YAA6B,cAAkG;QAAlG,mBAAc,GAAd,cAAc,CAAoF;IAAG,CAAC;IAEnI,yBAAyB,CAAC,IAA0B;QAClD,MAAM,aAAa,GAAG,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC;QAE/D,OAAO;YACL,EAAE,EAAE,IAAI,CAAC,EAAE;YACX,IAAI,EAAE,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI;YACnF,OAAO,EAAE,aAAa,EAAE,OAAO,IAAI,EAAE;YACrC,WAAW,EAAE,aAAa,EAAE,YAAY,IAAI,EAAE;YAC9C,WAAW,EAAE,aAAa,EAAE,aAAa,IAAI,EAAE;YAC/C,OAAO,EAAE,aAAa,EAAE,IAAI,IAAI,OAAO;YACvC,MAAM,EAAE,OAAO,CAAC,aAAa,CAAC;YAC9B,SAAS,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC;YACpC,SAAS,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC;SACrC,CAAC;IACJ,CAAC;CACF;AAlBD,8CAkBC;AAED,MAAa,eAAe;IAC1B,uBAAuB,CAAC,IAAgC;QACtD,MAAM,cAAc,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;QAC9D,OAAO;YACL,EAAE,EAAE,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;YACnB,KAAK,EAAE,IAAI,CAAC,UAAU;YACtB,IAAI,EAAE,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,QAAQ;YACrC,UAAU,EAAE,IAAI,CAAC,QAAQ;YACzB,MAAM,EAAE,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,UAAU,CAAC;YAC3C,kBAAkB,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC;YACrF,SAAS,EAAE,IAAI,IAAI,EAAE,EAAE,oCAAoC;YAC3D,GAAG,CAAC,cAAc,IAAI,EAAE,cAAc,EAAE,CAAC;SAC1C,CAAC;IACJ,CAAC;IAED,aAAa,CAAC,KAAa;QACzB,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QACpC,OAAO,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAC1B,CAAC;IAED,aAAa,CAAC,OAAe,EAAE,OAAe;QAC5C,OAAO,OAAO,CAAC,WAAW,EAAE,KAAK,OAAO,CAAC,WAAW,EAAE,CAAC;IACzD,CAAC;CACF;AAvBD,0CAuBC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SendGrid-specific error classes
|
|
3
|
+
* Merged from @bernierllc/email-sendgrid-plugin v1.0.1
|
|
4
|
+
*/
|
|
5
|
+
export declare class SendGridApiError extends Error {
|
|
6
|
+
statusCode?: number | undefined;
|
|
7
|
+
response?: unknown | undefined;
|
|
8
|
+
constructor(message: string, statusCode?: number | undefined, response?: unknown | undefined);
|
|
9
|
+
}
|
|
10
|
+
export declare class TemplateNotFoundError extends Error {
|
|
11
|
+
constructor(templateId: string);
|
|
12
|
+
}
|
|
13
|
+
export declare class UnauthorizedTemplateAccessError extends Error {
|
|
14
|
+
constructor(templateId: string);
|
|
15
|
+
}
|
|
16
|
+
export declare class TemplateConflictError extends Error {
|
|
17
|
+
conflicts: string[];
|
|
18
|
+
constructor(templateId: string, conflicts: string[]);
|
|
19
|
+
}
|
|
20
|
+
export declare class RateLimitError extends Error {
|
|
21
|
+
constructor(message: string);
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../../src/providers/sendgrid/errors.ts"],"names":[],"mappings":"AAQA;;;GAGG;AAEH,qBAAa,gBAAiB,SAAQ,KAAK;IAGhC,UAAU,CAAC,EAAE,MAAM;IACnB,QAAQ,CAAC,EAAE,OAAO;gBAFzB,OAAO,EAAE,MAAM,EACR,UAAU,CAAC,EAAE,MAAM,YAAA,EACnB,QAAQ,CAAC,EAAE,OAAO,YAAA;CAK5B;AAED,qBAAa,qBAAsB,SAAQ,KAAK;gBAClC,UAAU,EAAE,MAAM;CAI/B;AAED,qBAAa,+BAAgC,SAAQ,KAAK;gBAC5C,UAAU,EAAE,MAAM;CAI/B;AAED,qBAAa,qBAAsB,SAAQ,KAAK;IAGrC,SAAS,EAAE,MAAM,EAAE;gBAD1B,UAAU,EAAE,MAAM,EACX,SAAS,EAAE,MAAM,EAAE;CAK7B;AAED,qBAAa,cAAe,SAAQ,KAAK;gBAC3B,OAAO,EAAE,MAAM;CAI5B"}
|
|
@@ -0,0 +1,53 @@
|
|
|
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.RateLimitError = exports.TemplateConflictError = exports.UnauthorizedTemplateAccessError = exports.TemplateNotFoundError = exports.SendGridApiError = void 0;
|
|
11
|
+
/**
|
|
12
|
+
* SendGrid-specific error classes
|
|
13
|
+
* Merged from @bernierllc/email-sendgrid-plugin v1.0.1
|
|
14
|
+
*/
|
|
15
|
+
class SendGridApiError extends Error {
|
|
16
|
+
constructor(message, statusCode, response) {
|
|
17
|
+
super(message);
|
|
18
|
+
this.statusCode = statusCode;
|
|
19
|
+
this.response = response;
|
|
20
|
+
this.name = 'SendGridApiError';
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
exports.SendGridApiError = SendGridApiError;
|
|
24
|
+
class TemplateNotFoundError extends Error {
|
|
25
|
+
constructor(templateId) {
|
|
26
|
+
super(`Template not found: ${templateId}`);
|
|
27
|
+
this.name = 'TemplateNotFoundError';
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
exports.TemplateNotFoundError = TemplateNotFoundError;
|
|
31
|
+
class UnauthorizedTemplateAccessError extends Error {
|
|
32
|
+
constructor(templateId) {
|
|
33
|
+
super(`Unauthorized access to template: ${templateId}`);
|
|
34
|
+
this.name = 'UnauthorizedTemplateAccessError';
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
exports.UnauthorizedTemplateAccessError = UnauthorizedTemplateAccessError;
|
|
38
|
+
class TemplateConflictError extends Error {
|
|
39
|
+
constructor(templateId, conflicts) {
|
|
40
|
+
super(`Template conflict detected for ${templateId}: ${conflicts.join(', ')}`);
|
|
41
|
+
this.conflicts = conflicts;
|
|
42
|
+
this.name = 'TemplateConflictError';
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
exports.TemplateConflictError = TemplateConflictError;
|
|
46
|
+
class RateLimitError extends Error {
|
|
47
|
+
constructor(message) {
|
|
48
|
+
super(message);
|
|
49
|
+
this.name = 'RateLimitError';
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
exports.RateLimitError = RateLimitError;
|
|
53
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../../src/providers/sendgrid/errors.ts"],"names":[],"mappings":";AAAA;;;;;;EAME;;;AAEF;;;GAGG;AAEH,MAAa,gBAAiB,SAAQ,KAAK;IACzC,YACE,OAAe,EACR,UAAmB,EACnB,QAAkB;QAEzB,KAAK,CAAC,OAAO,CAAC,CAAC;QAHR,eAAU,GAAV,UAAU,CAAS;QACnB,aAAQ,GAAR,QAAQ,CAAU;QAGzB,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAC;IACjC,CAAC;CACF;AATD,4CASC;AAED,MAAa,qBAAsB,SAAQ,KAAK;IAC9C,YAAY,UAAkB;QAC5B,KAAK,CAAC,uBAAuB,UAAU,EAAE,CAAC,CAAC;QAC3C,IAAI,CAAC,IAAI,GAAG,uBAAuB,CAAC;IACtC,CAAC;CACF;AALD,sDAKC;AAED,MAAa,+BAAgC,SAAQ,KAAK;IACxD,YAAY,UAAkB;QAC5B,KAAK,CAAC,oCAAoC,UAAU,EAAE,CAAC,CAAC;QACxD,IAAI,CAAC,IAAI,GAAG,iCAAiC,CAAC;IAChD,CAAC;CACF;AALD,0EAKC;AAED,MAAa,qBAAsB,SAAQ,KAAK;IAC9C,YACE,UAAkB,EACX,SAAmB;QAE1B,KAAK,CAAC,kCAAkC,UAAU,KAAK,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAFxE,cAAS,GAAT,SAAS,CAAU;QAG1B,IAAI,CAAC,IAAI,GAAG,uBAAuB,CAAC;IACtC,CAAC;CACF;AARD,sDAQC;AAED,MAAa,cAAe,SAAQ,KAAK;IACvC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAC;IAC/B,CAAC;CACF;AALD,wCAKC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SendGrid advanced features module
|
|
3
|
+
* Consolidated from @bernierllc/email-sendgrid-plugin v1.0.1
|
|
4
|
+
*/
|
|
5
|
+
export { SendGridClient, type SendGridClientConfig } from './client';
|
|
6
|
+
export { TemplateManager } from './template-manager';
|
|
7
|
+
export { SenderManager } from './sender-manager';
|
|
8
|
+
export { SimpleRateLimiter, type RateLimiterConfig } from './rate-limiter';
|
|
9
|
+
export { TemplateConverter, SenderConverter } from './converters';
|
|
10
|
+
export { OwnershipValidator, PrefixEnforcer, type SafetyMode } from './safety';
|
|
11
|
+
export { SendGridApiError, TemplateNotFoundError, UnauthorizedTemplateAccessError, TemplateConflictError, RateLimitError } from './errors';
|
|
12
|
+
export type { VerifiedSender, SenderValidationResult, SendGridTemplateData, SendGridTemplateVersion, SendGridVerifiedSenderData, Template, ProviderTemplate, TemplateVersion, SyncResult, TemplateAnalytics, ApiRequestOptions, ApiResponse, SendGridAdvancedConfig } from './types';
|
|
13
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/providers/sendgrid/index.ts"],"names":[],"mappings":"AAQA;;;GAGG;AAGH,OAAO,EAAE,cAAc,EAAE,KAAK,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAGrE,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAGjD,OAAO,EAAE,iBAAiB,EAAE,KAAK,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAC3E,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAClE,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,KAAK,UAAU,EAAE,MAAM,UAAU,CAAC;AAG/E,OAAO,EACL,gBAAgB,EAChB,qBAAqB,EACrB,+BAA+B,EAC/B,qBAAqB,EACrB,cAAc,EACf,MAAM,UAAU,CAAC;AAGlB,YAAY,EACV,cAAc,EACd,sBAAsB,EACtB,oBAAoB,EACpB,uBAAuB,EACvB,0BAA0B,EAC1B,QAAQ,EACR,gBAAgB,EAChB,eAAe,EACf,UAAU,EACV,iBAAiB,EACjB,iBAAiB,EACjB,WAAW,EACX,sBAAsB,EACvB,MAAM,SAAS,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
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.RateLimitError = exports.TemplateConflictError = exports.UnauthorizedTemplateAccessError = exports.TemplateNotFoundError = exports.SendGridApiError = exports.PrefixEnforcer = exports.OwnershipValidator = exports.SenderConverter = exports.TemplateConverter = exports.SimpleRateLimiter = exports.SenderManager = exports.TemplateManager = exports.SendGridClient = void 0;
|
|
11
|
+
/**
|
|
12
|
+
* SendGrid advanced features module
|
|
13
|
+
* Consolidated from @bernierllc/email-sendgrid-plugin v1.0.1
|
|
14
|
+
*/
|
|
15
|
+
// Client
|
|
16
|
+
var client_1 = require("./client");
|
|
17
|
+
Object.defineProperty(exports, "SendGridClient", { enumerable: true, get: function () { return client_1.SendGridClient; } });
|
|
18
|
+
// Managers
|
|
19
|
+
var template_manager_1 = require("./template-manager");
|
|
20
|
+
Object.defineProperty(exports, "TemplateManager", { enumerable: true, get: function () { return template_manager_1.TemplateManager; } });
|
|
21
|
+
var sender_manager_1 = require("./sender-manager");
|
|
22
|
+
Object.defineProperty(exports, "SenderManager", { enumerable: true, get: function () { return sender_manager_1.SenderManager; } });
|
|
23
|
+
// Utilities
|
|
24
|
+
var rate_limiter_1 = require("./rate-limiter");
|
|
25
|
+
Object.defineProperty(exports, "SimpleRateLimiter", { enumerable: true, get: function () { return rate_limiter_1.SimpleRateLimiter; } });
|
|
26
|
+
var converters_1 = require("./converters");
|
|
27
|
+
Object.defineProperty(exports, "TemplateConverter", { enumerable: true, get: function () { return converters_1.TemplateConverter; } });
|
|
28
|
+
Object.defineProperty(exports, "SenderConverter", { enumerable: true, get: function () { return converters_1.SenderConverter; } });
|
|
29
|
+
var safety_1 = require("./safety");
|
|
30
|
+
Object.defineProperty(exports, "OwnershipValidator", { enumerable: true, get: function () { return safety_1.OwnershipValidator; } });
|
|
31
|
+
Object.defineProperty(exports, "PrefixEnforcer", { enumerable: true, get: function () { return safety_1.PrefixEnforcer; } });
|
|
32
|
+
// Errors
|
|
33
|
+
var errors_1 = require("./errors");
|
|
34
|
+
Object.defineProperty(exports, "SendGridApiError", { enumerable: true, get: function () { return errors_1.SendGridApiError; } });
|
|
35
|
+
Object.defineProperty(exports, "TemplateNotFoundError", { enumerable: true, get: function () { return errors_1.TemplateNotFoundError; } });
|
|
36
|
+
Object.defineProperty(exports, "UnauthorizedTemplateAccessError", { enumerable: true, get: function () { return errors_1.UnauthorizedTemplateAccessError; } });
|
|
37
|
+
Object.defineProperty(exports, "TemplateConflictError", { enumerable: true, get: function () { return errors_1.TemplateConflictError; } });
|
|
38
|
+
Object.defineProperty(exports, "RateLimitError", { enumerable: true, get: function () { return errors_1.RateLimitError; } });
|
|
39
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/providers/sendgrid/index.ts"],"names":[],"mappings":";AAAA;;;;;;EAME;;;AAEF;;;GAGG;AAEH,SAAS;AACT,mCAAqE;AAA5D,wGAAA,cAAc,OAAA;AAEvB,WAAW;AACX,uDAAqD;AAA5C,mHAAA,eAAe,OAAA;AACxB,mDAAiD;AAAxC,+GAAA,aAAa,OAAA;AAEtB,YAAY;AACZ,+CAA2E;AAAlE,iHAAA,iBAAiB,OAAA;AAC1B,2CAAkE;AAAzD,+GAAA,iBAAiB,OAAA;AAAE,6GAAA,eAAe,OAAA;AAC3C,mCAA+E;AAAtE,4GAAA,kBAAkB,OAAA;AAAE,wGAAA,cAAc,OAAA;AAE3C,SAAS;AACT,mCAMkB;AALhB,0GAAA,gBAAgB,OAAA;AAChB,+GAAA,qBAAqB,OAAA;AACrB,yHAAA,+BAA+B,OAAA;AAC/B,+GAAA,qBAAqB,OAAA;AACrB,wGAAA,cAAc,OAAA"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface RateLimiterConfig {
|
|
2
|
+
maxRequestsPerSecond: number;
|
|
3
|
+
maxRequestsPerMinute: number;
|
|
4
|
+
}
|
|
5
|
+
export declare class SimpleRateLimiter {
|
|
6
|
+
private requestTimestamps;
|
|
7
|
+
private readonly maxRequestsPerSecond;
|
|
8
|
+
private readonly maxRequestsPerMinute;
|
|
9
|
+
constructor(config: RateLimiterConfig);
|
|
10
|
+
acquire(): Promise<void>;
|
|
11
|
+
release(): void;
|
|
12
|
+
private sleep;
|
|
13
|
+
getRemainingCapacity(): {
|
|
14
|
+
perSecond: number;
|
|
15
|
+
perMinute: number;
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=rate-limiter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rate-limiter.d.ts","sourceRoot":"","sources":["../../../src/providers/sendgrid/rate-limiter.ts"],"names":[],"mappings":"AAeA,MAAM,WAAW,iBAAiB;IAChC,oBAAoB,EAAE,MAAM,CAAC;IAC7B,oBAAoB,EAAE,MAAM,CAAC;CAC9B;AAED,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,iBAAiB,CAAgB;IACzC,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAS;IAC9C,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAS;gBAElC,MAAM,EAAE,iBAAiB;IAK/B,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAuC9B,OAAO,IAAI,IAAI;IAIf,OAAO,CAAC,KAAK;IAIb,oBAAoB,IAAI;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE;CAYjE"}
|
|
@@ -0,0 +1,69 @@
|
|
|
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.SimpleRateLimiter = void 0;
|
|
11
|
+
/**
|
|
12
|
+
* Simple rate limiter for SendGrid API calls
|
|
13
|
+
* Merged from @bernierllc/email-sendgrid-plugin v1.0.1
|
|
14
|
+
*/
|
|
15
|
+
const errors_1 = require("./errors");
|
|
16
|
+
class SimpleRateLimiter {
|
|
17
|
+
constructor(config) {
|
|
18
|
+
this.requestTimestamps = [];
|
|
19
|
+
this.maxRequestsPerSecond = config.maxRequestsPerSecond;
|
|
20
|
+
this.maxRequestsPerMinute = config.maxRequestsPerMinute;
|
|
21
|
+
}
|
|
22
|
+
async acquire() {
|
|
23
|
+
const now = Date.now();
|
|
24
|
+
// Clean up old timestamps
|
|
25
|
+
this.requestTimestamps = this.requestTimestamps.filter(timestamp => now - timestamp < 60000 // Keep last minute
|
|
26
|
+
);
|
|
27
|
+
// Check per-second limit
|
|
28
|
+
const lastSecond = this.requestTimestamps.filter(timestamp => now - timestamp < 1000);
|
|
29
|
+
if (lastSecond.length >= this.maxRequestsPerSecond) {
|
|
30
|
+
const firstTimestamp = lastSecond[0];
|
|
31
|
+
if (firstTimestamp) {
|
|
32
|
+
const waitTime = 1000 - (now - firstTimestamp);
|
|
33
|
+
await this.sleep(waitTime);
|
|
34
|
+
return this.acquire();
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
// Check per-minute limit
|
|
38
|
+
if (this.requestTimestamps.length >= this.maxRequestsPerMinute) {
|
|
39
|
+
const firstTimestamp = this.requestTimestamps[0];
|
|
40
|
+
if (firstTimestamp) {
|
|
41
|
+
const waitTime = 60000 - (now - firstTimestamp);
|
|
42
|
+
if (waitTime > 5000) {
|
|
43
|
+
throw new errors_1.RateLimitError(`Rate limit exceeded, would need to wait ${Math.ceil(waitTime / 1000)}s`);
|
|
44
|
+
}
|
|
45
|
+
await this.sleep(waitTime);
|
|
46
|
+
return this.acquire();
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
// Add timestamp and proceed
|
|
50
|
+
this.requestTimestamps.push(now);
|
|
51
|
+
}
|
|
52
|
+
release() {
|
|
53
|
+
// No-op for simple implementation
|
|
54
|
+
}
|
|
55
|
+
sleep(ms) {
|
|
56
|
+
return new Promise(resolve => setTimeout(resolve, Math.max(0, ms)));
|
|
57
|
+
}
|
|
58
|
+
getRemainingCapacity() {
|
|
59
|
+
const now = Date.now();
|
|
60
|
+
const lastSecond = this.requestTimestamps.filter(timestamp => now - timestamp < 1000).length;
|
|
61
|
+
const lastMinute = this.requestTimestamps.length;
|
|
62
|
+
return {
|
|
63
|
+
perSecond: Math.max(0, this.maxRequestsPerSecond - lastSecond),
|
|
64
|
+
perMinute: Math.max(0, this.maxRequestsPerMinute - lastMinute)
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
exports.SimpleRateLimiter = SimpleRateLimiter;
|
|
69
|
+
//# sourceMappingURL=rate-limiter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rate-limiter.js","sourceRoot":"","sources":["../../../src/providers/sendgrid/rate-limiter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export type SafetyMode = 'strict' | 'relaxed';
|
|
2
|
+
/**
|
|
3
|
+
* Validates ownership of templates to prevent accidental modification
|
|
4
|
+
* of templates not managed by this application
|
|
5
|
+
*/
|
|
6
|
+
export declare class OwnershipValidator {
|
|
7
|
+
private readonly mode;
|
|
8
|
+
private readonly logger?;
|
|
9
|
+
private managedTemplateIds;
|
|
10
|
+
constructor(mode?: SafetyMode, logger?: {
|
|
11
|
+
info: (message: string) => void;
|
|
12
|
+
error: (message: string) => void;
|
|
13
|
+
} | undefined);
|
|
14
|
+
registerTemplate(templateId: string): void;
|
|
15
|
+
unregisterTemplate(templateId: string): void;
|
|
16
|
+
validateOwnership(templateId: string): void;
|
|
17
|
+
isManaged(templateId: string): boolean;
|
|
18
|
+
clearRegistrations(): void;
|
|
19
|
+
getManagedCount(): number;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Enforces template naming prefix to prevent namespace conflicts
|
|
23
|
+
*/
|
|
24
|
+
export declare class PrefixEnforcer {
|
|
25
|
+
private readonly prefix;
|
|
26
|
+
constructor(prefix?: string);
|
|
27
|
+
applyPrefix(name: string): string;
|
|
28
|
+
removePrefix(name: string): string;
|
|
29
|
+
hasPrefix(name: string): boolean;
|
|
30
|
+
getPrefix(): string;
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=safety.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"safety.d.ts","sourceRoot":"","sources":["../../../src/providers/sendgrid/safety.ts"],"names":[],"mappings":"AAeA,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,SAAS,CAAC;AAE9C;;;GAGG;AACH,qBAAa,kBAAkB;IAI3B,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC;IAJ1B,OAAO,CAAC,kBAAkB,CAA0B;gBAGjC,IAAI,GAAE,UAAqB,EAC3B,MAAM,CAAC,EAAE;QACxB,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;QAChC,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;KAClC,YAAA;IAGH,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAK1C,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAK5C,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAW3C,SAAS,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO;IAItC,kBAAkB,IAAI,IAAI;IAK1B,eAAe,IAAI,MAAM;CAG1B;AAED;;GAEG;AACH,qBAAa,cAAc;IACb,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAAN,MAAM,GAAE,MAAe;IAEpD,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAOjC,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAOlC,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAIhC,SAAS,IAAI,MAAM;CAGpB"}
|
|
@@ -0,0 +1,82 @@
|
|
|
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.PrefixEnforcer = exports.OwnershipValidator = void 0;
|
|
11
|
+
/**
|
|
12
|
+
* Safety validators for template management
|
|
13
|
+
* Merged from @bernierllc/email-sendgrid-plugin v1.0.1
|
|
14
|
+
*/
|
|
15
|
+
const errors_1 = require("./errors");
|
|
16
|
+
/**
|
|
17
|
+
* Validates ownership of templates to prevent accidental modification
|
|
18
|
+
* of templates not managed by this application
|
|
19
|
+
*/
|
|
20
|
+
class OwnershipValidator {
|
|
21
|
+
constructor(mode = 'strict', logger) {
|
|
22
|
+
this.mode = mode;
|
|
23
|
+
this.logger = logger;
|
|
24
|
+
this.managedTemplateIds = new Set();
|
|
25
|
+
}
|
|
26
|
+
registerTemplate(templateId) {
|
|
27
|
+
this.managedTemplateIds.add(templateId);
|
|
28
|
+
this.logger?.info(`Registered template as app-managed: ${templateId}`);
|
|
29
|
+
}
|
|
30
|
+
unregisterTemplate(templateId) {
|
|
31
|
+
this.managedTemplateIds.delete(templateId);
|
|
32
|
+
this.logger?.info(`Unregistered template: ${templateId}`);
|
|
33
|
+
}
|
|
34
|
+
validateOwnership(templateId) {
|
|
35
|
+
if (this.mode === 'relaxed') {
|
|
36
|
+
return; // Skip validation in relaxed mode
|
|
37
|
+
}
|
|
38
|
+
if (!this.managedTemplateIds.has(templateId)) {
|
|
39
|
+
this.logger?.error(`Attempted to access unmanaged template: ${templateId}`);
|
|
40
|
+
throw new errors_1.UnauthorizedTemplateAccessError(templateId);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
isManaged(templateId) {
|
|
44
|
+
return this.managedTemplateIds.has(templateId);
|
|
45
|
+
}
|
|
46
|
+
clearRegistrations() {
|
|
47
|
+
this.managedTemplateIds.clear();
|
|
48
|
+
this.logger?.info('Cleared all template registrations');
|
|
49
|
+
}
|
|
50
|
+
getManagedCount() {
|
|
51
|
+
return this.managedTemplateIds.size;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
exports.OwnershipValidator = OwnershipValidator;
|
|
55
|
+
/**
|
|
56
|
+
* Enforces template naming prefix to prevent namespace conflicts
|
|
57
|
+
*/
|
|
58
|
+
class PrefixEnforcer {
|
|
59
|
+
constructor(prefix = 'app_') {
|
|
60
|
+
this.prefix = prefix;
|
|
61
|
+
}
|
|
62
|
+
applyPrefix(name) {
|
|
63
|
+
if (this.hasPrefix(name)) {
|
|
64
|
+
return name;
|
|
65
|
+
}
|
|
66
|
+
return `${this.prefix}${name}`;
|
|
67
|
+
}
|
|
68
|
+
removePrefix(name) {
|
|
69
|
+
if (this.hasPrefix(name)) {
|
|
70
|
+
return name.substring(this.prefix.length);
|
|
71
|
+
}
|
|
72
|
+
return name;
|
|
73
|
+
}
|
|
74
|
+
hasPrefix(name) {
|
|
75
|
+
return name.startsWith(this.prefix);
|
|
76
|
+
}
|
|
77
|
+
getPrefix() {
|
|
78
|
+
return this.prefix;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
exports.PrefixEnforcer = PrefixEnforcer;
|
|
82
|
+
//# sourceMappingURL=safety.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"safety.js","sourceRoot":"","sources":["../../../src/providers/sendgrid/safety.ts"],"names":[],"mappings":";AAAA;;;;;;EAME;;;AAEF;;;GAGG;AAEH,qCAA2D;AAI3D;;;GAGG;AACH,MAAa,kBAAkB;IAG7B,YACmB,OAAmB,QAAQ,EAC3B,MAGhB;QAJgB,SAAI,GAAJ,IAAI,CAAuB;QAC3B,WAAM,GAAN,MAAM,CAGtB;QAPK,uBAAkB,GAAgB,IAAI,GAAG,EAAE,CAAC;IAQjD,CAAC;IAEJ,gBAAgB,CAAC,UAAkB;QACjC,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QACxC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,uCAAuC,UAAU,EAAE,CAAC,CAAC;IACzE,CAAC;IAED,kBAAkB,CAAC,UAAkB;QACnC,IAAI,CAAC,kBAAkB,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;QAC3C,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,0BAA0B,UAAU,EAAE,CAAC,CAAC;IAC5D,CAAC;IAED,iBAAiB,CAAC,UAAkB;QAClC,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YAC5B,OAAO,CAAC,kCAAkC;QAC5C,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC;YAC7C,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,2CAA2C,UAAU,EAAE,CAAC,CAAC;YAC5E,MAAM,IAAI,wCAA+B,CAAC,UAAU,CAAC,CAAC;QACxD,CAAC;IACH,CAAC;IAED,SAAS,CAAC,UAAkB;QAC1B,OAAO,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IACjD,CAAC;IAED,kBAAkB;QAChB,IAAI,CAAC,kBAAkB,CAAC,KAAK,EAAE,CAAC;QAChC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,oCAAoC,CAAC,CAAC;IAC1D,CAAC;IAED,eAAe;QACb,OAAO,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC;IACtC,CAAC;CACF;AA5CD,gDA4CC;AAED;;GAEG;AACH,MAAa,cAAc;IACzB,YAA6B,SAAiB,MAAM;QAAvB,WAAM,GAAN,MAAM,CAAiB;IAAG,CAAC;IAExD,WAAW,CAAC,IAAY;QACtB,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;YACzB,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,GAAG,IAAI,CAAC,MAAM,GAAG,IAAI,EAAE,CAAC;IACjC,CAAC;IAED,YAAY,CAAC,IAAY;QACvB,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;YACzB,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAC5C,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,SAAS,CAAC,IAAY;QACpB,OAAO,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACtC,CAAC;IAED,SAAS;QACP,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;CACF;AAxBD,wCAwBC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Verified sender management for SendGrid
|
|
3
|
+
* Merged from @bernierllc/email-sendgrid-plugin v1.0.1
|
|
4
|
+
*/
|
|
5
|
+
import { SendGridClient } from './client';
|
|
6
|
+
import { SenderConverter } from './converters';
|
|
7
|
+
import { VerifiedSender, SenderValidationResult } from './types';
|
|
8
|
+
export declare class SenderManager {
|
|
9
|
+
private readonly client;
|
|
10
|
+
private readonly converter;
|
|
11
|
+
private readonly logger?;
|
|
12
|
+
private sendersCache?;
|
|
13
|
+
private cacheTimestamp?;
|
|
14
|
+
private readonly cacheTTL;
|
|
15
|
+
constructor(client: SendGridClient, converter: SenderConverter, logger?: {
|
|
16
|
+
info: (message: string) => void;
|
|
17
|
+
debug: (message: string) => void;
|
|
18
|
+
} | undefined);
|
|
19
|
+
getVerifiedSenders(useCache?: boolean): Promise<VerifiedSender[]>;
|
|
20
|
+
validateSender(email: string): Promise<SenderValidationResult>;
|
|
21
|
+
selectBestSender(fromEmail: string): Promise<VerifiedSender | null>;
|
|
22
|
+
clearCache(): void;
|
|
23
|
+
private getSenderSuggestions;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=sender-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sender-manager.d.ts","sourceRoot":"","sources":["../../../src/providers/sendgrid/sender-manager.ts"],"names":[],"mappings":"AAQA;;;GAGG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAE1C,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EACL,cAAc,EACd,sBAAsB,EAEvB,MAAM,SAAS,CAAC;AAEjB,qBAAa,aAAa;IAMtB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC;IAP1B,OAAO,CAAC,YAAY,CAAC,CAAmB;IACxC,OAAO,CAAC,cAAc,CAAC,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAU;gBAGhB,MAAM,EAAE,cAAc,EACtB,SAAS,EAAE,eAAe,EAC1B,MAAM,CAAC,EAAE;QACxB,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;QAChC,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;KAClC,YAAA;IAGG,kBAAkB,CAAC,QAAQ,UAAO,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IAoC9D,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,sBAAsB,CAAC;IA8C9D,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;IA0BzE,UAAU,IAAI,IAAI;IAMlB,OAAO,CAAC,oBAAoB;CAsB7B"}
|
|
@@ -0,0 +1,126 @@
|
|
|
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.SenderManager = void 0;
|
|
11
|
+
const errors_1 = require("./errors");
|
|
12
|
+
class SenderManager {
|
|
13
|
+
constructor(client, converter, logger) {
|
|
14
|
+
this.client = client;
|
|
15
|
+
this.converter = converter;
|
|
16
|
+
this.logger = logger;
|
|
17
|
+
this.cacheTTL = 300000; // 5 minutes
|
|
18
|
+
}
|
|
19
|
+
async getVerifiedSenders(useCache = true) {
|
|
20
|
+
// Return cached data if valid
|
|
21
|
+
if (useCache &&
|
|
22
|
+
this.sendersCache &&
|
|
23
|
+
this.cacheTimestamp &&
|
|
24
|
+
Date.now() - this.cacheTimestamp < this.cacheTTL) {
|
|
25
|
+
this.logger?.debug('Returning cached verified senders');
|
|
26
|
+
return this.sendersCache;
|
|
27
|
+
}
|
|
28
|
+
const response = await this.client.request('/verified_senders', {
|
|
29
|
+
method: 'GET'
|
|
30
|
+
});
|
|
31
|
+
if (!this.client.isSuccessResponse(response)) {
|
|
32
|
+
throw new errors_1.SendGridApiError('Failed to fetch verified senders', response.statusCode, response.body);
|
|
33
|
+
}
|
|
34
|
+
const data = this.client.parseResponseBody(response);
|
|
35
|
+
const senders = data.results.map(sender => this.converter.convertToVerifiedSender(sender));
|
|
36
|
+
// Update cache
|
|
37
|
+
this.sendersCache = senders;
|
|
38
|
+
this.cacheTimestamp = Date.now();
|
|
39
|
+
this.logger?.info(`Fetched ${senders.length} verified senders from SendGrid`);
|
|
40
|
+
return senders;
|
|
41
|
+
}
|
|
42
|
+
async validateSender(email) {
|
|
43
|
+
const verifiedSenders = await this.getVerifiedSenders();
|
|
44
|
+
const emailDomain = this.converter.extractDomain(email);
|
|
45
|
+
// Check for exact match
|
|
46
|
+
const exactMatch = verifiedSenders.find(sender => sender.email.toLowerCase() === email.toLowerCase() && sender.isVerified);
|
|
47
|
+
if (exactMatch) {
|
|
48
|
+
return {
|
|
49
|
+
isValid: true,
|
|
50
|
+
verifiedSender: exactMatch,
|
|
51
|
+
domain: emailDomain,
|
|
52
|
+
domainMatches: [exactMatch],
|
|
53
|
+
errors: [],
|
|
54
|
+
suggestions: []
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
// Check for domain matches
|
|
58
|
+
const domainMatches = verifiedSenders.filter(sender => {
|
|
59
|
+
const senderDomain = this.converter.extractDomain(sender.email);
|
|
60
|
+
return this.converter.isDomainMatch(emailDomain, senderDomain) && sender.isVerified;
|
|
61
|
+
});
|
|
62
|
+
if (domainMatches.length > 0) {
|
|
63
|
+
return {
|
|
64
|
+
isValid: true,
|
|
65
|
+
domain: emailDomain,
|
|
66
|
+
domainMatches,
|
|
67
|
+
errors: [],
|
|
68
|
+
suggestions: domainMatches.map(sender => sender.email)
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
// No matches found
|
|
72
|
+
return {
|
|
73
|
+
isValid: false,
|
|
74
|
+
domain: emailDomain,
|
|
75
|
+
domainMatches: [],
|
|
76
|
+
errors: [`No verified sender found for email ${email} or domain ${emailDomain}`],
|
|
77
|
+
suggestions: this.getSenderSuggestions(email, verifiedSenders)
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
async selectBestSender(fromEmail) {
|
|
81
|
+
const validation = await this.validateSender(fromEmail);
|
|
82
|
+
if (!validation.isValid || validation.domainMatches.length === 0) {
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
// Prefer exact match
|
|
86
|
+
if (validation.verifiedSender) {
|
|
87
|
+
return validation.verifiedSender;
|
|
88
|
+
}
|
|
89
|
+
// Fall back to best domain match
|
|
90
|
+
// Priority: most recently verified, then alphabetical
|
|
91
|
+
const bestMatch = validation.domainMatches.sort((a, b) => {
|
|
92
|
+
if (a.lastVerifiedAt && b.lastVerifiedAt) {
|
|
93
|
+
return b.lastVerifiedAt.getTime() - a.lastVerifiedAt.getTime();
|
|
94
|
+
}
|
|
95
|
+
if (a.lastVerifiedAt && !b.lastVerifiedAt)
|
|
96
|
+
return -1;
|
|
97
|
+
if (!a.lastVerifiedAt && b.lastVerifiedAt)
|
|
98
|
+
return 1;
|
|
99
|
+
return a.email.localeCompare(b.email);
|
|
100
|
+
})[0];
|
|
101
|
+
return bestMatch || null;
|
|
102
|
+
}
|
|
103
|
+
clearCache() {
|
|
104
|
+
this.sendersCache = [];
|
|
105
|
+
this.cacheTimestamp = 0;
|
|
106
|
+
this.logger?.debug('Cleared verified senders cache');
|
|
107
|
+
}
|
|
108
|
+
getSenderSuggestions(email, senders) {
|
|
109
|
+
const emailDomain = this.converter.extractDomain(email);
|
|
110
|
+
// Find senders with similar domains
|
|
111
|
+
const suggestions = [];
|
|
112
|
+
for (const sender of senders) {
|
|
113
|
+
if (!sender.isVerified)
|
|
114
|
+
continue;
|
|
115
|
+
const senderDomain = this.converter.extractDomain(sender.email);
|
|
116
|
+
// Check for partial domain matches
|
|
117
|
+
if (emailDomain.includes(senderDomain) ||
|
|
118
|
+
senderDomain.includes(emailDomain)) {
|
|
119
|
+
suggestions.push(sender.email);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return suggestions.slice(0, 5); // Limit to 5 suggestions
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
exports.SenderManager = SenderManager;
|
|
126
|
+
//# sourceMappingURL=sender-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sender-manager.js","sourceRoot":"","sources":["../../../src/providers/sendgrid/sender-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Template management for SendGrid
|
|
3
|
+
* Merged from @bernierllc/email-sendgrid-plugin v1.0.1
|
|
4
|
+
*/
|
|
5
|
+
import { SendGridClient } from './client';
|
|
6
|
+
import { OwnershipValidator, PrefixEnforcer } from './safety';
|
|
7
|
+
import { TemplateConverter } from './converters';
|
|
8
|
+
import { Template, ProviderTemplate, TemplateVersion } from './types';
|
|
9
|
+
export declare class TemplateManager {
|
|
10
|
+
private readonly client;
|
|
11
|
+
private readonly ownershipValidator;
|
|
12
|
+
private readonly prefixEnforcer;
|
|
13
|
+
private readonly converter;
|
|
14
|
+
private readonly logger?;
|
|
15
|
+
constructor(client: SendGridClient, ownershipValidator: OwnershipValidator, prefixEnforcer: PrefixEnforcer, converter: TemplateConverter, logger?: {
|
|
16
|
+
info: (message: string) => void;
|
|
17
|
+
error: (message: string) => void;
|
|
18
|
+
} | undefined);
|
|
19
|
+
createTemplate(template: Template): Promise<string>;
|
|
20
|
+
updateTemplate(providerTemplateId: string, template: Template): Promise<void>;
|
|
21
|
+
deleteTemplate(providerTemplateId: string): Promise<void>;
|
|
22
|
+
getTemplate(providerTemplateId: string): Promise<ProviderTemplate>;
|
|
23
|
+
listTemplates(): Promise<ProviderTemplate[]>;
|
|
24
|
+
createTemplateVersion(templateId: string, version: TemplateVersion): Promise<string>;
|
|
25
|
+
activateTemplateVersion(templateId: string, versionId: string): Promise<void>;
|
|
26
|
+
private hasConflicts;
|
|
27
|
+
private detectConflicts;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=template-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"template-manager.d.ts","sourceRoot":"","sources":["../../../src/providers/sendgrid/template-manager.ts"],"names":[],"mappings":"AAQA;;;GAGG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAE1C,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,EACL,QAAQ,EACR,gBAAgB,EAChB,eAAe,EAGhB,MAAM,SAAS,CAAC;AAEjB,qBAAa,eAAe;IAExB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,kBAAkB;IACnC,OAAO,CAAC,QAAQ,CAAC,cAAc;IAC/B,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC;gBAJP,MAAM,EAAE,cAAc,EACtB,kBAAkB,EAAE,kBAAkB,EACtC,cAAc,EAAE,cAAc,EAC9B,SAAS,EAAE,iBAAiB,EAC5B,MAAM,CAAC,EAAE;QACxB,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;QAChC,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;KAClC,YAAA;IAGG,cAAc,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC;IA4CnD,cAAc,CAAC,kBAAkB,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IA2B7E,cAAc,CAAC,kBAAkB,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAmBzD,WAAW,CAAC,kBAAkB,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAuBlE,aAAa,IAAI,OAAO,CAAC,gBAAgB,EAAE,CAAC;IA8B5C,qBAAqB,CACzB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,eAAe,GACvB,OAAO,CAAC,MAAM,CAAC;IA2BZ,uBAAuB,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAiBnF,OAAO,CAAC,YAAY;IAKpB,OAAO,CAAC,eAAe;CAaxB"}
|