@rudderjs/mail 0.0.5
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/LICENSE +21 -0
- package/README.md +156 -0
- package/dist/failover.d.ts +26 -0
- package/dist/failover.d.ts.map +1 -0
- package/dist/failover.js +48 -0
- package/dist/failover.js.map +1 -0
- package/dist/fake.d.ts +62 -0
- package/dist/fake.d.ts.map +1 -0
- package/dist/fake.js +113 -0
- package/dist/fake.js.map +1 -0
- package/dist/index.d.ts +102 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +215 -0
- package/dist/index.js.map +1 -0
- package/dist/mailable.d.ts +21 -0
- package/dist/mailable.d.ts.map +1 -0
- package/dist/mailable.js +24 -0
- package/dist/mailable.js.map +1 -0
- package/dist/markdown.d.ts +39 -0
- package/dist/markdown.d.ts.map +1 -0
- package/dist/markdown.js +194 -0
- package/dist/markdown.js.map +1 -0
- package/dist/preview.d.ts +21 -0
- package/dist/preview.d.ts.map +1 -0
- package/dist/preview.js +62 -0
- package/dist/preview.js.map +1 -0
- package/dist/queued.d.ts +11 -0
- package/dist/queued.d.ts.map +1 -0
- package/dist/queued.js +36 -0
- package/dist/queued.js.map +1 -0
- package/package.json +41 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import { ServiceProvider } from '@rudderjs/core';
|
|
2
|
+
import { resolveOptionalPeer } from '@rudderjs/core';
|
|
3
|
+
export { Mailable } from './mailable.js';
|
|
4
|
+
// ─── Mail Registry ─────────────────────────────────────────
|
|
5
|
+
export class MailRegistry {
|
|
6
|
+
static adapter = null;
|
|
7
|
+
static _from = { address: 'noreply@example.com' };
|
|
8
|
+
static set(adapter) { this.adapter = adapter; }
|
|
9
|
+
static get() { return this.adapter; }
|
|
10
|
+
static setFrom(from) { this._from = { ...from }; }
|
|
11
|
+
static getFrom() { return { ...this._from }; }
|
|
12
|
+
/** @internal — clears the registered adapter and resets from. Used for testing. */
|
|
13
|
+
static reset() {
|
|
14
|
+
this.adapter = null;
|
|
15
|
+
this._from = { address: 'noreply@example.com' };
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
// ─── Pending Send (fluent builder) ─────────────────────────
|
|
19
|
+
export class MailPendingSend {
|
|
20
|
+
_to;
|
|
21
|
+
_cc = [];
|
|
22
|
+
_bcc = [];
|
|
23
|
+
_queue;
|
|
24
|
+
constructor(_to) {
|
|
25
|
+
this._to = _to;
|
|
26
|
+
}
|
|
27
|
+
cc(...addresses) { this._cc = addresses; return this; }
|
|
28
|
+
bcc(...addresses) { this._bcc = addresses; return this; }
|
|
29
|
+
/** Specify which queue to use for queued mail. */
|
|
30
|
+
onQueue(name) { this._queue = name; return this; }
|
|
31
|
+
async send(mailable) {
|
|
32
|
+
const adapter = MailRegistry.get();
|
|
33
|
+
if (!adapter)
|
|
34
|
+
throw new Error('[RudderJS Mail] No mail adapter registered. Add mail() to providers.');
|
|
35
|
+
const from = MailRegistry.getFrom();
|
|
36
|
+
await adapter.send(mailable, { to: this._to, from, cc: this._cc, bcc: this._bcc });
|
|
37
|
+
}
|
|
38
|
+
/** Queue the mailable for background sending. Requires `@rudderjs/queue`. */
|
|
39
|
+
async queue(mailable) {
|
|
40
|
+
const { dispatchMailJob } = await import('./queued.js');
|
|
41
|
+
const from = MailRegistry.getFrom();
|
|
42
|
+
const opts = {};
|
|
43
|
+
if (this._queue)
|
|
44
|
+
opts.queue = this._queue;
|
|
45
|
+
await dispatchMailJob(mailable, { to: this._to, from, cc: this._cc, bcc: this._bcc }, opts);
|
|
46
|
+
}
|
|
47
|
+
/** Queue the mailable to be sent after a delay (ms). Requires `@rudderjs/queue`. */
|
|
48
|
+
async later(delay, mailable) {
|
|
49
|
+
const { dispatchMailJob } = await import('./queued.js');
|
|
50
|
+
const from = MailRegistry.getFrom();
|
|
51
|
+
const opts = { delay };
|
|
52
|
+
if (this._queue)
|
|
53
|
+
opts.queue = this._queue;
|
|
54
|
+
await dispatchMailJob(mailable, { to: this._to, from, cc: this._cc, bcc: this._bcc }, opts);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
// ─── Mail Facade ───────────────────────────────────────────
|
|
58
|
+
export class Mail {
|
|
59
|
+
static to(...addresses) {
|
|
60
|
+
return new MailPendingSend(addresses);
|
|
61
|
+
}
|
|
62
|
+
/** Replace the mail adapter with a fake for testing. */
|
|
63
|
+
static fake() {
|
|
64
|
+
// Dynamic require to avoid circular top-level import (fake.ts imports from index.ts)
|
|
65
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
66
|
+
const { FakeMailAdapter } = require('./fake.js');
|
|
67
|
+
return FakeMailAdapter.fake();
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
function isNodemailerConfig(config) {
|
|
71
|
+
return (config.driver === 'smtp' &&
|
|
72
|
+
typeof config.host === 'string' &&
|
|
73
|
+
typeof config.port === 'number');
|
|
74
|
+
}
|
|
75
|
+
// ─── Built-in Log Adapter ──────────────────────────────────
|
|
76
|
+
export class LogAdapter {
|
|
77
|
+
async send(mailable, options) {
|
|
78
|
+
const msg = await mailable.compile();
|
|
79
|
+
const line = '─'.repeat(50);
|
|
80
|
+
console.log(`\n[RudderJS Mail] ${line}`);
|
|
81
|
+
console.log(`[RudderJS Mail] To: ${options.to.join(', ')}`);
|
|
82
|
+
console.log(`[RudderJS Mail] From: ${options.from.name ? `${options.from.name} <${options.from.address}>` : options.from.address}`);
|
|
83
|
+
console.log(`[RudderJS Mail] Subject: ${msg.subject}`);
|
|
84
|
+
if (msg.html)
|
|
85
|
+
console.log(`[RudderJS Mail] HTML: ${msg.html.replace(/<[^>]+>/g, '').trim().slice(0, 120)}`);
|
|
86
|
+
if (msg.text)
|
|
87
|
+
console.log(`[RudderJS Mail] Text: ${msg.text.trim().slice(0, 120)}`);
|
|
88
|
+
console.log(`[RudderJS Mail] ${line}\n`);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
class NodemailerAdapter {
|
|
92
|
+
config;
|
|
93
|
+
from;
|
|
94
|
+
_transporter = null;
|
|
95
|
+
constructor(config, from) {
|
|
96
|
+
this.config = config;
|
|
97
|
+
this.from = from;
|
|
98
|
+
}
|
|
99
|
+
async transporter() {
|
|
100
|
+
if (!this._transporter) {
|
|
101
|
+
this._transporter = (async () => {
|
|
102
|
+
let nodemailer;
|
|
103
|
+
try {
|
|
104
|
+
nodemailer = await resolveOptionalPeer('nodemailer');
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
throw new Error('[RudderJS Mail] SMTP driver requires "nodemailer". Install it with: pnpm add nodemailer');
|
|
108
|
+
}
|
|
109
|
+
const secure = this.config.encryption === 'ssl';
|
|
110
|
+
const transportConfig = {
|
|
111
|
+
host: this.config.host,
|
|
112
|
+
port: this.config.port,
|
|
113
|
+
secure,
|
|
114
|
+
};
|
|
115
|
+
if (this.config.username) {
|
|
116
|
+
transportConfig.auth = { user: this.config.username, pass: this.config.password ?? '' };
|
|
117
|
+
}
|
|
118
|
+
return nodemailer.createTransport(transportConfig);
|
|
119
|
+
})();
|
|
120
|
+
}
|
|
121
|
+
return this._transporter;
|
|
122
|
+
}
|
|
123
|
+
async send(mailable, options) {
|
|
124
|
+
const msg = await mailable.compile();
|
|
125
|
+
const fromStr = this.from.name
|
|
126
|
+
? `${this.from.name} <${this.from.address}>`
|
|
127
|
+
: this.from.address;
|
|
128
|
+
const transporter = await this.transporter();
|
|
129
|
+
const message = {
|
|
130
|
+
from: fromStr,
|
|
131
|
+
to: options.to.join(', '),
|
|
132
|
+
subject: msg.subject,
|
|
133
|
+
};
|
|
134
|
+
if (options.cc && options.cc.length)
|
|
135
|
+
message.cc = options.cc.join(', ');
|
|
136
|
+
if (options.bcc && options.bcc.length)
|
|
137
|
+
message.bcc = options.bcc.join(', ');
|
|
138
|
+
if (msg.html !== undefined)
|
|
139
|
+
message.html = msg.html;
|
|
140
|
+
if (msg.text !== undefined)
|
|
141
|
+
message.text = msg.text;
|
|
142
|
+
await transporter.sendMail(message);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
export function nodemailer(config, from) {
|
|
146
|
+
return {
|
|
147
|
+
create() {
|
|
148
|
+
return new NodemailerAdapter(config, from);
|
|
149
|
+
},
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
// ─── Service Provider Factory ──────────────────────────────
|
|
153
|
+
/**
|
|
154
|
+
* Returns a MailServiceProvider class configured for the given mail config.
|
|
155
|
+
*
|
|
156
|
+
* Built-in drivers: log (prints to console — great for dev), smtp (Nodemailer)
|
|
157
|
+
*
|
|
158
|
+
* Usage in bootstrap/providers.ts:
|
|
159
|
+
* import { mail } from '@rudderjs/mail'
|
|
160
|
+
* import configs from '../config/index.js'
|
|
161
|
+
* export default [..., mail(configs.mail), ...]
|
|
162
|
+
*/
|
|
163
|
+
export function mail(config) {
|
|
164
|
+
class MailServiceProvider extends ServiceProvider {
|
|
165
|
+
register() { }
|
|
166
|
+
async boot() {
|
|
167
|
+
const mailerName = config.default;
|
|
168
|
+
const mailerConfig = config.mailers[mailerName] ?? { driver: 'log' };
|
|
169
|
+
const driver = mailerConfig['driver'];
|
|
170
|
+
MailRegistry.setFrom(config.from);
|
|
171
|
+
let adapter;
|
|
172
|
+
if (driver === 'log') {
|
|
173
|
+
adapter = new LogAdapter();
|
|
174
|
+
}
|
|
175
|
+
else if (driver === 'smtp') {
|
|
176
|
+
if (!isNodemailerConfig(mailerConfig)) {
|
|
177
|
+
throw new Error('[RudderJS Mail] Invalid SMTP config. Expected fields: host (string), port (number).');
|
|
178
|
+
}
|
|
179
|
+
adapter = nodemailer(mailerConfig, config.from).create();
|
|
180
|
+
}
|
|
181
|
+
else if (driver === 'failover') {
|
|
182
|
+
const mailerNames = mailerConfig['mailers'] ?? [];
|
|
183
|
+
const retryAfter = mailerConfig['retryAfter'] ?? 60;
|
|
184
|
+
const adapters = [];
|
|
185
|
+
for (const name of mailerNames) {
|
|
186
|
+
const mc = config.mailers[name];
|
|
187
|
+
if (!mc)
|
|
188
|
+
continue;
|
|
189
|
+
if (mc.driver === 'log') {
|
|
190
|
+
adapters.push(new LogAdapter());
|
|
191
|
+
}
|
|
192
|
+
else if (mc.driver === 'smtp' && isNodemailerConfig(mc)) {
|
|
193
|
+
adapters.push(nodemailer(mc, config.from).create());
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
if (adapters.length === 0)
|
|
197
|
+
throw new Error('[RudderJS Mail] Failover driver has no valid mailers configured.');
|
|
198
|
+
const { FailoverAdapter } = await import('./failover.js');
|
|
199
|
+
adapter = new FailoverAdapter(adapters, retryAfter);
|
|
200
|
+
}
|
|
201
|
+
else {
|
|
202
|
+
throw new Error(`[RudderJS Mail] Unknown driver "${driver}". Available: log, smtp, failover`);
|
|
203
|
+
}
|
|
204
|
+
MailRegistry.set(adapter);
|
|
205
|
+
this.app.instance('mail', adapter);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
return MailServiceProvider;
|
|
209
|
+
}
|
|
210
|
+
// ─── Re-exports ────────────────────────────────────────────
|
|
211
|
+
export { FailoverAdapter } from './failover.js';
|
|
212
|
+
export { MarkdownMailable } from './markdown.js';
|
|
213
|
+
export { mailPreview } from './preview.js';
|
|
214
|
+
export { FakeMailAdapter } from './fake.js';
|
|
215
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export interface MailMessage {
|
|
2
|
+
subject: string;
|
|
3
|
+
html?: string;
|
|
4
|
+
text?: string;
|
|
5
|
+
}
|
|
6
|
+
export declare abstract class Mailable {
|
|
7
|
+
protected _subject: string;
|
|
8
|
+
private _html?;
|
|
9
|
+
private _text?;
|
|
10
|
+
/** Set the email subject */
|
|
11
|
+
protected subject(subject: string): this;
|
|
12
|
+
/** Set the HTML body */
|
|
13
|
+
protected html(html: string): this;
|
|
14
|
+
/** Set the plain-text body */
|
|
15
|
+
protected text(text: string): this;
|
|
16
|
+
/** Build the mailable — called before sending. Override to set subject/html/text. */
|
|
17
|
+
abstract build(): this | Promise<this>;
|
|
18
|
+
/** Called by the adapter — builds then returns the compiled message */
|
|
19
|
+
compile(): Promise<MailMessage>;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=mailable.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mailable.d.ts","sourceRoot":"","sources":["../src/mailable.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,CAAC,EAAI,MAAM,CAAA;IACf,IAAI,CAAC,EAAI,MAAM,CAAA;CAChB;AAID,8BAAsB,QAAQ;IAC5B,SAAS,CAAC,QAAQ,SAAK;IACvB,OAAO,CAAC,KAAK,CAAC,CAAQ;IACtB,OAAO,CAAC,KAAK,CAAC,CAAQ;IAEtB,4BAA4B;IAC5B,SAAS,CAAC,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAExC,wBAAwB;IACxB,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAElC,8BAA8B;IAC9B,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAElC,qFAAqF;IACrF,QAAQ,CAAC,KAAK,IAAI,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAEtC,uEAAuE;IACjE,OAAO,IAAI,OAAO,CAAC,WAAW,CAAC;CAOtC"}
|
package/dist/mailable.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// ─── Mail Message ──────────────────────────────────────────
|
|
2
|
+
// ─── Mailable ──────────────────────────────────────────────
|
|
3
|
+
export class Mailable {
|
|
4
|
+
_subject = '';
|
|
5
|
+
_html;
|
|
6
|
+
_text;
|
|
7
|
+
/** Set the email subject */
|
|
8
|
+
subject(subject) { this._subject = subject; return this; }
|
|
9
|
+
/** Set the HTML body */
|
|
10
|
+
html(html) { this._html = html; return this; }
|
|
11
|
+
/** Set the plain-text body */
|
|
12
|
+
text(text) { this._text = text; return this; }
|
|
13
|
+
/** Called by the adapter — builds then returns the compiled message */
|
|
14
|
+
async compile() {
|
|
15
|
+
await this.build();
|
|
16
|
+
const msg = { subject: this._subject };
|
|
17
|
+
if (this._html !== undefined)
|
|
18
|
+
msg.html = this._html;
|
|
19
|
+
if (this._text !== undefined)
|
|
20
|
+
msg.text = this._text;
|
|
21
|
+
return msg;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=mailable.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mailable.js","sourceRoot":"","sources":["../src/mailable.ts"],"names":[],"mappings":"AAAA,8DAA8D;AAQ9D,8DAA8D;AAE9D,MAAM,OAAgB,QAAQ;IAClB,QAAQ,GAAG,EAAE,CAAA;IACf,KAAK,CAAS;IACd,KAAK,CAAS;IAEtB,4BAA4B;IAClB,OAAO,CAAC,OAAe,IAAU,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,CAAC,OAAO,IAAI,CAAA,CAAC,CAAC;IAEjF,wBAAwB;IACd,IAAI,CAAC,IAAY,IAAU,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC,OAAO,IAAI,CAAA,CAAC,CAAC;IAErE,8BAA8B;IACpB,IAAI,CAAC,IAAY,IAAU,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC,OAAO,IAAI,CAAA,CAAC,CAAC;IAKrE,uEAAuE;IACvE,KAAK,CAAC,OAAO;QACX,MAAM,IAAI,CAAC,KAAK,EAAE,CAAA;QAClB,MAAM,GAAG,GAAgB,EAAE,OAAO,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAA;QACnD,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS;YAAE,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,KAAK,CAAA;QACnD,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS;YAAE,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,KAAK,CAAA;QACnD,OAAO,GAAG,CAAA;IACZ,CAAC;CACF"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { Mailable, type MailMessage } from './mailable.js';
|
|
2
|
+
/**
|
|
3
|
+
* A mailable that renders markdown content into responsive HTML email.
|
|
4
|
+
* Supports special components: `@component('name', { attrs })` ... `@endcomponent`
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* class WelcomeMail extends MarkdownMailable {
|
|
8
|
+
* build() {
|
|
9
|
+
* return this.subject('Welcome!')
|
|
10
|
+
* .markdown(`
|
|
11
|
+
* # Welcome, {{ name }}!
|
|
12
|
+
*
|
|
13
|
+
* Thanks for signing up.
|
|
14
|
+
*
|
|
15
|
+
* @component('button', { url: '{{ url }}' })
|
|
16
|
+
* Get Started
|
|
17
|
+
* @endcomponent
|
|
18
|
+
*
|
|
19
|
+
* @component('panel')
|
|
20
|
+
* If you didn't create this account, no action is needed.
|
|
21
|
+
* @endcomponent
|
|
22
|
+
* `)
|
|
23
|
+
* .with({ name: this.user.name, url: 'https://example.com/dashboard' })
|
|
24
|
+
* }
|
|
25
|
+
* }
|
|
26
|
+
*/
|
|
27
|
+
export declare abstract class MarkdownMailable extends Mailable {
|
|
28
|
+
private _markdown;
|
|
29
|
+
private _vars;
|
|
30
|
+
private _theme?;
|
|
31
|
+
/** Set the markdown content */
|
|
32
|
+
protected markdown(content: string): this;
|
|
33
|
+
/** Set template variables — replaces `{{ key }}` in the markdown */
|
|
34
|
+
protected with(vars: Record<string, string>): this;
|
|
35
|
+
/** Set the theme (CSS overrides). Default: built-in responsive layout. */
|
|
36
|
+
protected theme(css: string): this;
|
|
37
|
+
compile(): Promise<MailMessage>;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=markdown.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../src/markdown.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,KAAK,WAAW,EAAE,MAAM,eAAe,CAAA;AA+D1D;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,8BAAsB,gBAAiB,SAAQ,QAAQ;IACrD,OAAO,CAAC,SAAS,CAAK;IACtB,OAAO,CAAC,KAAK,CAA6B;IAC1C,OAAO,CAAC,MAAM,CAAC,CAAQ;IAEvB,+BAA+B;IAC/B,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAKzC,oEAAoE;IACpE,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI;IAKlD,0EAA0E;IAC1E,SAAS,CAAC,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAK5B,OAAO,IAAI,OAAO,CAAC,WAAW,CAAC;CAwBtC"}
|
package/dist/markdown.js
ADDED
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import { Mailable } from './mailable.js';
|
|
2
|
+
// ─── Markdown Components ────────────────────────────────────
|
|
3
|
+
const COMPONENTS = {
|
|
4
|
+
button: (attrs, body) => {
|
|
5
|
+
const url = attrs['url'] ?? '#';
|
|
6
|
+
const color = attrs['color'] ?? '#3490dc';
|
|
7
|
+
return `<table width="100%" cellpadding="0" cellspacing="0" role="presentation">
|
|
8
|
+
<tr><td align="center" style="padding: 16px 0;">
|
|
9
|
+
<a href="${_escHtml(url)}" style="display:inline-block;padding:12px 24px;background-color:${_escHtml(color)};color:#ffffff;text-decoration:none;border-radius:6px;font-weight:600;">${_escHtml(body)}</a>
|
|
10
|
+
</td></tr>
|
|
11
|
+
</table>`;
|
|
12
|
+
},
|
|
13
|
+
panel: (_attrs, body) => {
|
|
14
|
+
return `<table width="100%" cellpadding="0" cellspacing="0" role="presentation">
|
|
15
|
+
<tr><td style="padding:16px;background-color:#f8fafc;border-left:4px solid #3490dc;border-radius:4px;">
|
|
16
|
+
${_mdToHtml(body)}
|
|
17
|
+
</td></tr>
|
|
18
|
+
</table>`;
|
|
19
|
+
},
|
|
20
|
+
table: (_attrs, body) => {
|
|
21
|
+
const rows = body.trim().split('\n').filter(r => r.trim());
|
|
22
|
+
if (rows.length === 0)
|
|
23
|
+
return '';
|
|
24
|
+
const headerCells = rows[0].split('|').map(c => c.trim()).filter(Boolean);
|
|
25
|
+
const dataRows = rows.slice(2); // skip header + separator
|
|
26
|
+
let html = '<table width="100%" cellpadding="8" cellspacing="0" style="border-collapse:collapse;margin:16px 0;">';
|
|
27
|
+
html += '<thead><tr>';
|
|
28
|
+
for (const cell of headerCells) {
|
|
29
|
+
html += `<th style="border-bottom:2px solid #dee2e6;text-align:left;padding:8px;">${_escHtml(cell)}</th>`;
|
|
30
|
+
}
|
|
31
|
+
html += '</tr></thead><tbody>';
|
|
32
|
+
for (const row of dataRows) {
|
|
33
|
+
const cells = row.split('|').map(c => c.trim()).filter(Boolean);
|
|
34
|
+
html += '<tr>';
|
|
35
|
+
for (const cell of cells) {
|
|
36
|
+
html += `<td style="border-bottom:1px solid #dee2e6;padding:8px;">${_escHtml(cell)}</td>`;
|
|
37
|
+
}
|
|
38
|
+
html += '</tr>';
|
|
39
|
+
}
|
|
40
|
+
html += '</tbody></table>';
|
|
41
|
+
return html;
|
|
42
|
+
},
|
|
43
|
+
header: (_attrs, body) => {
|
|
44
|
+
return `<div style="padding:24px 0;text-align:center;border-bottom:1px solid #e8e5ef;">
|
|
45
|
+
<h1 style="margin:0;font-size:20px;color:#333;">${_escHtml(body)}</h1>
|
|
46
|
+
</div>`;
|
|
47
|
+
},
|
|
48
|
+
footer: (_attrs, body) => {
|
|
49
|
+
return `<div style="padding:16px 0;text-align:center;border-top:1px solid #e8e5ef;color:#999;font-size:12px;">
|
|
50
|
+
${_mdToHtml(body)}
|
|
51
|
+
</div>`;
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
// ─── MarkdownMailable ───────────────────────────────────────
|
|
55
|
+
/**
|
|
56
|
+
* A mailable that renders markdown content into responsive HTML email.
|
|
57
|
+
* Supports special components: `@component('name', { attrs })` ... `@endcomponent`
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* class WelcomeMail extends MarkdownMailable {
|
|
61
|
+
* build() {
|
|
62
|
+
* return this.subject('Welcome!')
|
|
63
|
+
* .markdown(`
|
|
64
|
+
* # Welcome, {{ name }}!
|
|
65
|
+
*
|
|
66
|
+
* Thanks for signing up.
|
|
67
|
+
*
|
|
68
|
+
* @component('button', { url: '{{ url }}' })
|
|
69
|
+
* Get Started
|
|
70
|
+
* @endcomponent
|
|
71
|
+
*
|
|
72
|
+
* @component('panel')
|
|
73
|
+
* If you didn't create this account, no action is needed.
|
|
74
|
+
* @endcomponent
|
|
75
|
+
* `)
|
|
76
|
+
* .with({ name: this.user.name, url: 'https://example.com/dashboard' })
|
|
77
|
+
* }
|
|
78
|
+
* }
|
|
79
|
+
*/
|
|
80
|
+
export class MarkdownMailable extends Mailable {
|
|
81
|
+
_markdown = '';
|
|
82
|
+
_vars = {};
|
|
83
|
+
_theme;
|
|
84
|
+
/** Set the markdown content */
|
|
85
|
+
markdown(content) {
|
|
86
|
+
this._markdown = content;
|
|
87
|
+
return this;
|
|
88
|
+
}
|
|
89
|
+
/** Set template variables — replaces `{{ key }}` in the markdown */
|
|
90
|
+
with(vars) {
|
|
91
|
+
Object.assign(this._vars, vars);
|
|
92
|
+
return this;
|
|
93
|
+
}
|
|
94
|
+
/** Set the theme (CSS overrides). Default: built-in responsive layout. */
|
|
95
|
+
theme(css) {
|
|
96
|
+
this._theme = css;
|
|
97
|
+
return this;
|
|
98
|
+
}
|
|
99
|
+
async compile() {
|
|
100
|
+
await this.build();
|
|
101
|
+
// Interpolate variables
|
|
102
|
+
let md = this._markdown;
|
|
103
|
+
for (const [key, value] of Object.entries(this._vars)) {
|
|
104
|
+
md = md.replace(new RegExp(`\\{\\{\\s*${key}\\s*\\}\\}`, 'g'), value);
|
|
105
|
+
}
|
|
106
|
+
// Process components
|
|
107
|
+
md = _processComponents(md);
|
|
108
|
+
// Convert remaining markdown to HTML
|
|
109
|
+
const bodyHtml = _mdToHtml(md);
|
|
110
|
+
// Wrap in responsive email layout
|
|
111
|
+
const html = _wrapLayout(bodyHtml, this._theme);
|
|
112
|
+
return {
|
|
113
|
+
subject: this._subject,
|
|
114
|
+
html,
|
|
115
|
+
text: _stripHtml(bodyHtml),
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
// ─── Internal helpers ───────────────────────────────────────
|
|
120
|
+
function _escHtml(s) {
|
|
121
|
+
return s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"');
|
|
122
|
+
}
|
|
123
|
+
function _stripHtml(html) {
|
|
124
|
+
return html.replace(/<[^>]+>/g, '').replace(/\s+/g, ' ').trim();
|
|
125
|
+
}
|
|
126
|
+
function _processComponents(md) {
|
|
127
|
+
// Match @component('name', { attrs }) ... @endcomponent
|
|
128
|
+
return md.replace(/@component\('(\w+)'(?:,\s*(\{[^}]*\}))?\)\s*\n([\s\S]*?)@endcomponent/g, (_match, name, attrsStr, body) => {
|
|
129
|
+
const handler = COMPONENTS[name];
|
|
130
|
+
if (!handler)
|
|
131
|
+
return body;
|
|
132
|
+
let attrs = {};
|
|
133
|
+
if (attrsStr) {
|
|
134
|
+
try {
|
|
135
|
+
// Parse simple { key: 'value' } objects
|
|
136
|
+
attrs = JSON.parse(attrsStr.replace(/'/g, '"').replace(/(\w+):/g, '"$1":'));
|
|
137
|
+
}
|
|
138
|
+
catch { /* use empty attrs */ }
|
|
139
|
+
}
|
|
140
|
+
return handler(attrs, body.trim());
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
function _mdToHtml(md) {
|
|
144
|
+
let html = md;
|
|
145
|
+
// Headers
|
|
146
|
+
html = html.replace(/^### (.+)$/gm, '<h3 style="margin:16px 0 8px;color:#333;">$1</h3>');
|
|
147
|
+
html = html.replace(/^## (.+)$/gm, '<h2 style="margin:20px 0 8px;color:#333;">$1</h2>');
|
|
148
|
+
html = html.replace(/^# (.+)$/gm, '<h1 style="margin:24px 0 12px;color:#333;">$1</h1>');
|
|
149
|
+
// Bold and italic
|
|
150
|
+
html = html.replace(/\*\*(.+?)\*\*/g, '<strong>$1</strong>');
|
|
151
|
+
html = html.replace(/\*(.+?)\*/g, '<em>$1</em>');
|
|
152
|
+
// Links
|
|
153
|
+
html = html.replace(/\[([^\]]+)\]\(([^)]+)\)/g, '<a href="$2" style="color:#3490dc;">$1</a>');
|
|
154
|
+
// Inline code
|
|
155
|
+
html = html.replace(/`([^`]+)`/g, '<code style="background:#f0f0f0;padding:2px 6px;border-radius:3px;font-size:13px;">$1</code>');
|
|
156
|
+
// Unordered lists
|
|
157
|
+
html = html.replace(/^- (.+)$/gm, '<li>$1</li>');
|
|
158
|
+
html = html.replace(/(<li>.*<\/li>\n?)+/g, '<ul style="margin:8px 0;padding-left:24px;">$&</ul>');
|
|
159
|
+
// Horizontal rules
|
|
160
|
+
html = html.replace(/^---$/gm, '<hr style="border:none;border-top:1px solid #e8e5ef;margin:24px 0;">');
|
|
161
|
+
// Paragraphs (double newline)
|
|
162
|
+
html = html.replace(/\n\n+/g, '</p><p style="margin:12px 0;line-height:1.6;color:#555;">');
|
|
163
|
+
// Wrap in paragraph if not already wrapped in a block element
|
|
164
|
+
if (!html.startsWith('<')) {
|
|
165
|
+
html = `<p style="margin:12px 0;line-height:1.6;color:#555;">${html}</p>`;
|
|
166
|
+
}
|
|
167
|
+
return html;
|
|
168
|
+
}
|
|
169
|
+
function _wrapLayout(body, customCss) {
|
|
170
|
+
const css = customCss ?? `
|
|
171
|
+
body { margin: 0; padding: 0; background-color: #f4f4f7; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif; }
|
|
172
|
+
.wrapper { width: 100%; padding: 40px 0; background-color: #f4f4f7; }
|
|
173
|
+
.content { max-width: 570px; margin: 0 auto; background: #ffffff; border-radius: 8px; overflow: hidden; box-shadow: 0 2px 4px rgba(0,0,0,0.05); }
|
|
174
|
+
.inner { padding: 32px; }
|
|
175
|
+
`;
|
|
176
|
+
return `<!DOCTYPE html>
|
|
177
|
+
<html>
|
|
178
|
+
<head>
|
|
179
|
+
<meta charset="utf-8">
|
|
180
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
181
|
+
<style>${css}</style>
|
|
182
|
+
</head>
|
|
183
|
+
<body>
|
|
184
|
+
<div class="wrapper">
|
|
185
|
+
<div class="content">
|
|
186
|
+
<div class="inner">
|
|
187
|
+
${body}
|
|
188
|
+
</div>
|
|
189
|
+
</div>
|
|
190
|
+
</div>
|
|
191
|
+
</body>
|
|
192
|
+
</html>`;
|
|
193
|
+
}
|
|
194
|
+
//# sourceMappingURL=markdown.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markdown.js","sourceRoot":"","sources":["../src/markdown.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Mailable } from './mailable.js';
|
|
2
|
+
/**
|
|
3
|
+
* Renders a mailable as HTML in the browser for development preview.
|
|
4
|
+
* Returns a route handler that compiles the mailable and serves the HTML.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* import { mailPreview } from '@rudderjs/mail'
|
|
8
|
+
* import { WelcomeEmail } from '../app/Mail/WelcomeEmail.js'
|
|
9
|
+
*
|
|
10
|
+
* // In routes/web.ts (only in development):
|
|
11
|
+
* if (process.env.NODE_ENV !== 'production') {
|
|
12
|
+
* router.get('/mail-preview/welcome', mailPreview(() => new WelcomeEmail(sampleUser)))
|
|
13
|
+
* }
|
|
14
|
+
*/
|
|
15
|
+
export declare function mailPreview(factory: () => Mailable | Promise<Mailable>): (_req: unknown, res: {
|
|
16
|
+
status(code: number): {
|
|
17
|
+
send(body: string): void;
|
|
18
|
+
};
|
|
19
|
+
headers?: Record<string, string>;
|
|
20
|
+
}) => Promise<void>;
|
|
21
|
+
//# sourceMappingURL=preview.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"preview.d.ts","sourceRoot":"","sources":["../src/preview.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AAI7C;;;;;;;;;;;;GAYG;AACH,wBAAgB,WAAW,CACzB,OAAO,EAAE,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,GAC1C,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE;IAAE,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG;QAAE,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAyCjI"}
|
package/dist/preview.js
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
// ─── Mail Preview ───────────────────────────────────────────
|
|
2
|
+
/**
|
|
3
|
+
* Renders a mailable as HTML in the browser for development preview.
|
|
4
|
+
* Returns a route handler that compiles the mailable and serves the HTML.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* import { mailPreview } from '@rudderjs/mail'
|
|
8
|
+
* import { WelcomeEmail } from '../app/Mail/WelcomeEmail.js'
|
|
9
|
+
*
|
|
10
|
+
* // In routes/web.ts (only in development):
|
|
11
|
+
* if (process.env.NODE_ENV !== 'production') {
|
|
12
|
+
* router.get('/mail-preview/welcome', mailPreview(() => new WelcomeEmail(sampleUser)))
|
|
13
|
+
* }
|
|
14
|
+
*/
|
|
15
|
+
export function mailPreview(factory) {
|
|
16
|
+
return async (_req, res) => {
|
|
17
|
+
try {
|
|
18
|
+
const mailable = await factory();
|
|
19
|
+
const msg = await mailable.compile();
|
|
20
|
+
const html = msg.html ?? `<pre>${msg.text ?? '(no content)'}</pre>`;
|
|
21
|
+
// Wrap in a preview shell with subject header
|
|
22
|
+
const preview = `<!DOCTYPE html>
|
|
23
|
+
<html>
|
|
24
|
+
<head>
|
|
25
|
+
<meta charset="utf-8">
|
|
26
|
+
<title>Mail Preview: ${_escHtml(msg.subject)}</title>
|
|
27
|
+
<style>
|
|
28
|
+
body { margin: 0; font-family: -apple-system, BlinkMacSystemFont, sans-serif; background: #e5e5e5; }
|
|
29
|
+
.preview-bar { padding: 12px 24px; background: #1a1a2e; color: #fff; font-size: 13px; display: flex; gap: 24px; align-items: center; }
|
|
30
|
+
.preview-bar strong { color: #a78bfa; }
|
|
31
|
+
.preview-frame { max-width: 640px; margin: 24px auto; background: #fff; border-radius: 8px; overflow: hidden; box-shadow: 0 4px 12px rgba(0,0,0,0.1); }
|
|
32
|
+
.preview-content { padding: 0; }
|
|
33
|
+
.preview-content iframe { width: 100%; height: 80vh; border: none; }
|
|
34
|
+
</style>
|
|
35
|
+
</head>
|
|
36
|
+
<body>
|
|
37
|
+
<div class="preview-bar">
|
|
38
|
+
<span><strong>Subject:</strong> ${_escHtml(msg.subject)}</span>
|
|
39
|
+
<span><strong>Type:</strong> ${msg.html ? 'HTML' : 'Plain Text'}</span>
|
|
40
|
+
</div>
|
|
41
|
+
<div class="preview-frame">
|
|
42
|
+
<div class="preview-content">
|
|
43
|
+
<iframe srcdoc="${_escAttr(html)}"></iframe>
|
|
44
|
+
</div>
|
|
45
|
+
</div>
|
|
46
|
+
</body>
|
|
47
|
+
</html>`;
|
|
48
|
+
res.status(200).send(preview);
|
|
49
|
+
}
|
|
50
|
+
catch (err) {
|
|
51
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
52
|
+
res.status(500).send(`<pre>Mail preview error:\n${_escHtml(message)}</pre>`);
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
function _escHtml(s) {
|
|
57
|
+
return s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"');
|
|
58
|
+
}
|
|
59
|
+
function _escAttr(s) {
|
|
60
|
+
return s.replace(/&/g, '&').replace(/"/g, '"').replace(/</g, '<').replace(/>/g, '>');
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=preview.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"preview.js","sourceRoot":"","sources":["../src/preview.ts"],"names":[],"mappings":"AAEA,+DAA+D;AAE/D;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,WAAW,CACzB,OAA2C;IAE3C,OAAO,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE;QACzB,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,OAAO,EAAE,CAAA;YAChC,MAAM,GAAG,GAAQ,MAAM,QAAQ,CAAC,OAAO,EAAE,CAAA;YACzC,MAAM,IAAI,GAAO,GAAG,CAAC,IAAI,IAAI,QAAQ,GAAG,CAAC,IAAI,IAAI,cAAc,QAAQ,CAAA;YAEvE,8CAA8C;YAC9C,MAAM,OAAO,GAAG;;;;yBAIG,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC;;;;;;;;;;;;sCAYR,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC;mCACxB,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,YAAY;;;;wBAI3C,QAAQ,CAAC,IAAI,CAAC;;;;QAI9B,CAAA;YAEF,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;QAC/B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;YAChE,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,6BAA6B,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;QAC9E,CAAC;IACH,CAAC,CAAA;AACH,CAAC;AAED,SAAS,QAAQ,CAAC,CAAS;IACzB,OAAO,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAA;AACrG,CAAC;AAED,SAAS,QAAQ,CAAC,CAAS;IACzB,OAAO,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;AACrG,CAAC"}
|
package/dist/queued.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Mailable } from './mailable.js';
|
|
2
|
+
import type { SendOptions } from './index.js';
|
|
3
|
+
/**
|
|
4
|
+
* @internal — dispatches a mailable through the queue system.
|
|
5
|
+
* Dynamically requires @rudderjs/queue to avoid hard dependency.
|
|
6
|
+
*/
|
|
7
|
+
export declare function dispatchMailJob(mailable: Mailable, options: SendOptions, queueOptions?: {
|
|
8
|
+
queue?: string;
|
|
9
|
+
delay?: number;
|
|
10
|
+
}): Promise<void>;
|
|
11
|
+
//# sourceMappingURL=queued.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"queued.d.ts","sourceRoot":"","sources":["../src/queued.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AAC7C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAS7C;;;GAGG;AACH,wBAAsB,eAAe,CACnC,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,WAAW,EACpB,YAAY,CAAC,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GAChD,OAAO,CAAC,IAAI,CAAC,CAiCf"}
|