@breadstone/archipel-platform-mailing 0.0.11 → 0.0.14
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 +2 -0
- package/package.json +4 -3
- package/src/MailModule.js +5 -4
- package/src/env.d.ts +18 -18
- package/src/env.js +19 -19
- package/src/index.d.ts +1 -0
- package/src/index.js +1 -0
- package/src/mailgun/env.d.ts +3 -3
- package/src/mailgun/env.js +3 -3
- package/src/models/IMailAttachment.d.ts +31 -0
- package/src/models/IMailAttachment.js +29 -0
- package/src/postmark/env.d.ts +2 -2
- package/src/postmark/env.js +2 -2
- package/src/resend/env.d.ts +2 -2
- package/src/resend/env.js +2 -2
- package/src/sendgrid/env.d.ts +2 -2
- package/src/sendgrid/env.js +2 -2
- package/src/services/MailService.d.ts +10 -2
- package/src/services/MailService.js +31 -7
- package/src/services/MailVerificationService.d.ts +7 -2
- package/src/services/MailVerificationService.js +13 -6
- package/src/services/strategies/LogDeliveryStrategy.d.ts +2 -4
- package/src/services/strategies/LogDeliveryStrategy.js +3 -3
- package/src/services/strategies/MailgunDeliveryStrategy.d.ts +2 -2
- package/src/services/strategies/MailgunDeliveryStrategy.js +6 -2
- package/src/services/strategies/PostmarkDeliveryStrategy.d.ts +2 -2
- package/src/services/strategies/PostmarkDeliveryStrategy.js +6 -2
- package/src/services/strategies/ResendDeliveryStrategy.d.ts +2 -2
- package/src/services/strategies/ResendDeliveryStrategy.js +6 -2
- package/src/services/strategies/SendGridDeliveryStrategy.d.ts +2 -2
- package/src/services/strategies/SendGridDeliveryStrategy.js +6 -2
- package/src/services/strategies/SmtpDeliveryStrategy.d.ts +2 -2
- package/src/services/strategies/SmtpDeliveryStrategy.js +7 -3
- package/src/services/strategies/abstracts/DeliveryStrategyBase.d.ts +3 -1
- package/src/templating/MailTemplateEngine.d.ts +3 -1
- package/src/templating/MailTemplateEngine.js +23 -3
- package/src/templating/strategies/BlobTemplateFetchStrategy.d.ts +2 -1
- package/src/templating/strategies/BlobTemplateFetchStrategy.js +3 -2
- package/src/terminus/MailHealthIndicator.d.ts +2 -1
- package/src/terminus/MailHealthIndicator.js +2 -2
package/README.md
CHANGED
|
@@ -70,6 +70,8 @@ Set `MAIL_DELIVERY_STRATEGY` to one of: `smtp`, `postmark`, `resend`, `sendgrid`
|
|
|
70
70
|
- **Template engines**: File-based or blob-based template fetching with variable substitution
|
|
71
71
|
- **Health checks**: Built-in `MailHealthIndicator` for readiness probes
|
|
72
72
|
- **Email verification**: `MailVerificationService` for address verification flows
|
|
73
|
+
- **Attachment support**: Send file attachments with MIME-type validation and size limits (25 MB max)
|
|
74
|
+
- **Header injection prevention**: Subject lines are automatically sanitized against SMTP header injection
|
|
73
75
|
|
|
74
76
|
## Available Providers
|
|
75
77
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@breadstone/archipel-platform-mailing",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.14",
|
|
4
4
|
"description": "Email delivery with strategy-based transport and template engines for NestJS applications.",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"main": "./src/index.js",
|
|
@@ -75,8 +75,9 @@
|
|
|
75
75
|
"README.md"
|
|
76
76
|
],
|
|
77
77
|
"dependencies": {
|
|
78
|
-
"@breadstone/archipel-platform-blob-storage": "0.0.
|
|
79
|
-
"@breadstone/archipel-platform-
|
|
78
|
+
"@breadstone/archipel-platform-blob-storage": "0.0.14",
|
|
79
|
+
"@breadstone/archipel-platform-configuration": "0.0.14",
|
|
80
|
+
"@breadstone/archipel-platform-core": "0.0.14",
|
|
80
81
|
"form-data": "4.0.5",
|
|
81
82
|
"nodemailer": "8.0.5",
|
|
82
83
|
"tslib": "2.8.1"
|
package/src/MailModule.js
CHANGED
|
@@ -4,6 +4,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
4
4
|
exports.MailModule = void 0;
|
|
5
5
|
const tslib_1 = require("tslib");
|
|
6
6
|
const archipel_platform_blob_storage_1 = require("@breadstone/archipel-platform-blob-storage");
|
|
7
|
+
const archipel_platform_configuration_1 = require("@breadstone/archipel-platform-configuration");
|
|
7
8
|
const archipel_platform_core_1 = require("@breadstone/archipel-platform-core");
|
|
8
9
|
const common_1 = require("@nestjs/common");
|
|
9
10
|
const env_1 = require("./env");
|
|
@@ -28,7 +29,7 @@ exports.MailModule = MailModule = tslib_1.__decorate([
|
|
|
28
29
|
(0, common_1.Global)(),
|
|
29
30
|
(0, common_1.Module)({
|
|
30
31
|
imports: [
|
|
31
|
-
|
|
32
|
+
archipel_platform_configuration_1.ConfigModule.register('platform-mailing', env_1.PLATFORM_MAILING_CONFIG_ENTRIES),
|
|
32
33
|
archipel_platform_blob_storage_1.BlobModule,
|
|
33
34
|
archipel_platform_core_1.EventModule,
|
|
34
35
|
archipel_platform_core_1.HealthModule,
|
|
@@ -46,7 +47,7 @@ exports.MailModule = MailModule = tslib_1.__decorate([
|
|
|
46
47
|
}
|
|
47
48
|
throw new Error(`Unknown template strategy: ${templateStrategy}`);
|
|
48
49
|
},
|
|
49
|
-
inject: [
|
|
50
|
+
inject: [archipel_platform_configuration_1.ConfigService, archipel_platform_blob_storage_1.BlobService, archipel_platform_core_1.ResourceManager],
|
|
50
51
|
},
|
|
51
52
|
{
|
|
52
53
|
provide: MailTokens_1.MAIL_DELIVERY_STRATEGY_TOKEN,
|
|
@@ -54,7 +55,7 @@ exports.MailModule = MailModule = tslib_1.__decorate([
|
|
|
54
55
|
const deliveryStrategy = configService.get(env_1.MAIL_DELIVERY_STRATEGY.key);
|
|
55
56
|
if (deliveryStrategy === 'log') {
|
|
56
57
|
const { LogDeliveryStrategy } = await Promise.resolve().then(() => tslib_1.__importStar(require('./services/strategies/LogDeliveryStrategy')));
|
|
57
|
-
return new LogDeliveryStrategy(
|
|
58
|
+
return new LogDeliveryStrategy();
|
|
58
59
|
}
|
|
59
60
|
if (deliveryStrategy === 'smtp') {
|
|
60
61
|
const { SmtpDeliveryStrategy } = await Promise.resolve().then(() => tslib_1.__importStar(require('./services/strategies/SmtpDeliveryStrategy')));
|
|
@@ -78,7 +79,7 @@ exports.MailModule = MailModule = tslib_1.__decorate([
|
|
|
78
79
|
}
|
|
79
80
|
throw new Error(`Unknown delivery strategy: ${deliveryStrategy}`);
|
|
80
81
|
},
|
|
81
|
-
inject: [
|
|
82
|
+
inject: [archipel_platform_configuration_1.ConfigService],
|
|
82
83
|
},
|
|
83
84
|
archipel_platform_core_1.ContentTemplateEngine,
|
|
84
85
|
MailService_1.MailService,
|
package/src/env.d.ts
CHANGED
|
@@ -1,37 +1,37 @@
|
|
|
1
|
-
import { IConfigRegistryEntry } from '@breadstone/archipel-platform-
|
|
1
|
+
import { IConfigRegistryEntry } from '@breadstone/archipel-platform-configuration';
|
|
2
2
|
/** Which template-fetch strategy to use (e.g. `file`, `blob`). */
|
|
3
|
-
export declare const MAIL_TEMPLATE_STRATEGY: import("@breadstone/archipel-platform-
|
|
3
|
+
export declare const MAIL_TEMPLATE_STRATEGY: import("@breadstone/archipel-platform-configuration").IConfigKey<string>;
|
|
4
4
|
/** Which delivery strategy to use (e.g. `smtp`, `postmark`, `resend`, `sendgrid`, `mailgun`, `log`). */
|
|
5
|
-
export declare const MAIL_DELIVERY_STRATEGY: import("@breadstone/archipel-platform-
|
|
5
|
+
export declare const MAIL_DELIVERY_STRATEGY: import("@breadstone/archipel-platform-configuration").IConfigKey<string>;
|
|
6
6
|
/** Sender e-mail address shown in the `From` header. */
|
|
7
|
-
export declare const MAIL_SENDER_EMAIL: import("@breadstone/archipel-platform-
|
|
7
|
+
export declare const MAIL_SENDER_EMAIL: import("@breadstone/archipel-platform-configuration").IConfigKey<string>;
|
|
8
8
|
/** Template engine format identifier (e.g. `handlebars`). */
|
|
9
|
-
export declare const MAIL_TEMPLATE_ENGINE_FORMAT: import("@breadstone/archipel-platform-
|
|
9
|
+
export declare const MAIL_TEMPLATE_ENGINE_FORMAT: import("@breadstone/archipel-platform-configuration").IConfigKey<string>;
|
|
10
10
|
/** API key for the Postmark delivery service. */
|
|
11
|
-
export declare const MAIL_POSTMARK_API_KEY: import("@breadstone/archipel-platform-
|
|
11
|
+
export declare const MAIL_POSTMARK_API_KEY: import("@breadstone/archipel-platform-configuration").IConfigKey<string>;
|
|
12
12
|
/** API key for the Resend delivery service. */
|
|
13
|
-
export declare const MAIL_RESEND_API_KEY: import("@breadstone/archipel-platform-
|
|
13
|
+
export declare const MAIL_RESEND_API_KEY: import("@breadstone/archipel-platform-configuration").IConfigKey<string>;
|
|
14
14
|
/** API key for the SendGrid delivery service. */
|
|
15
|
-
export declare const MAIL_SENDGRID_API_KEY: import("@breadstone/archipel-platform-
|
|
15
|
+
export declare const MAIL_SENDGRID_API_KEY: import("@breadstone/archipel-platform-configuration").IConfigKey<string>;
|
|
16
16
|
/** API key for the Mailgun delivery service. */
|
|
17
|
-
export declare const MAIL_MAILGUN_API_KEY: import("@breadstone/archipel-platform-
|
|
17
|
+
export declare const MAIL_MAILGUN_API_KEY: import("@breadstone/archipel-platform-configuration").IConfigKey<string>;
|
|
18
18
|
/** Mailgun domain (e.g. `mg.example.com`). */
|
|
19
|
-
export declare const MAIL_MAILGUN_DOMAIN: import("@breadstone/archipel-platform-
|
|
19
|
+
export declare const MAIL_MAILGUN_DOMAIN: import("@breadstone/archipel-platform-configuration").IConfigKey<string>;
|
|
20
20
|
/** SMTP server host. */
|
|
21
|
-
export declare const MAIL_SMTP_HOST: import("@breadstone/archipel-platform-
|
|
21
|
+
export declare const MAIL_SMTP_HOST: import("@breadstone/archipel-platform-configuration").IConfigKey<string>;
|
|
22
22
|
/** SMTP server port. */
|
|
23
|
-
export declare const MAIL_SMTP_PORT: import("@breadstone/archipel-platform-
|
|
23
|
+
export declare const MAIL_SMTP_PORT: import("@breadstone/archipel-platform-configuration").IConfigKey<number>;
|
|
24
24
|
/** Whether the SMTP connection uses TLS. */
|
|
25
|
-
export declare const MAIL_SMTP_SECURE: import("@breadstone/archipel-platform-
|
|
25
|
+
export declare const MAIL_SMTP_SECURE: import("@breadstone/archipel-platform-configuration").IConfigKey<boolean>;
|
|
26
26
|
/** SMTP authentication username. */
|
|
27
|
-
export declare const MAIL_SMTP_USER: import("@breadstone/archipel-platform-
|
|
27
|
+
export declare const MAIL_SMTP_USER: import("@breadstone/archipel-platform-configuration").IConfigKey<string>;
|
|
28
28
|
/** SMTP authentication password. */
|
|
29
|
-
export declare const MAIL_SMTP_PASSWORD: import("@breadstone/archipel-platform-
|
|
29
|
+
export declare const MAIL_SMTP_PASSWORD: import("@breadstone/archipel-platform-configuration").IConfigKey<string>;
|
|
30
30
|
/** Mail host checked by the health indicator. */
|
|
31
|
-
export declare const MAIL_HOST: import("@breadstone/archipel-platform-
|
|
31
|
+
export declare const MAIL_HOST: import("@breadstone/archipel-platform-configuration").IConfigKey<string>;
|
|
32
32
|
/** Mail user checked by the health indicator. */
|
|
33
|
-
export declare const MAIL_USER: import("@breadstone/archipel-platform-
|
|
33
|
+
export declare const MAIL_USER: import("@breadstone/archipel-platform-configuration").IConfigKey<string>;
|
|
34
34
|
/** Mail port checked by the health indicator. */
|
|
35
|
-
export declare const MAIL_PORT: import("@breadstone/archipel-platform-
|
|
35
|
+
export declare const MAIL_PORT: import("@breadstone/archipel-platform-configuration").IConfigKey<number>;
|
|
36
36
|
/** All configuration entries required by `platform-mailing`. */
|
|
37
37
|
export declare const PLATFORM_MAILING_CONFIG_ENTRIES: ReadonlyArray<Omit<IConfigRegistryEntry, 'module'>>;
|
package/src/env.js
CHANGED
|
@@ -2,63 +2,63 @@
|
|
|
2
2
|
// #region Imports
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
4
|
exports.PLATFORM_MAILING_CONFIG_ENTRIES = exports.MAIL_PORT = exports.MAIL_USER = exports.MAIL_HOST = exports.MAIL_SMTP_PASSWORD = exports.MAIL_SMTP_USER = exports.MAIL_SMTP_SECURE = exports.MAIL_SMTP_PORT = exports.MAIL_SMTP_HOST = exports.MAIL_MAILGUN_DOMAIN = exports.MAIL_MAILGUN_API_KEY = exports.MAIL_SENDGRID_API_KEY = exports.MAIL_RESEND_API_KEY = exports.MAIL_POSTMARK_API_KEY = exports.MAIL_TEMPLATE_ENGINE_FORMAT = exports.MAIL_SENDER_EMAIL = exports.MAIL_DELIVERY_STRATEGY = exports.MAIL_TEMPLATE_STRATEGY = void 0;
|
|
5
|
-
const
|
|
5
|
+
const archipel_platform_configuration_1 = require("@breadstone/archipel-platform-configuration");
|
|
6
6
|
// #endregion
|
|
7
7
|
// ──────────────────────────────────────────────────────────────
|
|
8
8
|
// Delivery & Template Strategy
|
|
9
9
|
// ──────────────────────────────────────────────────────────────
|
|
10
10
|
/** Which template-fetch strategy to use (e.g. `file`, `blob`). */
|
|
11
|
-
exports.MAIL_TEMPLATE_STRATEGY = (0,
|
|
11
|
+
exports.MAIL_TEMPLATE_STRATEGY = (0, archipel_platform_configuration_1.createConfigKey)('MAIL_TEMPLATE_STRATEGY');
|
|
12
12
|
/** Which delivery strategy to use (e.g. `smtp`, `postmark`, `resend`, `sendgrid`, `mailgun`, `log`). */
|
|
13
|
-
exports.MAIL_DELIVERY_STRATEGY = (0,
|
|
13
|
+
exports.MAIL_DELIVERY_STRATEGY = (0, archipel_platform_configuration_1.createConfigKey)('MAIL_DELIVERY_STRATEGY');
|
|
14
14
|
/** Sender e-mail address shown in the `From` header. */
|
|
15
|
-
exports.MAIL_SENDER_EMAIL = (0,
|
|
15
|
+
exports.MAIL_SENDER_EMAIL = (0, archipel_platform_configuration_1.createConfigKey)('MAIL_SENDER_EMAIL');
|
|
16
16
|
/** Template engine format identifier (e.g. `handlebars`). */
|
|
17
|
-
exports.MAIL_TEMPLATE_ENGINE_FORMAT = (0,
|
|
17
|
+
exports.MAIL_TEMPLATE_ENGINE_FORMAT = (0, archipel_platform_configuration_1.createConfigKey)('MAIL_TEMPLATE_ENGINE_FORMAT');
|
|
18
18
|
// ──────────────────────────────────────────────────────────────
|
|
19
19
|
// Postmark
|
|
20
20
|
// ──────────────────────────────────────────────────────────────
|
|
21
21
|
/** API key for the Postmark delivery service. */
|
|
22
|
-
exports.MAIL_POSTMARK_API_KEY = (0,
|
|
22
|
+
exports.MAIL_POSTMARK_API_KEY = (0, archipel_platform_configuration_1.createConfigKey)('MAIL_POSTMARK_API_KEY');
|
|
23
23
|
// ──────────────────────────────────────────────────────────────
|
|
24
24
|
// Resend
|
|
25
25
|
// ──────────────────────────────────────────────────────────────
|
|
26
26
|
/** API key for the Resend delivery service. */
|
|
27
|
-
exports.MAIL_RESEND_API_KEY = (0,
|
|
27
|
+
exports.MAIL_RESEND_API_KEY = (0, archipel_platform_configuration_1.createConfigKey)('MAIL_RESEND_API_KEY');
|
|
28
28
|
// ──────────────────────────────────────────────────────────────
|
|
29
29
|
// SendGrid
|
|
30
30
|
// ──────────────────────────────────────────────────────────────
|
|
31
31
|
/** API key for the SendGrid delivery service. */
|
|
32
|
-
exports.MAIL_SENDGRID_API_KEY = (0,
|
|
32
|
+
exports.MAIL_SENDGRID_API_KEY = (0, archipel_platform_configuration_1.createConfigKey)('MAIL_SENDGRID_API_KEY');
|
|
33
33
|
// ──────────────────────────────────────────────────────────────
|
|
34
34
|
// Mailgun
|
|
35
35
|
// ──────────────────────────────────────────────────────────────
|
|
36
36
|
/** API key for the Mailgun delivery service. */
|
|
37
|
-
exports.MAIL_MAILGUN_API_KEY = (0,
|
|
37
|
+
exports.MAIL_MAILGUN_API_KEY = (0, archipel_platform_configuration_1.createConfigKey)('MAIL_MAILGUN_API_KEY');
|
|
38
38
|
/** Mailgun domain (e.g. `mg.example.com`). */
|
|
39
|
-
exports.MAIL_MAILGUN_DOMAIN = (0,
|
|
39
|
+
exports.MAIL_MAILGUN_DOMAIN = (0, archipel_platform_configuration_1.createConfigKey)('MAIL_MAILGUN_DOMAIN');
|
|
40
40
|
// ──────────────────────────────────────────────────────────────
|
|
41
41
|
// SMTP
|
|
42
42
|
// ──────────────────────────────────────────────────────────────
|
|
43
43
|
/** SMTP server host. */
|
|
44
|
-
exports.MAIL_SMTP_HOST = (0,
|
|
44
|
+
exports.MAIL_SMTP_HOST = (0, archipel_platform_configuration_1.createConfigKey)('MAIL_SMTP_HOST');
|
|
45
45
|
/** SMTP server port. */
|
|
46
|
-
exports.MAIL_SMTP_PORT = (0,
|
|
46
|
+
exports.MAIL_SMTP_PORT = (0, archipel_platform_configuration_1.createConfigKey)('MAIL_SMTP_PORT');
|
|
47
47
|
/** Whether the SMTP connection uses TLS. */
|
|
48
|
-
exports.MAIL_SMTP_SECURE = (0,
|
|
48
|
+
exports.MAIL_SMTP_SECURE = (0, archipel_platform_configuration_1.createConfigKey)('MAIL_SMTP_SECURE');
|
|
49
49
|
/** SMTP authentication username. */
|
|
50
|
-
exports.MAIL_SMTP_USER = (0,
|
|
50
|
+
exports.MAIL_SMTP_USER = (0, archipel_platform_configuration_1.createConfigKey)('MAIL_SMTP_USER');
|
|
51
51
|
/** SMTP authentication password. */
|
|
52
|
-
exports.MAIL_SMTP_PASSWORD = (0,
|
|
52
|
+
exports.MAIL_SMTP_PASSWORD = (0, archipel_platform_configuration_1.createConfigKey)('MAIL_SMTP_PASSWORD');
|
|
53
53
|
// ──────────────────────────────────────────────────────────────
|
|
54
54
|
// Health Indicator
|
|
55
55
|
// ──────────────────────────────────────────────────────────────
|
|
56
56
|
/** Mail host checked by the health indicator. */
|
|
57
|
-
exports.MAIL_HOST = (0,
|
|
57
|
+
exports.MAIL_HOST = (0, archipel_platform_configuration_1.createConfigKey)('MAIL_HOST');
|
|
58
58
|
/** Mail user checked by the health indicator. */
|
|
59
|
-
exports.MAIL_USER = (0,
|
|
59
|
+
exports.MAIL_USER = (0, archipel_platform_configuration_1.createConfigKey)('MAIL_USER');
|
|
60
60
|
/** Mail port checked by the health indicator. */
|
|
61
|
-
exports.MAIL_PORT = (0,
|
|
61
|
+
exports.MAIL_PORT = (0, archipel_platform_configuration_1.createConfigKey)('MAIL_PORT');
|
|
62
62
|
// ──────────────────────────────────────────────────────────────
|
|
63
63
|
// Registry entries
|
|
64
64
|
// ──────────────────────────────────────────────────────────────
|
|
@@ -105,7 +105,7 @@ exports.PLATFORM_MAILING_CONFIG_ENTRIES = [
|
|
|
105
105
|
// SMTP
|
|
106
106
|
{ key: exports.MAIL_SMTP_HOST, required: false, defaultValue: 'localhost', description: 'SMTP server host.' },
|
|
107
107
|
{ key: exports.MAIL_SMTP_PORT, required: false, defaultValue: 587, description: 'SMTP server port.' },
|
|
108
|
-
{ key: exports.MAIL_SMTP_SECURE, required: false, defaultValue:
|
|
108
|
+
{ key: exports.MAIL_SMTP_SECURE, required: false, defaultValue: true, description: 'Whether SMTP uses TLS.' },
|
|
109
109
|
{ key: exports.MAIL_SMTP_USER, required: false, defaultValue: '', description: 'SMTP authentication username.' },
|
|
110
110
|
{ key: exports.MAIL_SMTP_PASSWORD, required: false, defaultValue: '', description: 'SMTP authentication password.' },
|
|
111
111
|
// Health
|
package/src/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ export * from './env';
|
|
|
2
2
|
export * from './events';
|
|
3
3
|
export * from './MailModule';
|
|
4
4
|
export * from './MailTokens';
|
|
5
|
+
export * from './models/IMailAttachment';
|
|
5
6
|
export * from './services/MailService';
|
|
6
7
|
export * from './services/MailVerificationService';
|
|
7
8
|
export * from './services/strategies/abstracts/DeliveryStrategyBase';
|
package/src/index.js
CHANGED
|
@@ -5,6 +5,7 @@ tslib_1.__exportStar(require("./env"), exports);
|
|
|
5
5
|
tslib_1.__exportStar(require("./events"), exports);
|
|
6
6
|
tslib_1.__exportStar(require("./MailModule"), exports);
|
|
7
7
|
tslib_1.__exportStar(require("./MailTokens"), exports);
|
|
8
|
+
tslib_1.__exportStar(require("./models/IMailAttachment"), exports);
|
|
8
9
|
tslib_1.__exportStar(require("./services/MailService"), exports);
|
|
9
10
|
tslib_1.__exportStar(require("./services/MailVerificationService"), exports);
|
|
10
11
|
tslib_1.__exportStar(require("./services/strategies/abstracts/DeliveryStrategyBase"), exports);
|
package/src/mailgun/env.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { IConfigRegistryEntry } from '@breadstone/archipel-platform-
|
|
1
|
+
import { IConfigRegistryEntry } from '@breadstone/archipel-platform-configuration';
|
|
2
2
|
/** API key for the Mailgun delivery service. */
|
|
3
|
-
export declare const MAILGUN_API_KEY: import("@breadstone/archipel-platform-
|
|
3
|
+
export declare const MAILGUN_API_KEY: import("@breadstone/archipel-platform-configuration").IConfigKey<string>;
|
|
4
4
|
/** Mailgun domain (e.g. `mg.example.com`). */
|
|
5
|
-
export declare const MAILGUN_DOMAIN: import("@breadstone/archipel-platform-
|
|
5
|
+
export declare const MAILGUN_DOMAIN: import("@breadstone/archipel-platform-configuration").IConfigKey<string>;
|
|
6
6
|
/** Configuration entries required by the Mailgun delivery provider. */
|
|
7
7
|
export declare const MAILGUN_CONFIG_ENTRIES: ReadonlyArray<Omit<IConfigRegistryEntry, 'module'>>;
|
package/src/mailgun/env.js
CHANGED
|
@@ -2,15 +2,15 @@
|
|
|
2
2
|
// #region Imports
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
4
|
exports.MAILGUN_CONFIG_ENTRIES = exports.MAILGUN_DOMAIN = exports.MAILGUN_API_KEY = void 0;
|
|
5
|
-
const
|
|
5
|
+
const archipel_platform_configuration_1 = require("@breadstone/archipel-platform-configuration");
|
|
6
6
|
// #endregion
|
|
7
7
|
// ──────────────────────────────────────────────────────────────
|
|
8
8
|
// Mailgun
|
|
9
9
|
// ──────────────────────────────────────────────────────────────
|
|
10
10
|
/** API key for the Mailgun delivery service. */
|
|
11
|
-
exports.MAILGUN_API_KEY = (0,
|
|
11
|
+
exports.MAILGUN_API_KEY = (0, archipel_platform_configuration_1.createConfigKey)('MAIL_MAILGUN_API_KEY');
|
|
12
12
|
/** Mailgun domain (e.g. `mg.example.com`). */
|
|
13
|
-
exports.MAILGUN_DOMAIN = (0,
|
|
13
|
+
exports.MAILGUN_DOMAIN = (0, archipel_platform_configuration_1.createConfigKey)('MAIL_MAILGUN_DOMAIN');
|
|
14
14
|
// ──────────────────────────────────────────────────────────────
|
|
15
15
|
// Registry entries
|
|
16
16
|
// ──────────────────────────────────────────────────────────────
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Allowed MIME types for email attachments.
|
|
3
|
+
*
|
|
4
|
+
* @public
|
|
5
|
+
*/
|
|
6
|
+
export declare const ALLOWED_ATTACHMENT_MIME_TYPES: readonly ["application/pdf", "application/msword", "application/vnd.openxmlformats-officedocument.wordprocessingml.document", "application/vnd.ms-excel", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "application/zip", "image/png", "image/jpeg", "image/gif", "image/webp", "text/plain", "text/csv"];
|
|
7
|
+
/**
|
|
8
|
+
* Maximum attachment size in bytes (25 MB).
|
|
9
|
+
*
|
|
10
|
+
* @public
|
|
11
|
+
*/
|
|
12
|
+
export declare const MAX_ATTACHMENT_SIZE_BYTES: number;
|
|
13
|
+
/**
|
|
14
|
+
* Represents an email attachment.
|
|
15
|
+
*
|
|
16
|
+
* @public
|
|
17
|
+
*/
|
|
18
|
+
export interface IMailAttachment {
|
|
19
|
+
/**
|
|
20
|
+
* The filename of the attachment as displayed to the recipient.
|
|
21
|
+
*/
|
|
22
|
+
readonly filename: string;
|
|
23
|
+
/**
|
|
24
|
+
* The raw content of the attachment.
|
|
25
|
+
*/
|
|
26
|
+
readonly content: Buffer | string;
|
|
27
|
+
/**
|
|
28
|
+
* The MIME type of the attachment.
|
|
29
|
+
*/
|
|
30
|
+
readonly contentType: string;
|
|
31
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MAX_ATTACHMENT_SIZE_BYTES = exports.ALLOWED_ATTACHMENT_MIME_TYPES = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Allowed MIME types for email attachments.
|
|
6
|
+
*
|
|
7
|
+
* @public
|
|
8
|
+
*/
|
|
9
|
+
exports.ALLOWED_ATTACHMENT_MIME_TYPES = [
|
|
10
|
+
'application/pdf',
|
|
11
|
+
'application/msword',
|
|
12
|
+
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
|
13
|
+
'application/vnd.ms-excel',
|
|
14
|
+
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
|
15
|
+
'application/zip',
|
|
16
|
+
'image/png',
|
|
17
|
+
'image/jpeg',
|
|
18
|
+
'image/gif',
|
|
19
|
+
'image/webp',
|
|
20
|
+
'text/plain',
|
|
21
|
+
'text/csv',
|
|
22
|
+
];
|
|
23
|
+
/**
|
|
24
|
+
* Maximum attachment size in bytes (25 MB).
|
|
25
|
+
*
|
|
26
|
+
* @public
|
|
27
|
+
*/
|
|
28
|
+
exports.MAX_ATTACHMENT_SIZE_BYTES = 25 * 1024 * 1024;
|
|
29
|
+
//# sourceMappingURL=IMailAttachment.js.map
|
package/src/postmark/env.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { IConfigRegistryEntry } from '@breadstone/archipel-platform-
|
|
1
|
+
import { IConfigRegistryEntry } from '@breadstone/archipel-platform-configuration';
|
|
2
2
|
/** API key for the Postmark delivery service. */
|
|
3
|
-
export declare const POSTMARK_API_KEY: import("@breadstone/archipel-platform-
|
|
3
|
+
export declare const POSTMARK_API_KEY: import("@breadstone/archipel-platform-configuration").IConfigKey<string>;
|
|
4
4
|
/** Configuration entries required by the Postmark delivery provider. */
|
|
5
5
|
export declare const POSTMARK_CONFIG_ENTRIES: ReadonlyArray<Omit<IConfigRegistryEntry, 'module'>>;
|
package/src/postmark/env.js
CHANGED
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
// #region Imports
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
4
|
exports.POSTMARK_CONFIG_ENTRIES = exports.POSTMARK_API_KEY = void 0;
|
|
5
|
-
const
|
|
5
|
+
const archipel_platform_configuration_1 = require("@breadstone/archipel-platform-configuration");
|
|
6
6
|
// #endregion
|
|
7
7
|
// ──────────────────────────────────────────────────────────────
|
|
8
8
|
// Postmark
|
|
9
9
|
// ──────────────────────────────────────────────────────────────
|
|
10
10
|
/** API key for the Postmark delivery service. */
|
|
11
|
-
exports.POSTMARK_API_KEY = (0,
|
|
11
|
+
exports.POSTMARK_API_KEY = (0, archipel_platform_configuration_1.createConfigKey)('MAIL_POSTMARK_API_KEY');
|
|
12
12
|
// ──────────────────────────────────────────────────────────────
|
|
13
13
|
// Registry entries
|
|
14
14
|
// ──────────────────────────────────────────────────────────────
|
package/src/resend/env.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { IConfigRegistryEntry } from '@breadstone/archipel-platform-
|
|
1
|
+
import { IConfigRegistryEntry } from '@breadstone/archipel-platform-configuration';
|
|
2
2
|
/** API key for the Resend delivery service. */
|
|
3
|
-
export declare const RESEND_API_KEY: import("@breadstone/archipel-platform-
|
|
3
|
+
export declare const RESEND_API_KEY: import("@breadstone/archipel-platform-configuration").IConfigKey<string>;
|
|
4
4
|
/** Configuration entries required by the Resend delivery provider. */
|
|
5
5
|
export declare const RESEND_CONFIG_ENTRIES: ReadonlyArray<Omit<IConfigRegistryEntry, 'module'>>;
|
package/src/resend/env.js
CHANGED
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
// #region Imports
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
4
|
exports.RESEND_CONFIG_ENTRIES = exports.RESEND_API_KEY = void 0;
|
|
5
|
-
const
|
|
5
|
+
const archipel_platform_configuration_1 = require("@breadstone/archipel-platform-configuration");
|
|
6
6
|
// #endregion
|
|
7
7
|
// ──────────────────────────────────────────────────────────────
|
|
8
8
|
// Resend
|
|
9
9
|
// ──────────────────────────────────────────────────────────────
|
|
10
10
|
/** API key for the Resend delivery service. */
|
|
11
|
-
exports.RESEND_API_KEY = (0,
|
|
11
|
+
exports.RESEND_API_KEY = (0, archipel_platform_configuration_1.createConfigKey)('MAIL_RESEND_API_KEY');
|
|
12
12
|
// ──────────────────────────────────────────────────────────────
|
|
13
13
|
// Registry entries
|
|
14
14
|
// ──────────────────────────────────────────────────────────────
|
package/src/sendgrid/env.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { IConfigRegistryEntry } from '@breadstone/archipel-platform-
|
|
1
|
+
import { IConfigRegistryEntry } from '@breadstone/archipel-platform-configuration';
|
|
2
2
|
/** API key for the SendGrid delivery service. */
|
|
3
|
-
export declare const SENDGRID_API_KEY: import("@breadstone/archipel-platform-
|
|
3
|
+
export declare const SENDGRID_API_KEY: import("@breadstone/archipel-platform-configuration").IConfigKey<string>;
|
|
4
4
|
/** Configuration entries required by the SendGrid delivery provider. */
|
|
5
5
|
export declare const SENDGRID_CONFIG_ENTRIES: ReadonlyArray<Omit<IConfigRegistryEntry, 'module'>>;
|
package/src/sendgrid/env.js
CHANGED
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
// #region Imports
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
4
|
exports.SENDGRID_CONFIG_ENTRIES = exports.SENDGRID_API_KEY = void 0;
|
|
5
|
-
const
|
|
5
|
+
const archipel_platform_configuration_1 = require("@breadstone/archipel-platform-configuration");
|
|
6
6
|
// #endregion
|
|
7
7
|
// ──────────────────────────────────────────────────────────────
|
|
8
8
|
// SendGrid
|
|
9
9
|
// ──────────────────────────────────────────────────────────────
|
|
10
10
|
/** API key for the SendGrid delivery service. */
|
|
11
|
-
exports.SENDGRID_API_KEY = (0,
|
|
11
|
+
exports.SENDGRID_API_KEY = (0, archipel_platform_configuration_1.createConfigKey)('MAIL_SENDGRID_API_KEY');
|
|
12
12
|
// ──────────────────────────────────────────────────────────────
|
|
13
13
|
// Registry entries
|
|
14
14
|
// ──────────────────────────────────────────────────────────────
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { ConfigService } from '@breadstone/archipel-platform-
|
|
1
|
+
import { ConfigService } from '@breadstone/archipel-platform-configuration';
|
|
2
|
+
import { type IMailAttachment } from '../models/IMailAttachment';
|
|
2
3
|
import { MailTemplateEngine } from '../templating/MailTemplateEngine';
|
|
3
4
|
import { DeliveryStrategyBase } from './strategies/abstracts/DeliveryStrategyBase';
|
|
4
5
|
/**
|
|
@@ -31,7 +32,7 @@ export declare class MailService {
|
|
|
31
32
|
from?: string;
|
|
32
33
|
to: string;
|
|
33
34
|
subject: string;
|
|
34
|
-
}, content: string, isHtml: boolean): Promise<void>;
|
|
35
|
+
}, content: string, isHtml: boolean, attachments?: Array<IMailAttachment>): Promise<void>;
|
|
35
36
|
/**
|
|
36
37
|
* Sends an email using a predefined template (HTML or text).
|
|
37
38
|
* Automatically uses the template format (either 'html' or 'txt') based on the environment variable.
|
|
@@ -57,4 +58,11 @@ export declare class MailService {
|
|
|
57
58
|
* @throws Error if the format is invalid.
|
|
58
59
|
*/
|
|
59
60
|
private ensureValidEmail;
|
|
61
|
+
/**
|
|
62
|
+
* Validates email attachments against MIME-type allowlist and size limits.
|
|
63
|
+
*
|
|
64
|
+
* @param attachments - Array of attachments to validate
|
|
65
|
+
* @throws Error if any attachment violates constraints
|
|
66
|
+
*/
|
|
67
|
+
private validateAttachments;
|
|
60
68
|
}
|
|
@@ -3,9 +3,10 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
4
|
exports.MailService = void 0;
|
|
5
5
|
const tslib_1 = require("tslib");
|
|
6
|
-
const
|
|
6
|
+
const archipel_platform_configuration_1 = require("@breadstone/archipel-platform-configuration");
|
|
7
7
|
const common_1 = require("@nestjs/common");
|
|
8
8
|
const env_1 = require("../env");
|
|
9
|
+
const IMailAttachment_1 = require("../models/IMailAttachment");
|
|
9
10
|
const MailTokens_1 = require("../MailTokens");
|
|
10
11
|
const MailTemplateEngine_1 = require("../templating/MailTemplateEngine");
|
|
11
12
|
const DeliveryStrategyBase_1 = require("./strategies/abstracts/DeliveryStrategyBase");
|
|
@@ -45,13 +46,17 @@ let MailService = class MailService {
|
|
|
45
46
|
* @param content - Email body content (plain text or HTML)
|
|
46
47
|
* @param isHtml - Flag to indicate whether the email is HTML (true) or plain text (false)
|
|
47
48
|
*/
|
|
48
|
-
async send(mailOptions, content, isHtml) {
|
|
49
|
+
async send(mailOptions, content, isHtml, attachments) {
|
|
49
50
|
this.ensureValidEmail(mailOptions.to);
|
|
50
51
|
if (mailOptions.from) {
|
|
51
52
|
this.ensureValidEmail(mailOptions.from);
|
|
52
53
|
}
|
|
54
|
+
if (attachments) {
|
|
55
|
+
this.validateAttachments(attachments);
|
|
56
|
+
}
|
|
53
57
|
const sender = mailOptions.from ?? this._defaultFrom;
|
|
54
|
-
|
|
58
|
+
const sanitizedSubject = mailOptions.subject.replace(/[\r\n]/g, ' ');
|
|
59
|
+
await this._deliveryStrategy.send(sender, mailOptions.to, sanitizedSubject, content, isHtml, attachments);
|
|
55
60
|
}
|
|
56
61
|
/**
|
|
57
62
|
* Sends an email using a predefined template (HTML or text).
|
|
@@ -75,18 +80,37 @@ let MailService = class MailService {
|
|
|
75
80
|
* @throws Error if the format is invalid.
|
|
76
81
|
*/
|
|
77
82
|
ensureValidEmail(email) {
|
|
78
|
-
//
|
|
79
|
-
const emailRegex = /^[A-Z0-9._%+-]
|
|
80
|
-
if (!emailRegex.test(email)) {
|
|
83
|
+
// Rejects leading/trailing dots, consecutive dots, and requires valid domain structure.
|
|
84
|
+
const emailRegex = /^[A-Z0-9](?:[A-Z0-9._%+-]*[A-Z0-9])?@[A-Z0-9](?:[A-Z0-9-]*[A-Z0-9])?(?:\.[A-Z0-9](?:[A-Z0-9-]*[A-Z0-9])?)*\.[A-Z]{2,}$/i;
|
|
85
|
+
if (!emailRegex.test(email) || email.includes('..')) {
|
|
81
86
|
throw new Error(`Invalid email address: '${email}'`);
|
|
82
87
|
}
|
|
83
88
|
}
|
|
89
|
+
/**
|
|
90
|
+
* Validates email attachments against MIME-type allowlist and size limits.
|
|
91
|
+
*
|
|
92
|
+
* @param attachments - Array of attachments to validate
|
|
93
|
+
* @throws Error if any attachment violates constraints
|
|
94
|
+
*/
|
|
95
|
+
validateAttachments(attachments) {
|
|
96
|
+
for (const attachment of attachments) {
|
|
97
|
+
if (!IMailAttachment_1.ALLOWED_ATTACHMENT_MIME_TYPES.includes(attachment.contentType)) {
|
|
98
|
+
throw new Error(`Unsupported attachment MIME type: '${attachment.contentType}'`);
|
|
99
|
+
}
|
|
100
|
+
const size = typeof attachment.content === 'string'
|
|
101
|
+
? Buffer.byteLength(attachment.content, 'utf-8')
|
|
102
|
+
: attachment.content.length;
|
|
103
|
+
if (size > IMailAttachment_1.MAX_ATTACHMENT_SIZE_BYTES) {
|
|
104
|
+
throw new Error(`Attachment '${attachment.filename}' exceeds maximum size of ${IMailAttachment_1.MAX_ATTACHMENT_SIZE_BYTES} bytes`);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
84
108
|
};
|
|
85
109
|
exports.MailService = MailService;
|
|
86
110
|
exports.MailService = MailService = tslib_1.__decorate([
|
|
87
111
|
(0, common_1.Injectable)(),
|
|
88
112
|
tslib_1.__param(2, (0, common_1.Inject)(MailTokens_1.MAIL_DELIVERY_STRATEGY_TOKEN)),
|
|
89
|
-
tslib_1.__metadata("design:paramtypes", [
|
|
113
|
+
tslib_1.__metadata("design:paramtypes", [archipel_platform_configuration_1.ConfigService,
|
|
90
114
|
MailTemplateEngine_1.MailTemplateEngine,
|
|
91
115
|
DeliveryStrategyBase_1.DeliveryStrategyBase])
|
|
92
116
|
], MailService);
|
|
@@ -1,10 +1,15 @@
|
|
|
1
|
-
import { ConfigService } from '@breadstone/archipel-platform-
|
|
1
|
+
import { ConfigService } from '@breadstone/archipel-platform-configuration';
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
3
|
+
* Verifies SMTP server connectivity. Does **not** validate individual email
|
|
4
|
+
* addresses — only checks whether the configured SMTP transport is reachable.
|
|
4
5
|
*
|
|
5
6
|
* @public
|
|
7
|
+
* @deprecated Renamed to `SmtpConnectionVerifier` in a future release to better
|
|
8
|
+
* reflect its actual purpose. Prefer wrapping this in a health-check rather
|
|
9
|
+
* than calling it directly.
|
|
6
10
|
*/
|
|
7
11
|
export declare class MailVerificationService {
|
|
12
|
+
private readonly _logger;
|
|
8
13
|
private readonly _transporter;
|
|
9
14
|
/**
|
|
10
15
|
* Constructs a new instance of the `MailVerificationService` class.
|
|
@@ -1,19 +1,24 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
// #region Imports
|
|
3
|
+
var MailVerificationService_1;
|
|
3
4
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
5
|
exports.MailVerificationService = void 0;
|
|
5
6
|
const tslib_1 = require("tslib");
|
|
6
|
-
const
|
|
7
|
+
const archipel_platform_configuration_1 = require("@breadstone/archipel-platform-configuration");
|
|
7
8
|
const common_1 = require("@nestjs/common");
|
|
8
9
|
const nodemailer = tslib_1.__importStar(require("nodemailer"));
|
|
9
10
|
const env_1 = require("../env");
|
|
10
11
|
// #endregion
|
|
11
12
|
/**
|
|
12
|
-
*
|
|
13
|
+
* Verifies SMTP server connectivity. Does **not** validate individual email
|
|
14
|
+
* addresses — only checks whether the configured SMTP transport is reachable.
|
|
13
15
|
*
|
|
14
16
|
* @public
|
|
17
|
+
* @deprecated Renamed to `SmtpConnectionVerifier` in a future release to better
|
|
18
|
+
* reflect its actual purpose. Prefer wrapping this in a health-check rather
|
|
19
|
+
* than calling it directly.
|
|
15
20
|
*/
|
|
16
|
-
let MailVerificationService = class MailVerificationService {
|
|
21
|
+
let MailVerificationService = MailVerificationService_1 = class MailVerificationService {
|
|
17
22
|
// #endregion
|
|
18
23
|
// #region Ctor
|
|
19
24
|
/**
|
|
@@ -22,6 +27,8 @@ let MailVerificationService = class MailVerificationService {
|
|
|
22
27
|
* @public
|
|
23
28
|
*/
|
|
24
29
|
constructor(configService) {
|
|
30
|
+
// #region Fields
|
|
31
|
+
this._logger = new common_1.Logger(MailVerificationService_1.name);
|
|
25
32
|
this._transporter = nodemailer.createTransport({
|
|
26
33
|
host: configService.tryGet(env_1.MAIL_SMTP_HOST.key, 'localhost'),
|
|
27
34
|
port: 465,
|
|
@@ -42,7 +49,7 @@ let MailVerificationService = class MailVerificationService {
|
|
|
42
49
|
return new Promise((resolve, reject) => {
|
|
43
50
|
this._transporter.verify((error, success) => {
|
|
44
51
|
if (error) {
|
|
45
|
-
|
|
52
|
+
this._logger.error('SMTP verification error:', error);
|
|
46
53
|
resolve(false);
|
|
47
54
|
return; // Couldn't connect or verify
|
|
48
55
|
}
|
|
@@ -70,8 +77,8 @@ let MailVerificationService = class MailVerificationService {
|
|
|
70
77
|
}
|
|
71
78
|
};
|
|
72
79
|
exports.MailVerificationService = MailVerificationService;
|
|
73
|
-
exports.MailVerificationService = MailVerificationService = tslib_1.__decorate([
|
|
80
|
+
exports.MailVerificationService = MailVerificationService = MailVerificationService_1 = tslib_1.__decorate([
|
|
74
81
|
(0, common_1.Injectable)(),
|
|
75
|
-
tslib_1.__metadata("design:paramtypes", [
|
|
82
|
+
tslib_1.__metadata("design:paramtypes", [archipel_platform_configuration_1.ConfigService])
|
|
76
83
|
], MailVerificationService);
|
|
77
84
|
//# sourceMappingURL=MailVerificationService.js.map
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { ConfigService } from '@breadstone/archipel-platform-core';
|
|
2
1
|
import { DeliveryStrategyBase } from './abstracts/DeliveryStrategyBase';
|
|
3
2
|
/**
|
|
4
3
|
* The `LogDeliveryStrategy` class.
|
|
@@ -7,12 +6,11 @@ import { DeliveryStrategyBase } from './abstracts/DeliveryStrategyBase';
|
|
|
7
6
|
*/
|
|
8
7
|
export declare class LogDeliveryStrategy extends DeliveryStrategyBase {
|
|
9
8
|
private readonly _logger;
|
|
10
|
-
private readonly _configService;
|
|
11
9
|
/**
|
|
12
10
|
* Constructs a new instance of the `LogDelivery` class.
|
|
13
11
|
*
|
|
14
12
|
* @public
|
|
15
13
|
*/
|
|
16
|
-
constructor(
|
|
17
|
-
send(from: string, to: string, subject: string, content: string, isHtml: boolean): Promise<void>;
|
|
14
|
+
constructor();
|
|
15
|
+
send(from: string, to: string, subject: string, content: string, isHtml: boolean, _attachments?: Array<import('../../models/IMailAttachment').IMailAttachment>): Promise<void>;
|
|
18
16
|
}
|
|
@@ -18,14 +18,14 @@ class LogDeliveryStrategy extends DeliveryStrategyBase_1.DeliveryStrategyBase {
|
|
|
18
18
|
*
|
|
19
19
|
* @public
|
|
20
20
|
*/
|
|
21
|
-
constructor(
|
|
21
|
+
constructor() {
|
|
22
22
|
super();
|
|
23
23
|
// #region Fields
|
|
24
24
|
this._logger = new common_1.Logger(LogDeliveryStrategy.name);
|
|
25
|
-
this._configService = configService;
|
|
26
25
|
}
|
|
27
26
|
// #endregion
|
|
28
|
-
|
|
27
|
+
// #region Methods
|
|
28
|
+
send(from, to, subject, content, isHtml, _attachments) {
|
|
29
29
|
this._logger.log(`Logged email: ${JSON.stringify({
|
|
30
30
|
from: from,
|
|
31
31
|
to: to,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ConfigService } from '@breadstone/archipel-platform-
|
|
1
|
+
import { ConfigService } from '@breadstone/archipel-platform-configuration';
|
|
2
2
|
import { DeliveryStrategyBase } from './abstracts/DeliveryStrategyBase';
|
|
3
3
|
/**
|
|
4
4
|
* Delivers emails via the Mailgun API.
|
|
@@ -25,5 +25,5 @@ export declare class MailgunDeliveryStrategy extends DeliveryStrategyBase {
|
|
|
25
25
|
* @param content - Email body content (plain text or HTML)
|
|
26
26
|
* @param isHtml - Flag to indicate whether the email is HTML (true) or plain text (false)
|
|
27
27
|
*/
|
|
28
|
-
send(from: string, to: string, subject: string, content: string, isHtml: boolean): Promise<void>;
|
|
28
|
+
send(from: string, to: string, subject: string, content: string, isHtml: boolean, _attachments?: Array<import('../../models/IMailAttachment').IMailAttachment>): Promise<void>;
|
|
29
29
|
}
|
|
@@ -45,14 +45,18 @@ class MailgunDeliveryStrategy extends DeliveryStrategyBase_1.DeliveryStrategyBas
|
|
|
45
45
|
* @param content - Email body content (plain text or HTML)
|
|
46
46
|
* @param isHtml - Flag to indicate whether the email is HTML (true) or plain text (false)
|
|
47
47
|
*/
|
|
48
|
-
async send(from, to, subject, content, isHtml) {
|
|
48
|
+
async send(from, to, subject, content, isHtml, _attachments) {
|
|
49
49
|
try {
|
|
50
|
-
|
|
50
|
+
const sendPromise = this._mailgunClient.messages.create(this._domain, {
|
|
51
51
|
from,
|
|
52
52
|
to,
|
|
53
53
|
subject,
|
|
54
54
|
...(isHtml ? { html: content } : { text: content }),
|
|
55
55
|
});
|
|
56
|
+
const timeoutPromise = new Promise((_resolve, reject) => {
|
|
57
|
+
setTimeout(() => reject(new Error('Mailgun send timed out after 30000ms')), 30_000);
|
|
58
|
+
});
|
|
59
|
+
await Promise.race([sendPromise, timeoutPromise]);
|
|
56
60
|
this._logger.log('Email sent successfully', 'Mail');
|
|
57
61
|
}
|
|
58
62
|
catch (error) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ConfigService } from '@breadstone/archipel-platform-
|
|
1
|
+
import { ConfigService } from '@breadstone/archipel-platform-configuration';
|
|
2
2
|
import { DeliveryStrategyBase } from './abstracts/DeliveryStrategyBase';
|
|
3
3
|
/**
|
|
4
4
|
* The `PostmarkDeliveryStrategy` class.
|
|
@@ -24,5 +24,5 @@ export declare class PostmarkDeliveryStrategy extends DeliveryStrategyBase {
|
|
|
24
24
|
* @param content - Email body content (plain text or HTML)
|
|
25
25
|
* @param isHtml - Flag to indicate whether the email is HTML (true) or plain text (false)
|
|
26
26
|
*/
|
|
27
|
-
send(from: string, to: string, subject: string, content: string, isHtml: boolean): Promise<void>;
|
|
27
|
+
send(from: string, to: string, subject: string, content: string, isHtml: boolean, _attachments?: Array<import('../../models/IMailAttachment').IMailAttachment>): Promise<void>;
|
|
28
28
|
}
|
|
@@ -38,14 +38,18 @@ class PostmarkDeliveryStrategy extends DeliveryStrategyBase_1.DeliveryStrategyBa
|
|
|
38
38
|
* @param content - Email body content (plain text or HTML)
|
|
39
39
|
* @param isHtml - Flag to indicate whether the email is HTML (true) or plain text (false)
|
|
40
40
|
*/
|
|
41
|
-
async send(from, to, subject, content, isHtml) {
|
|
41
|
+
async send(from, to, subject, content, isHtml, _attachments) {
|
|
42
42
|
try {
|
|
43
|
-
|
|
43
|
+
const sendPromise = this._postmarkClient.sendEmail({
|
|
44
44
|
From: from,
|
|
45
45
|
To: to,
|
|
46
46
|
Subject: subject,
|
|
47
47
|
...(isHtml ? { HtmlBody: content } : { TextBody: content }),
|
|
48
48
|
});
|
|
49
|
+
const timeoutPromise = new Promise((_resolve, reject) => {
|
|
50
|
+
setTimeout(() => reject(new Error('Postmark send timed out after 30000ms')), 30_000);
|
|
51
|
+
});
|
|
52
|
+
await Promise.race([sendPromise, timeoutPromise]);
|
|
49
53
|
this._logger.log('Email sent successfully', 'Mail');
|
|
50
54
|
}
|
|
51
55
|
catch (error) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ConfigService } from '@breadstone/archipel-platform-
|
|
1
|
+
import { ConfigService } from '@breadstone/archipel-platform-configuration';
|
|
2
2
|
import { DeliveryStrategyBase } from './abstracts/DeliveryStrategyBase';
|
|
3
3
|
/**
|
|
4
4
|
* Delivers emails via the Resend API.
|
|
@@ -24,5 +24,5 @@ export declare class ResendDeliveryStrategy extends DeliveryStrategyBase {
|
|
|
24
24
|
* @param content - Email body content (plain text or HTML)
|
|
25
25
|
* @param isHtml - Flag to indicate whether the email is HTML (true) or plain text (false)
|
|
26
26
|
*/
|
|
27
|
-
send(from: string, to: string, subject: string, content: string, isHtml: boolean): Promise<void>;
|
|
27
|
+
send(from: string, to: string, subject: string, content: string, isHtml: boolean, _attachments?: Array<import('../../models/IMailAttachment').IMailAttachment>): Promise<void>;
|
|
28
28
|
}
|
|
@@ -38,14 +38,18 @@ class ResendDeliveryStrategy extends DeliveryStrategyBase_1.DeliveryStrategyBase
|
|
|
38
38
|
* @param content - Email body content (plain text or HTML)
|
|
39
39
|
* @param isHtml - Flag to indicate whether the email is HTML (true) or plain text (false)
|
|
40
40
|
*/
|
|
41
|
-
async send(from, to, subject, content, isHtml) {
|
|
41
|
+
async send(from, to, subject, content, isHtml, _attachments) {
|
|
42
42
|
try {
|
|
43
|
-
|
|
43
|
+
const sendPromise = this._resendClient.emails.send({
|
|
44
44
|
from,
|
|
45
45
|
to,
|
|
46
46
|
subject,
|
|
47
47
|
...(isHtml ? { html: content } : { text: content }),
|
|
48
48
|
});
|
|
49
|
+
const timeoutPromise = new Promise((_resolve, reject) => {
|
|
50
|
+
setTimeout(() => reject(new Error('Resend send timed out after 30000ms')), 30_000);
|
|
51
|
+
});
|
|
52
|
+
await Promise.race([sendPromise, timeoutPromise]);
|
|
49
53
|
this._logger.log('Email sent successfully', 'Mail');
|
|
50
54
|
}
|
|
51
55
|
catch (error) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ConfigService } from '@breadstone/archipel-platform-
|
|
1
|
+
import { ConfigService } from '@breadstone/archipel-platform-configuration';
|
|
2
2
|
import { DeliveryStrategyBase } from './abstracts/DeliveryStrategyBase';
|
|
3
3
|
/**
|
|
4
4
|
* Delivers emails via the SendGrid API.
|
|
@@ -23,5 +23,5 @@ export declare class SendGridDeliveryStrategy extends DeliveryStrategyBase {
|
|
|
23
23
|
* @param content - Email body content (plain text or HTML)
|
|
24
24
|
* @param isHtml - Flag to indicate whether the email is HTML (true) or plain text (false)
|
|
25
25
|
*/
|
|
26
|
-
send(from: string, to: string, subject: string, content: string, isHtml: boolean): Promise<void>;
|
|
26
|
+
send(from: string, to: string, subject: string, content: string, isHtml: boolean, _attachments?: Array<import('../../models/IMailAttachment').IMailAttachment>): Promise<void>;
|
|
27
27
|
}
|
|
@@ -39,14 +39,18 @@ class SendGridDeliveryStrategy extends DeliveryStrategyBase_1.DeliveryStrategyBa
|
|
|
39
39
|
* @param content - Email body content (plain text or HTML)
|
|
40
40
|
* @param isHtml - Flag to indicate whether the email is HTML (true) or plain text (false)
|
|
41
41
|
*/
|
|
42
|
-
async send(from, to, subject, content, isHtml) {
|
|
42
|
+
async send(from, to, subject, content, isHtml, _attachments) {
|
|
43
43
|
try {
|
|
44
|
-
|
|
44
|
+
const sendPromise = mail_1.default.send({
|
|
45
45
|
from,
|
|
46
46
|
to,
|
|
47
47
|
subject,
|
|
48
48
|
...(isHtml ? { html: content } : { text: content }),
|
|
49
49
|
});
|
|
50
|
+
const timeoutPromise = new Promise((_resolve, reject) => {
|
|
51
|
+
setTimeout(() => reject(new Error('SendGrid send timed out after 30000ms')), 30_000);
|
|
52
|
+
});
|
|
53
|
+
await Promise.race([sendPromise, timeoutPromise]);
|
|
50
54
|
this._logger.log('Email sent successfully', 'Mail');
|
|
51
55
|
}
|
|
52
56
|
catch (error) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ConfigService } from '@breadstone/archipel-platform-
|
|
1
|
+
import { ConfigService } from '@breadstone/archipel-platform-configuration';
|
|
2
2
|
import { DeliveryStrategyBase } from './abstracts/DeliveryStrategyBase';
|
|
3
3
|
/**
|
|
4
4
|
* The `SmtpDeliveryStrategy` class.
|
|
@@ -24,5 +24,5 @@ export declare class SmtpDeliveryStrategy extends DeliveryStrategyBase {
|
|
|
24
24
|
* @param content - Email body content (plain text or HTML)
|
|
25
25
|
* @param isHtml - Flag to indicate whether the email is HTML (true) or plain text (false)
|
|
26
26
|
*/
|
|
27
|
-
send(from: string, to: string, subject: string, content: string, isHtml: boolean): Promise<void>;
|
|
27
|
+
send(from: string, to: string, subject: string, content: string, isHtml: boolean, _attachments?: Array<import('../../models/IMailAttachment').IMailAttachment>): Promise<void>;
|
|
28
28
|
}
|
|
@@ -27,7 +27,7 @@ class SmtpDeliveryStrategy extends DeliveryStrategyBase_1.DeliveryStrategyBase {
|
|
|
27
27
|
const options = {
|
|
28
28
|
host: configService.tryGet(env_1.MAIL_SMTP_HOST.key, 'localhost'),
|
|
29
29
|
port: configService.tryGet(env_1.MAIL_SMTP_PORT.key, 587),
|
|
30
|
-
secure: configService.tryGet(env_1.MAIL_SMTP_SECURE.key,
|
|
30
|
+
secure: configService.tryGet(env_1.MAIL_SMTP_SECURE.key, true),
|
|
31
31
|
auth: {
|
|
32
32
|
user: configService.tryGet(env_1.MAIL_SMTP_USER.key, ''),
|
|
33
33
|
pass: configService.tryGet(env_1.MAIL_SMTP_PASSWORD.key, ''),
|
|
@@ -47,14 +47,18 @@ class SmtpDeliveryStrategy extends DeliveryStrategyBase_1.DeliveryStrategyBase {
|
|
|
47
47
|
* @param content - Email body content (plain text or HTML)
|
|
48
48
|
* @param isHtml - Flag to indicate whether the email is HTML (true) or plain text (false)
|
|
49
49
|
*/
|
|
50
|
-
async send(from, to, subject, content, isHtml) {
|
|
50
|
+
async send(from, to, subject, content, isHtml, _attachments) {
|
|
51
51
|
try {
|
|
52
|
-
|
|
52
|
+
const sendPromise = this._transporter.sendMail({
|
|
53
53
|
from,
|
|
54
54
|
to,
|
|
55
55
|
subject,
|
|
56
56
|
...(isHtml ? { html: content } : { text: content }),
|
|
57
57
|
});
|
|
58
|
+
const timeoutPromise = new Promise((_resolve, reject) => {
|
|
59
|
+
setTimeout(() => reject(new Error('SMTP send timed out after 30000ms')), 30_000);
|
|
60
|
+
});
|
|
61
|
+
await Promise.race([sendPromise, timeoutPromise]);
|
|
58
62
|
this._logger.log('Email sent successfully', 'Mail');
|
|
59
63
|
}
|
|
60
64
|
catch (error) {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { IMailAttachment } from '../../../models/IMailAttachment';
|
|
1
2
|
/**
|
|
2
3
|
* Represents the base class for all email delivery strategies.
|
|
3
4
|
*
|
|
@@ -21,6 +22,7 @@ export declare abstract class DeliveryStrategyBase {
|
|
|
21
22
|
* @param subject - Subject of the email
|
|
22
23
|
* @param content - Email body content (plain text or HTML)
|
|
23
24
|
* @param isHtml - Flag to indicate whether the email is HTML (true) or plain text (false)
|
|
25
|
+
* @param attachments - Optional array of file attachments
|
|
24
26
|
*/
|
|
25
|
-
abstract send(from: string, to: string, subject: string, content: string, isHtml: boolean): Promise<void>;
|
|
27
|
+
abstract send(from: string, to: string, subject: string, content: string, isHtml: boolean, attachments?: Array<IMailAttachment>): Promise<void>;
|
|
26
28
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ContentTemplateEngine } from '@breadstone/archipel-platform-core';
|
|
2
2
|
import { OnModuleInit } from '@nestjs/common';
|
|
3
|
-
import { TemplateFetchStrategyBase } from './strategies/abstracts/TemplateFetchStrategyBase';
|
|
4
3
|
import { MailTemplateFormat } from '../MailTokens';
|
|
4
|
+
import { TemplateFetchStrategyBase } from './strategies/abstracts/TemplateFetchStrategyBase';
|
|
5
5
|
/**
|
|
6
6
|
* The `MailTemplateEngine` class.
|
|
7
7
|
*
|
|
@@ -35,4 +35,6 @@ export declare class MailTemplateEngine implements OnModuleInit {
|
|
|
35
35
|
* @returns The compiled template as a string.
|
|
36
36
|
*/
|
|
37
37
|
compileTemplate(templateKey: string, params: Record<string, unknown>, format: MailTemplateFormat): string;
|
|
38
|
+
private escapeHtmlParams;
|
|
39
|
+
private escapeHtml;
|
|
38
40
|
}
|
|
@@ -5,8 +5,8 @@ exports.MailTemplateEngine = void 0;
|
|
|
5
5
|
const tslib_1 = require("tslib");
|
|
6
6
|
const archipel_platform_core_1 = require("@breadstone/archipel-platform-core");
|
|
7
7
|
const common_1 = require("@nestjs/common");
|
|
8
|
-
const TemplateFetchStrategyBase_1 = require("./strategies/abstracts/TemplateFetchStrategyBase");
|
|
9
8
|
const MailTokens_1 = require("../MailTokens");
|
|
9
|
+
const TemplateFetchStrategyBase_1 = require("./strategies/abstracts/TemplateFetchStrategyBase");
|
|
10
10
|
// #endregion
|
|
11
11
|
/**
|
|
12
12
|
* The `MailTemplateEngine` class.
|
|
@@ -48,12 +48,17 @@ let MailTemplateEngine = class MailTemplateEngine {
|
|
|
48
48
|
* @returns The compiled template as a string.
|
|
49
49
|
*/
|
|
50
50
|
compileTemplate(templateKey, params, format) {
|
|
51
|
-
const
|
|
51
|
+
const templateVariants = this._templates[templateKey];
|
|
52
|
+
if (!templateVariants) {
|
|
53
|
+
throw new Error(`Template with key '${templateKey}' not found.`);
|
|
54
|
+
}
|
|
55
|
+
const template = templateVariants[format];
|
|
52
56
|
if (!template) {
|
|
53
57
|
throw new Error(`Template with key '${templateKey}' and format '${format}' not found.`);
|
|
54
58
|
}
|
|
55
59
|
try {
|
|
56
|
-
const
|
|
60
|
+
const safeParams = format === 'html' ? this.escapeHtmlParams(params) : params;
|
|
61
|
+
const interpolatedTemplate = this._contentTemplateEngine.compileTemplate(template, safeParams);
|
|
57
62
|
return interpolatedTemplate;
|
|
58
63
|
}
|
|
59
64
|
catch (error) {
|
|
@@ -61,6 +66,21 @@ let MailTemplateEngine = class MailTemplateEngine {
|
|
|
61
66
|
throw error;
|
|
62
67
|
}
|
|
63
68
|
}
|
|
69
|
+
escapeHtmlParams(params) {
|
|
70
|
+
const escaped = {};
|
|
71
|
+
for (const [key, value] of Object.entries(params)) {
|
|
72
|
+
escaped[key] = typeof value === 'string' ? this.escapeHtml(value) : value;
|
|
73
|
+
}
|
|
74
|
+
return escaped;
|
|
75
|
+
}
|
|
76
|
+
escapeHtml(text) {
|
|
77
|
+
return text
|
|
78
|
+
.replace(/&/g, '&')
|
|
79
|
+
.replace(/</g, '<')
|
|
80
|
+
.replace(/>/g, '>')
|
|
81
|
+
.replace(/"/g, '"')
|
|
82
|
+
.replace(/'/g, ''');
|
|
83
|
+
}
|
|
64
84
|
};
|
|
65
85
|
exports.MailTemplateEngine = MailTemplateEngine;
|
|
66
86
|
exports.MailTemplateEngine = MailTemplateEngine = tslib_1.__decorate([
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { BlobService } from '@breadstone/archipel-platform-blob-storage';
|
|
2
|
-
import { TemplateFetchStrategyBase } from './abstracts/TemplateFetchStrategyBase';
|
|
3
2
|
import { IMailTemplateVariants } from '../../MailTokens';
|
|
3
|
+
import { TemplateFetchStrategyBase } from './abstracts/TemplateFetchStrategyBase';
|
|
4
4
|
/**
|
|
5
5
|
* The `BlobTemplateFetchStrategy` class.
|
|
6
6
|
*
|
|
@@ -8,6 +8,7 @@ import { IMailTemplateVariants } from '../../MailTokens';
|
|
|
8
8
|
*/
|
|
9
9
|
export declare class BlobTemplateFetchStrategy extends TemplateFetchStrategyBase {
|
|
10
10
|
private readonly _blobService;
|
|
11
|
+
private readonly _logger;
|
|
11
12
|
/**
|
|
12
13
|
* Constructs a new instance of the `BlobTemplateFetchStrategy` class.
|
|
13
14
|
*
|
|
@@ -22,6 +22,7 @@ class BlobTemplateFetchStrategy extends TemplateFetchStrategyBase_1.TemplateFetc
|
|
|
22
22
|
*/
|
|
23
23
|
constructor(blobService) {
|
|
24
24
|
super();
|
|
25
|
+
this._logger = new common_1.Logger(BlobTemplateFetchStrategy.name);
|
|
25
26
|
this._blobService = blobService;
|
|
26
27
|
}
|
|
27
28
|
// #endregion
|
|
@@ -44,10 +45,10 @@ class BlobTemplateFetchStrategy extends TemplateFetchStrategyBase_1.TemplateFetc
|
|
|
44
45
|
templates[templateName].txt = templateContent;
|
|
45
46
|
}
|
|
46
47
|
else {
|
|
47
|
-
|
|
48
|
+
this._logger.warn(`Unknown template extension '${extension}' for '${file}'`);
|
|
48
49
|
}
|
|
49
50
|
}
|
|
50
|
-
|
|
51
|
+
this._logger.log('Templates loaded from blob storage');
|
|
51
52
|
return templates;
|
|
52
53
|
}
|
|
53
54
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { ConfigService
|
|
1
|
+
import { ConfigService } from '@breadstone/archipel-platform-configuration';
|
|
2
|
+
import { IHealthIndicator } from '@breadstone/archipel-platform-core';
|
|
2
3
|
import { HealthIndicatorResult } from '@nestjs/terminus';
|
|
3
4
|
/**
|
|
4
5
|
* Health indicator for mail service.
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
4
|
exports.MailHealthIndicator = void 0;
|
|
5
5
|
const tslib_1 = require("tslib");
|
|
6
|
-
const
|
|
6
|
+
const archipel_platform_configuration_1 = require("@breadstone/archipel-platform-configuration");
|
|
7
7
|
const common_1 = require("@nestjs/common");
|
|
8
8
|
const env_1 = require("../env");
|
|
9
9
|
// #endregion
|
|
@@ -50,6 +50,6 @@ let MailHealthIndicator = class MailHealthIndicator {
|
|
|
50
50
|
exports.MailHealthIndicator = MailHealthIndicator;
|
|
51
51
|
exports.MailHealthIndicator = MailHealthIndicator = tslib_1.__decorate([
|
|
52
52
|
(0, common_1.Injectable)(),
|
|
53
|
-
tslib_1.__metadata("design:paramtypes", [
|
|
53
|
+
tslib_1.__metadata("design:paramtypes", [archipel_platform_configuration_1.ConfigService])
|
|
54
54
|
], MailHealthIndicator);
|
|
55
55
|
//# sourceMappingURL=MailHealthIndicator.js.map
|