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