@impruthvi/nodemail 0.6.0 → 1.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 +296 -15
- package/dist/core/FailoverManager.d.ts +7 -0
- package/dist/core/FailoverManager.d.ts.map +1 -0
- package/dist/core/FailoverManager.js +103 -0
- package/dist/core/FailoverManager.js.map +1 -0
- package/dist/core/MailManager.d.ts +1 -0
- package/dist/core/MailManager.d.ts.map +1 -1
- package/dist/core/MailManager.js +57 -2
- package/dist/core/MailManager.js.map +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -2
- package/dist/index.js.map +1 -1
- package/dist/markdown/MarkdownMailable.d.ts +10 -0
- package/dist/markdown/MarkdownMailable.d.ts.map +1 -0
- package/dist/markdown/MarkdownMailable.js +42 -0
- package/dist/markdown/MarkdownMailable.js.map +1 -0
- package/dist/markdown/MarkdownRenderer.d.ts +26 -0
- package/dist/markdown/MarkdownRenderer.d.ts.map +1 -0
- package/dist/markdown/MarkdownRenderer.js +121 -0
- package/dist/markdown/MarkdownRenderer.js.map +1 -0
- package/dist/markdown/index.d.ts +6 -0
- package/dist/markdown/index.d.ts.map +1 -0
- package/dist/markdown/index.js +10 -0
- package/dist/markdown/index.js.map +1 -0
- package/dist/markdown/themes/default.d.ts +7 -0
- package/dist/markdown/themes/default.d.ts.map +1 -0
- package/dist/markdown/themes/default.js +248 -0
- package/dist/markdown/themes/default.js.map +1 -0
- package/dist/testing/AssertableMessage.d.ts +10 -2
- package/dist/testing/AssertableMessage.d.ts.map +1 -1
- package/dist/testing/AssertableMessage.js +27 -1
- package/dist/testing/AssertableMessage.js.map +1 -1
- package/dist/testing/MailFake.d.ts +4 -0
- package/dist/testing/MailFake.d.ts.map +1 -1
- package/dist/testing/MailFake.js +19 -0
- package/dist/testing/MailFake.js.map +1 -1
- package/dist/types/index.d.ts +34 -0
- package/dist/types/index.d.ts.map +1 -1
- package/examples/markdown-mail.ts +219 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
[](https://www.npmjs.com/package/@impruthvi/nodemail)
|
|
4
4
|
[](https://opensource.org/licenses/MIT)
|
|
5
5
|
[](https://www.typescriptlang.org/)
|
|
6
|
-
[](https://github.com/impruthvi/nodemail)
|
|
7
7
|
[](https://github.com/impruthvi/nodemail)
|
|
8
8
|
|
|
9
9
|
**@impruthvi/nodemail** brings the simplicity and elegance of Laravel's Mail system to the Node.js ecosystem with full TypeScript support.
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
|
|
13
13
|
A lightweight, developer-friendly email library where you can:
|
|
14
14
|
- Switch email providers by just changing environment variables
|
|
15
|
-
- Use elegant, class-based Mailable patterns
|
|
15
|
+
- Use elegant, class-based Mailable patterns
|
|
16
16
|
- Keep your package lightweight (install only what you need)
|
|
17
17
|
- Write clean, maintainable email code
|
|
18
18
|
|
|
@@ -20,10 +20,13 @@ Inspired by [Laravel's Mail system](https://laravel.com/docs/mail).
|
|
|
20
20
|
|
|
21
21
|
## ✨ Features
|
|
22
22
|
|
|
23
|
-
### ✅ Available Now (
|
|
23
|
+
### ✅ Available Now (v1.0.0)
|
|
24
24
|
- 🎯 **Multiple Providers** - SMTP (Nodemailer), SendGrid, AWS SES, Mailgun, Resend, Postmark
|
|
25
25
|
- 🎨 **Template Engines** - Handlebars, EJS, Pug support with dynamic loading
|
|
26
26
|
- 📝 **Mailable Classes** - Reusable email definitions with template support
|
|
27
|
+
- 📋 **Markdown Mail** - Write emails in Markdown with components (button, panel, table)
|
|
28
|
+
- 📦 **Queue Support** - Background email sending with Bull/BullMQ
|
|
29
|
+
- 🔄 **Provider Failover** - Automatic failover chain with retries, delays, and callbacks
|
|
27
30
|
- 🧪 **Testing Utilities** - Mail::fake() for testing (Laravel-style assertions)
|
|
28
31
|
- 🪶 **Lightweight** - Only ~25MB with SMTP, install additional providers as needed
|
|
29
32
|
- 🔒 **Type-Safe** - Full TypeScript support with strict typing
|
|
@@ -33,10 +36,9 @@ Inspired by [Laravel's Mail system](https://laravel.com/docs/mail).
|
|
|
33
36
|
|
|
34
37
|
### 🚧 Coming Soon
|
|
35
38
|
- 🔔 **Notifications** - Multi-channel notification system
|
|
36
|
-
- 📋 **Markdown Mail** - Beautiful emails from markdown
|
|
37
|
-
- 📦 **Queue Support** - Background email sending (Bull/BullMQ)
|
|
38
39
|
- 🌍 **i18n Support** - Multi-language emails
|
|
39
40
|
- 🚀 **More Providers** - Mailtrap and others
|
|
41
|
+
- 🎨 **Enhanced CLI** - Command-line tools for queue management
|
|
40
42
|
|
|
41
43
|
## 📦 Installation
|
|
42
44
|
|
|
@@ -46,7 +48,7 @@ npm install @impruthvi/nodemail
|
|
|
46
48
|
|
|
47
49
|
Or install a specific version:
|
|
48
50
|
```bash
|
|
49
|
-
npm install @impruthvi/nodemail@0.
|
|
51
|
+
npm install @impruthvi/nodemail@1.0.0
|
|
50
52
|
```
|
|
51
53
|
|
|
52
54
|
**Lightweight by default!** Only includes SMTP support (~25MB).
|
|
@@ -85,6 +87,12 @@ npm install ejs
|
|
|
85
87
|
npm install pug
|
|
86
88
|
```
|
|
87
89
|
|
|
90
|
+
### Adding Markdown Mail Support (Optional)
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
npm install marked juice
|
|
94
|
+
```
|
|
95
|
+
|
|
88
96
|
## 🚀 Quick Start
|
|
89
97
|
|
|
90
98
|
### SMTP (Nodemailer)
|
|
@@ -284,6 +292,244 @@ await Mail.to('user@example.com')
|
|
|
284
292
|
.send();
|
|
285
293
|
```
|
|
286
294
|
|
|
295
|
+
## 📋 Markdown Mail
|
|
296
|
+
|
|
297
|
+
Write beautiful emails in Markdown with built-in components. Requires `npm install marked juice`.
|
|
298
|
+
|
|
299
|
+
### MarkdownMailable
|
|
300
|
+
|
|
301
|
+
```typescript
|
|
302
|
+
import { MarkdownMailable, Mail } from '@impruthvi/nodemail';
|
|
303
|
+
|
|
304
|
+
class WelcomeEmail extends MarkdownMailable {
|
|
305
|
+
constructor(
|
|
306
|
+
private user: { name: string },
|
|
307
|
+
private appName: string
|
|
308
|
+
) {
|
|
309
|
+
super();
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
build(): this {
|
|
313
|
+
return this
|
|
314
|
+
.subject(`Welcome to ${this.appName}!`)
|
|
315
|
+
.from('noreply@example.com')
|
|
316
|
+
.markdown(`# Welcome, {{name}}!
|
|
317
|
+
|
|
318
|
+
Thank you for joining **{{appName}}**.
|
|
319
|
+
|
|
320
|
+
[button url="https://example.com/start" color="primary"]Get Started[/button]
|
|
321
|
+
|
|
322
|
+
[panel]Need help? Contact support@example.com[/panel]`, {
|
|
323
|
+
name: this.user.name,
|
|
324
|
+
appName: this.appName,
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
await Mail.to('user@example.com').send(new WelcomeEmail(user, 'My App'));
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
### Components
|
|
333
|
+
|
|
334
|
+
**Button** - Call-to-action buttons with color variants:
|
|
335
|
+
```markdown
|
|
336
|
+
[button url="https://example.com" color="primary"]Click Here[/button]
|
|
337
|
+
[button url="https://example.com" color="success"]Confirm[/button]
|
|
338
|
+
[button url="https://example.com" color="error"]Delete[/button]
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
**Panel** - Bordered callout sections:
|
|
342
|
+
```markdown
|
|
343
|
+
[panel]
|
|
344
|
+
**Important:** This is a highlighted notice.
|
|
345
|
+
[/panel]
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
**Table** - Styled table wrapper:
|
|
349
|
+
```markdown
|
|
350
|
+
[table]
|
|
351
|
+
| Name | Price |
|
|
352
|
+
|-------|--------|
|
|
353
|
+
| Item | $9.99 |
|
|
354
|
+
[/table]
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
### Custom Themes
|
|
358
|
+
|
|
359
|
+
```typescript
|
|
360
|
+
class BrandedEmail extends MarkdownMailable {
|
|
361
|
+
build(): this {
|
|
362
|
+
return this
|
|
363
|
+
.subject('Update')
|
|
364
|
+
.markdown('# News\n\nLatest updates...')
|
|
365
|
+
.theme({
|
|
366
|
+
css: 'h1 { color: #e94560; } .button-primary { background: #e94560; }',
|
|
367
|
+
headerHtml: '<img src="https://example.com/logo.png" alt="Logo">',
|
|
368
|
+
footerHtml: '<p>© 2026 Company</p>',
|
|
369
|
+
});
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
### Markdown Configuration
|
|
375
|
+
|
|
376
|
+
```typescript
|
|
377
|
+
Mail.configure({
|
|
378
|
+
// ... mailer config
|
|
379
|
+
markdown: {
|
|
380
|
+
theme: {
|
|
381
|
+
css: '/* custom global CSS */',
|
|
382
|
+
headerHtml: '<img src="logo.png">',
|
|
383
|
+
footerHtml: '<p>Footer</p>',
|
|
384
|
+
},
|
|
385
|
+
customCss: '.button { border-radius: 8px; }',
|
|
386
|
+
},
|
|
387
|
+
});
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
## 📦 Queue Support
|
|
391
|
+
|
|
392
|
+
Send emails in the background with Bull or BullMQ. Requires `npm install bullmq` (or `bull`).
|
|
393
|
+
|
|
394
|
+
```typescript
|
|
395
|
+
Mail.configure({
|
|
396
|
+
// ... mailer config
|
|
397
|
+
queue: {
|
|
398
|
+
driver: 'bullmq',
|
|
399
|
+
connection: { host: 'localhost', port: 6379 },
|
|
400
|
+
retries: 3,
|
|
401
|
+
backoff: { type: 'exponential', delay: 1000 },
|
|
402
|
+
},
|
|
403
|
+
});
|
|
404
|
+
|
|
405
|
+
// Queue immediately
|
|
406
|
+
await Mail.to('user@example.com')
|
|
407
|
+
.subject('Welcome!')
|
|
408
|
+
.html('<h1>Welcome!</h1>')
|
|
409
|
+
.queue();
|
|
410
|
+
|
|
411
|
+
// Delayed sending (60 seconds)
|
|
412
|
+
await Mail.to('user@example.com').later(60, new WelcomeEmail(user));
|
|
413
|
+
|
|
414
|
+
// Scheduled delivery
|
|
415
|
+
await Mail.to('user@example.com').at(new Date('2026-12-25'), new ChristmasEmail());
|
|
416
|
+
|
|
417
|
+
// Process queued emails (in worker)
|
|
418
|
+
await Mail.processQueue();
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
## 🔄 Provider Failover
|
|
422
|
+
|
|
423
|
+
Automatically fail over to backup providers when the primary provider fails. Supports retries, delays, and monitoring callbacks.
|
|
424
|
+
|
|
425
|
+
### Global Failover Configuration
|
|
426
|
+
|
|
427
|
+
```typescript
|
|
428
|
+
Mail.configure({
|
|
429
|
+
default: 'smtp',
|
|
430
|
+
from: { address: 'noreply@example.com', name: 'My App' },
|
|
431
|
+
mailers: {
|
|
432
|
+
smtp: {
|
|
433
|
+
driver: 'smtp',
|
|
434
|
+
host: process.env.SMTP_HOST,
|
|
435
|
+
port: 587,
|
|
436
|
+
auth: { user: process.env.SMTP_USER, pass: process.env.SMTP_PASS },
|
|
437
|
+
},
|
|
438
|
+
sendgrid: {
|
|
439
|
+
driver: 'sendgrid',
|
|
440
|
+
apiKey: process.env.SENDGRID_API_KEY,
|
|
441
|
+
},
|
|
442
|
+
ses: {
|
|
443
|
+
driver: 'ses',
|
|
444
|
+
region: 'us-east-1',
|
|
445
|
+
accessKeyId: process.env.AWS_ACCESS_KEY_ID,
|
|
446
|
+
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
|
|
447
|
+
},
|
|
448
|
+
},
|
|
449
|
+
failover: {
|
|
450
|
+
chain: ['sendgrid', 'ses'],
|
|
451
|
+
maxRetriesPerProvider: 2,
|
|
452
|
+
retryDelay: 1000,
|
|
453
|
+
failoverDelay: 500,
|
|
454
|
+
},
|
|
455
|
+
});
|
|
456
|
+
|
|
457
|
+
// Sends via SMTP first; if SMTP fails (after 2 retries), tries SendGrid, then SES
|
|
458
|
+
await Mail.to('user@example.com')
|
|
459
|
+
.subject('Hello!')
|
|
460
|
+
.html('<h1>Hello!</h1>')
|
|
461
|
+
.send();
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
### Per-mailer Failover Override
|
|
465
|
+
|
|
466
|
+
Override the global failover config for a specific mailer:
|
|
467
|
+
|
|
468
|
+
```typescript
|
|
469
|
+
Mail.configure({
|
|
470
|
+
default: 'smtp',
|
|
471
|
+
mailers: {
|
|
472
|
+
smtp: {
|
|
473
|
+
driver: 'smtp',
|
|
474
|
+
host: process.env.SMTP_HOST,
|
|
475
|
+
port: 587,
|
|
476
|
+
auth: { user: process.env.SMTP_USER, pass: process.env.SMTP_PASS },
|
|
477
|
+
failover: {
|
|
478
|
+
chain: ['postmark'], // Only fail over to Postmark for SMTP
|
|
479
|
+
maxRetriesPerProvider: 3,
|
|
480
|
+
},
|
|
481
|
+
},
|
|
482
|
+
postmark: {
|
|
483
|
+
driver: 'postmark',
|
|
484
|
+
serverToken: process.env.POSTMARK_SERVER_TOKEN,
|
|
485
|
+
},
|
|
486
|
+
},
|
|
487
|
+
});
|
|
488
|
+
```
|
|
489
|
+
|
|
490
|
+
### onFailover Callback
|
|
491
|
+
|
|
492
|
+
Monitor failover events for logging or alerting:
|
|
493
|
+
|
|
494
|
+
```typescript
|
|
495
|
+
Mail.configure({
|
|
496
|
+
// ... mailer config
|
|
497
|
+
failover: {
|
|
498
|
+
chain: ['sendgrid', 'ses'],
|
|
499
|
+
onFailover: (event) => {
|
|
500
|
+
console.log(`Failover: ${event.failedMailer} → ${event.nextMailer}`);
|
|
501
|
+
console.log(`Error: ${event.error}`);
|
|
502
|
+
console.log(`Attempt: ${event.attemptIndex}, Time: ${event.timestamp}`);
|
|
503
|
+
},
|
|
504
|
+
},
|
|
505
|
+
});
|
|
506
|
+
```
|
|
507
|
+
|
|
508
|
+
### Response Metadata
|
|
509
|
+
|
|
510
|
+
After sending, the response includes failover details:
|
|
511
|
+
|
|
512
|
+
```typescript
|
|
513
|
+
const result = await Mail.to('user@example.com')
|
|
514
|
+
.subject('Hello!')
|
|
515
|
+
.html('<h1>Hello!</h1>')
|
|
516
|
+
.send();
|
|
517
|
+
|
|
518
|
+
console.log(result.provider); // 'sendgrid' (which provider actually sent)
|
|
519
|
+
console.log(result.failoverUsed); // true (failover was triggered)
|
|
520
|
+
console.log(result.failoverAttempts); // Array of FailoverDetail objects
|
|
521
|
+
```
|
|
522
|
+
|
|
523
|
+
### FailoverConfig Reference
|
|
524
|
+
|
|
525
|
+
| Property | Type | Default | Description |
|
|
526
|
+
|----------|------|---------|-------------|
|
|
527
|
+
| `chain` | `string[]` | (required) | Ordered list of backup mailer names |
|
|
528
|
+
| `maxRetriesPerProvider` | `number` | `1` | Retries per provider before moving to the next |
|
|
529
|
+
| `retryDelay` | `number` | `0` | Delay (ms) between retries on the same provider |
|
|
530
|
+
| `failoverDelay` | `number` | `0` | Delay (ms) before switching to the next provider |
|
|
531
|
+
| `onFailover` | `(event: FailoverEvent) => void` | — | Callback fired on each failover transition |
|
|
532
|
+
|
|
287
533
|
## 📨 Complete Fluent API
|
|
288
534
|
|
|
289
535
|
```typescript
|
|
@@ -408,6 +654,10 @@ describe('User Registration', () => {
|
|
|
408
654
|
| `Mail.assertNothingQueued()` | Assert nothing was queued |
|
|
409
655
|
| `Mail.sent()` | Get all sent messages |
|
|
410
656
|
| `Mail.sent(Mailable)` | Get sent messages of specific type |
|
|
657
|
+
| `Mail.hasSent()` | Check if any messages were sent |
|
|
658
|
+
| `Mail.hasQueued()` | Check if any messages were queued |
|
|
659
|
+
| `Mail.simulateFailures(n)` | Simulate failures for the first N sends |
|
|
660
|
+
| `Mail.resetFailures()` | Clear failure simulation state |
|
|
411
661
|
|
|
412
662
|
### AssertableMessage Methods
|
|
413
663
|
|
|
@@ -427,6 +677,16 @@ sent.subjectContains('Welcome'); // Subject contains
|
|
|
427
677
|
sent.htmlContains('Hello'); // HTML contains
|
|
428
678
|
sent.textContains('Hello'); // Plain text contains
|
|
429
679
|
|
|
680
|
+
// Check markdown
|
|
681
|
+
sent.isMarkdown(); // Was built from markdown
|
|
682
|
+
sent.getMarkdown(); // Get raw markdown source
|
|
683
|
+
sent.markdownContains('[button'); // Markdown source contains
|
|
684
|
+
|
|
685
|
+
// Check failover
|
|
686
|
+
sent.wasFailoverUsed(); // Whether failover was triggered
|
|
687
|
+
sent.getProvider(); // Provider that actually sent
|
|
688
|
+
sent.getFailoverAttempts(); // Array of FailoverDetail objects
|
|
689
|
+
|
|
430
690
|
// Check attachments
|
|
431
691
|
sent.hasAttachments(); // Has any attachments
|
|
432
692
|
sent.hasAttachment('file.pdf'); // Has specific attachment
|
|
@@ -478,15 +738,36 @@ sent.getHtml(); // Get HTML content
|
|
|
478
738
|
- ✅ assertSent(), assertNotSent(), assertNothingSent()
|
|
479
739
|
- ✅ assertQueued(), assertNothingQueued()
|
|
480
740
|
- ✅ AssertableMessage with inspection methods
|
|
481
|
-
- ✅ Comprehensive test suite (172 tests)
|
|
482
|
-
- ✅ 85%+ code coverage
|
|
483
741
|
|
|
484
|
-
**Phase 6:
|
|
485
|
-
-
|
|
486
|
-
-
|
|
487
|
-
-
|
|
488
|
-
-
|
|
489
|
-
|
|
742
|
+
**Phase 6: Queue Management** ✅ Complete (v0.6.0)
|
|
743
|
+
- ✅ QueueManager with Bull and BullMQ drivers
|
|
744
|
+
- ✅ Immediate, delayed, and scheduled sending
|
|
745
|
+
- ✅ Automatic retries with configurable backoff
|
|
746
|
+
- ✅ MailFake queue assertion support
|
|
747
|
+
|
|
748
|
+
**Phase 7: Markdown Mail** ✅ Complete (v0.7.0)
|
|
749
|
+
- ✅ MarkdownMailable base class
|
|
750
|
+
- ✅ MarkdownRenderer with CSS inlining
|
|
751
|
+
- ✅ Components: button, panel, table
|
|
752
|
+
- ✅ Default responsive email theme
|
|
753
|
+
- ✅ Custom themes and CSS support
|
|
754
|
+
- ✅ AssertableMessage markdown assertions
|
|
755
|
+
|
|
756
|
+
**Phase 8: Provider Failover** ✅ Complete (v1.0.0)
|
|
757
|
+
- ✅ FailoverManager with automatic provider chain
|
|
758
|
+
- ✅ Configurable retries per provider (`maxRetriesPerProvider`)
|
|
759
|
+
- ✅ Retry and failover delays (`retryDelay`, `failoverDelay`)
|
|
760
|
+
- ✅ `onFailover` callback for monitoring/logging
|
|
761
|
+
- ✅ Per-mailer failover overrides
|
|
762
|
+
- ✅ MailFake `simulateFailures()` / `resetFailures()` for testing
|
|
763
|
+
- ✅ Response metadata: `provider`, `failoverUsed`, `failoverAttempts`
|
|
764
|
+
- ✅ 269 passing tests
|
|
765
|
+
|
|
766
|
+
**Phase 9+** 🚧 Coming Soon
|
|
767
|
+
- 🔔 Notifications - Multi-channel notification system
|
|
768
|
+
- 🌍 i18n Support - Multi-language emails
|
|
769
|
+
- 🎨 Enhanced CLI - Command-line tools
|
|
770
|
+
- 🚀 More Providers - Mailtrap and others
|
|
490
771
|
|
|
491
772
|
## 🤝 Contributing
|
|
492
773
|
|
|
@@ -549,7 +830,7 @@ Unlike other packages that bundle everything:
|
|
|
549
830
|
- **Type-Safe**: Full TypeScript support with strict typing
|
|
550
831
|
- **Developer-Friendly**: Clean, intuitive API
|
|
551
832
|
- **Production-Ready**: Built with best practices
|
|
552
|
-
- **Well-Tested**:
|
|
833
|
+
- **Well-Tested**: 269 passing tests with 85%+ coverage
|
|
553
834
|
|
|
554
835
|
## 📄 License
|
|
555
836
|
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { MailOptions, MailProvider, MailResponse, FailoverConfig } from '../types';
|
|
2
|
+
export declare class FailoverManager {
|
|
3
|
+
sendWithFailover(options: MailOptions, primaryName: string, primaryProvider: MailProvider, failoverConfig: FailoverConfig, getProvider: (name: string) => MailProvider): Promise<MailResponse>;
|
|
4
|
+
private tryProvider;
|
|
5
|
+
private delay;
|
|
6
|
+
}
|
|
7
|
+
//# sourceMappingURL=FailoverManager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FailoverManager.d.ts","sourceRoot":"","sources":["../../src/core/FailoverManager.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,cAAc,EAEf,MAAM,UAAU,CAAC;AAElB,qBAAa,eAAe;IAKpB,gBAAgB,CACpB,OAAO,EAAE,WAAW,EACpB,WAAW,EAAE,MAAM,EACnB,eAAe,EAAE,YAAY,EAC7B,cAAc,EAAE,cAAc,EAC9B,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,YAAY,GAC1C,OAAO,CAAC,YAAY,CAAC;YA+FV,WAAW;IA8CzB,OAAO,CAAC,KAAK;CAGd"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FailoverManager = void 0;
|
|
4
|
+
class FailoverManager {
|
|
5
|
+
async sendWithFailover(options, primaryName, primaryProvider, failoverConfig, getProvider) {
|
|
6
|
+
const maxRetries = failoverConfig.maxRetriesPerProvider ?? 1;
|
|
7
|
+
const retryDelay = failoverConfig.retryDelay ?? 0;
|
|
8
|
+
const failoverDelay = failoverConfig.failoverDelay ?? 0;
|
|
9
|
+
const attempts = [];
|
|
10
|
+
const primaryResult = await this.tryProvider(primaryProvider, primaryName, options, maxRetries, retryDelay, attempts);
|
|
11
|
+
if (primaryResult.success) {
|
|
12
|
+
return {
|
|
13
|
+
...primaryResult,
|
|
14
|
+
provider: primaryName,
|
|
15
|
+
failoverUsed: false,
|
|
16
|
+
failoverAttempts: attempts,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
for (const chainName of failoverConfig.chain) {
|
|
20
|
+
if (chainName === primaryName) {
|
|
21
|
+
continue;
|
|
22
|
+
}
|
|
23
|
+
let chainProvider;
|
|
24
|
+
try {
|
|
25
|
+
chainProvider = getProvider(chainName);
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
const lastFailed = attempts[attempts.length - 1];
|
|
31
|
+
if (failoverConfig.onFailover && lastFailed) {
|
|
32
|
+
try {
|
|
33
|
+
failoverConfig.onFailover({
|
|
34
|
+
failedMailer: lastFailed.mailer,
|
|
35
|
+
error: lastFailed.error ?? 'Unknown error',
|
|
36
|
+
nextMailer: chainName,
|
|
37
|
+
attemptIndex: attempts.length,
|
|
38
|
+
timestamp: new Date().toISOString(),
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
if (failoverDelay > 0) {
|
|
45
|
+
await this.delay(failoverDelay);
|
|
46
|
+
}
|
|
47
|
+
const chainResult = await this.tryProvider(chainProvider, chainName, options, maxRetries, retryDelay, attempts);
|
|
48
|
+
if (chainResult.success) {
|
|
49
|
+
return {
|
|
50
|
+
...chainResult,
|
|
51
|
+
provider: chainName,
|
|
52
|
+
failoverUsed: true,
|
|
53
|
+
failoverAttempts: attempts,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return {
|
|
58
|
+
success: false,
|
|
59
|
+
error: 'All providers failed',
|
|
60
|
+
provider: primaryName,
|
|
61
|
+
failoverUsed: true,
|
|
62
|
+
failoverAttempts: attempts,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
async tryProvider(provider, name, options, maxRetries, retryDelay, attempts) {
|
|
66
|
+
let lastResponse = { success: false, error: 'No attempts made' };
|
|
67
|
+
for (let attempt = 0; attempt < maxRetries; attempt++) {
|
|
68
|
+
if (attempt > 0 && retryDelay > 0) {
|
|
69
|
+
await this.delay(retryDelay);
|
|
70
|
+
}
|
|
71
|
+
const start = Date.now();
|
|
72
|
+
try {
|
|
73
|
+
lastResponse = await provider.send(options);
|
|
74
|
+
const durationMs = Date.now() - start;
|
|
75
|
+
const detail = { mailer: name, success: lastResponse.success, durationMs };
|
|
76
|
+
if (!lastResponse.success && lastResponse.error) {
|
|
77
|
+
detail.error = lastResponse.error;
|
|
78
|
+
}
|
|
79
|
+
attempts.push(detail);
|
|
80
|
+
if (lastResponse.success) {
|
|
81
|
+
return lastResponse;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
catch (err) {
|
|
85
|
+
const durationMs = Date.now() - start;
|
|
86
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
87
|
+
lastResponse = { success: false, error: errorMessage };
|
|
88
|
+
attempts.push({
|
|
89
|
+
mailer: name,
|
|
90
|
+
success: false,
|
|
91
|
+
error: errorMessage,
|
|
92
|
+
durationMs,
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return lastResponse;
|
|
97
|
+
}
|
|
98
|
+
delay(ms) {
|
|
99
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
exports.FailoverManager = FailoverManager;
|
|
103
|
+
//# sourceMappingURL=FailoverManager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FailoverManager.js","sourceRoot":"","sources":["../../src/core/FailoverManager.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MailManager.d.ts","sourceRoot":"","sources":["../../src/core/MailManager.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,UAAU,EACV,WAAW,EAEX,YAAY,EAEZ,UAAU,EACV,cAAc,EACf,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"MailManager.d.ts","sourceRoot":"","sources":["../../src/core/MailManager.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,UAAU,EACV,WAAW,EAEX,YAAY,EAEZ,UAAU,EACV,cAAc,EACf,MAAM,UAAU,CAAC;AAYlB,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAIrD,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAAa;IAC3B,OAAO,CAAC,SAAS,CAAwC;IACzD,OAAO,CAAC,cAAc,CAAC,CAAiB;IACxC,OAAO,CAAC,YAAY,CAAC,CAAe;IACpC,OAAO,CAAC,eAAe,CAAyB;gBAEpC,MAAM,EAAE,UAAU;IAU9B,OAAO,CAAC,wBAAwB;IA0ChC,OAAO,CAAC,sBAAsB;IAU9B,eAAe,IAAI,YAAY,GAAG,SAAS;IAOrC,KAAK,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,cAAc,CAAC;IAUpD,KAAK,CAAC,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAU1E,EAAE,CAAC,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,cAAc,CAAC;IAU7D,YAAY,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAYrD,OAAO,CAAC,cAAc;IAsBtB,OAAO,CAAC,WAAW;IAyBnB,EAAE,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE;IAO7B,MAAM,CAAC,IAAI,EAAE,MAAM;IAab,IAAI,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC;IAkGvD,gBAAgB,IAAI,MAAM;CAG3B;AAKD,qBAAa,cAAc;IAIvB,OAAO,CAAC,OAAO;IAHV,OAAO,EAAE,OAAO,CAAC,WAAW,CAAC,CAAM;gBAGhC,OAAO,EAAE,WAAW,EAC5B,EAAE,EAAE,MAAM,GAAG,MAAM,EAAE;IAKvB,OAAO,CAAC,OAAO,EAAE,MAAM;IAKvB,IAAI,CAAC,IAAI,EAAE,MAAM;IAKjB,IAAI,CAAC,IAAI,EAAE,MAAM;IAKjB,IAAI,CAAC,IAAI,EAAE,MAAM;IAKjB,EAAE,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,EAAE;IAKxB,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE;IAK1B,OAAO,CAAC,OAAO,EAAE,MAAM;IAKvB,WAAW,CAAC,WAAW,EAAE,UAAU,EAAE;IAKrC,OAAO,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAKvC,QAAQ,CAAC,QAAQ,EAAE,MAAM;IAKzB,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAK5B,IAAI,CAAC,QAAQ,CAAC,EAAE,OAAO,YAAY,EAAE,QAAQ,GAAG,OAAO,CAAC,YAAY,CAAC;IAwBrE,KAAK,CAAC,QAAQ,CAAC,EAAE,OAAO,YAAY,EAAE,QAAQ,GAAG,OAAO,CAAC,cAAc,CAAC;IAQxE,KAAK,CAAC,YAAY,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,OAAO,YAAY,EAAE,QAAQ,GAAG,OAAO,CAAC,cAAc,CAAC;IAQ9F,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,CAAC,EAAE,OAAO,YAAY,EAAE,QAAQ,GAAG,OAAO,CAAC,cAAc,CAAC;IAQvF,OAAO,CAAC,cAAc;CAgBvB"}
|
package/dist/core/MailManager.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.MessageBuilder = exports.MailManager = void 0;
|
|
4
|
+
const FailoverManager_1 = require("./FailoverManager");
|
|
4
5
|
const SmtpProvider_1 = require("../providers/SmtpProvider");
|
|
5
6
|
const SendGridProvider_1 = require("../providers/SendGridProvider");
|
|
6
7
|
const SesProvider_1 = require("../providers/SesProvider");
|
|
@@ -11,11 +12,13 @@ const HandlebarsEngine_1 = require("../templates/HandlebarsEngine");
|
|
|
11
12
|
const EjsEngine_1 = require("../templates/EjsEngine");
|
|
12
13
|
const PugEngine_1 = require("../templates/PugEngine");
|
|
13
14
|
const QueueManager_1 = require("../queue/QueueManager");
|
|
15
|
+
const MarkdownRenderer_1 = require("../markdown/MarkdownRenderer");
|
|
14
16
|
class MailManager {
|
|
15
17
|
config;
|
|
16
18
|
providers = new Map();
|
|
17
19
|
templateEngine;
|
|
18
20
|
queueManager;
|
|
21
|
+
failoverManager = new FailoverManager_1.FailoverManager();
|
|
19
22
|
constructor(config) {
|
|
20
23
|
this.config = config;
|
|
21
24
|
this.initializeTemplateEngine();
|
|
@@ -134,12 +137,64 @@ class MailManager {
|
|
|
134
137
|
return new MailManager(newConfig);
|
|
135
138
|
}
|
|
136
139
|
async send(options) {
|
|
140
|
+
if (options.data?.['__markdown']) {
|
|
141
|
+
const markdownContent = options.data['__markdown'];
|
|
142
|
+
const mailableOverrides = (options.data['__markdownRendererOptions'] || {});
|
|
143
|
+
const rendererOptions = {};
|
|
144
|
+
if (this.config.markdown?.theme) {
|
|
145
|
+
const themeCfg = this.config.markdown.theme;
|
|
146
|
+
rendererOptions.theme = {
|
|
147
|
+
css: themeCfg.css || '',
|
|
148
|
+
...(themeCfg.headerHtml !== undefined ? { headerHtml: themeCfg.headerHtml } : {}),
|
|
149
|
+
...(themeCfg.footerHtml !== undefined ? { footerHtml: themeCfg.footerHtml } : {}),
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
if (this.config.markdown?.customCss) {
|
|
153
|
+
rendererOptions.customCss = this.config.markdown.customCss;
|
|
154
|
+
}
|
|
155
|
+
if (mailableOverrides['theme'] !== undefined) {
|
|
156
|
+
rendererOptions.theme = mailableOverrides['theme'];
|
|
157
|
+
}
|
|
158
|
+
if (mailableOverrides['customCss']) {
|
|
159
|
+
rendererOptions.customCss = mailableOverrides['customCss'];
|
|
160
|
+
}
|
|
161
|
+
const renderer = new MarkdownRenderer_1.MarkdownRenderer(rendererOptions);
|
|
162
|
+
const userData = {};
|
|
163
|
+
for (const [key, value] of Object.entries(options.data)) {
|
|
164
|
+
if (key !== '__markdown' && key !== '__markdownRendererOptions') {
|
|
165
|
+
userData[key] = value;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
const { html, text } = await renderer.render(markdownContent, Object.keys(userData).length > 0 ? userData : undefined);
|
|
169
|
+
options = {
|
|
170
|
+
...options,
|
|
171
|
+
html: options.html || html,
|
|
172
|
+
text: options.text || text,
|
|
173
|
+
};
|
|
174
|
+
const cleanData = { ...options.data };
|
|
175
|
+
delete cleanData['__markdown'];
|
|
176
|
+
delete cleanData['__markdownRendererOptions'];
|
|
177
|
+
const hasRemainingData = Object.keys(cleanData).length > 0;
|
|
178
|
+
options = {
|
|
179
|
+
...options,
|
|
180
|
+
...(hasRemainingData ? { data: cleanData } : {}),
|
|
181
|
+
};
|
|
182
|
+
if (!hasRemainingData) {
|
|
183
|
+
delete options['data'];
|
|
184
|
+
}
|
|
185
|
+
}
|
|
137
186
|
if (options.template && this.templateEngine) {
|
|
138
187
|
const html = await this.templateEngine.renderFile(options.template, options.data);
|
|
139
188
|
options = { ...options, html };
|
|
140
189
|
}
|
|
141
|
-
const
|
|
142
|
-
|
|
190
|
+
const mailerName = this.config.default;
|
|
191
|
+
const provider = this.getProvider(mailerName);
|
|
192
|
+
const mailerConfig = this.config.mailers[mailerName];
|
|
193
|
+
const failoverConfig = mailerConfig?.failover ?? this.config.failover;
|
|
194
|
+
if (!failoverConfig || failoverConfig.chain.length === 0) {
|
|
195
|
+
return provider.send(options);
|
|
196
|
+
}
|
|
197
|
+
return this.failoverManager.sendWithFailover(options, mailerName, provider, failoverConfig, (name) => this.getProvider(name));
|
|
143
198
|
}
|
|
144
199
|
getDefaultMailer() {
|
|
145
200
|
return this.config.default;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MailManager.js","sourceRoot":"","sources":["../../src/core/MailManager.ts"],"names":[],"mappings":";;;AAcA,4DAAyD;AACzD,oEAAiE;AACjE,0DAAuD;AACvD,kEAA+D;AAC/D,gEAA6D;AAC7D,oEAAiE;AAEjE,oEAAiE;AACjE,sDAAmD;AACnD,sDAAmD;AACnD,wDAAqD;
|
|
1
|
+
{"version":3,"file":"MailManager.js","sourceRoot":"","sources":["../../src/core/MailManager.ts"],"names":[],"mappings":"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"}
|