@nuntly/better-email 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/dist/index.cjs +549 -0
- package/dist/index.d.cts +686 -0
- package/dist/index.d.mts +686 -0
- package/dist/index.d.ts +686 -0
- package/dist/index.mjs +528 -0
- package/package.json +58 -0
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,686 @@
|
|
|
1
|
+
import { User } from 'better-auth';
|
|
2
|
+
|
|
3
|
+
type EmailType = 'verification-email' | 'reset-password' | 'change-email-verification' | 'delete-account-verification' | 'magic-link' | 'verification-otp' | 'organization-invitation' | 'two-factor-otp';
|
|
4
|
+
interface EmailTag {
|
|
5
|
+
name: string;
|
|
6
|
+
value: string;
|
|
7
|
+
}
|
|
8
|
+
interface EmailMessage {
|
|
9
|
+
to: string;
|
|
10
|
+
subject: string;
|
|
11
|
+
html: string;
|
|
12
|
+
text: string;
|
|
13
|
+
tags?: EmailTag[];
|
|
14
|
+
}
|
|
15
|
+
interface EmailSendResponse {
|
|
16
|
+
messageId?: string;
|
|
17
|
+
}
|
|
18
|
+
interface EmailProvider {
|
|
19
|
+
send(message: EmailMessage): Promise<EmailSendResponse | void>;
|
|
20
|
+
}
|
|
21
|
+
interface VerificationEmailContext {
|
|
22
|
+
type: 'verification-email';
|
|
23
|
+
user: User;
|
|
24
|
+
url: string;
|
|
25
|
+
token: string;
|
|
26
|
+
}
|
|
27
|
+
interface ResetPasswordContext {
|
|
28
|
+
type: 'reset-password';
|
|
29
|
+
user: User;
|
|
30
|
+
url: string;
|
|
31
|
+
token: string;
|
|
32
|
+
}
|
|
33
|
+
interface ChangeEmailVerificationContext {
|
|
34
|
+
type: 'change-email-verification';
|
|
35
|
+
user: User;
|
|
36
|
+
newEmail: string;
|
|
37
|
+
url: string;
|
|
38
|
+
token: string;
|
|
39
|
+
}
|
|
40
|
+
interface DeleteAccountVerificationContext {
|
|
41
|
+
type: 'delete-account-verification';
|
|
42
|
+
user: User;
|
|
43
|
+
url: string;
|
|
44
|
+
token: string;
|
|
45
|
+
}
|
|
46
|
+
interface MagicLinkContext {
|
|
47
|
+
type: 'magic-link';
|
|
48
|
+
email: string;
|
|
49
|
+
url: string;
|
|
50
|
+
token: string;
|
|
51
|
+
}
|
|
52
|
+
interface VerificationOTPContext {
|
|
53
|
+
type: 'verification-otp';
|
|
54
|
+
email: string;
|
|
55
|
+
otp: string;
|
|
56
|
+
otpType: 'sign-in' | 'email-verification' | 'forget-password';
|
|
57
|
+
}
|
|
58
|
+
interface OrganizationInvitationContext {
|
|
59
|
+
type: 'organization-invitation';
|
|
60
|
+
id: string;
|
|
61
|
+
role: string;
|
|
62
|
+
email: string;
|
|
63
|
+
organization: {
|
|
64
|
+
id: string;
|
|
65
|
+
name: string;
|
|
66
|
+
slug?: string;
|
|
67
|
+
logo?: string | null;
|
|
68
|
+
metadata?: string | null;
|
|
69
|
+
createdAt: Date;
|
|
70
|
+
};
|
|
71
|
+
invitation: {
|
|
72
|
+
id: string;
|
|
73
|
+
email: string;
|
|
74
|
+
status: string;
|
|
75
|
+
organizationId: string;
|
|
76
|
+
role: string;
|
|
77
|
+
inviterId: string;
|
|
78
|
+
expiresAt: Date;
|
|
79
|
+
};
|
|
80
|
+
inviter: {
|
|
81
|
+
id: string;
|
|
82
|
+
organizationId: string;
|
|
83
|
+
userId: string;
|
|
84
|
+
role: string;
|
|
85
|
+
createdAt: Date;
|
|
86
|
+
user: User;
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
interface TwoFactorOTPContext {
|
|
90
|
+
type: 'two-factor-otp';
|
|
91
|
+
user: User & {
|
|
92
|
+
twoFactorEnabled?: boolean;
|
|
93
|
+
};
|
|
94
|
+
otp: string;
|
|
95
|
+
}
|
|
96
|
+
type EmailContext = VerificationEmailContext | ResetPasswordContext | ChangeEmailVerificationContext | DeleteAccountVerificationContext | MagicLinkContext | VerificationOTPContext | OrganizationInvitationContext | TwoFactorOTPContext;
|
|
97
|
+
/** Extracts the context interface for a given email type from the `EmailContext` union. */
|
|
98
|
+
type EmailContextFor<T extends EmailType> = Extract<EmailContext, {
|
|
99
|
+
type: T;
|
|
100
|
+
}>;
|
|
101
|
+
/** Context fields for a given email type, without the `type` discriminator. Useful for typing callback data and template props. */
|
|
102
|
+
type EmailProps<T extends EmailType> = Omit<EmailContextFor<T>, 'type'>;
|
|
103
|
+
interface RenderedEmail {
|
|
104
|
+
subject: string;
|
|
105
|
+
html: string;
|
|
106
|
+
text: string;
|
|
107
|
+
}
|
|
108
|
+
interface EmailTemplateRenderer {
|
|
109
|
+
render(context: EmailContext): Promise<RenderedEmail>;
|
|
110
|
+
}
|
|
111
|
+
type SendEmailResult = {
|
|
112
|
+
success: true;
|
|
113
|
+
skipped?: false;
|
|
114
|
+
messageId?: string;
|
|
115
|
+
} | {
|
|
116
|
+
success: true;
|
|
117
|
+
skipped: true;
|
|
118
|
+
} | {
|
|
119
|
+
success: false;
|
|
120
|
+
error: Error;
|
|
121
|
+
};
|
|
122
|
+
interface BetterEmailOptions {
|
|
123
|
+
provider: EmailProvider;
|
|
124
|
+
templateRenderer: EmailTemplateRenderer;
|
|
125
|
+
defaultTags?: EmailTag[];
|
|
126
|
+
tags?: Partial<Record<EmailType, EmailTag[]>>;
|
|
127
|
+
onBeforeSend?: (context: EmailContext, message: EmailMessage) => Promise<boolean | void>;
|
|
128
|
+
onAfterSend?: (context: EmailContext, message: EmailMessage) => Promise<void>;
|
|
129
|
+
onSendError?: (context: EmailContext, message: EmailMessage, error: Error) => Promise<void>;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
declare function sendEmail(options: BetterEmailOptions, context: EmailContext): Promise<SendEmailResult>;
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Logs emails to the console instead of sending them.
|
|
136
|
+
* Useful for development and testing.
|
|
137
|
+
*
|
|
138
|
+
* ```ts
|
|
139
|
+
* const provider = new ConsoleProvider();
|
|
140
|
+
* ```
|
|
141
|
+
*/
|
|
142
|
+
declare class ConsoleProvider implements EmailProvider {
|
|
143
|
+
send(message: EmailMessage): Promise<void>;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
interface MailgunProviderOptions {
|
|
147
|
+
/** Mailgun API key. */
|
|
148
|
+
apiKey: string;
|
|
149
|
+
/** Mailgun sending domain (e.g. `"mg.example.com"`). */
|
|
150
|
+
domain: string;
|
|
151
|
+
/** Default sender address (e.g. `"Acme <noreply@acme.com>"`). */
|
|
152
|
+
from: string;
|
|
153
|
+
/** Override the Mailgun API base URL. Defaults to `https://api.mailgun.net`. Use `https://api.eu.mailgun.net` for EU region. */
|
|
154
|
+
baseUrl?: string;
|
|
155
|
+
/** Request timeout in milliseconds. Defaults to `30_000` (30 s). */
|
|
156
|
+
timeout?: number;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Sends emails via the Mailgun REST API.
|
|
160
|
+
*
|
|
161
|
+
* ```ts
|
|
162
|
+
* const provider = new MailgunProvider({
|
|
163
|
+
* apiKey: process.env.MAILGUN_API_KEY!,
|
|
164
|
+
* domain: 'mg.example.com',
|
|
165
|
+
* from: 'Acme <noreply@acme.com>',
|
|
166
|
+
* });
|
|
167
|
+
* ```
|
|
168
|
+
*/
|
|
169
|
+
declare class MailgunProvider implements EmailProvider {
|
|
170
|
+
private apiKey;
|
|
171
|
+
private domain;
|
|
172
|
+
private from;
|
|
173
|
+
private baseUrl;
|
|
174
|
+
private timeout;
|
|
175
|
+
constructor(options: MailgunProviderOptions);
|
|
176
|
+
send(message: EmailMessage): Promise<{
|
|
177
|
+
messageId?: string;
|
|
178
|
+
}>;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
interface NuntlyProviderOptions {
|
|
182
|
+
/** Nuntly API key. */
|
|
183
|
+
apiKey: string;
|
|
184
|
+
/** Default sender address (e.g. `"Acme <noreply@acme.com>"`). */
|
|
185
|
+
from: string;
|
|
186
|
+
/** Override the Nuntly API base URL. Defaults to `https://api.nuntly.com`. */
|
|
187
|
+
baseUrl?: string;
|
|
188
|
+
/** Request timeout in milliseconds. Defaults to `30_000` (30 s). */
|
|
189
|
+
timeout?: number;
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Sends emails via the Nuntly REST API.
|
|
193
|
+
*
|
|
194
|
+
* ```ts
|
|
195
|
+
* const provider = new NuntlyProvider({
|
|
196
|
+
* apiKey: process.env.NUNTLY_API_KEY!,
|
|
197
|
+
* from: 'Acme <noreply@acme.com>',
|
|
198
|
+
* });
|
|
199
|
+
* ```
|
|
200
|
+
*/
|
|
201
|
+
declare class NuntlyProvider implements EmailProvider {
|
|
202
|
+
private apiKey;
|
|
203
|
+
private from;
|
|
204
|
+
private baseUrl;
|
|
205
|
+
private timeout;
|
|
206
|
+
constructor(options: NuntlyProviderOptions);
|
|
207
|
+
send(message: EmailMessage): Promise<{
|
|
208
|
+
messageId?: string;
|
|
209
|
+
}>;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
interface PostmarkProviderOptions {
|
|
213
|
+
/** Postmark server API token. */
|
|
214
|
+
serverToken: string;
|
|
215
|
+
/** Default sender address (e.g. `"Acme <noreply@acme.com>"`). */
|
|
216
|
+
from: string;
|
|
217
|
+
/** Postmark message stream ID (e.g. `"outbound"` or a custom transactional stream). */
|
|
218
|
+
messageStream?: string;
|
|
219
|
+
/** Override the Postmark API base URL. Defaults to `https://api.postmarkapp.com`. */
|
|
220
|
+
baseUrl?: string;
|
|
221
|
+
/** Request timeout in milliseconds. Defaults to `30_000` (30 s). */
|
|
222
|
+
timeout?: number;
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Sends emails via the Postmark REST API.
|
|
226
|
+
*
|
|
227
|
+
* ```ts
|
|
228
|
+
* const provider = new PostmarkProvider({
|
|
229
|
+
* serverToken: process.env.POSTMARK_SERVER_TOKEN!,
|
|
230
|
+
* from: 'Acme <noreply@acme.com>',
|
|
231
|
+
* });
|
|
232
|
+
* ```
|
|
233
|
+
*/
|
|
234
|
+
declare class PostmarkProvider implements EmailProvider {
|
|
235
|
+
private serverToken;
|
|
236
|
+
private from;
|
|
237
|
+
private messageStream;
|
|
238
|
+
private baseUrl;
|
|
239
|
+
private timeout;
|
|
240
|
+
constructor(options: PostmarkProviderOptions);
|
|
241
|
+
send(message: EmailMessage): Promise<{
|
|
242
|
+
messageId?: string;
|
|
243
|
+
}>;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
interface ResendProviderOptions {
|
|
247
|
+
/** Resend API key. */
|
|
248
|
+
apiKey: string;
|
|
249
|
+
/** Default sender address (e.g. `"Acme <noreply@acme.com>"`). */
|
|
250
|
+
from: string;
|
|
251
|
+
/** Override the Resend API base URL. Defaults to `https://api.resend.com`. */
|
|
252
|
+
baseUrl?: string;
|
|
253
|
+
/** Request timeout in milliseconds. Defaults to `30_000` (30 s). */
|
|
254
|
+
timeout?: number;
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Sends emails via the Resend REST API.
|
|
258
|
+
*
|
|
259
|
+
* ```ts
|
|
260
|
+
* const provider = new ResendProvider({
|
|
261
|
+
* apiKey: process.env.RESEND_API_KEY!,
|
|
262
|
+
* from: 'Acme <noreply@acme.com>',
|
|
263
|
+
* });
|
|
264
|
+
* ```
|
|
265
|
+
*/
|
|
266
|
+
declare class ResendProvider implements EmailProvider {
|
|
267
|
+
private apiKey;
|
|
268
|
+
private from;
|
|
269
|
+
private baseUrl;
|
|
270
|
+
private timeout;
|
|
271
|
+
constructor(options: ResendProviderOptions);
|
|
272
|
+
send(message: EmailMessage): Promise<{
|
|
273
|
+
messageId?: string;
|
|
274
|
+
}>;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
interface SESProviderOptions {
|
|
278
|
+
/**
|
|
279
|
+
* An `SESv2Client` instance from `@aws-sdk/client-sesv2`.
|
|
280
|
+
*
|
|
281
|
+
* ```ts
|
|
282
|
+
* import { SESv2Client } from '@aws-sdk/client-sesv2';
|
|
283
|
+
* const client = new SESv2Client({ region: 'us-east-1' });
|
|
284
|
+
* ```
|
|
285
|
+
*/
|
|
286
|
+
client: {
|
|
287
|
+
send(command: unknown): Promise<unknown>;
|
|
288
|
+
};
|
|
289
|
+
/**
|
|
290
|
+
* The `SendEmailCommand` class from `@aws-sdk/client-sesv2`.
|
|
291
|
+
*
|
|
292
|
+
* ```ts
|
|
293
|
+
* import { SendEmailCommand } from '@aws-sdk/client-sesv2';
|
|
294
|
+
* ```
|
|
295
|
+
*/
|
|
296
|
+
SendEmailCommand: new (input: unknown) => unknown;
|
|
297
|
+
/** Default sender address (e.g. `"Acme <noreply@acme.com>"`). */
|
|
298
|
+
from: string;
|
|
299
|
+
/** SES configuration set name for tracking. */
|
|
300
|
+
configurationSetName?: string;
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* Sends emails via AWS SES v2.
|
|
304
|
+
*
|
|
305
|
+
* Accepts an `SESv2Client` instance and the `SendEmailCommand` class.
|
|
306
|
+
* The provider handles building the full SES payload internally.
|
|
307
|
+
*
|
|
308
|
+
* ```ts
|
|
309
|
+
* import { SESv2Client, SendEmailCommand } from '@aws-sdk/client-sesv2';
|
|
310
|
+
*
|
|
311
|
+
* const provider = new SESProvider({
|
|
312
|
+
* client: new SESv2Client({ region: 'us-east-1' }),
|
|
313
|
+
* SendEmailCommand,
|
|
314
|
+
* from: 'Acme <noreply@acme.com>',
|
|
315
|
+
* });
|
|
316
|
+
* ```
|
|
317
|
+
*/
|
|
318
|
+
declare class SESProvider implements EmailProvider {
|
|
319
|
+
private client;
|
|
320
|
+
private SendEmailCommand;
|
|
321
|
+
private from;
|
|
322
|
+
private configurationSetName;
|
|
323
|
+
constructor(options: SESProviderOptions);
|
|
324
|
+
send(message: EmailMessage): Promise<{
|
|
325
|
+
messageId?: string;
|
|
326
|
+
}>;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
interface SMTPProviderOptions {
|
|
330
|
+
/**
|
|
331
|
+
* A nodemailer transporter instance.
|
|
332
|
+
*
|
|
333
|
+
* ```ts
|
|
334
|
+
* import nodemailer from 'nodemailer';
|
|
335
|
+
*
|
|
336
|
+
* const transporter = nodemailer.createTransport({
|
|
337
|
+
* host: 'smtp.example.com',
|
|
338
|
+
* port: 587,
|
|
339
|
+
* auth: { user: 'user', pass: 'pass' },
|
|
340
|
+
* });
|
|
341
|
+
* ```
|
|
342
|
+
*/
|
|
343
|
+
transporter: {
|
|
344
|
+
sendMail(options: Record<string, unknown>): Promise<unknown>;
|
|
345
|
+
};
|
|
346
|
+
/** Default sender address (e.g. `"Acme <noreply@acme.com>"`). */
|
|
347
|
+
from: string;
|
|
348
|
+
}
|
|
349
|
+
/**
|
|
350
|
+
* Sends emails via SMTP using a nodemailer transporter.
|
|
351
|
+
*
|
|
352
|
+
* Accepts a pre-configured transporter instance.
|
|
353
|
+
* The provider handles message formatting internally.
|
|
354
|
+
*
|
|
355
|
+
* ```ts
|
|
356
|
+
* import nodemailer from 'nodemailer';
|
|
357
|
+
*
|
|
358
|
+
* const provider = new SMTPProvider({
|
|
359
|
+
* transporter: nodemailer.createTransport({
|
|
360
|
+
* host: 'smtp.example.com',
|
|
361
|
+
* port: 587,
|
|
362
|
+
* auth: { user: 'user', pass: 'pass' },
|
|
363
|
+
* }),
|
|
364
|
+
* from: 'Acme <noreply@acme.com>',
|
|
365
|
+
* });
|
|
366
|
+
* ```
|
|
367
|
+
*/
|
|
368
|
+
declare class SMTPProvider implements EmailProvider {
|
|
369
|
+
private transporter;
|
|
370
|
+
private from;
|
|
371
|
+
constructor(options: SMTPProviderOptions);
|
|
372
|
+
send(message: EmailMessage): Promise<{
|
|
373
|
+
messageId?: string;
|
|
374
|
+
}>;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
declare class DefaultTemplateRenderer implements EmailTemplateRenderer {
|
|
378
|
+
render(context: EmailContext): Promise<RenderedEmail>;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
interface MJMLRenderedTemplate {
|
|
382
|
+
subject: string;
|
|
383
|
+
mjml: string;
|
|
384
|
+
text: string;
|
|
385
|
+
}
|
|
386
|
+
interface MJMLRendererOptions {
|
|
387
|
+
/**
|
|
388
|
+
* The `mjml` compile function.
|
|
389
|
+
*
|
|
390
|
+
* ```ts
|
|
391
|
+
* import mjml2html from 'mjml';
|
|
392
|
+
*
|
|
393
|
+
* const renderer = new MJMLRenderer({
|
|
394
|
+
* compile: (mjmlString) => mjml2html(mjmlString).html,
|
|
395
|
+
* templates: { ... },
|
|
396
|
+
* });
|
|
397
|
+
* ```
|
|
398
|
+
*/
|
|
399
|
+
compile: (mjml: string) => string;
|
|
400
|
+
/**
|
|
401
|
+
* Map of email type to a function returning `{ subject, mjml, text }`.
|
|
402
|
+
* Each function receives the typed context for its email type.
|
|
403
|
+
*
|
|
404
|
+
* TypeScript enforces that a `'magic-link'` template receives `MagicLinkContext`,
|
|
405
|
+
* a `'verification-email'` template receives `VerificationEmailContext`, etc.
|
|
406
|
+
*
|
|
407
|
+
* ```ts
|
|
408
|
+
* templates: {
|
|
409
|
+
* 'verification-email': (ctx) => ({
|
|
410
|
+
* subject: 'Verify your email',
|
|
411
|
+
* mjml: `
|
|
412
|
+
* <mjml>
|
|
413
|
+
* <mj-body>
|
|
414
|
+
* <mj-section>
|
|
415
|
+
* <mj-column>
|
|
416
|
+
* <mj-text>Click <a href="${ctx.url}">here</a> to verify.</mj-text>
|
|
417
|
+
* </mj-column>
|
|
418
|
+
* </mj-section>
|
|
419
|
+
* </mj-body>
|
|
420
|
+
* </mjml>
|
|
421
|
+
* `,
|
|
422
|
+
* text: `Verify your email: ${ctx.url}`,
|
|
423
|
+
* }),
|
|
424
|
+
* }
|
|
425
|
+
* ```
|
|
426
|
+
*/
|
|
427
|
+
templates: {
|
|
428
|
+
[K in EmailType]?: (context: EmailContextFor<K>) => MJMLRenderedTemplate;
|
|
429
|
+
};
|
|
430
|
+
/**
|
|
431
|
+
* Optional fallback renderer for email types without a template.
|
|
432
|
+
*/
|
|
433
|
+
fallback?: EmailTemplateRenderer;
|
|
434
|
+
}
|
|
435
|
+
declare class MJMLRenderer implements EmailTemplateRenderer {
|
|
436
|
+
private options;
|
|
437
|
+
constructor(options: MJMLRendererOptions);
|
|
438
|
+
render(context: EmailContext): Promise<RenderedEmail>;
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
interface MustacheRenderedTemplate {
|
|
442
|
+
subject: string;
|
|
443
|
+
template: string;
|
|
444
|
+
text: string;
|
|
445
|
+
}
|
|
446
|
+
interface MustacheRendererOptions {
|
|
447
|
+
/**
|
|
448
|
+
* The mustache render function.
|
|
449
|
+
*
|
|
450
|
+
* ```ts
|
|
451
|
+
* import Mustache from 'mustache';
|
|
452
|
+
*
|
|
453
|
+
* const renderer = new MustacheRenderer({
|
|
454
|
+
* render: (template, data) => Mustache.render(template, data),
|
|
455
|
+
* templates: { ... },
|
|
456
|
+
* });
|
|
457
|
+
* ```
|
|
458
|
+
*/
|
|
459
|
+
render: (template: string, data: Record<string, unknown>) => string;
|
|
460
|
+
/**
|
|
461
|
+
* Map of email type to a function returning `{ subject, template, text }`.
|
|
462
|
+
* Each function receives the typed context for its email type.
|
|
463
|
+
*
|
|
464
|
+
* TypeScript enforces that a `'magic-link'` template receives `MagicLinkContext`,
|
|
465
|
+
* a `'verification-email'` template receives `VerificationEmailContext`, etc.
|
|
466
|
+
*
|
|
467
|
+
* ```ts
|
|
468
|
+
* templates: {
|
|
469
|
+
* 'verification-email': (ctx) => ({
|
|
470
|
+
* subject: 'Verify your email',
|
|
471
|
+
* template: `
|
|
472
|
+
* <html>
|
|
473
|
+
* <body>
|
|
474
|
+
* <p>Click <a href="{{url}}">here</a> to verify.</p>
|
|
475
|
+
* </body>
|
|
476
|
+
* </html>
|
|
477
|
+
* `,
|
|
478
|
+
* text: `Verify your email: ${ctx.url}`,
|
|
479
|
+
* }),
|
|
480
|
+
* }
|
|
481
|
+
* ```
|
|
482
|
+
*/
|
|
483
|
+
templates: {
|
|
484
|
+
[K in EmailType]?: (context: EmailContextFor<K>) => MustacheRenderedTemplate;
|
|
485
|
+
};
|
|
486
|
+
/**
|
|
487
|
+
* Optional fallback renderer for email types without a template.
|
|
488
|
+
*/
|
|
489
|
+
fallback?: EmailTemplateRenderer;
|
|
490
|
+
}
|
|
491
|
+
declare class MustacheRenderer implements EmailTemplateRenderer {
|
|
492
|
+
private options;
|
|
493
|
+
constructor(options: MustacheRendererOptions);
|
|
494
|
+
render(context: EmailContext): Promise<RenderedEmail>;
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
interface ReactEmailRendererOptions {
|
|
498
|
+
/**
|
|
499
|
+
* The `render` function from `@react-email/render`.
|
|
500
|
+
*
|
|
501
|
+
* ```ts
|
|
502
|
+
* import { render } from '@react-email/render';
|
|
503
|
+
* ```
|
|
504
|
+
*/
|
|
505
|
+
render: (element: any, options?: {
|
|
506
|
+
plainText?: boolean;
|
|
507
|
+
}) => Promise<string>;
|
|
508
|
+
/**
|
|
509
|
+
* `React.createElement` from `react`.
|
|
510
|
+
*
|
|
511
|
+
* ```ts
|
|
512
|
+
* import { createElement } from 'react';
|
|
513
|
+
* ```
|
|
514
|
+
*/
|
|
515
|
+
createElement: (component: any, props: any) => any;
|
|
516
|
+
/**
|
|
517
|
+
* Map of email type to React Email component.
|
|
518
|
+
* Each component receives the typed context for its email type as props.
|
|
519
|
+
*
|
|
520
|
+
* TypeScript enforces that a `'magic-link'` template accepts `MagicLinkContext` props,
|
|
521
|
+
* a `'verification-email'` template accepts `VerificationEmailContext` props, etc.
|
|
522
|
+
*
|
|
523
|
+
* ```ts
|
|
524
|
+
* templates: {
|
|
525
|
+
* 'verification-email': VerificationEmail,
|
|
526
|
+
* 'reset-password': ResetPasswordEmail,
|
|
527
|
+
* }
|
|
528
|
+
* ```
|
|
529
|
+
*/
|
|
530
|
+
templates: {
|
|
531
|
+
[K in EmailType]?: (props: EmailContextFor<K>) => any;
|
|
532
|
+
};
|
|
533
|
+
/**
|
|
534
|
+
* Map of email type to subject line (string or function).
|
|
535
|
+
* When using a function, the context is narrowed to the specific email type.
|
|
536
|
+
*
|
|
537
|
+
* ```ts
|
|
538
|
+
* subjects: {
|
|
539
|
+
* 'verification-email': 'Verify your email',
|
|
540
|
+
* 'reset-password': (ctx) => `Reset password for ${ctx.user.name}`,
|
|
541
|
+
* }
|
|
542
|
+
* ```
|
|
543
|
+
*/
|
|
544
|
+
subjects: {
|
|
545
|
+
[K in EmailType]?: string | ((context: EmailContextFor<K>) => string);
|
|
546
|
+
};
|
|
547
|
+
/**
|
|
548
|
+
* Optional: Custom plain text renderer. If not provided, uses `render(element, { plainText: true })`.
|
|
549
|
+
*
|
|
550
|
+
* You can use `renderToPlainText` from `@react-email/render` for more control:
|
|
551
|
+
*
|
|
552
|
+
* ```ts
|
|
553
|
+
* import { render, renderToPlainText } from '@react-email/render';
|
|
554
|
+
*
|
|
555
|
+
* const renderer = new ReactEmailRenderer({
|
|
556
|
+
* render,
|
|
557
|
+
* renderPlainText: renderToPlainText,
|
|
558
|
+
* // ...
|
|
559
|
+
* });
|
|
560
|
+
* ```
|
|
561
|
+
*/
|
|
562
|
+
renderPlainText?: (element: any) => Promise<string> | string;
|
|
563
|
+
/**
|
|
564
|
+
* Optional fallback renderer for email types without a template.
|
|
565
|
+
*/
|
|
566
|
+
fallback?: EmailTemplateRenderer;
|
|
567
|
+
}
|
|
568
|
+
declare class ReactEmailRenderer implements EmailTemplateRenderer {
|
|
569
|
+
private options;
|
|
570
|
+
constructor(options: ReactEmailRendererOptions);
|
|
571
|
+
render(context: EmailContext): Promise<RenderedEmail>;
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
interface ReactMJMLRendererOptions {
|
|
575
|
+
/**
|
|
576
|
+
* The `render` function from `@faire/mjml-react`.
|
|
577
|
+
*
|
|
578
|
+
* ```ts
|
|
579
|
+
* import { render } from '@faire/mjml-react';
|
|
580
|
+
*
|
|
581
|
+
* const renderer = new ReactMJMLRenderer({
|
|
582
|
+
* render: (element) => render(element),
|
|
583
|
+
* createElement,
|
|
584
|
+
* templates: { ... },
|
|
585
|
+
* subjects: { ... },
|
|
586
|
+
* });
|
|
587
|
+
* ```
|
|
588
|
+
*/
|
|
589
|
+
render: (element: any) => {
|
|
590
|
+
html: string;
|
|
591
|
+
errors: any[];
|
|
592
|
+
};
|
|
593
|
+
/**
|
|
594
|
+
* `React.createElement` from `react`.
|
|
595
|
+
*
|
|
596
|
+
* ```ts
|
|
597
|
+
* import { createElement } from 'react';
|
|
598
|
+
* ```
|
|
599
|
+
*/
|
|
600
|
+
createElement: (component: any, props: any) => any;
|
|
601
|
+
/**
|
|
602
|
+
* Map of email type to React component using `@faire/mjml-react` components.
|
|
603
|
+
* Each component receives the typed context for its email type as props.
|
|
604
|
+
*
|
|
605
|
+
* TypeScript enforces that a `'magic-link'` template accepts `MagicLinkContext` props,
|
|
606
|
+
* a `'verification-email'` template accepts `VerificationEmailContext` props, etc.
|
|
607
|
+
*
|
|
608
|
+
* ```ts
|
|
609
|
+
* import { Mjml, MjmlBody, MjmlSection, MjmlColumn, MjmlText } from '@faire/mjml-react';
|
|
610
|
+
*
|
|
611
|
+
* function VerificationEmail({ url }: { url: string }) {
|
|
612
|
+
* return (
|
|
613
|
+
* <Mjml>
|
|
614
|
+
* <MjmlBody>
|
|
615
|
+
* <MjmlSection>
|
|
616
|
+
* <MjmlColumn>
|
|
617
|
+
* <MjmlText>Click <a href={url}>here</a> to verify.</MjmlText>
|
|
618
|
+
* </MjmlColumn>
|
|
619
|
+
* </MjmlSection>
|
|
620
|
+
* </MjmlBody>
|
|
621
|
+
* </Mjml>
|
|
622
|
+
* );
|
|
623
|
+
* }
|
|
624
|
+
* ```
|
|
625
|
+
*/
|
|
626
|
+
templates: {
|
|
627
|
+
[K in EmailType]?: (props: EmailContextFor<K>) => any;
|
|
628
|
+
};
|
|
629
|
+
/**
|
|
630
|
+
* Map of email type to subject line (string or function).
|
|
631
|
+
* When using a function, the context is narrowed to the specific email type.
|
|
632
|
+
*/
|
|
633
|
+
subjects: {
|
|
634
|
+
[K in EmailType]?: string | ((context: EmailContextFor<K>) => string);
|
|
635
|
+
};
|
|
636
|
+
/**
|
|
637
|
+
* Optional fallback renderer for email types without a template.
|
|
638
|
+
*/
|
|
639
|
+
fallback?: EmailTemplateRenderer;
|
|
640
|
+
}
|
|
641
|
+
declare class ReactMJMLRenderer implements EmailTemplateRenderer {
|
|
642
|
+
private options;
|
|
643
|
+
constructor(options: ReactMJMLRendererOptions);
|
|
644
|
+
render(context: EmailContext): Promise<RenderedEmail>;
|
|
645
|
+
/**
|
|
646
|
+
* Converts HTML to plain text with basic formatting preservation.
|
|
647
|
+
* Handles line breaks, links, lists, and common block elements.
|
|
648
|
+
*/
|
|
649
|
+
private htmlToPlainText;
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
declare const betterEmail: (options: BetterEmailOptions) => {
|
|
653
|
+
id: "better-email";
|
|
654
|
+
helpers: {
|
|
655
|
+
changeEmail: (data: EmailProps<"change-email-verification">) => Promise<void>;
|
|
656
|
+
deleteAccount: (data: EmailProps<"delete-account-verification">) => Promise<void>;
|
|
657
|
+
magicLink: (data: EmailProps<"magic-link">) => Promise<void>;
|
|
658
|
+
otp: (data: Omit<EmailProps<"verification-otp">, "otpType"> & {
|
|
659
|
+
type: VerificationOTPContext["otpType"];
|
|
660
|
+
}) => Promise<void>;
|
|
661
|
+
invitation: (data: EmailProps<"organization-invitation">) => Promise<void>;
|
|
662
|
+
twoFactor: (data: EmailProps<"two-factor-otp">) => Promise<void>;
|
|
663
|
+
};
|
|
664
|
+
init(): {
|
|
665
|
+
options: {
|
|
666
|
+
emailVerification: {
|
|
667
|
+
sendVerificationEmail: (data: EmailProps<"verification-email">) => Promise<void>;
|
|
668
|
+
};
|
|
669
|
+
emailAndPassword: {
|
|
670
|
+
enabled: true;
|
|
671
|
+
sendResetPassword: (data: EmailProps<"reset-password">) => Promise<void>;
|
|
672
|
+
};
|
|
673
|
+
};
|
|
674
|
+
};
|
|
675
|
+
};
|
|
676
|
+
declare function betterEmailChangeEmail(options: BetterEmailOptions): (data: EmailProps<"change-email-verification">) => Promise<void>;
|
|
677
|
+
declare function betterEmailDeleteAccount(options: BetterEmailOptions): (data: EmailProps<"delete-account-verification">) => Promise<void>;
|
|
678
|
+
declare function betterEmailMagicLink(options: BetterEmailOptions): (data: EmailProps<"magic-link">) => Promise<void>;
|
|
679
|
+
declare function betterEmailOTP(options: BetterEmailOptions): (data: Omit<EmailProps<"verification-otp">, "otpType"> & {
|
|
680
|
+
type: VerificationOTPContext["otpType"];
|
|
681
|
+
}) => Promise<void>;
|
|
682
|
+
declare function betterEmailInvitation(options: BetterEmailOptions): (data: EmailProps<"organization-invitation">) => Promise<void>;
|
|
683
|
+
declare function betterEmailTwoFactor(options: BetterEmailOptions): (data: EmailProps<"two-factor-otp">) => Promise<void>;
|
|
684
|
+
|
|
685
|
+
export { ConsoleProvider, DefaultTemplateRenderer, MJMLRenderer, MailgunProvider, MustacheRenderer, NuntlyProvider, PostmarkProvider, ReactEmailRenderer, ReactMJMLRenderer, ResendProvider, SESProvider, SMTPProvider, betterEmail, betterEmailChangeEmail, betterEmailDeleteAccount, betterEmailInvitation, betterEmailMagicLink, betterEmailOTP, betterEmailTwoFactor, sendEmail };
|
|
686
|
+
export type { BetterEmailOptions, ChangeEmailVerificationContext, DeleteAccountVerificationContext, EmailContext, EmailContextFor, EmailMessage, EmailProps, EmailProvider, EmailSendResponse, EmailTag, EmailTemplateRenderer, EmailType, MJMLRenderedTemplate, MJMLRendererOptions, MagicLinkContext, MailgunProviderOptions, MustacheRenderedTemplate, MustacheRendererOptions, NuntlyProviderOptions, OrganizationInvitationContext, PostmarkProviderOptions, ReactEmailRendererOptions, ReactMJMLRendererOptions, RenderedEmail, ResendProviderOptions, ResetPasswordContext, SESProviderOptions, SMTPProviderOptions, SendEmailResult, TwoFactorOTPContext, VerificationEmailContext, VerificationOTPContext };
|