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