@spinajs/email-smtp-transport 2.0.557 → 3.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -8
- package/lib/cjs/index.d.ts +0 -1
- package/lib/cjs/index.d.ts.map +1 -1
- package/lib/cjs/index.js +36 -47
- package/lib/cjs/index.js.map +1 -1
- package/lib/mjs/index.d.ts +0 -1
- package/lib/mjs/index.d.ts.map +1 -1
- package/lib/mjs/index.js +37 -48
- package/lib/mjs/index.js.map +1 -1
- package/lib/tsconfig.cjs.tsbuildinfo +1 -1
- package/lib/tsconfig.mjs.tsbuildinfo +1 -1
- package/package.json +10 -10
package/README.md
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
#
|
|
1
|
+
# `@spinajs/email-smtp-transport`
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
SMTP transport for `@spinajs/email`, built on `nodemailer`.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Documentation
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
7
|
+
- [Package overview](../../docs/email-smtp-transport/README.md)
|
|
8
|
+
- [SMTP connection](../../docs/email-smtp-transport/01-smtp-connection.md)
|
|
9
|
+
- [Sending mail](../../docs/email-smtp-transport/02-sending-mail.md)
|
|
10
|
+
- [Send resilience](../../docs/email-smtp-transport/03-send-resilience.md)
|
|
11
|
+
- [Extending the SMTP sender](../../docs/email-smtp-transport/04-extending-the-smtp-sender.md)
|
package/lib/cjs/index.d.ts
CHANGED
|
@@ -7,7 +7,6 @@ export declare class EmailSenderSmtp extends EmailSender {
|
|
|
7
7
|
Options: EmailConnectionOptions;
|
|
8
8
|
protected Log: Log;
|
|
9
9
|
protected Templates: Templates;
|
|
10
|
-
protected DefaultFileProvider: string;
|
|
11
10
|
protected Transporter: nodemailer.Transporter;
|
|
12
11
|
/**
|
|
13
12
|
* In-process resilience pipeline guarding the SMTP send ( per-attempt timeout + retry ).
|
package/lib/cjs/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,GAAG,EAAU,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,sBAAsB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,GAAG,EAAU,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,sBAAsB,EAAkD,MAAM,gBAAgB,CAAC;AAC7H,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAe,kBAAkB,EAA6B,MAAM,eAAe,CAAC;AAC3F,OAAO,KAAK,UAAU,MAAM,YAAY,CAAC;AAIzC,qBAEa,eAAgB,SAAQ,WAAW;IAc3B,OAAO,EAAE,sBAAsB;IAZlD,SAAS,CAAC,GAAG,EAAE,GAAG,CAAC;IAGnB,SAAS,CAAC,SAAS,EAAE,SAAS,CAAC;IAE/B,SAAS,CAAC,WAAW,EAAE,UAAU,CAAC,WAAW,CAAC;IAE9C;;OAEG;IACH,SAAS,CAAC,YAAY,EAAE,kBAAkB,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC;IAEvE,YAAmB,OAAO,EAAE,sBAAsB,EAEjD;IAED;;;;OAIG;IACH,SAAS,CAAC,iBAAiB,IAAI,kBAAkB,CAAC,UAAU,CAAC,eAAe,CAAC,CAY5E;IAEY,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAuCpC;IAEY,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA0E9C;CACF"}
|
package/lib/cjs/index.js
CHANGED
|
@@ -55,7 +55,6 @@ const util_1 = require("@spinajs/util");
|
|
|
55
55
|
const nodemailer = __importStar(require("nodemailer"));
|
|
56
56
|
const fs_1 = require("@spinajs/fs");
|
|
57
57
|
const lodash_1 = __importDefault(require("lodash"));
|
|
58
|
-
const configuration_1 = require("@spinajs/configuration");
|
|
59
58
|
let EmailSenderSmtp = class EmailSenderSmtp extends email_1.EmailSender {
|
|
60
59
|
constructor(Options) {
|
|
61
60
|
super();
|
|
@@ -68,8 +67,15 @@ let EmailSenderSmtp = class EmailSenderSmtp extends email_1.EmailSender {
|
|
|
68
67
|
*/
|
|
69
68
|
buildSendPipeline() {
|
|
70
69
|
return new util_1.ResiliencePipelineBuilder()
|
|
70
|
+
.addRetry({
|
|
71
|
+
MaxRetryAttempts: this.Options.resilience?.retries ?? 2,
|
|
72
|
+
Delay: this.Options.resilience?.delay ?? 500,
|
|
73
|
+
BackoffType: util_1.BackoffType.Exponential,
|
|
74
|
+
UseJitter: true,
|
|
75
|
+
// SMTP 5xx replies are permanent rejections, repeating them cannot succeed
|
|
76
|
+
ShouldHandle: ({ Error: error }) => error !== undefined && (error.responseCode ?? 0) < 500,
|
|
77
|
+
})
|
|
71
78
|
.addTimeout(this.Options.resilience?.timeout ?? 30_000)
|
|
72
|
-
.addRetry({ MaxRetryAttempts: this.Options.resilience?.retries ?? 2, Delay: this.Options.resilience?.delay ?? 500, BackoffType: util_1.BackoffType.Exponential, UseJitter: true })
|
|
73
79
|
.build();
|
|
74
80
|
}
|
|
75
81
|
async resolve() {
|
|
@@ -78,14 +84,12 @@ let EmailSenderSmtp = class EmailSenderSmtp extends email_1.EmailSender {
|
|
|
78
84
|
host: this.Options.host,
|
|
79
85
|
port: this.Options.port,
|
|
80
86
|
secure: this.Options.ssl, // true for 465, false for other ports
|
|
81
|
-
auth
|
|
82
|
-
|
|
83
|
-
pass: this.Options.password, // generated ethereal password
|
|
84
|
-
},
|
|
87
|
+
// nodemailer attempts LOGIN whenever an auth object is present, even an empty one
|
|
88
|
+
auth: this.Options.user || this.Options.password ? { user: this.Options.user, pass: this.Options.password } : undefined,
|
|
85
89
|
},
|
|
86
90
|
// all additional options merged
|
|
87
91
|
this.Options.options);
|
|
88
|
-
this.Log.info(
|
|
92
|
+
this.Log.info({ user: options.auth?.user, host: options.host, port: options.port, secure: options.secure }, 'Creating connection to smtp: ${user}@${host}:${port}, secure: ${secure}');
|
|
89
93
|
// create reusable transporter object using the default SMTP transport
|
|
90
94
|
this.Transporter = nodemailer.createTransport(options);
|
|
91
95
|
// in-process resilience applied only around the SMTP send. Queue-level retry
|
|
@@ -97,10 +101,10 @@ let EmailSenderSmtp = class EmailSenderSmtp extends email_1.EmailSender {
|
|
|
97
101
|
await this.Transporter.verify();
|
|
98
102
|
}
|
|
99
103
|
catch (err) {
|
|
100
|
-
this.Log.error(err,
|
|
104
|
+
this.Log.error({ error: err, connection: this.Options.name, host: this.Options.host, port: this.Options.port }, 'Cannot verify smtp connection ${connection} (${host}:${port})');
|
|
101
105
|
throw new exceptions_1.UnexpectedServerError(`Cannot verify smtp connection ${this.Options.name} (${this.Options.host}:${this.Options.port})`, err);
|
|
102
106
|
}
|
|
103
|
-
this.Log.success(
|
|
107
|
+
this.Log.success({ connection: this.Options.name, host: this.Options.host }, 'Email smtp connection ${connection} on host ${host} established !');
|
|
104
108
|
}
|
|
105
109
|
async send(email) {
|
|
106
110
|
if (!email.from && !this.Options.defaults?.mailFrom) {
|
|
@@ -112,23 +116,22 @@ let EmailSenderSmtp = class EmailSenderSmtp extends email_1.EmailSender {
|
|
|
112
116
|
if (email.template) {
|
|
113
117
|
// string template -> default template filesystem
|
|
114
118
|
// IEmailTemplate object -> resolve its own fs provider
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
throw new exceptions_1.IOFail(`Filesystem provider for ${email.template.fs} not registered. Make sure you importer all required fs providers`);
|
|
120
|
-
}
|
|
119
|
+
// getFs() throws ResolveException for a name that is not registered
|
|
120
|
+
const templateFs = lodash_1.default.isString(email.template) ? this.defaultTemplateFs : (0, fs_1.getFs)(email.template.fs);
|
|
121
|
+
if (!templateFs) {
|
|
122
|
+
throw new exceptions_1.IOFail(`No filesystem to load email template from. Set email.templateFs, or fs of the template`);
|
|
121
123
|
}
|
|
122
|
-
this.Log.trace(
|
|
124
|
+
this.Log.trace({ filesystem: templateFs.Name }, 'Using filesystem ${filesystem} to resolve email template');
|
|
123
125
|
const tfile = await (lodash_1.default.isString(email.template) ? templateFs.download(email.template) : templateFs.download(email.template.file));
|
|
124
|
-
this.Log.trace(
|
|
126
|
+
this.Log.trace({ templateFile: tfile }, 'Resolved email template ${templateFile}');
|
|
125
127
|
try {
|
|
126
|
-
html = await this.Templates.render(tfile, { ...
|
|
128
|
+
html = await this.Templates.render(tfile, { ...this.Options.templates?.defaults, ...email.model }, email.lang, email.redact ? { redact: email.redact } : undefined);
|
|
127
129
|
}
|
|
128
130
|
catch (err) {
|
|
129
|
-
// template rendering is a deterministic failure - log & rethrow
|
|
130
|
-
|
|
131
|
-
|
|
131
|
+
// template rendering is a deterministic failure - log & rethrow, do not retry
|
|
132
|
+
const failure = (0, email_1.redactError)(err, email.redact);
|
|
133
|
+
this.Log.error({ error: failure, templateFile: tfile, connection: this.Options.name }, 'Cannot render email template ${templateFile} for connection ${connection}');
|
|
134
|
+
throw failure;
|
|
132
135
|
}
|
|
133
136
|
}
|
|
134
137
|
const options = {
|
|
@@ -143,25 +146,13 @@ let EmailSenderSmtp = class EmailSenderSmtp extends email_1.EmailSender {
|
|
|
143
146
|
attachments: [],
|
|
144
147
|
};
|
|
145
148
|
if (email.attachements) {
|
|
146
|
-
options.attachments = await Promise.all(
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
// other implementations should dodwnload file locally,
|
|
154
|
-
// and return temporary path
|
|
155
|
-
// we provide path to file, becouse nodemailer
|
|
156
|
-
// prefer it when sending bigger files
|
|
157
|
-
const file = await provider.download(a.path);
|
|
158
|
-
return {
|
|
159
|
-
cid: a.cid,
|
|
160
|
-
filename: a.name,
|
|
161
|
-
path: file,
|
|
162
|
-
provider: provider.Name,
|
|
163
|
-
};
|
|
164
|
-
}));
|
|
149
|
+
options.attachments = await Promise.all(
|
|
150
|
+
// A local path rather than content: nodemailer streams it, which suits bigger files.
|
|
151
|
+
email.attachements.map(async (a) => ({
|
|
152
|
+
cid: a.cid,
|
|
153
|
+
filename: a.name,
|
|
154
|
+
path: await (0, email_1.attachmentFile)(a, this.DefaultFileProvider),
|
|
155
|
+
})));
|
|
165
156
|
}
|
|
166
157
|
let message;
|
|
167
158
|
try {
|
|
@@ -169,10 +160,12 @@ let EmailSenderSmtp = class EmailSenderSmtp extends email_1.EmailSender {
|
|
|
169
160
|
message = await this.SendPipeline.execute(() => this.Transporter.sendMail(options));
|
|
170
161
|
}
|
|
171
162
|
catch (err) {
|
|
172
|
-
|
|
173
|
-
|
|
163
|
+
// an SMTP response may quote the message back, secret values included
|
|
164
|
+
const failure = (0, email_1.redactError)(err, email.redact);
|
|
165
|
+
this.Log.error({ error: failure, connection: this.Options.name, subject: email.subject, recipients: email.to?.length ?? 0 }, 'Cannot send email for connection ${connection}, subject: ${subject}, recipients: ${recipients}');
|
|
166
|
+
throw failure;
|
|
174
167
|
}
|
|
175
|
-
this.Log.trace(
|
|
168
|
+
this.Log.trace({ email: lodash_1.default.pick(email, ['from', 'to', 'cc', 'bcc', 'replyTo', 'subject']), messageId: message?.messageId, response: message?.response }, 'Sent email with data: ${email}, messageId: ${messageId}, response: ${response}');
|
|
176
169
|
}
|
|
177
170
|
};
|
|
178
171
|
exports.EmailSenderSmtp = EmailSenderSmtp;
|
|
@@ -184,10 +177,6 @@ __decorate([
|
|
|
184
177
|
(0, di_1.Autoinject)(templates_1.Templates),
|
|
185
178
|
__metadata("design:type", templates_1.Templates)
|
|
186
179
|
], EmailSenderSmtp.prototype, "Templates", void 0);
|
|
187
|
-
__decorate([
|
|
188
|
-
(0, configuration_1.Config)('fs.defaultProvider'),
|
|
189
|
-
__metadata("design:type", String)
|
|
190
|
-
], EmailSenderSmtp.prototype, "DefaultFileProvider", void 0);
|
|
191
180
|
exports.EmailSenderSmtp = EmailSenderSmtp = __decorate([
|
|
192
181
|
(0, di_1.Injectable)(email_1.EmailSender),
|
|
193
182
|
(0, di_1.NewInstance)(),
|
package/lib/cjs/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,oDAAoE;AACpE,oCAAkE;AAClE,sCAA2C;AAC3C,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
|
package/lib/mjs/index.d.ts
CHANGED
|
@@ -7,7 +7,6 @@ export declare class EmailSenderSmtp extends EmailSender {
|
|
|
7
7
|
Options: EmailConnectionOptions;
|
|
8
8
|
protected Log: Log;
|
|
9
9
|
protected Templates: Templates;
|
|
10
|
-
protected DefaultFileProvider: string;
|
|
11
10
|
protected Transporter: nodemailer.Transporter;
|
|
12
11
|
/**
|
|
13
12
|
* In-process resilience pipeline guarding the SMTP send ( per-attempt timeout + retry ).
|
package/lib/mjs/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,GAAG,EAAU,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,sBAAsB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,GAAG,EAAU,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,sBAAsB,EAAkD,MAAM,gBAAgB,CAAC;AAC7H,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAe,kBAAkB,EAA6B,MAAM,eAAe,CAAC;AAC3F,OAAO,KAAK,UAAU,MAAM,YAAY,CAAC;AAIzC,qBAEa,eAAgB,SAAQ,WAAW;IAc3B,OAAO,EAAE,sBAAsB;IAZlD,SAAS,CAAC,GAAG,EAAE,GAAG,CAAC;IAGnB,SAAS,CAAC,SAAS,EAAE,SAAS,CAAC;IAE/B,SAAS,CAAC,WAAW,EAAE,UAAU,CAAC,WAAW,CAAC;IAE9C;;OAEG;IACH,SAAS,CAAC,YAAY,EAAE,kBAAkB,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC;IAEvE,YAAmB,OAAO,EAAE,sBAAsB,EAEjD;IAED;;;;OAIG;IACH,SAAS,CAAC,iBAAiB,IAAI,kBAAkB,CAAC,UAAU,CAAC,eAAe,CAAC,CAY5E;IAEY,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAuCpC;IAEY,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA0E9C;CACF"}
|
package/lib/mjs/index.js
CHANGED
|
@@ -10,13 +10,12 @@ var __metadata = (this && this.__metadata) || function (k, v) {
|
|
|
10
10
|
import { IOFail, UnexpectedServerError } from '@spinajs/exceptions';
|
|
11
11
|
import { Autoinject, Injectable, NewInstance } from '@spinajs/di';
|
|
12
12
|
import { Log, Logger } from '@spinajs/log';
|
|
13
|
-
import { EmailSender } from '@spinajs/email';
|
|
13
|
+
import { EmailSender, attachmentFile, redactError } from '@spinajs/email';
|
|
14
14
|
import { Templates } from '@spinajs/templates';
|
|
15
15
|
import { BackoffType, ResiliencePipelineBuilder } from '@spinajs/util';
|
|
16
16
|
import * as nodemailer from 'nodemailer';
|
|
17
17
|
import { getFs } from '@spinajs/fs';
|
|
18
18
|
import _ from 'lodash';
|
|
19
|
-
import { Config } from '@spinajs/configuration';
|
|
20
19
|
let EmailSenderSmtp = class EmailSenderSmtp extends EmailSender {
|
|
21
20
|
constructor(Options) {
|
|
22
21
|
super();
|
|
@@ -29,8 +28,15 @@ let EmailSenderSmtp = class EmailSenderSmtp extends EmailSender {
|
|
|
29
28
|
*/
|
|
30
29
|
buildSendPipeline() {
|
|
31
30
|
return new ResiliencePipelineBuilder()
|
|
31
|
+
.addRetry({
|
|
32
|
+
MaxRetryAttempts: this.Options.resilience?.retries ?? 2,
|
|
33
|
+
Delay: this.Options.resilience?.delay ?? 500,
|
|
34
|
+
BackoffType: BackoffType.Exponential,
|
|
35
|
+
UseJitter: true,
|
|
36
|
+
// SMTP 5xx replies are permanent rejections, repeating them cannot succeed
|
|
37
|
+
ShouldHandle: ({ Error: error }) => error !== undefined && (error.responseCode ?? 0) < 500,
|
|
38
|
+
})
|
|
32
39
|
.addTimeout(this.Options.resilience?.timeout ?? 30_000)
|
|
33
|
-
.addRetry({ MaxRetryAttempts: this.Options.resilience?.retries ?? 2, Delay: this.Options.resilience?.delay ?? 500, BackoffType: BackoffType.Exponential, UseJitter: true })
|
|
34
40
|
.build();
|
|
35
41
|
}
|
|
36
42
|
async resolve() {
|
|
@@ -39,14 +45,12 @@ let EmailSenderSmtp = class EmailSenderSmtp extends EmailSender {
|
|
|
39
45
|
host: this.Options.host,
|
|
40
46
|
port: this.Options.port,
|
|
41
47
|
secure: this.Options.ssl, // true for 465, false for other ports
|
|
42
|
-
auth
|
|
43
|
-
|
|
44
|
-
pass: this.Options.password, // generated ethereal password
|
|
45
|
-
},
|
|
48
|
+
// nodemailer attempts LOGIN whenever an auth object is present, even an empty one
|
|
49
|
+
auth: this.Options.user || this.Options.password ? { user: this.Options.user, pass: this.Options.password } : undefined,
|
|
46
50
|
},
|
|
47
51
|
// all additional options merged
|
|
48
52
|
this.Options.options);
|
|
49
|
-
this.Log.info(
|
|
53
|
+
this.Log.info({ user: options.auth?.user, host: options.host, port: options.port, secure: options.secure }, 'Creating connection to smtp: ${user}@${host}:${port}, secure: ${secure}');
|
|
50
54
|
// create reusable transporter object using the default SMTP transport
|
|
51
55
|
this.Transporter = nodemailer.createTransport(options);
|
|
52
56
|
// in-process resilience applied only around the SMTP send. Queue-level retry
|
|
@@ -58,10 +62,10 @@ let EmailSenderSmtp = class EmailSenderSmtp extends EmailSender {
|
|
|
58
62
|
await this.Transporter.verify();
|
|
59
63
|
}
|
|
60
64
|
catch (err) {
|
|
61
|
-
this.Log.error(err,
|
|
65
|
+
this.Log.error({ error: err, connection: this.Options.name, host: this.Options.host, port: this.Options.port }, 'Cannot verify smtp connection ${connection} (${host}:${port})');
|
|
62
66
|
throw new UnexpectedServerError(`Cannot verify smtp connection ${this.Options.name} (${this.Options.host}:${this.Options.port})`, err);
|
|
63
67
|
}
|
|
64
|
-
this.Log.success(
|
|
68
|
+
this.Log.success({ connection: this.Options.name, host: this.Options.host }, 'Email smtp connection ${connection} on host ${host} established !');
|
|
65
69
|
}
|
|
66
70
|
async send(email) {
|
|
67
71
|
if (!email.from && !this.Options.defaults?.mailFrom) {
|
|
@@ -73,23 +77,22 @@ let EmailSenderSmtp = class EmailSenderSmtp extends EmailSender {
|
|
|
73
77
|
if (email.template) {
|
|
74
78
|
// string template -> default template filesystem
|
|
75
79
|
// IEmailTemplate object -> resolve its own fs provider
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
throw new IOFail(`Filesystem provider for ${email.template.fs} not registered. Make sure you importer all required fs providers`);
|
|
81
|
-
}
|
|
80
|
+
// getFs() throws ResolveException for a name that is not registered
|
|
81
|
+
const templateFs = _.isString(email.template) ? this.defaultTemplateFs : getFs(email.template.fs);
|
|
82
|
+
if (!templateFs) {
|
|
83
|
+
throw new IOFail(`No filesystem to load email template from. Set email.templateFs, or fs of the template`);
|
|
82
84
|
}
|
|
83
|
-
this.Log.trace(
|
|
85
|
+
this.Log.trace({ filesystem: templateFs.Name }, 'Using filesystem ${filesystem} to resolve email template');
|
|
84
86
|
const tfile = await (_.isString(email.template) ? templateFs.download(email.template) : templateFs.download(email.template.file));
|
|
85
|
-
this.Log.trace(
|
|
87
|
+
this.Log.trace({ templateFile: tfile }, 'Resolved email template ${templateFile}');
|
|
86
88
|
try {
|
|
87
|
-
html = await this.Templates.render(tfile, { ...
|
|
89
|
+
html = await this.Templates.render(tfile, { ...this.Options.templates?.defaults, ...email.model }, email.lang, email.redact ? { redact: email.redact } : undefined);
|
|
88
90
|
}
|
|
89
91
|
catch (err) {
|
|
90
|
-
// template rendering is a deterministic failure - log & rethrow
|
|
91
|
-
|
|
92
|
-
|
|
92
|
+
// template rendering is a deterministic failure - log & rethrow, do not retry
|
|
93
|
+
const failure = redactError(err, email.redact);
|
|
94
|
+
this.Log.error({ error: failure, templateFile: tfile, connection: this.Options.name }, 'Cannot render email template ${templateFile} for connection ${connection}');
|
|
95
|
+
throw failure;
|
|
93
96
|
}
|
|
94
97
|
}
|
|
95
98
|
const options = {
|
|
@@ -104,25 +107,13 @@ let EmailSenderSmtp = class EmailSenderSmtp extends EmailSender {
|
|
|
104
107
|
attachments: [],
|
|
105
108
|
};
|
|
106
109
|
if (email.attachements) {
|
|
107
|
-
options.attachments = await Promise.all(
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
// other implementations should dodwnload file locally,
|
|
115
|
-
// and return temporary path
|
|
116
|
-
// we provide path to file, becouse nodemailer
|
|
117
|
-
// prefer it when sending bigger files
|
|
118
|
-
const file = await provider.download(a.path);
|
|
119
|
-
return {
|
|
120
|
-
cid: a.cid,
|
|
121
|
-
filename: a.name,
|
|
122
|
-
path: file,
|
|
123
|
-
provider: provider.Name,
|
|
124
|
-
};
|
|
125
|
-
}));
|
|
110
|
+
options.attachments = await Promise.all(
|
|
111
|
+
// A local path rather than content: nodemailer streams it, which suits bigger files.
|
|
112
|
+
email.attachements.map(async (a) => ({
|
|
113
|
+
cid: a.cid,
|
|
114
|
+
filename: a.name,
|
|
115
|
+
path: await attachmentFile(a, this.DefaultFileProvider),
|
|
116
|
+
})));
|
|
126
117
|
}
|
|
127
118
|
let message;
|
|
128
119
|
try {
|
|
@@ -130,10 +121,12 @@ let EmailSenderSmtp = class EmailSenderSmtp extends EmailSender {
|
|
|
130
121
|
message = await this.SendPipeline.execute(() => this.Transporter.sendMail(options));
|
|
131
122
|
}
|
|
132
123
|
catch (err) {
|
|
133
|
-
|
|
134
|
-
|
|
124
|
+
// an SMTP response may quote the message back, secret values included
|
|
125
|
+
const failure = redactError(err, email.redact);
|
|
126
|
+
this.Log.error({ error: failure, connection: this.Options.name, subject: email.subject, recipients: email.to?.length ?? 0 }, 'Cannot send email for connection ${connection}, subject: ${subject}, recipients: ${recipients}');
|
|
127
|
+
throw failure;
|
|
135
128
|
}
|
|
136
|
-
this.Log.trace(
|
|
129
|
+
this.Log.trace({ email: _.pick(email, ['from', 'to', 'cc', 'bcc', 'replyTo', 'subject']), messageId: message?.messageId, response: message?.response }, 'Sent email with data: ${email}, messageId: ${messageId}, response: ${response}');
|
|
137
130
|
}
|
|
138
131
|
};
|
|
139
132
|
__decorate([
|
|
@@ -144,10 +137,6 @@ __decorate([
|
|
|
144
137
|
Autoinject(Templates),
|
|
145
138
|
__metadata("design:type", Templates)
|
|
146
139
|
], EmailSenderSmtp.prototype, "Templates", void 0);
|
|
147
|
-
__decorate([
|
|
148
|
-
Config('fs.defaultProvider'),
|
|
149
|
-
__metadata("design:type", String)
|
|
150
|
-
], EmailSenderSmtp.prototype, "DefaultFileProvider", void 0);
|
|
151
140
|
EmailSenderSmtp = __decorate([
|
|
152
141
|
Injectable(EmailSender),
|
|
153
142
|
NewInstance(),
|
package/lib/mjs/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,MAAM,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AACpE,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAClE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAU,WAAW,EAA6C,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
|