@travetto/email 3.1.7 → 3.1.9
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/package.json +1 -1
- package/src/service.ts +52 -56
package/package.json
CHANGED
package/src/service.ts
CHANGED
|
@@ -7,7 +7,8 @@ import { MailTemplateEngine } from './template';
|
|
|
7
7
|
import { MailUtil } from './util';
|
|
8
8
|
import { EmailResource } from './resource';
|
|
9
9
|
|
|
10
|
-
type
|
|
10
|
+
type Compiled = { html: string, text?: string, subject: string };
|
|
11
|
+
type MessageWithoutBody = Omit<MessageOptions, keyof Compiled>;
|
|
11
12
|
|
|
12
13
|
/**
|
|
13
14
|
* Email service for sending and templating emails
|
|
@@ -15,7 +16,7 @@ type MessageWithoutBody = Omit<MessageOptions, 'html' | 'text' | 'subject'>;
|
|
|
15
16
|
@Injectable()
|
|
16
17
|
export class MailService {
|
|
17
18
|
|
|
18
|
-
#compiled = new Map<string,
|
|
19
|
+
#compiled = new Map<string, Compiled>();
|
|
19
20
|
#transport: MailTransport;
|
|
20
21
|
#tplEngine: MailTemplateEngine;
|
|
21
22
|
#resources: EmailResource;
|
|
@@ -30,41 +31,10 @@ export class MailService {
|
|
|
30
31
|
this.#resources = resources;
|
|
31
32
|
}
|
|
32
33
|
|
|
33
|
-
/**
|
|
34
|
-
* Force content into alternative slots, satisfies node mailer
|
|
35
|
-
*/
|
|
36
|
-
#forceContentToAlternative(msg: MessageOptions): MessageOptions {
|
|
37
|
-
for (const [key, mime] of [['text', 'text/plain'], ['html', 'text/html']] as const) {
|
|
38
|
-
if (msg[key]) {
|
|
39
|
-
(msg.alternatives ??= []).push({
|
|
40
|
-
content: msg[key], contentDisposition: 'inline', contentTransferEncoding: '7bit', contentType: `${mime}; charset=utf-8`
|
|
41
|
-
});
|
|
42
|
-
delete msg[key];
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
return msg;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Send multiple messages.
|
|
50
|
-
*/
|
|
51
|
-
async sendAll<S extends SentMessage = SentMessage>(messages: MessageOptions[], base: Partial<MessageOptions> = {}): Promise<S[]> {
|
|
52
|
-
return Promise.all(messages.map(msg => this.send<S>({
|
|
53
|
-
...base,
|
|
54
|
-
...msg,
|
|
55
|
-
...(msg.context || base.context ? {
|
|
56
|
-
context: {
|
|
57
|
-
...(base.context || {}),
|
|
58
|
-
...(msg.context || {})
|
|
59
|
-
}
|
|
60
|
-
} : {})
|
|
61
|
-
})));
|
|
62
|
-
}
|
|
63
|
-
|
|
64
34
|
/**
|
|
65
35
|
* Get compiled content by key
|
|
66
36
|
*/
|
|
67
|
-
async getCompiled(key: string): Promise<
|
|
37
|
+
async getCompiled(key: string): Promise<Compiled> {
|
|
68
38
|
if (GlobalEnv.dynamic || !this.#compiled.has(key)) {
|
|
69
39
|
const [html, text, subject] = await Promise.all([
|
|
70
40
|
this.#resources.read(`${key}.compiled.html`),
|
|
@@ -79,42 +49,68 @@ export class MailService {
|
|
|
79
49
|
|
|
80
50
|
/**
|
|
81
51
|
* Build message from key/context
|
|
82
|
-
* @param
|
|
52
|
+
* @param keyOrMessage
|
|
83
53
|
* @param ctx
|
|
84
54
|
* @returns
|
|
85
55
|
*/
|
|
86
|
-
async
|
|
87
|
-
const tpl = (typeof
|
|
88
|
-
|
|
89
|
-
const [
|
|
56
|
+
async templateMessage(keyOrMessage: string | Compiled, ctx: Record<string, unknown>): Promise<Compiled> {
|
|
57
|
+
const tpl = (typeof keyOrMessage === 'string' ? await this.getCompiled(keyOrMessage) : keyOrMessage);
|
|
58
|
+
|
|
59
|
+
const [html, text, subject] = await Promise.all([
|
|
90
60
|
tpl.html ? this.#tplEngine!.template(tpl.html, ctx) : undefined,
|
|
91
61
|
tpl.text ? this.#tplEngine!.template(tpl.text, ctx) : undefined,
|
|
92
62
|
tpl.subject ? this.#tplEngine!.template(tpl.subject, ctx) : undefined
|
|
93
63
|
]);
|
|
94
64
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
65
|
+
return { html: html!, text, subject: subject! };
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Send a single message
|
|
70
|
+
*/
|
|
71
|
+
async send<S extends SentMessage = SentMessage>(
|
|
72
|
+
message: Pick<MessageOptions, 'to' | 'from' | 'replyTo'>,
|
|
73
|
+
key: string,
|
|
74
|
+
ctx?: Record<string, unknown>,
|
|
75
|
+
base?: MessageWithoutBody
|
|
76
|
+
): Promise<S>;
|
|
77
|
+
async send<S extends SentMessage = SentMessage>(message: MessageOptions): Promise<S>;
|
|
78
|
+
async send<S extends SentMessage = SentMessage>(
|
|
79
|
+
message: MessageOptions | Pick<MessageOptions, 'to' | 'from' | 'replyTo'>,
|
|
80
|
+
key?: string,
|
|
81
|
+
ctx?: Record<string, unknown>,
|
|
82
|
+
base?: MessageWithoutBody
|
|
83
|
+
): Promise<S> {
|
|
84
|
+
const keyOrMessage = key ?? ('html' in message ? message : '') ?? '';
|
|
85
|
+
const context = ctx ?? (('context' in message) ? message.context : {}) ?? {};
|
|
86
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
87
|
+
const compiled = await this.templateMessage(keyOrMessage as Compiled, context);
|
|
100
88
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
89
|
+
const final = { ...base, ...message, ...compiled };
|
|
90
|
+
|
|
91
|
+
// Extract images
|
|
92
|
+
if (compiled.html) {
|
|
93
|
+
const { html, attachments } = await MailUtil.extractImageAttachments(compiled.html);
|
|
94
|
+
final.html = html;
|
|
95
|
+
final.attachments = [...attachments, ...(final.attachments ?? [])];
|
|
105
96
|
}
|
|
106
97
|
|
|
107
|
-
return
|
|
98
|
+
return this.#transport.send<S>(final);
|
|
108
99
|
}
|
|
109
100
|
|
|
110
101
|
/**
|
|
111
|
-
* Send
|
|
102
|
+
* Send multiple messages.
|
|
112
103
|
*/
|
|
113
|
-
async
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
104
|
+
async sendAll<S extends SentMessage = SentMessage>(messages: MessageOptions[], base: Partial<MessageOptions> = {}): Promise<S[]> {
|
|
105
|
+
return Promise.all(messages.map(msg => this.send<S>({
|
|
106
|
+
...base,
|
|
107
|
+
...msg,
|
|
108
|
+
...(msg.context || base.context ? {
|
|
109
|
+
context: {
|
|
110
|
+
...(base.context || {}),
|
|
111
|
+
...(msg.context || {})
|
|
112
|
+
}
|
|
113
|
+
} : {})
|
|
114
|
+
})));
|
|
119
115
|
}
|
|
120
116
|
}
|