@takaro/email 0.0.0-next.0da151e
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/config.d.ts +57 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +45 -0
- package/dist/config.js.map +1 -0
- package/dist/main.d.ts +3 -0
- package/dist/main.d.ts.map +1 -0
- package/dist/main.js +3 -0
- package/dist/main.js.map +1 -0
- package/dist/send.d.ts +8 -0
- package/dist/send.d.ts.map +1 -0
- package/dist/send.js +36 -0
- package/dist/send.js.map +1 -0
- package/dist/templates.d.ts +8 -0
- package/dist/templates.d.ts.map +1 -0
- package/dist/templates.js +12 -0
- package/dist/templates.js.map +1 -0
- package/package.json +14 -0
- package/src/config.ts +59 -0
- package/src/main.ts +3 -0
- package/src/send.ts +50 -0
- package/src/templates.ts +12 -0
- package/tsconfig.build.json +9 -0
- package/tsconfig.json +8 -0
- package/typedoc.json +3 -0
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { Config, IBaseConfig } from '@takaro/config';
|
|
2
|
+
export interface IMailConfig extends IBaseConfig {
|
|
3
|
+
mail: {
|
|
4
|
+
postmarkApiKey: string;
|
|
5
|
+
host: string;
|
|
6
|
+
port: number;
|
|
7
|
+
secure: boolean;
|
|
8
|
+
auth: {
|
|
9
|
+
user: string;
|
|
10
|
+
pass: string;
|
|
11
|
+
};
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
export declare const configSchema: {
|
|
15
|
+
mail: {
|
|
16
|
+
postmarkApiKey: {
|
|
17
|
+
doc: string;
|
|
18
|
+
format: StringConstructor;
|
|
19
|
+
default: string;
|
|
20
|
+
env: string;
|
|
21
|
+
};
|
|
22
|
+
host: {
|
|
23
|
+
doc: string;
|
|
24
|
+
format: StringConstructor;
|
|
25
|
+
default: string;
|
|
26
|
+
env: string;
|
|
27
|
+
};
|
|
28
|
+
port: {
|
|
29
|
+
doc: string;
|
|
30
|
+
format: NumberConstructor;
|
|
31
|
+
default: number;
|
|
32
|
+
env: string;
|
|
33
|
+
};
|
|
34
|
+
secure: {
|
|
35
|
+
doc: string;
|
|
36
|
+
format: BooleanConstructor;
|
|
37
|
+
default: boolean;
|
|
38
|
+
env: string;
|
|
39
|
+
};
|
|
40
|
+
auth: {
|
|
41
|
+
user: {
|
|
42
|
+
doc: string;
|
|
43
|
+
format: StringConstructor;
|
|
44
|
+
default: string;
|
|
45
|
+
env: string;
|
|
46
|
+
};
|
|
47
|
+
pass: {
|
|
48
|
+
doc: string;
|
|
49
|
+
format: StringConstructor;
|
|
50
|
+
default: string;
|
|
51
|
+
env: string;
|
|
52
|
+
};
|
|
53
|
+
};
|
|
54
|
+
};
|
|
55
|
+
};
|
|
56
|
+
export declare const config: Config<IMailConfig>;
|
|
57
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAErD,MAAM,WAAW,WAAY,SAAQ,WAAW;IAC9C,IAAI,EAAE;QACJ,cAAc,EAAE,MAAM,CAAC;QACvB,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,OAAO,CAAC;QAChB,IAAI,EAAE;YACJ,IAAI,EAAE,MAAM,CAAC;YACb,IAAI,EAAE,MAAM,CAAC;SACd,CAAC;KACH,CAAC;CACH;AAED,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyCxB,CAAC;AAEF,eAAO,MAAM,MAAM,qBAA0C,CAAC"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { Config } from '@takaro/config';
|
|
2
|
+
export const configSchema = {
|
|
3
|
+
mail: {
|
|
4
|
+
postmarkApiKey: {
|
|
5
|
+
doc: 'The API key for the Postmark mail service.',
|
|
6
|
+
format: String,
|
|
7
|
+
default: '',
|
|
8
|
+
env: 'MAIL_POSTMARK_API_KEY',
|
|
9
|
+
},
|
|
10
|
+
host: {
|
|
11
|
+
doc: 'The host of the mail server.',
|
|
12
|
+
format: String,
|
|
13
|
+
default: 'mailhog',
|
|
14
|
+
env: 'MAIL_HOST',
|
|
15
|
+
},
|
|
16
|
+
port: {
|
|
17
|
+
doc: 'The port of the mail server.',
|
|
18
|
+
format: Number,
|
|
19
|
+
default: 1025,
|
|
20
|
+
env: 'MAIL_PORT',
|
|
21
|
+
},
|
|
22
|
+
secure: {
|
|
23
|
+
doc: 'Whether to use TLS or not.',
|
|
24
|
+
format: Boolean,
|
|
25
|
+
default: false,
|
|
26
|
+
env: 'MAIL_SECURE',
|
|
27
|
+
},
|
|
28
|
+
auth: {
|
|
29
|
+
user: {
|
|
30
|
+
doc: 'The username to use for authentication.',
|
|
31
|
+
format: String,
|
|
32
|
+
default: 'test',
|
|
33
|
+
env: 'MAIL_USER',
|
|
34
|
+
},
|
|
35
|
+
pass: {
|
|
36
|
+
doc: 'The password to use for authentication.',
|
|
37
|
+
format: String,
|
|
38
|
+
default: 'test',
|
|
39
|
+
env: 'MAIL_PASS',
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
export const config = new Config([configSchema]);
|
|
45
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAe,MAAM,gBAAgB,CAAC;AAerD,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,IAAI,EAAE;QACJ,cAAc,EAAE;YACd,GAAG,EAAE,4CAA4C;YACjD,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE;YACX,GAAG,EAAE,uBAAuB;SAC7B;QACD,IAAI,EAAE;YACJ,GAAG,EAAE,8BAA8B;YACnC,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,SAAS;YAClB,GAAG,EAAE,WAAW;SACjB;QACD,IAAI,EAAE;YACJ,GAAG,EAAE,8BAA8B;YACnC,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,IAAI;YACb,GAAG,EAAE,WAAW;SACjB;QACD,MAAM,EAAE;YACN,GAAG,EAAE,4BAA4B;YACjC,MAAM,EAAE,OAAO;YACf,OAAO,EAAE,KAAK;YACd,GAAG,EAAE,aAAa;SACnB;QACD,IAAI,EAAE;YACJ,IAAI,EAAE;gBACJ,GAAG,EAAE,yCAAyC;gBAC9C,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,MAAM;gBACf,GAAG,EAAE,WAAW;aACjB;YACD,IAAI,EAAE;gBACJ,GAAG,EAAE,yCAAyC;gBAC9C,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,MAAM;gBACf,GAAG,EAAE,WAAW;aACjB;SACF;KACF;CACF,CAAC;AAEF,MAAM,CAAC,MAAM,MAAM,GAAG,IAAI,MAAM,CAAc,CAAC,YAAY,CAAC,CAAC,CAAC"}
|
package/dist/main.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC"}
|
package/dist/main.js
ADDED
package/dist/main.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC"}
|
package/dist/send.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { EMAIL_TEMPLATES } from './templates.js';
|
|
2
|
+
export interface ISendOptions {
|
|
3
|
+
address: string;
|
|
4
|
+
template: keyof typeof EMAIL_TEMPLATES;
|
|
5
|
+
data: Record<string, unknown>;
|
|
6
|
+
}
|
|
7
|
+
export declare function send(opts: ISendOptions): Promise<any>;
|
|
8
|
+
//# sourceMappingURL=send.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"send.d.ts","sourceRoot":"","sources":["../src/send.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAKjD,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,OAAO,eAAe,CAAC;IACvC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC/B;AAmBD,wBAAsB,IAAI,CAAC,IAAI,EAAE,YAAY,gBAmB5C"}
|
package/dist/send.js
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { errors, logger } from '@takaro/util';
|
|
2
|
+
import { createTransport } from 'nodemailer';
|
|
3
|
+
import { EMAIL_TEMPLATES } from './templates.js';
|
|
4
|
+
import { PostmarkTransport } from 'nodemailer-postmark-transport';
|
|
5
|
+
import { config } from './config.js';
|
|
6
|
+
const log = logger('email:send');
|
|
7
|
+
let transporter;
|
|
8
|
+
if (config.get('mail.postmarkApiKey')) {
|
|
9
|
+
log.info('Using Postmark as mail transport');
|
|
10
|
+
transporter = createTransport(new PostmarkTransport({
|
|
11
|
+
auth: {
|
|
12
|
+
apiKey: config.get('mail.postmarkApiKey'),
|
|
13
|
+
},
|
|
14
|
+
}));
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
log.info('Using SMTP as mail transport');
|
|
18
|
+
transporter = createTransport(config.get('mail'));
|
|
19
|
+
}
|
|
20
|
+
export async function send(opts) {
|
|
21
|
+
const template = EMAIL_TEMPLATES[opts.template];
|
|
22
|
+
if (!template) {
|
|
23
|
+
log.error(`Template ${opts.template} does not exist`);
|
|
24
|
+
throw new errors.InternalServerError();
|
|
25
|
+
}
|
|
26
|
+
const html = template.body(opts.data);
|
|
27
|
+
const result = await transporter.sendMail({
|
|
28
|
+
from: '"noreply@takaro.io" <noreply@takaro.io>',
|
|
29
|
+
to: opts.address,
|
|
30
|
+
subject: template.subject,
|
|
31
|
+
html,
|
|
32
|
+
});
|
|
33
|
+
log.info('Sent an email', { ...opts });
|
|
34
|
+
return result;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=send.js.map
|
package/dist/send.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"send.js","sourceRoot":"","sources":["../src/send.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAe,MAAM,YAAY,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAElE,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAQrC,MAAM,GAAG,GAAG,MAAM,CAAC,YAAY,CAAC,CAAC;AAEjC,IAAI,WAAwB,CAAC;AAC7B,IAAI,MAAM,CAAC,GAAG,CAAC,qBAAqB,CAAC,EAAE,CAAC;IACtC,GAAG,CAAC,IAAI,CAAC,kCAAkC,CAAC,CAAC;IAC7C,WAAW,GAAG,eAAe,CAC3B,IAAI,iBAAiB,CAAC;QACpB,IAAI,EAAE;YACJ,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,qBAAqB,CAAC;SAC1C;KACF,CAAC,CACH,CAAC;AACJ,CAAC;KAAM,CAAC;IACN,GAAG,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAC;IACzC,WAAW,GAAG,eAAe,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;AACpD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,IAAI,CAAC,IAAkB;IAC3C,MAAM,QAAQ,GAAG,eAAe,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAEhD,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,GAAG,CAAC,KAAK,CAAC,YAAY,IAAI,CAAC,QAAQ,iBAAiB,CAAC,CAAC;QACtD,MAAM,IAAI,MAAM,CAAC,mBAAmB,EAAE,CAAC;IACzC,CAAC;IAED,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAEtC,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,QAAQ,CAAC;QACxC,IAAI,EAAE,yCAAyC;QAC/C,EAAE,EAAE,IAAI,CAAC,OAAO;QAChB,OAAO,EAAE,QAAQ,CAAC,OAAO;QACzB,IAAI;KACL,CAAC,CAAC;IAEH,GAAG,CAAC,IAAI,CAAC,eAAe,EAAE,EAAE,GAAG,IAAI,EAAE,CAAC,CAAC;IACvC,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"templates.d.ts","sourceRoot":"","sources":["../src/templates.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,KAAK,CAAC;AAEtB,eAAO,MAAM,eAAe;;;;;CAS3B,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import ejs from 'ejs';
|
|
2
|
+
export const EMAIL_TEMPLATES = {
|
|
3
|
+
invite: {
|
|
4
|
+
subject: 'You have been invited to Takaro',
|
|
5
|
+
body: ejs.compile(`
|
|
6
|
+
<h1>You have been invited to Takaro.</h1>
|
|
7
|
+
|
|
8
|
+
<p>Click <a href="<%= inviteLink %>">here</a> to sign up.</p>
|
|
9
|
+
`),
|
|
10
|
+
},
|
|
11
|
+
};
|
|
12
|
+
//# sourceMappingURL=templates.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"templates.js","sourceRoot":"","sources":["../src/templates.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,KAAK,CAAC;AAEtB,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,MAAM,EAAE;QACN,OAAO,EAAE,iCAAiC;QAC1C,IAAI,EAAE,GAAG,CAAC,OAAO,CAAC;;;;OAIf,CAAC;KACL;CACF,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@takaro/email",
|
|
3
|
+
"version": "0.0.0-next.0da151e",
|
|
4
|
+
"description": "",
|
|
5
|
+
"main": "dist/main.js",
|
|
6
|
+
"types": "dist/main.d.ts",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"scripts": {
|
|
9
|
+
"start:dev": "tsc --watch --preserveWatchOutput -p ./tsconfig.build.json",
|
|
10
|
+
"build": "tsc -p ./tsconfig.build.json"
|
|
11
|
+
},
|
|
12
|
+
"author": "",
|
|
13
|
+
"license": "ISC"
|
|
14
|
+
}
|
package/src/config.ts
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { Config, IBaseConfig } from '@takaro/config';
|
|
2
|
+
|
|
3
|
+
export interface IMailConfig extends IBaseConfig {
|
|
4
|
+
mail: {
|
|
5
|
+
postmarkApiKey: string;
|
|
6
|
+
host: string;
|
|
7
|
+
port: number;
|
|
8
|
+
secure: boolean;
|
|
9
|
+
auth: {
|
|
10
|
+
user: string;
|
|
11
|
+
pass: string;
|
|
12
|
+
};
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const configSchema = {
|
|
17
|
+
mail: {
|
|
18
|
+
postmarkApiKey: {
|
|
19
|
+
doc: 'The API key for the Postmark mail service.',
|
|
20
|
+
format: String,
|
|
21
|
+
default: '',
|
|
22
|
+
env: 'MAIL_POSTMARK_API_KEY',
|
|
23
|
+
},
|
|
24
|
+
host: {
|
|
25
|
+
doc: 'The host of the mail server.',
|
|
26
|
+
format: String,
|
|
27
|
+
default: 'mailhog',
|
|
28
|
+
env: 'MAIL_HOST',
|
|
29
|
+
},
|
|
30
|
+
port: {
|
|
31
|
+
doc: 'The port of the mail server.',
|
|
32
|
+
format: Number,
|
|
33
|
+
default: 1025,
|
|
34
|
+
env: 'MAIL_PORT',
|
|
35
|
+
},
|
|
36
|
+
secure: {
|
|
37
|
+
doc: 'Whether to use TLS or not.',
|
|
38
|
+
format: Boolean,
|
|
39
|
+
default: false,
|
|
40
|
+
env: 'MAIL_SECURE',
|
|
41
|
+
},
|
|
42
|
+
auth: {
|
|
43
|
+
user: {
|
|
44
|
+
doc: 'The username to use for authentication.',
|
|
45
|
+
format: String,
|
|
46
|
+
default: 'test',
|
|
47
|
+
env: 'MAIL_USER',
|
|
48
|
+
},
|
|
49
|
+
pass: {
|
|
50
|
+
doc: 'The password to use for authentication.',
|
|
51
|
+
format: String,
|
|
52
|
+
default: 'test',
|
|
53
|
+
env: 'MAIL_PASS',
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export const config = new Config<IMailConfig>([configSchema]);
|
package/src/main.ts
ADDED
package/src/send.ts
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { errors, logger } from '@takaro/util';
|
|
2
|
+
import { createTransport, Transporter } from 'nodemailer';
|
|
3
|
+
import { EMAIL_TEMPLATES } from './templates.js';
|
|
4
|
+
import { PostmarkTransport } from 'nodemailer-postmark-transport';
|
|
5
|
+
|
|
6
|
+
import { config } from './config.js';
|
|
7
|
+
|
|
8
|
+
export interface ISendOptions {
|
|
9
|
+
address: string;
|
|
10
|
+
template: keyof typeof EMAIL_TEMPLATES;
|
|
11
|
+
data: Record<string, unknown>;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const log = logger('email:send');
|
|
15
|
+
|
|
16
|
+
let transporter: Transporter;
|
|
17
|
+
if (config.get('mail.postmarkApiKey')) {
|
|
18
|
+
log.info('Using Postmark as mail transport');
|
|
19
|
+
transporter = createTransport(
|
|
20
|
+
new PostmarkTransport({
|
|
21
|
+
auth: {
|
|
22
|
+
apiKey: config.get('mail.postmarkApiKey'),
|
|
23
|
+
},
|
|
24
|
+
}),
|
|
25
|
+
);
|
|
26
|
+
} else {
|
|
27
|
+
log.info('Using SMTP as mail transport');
|
|
28
|
+
transporter = createTransport(config.get('mail'));
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export async function send(opts: ISendOptions) {
|
|
32
|
+
const template = EMAIL_TEMPLATES[opts.template];
|
|
33
|
+
|
|
34
|
+
if (!template) {
|
|
35
|
+
log.error(`Template ${opts.template} does not exist`);
|
|
36
|
+
throw new errors.InternalServerError();
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const html = template.body(opts.data);
|
|
40
|
+
|
|
41
|
+
const result = await transporter.sendMail({
|
|
42
|
+
from: '"noreply@takaro.io" <noreply@takaro.io>',
|
|
43
|
+
to: opts.address,
|
|
44
|
+
subject: template.subject,
|
|
45
|
+
html,
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
log.info('Sent an email', { ...opts });
|
|
49
|
+
return result;
|
|
50
|
+
}
|
package/src/templates.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import ejs from 'ejs';
|
|
2
|
+
|
|
3
|
+
export const EMAIL_TEMPLATES = {
|
|
4
|
+
invite: {
|
|
5
|
+
subject: 'You have been invited to Takaro',
|
|
6
|
+
body: ejs.compile(`
|
|
7
|
+
<h1>You have been invited to Takaro.</h1>
|
|
8
|
+
|
|
9
|
+
<p>Click <a href="<%= inviteLink %>">here</a> to sign up.</p>
|
|
10
|
+
`),
|
|
11
|
+
},
|
|
12
|
+
};
|
package/tsconfig.json
ADDED
package/typedoc.json
ADDED