@veloxts/mail 0.6.87 → 0.6.89
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/GUIDE.md +130 -23
- package/dist/manager.d.ts +3 -0
- package/dist/manager.js +3 -0
- package/package.json +5 -5
package/GUIDE.md
CHANGED
|
@@ -1,28 +1,50 @@
|
|
|
1
1
|
# @veloxts/mail Guide
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Email sending for VeloxTS applications with React Email templates, supporting SMTP and Resend.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## Installation
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
```bash
|
|
8
|
+
pnpm add @veloxts/mail
|
|
9
|
+
|
|
10
|
+
# For Resend (recommended for production)
|
|
11
|
+
pnpm add resend
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Quick Start
|
|
15
|
+
|
|
16
|
+
### Development (Log)
|
|
17
|
+
|
|
18
|
+
Logs emails to console instead of sending:
|
|
8
19
|
|
|
9
20
|
```typescript
|
|
21
|
+
import { veloxApp } from '@veloxts/core';
|
|
10
22
|
import { mailPlugin } from '@veloxts/mail';
|
|
11
23
|
|
|
12
|
-
app
|
|
13
|
-
```
|
|
24
|
+
const app = veloxApp();
|
|
14
25
|
|
|
15
|
-
|
|
26
|
+
app.register(mailPlugin({
|
|
27
|
+
driver: 'log',
|
|
28
|
+
from: { name: 'My App', email: 'noreply@myapp.com' },
|
|
29
|
+
}));
|
|
30
|
+
|
|
31
|
+
await app.start();
|
|
32
|
+
```
|
|
16
33
|
|
|
17
|
-
|
|
34
|
+
### Production (SMTP)
|
|
18
35
|
|
|
19
36
|
```typescript
|
|
20
|
-
|
|
37
|
+
import { veloxApp } from '@veloxts/core';
|
|
38
|
+
import { mailPlugin } from '@veloxts/mail';
|
|
39
|
+
|
|
40
|
+
const app = veloxApp();
|
|
41
|
+
|
|
42
|
+
app.register(mailPlugin({
|
|
21
43
|
driver: 'smtp',
|
|
22
44
|
config: {
|
|
23
|
-
host:
|
|
24
|
-
port: 587,
|
|
25
|
-
secure:
|
|
45
|
+
host: process.env.SMTP_HOST,
|
|
46
|
+
port: parseInt(process.env.SMTP_PORT || '587'),
|
|
47
|
+
secure: process.env.SMTP_SECURE === 'true',
|
|
26
48
|
auth: {
|
|
27
49
|
user: process.env.SMTP_USER,
|
|
28
50
|
pass: process.env.SMTP_PASS,
|
|
@@ -30,32 +52,50 @@ app.use(mailPlugin({
|
|
|
30
52
|
},
|
|
31
53
|
from: { name: 'My App', email: 'noreply@myapp.com' },
|
|
32
54
|
}));
|
|
55
|
+
|
|
56
|
+
await app.start();
|
|
33
57
|
```
|
|
34
58
|
|
|
35
|
-
### Resend
|
|
59
|
+
### Production (Resend)
|
|
36
60
|
|
|
37
|
-
|
|
61
|
+
```typescript
|
|
62
|
+
import { veloxApp } from '@veloxts/core';
|
|
63
|
+
import { mailPlugin } from '@veloxts/mail';
|
|
38
64
|
|
|
39
|
-
|
|
40
|
-
npm install resend
|
|
41
|
-
```
|
|
65
|
+
const app = veloxApp();
|
|
42
66
|
|
|
43
|
-
|
|
44
|
-
app.use(mailPlugin({
|
|
67
|
+
app.register(mailPlugin({
|
|
45
68
|
driver: 'resend',
|
|
46
69
|
config: {
|
|
47
70
|
apiKey: process.env.RESEND_API_KEY,
|
|
48
71
|
},
|
|
49
72
|
from: { name: 'My App', email: 'noreply@myapp.com' },
|
|
50
73
|
}));
|
|
74
|
+
|
|
75
|
+
await app.start();
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
**Environment Variables:**
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
# .env (SMTP)
|
|
82
|
+
SMTP_HOST=smtp.example.com
|
|
83
|
+
SMTP_PORT=587
|
|
84
|
+
SMTP_SECURE=false
|
|
85
|
+
SMTP_USER=your-username
|
|
86
|
+
SMTP_PASS=your-password
|
|
87
|
+
|
|
88
|
+
# .env (Resend)
|
|
89
|
+
RESEND_API_KEY=re_xxxxxxxxxxxx
|
|
51
90
|
```
|
|
52
91
|
|
|
53
92
|
## Defining Email Templates
|
|
54
93
|
|
|
55
94
|
Using React Email components:
|
|
56
95
|
|
|
57
|
-
```
|
|
96
|
+
```tsx
|
|
58
97
|
import { defineMail } from '@veloxts/mail';
|
|
98
|
+
import { z } from 'zod';
|
|
59
99
|
import { Html, Head, Body, Container, Text, Button } from '@react-email/components';
|
|
60
100
|
|
|
61
101
|
export const WelcomeEmail = defineMail({
|
|
@@ -104,6 +144,13 @@ await ctx.mail.send(InvoiceEmail, {
|
|
|
104
144
|
{ filename: 'invoice.pdf', content: pdfBuffer },
|
|
105
145
|
],
|
|
106
146
|
});
|
|
147
|
+
|
|
148
|
+
// Override subject
|
|
149
|
+
await ctx.mail.send(WelcomeEmail, {
|
|
150
|
+
to: 'user@example.com',
|
|
151
|
+
subject: 'Custom Subject',
|
|
152
|
+
data: { user, activationUrl },
|
|
153
|
+
});
|
|
107
154
|
```
|
|
108
155
|
|
|
109
156
|
## Bulk Sending
|
|
@@ -117,7 +164,7 @@ const results = await ctx.mail.sendBulk(WelcomeEmail, [
|
|
|
117
164
|
|
|
118
165
|
## Preview Emails
|
|
119
166
|
|
|
120
|
-
Render without sending (useful for testing):
|
|
167
|
+
Render without sending (useful for testing or previews):
|
|
121
168
|
|
|
122
169
|
```typescript
|
|
123
170
|
const { html, text, subject } = await ctx.mail.render(WelcomeEmail, {
|
|
@@ -125,8 +172,68 @@ const { html, text, subject } = await ctx.mail.render(WelcomeEmail, {
|
|
|
125
172
|
});
|
|
126
173
|
```
|
|
127
174
|
|
|
128
|
-
##
|
|
175
|
+
## Production Deployment
|
|
129
176
|
|
|
130
|
-
|
|
131
|
-
|
|
177
|
+
### Choosing a Provider
|
|
178
|
+
|
|
179
|
+
| Provider | Best For |
|
|
180
|
+
|----------|----------|
|
|
181
|
+
| [Resend](https://resend.com) | Simple API, React Email native, generous free tier |
|
|
182
|
+
| [AWS SES](https://aws.amazon.com/ses/) | High volume, cost-effective |
|
|
183
|
+
| [SendGrid](https://sendgrid.com) | Enterprise features |
|
|
184
|
+
| [Postmark](https://postmarkapp.com) | Transactional email focus |
|
|
185
|
+
|
|
186
|
+
### Production Checklist
|
|
187
|
+
|
|
188
|
+
1. **Verify sending domain** - SPF, DKIM, DMARC records
|
|
189
|
+
2. **Use environment variables** - Never hardcode credentials
|
|
190
|
+
3. **Set proper From address** - Use verified domain email
|
|
191
|
+
4. **Handle bounces** - Configure bounce/complaint webhooks
|
|
192
|
+
5. **Queue emails** - Use `@veloxts/queue` for background sending
|
|
193
|
+
|
|
194
|
+
### Sending Emails in Background
|
|
195
|
+
|
|
196
|
+
For better performance, queue emails instead of sending synchronously:
|
|
197
|
+
|
|
198
|
+
```typescript
|
|
199
|
+
// Define a job for sending emails
|
|
200
|
+
const sendEmailJob = defineJob({
|
|
201
|
+
name: 'email.send',
|
|
202
|
+
schema: z.object({
|
|
203
|
+
template: z.string(),
|
|
204
|
+
to: z.string().email(),
|
|
205
|
+
data: z.record(z.unknown()),
|
|
206
|
+
}),
|
|
207
|
+
handler: async ({ data, ctx }) => {
|
|
208
|
+
const template = emailTemplates[data.template];
|
|
209
|
+
await ctx.mail.send(template, { to: data.to, data: data.data });
|
|
210
|
+
},
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
// Dispatch instead of sending directly
|
|
214
|
+
await ctx.queue.dispatch(sendEmailJob, {
|
|
215
|
+
template: 'welcome',
|
|
216
|
+
to: 'user@example.com',
|
|
217
|
+
data: { user, activationUrl },
|
|
218
|
+
});
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
## Standalone Usage
|
|
222
|
+
|
|
223
|
+
Use mail outside of Fastify request context (CLI commands, background jobs):
|
|
224
|
+
|
|
225
|
+
```typescript
|
|
226
|
+
import { getMail, closeMail } from '@veloxts/mail';
|
|
227
|
+
|
|
228
|
+
// Get standalone mail instance
|
|
229
|
+
const mail = await getMail({
|
|
230
|
+
driver: 'resend',
|
|
231
|
+
config: { apiKey: process.env.RESEND_API_KEY },
|
|
232
|
+
from: { email: 'noreply@example.com' },
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
await mail.send(WelcomeEmail, { to: 'user@example.com', data: {...} });
|
|
236
|
+
|
|
237
|
+
// Clean up when done
|
|
238
|
+
await closeMail();
|
|
132
239
|
```
|
package/dist/manager.d.ts
CHANGED
|
@@ -78,5 +78,8 @@ export interface MailManager {
|
|
|
78
78
|
export declare function createMailManager(options?: MailPluginOptions): Promise<MailManager>;
|
|
79
79
|
/**
|
|
80
80
|
* Alias for createMailManager.
|
|
81
|
+
*
|
|
82
|
+
* Note: `mail` is already used as an alias for `defineMail` (for defining templates),
|
|
83
|
+
* following the same pattern as queue (`job` = `defineJob`, `queue` = `createQueueManager`).
|
|
81
84
|
*/
|
|
82
85
|
export declare const mailer: typeof createMailManager;
|
package/dist/manager.js
CHANGED
|
@@ -149,5 +149,8 @@ export async function createMailManager(options = {}) {
|
|
|
149
149
|
}
|
|
150
150
|
/**
|
|
151
151
|
* Alias for createMailManager.
|
|
152
|
+
*
|
|
153
|
+
* Note: `mail` is already used as an alias for `defineMail` (for defining templates),
|
|
154
|
+
* following the same pattern as queue (`job` = `defineJob`, `queue` = `createQueueManager`).
|
|
152
155
|
*/
|
|
153
156
|
export const mailer = createMailManager;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@veloxts/mail",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.89",
|
|
4
4
|
"description": "Email templating and sending for VeloxTS framework",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -28,19 +28,19 @@
|
|
|
28
28
|
"nodemailer": "7.0.13",
|
|
29
29
|
"resend": "4.1.2",
|
|
30
30
|
"zod": "3.24.4",
|
|
31
|
-
"@veloxts/core": "0.6.
|
|
31
|
+
"@veloxts/core": "0.6.89"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
34
|
"@biomejs/biome": "2.0.0",
|
|
35
|
-
"@types/node": "
|
|
35
|
+
"@types/node": "25.0.3",
|
|
36
36
|
"@types/nodemailer": "7.0.9",
|
|
37
37
|
"@types/react": "19.2.7",
|
|
38
38
|
"@vitest/coverage-v8": "4.0.16",
|
|
39
39
|
"fastify": "5.6.2",
|
|
40
40
|
"react": "19.2.3",
|
|
41
|
-
"typescript": "5.
|
|
41
|
+
"typescript": "5.9.3",
|
|
42
42
|
"vitest": "4.0.16",
|
|
43
|
-
"@veloxts/testing": "0.6.
|
|
43
|
+
"@veloxts/testing": "0.6.89"
|
|
44
44
|
},
|
|
45
45
|
"peerDependencies": {
|
|
46
46
|
"fastify": "^5.0.0",
|