@impruthvi/nodemail 0.3.0 → 0.5.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/CHANGELOG.md +63 -0
- package/README.md +247 -64
- package/dist/core/MailFacade.d.ts +42 -4
- package/dist/core/MailFacade.d.ts.map +1 -1
- package/dist/core/MailFacade.js +191 -4
- package/dist/core/MailFacade.js.map +1 -1
- package/dist/core/MailManager.d.ts +11 -2
- package/dist/core/MailManager.d.ts.map +1 -1
- package/dist/core/MailManager.js +79 -1
- package/dist/core/MailManager.js.map +1 -1
- package/dist/core/Mailable.d.ts +12 -2
- package/dist/core/Mailable.d.ts.map +1 -1
- package/dist/core/Mailable.js +44 -2
- package/dist/core/Mailable.js.map +1 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -2
- package/dist/index.js.map +1 -1
- package/dist/templates/EjsEngine.d.ts +14 -0
- package/dist/templates/EjsEngine.d.ts.map +1 -0
- package/dist/templates/EjsEngine.js +59 -0
- package/dist/templates/EjsEngine.js.map +1 -0
- package/dist/templates/HandlebarsEngine.d.ts +16 -0
- package/dist/templates/HandlebarsEngine.d.ts.map +1 -0
- package/dist/templates/HandlebarsEngine.js +65 -0
- package/dist/templates/HandlebarsEngine.js.map +1 -0
- package/dist/templates/PugEngine.d.ts +15 -0
- package/dist/templates/PugEngine.d.ts.map +1 -0
- package/dist/templates/PugEngine.js +70 -0
- package/dist/templates/PugEngine.js.map +1 -0
- package/dist/templates/TemplateEngine.d.ts +12 -0
- package/dist/templates/TemplateEngine.d.ts.map +1 -0
- package/dist/templates/TemplateEngine.js +3 -0
- package/dist/templates/TemplateEngine.js.map +1 -0
- package/dist/templates/index.d.ts +5 -0
- package/dist/templates/index.d.ts.map +1 -0
- package/dist/templates/index.js +10 -0
- package/dist/templates/index.js.map +1 -0
- package/dist/testing/AssertableMessage.d.ts +40 -0
- package/dist/testing/AssertableMessage.d.ts.map +1 -0
- package/dist/testing/AssertableMessage.js +158 -0
- package/dist/testing/AssertableMessage.js.map +1 -0
- package/dist/testing/MailFake.d.ts +32 -0
- package/dist/testing/MailFake.d.ts.map +1 -0
- package/dist/testing/MailFake.js +155 -0
- package/dist/testing/MailFake.js.map +1 -0
- package/dist/testing/index.d.ts +4 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +8 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/types/index.d.ts +9 -0
- package/dist/types/index.d.ts.map +1 -1
- package/examples/mailgun.ts +1 -1
- package/examples/postmark.ts +1 -1
- package/examples/resend.ts +1 -1
- package/examples/testing-example.ts +303 -0
- package/examples/views/invoice.ejs +26 -0
- package/examples/views/notification.pug +14 -0
- package/examples/views/welcome.hbs +15 -0
- package/examples/with-ejs.ts +63 -0
- package/examples/with-handlebars.ts +60 -0
- package/examples/with-mailable-templates.ts +146 -0
- package/examples/with-pug.ts +66 -0
- package/package.json +16 -4
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,69 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.4.0] - 2025-12-07
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- **Template Engine Support** (Phase 4 complete)
|
|
14
|
+
- HandlebarsEngine with dynamic loading and caching
|
|
15
|
+
- EjsEngine with dynamic loading and caching
|
|
16
|
+
- PugEngine with dynamic loading and caching
|
|
17
|
+
- TemplateEngine interface for custom engines
|
|
18
|
+
- **Complete Fluent API** - All email options now chainable
|
|
19
|
+
- Added `cc()` method for carbon copy recipients
|
|
20
|
+
- Added `bcc()` method for blind carbon copy recipients
|
|
21
|
+
- Added `replyTo()` method for reply-to addresses
|
|
22
|
+
- Added `attachments()` method for file attachments
|
|
23
|
+
- Added `headers()` method for custom headers
|
|
24
|
+
- **Laravel-like Mailable Pattern** - Elegant email class API
|
|
25
|
+
- `Mailable.to()` method for setting recipients
|
|
26
|
+
- `Mailable.send()` method for direct sending
|
|
27
|
+
- `Mail.to().send(mailable)` Laravel-style syntax (recommended)
|
|
28
|
+
- `mailable.to().send()` alternative direct syntax
|
|
29
|
+
- Protected methods: `cc()`, `bcc()`, `replyTo()`, `attach()`, `withHeaders()`
|
|
30
|
+
- Enhanced MailManager with automatic template rendering
|
|
31
|
+
- Added template configuration to MailConfig
|
|
32
|
+
- Support for 'handlebars', 'ejs', 'pug' engines
|
|
33
|
+
- Custom engine instance support
|
|
34
|
+
- Configurable views path, extension, and caching
|
|
35
|
+
- Template engine tests (34 new tests)
|
|
36
|
+
- HandlebarsEngine.test.ts (11 tests)
|
|
37
|
+
- EjsEngine.test.ts (11 tests)
|
|
38
|
+
- PugEngine.test.ts (12 tests)
|
|
39
|
+
- Mailable tests (10 new tests)
|
|
40
|
+
- Comprehensive Mailable class testing
|
|
41
|
+
- Template support validation
|
|
42
|
+
- Laravel-style API testing
|
|
43
|
+
- Template examples
|
|
44
|
+
- examples/with-handlebars.ts
|
|
45
|
+
- examples/with-ejs.ts
|
|
46
|
+
- examples/with-pug.ts
|
|
47
|
+
- examples/with-mailable-templates.ts (refactored)
|
|
48
|
+
- examples/views/ directory with sample templates
|
|
49
|
+
- Test utilities
|
|
50
|
+
- test-smtp-ethereal.ts for instant SMTP testing
|
|
51
|
+
- test-templates.ts for template engine validation
|
|
52
|
+
|
|
53
|
+
### Changed
|
|
54
|
+
- **BREAKING**: Refactored Mailable class to Laravel-like pattern
|
|
55
|
+
- Removed `getMailOptions()` method
|
|
56
|
+
- Now uses `build()` method with fluent API
|
|
57
|
+
- Direct sending capability added
|
|
58
|
+
- Updated package.json to version 0.4.0
|
|
59
|
+
- Added handlebars, ejs, pug to peerDependencies (all optional)
|
|
60
|
+
- Enhanced MessageBuilder.send() to accept Mailable instances
|
|
61
|
+
- Updated test suite: 122 total tests (17 new tests added)
|
|
62
|
+
- Code coverage: 85%+ overall
|
|
63
|
+
- Template engines coverage: 93.5%
|
|
64
|
+
- ESLint configuration for all directories (src, examples, tests)
|
|
65
|
+
|
|
66
|
+
### Fixed
|
|
67
|
+
- Type safety for template engine configuration
|
|
68
|
+
- Promise handling in template rendering
|
|
69
|
+
- ESLint warnings for template engine dynamic loading
|
|
70
|
+
- ESLint parsing errors for examples directory
|
|
71
|
+
- Floating promise warnings in example files
|
|
72
|
+
|
|
10
73
|
## [0.3.0] - 2025-11-25
|
|
11
74
|
|
|
12
75
|
### Added
|
package/README.md
CHANGED
|
@@ -3,12 +3,10 @@
|
|
|
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
|
+
[](https://github.com/impruthvi/nodemail)
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
**@impruthvi/nodemail** aims to bring the simplicity and elegance of Laravel's Mail system to the Node.js ecosystem with full TypeScript support.
|
|
9
|
+
**@impruthvi/nodemail** brings the simplicity and elegance of Laravel's Mail system to the Node.js ecosystem with full TypeScript support.
|
|
12
10
|
|
|
13
11
|
## 🎯 Vision
|
|
14
12
|
|
|
@@ -22,33 +20,33 @@ Inspired by [Laravel's Mail system](https://laravel.com/docs/mail).
|
|
|
22
20
|
|
|
23
21
|
## ✨ Features
|
|
24
22
|
|
|
25
|
-
### ✅ Available Now
|
|
23
|
+
### ✅ Available Now (v0.5.0)
|
|
26
24
|
- 🎯 **Multiple Providers** - SMTP (Nodemailer), SendGrid, AWS SES, Mailgun, Resend, Postmark
|
|
25
|
+
- 🎨 **Template Engines** - Handlebars, EJS, Pug support with dynamic loading
|
|
26
|
+
- 📝 **Mailable Classes** - Reusable email definitions with template support
|
|
27
|
+
- 🧪 **Testing Utilities** - Mail::fake() for testing (Laravel-style assertions)
|
|
27
28
|
- 🪶 **Lightweight** - Only ~25MB with SMTP, install additional providers as needed
|
|
28
29
|
- 🔒 **Type-Safe** - Full TypeScript support with strict typing
|
|
29
|
-
-
|
|
30
|
-
- ⚡ **Dynamic Loading** - Providers loaded only when installed (peerDependencies)
|
|
30
|
+
- ✨ **Complete Fluent API** - Chain to(), subject(), html(), template(), data(), cc(), bcc(), attachments(), headers()
|
|
31
|
+
- ⚡ **Dynamic Loading** - Providers and templates loaded only when installed (peerDependencies)
|
|
31
32
|
- 🛡️ **Error Handling** - Graceful degradation with helpful error messages
|
|
32
33
|
|
|
33
34
|
### 🚧 Coming Soon
|
|
34
|
-
- 📝 **Mailable Classes** - Enhanced reusable email definitions
|
|
35
35
|
- 🔔 **Notifications** - Multi-channel notification system
|
|
36
36
|
- 📋 **Markdown Mail** - Beautiful emails from markdown
|
|
37
|
-
- 🧪 **Testing Utilities** - Mail::fake() for testing
|
|
38
37
|
- 📦 **Queue Support** - Background email sending (Bull/BullMQ)
|
|
39
|
-
- 🎨 **Template Engines** - Handlebars, EJS, Pug
|
|
40
38
|
- 🌍 **i18n Support** - Multi-language emails
|
|
41
39
|
- 🚀 **More Providers** - Mailtrap and others
|
|
42
40
|
|
|
43
41
|
## 📦 Installation
|
|
44
42
|
|
|
45
43
|
```bash
|
|
46
|
-
npm install @impruthvi/nodemail
|
|
44
|
+
npm install @impruthvi/nodemail
|
|
47
45
|
```
|
|
48
46
|
|
|
49
|
-
Or
|
|
47
|
+
Or install a specific version:
|
|
50
48
|
```bash
|
|
51
|
-
npm install @impruthvi/nodemail
|
|
49
|
+
npm install @impruthvi/nodemail@0.5.0
|
|
52
50
|
```
|
|
53
51
|
|
|
54
52
|
**Lightweight by default!** Only includes SMTP support (~25MB).
|
|
@@ -73,6 +71,20 @@ npm install resend
|
|
|
73
71
|
npm install postmark
|
|
74
72
|
```
|
|
75
73
|
|
|
74
|
+
### Adding Template Engines (Optional)
|
|
75
|
+
|
|
76
|
+
**Currently Supported:**
|
|
77
|
+
```bash
|
|
78
|
+
# Handlebars (✅ Implemented)
|
|
79
|
+
npm install handlebars
|
|
80
|
+
|
|
81
|
+
# EJS (✅ Implemented)
|
|
82
|
+
npm install ejs
|
|
83
|
+
|
|
84
|
+
# Pug (✅ Implemented)
|
|
85
|
+
npm install pug
|
|
86
|
+
```
|
|
87
|
+
|
|
76
88
|
## 🚀 Quick Start
|
|
77
89
|
|
|
78
90
|
### SMTP (Nodemailer)
|
|
@@ -200,79 +212,233 @@ Mail.configure({
|
|
|
200
212
|
});
|
|
201
213
|
```
|
|
202
214
|
|
|
203
|
-
|
|
215
|
+
## 🎨 Template Engines
|
|
216
|
+
|
|
217
|
+
### Using Handlebars
|
|
204
218
|
|
|
205
219
|
```typescript
|
|
206
|
-
|
|
220
|
+
// npm install handlebars
|
|
221
|
+
import { Mail } from '@impruthvi/nodemail';
|
|
207
222
|
|
|
208
|
-
// Configure once
|
|
209
223
|
Mail.configure({
|
|
210
224
|
default: 'smtp',
|
|
211
|
-
from: {
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
host: process.env.MAIL_HOST,
|
|
219
|
-
port: 587,
|
|
220
|
-
username: process.env.MAIL_USERNAME,
|
|
221
|
-
password: process.env.MAIL_PASSWORD,
|
|
222
|
-
},
|
|
225
|
+
from: { address: 'noreply@example.com', name: 'My App' },
|
|
226
|
+
mailers: { /* your mailer config */ },
|
|
227
|
+
templates: {
|
|
228
|
+
engine: 'handlebars',
|
|
229
|
+
viewsPath: './views/emails',
|
|
230
|
+
extension: '.hbs',
|
|
231
|
+
cache: true,
|
|
223
232
|
},
|
|
224
233
|
});
|
|
225
234
|
|
|
226
|
-
// Send
|
|
235
|
+
// Send with template
|
|
227
236
|
await Mail.to('user@example.com')
|
|
228
237
|
.subject('Welcome!')
|
|
229
|
-
.
|
|
238
|
+
.template('welcome')
|
|
239
|
+
.data({ name: 'John', appName: 'My App' })
|
|
230
240
|
.send();
|
|
231
241
|
```
|
|
232
242
|
|
|
233
|
-
**
|
|
243
|
+
**Template file** (`views/emails/welcome.hbs`):
|
|
244
|
+
```handlebars
|
|
245
|
+
<h1>Welcome, {{name}}!</h1>
|
|
246
|
+
<p>Thank you for joining {{appName}}.</p>
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
### Using EJS
|
|
234
250
|
|
|
235
251
|
```typescript
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
// Configure once
|
|
252
|
+
// npm install ejs
|
|
239
253
|
Mail.configure({
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
254
|
+
templates: {
|
|
255
|
+
engine: 'ejs',
|
|
256
|
+
viewsPath: './views/emails',
|
|
257
|
+
extension: '.ejs',
|
|
244
258
|
},
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
await Mail.to('customer@example.com')
|
|
262
|
+
.subject('Your Invoice')
|
|
263
|
+
.template('invoice')
|
|
264
|
+
.data({ items: [...], total: 99.99 })
|
|
265
|
+
.send();
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
### Using Pug
|
|
269
|
+
|
|
270
|
+
```typescript
|
|
271
|
+
// npm install pug
|
|
272
|
+
Mail.configure({
|
|
273
|
+
templates: {
|
|
274
|
+
engine: 'pug',
|
|
275
|
+
viewsPath: './views/emails',
|
|
276
|
+
cache: true,
|
|
253
277
|
},
|
|
254
278
|
});
|
|
255
279
|
|
|
256
|
-
// Send anywhere in your app
|
|
257
280
|
await Mail.to('user@example.com')
|
|
258
|
-
.subject('
|
|
259
|
-
.
|
|
281
|
+
.subject('Notification')
|
|
282
|
+
.template('notification')
|
|
283
|
+
.data({ title: 'Update', message: 'New features!' })
|
|
284
|
+
.send();
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
## 📨 Complete Fluent API
|
|
288
|
+
|
|
289
|
+
```typescript
|
|
290
|
+
await Mail.to('user@example.com')
|
|
291
|
+
.subject('Complete Example')
|
|
292
|
+
.html('<h1>Hello!</h1>')
|
|
293
|
+
.text('Hello!')
|
|
294
|
+
.from('custom@example.com')
|
|
295
|
+
.cc(['manager@example.com', 'team@example.com'])
|
|
296
|
+
.bcc('archive@example.com')
|
|
297
|
+
.replyTo('support@example.com')
|
|
298
|
+
.attachments([
|
|
299
|
+
{ filename: 'report.pdf', path: './files/report.pdf' },
|
|
300
|
+
{ filename: 'image.png', content: buffer },
|
|
301
|
+
])
|
|
302
|
+
.headers({ 'X-Custom-Header': 'value' })
|
|
260
303
|
.send();
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
## 📝 Mailable Classes
|
|
307
|
+
|
|
308
|
+
Create reusable email classes with Laravel-like syntax:
|
|
309
|
+
|
|
310
|
+
```typescript
|
|
311
|
+
import { Mailable } from '@impruthvi/nodemail';
|
|
261
312
|
|
|
262
|
-
// Or use Mailable classes
|
|
263
313
|
class WelcomeEmail extends Mailable {
|
|
264
|
-
constructor(
|
|
314
|
+
constructor(
|
|
315
|
+
private user: { name: string; email: string },
|
|
316
|
+
private appName: string
|
|
317
|
+
) {
|
|
265
318
|
super();
|
|
266
319
|
}
|
|
267
320
|
|
|
268
321
|
build() {
|
|
269
322
|
return this
|
|
270
|
-
.subject(`Welcome
|
|
271
|
-
.view('
|
|
323
|
+
.subject(`Welcome to ${this.appName}!`)
|
|
324
|
+
.view('welcome', {
|
|
325
|
+
name: this.user.name,
|
|
326
|
+
email: this.user.email,
|
|
327
|
+
appName: this.appName,
|
|
328
|
+
});
|
|
272
329
|
}
|
|
273
330
|
}
|
|
274
331
|
|
|
275
|
-
|
|
332
|
+
// Method 1: Laravel-style (recommended)
|
|
333
|
+
await Mail.to('user@example.com').send(new WelcomeEmail(user, 'My App'));
|
|
334
|
+
|
|
335
|
+
// Method 2: Direct sending
|
|
336
|
+
await new WelcomeEmail(user, 'My App').to('user@example.com').send();
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
## 🧪 Testing with Mail::fake()
|
|
340
|
+
|
|
341
|
+
Test your emails without actually sending them - just like Laravel's `Mail::fake()`:
|
|
342
|
+
|
|
343
|
+
```typescript
|
|
344
|
+
import { Mail, Mailable } from '@impruthvi/nodemail';
|
|
345
|
+
|
|
346
|
+
// Your Mailable class
|
|
347
|
+
class WelcomeEmail extends Mailable {
|
|
348
|
+
constructor(public userName: string) {
|
|
349
|
+
super();
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
build() {
|
|
353
|
+
return this
|
|
354
|
+
.subject(`Welcome, ${this.userName}!`)
|
|
355
|
+
.html(`<h1>Hello ${this.userName}!</h1>`);
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
// In your tests
|
|
360
|
+
describe('User Registration', () => {
|
|
361
|
+
beforeEach(() => {
|
|
362
|
+
Mail.fake(); // Enable fake mode
|
|
363
|
+
});
|
|
364
|
+
|
|
365
|
+
afterEach(() => {
|
|
366
|
+
Mail.restore(); // Restore real mailer
|
|
367
|
+
});
|
|
368
|
+
|
|
369
|
+
it('sends welcome email on registration', async () => {
|
|
370
|
+
// Your application code that sends email
|
|
371
|
+
await Mail.to('user@example.com').send(new WelcomeEmail('John'));
|
|
372
|
+
|
|
373
|
+
// Assert email was sent
|
|
374
|
+
Mail.assertSent(WelcomeEmail);
|
|
375
|
+
|
|
376
|
+
// Assert with conditions
|
|
377
|
+
Mail.assertSent(WelcomeEmail, (mail) => {
|
|
378
|
+
return mail.hasTo('user@example.com') &&
|
|
379
|
+
mail.subjectContains('Welcome');
|
|
380
|
+
});
|
|
381
|
+
|
|
382
|
+
// Assert sent count
|
|
383
|
+
Mail.assertSentCount(WelcomeEmail, 1);
|
|
384
|
+
|
|
385
|
+
// Assert other mailables were NOT sent
|
|
386
|
+
Mail.assertNotSent(PasswordResetEmail);
|
|
387
|
+
});
|
|
388
|
+
|
|
389
|
+
it('does not send email when validation fails', async () => {
|
|
390
|
+
// Code that doesn't send email
|
|
391
|
+
Mail.assertNothingSent();
|
|
392
|
+
});
|
|
393
|
+
});
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
### Available Assertions
|
|
397
|
+
|
|
398
|
+
| Method | Description |
|
|
399
|
+
|--------|-------------|
|
|
400
|
+
| `Mail.fake()` | Enable fake mode (store emails instead of sending) |
|
|
401
|
+
| `Mail.restore()` | Restore real mailer |
|
|
402
|
+
| `Mail.assertSent(Mailable)` | Assert mailable was sent |
|
|
403
|
+
| `Mail.assertSent(Mailable, callback)` | Assert with custom conditions |
|
|
404
|
+
| `Mail.assertSentCount(Mailable, count)` | Assert sent exactly N times |
|
|
405
|
+
| `Mail.assertNotSent(Mailable)` | Assert mailable was NOT sent |
|
|
406
|
+
| `Mail.assertNothingSent()` | Assert no emails were sent |
|
|
407
|
+
| `Mail.assertQueued(Mailable)` | Assert mailable was queued |
|
|
408
|
+
| `Mail.assertNothingQueued()` | Assert nothing was queued |
|
|
409
|
+
| `Mail.sent()` | Get all sent messages |
|
|
410
|
+
| `Mail.sent(Mailable)` | Get sent messages of specific type |
|
|
411
|
+
|
|
412
|
+
### AssertableMessage Methods
|
|
413
|
+
|
|
414
|
+
When inspecting sent messages, you can use these helper methods:
|
|
415
|
+
|
|
416
|
+
```typescript
|
|
417
|
+
const sent = Mail.sent(WelcomeEmail)[0];
|
|
418
|
+
|
|
419
|
+
// Check recipients
|
|
420
|
+
sent.hasTo('user@example.com'); // Check TO
|
|
421
|
+
sent.hasCc('cc@example.com'); // Check CC
|
|
422
|
+
sent.hasBcc('bcc@example.com'); // Check BCC
|
|
423
|
+
|
|
424
|
+
// Check content
|
|
425
|
+
sent.hasSubject('Welcome!'); // Exact subject match
|
|
426
|
+
sent.subjectContains('Welcome'); // Subject contains
|
|
427
|
+
sent.htmlContains('Hello'); // HTML contains
|
|
428
|
+
sent.textContains('Hello'); // Plain text contains
|
|
429
|
+
|
|
430
|
+
// Check attachments
|
|
431
|
+
sent.hasAttachments(); // Has any attachments
|
|
432
|
+
sent.hasAttachment('file.pdf'); // Has specific attachment
|
|
433
|
+
|
|
434
|
+
// Check headers
|
|
435
|
+
sent.hasHeader('X-Custom'); // Has header
|
|
436
|
+
sent.hasHeader('X-Custom', 'value'); // Header with value
|
|
437
|
+
|
|
438
|
+
// Get values
|
|
439
|
+
sent.getTo(); // Get recipients array
|
|
440
|
+
sent.getSubject(); // Get subject
|
|
441
|
+
sent.getHtml(); // Get HTML content
|
|
276
442
|
```
|
|
277
443
|
|
|
278
444
|
## 🛠️ Current Status
|
|
@@ -290,20 +456,37 @@ await Mail.to('user@example.com').send(new WelcomeEmail(user));
|
|
|
290
456
|
- ✅ SMTP Provider (nodemailer)
|
|
291
457
|
- ✅ SendGrid Provider (@sendgrid/mail)
|
|
292
458
|
- ✅ AWS SES Provider (@aws-sdk/client-ses)
|
|
293
|
-
- ✅ Message builder with fluent API
|
|
459
|
+
- ✅ Message builder with complete fluent API
|
|
294
460
|
- ✅ Configuration system
|
|
295
461
|
- ✅ Error handling & graceful degradation
|
|
296
|
-
- 🚧 Other providers (Mailgun, Resend, Postmark) - coming soon
|
|
297
462
|
|
|
298
|
-
**Phase 3:
|
|
299
|
-
-
|
|
300
|
-
-
|
|
463
|
+
**Phase 3: Additional Providers** ✅ Complete
|
|
464
|
+
- ✅ Mailgun Provider (mailgun.js)
|
|
465
|
+
- ✅ Resend Provider (resend)
|
|
466
|
+
- ✅ Postmark Provider (postmark)
|
|
467
|
+
- ✅ Dynamic loading for all providers
|
|
468
|
+
- ✅ Comprehensive provider tests
|
|
469
|
+
|
|
470
|
+
**Phase 4: Template Engines & Mailable** ✅ Complete
|
|
471
|
+
- ✅ Template engines (Handlebars, EJS, Pug)
|
|
472
|
+
- ✅ Laravel-like Mailable classes with template support
|
|
473
|
+
- ✅ Complete fluent API (cc, bcc, replyTo, attachments, headers)
|
|
474
|
+
- ✅ Dynamic template loading with caching
|
|
475
|
+
|
|
476
|
+
**Phase 5: Testing Utilities** ✅ Complete (v0.5.0)
|
|
477
|
+
- ✅ Mail::fake() for testing
|
|
478
|
+
- ✅ assertSent(), assertNotSent(), assertNothingSent()
|
|
479
|
+
- ✅ assertQueued(), assertNothingQueued()
|
|
480
|
+
- ✅ AssertableMessage with inspection methods
|
|
481
|
+
- ✅ Comprehensive test suite (172 tests)
|
|
482
|
+
- ✅ 85%+ code coverage
|
|
483
|
+
|
|
484
|
+
**Phase 6: Advanced Features** 🚧 Coming Soon
|
|
301
485
|
- Queue integration (Bull/BullMQ)
|
|
302
|
-
- Template engines (Handlebars, EJS, Pug)
|
|
303
|
-
- Testing utilities (Mail::fake(), assertSent())
|
|
304
|
-
- Unit test coverage
|
|
305
486
|
- CLI tools
|
|
306
487
|
- Markdown mail support
|
|
488
|
+
- Multi-channel notifications
|
|
489
|
+
- i18n support
|
|
307
490
|
|
|
308
491
|
## 🤝 Contributing
|
|
309
492
|
|
|
@@ -366,7 +549,7 @@ Unlike other packages that bundle everything:
|
|
|
366
549
|
- **Type-Safe**: Full TypeScript support with strict typing
|
|
367
550
|
- **Developer-Friendly**: Clean, intuitive API
|
|
368
551
|
- **Production-Ready**: Built with best practices
|
|
369
|
-
- **Well-Tested**:
|
|
552
|
+
- **Well-Tested**: 172 passing tests with 85%+ coverage
|
|
370
553
|
|
|
371
554
|
## 📄 License
|
|
372
555
|
|
|
@@ -1,13 +1,51 @@
|
|
|
1
1
|
import { MailManager } from './MailManager';
|
|
2
|
-
import type { MailConfig } from '../types';
|
|
2
|
+
import type { MailConfig, MailOptions, MailResponse } from '../types';
|
|
3
|
+
import type { Mailable } from './Mailable';
|
|
4
|
+
import { MailFake } from '../testing/MailFake';
|
|
5
|
+
import type { AssertableMessage } from '../testing/AssertableMessage';
|
|
3
6
|
declare class MailFacade {
|
|
4
7
|
private static instance;
|
|
8
|
+
private static fakeInstance;
|
|
9
|
+
private static config;
|
|
5
10
|
static configure(config: MailConfig): void;
|
|
6
11
|
private static getInstance;
|
|
7
|
-
static
|
|
12
|
+
private static isFaking;
|
|
13
|
+
static to(address: string | string[]): FakeableMessageBuilder;
|
|
8
14
|
static mailer(name: string): MailManager;
|
|
9
|
-
static
|
|
10
|
-
static
|
|
15
|
+
static send(mailable: Mailable): Promise<MailResponse>;
|
|
16
|
+
static fake(): MailFake;
|
|
17
|
+
static restore(): void;
|
|
18
|
+
static getFake(): MailFake | null;
|
|
19
|
+
static assertSent<T extends Mailable>(mailableClass: new (...args: unknown[]) => T, callback?: (message: AssertableMessage) => boolean): void;
|
|
20
|
+
static assertSentCount<T extends Mailable>(mailableClass: new (...args: unknown[]) => T, count: number): void;
|
|
21
|
+
static assertNotSent<T extends Mailable>(mailableClass: new (...args: unknown[]) => T, callback?: (message: AssertableMessage) => boolean): void;
|
|
22
|
+
static assertNothingSent(): void;
|
|
23
|
+
static assertQueued<T extends Mailable>(mailableClass: new (...args: unknown[]) => T, callback?: (message: AssertableMessage) => boolean): void;
|
|
24
|
+
static assertQueuedCount<T extends Mailable>(mailableClass: new (...args: unknown[]) => T, count: number): void;
|
|
25
|
+
static assertNotQueued<T extends Mailable>(mailableClass: new (...args: unknown[]) => T, callback?: (message: AssertableMessage) => boolean): void;
|
|
26
|
+
static assertNothingQueued(): void;
|
|
27
|
+
static sent<T extends Mailable>(mailableClass?: new (...args: unknown[]) => T): AssertableMessage[];
|
|
28
|
+
static queued<T extends Mailable>(mailableClass?: new (...args: unknown[]) => T): AssertableMessage[];
|
|
29
|
+
static hasSent(): boolean;
|
|
30
|
+
static hasQueued(): boolean;
|
|
31
|
+
}
|
|
32
|
+
declare class FakeableMessageBuilder {
|
|
33
|
+
private manager;
|
|
34
|
+
options: Partial<MailOptions>;
|
|
35
|
+
constructor(manager: MailManager | MailFake, to: string | string[]);
|
|
36
|
+
subject(subject: string): this;
|
|
37
|
+
html(html: string): this;
|
|
38
|
+
text(text: string): this;
|
|
39
|
+
from(from: string): this;
|
|
40
|
+
cc(cc: string | string[]): this;
|
|
41
|
+
bcc(bcc: string | string[]): this;
|
|
42
|
+
replyTo(replyTo: string): this;
|
|
43
|
+
attachments(attachments: import('../types').Attachment[]): this;
|
|
44
|
+
headers(headers: Record<string, string>): this;
|
|
45
|
+
template(template: string): this;
|
|
46
|
+
data(data: Record<string, unknown>): this;
|
|
47
|
+
send(mailable?: Mailable): Promise<MailResponse>;
|
|
48
|
+
queue(mailable?: Mailable): Promise<MailResponse>;
|
|
11
49
|
}
|
|
12
50
|
export { MailFacade as Mail };
|
|
13
51
|
//# sourceMappingURL=MailFacade.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MailFacade.d.ts","sourceRoot":"","sources":["../../src/core/MailFacade.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"MailFacade.d.ts","sourceRoot":"","sources":["../../src/core/MailFacade.ts"],"names":[],"mappings":"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"}
|