@travetto/email 4.0.0-rc.0 → 4.0.0-rc.1
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/README.md +1 -1
- package/__index__.ts +1 -0
- package/package.json +4 -4
- package/src/resource.ts +19 -0
- package/src/service.ts +11 -0
- package/src/types.ts +21 -20
- package/src/util.ts +25 -1
package/README.md
CHANGED
|
@@ -13,7 +13,7 @@ npm install @travetto/email
|
|
|
13
13
|
yarn add @travetto/email
|
|
14
14
|
```
|
|
15
15
|
|
|
16
|
-
A standard API for sending and rendering emails. The mail transport must be defined to allow for mail to be sent properly. Out of the box, the only transport available by default is the [NullTransport](https://github.com/travetto/travetto/tree/main/module/email/src/transport.ts#L15) which will just drop emails. The structure of the API is derived from [nodemailer](https://nodemailer.com/about/), but is compatible with any library that can handle the [EmailOptions](https://github.com/travetto/travetto/tree/main/module/email/src/types.ts#
|
|
16
|
+
A standard API for sending and rendering emails. The mail transport must be defined to allow for mail to be sent properly. Out of the box, the only transport available by default is the [NullTransport](https://github.com/travetto/travetto/tree/main/module/email/src/transport.ts#L15) which will just drop emails. The structure of the API is derived from [nodemailer](https://nodemailer.com/about/), but is compatible with any library that can handle the [EmailOptions](https://github.com/travetto/travetto/tree/main/module/email/src/types.ts#L43) input.
|
|
17
17
|
|
|
18
18
|
To expose the necessary email transport, the following pattern is commonly used:
|
|
19
19
|
|
package/__index__.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@travetto/email",
|
|
3
|
-
"version": "4.0.0-rc.
|
|
3
|
+
"version": "4.0.0-rc.1",
|
|
4
4
|
"description": "Email transmission module.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"email",
|
|
@@ -23,9 +23,9 @@
|
|
|
23
23
|
"directory": "module/email"
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@travetto/base": "^4.0.0-rc.
|
|
27
|
-
"@travetto/config": "^4.0.0-rc.
|
|
28
|
-
"@travetto/di": "^4.0.0-rc.
|
|
26
|
+
"@travetto/base": "^4.0.0-rc.1",
|
|
27
|
+
"@travetto/config": "^4.0.0-rc.1",
|
|
28
|
+
"@travetto/di": "^4.0.0-rc.1",
|
|
29
29
|
"@types/mustache": "^4.2.5",
|
|
30
30
|
"mustache": "^4.2.0"
|
|
31
31
|
},
|
package/src/resource.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { AppError, Env, FileLoader } from '@travetto/base';
|
|
2
|
+
import { RuntimeIndex } from '@travetto/manifest';
|
|
3
|
+
|
|
4
|
+
/** Build a resource loader that looks into a module and it's dependencies */
|
|
5
|
+
export class EmailResourceLoader extends FileLoader {
|
|
6
|
+
constructor(module: string, globalResources?: string[]) {
|
|
7
|
+
const mod = RuntimeIndex.getModule(module);
|
|
8
|
+
if (!mod) {
|
|
9
|
+
throw new AppError(`Unknown module - ${module}`, 'notfound', { module });
|
|
10
|
+
}
|
|
11
|
+
super([
|
|
12
|
+
...Env.TRV_RESOURCES.list ?? [],
|
|
13
|
+
`${module}#resources`,
|
|
14
|
+
...RuntimeIndex.getDependentModules(mod, 'children').map(x => `${x.name}#resources`),
|
|
15
|
+
'@@#resources',
|
|
16
|
+
...globalResources ?? []
|
|
17
|
+
]);
|
|
18
|
+
}
|
|
19
|
+
}
|
package/src/service.ts
CHANGED
|
@@ -90,6 +90,17 @@ export class MailService {
|
|
|
90
90
|
final.attachments = [...attachments, ...(final.attachments ?? [])];
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
+
// Disable threading if desired, provide a unique message id and a unique reply-to
|
|
94
|
+
if ('disableThreading' in message && message.disableThreading) {
|
|
95
|
+
const id = MailUtil.buildUniqueMessageId(message);
|
|
96
|
+
final.headers = {
|
|
97
|
+
'In-Reply-To': id,
|
|
98
|
+
References: id,
|
|
99
|
+
'X-Message-Id': id,
|
|
100
|
+
...final.headers
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
|
|
93
104
|
return this.#transport.send<S>(final);
|
|
94
105
|
}
|
|
95
106
|
|
package/src/types.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { FileLoader } from '@travetto/base';
|
|
1
2
|
import { Readable } from 'node:stream';
|
|
2
3
|
import { Url } from 'node:url';
|
|
3
4
|
|
|
@@ -33,6 +34,9 @@ export interface EmailAttachment extends AttachmentLike {
|
|
|
33
34
|
|
|
34
35
|
type EmailContentType = 'html' | 'text' | 'subject';
|
|
35
36
|
|
|
37
|
+
export type EmailIdentity = string | EmailAddress;
|
|
38
|
+
export type EmailIdentityList = EmailIdentity | EmailIdentity[];
|
|
39
|
+
|
|
36
40
|
/**
|
|
37
41
|
* Full message options
|
|
38
42
|
*/
|
|
@@ -42,13 +46,15 @@ export interface EmailOptions {
|
|
|
42
46
|
subject: string;
|
|
43
47
|
context?: Record<string, unknown>; // For templating
|
|
44
48
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
49
|
+
disableThreading?: boolean;
|
|
50
|
+
|
|
51
|
+
from?: EmailIdentity;
|
|
52
|
+
sender?: EmailIdentity;
|
|
53
|
+
to?: EmailIdentityList;
|
|
54
|
+
cc?: EmailIdentityList;
|
|
55
|
+
bcc?: EmailIdentityList;
|
|
56
|
+
replyTo?: EmailIdentity;
|
|
57
|
+
inReplyTo?: EmailIdentity;
|
|
52
58
|
references?: string | string[];
|
|
53
59
|
headers?: Record<string, string | string[]>;
|
|
54
60
|
attachments?: EmailAttachment[];
|
|
@@ -65,20 +71,15 @@ export type SentEmail = {
|
|
|
65
71
|
export type EmailCompiled = Record<EmailContentType, string>;
|
|
66
72
|
|
|
67
73
|
// Compilation support, defined here to allow for templates to not have a direct dependency on the compiler
|
|
68
|
-
type
|
|
69
|
-
|
|
70
|
-
|
|
74
|
+
export type EmailTemplateResource = {
|
|
75
|
+
loader: FileLoader;
|
|
76
|
+
inlineStyle?: boolean;
|
|
77
|
+
inlineImages?: boolean;
|
|
78
|
+
globalStyles?: string;
|
|
71
79
|
};
|
|
72
80
|
|
|
73
|
-
|
|
74
|
-
export type EmailTemplateImageConfig = BaseTemplateConfig & {};
|
|
75
|
-
|
|
76
|
-
export type EmailTemplateConfig = {
|
|
77
|
-
styles?: EmailTemplateStyleConfig;
|
|
78
|
-
images?: EmailTemplateImageConfig;
|
|
79
|
-
};
|
|
81
|
+
type EmailTemplateContent = Record<EmailContentType, () => (Promise<string> | string)>;
|
|
80
82
|
|
|
81
83
|
export type EmailTemplateLocation = { file: string, module: string };
|
|
82
|
-
export type
|
|
83
|
-
export type
|
|
84
|
-
export type EmailCompileContext = EmailTemplateLocation & EmailCompileSource;
|
|
84
|
+
export type EmailTemplateModule = EmailTemplateResource & EmailTemplateContent;
|
|
85
|
+
export type EmailTemplateImport = { prepare(loc: EmailTemplateLocation): Promise<EmailTemplateModule> };
|
package/src/util.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { RuntimeContext } from '@travetto/manifest';
|
|
2
2
|
|
|
3
|
-
import { EmailAttachment } from './types';
|
|
3
|
+
import { EmailAttachment, EmailIdentity, EmailIdentityList, EmailOptions } from './types';
|
|
4
|
+
import { Util } from '@travetto/base';
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Utilities for email
|
|
@@ -57,4 +58,27 @@ export class MailUtil {
|
|
|
57
58
|
html, attachments
|
|
58
59
|
};
|
|
59
60
|
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Get the primary email, if set from an email identity or identity list
|
|
64
|
+
*/
|
|
65
|
+
static getPrimaryEmail(src?: EmailIdentity | EmailIdentityList): string | undefined {
|
|
66
|
+
if (!src) {
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
if (Array.isArray(src)) {
|
|
70
|
+
src = src[0];
|
|
71
|
+
}
|
|
72
|
+
return (typeof src === 'string') ? src : src.address;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Build a unique message id
|
|
77
|
+
*/
|
|
78
|
+
static buildUniqueMessageId(message: EmailOptions): string {
|
|
79
|
+
const from = this.getPrimaryEmail(message.from)!;
|
|
80
|
+
const to = this.getPrimaryEmail(message.to)!;
|
|
81
|
+
const uid = Util.shortHash(`${to}${from}${message.subject}${Date.now()}`).substring(0, 12);
|
|
82
|
+
return `<${uid}@${from.split('@')[1]}>`;
|
|
83
|
+
}
|
|
60
84
|
}
|