ts-mailkit 2.0.1 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +114 -63
- package/dist/core/client.d.ts +35 -40
- package/dist/core/client.d.ts.map +1 -1
- package/dist/core/errors.d.ts +3 -0
- package/dist/core/errors.d.ts.map +1 -1
- package/dist/core/types.d.ts +126 -7
- package/dist/core/types.d.ts.map +1 -1
- package/dist/index.cjs +329 -68
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +14 -13
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +327 -68
- package/dist/index.js.map +1 -1
- package/dist/renderers/default/default-renderer.d.ts +2 -2
- package/dist/renderers/renderer.interface.d.ts +1 -1
- package/dist/templates/factory.d.ts +1 -1
- package/dist/templates/factory.d.ts.map +1 -1
- package/dist/templates/template-builder.d.ts +36 -0
- package/dist/templates/template-builder.d.ts.map +1 -0
- package/dist/transports/console/console-sender.d.ts +7 -2
- package/dist/transports/console/console-sender.d.ts.map +1 -1
- package/dist/transports/cpaas/cpaas-sender.d.ts +51 -0
- package/dist/transports/cpaas/cpaas-sender.d.ts.map +1 -0
- package/dist/transports/cpaas/types.d.ts +133 -0
- package/dist/transports/cpaas/types.d.ts.map +1 -0
- package/dist/transports/memory/memory-sender.d.ts +26 -6
- package/dist/transports/memory/memory-sender.d.ts.map +1 -1
- package/dist/transports/sender.interface.d.ts +34 -3
- package/dist/transports/sender.interface.d.ts.map +1 -1
- package/package.json +39 -37
- package/dist/transports/zeptomail/types.d.ts +0 -47
- package/dist/transports/zeptomail/types.d.ts.map +0 -1
- package/dist/transports/zeptomail/zeptomail-sender.d.ts +0 -22
- package/dist/transports/zeptomail/zeptomail-sender.d.ts.map +0 -1
package/dist/index.js
CHANGED
|
@@ -67,6 +67,8 @@ var TransportError = class extends MailKitError {
|
|
|
67
67
|
transportName;
|
|
68
68
|
statusCode;
|
|
69
69
|
responseBody;
|
|
70
|
+
/** Parsed raw provider response, when available. */
|
|
71
|
+
rawResponse;
|
|
70
72
|
cause;
|
|
71
73
|
constructor(message, options) {
|
|
72
74
|
super(message);
|
|
@@ -74,6 +76,7 @@ var TransportError = class extends MailKitError {
|
|
|
74
76
|
this.transportName = options.transportName;
|
|
75
77
|
this.statusCode = options.statusCode;
|
|
76
78
|
this.responseBody = options.responseBody;
|
|
79
|
+
this.rawResponse = options.rawResponse;
|
|
77
80
|
this.cause = options.cause;
|
|
78
81
|
Object.setPrototypeOf(this, new.target.prototype);
|
|
79
82
|
}
|
|
@@ -220,18 +223,16 @@ var MailKit = class {
|
|
|
220
223
|
*
|
|
221
224
|
* Example:
|
|
222
225
|
* ```ts
|
|
223
|
-
* await mailer.
|
|
226
|
+
* await mailer.sendMail({
|
|
224
227
|
* to: 'user@example.com',
|
|
225
228
|
* template: myDto,
|
|
226
229
|
* });
|
|
227
230
|
* ```
|
|
228
231
|
*/
|
|
229
|
-
async
|
|
232
|
+
async sendMail(options) {
|
|
230
233
|
const template = options.template;
|
|
231
234
|
const recipientName = options.toName ?? template.userName;
|
|
232
|
-
|
|
233
|
-
if (!resolvedFromName && this.brandNameResolver) resolvedFromName = await this.brandNameResolver();
|
|
234
|
-
if (!resolvedFromName) resolvedFromName = this.defaultBrandName;
|
|
235
|
+
const resolvedFromName = await this.resolveFromName(template, options.fromName);
|
|
235
236
|
const rendered = await this.renderer.render(template);
|
|
236
237
|
const plaintextBody = template.noHtmlMessage ?? rendered.text;
|
|
237
238
|
let toRecipients;
|
|
@@ -240,11 +241,7 @@ var MailKit = class {
|
|
|
240
241
|
name: recipientName
|
|
241
242
|
};
|
|
242
243
|
else toRecipients = options.to;
|
|
243
|
-
|
|
244
|
-
if (resolvedFromName && from) from = {
|
|
245
|
-
address: normalizeRecipient(from).address,
|
|
246
|
-
name: resolvedFromName
|
|
247
|
-
};
|
|
244
|
+
const from = this.applyFromName(options.from ?? this.defaultFrom, resolvedFromName);
|
|
248
245
|
return await this.sendRaw({
|
|
249
246
|
to: toRecipients,
|
|
250
247
|
from,
|
|
@@ -261,6 +258,84 @@ var MailKit = class {
|
|
|
261
258
|
});
|
|
262
259
|
}
|
|
263
260
|
/**
|
|
261
|
+
* Sends a bulk email using a strongly-typed template DTO.
|
|
262
|
+
*
|
|
263
|
+
* The transport delivers an individual copy to each recipient, so
|
|
264
|
+
* recipients are not exposed to one another. Per-recipient personalization
|
|
265
|
+
* is available via {@link sendBulkKnownTemplate}.
|
|
266
|
+
*
|
|
267
|
+
* Example:
|
|
268
|
+
* ```ts
|
|
269
|
+
* await mailer.sendBulkMail({
|
|
270
|
+
* to: ['a@example.com', 'b@example.com'],
|
|
271
|
+
* template: myDto,
|
|
272
|
+
* });
|
|
273
|
+
* ```
|
|
274
|
+
*/
|
|
275
|
+
async sendBulkMail(options) {
|
|
276
|
+
const transport = this.transport;
|
|
277
|
+
if (typeof transport.sendBulk !== "function") throw new ConfigurationError("MailKit: The configured transport does not support bulk sending (sendBulk).");
|
|
278
|
+
const template = options.template;
|
|
279
|
+
const resolvedFromName = await this.resolveFromName(template);
|
|
280
|
+
const rendered = await this.renderer.render(template);
|
|
281
|
+
const plaintextBody = template.noHtmlMessage ?? rendered.text;
|
|
282
|
+
const from = this.applyFromName(options.from ?? this.defaultFrom, resolvedFromName);
|
|
283
|
+
return await transport.sendBulk({
|
|
284
|
+
to: options.to,
|
|
285
|
+
from,
|
|
286
|
+
subject: template.subject,
|
|
287
|
+
html: rendered.html,
|
|
288
|
+
text: plaintextBody,
|
|
289
|
+
cc: options.cc,
|
|
290
|
+
bcc: options.bcc,
|
|
291
|
+
replyTo: options.replyTo,
|
|
292
|
+
attachments: options.attachments,
|
|
293
|
+
headers: options.headers,
|
|
294
|
+
tags: options.tags,
|
|
295
|
+
metadata: options.metadata,
|
|
296
|
+
trackClicks: options.trackClicks,
|
|
297
|
+
trackOpens: options.trackOpens,
|
|
298
|
+
bounceAddress: options.bounceAddress,
|
|
299
|
+
clientReference: options.clientReference
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* Sends a single email using a provider-side template.
|
|
304
|
+
*/
|
|
305
|
+
async sendKnownTemplate(options) {
|
|
306
|
+
const transport = this.transport;
|
|
307
|
+
if (typeof transport.sendKnownTemplate !== "function") throw new ConfigurationError("MailKit: The configured transport does not support template sending (sendKnownTemplate).");
|
|
308
|
+
return await transport.sendKnownTemplate({
|
|
309
|
+
...options,
|
|
310
|
+
from: options.from ?? this.defaultFrom
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* Sends a bulk email using a provider-side template with optional
|
|
315
|
+
* per-recipient merge data.
|
|
316
|
+
*/
|
|
317
|
+
async sendBulkKnownTemplate(options) {
|
|
318
|
+
const transport = this.transport;
|
|
319
|
+
if (typeof transport.sendBulkKnownTemplate !== "function") throw new ConfigurationError("MailKit: The configured transport does not support bulk template sending (sendBulkKnownTemplate).");
|
|
320
|
+
return await transport.sendBulkKnownTemplate({
|
|
321
|
+
...options,
|
|
322
|
+
from: options.from ?? this.defaultFrom
|
|
323
|
+
});
|
|
324
|
+
}
|
|
325
|
+
async resolveFromName(template, explicitFromName) {
|
|
326
|
+
let resolved = explicitFromName ?? template.fromName;
|
|
327
|
+
if (!resolved && this.brandNameResolver) resolved = await this.brandNameResolver();
|
|
328
|
+
if (!resolved) resolved = this.defaultBrandName;
|
|
329
|
+
return resolved;
|
|
330
|
+
}
|
|
331
|
+
applyFromName(from, fromName) {
|
|
332
|
+
if (fromName && from) return {
|
|
333
|
+
address: normalizeRecipient(from).address,
|
|
334
|
+
name: fromName
|
|
335
|
+
};
|
|
336
|
+
return from;
|
|
337
|
+
}
|
|
338
|
+
/**
|
|
264
339
|
* Dispatches a raw, pre-rendered email directly through the transport.
|
|
265
340
|
* If `options.text` is omitted, plain text is automatically derived from `options.html`.
|
|
266
341
|
*/
|
|
@@ -282,38 +357,73 @@ function createMailKit(options) {
|
|
|
282
357
|
}
|
|
283
358
|
|
|
284
359
|
//#endregion
|
|
285
|
-
//#region src/transports/
|
|
360
|
+
//#region src/transports/cpaas/cpaas-sender.ts
|
|
286
361
|
/**
|
|
287
|
-
*
|
|
362
|
+
* Zoho CPaaS transactional email HTTP transport adapter.
|
|
288
363
|
*
|
|
289
|
-
*
|
|
290
|
-
*
|
|
364
|
+
* Uses the standard global `fetch` API for zero-dependency, universal edge
|
|
365
|
+
* compatibility (Node.js, Bun, Deno, Cloudflare Workers).
|
|
366
|
+
*
|
|
367
|
+
* Supports:
|
|
368
|
+
* - `send` — single raw email (`POST /v1.1/email`)
|
|
369
|
+
* - `sendBulk` — batch raw email (`POST /v1.1/email/batch`)
|
|
370
|
+
* - `sendKnownTemplate` — single template email (`POST /v1.1/email/template`)
|
|
371
|
+
* - `sendBulkKnownTemplate` — batch template email (`POST /v1.1/email/template/batch`)
|
|
291
372
|
*/
|
|
292
|
-
var
|
|
293
|
-
name = "
|
|
294
|
-
|
|
373
|
+
var CpaasHttpSender = class {
|
|
374
|
+
name = "cpaas";
|
|
375
|
+
apiBase;
|
|
295
376
|
authHeader;
|
|
296
377
|
defaultFrom;
|
|
378
|
+
preferTemplateAlias;
|
|
297
379
|
fetchImpl;
|
|
298
380
|
constructor(config) {
|
|
299
|
-
if (!config.apiToken || typeof config.apiToken !== "string") throw new ConfigurationError("
|
|
300
|
-
if (!config.from) throw new ConfigurationError("
|
|
301
|
-
const host = (config.apiHost || "
|
|
302
|
-
this.
|
|
381
|
+
if (!config.apiToken || typeof config.apiToken !== "string") throw new ConfigurationError("CpaasHttpSender: Missing or invalid apiToken.");
|
|
382
|
+
if (!config.from) throw new ConfigurationError("CpaasHttpSender: Missing required default from address.");
|
|
383
|
+
const host = (config.apiHost || "cpaas.zoho.com").replace(/^https?:\/\//, "").replace(/\/+$/, "");
|
|
384
|
+
this.apiBase = `https://${host}/v1.1`;
|
|
303
385
|
const token = config.apiToken.trim();
|
|
304
386
|
this.authHeader = token.startsWith("Zoho-") ? token : `Zoho-enczapikey ${token}`;
|
|
305
387
|
this.defaultFrom = normalizeRecipient(config.from);
|
|
306
|
-
if (!this.defaultFrom.address) throw new ConfigurationError("
|
|
388
|
+
if (!this.defaultFrom.address) throw new ConfigurationError("CpaasHttpSender: Configured from address must not be empty.");
|
|
389
|
+
this.preferTemplateAlias = config.preferTemplateAlias ?? false;
|
|
307
390
|
const fetchImpl = config.fetch ?? globalThis.fetch;
|
|
308
|
-
if (typeof fetchImpl !== "function") throw new ConfigurationError("
|
|
391
|
+
if (typeof fetchImpl !== "function") throw new ConfigurationError("CpaasHttpSender: No global fetch implementation found. Pass a custom fetch to CpaasHttpConfig if running on Node < 18.");
|
|
309
392
|
this.fetchImpl = fetchImpl.bind(globalThis);
|
|
310
393
|
}
|
|
311
394
|
/**
|
|
312
|
-
* Dispatches
|
|
395
|
+
* Dispatches a single raw email using Zoho CPaaS API.
|
|
313
396
|
*/
|
|
314
397
|
async send(options) {
|
|
398
|
+
const payload = this.buildSendPayload(options);
|
|
399
|
+
return await this.post(`${this.apiBase}/email`, payload);
|
|
400
|
+
}
|
|
401
|
+
/**
|
|
402
|
+
* Dispatches a batch of a single raw email content to many recipients.
|
|
403
|
+
* The provider delivers an individual copy to each recipient.
|
|
404
|
+
*/
|
|
405
|
+
async sendBulk(options) {
|
|
406
|
+
const payload = this.buildSendPayload(options);
|
|
407
|
+
return await this.post(`${this.apiBase}/email/batch`, payload);
|
|
408
|
+
}
|
|
409
|
+
/**
|
|
410
|
+
* Dispatches a single email using a provider-side template.
|
|
411
|
+
*/
|
|
412
|
+
async sendKnownTemplate(options) {
|
|
413
|
+
const payload = this.buildTemplatePayload(options);
|
|
414
|
+
return await this.post(`${this.apiBase}/email/template`, payload);
|
|
415
|
+
}
|
|
416
|
+
/**
|
|
417
|
+
* Dispatches a batch of emails using a provider-side template, with
|
|
418
|
+
* optional per-recipient merge data.
|
|
419
|
+
*/
|
|
420
|
+
async sendBulkKnownTemplate(options) {
|
|
421
|
+
const payload = this.buildBatchTemplatePayload(options);
|
|
422
|
+
return await this.post(`${this.apiBase}/email/template/batch`, payload);
|
|
423
|
+
}
|
|
424
|
+
buildSendPayload(options) {
|
|
315
425
|
const toRecipients = normalizeRecipients(options.to);
|
|
316
|
-
if (toRecipients.length === 0) throw new TransportError("
|
|
426
|
+
if (toRecipients.length === 0) throw new TransportError("CpaasHttpSender: At least one recipient (to) must be specified.", { transportName: this.name });
|
|
317
427
|
const resolvedFrom = options.from ? normalizeRecipient(options.from) : this.defaultFrom;
|
|
318
428
|
const payload = {
|
|
319
429
|
from: {
|
|
@@ -328,6 +438,52 @@ var ZeptoMailHttpSender = class {
|
|
|
328
438
|
htmlbody: options.html,
|
|
329
439
|
textbody: options.text
|
|
330
440
|
};
|
|
441
|
+
this.applyCommon(payload, options);
|
|
442
|
+
return payload;
|
|
443
|
+
}
|
|
444
|
+
buildTemplatePayload(options) {
|
|
445
|
+
const toRecipients = normalizeRecipients(options.to);
|
|
446
|
+
if (toRecipients.length === 0) throw new TransportError("CpaasHttpSender: At least one recipient (to) must be specified.", { transportName: this.name });
|
|
447
|
+
const resolvedFrom = options.from ? normalizeRecipient(options.from) : this.defaultFrom;
|
|
448
|
+
const payload = {
|
|
449
|
+
...this.templateRef(options.templateId),
|
|
450
|
+
from: {
|
|
451
|
+
address: resolvedFrom.address,
|
|
452
|
+
name: resolvedFrom.name
|
|
453
|
+
},
|
|
454
|
+
to: toRecipients.map((r) => ({ email_address: {
|
|
455
|
+
address: r.address,
|
|
456
|
+
name: r.name || ""
|
|
457
|
+
} }))
|
|
458
|
+
};
|
|
459
|
+
if (options.mergeInfo) payload.merge_info = options.mergeInfo;
|
|
460
|
+
this.applyCommon(payload, options);
|
|
461
|
+
return payload;
|
|
462
|
+
}
|
|
463
|
+
buildBatchTemplatePayload(options) {
|
|
464
|
+
if (!options.to || options.to.length === 0) throw new TransportError("CpaasHttpSender: At least one recipient (to) must be specified.", { transportName: this.name });
|
|
465
|
+
const resolvedFrom = options.from ? normalizeRecipient(options.from) : this.defaultFrom;
|
|
466
|
+
const payload = {
|
|
467
|
+
...this.templateRef(options.templateId),
|
|
468
|
+
from: {
|
|
469
|
+
address: resolvedFrom.address,
|
|
470
|
+
name: resolvedFrom.name
|
|
471
|
+
},
|
|
472
|
+
to: options.to.map((r) => ({
|
|
473
|
+
email_address: {
|
|
474
|
+
address: r.address,
|
|
475
|
+
name: r.name || ""
|
|
476
|
+
},
|
|
477
|
+
...r.mergeInfo ? { merge_info: r.mergeInfo } : {}
|
|
478
|
+
}))
|
|
479
|
+
};
|
|
480
|
+
this.applyCommon(payload, options);
|
|
481
|
+
return payload;
|
|
482
|
+
}
|
|
483
|
+
templateRef(templateId) {
|
|
484
|
+
return this.preferTemplateAlias ? { template_alias: templateId } : { template_key: templateId };
|
|
485
|
+
}
|
|
486
|
+
applyCommon(payload, options) {
|
|
331
487
|
if (options.cc) {
|
|
332
488
|
const ccList = normalizeRecipients(options.cc);
|
|
333
489
|
if (ccList.length > 0) payload.cc = ccList.map((r) => ({ email_address: {
|
|
@@ -349,26 +505,33 @@ var ZeptoMailHttpSender = class {
|
|
|
349
505
|
name: r.name
|
|
350
506
|
}));
|
|
351
507
|
}
|
|
352
|
-
if (options.attachments && options.attachments.length > 0) payload.attachments = options.attachments.map((att) =>
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
508
|
+
if (options.attachments && options.attachments.length > 0) payload.attachments = options.attachments.map((att) => this.toAttachmentPayload(att));
|
|
509
|
+
if (options.trackClicks !== void 0) payload.track_clicks = options.trackClicks;
|
|
510
|
+
if (options.trackOpens !== void 0) payload.track_opens = options.trackOpens;
|
|
511
|
+
if (options.bounceAddress !== void 0) payload.bounce_address = options.bounceAddress;
|
|
512
|
+
if (options.clientReference !== void 0) payload.client_reference = options.clientReference;
|
|
513
|
+
}
|
|
514
|
+
toAttachmentPayload(att) {
|
|
515
|
+
let contentBase64;
|
|
516
|
+
if (typeof att.content === "string") contentBase64 = att.content;
|
|
517
|
+
else if (typeof Buffer !== "undefined") contentBase64 = Buffer.from(att.content).toString("base64");
|
|
518
|
+
else {
|
|
519
|
+
let binary = "";
|
|
520
|
+
const bytes = new Uint8Array(att.content);
|
|
521
|
+
for (let i = 0; i < bytes.byteLength; i++) binary += String.fromCharCode(bytes[i]);
|
|
522
|
+
contentBase64 = btoa(binary);
|
|
523
|
+
}
|
|
524
|
+
return {
|
|
525
|
+
name: att.filename,
|
|
526
|
+
content: contentBase64,
|
|
527
|
+
mime_type: att.mimeType || att.contentType || "application/octet-stream",
|
|
528
|
+
cid: att.cid
|
|
529
|
+
};
|
|
530
|
+
}
|
|
531
|
+
async post(url, payload) {
|
|
369
532
|
let response;
|
|
370
533
|
try {
|
|
371
|
-
response = await this.fetchImpl(
|
|
534
|
+
response = await this.fetchImpl(url, {
|
|
372
535
|
method: "POST",
|
|
373
536
|
headers: {
|
|
374
537
|
Accept: "application/json",
|
|
@@ -378,7 +541,7 @@ var ZeptoMailHttpSender = class {
|
|
|
378
541
|
body: JSON.stringify(payload)
|
|
379
542
|
});
|
|
380
543
|
} catch (err) {
|
|
381
|
-
throw new TransportError(`
|
|
544
|
+
throw new TransportError(`CpaasHttpSender: Network request failed: ${err instanceof Error ? err.message : String(err)}`, {
|
|
382
545
|
transportName: this.name,
|
|
383
546
|
cause: err
|
|
384
547
|
});
|
|
@@ -391,17 +554,18 @@ var ZeptoMailHttpSender = class {
|
|
|
391
554
|
responseData = { raw: responseText };
|
|
392
555
|
}
|
|
393
556
|
if (!response.ok) {
|
|
394
|
-
const errorMessage = responseData?.error?.message || responseData?.message || `HTTP ${response.status}: ${responseText || response.statusText}`;
|
|
395
|
-
throw new TransportError(`
|
|
557
|
+
const errorMessage = responseData?.data?.message || responseData?.error?.message || responseData?.message || `HTTP ${response.status}: ${responseText || response.statusText}`;
|
|
558
|
+
throw new TransportError(`CpaasHttpSender: Failed to send email - ${errorMessage}`, {
|
|
396
559
|
transportName: this.name,
|
|
397
560
|
statusCode: response.status,
|
|
398
|
-
responseBody: responseText
|
|
561
|
+
responseBody: responseText,
|
|
562
|
+
rawResponse: responseData
|
|
399
563
|
});
|
|
400
564
|
}
|
|
401
565
|
return {
|
|
402
566
|
success: true,
|
|
403
567
|
messageId: responseData?.data?.[0]?.message_id,
|
|
404
|
-
|
|
568
|
+
rawResponse: responseData
|
|
405
569
|
};
|
|
406
570
|
}
|
|
407
571
|
};
|
|
@@ -415,36 +579,76 @@ var ZeptoMailHttpSender = class {
|
|
|
415
579
|
var MemoryEmailSender = class {
|
|
416
580
|
name = "memory";
|
|
417
581
|
sentMails = [];
|
|
582
|
+
sentBulkMails = [];
|
|
583
|
+
sentTemplateMails = [];
|
|
584
|
+
sentBulkTemplateMails = [];
|
|
418
585
|
nextId = 1;
|
|
419
|
-
|
|
420
|
-
this.
|
|
421
|
-
const messageId = `mem-${
|
|
586
|
+
result(prefix) {
|
|
587
|
+
const id = this.nextId++;
|
|
588
|
+
const messageId = prefix ? `mem-${prefix}-${id}-${Date.now()}` : `mem-${id}-${Date.now()}`;
|
|
422
589
|
return {
|
|
423
590
|
success: true,
|
|
424
591
|
messageId,
|
|
425
|
-
|
|
592
|
+
rawResponse: { id: messageId }
|
|
426
593
|
};
|
|
427
594
|
}
|
|
595
|
+
async send(options) {
|
|
596
|
+
this.sentMails.push({ ...options });
|
|
597
|
+
return this.result();
|
|
598
|
+
}
|
|
599
|
+
async sendBulk(options) {
|
|
600
|
+
this.sentBulkMails.push({ ...options });
|
|
601
|
+
return this.result("bulk");
|
|
602
|
+
}
|
|
603
|
+
async sendKnownTemplate(options) {
|
|
604
|
+
this.sentTemplateMails.push({ ...options });
|
|
605
|
+
return this.result("tpl");
|
|
606
|
+
}
|
|
607
|
+
async sendBulkKnownTemplate(options) {
|
|
608
|
+
this.sentBulkTemplateMails.push({ ...options });
|
|
609
|
+
return this.result("bulk-tpl");
|
|
610
|
+
}
|
|
428
611
|
/**
|
|
429
|
-
* Returns a copy of all emails sent through this transport instance.
|
|
612
|
+
* Returns a copy of all single emails sent through this transport instance.
|
|
430
613
|
*/
|
|
431
614
|
getSentMails() {
|
|
432
615
|
return [...this.sentMails];
|
|
433
616
|
}
|
|
434
617
|
/**
|
|
435
|
-
* Returns the most recent email sent, or undefined if
|
|
618
|
+
* Returns the most recent single email sent, or undefined if none have been sent.
|
|
436
619
|
*/
|
|
437
620
|
getLastMail() {
|
|
438
621
|
return this.sentMails.length > 0 ? { ...this.sentMails[this.sentMails.length - 1] } : void 0;
|
|
439
622
|
}
|
|
440
623
|
/**
|
|
441
|
-
*
|
|
624
|
+
* Returns a copy of all bulk emails sent through this transport instance.
|
|
625
|
+
*/
|
|
626
|
+
getSentBulkMails() {
|
|
627
|
+
return [...this.sentBulkMails];
|
|
628
|
+
}
|
|
629
|
+
/**
|
|
630
|
+
* Returns a copy of all single template emails sent through this transport instance.
|
|
631
|
+
*/
|
|
632
|
+
getSentTemplateMails() {
|
|
633
|
+
return [...this.sentTemplateMails];
|
|
634
|
+
}
|
|
635
|
+
/**
|
|
636
|
+
* Returns a copy of all bulk template emails sent through this transport instance.
|
|
637
|
+
*/
|
|
638
|
+
getSentBulkTemplateMails() {
|
|
639
|
+
return [...this.sentBulkTemplateMails];
|
|
640
|
+
}
|
|
641
|
+
/**
|
|
642
|
+
* Clears all recorded emails.
|
|
442
643
|
*/
|
|
443
644
|
clear() {
|
|
444
645
|
this.sentMails = [];
|
|
646
|
+
this.sentBulkMails = [];
|
|
647
|
+
this.sentTemplateMails = [];
|
|
648
|
+
this.sentBulkTemplateMails = [];
|
|
445
649
|
}
|
|
446
650
|
/**
|
|
447
|
-
* Returns the total count of
|
|
651
|
+
* Returns the total count of single emails sent.
|
|
448
652
|
*/
|
|
449
653
|
count() {
|
|
450
654
|
return this.sentMails.length;
|
|
@@ -467,33 +671,70 @@ var ConsoleEmailSender = class {
|
|
|
467
671
|
this.includeHtml = options.includeHtml ?? false;
|
|
468
672
|
}
|
|
469
673
|
async send(options) {
|
|
470
|
-
|
|
471
|
-
|
|
674
|
+
return this.logDispatch({
|
|
675
|
+
kind: "EMAIL",
|
|
676
|
+
to: options.to,
|
|
677
|
+
from: options.from,
|
|
678
|
+
subject: options.subject,
|
|
679
|
+
text: options.text,
|
|
680
|
+
html: options.html
|
|
681
|
+
});
|
|
682
|
+
}
|
|
683
|
+
async sendBulk(options) {
|
|
684
|
+
return this.logDispatch({
|
|
685
|
+
kind: "BULK EMAIL",
|
|
686
|
+
to: options.to,
|
|
687
|
+
from: options.from,
|
|
688
|
+
subject: options.subject,
|
|
689
|
+
text: options.text,
|
|
690
|
+
html: options.html
|
|
691
|
+
});
|
|
692
|
+
}
|
|
693
|
+
async sendKnownTemplate(options) {
|
|
694
|
+
return this.logDispatch({
|
|
695
|
+
kind: "TEMPLATE EMAIL",
|
|
696
|
+
to: options.to,
|
|
697
|
+
from: options.from,
|
|
698
|
+
templateId: options.templateId
|
|
699
|
+
});
|
|
700
|
+
}
|
|
701
|
+
async sendBulkKnownTemplate(options) {
|
|
702
|
+
return this.logDispatch({
|
|
703
|
+
kind: "BULK TEMPLATE EMAIL",
|
|
704
|
+
to: options.to,
|
|
705
|
+
from: options.from,
|
|
706
|
+
templateId: options.templateId
|
|
707
|
+
});
|
|
708
|
+
}
|
|
709
|
+
logDispatch(entry) {
|
|
710
|
+
const to = normalizeRecipients(entry.to).map((r) => r.name ? `${r.name} <${r.address}>` : r.address).join(", ");
|
|
711
|
+
const from = entry.from ? JSON.stringify(entry.from) : "(default)";
|
|
472
712
|
const messageId = `console-${this.nextId++}-${Date.now()}`;
|
|
473
713
|
const separator = "─".repeat(60);
|
|
474
714
|
const lines = [
|
|
475
715
|
`\n┌${separator}┐`,
|
|
476
|
-
`│ [ts-mailkit:console] DISPATCHED
|
|
716
|
+
`│ [ts-mailkit:console] DISPATCHED ${entry.kind} (${messageId})`,
|
|
477
717
|
`├${separator}┤`,
|
|
478
718
|
`│ From: ${from}`,
|
|
479
|
-
`│ To: ${to}
|
|
480
|
-
`│ Subject: ${options.subject}`,
|
|
481
|
-
`├${separator}┤`
|
|
719
|
+
`│ To: ${to}`
|
|
482
720
|
];
|
|
483
|
-
if (
|
|
721
|
+
if (entry.subject !== void 0) lines.push(`│ Subject: ${entry.subject}`);
|
|
722
|
+
if (entry.templateId !== void 0) lines.push(`│ Template: ${entry.templateId}`);
|
|
723
|
+
lines.push(`├${separator}┤`);
|
|
724
|
+
if (entry.text) {
|
|
484
725
|
lines.push("│ Text Body:");
|
|
485
|
-
for (const line of
|
|
726
|
+
for (const line of entry.text.split("\n")) lines.push(`│ ${line}`);
|
|
486
727
|
}
|
|
487
|
-
if (this.includeHtml &&
|
|
728
|
+
if (this.includeHtml && entry.html) {
|
|
488
729
|
lines.push("│ HTML Body:");
|
|
489
|
-
for (const line of
|
|
730
|
+
for (const line of entry.html.split("\n")) lines.push(`│ ${line}`);
|
|
490
731
|
}
|
|
491
732
|
lines.push(`└${separator}┘\n`);
|
|
492
733
|
this.log(lines.join("\n"));
|
|
493
734
|
return {
|
|
494
735
|
success: true,
|
|
495
736
|
messageId,
|
|
496
|
-
|
|
737
|
+
rawResponse: { logged: true }
|
|
497
738
|
};
|
|
498
739
|
}
|
|
499
740
|
};
|
|
@@ -680,5 +921,23 @@ var EmailTemplateFactory = class EmailTemplateFactory {
|
|
|
680
921
|
};
|
|
681
922
|
|
|
682
923
|
//#endregion
|
|
683
|
-
|
|
924
|
+
//#region src/templates/template-builder.ts
|
|
925
|
+
/**
|
|
926
|
+
* Builds an upload-ready HTML template from the canonical {@link EmailTemplateDto}.
|
|
927
|
+
*
|
|
928
|
+
* The output can be uploaded to a messaging platform (Zoho CPaaS, SendGrid, etc.)
|
|
929
|
+
* as a provider-side template.
|
|
930
|
+
*/
|
|
931
|
+
function buildHTMLTemplate(dto, options = {}) {
|
|
932
|
+
return buildHtml(dto, options);
|
|
933
|
+
}
|
|
934
|
+
/**
|
|
935
|
+
* Builds an upload-ready plain-text template from the canonical {@link EmailTemplateDto}.
|
|
936
|
+
*/
|
|
937
|
+
function buildPlainTextTemplate(dto, _options) {
|
|
938
|
+
return buildPlainText(dto);
|
|
939
|
+
}
|
|
940
|
+
|
|
941
|
+
//#endregion
|
|
942
|
+
export { ConfigurationError, ConsoleEmailSender, CpaasHttpSender, DefaultEmailRenderer, EmailTemplateFactory, MailKit, MailKitError, MemoryEmailSender, TemplateError, TransportError, buildHTMLTemplate, buildHtml, buildPlainText, buildPlainTextTemplate, createMailKit, decodeHtmlEntities, htmlToPlainText, isValidHttpUrl, normalizeRecipient, normalizeRecipients, parseEmailAddress };
|
|
684
943
|
//# sourceMappingURL=index.js.map
|