@takaro/email 0.0.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/dist/config.d.ts +49 -0
- package/dist/config.js +39 -0
- package/dist/config.js.map +1 -0
- package/dist/main.d.ts +2 -0
- package/dist/main.js +3 -0
- package/dist/main.js.map +1 -0
- package/dist/send.d.ts +8 -0
- package/dist/send.js +23 -0
- package/dist/send.js.map +1 -0
- package/dist/templates.d.ts +7 -0
- package/dist/templates.js +12 -0
- package/dist/templates.js.map +1 -0
- package/package.json +27 -0
- package/src/config.ts +52 -0
- package/src/main.ts +3 -0
- package/src/send.ts +35 -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,49 @@
|
|
|
1
|
+
import { Config, IBaseConfig } from '@takaro/config';
|
|
2
|
+
export interface IMailConfig extends IBaseConfig {
|
|
3
|
+
mail: {
|
|
4
|
+
host: string;
|
|
5
|
+
port: number;
|
|
6
|
+
secure: boolean;
|
|
7
|
+
auth: {
|
|
8
|
+
user: string;
|
|
9
|
+
pass: string;
|
|
10
|
+
};
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
export declare const configSchema: {
|
|
14
|
+
mail: {
|
|
15
|
+
host: {
|
|
16
|
+
doc: string;
|
|
17
|
+
format: StringConstructor;
|
|
18
|
+
default: string;
|
|
19
|
+
env: string;
|
|
20
|
+
};
|
|
21
|
+
port: {
|
|
22
|
+
doc: string;
|
|
23
|
+
format: NumberConstructor;
|
|
24
|
+
default: number;
|
|
25
|
+
env: string;
|
|
26
|
+
};
|
|
27
|
+
secure: {
|
|
28
|
+
doc: string;
|
|
29
|
+
format: BooleanConstructor;
|
|
30
|
+
default: boolean;
|
|
31
|
+
env: string;
|
|
32
|
+
};
|
|
33
|
+
auth: {
|
|
34
|
+
user: {
|
|
35
|
+
doc: string;
|
|
36
|
+
format: StringConstructor;
|
|
37
|
+
default: string;
|
|
38
|
+
env: string;
|
|
39
|
+
};
|
|
40
|
+
pass: {
|
|
41
|
+
doc: string;
|
|
42
|
+
format: StringConstructor;
|
|
43
|
+
default: string;
|
|
44
|
+
env: string;
|
|
45
|
+
};
|
|
46
|
+
};
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
export declare const config: Config<IMailConfig>;
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { Config } from '@takaro/config';
|
|
2
|
+
export const configSchema = {
|
|
3
|
+
mail: {
|
|
4
|
+
host: {
|
|
5
|
+
doc: 'The host of the mail server.',
|
|
6
|
+
format: String,
|
|
7
|
+
default: 'mailhog',
|
|
8
|
+
env: 'MAIL_HOST',
|
|
9
|
+
},
|
|
10
|
+
port: {
|
|
11
|
+
doc: 'The port of the mail server.',
|
|
12
|
+
format: Number,
|
|
13
|
+
default: 1025,
|
|
14
|
+
env: 'MAIL_PORT',
|
|
15
|
+
},
|
|
16
|
+
secure: {
|
|
17
|
+
doc: 'Whether to use TLS or not.',
|
|
18
|
+
format: Boolean,
|
|
19
|
+
default: false,
|
|
20
|
+
env: 'MAIL_SECURE',
|
|
21
|
+
},
|
|
22
|
+
auth: {
|
|
23
|
+
user: {
|
|
24
|
+
doc: 'The username to use for authentication.',
|
|
25
|
+
format: String,
|
|
26
|
+
default: 'test',
|
|
27
|
+
env: 'MAIL_USER',
|
|
28
|
+
},
|
|
29
|
+
pass: {
|
|
30
|
+
doc: 'The password to use for authentication.',
|
|
31
|
+
format: String,
|
|
32
|
+
default: 'test',
|
|
33
|
+
env: 'MAIL_PASS',
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
export const config = new Config([configSchema]);
|
|
39
|
+
//# 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;AAcrD,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,IAAI,EAAE;QACJ,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
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 const transporter: import("nodemailer").Transporter<import("nodemailer/lib/smtp-transport/index.js").SentMessageInfo>;
|
|
8
|
+
export declare function send(opts: ISendOptions): Promise<import("nodemailer/lib/smtp-transport/index.js").SentMessageInfo>;
|
package/dist/send.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { errors, logger } from '@takaro/util';
|
|
2
|
+
import { createTransport } from 'nodemailer';
|
|
3
|
+
import { EMAIL_TEMPLATES } from './templates.js';
|
|
4
|
+
import { config } from './config.js';
|
|
5
|
+
const log = logger('email:send');
|
|
6
|
+
export const transporter = createTransport(config.get('mail'));
|
|
7
|
+
export async function send(opts) {
|
|
8
|
+
const template = EMAIL_TEMPLATES[opts.template];
|
|
9
|
+
if (!template) {
|
|
10
|
+
log.error(`Template ${opts.template} does not exist`);
|
|
11
|
+
throw new errors.InternalServerError();
|
|
12
|
+
}
|
|
13
|
+
const html = template.body(opts.data);
|
|
14
|
+
const result = await transporter.sendMail({
|
|
15
|
+
from: '"noreply@takaro.io" <noreply@takaro.io>',
|
|
16
|
+
to: opts.address,
|
|
17
|
+
subject: template.subject,
|
|
18
|
+
html,
|
|
19
|
+
});
|
|
20
|
+
log.info('Sent an email', { ...opts });
|
|
21
|
+
return result;
|
|
22
|
+
}
|
|
23
|
+
//# 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;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEjD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAQrC,MAAM,GAAG,GAAG,MAAM,CAAC,YAAY,CAAC,CAAC;AACjC,MAAM,CAAC,MAAM,WAAW,GAAG,eAAe,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;AAE/D,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,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,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@takaro/email",
|
|
3
|
+
"version": "0.0.1",
|
|
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
|
+
"test": "npm run test:unit --if-present && npm run test:integration --if-present",
|
|
12
|
+
"test:unit": "echo 'No tests (yet :))'",
|
|
13
|
+
"test:integration": "echo 'No tests (yet :))'"
|
|
14
|
+
},
|
|
15
|
+
"author": "",
|
|
16
|
+
"license": "ISC",
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"@takaro/config": "0.0.1",
|
|
19
|
+
"@takaro/util": "0.0.1",
|
|
20
|
+
"ejs": "^3.1.9",
|
|
21
|
+
"nodemailer": "^6.9.3"
|
|
22
|
+
},
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"@types/ejs": "^3.1.2",
|
|
25
|
+
"@types/nodemailer": "^6.4.8"
|
|
26
|
+
}
|
|
27
|
+
}
|
package/src/config.ts
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { Config, IBaseConfig } from '@takaro/config';
|
|
2
|
+
|
|
3
|
+
export interface IMailConfig extends IBaseConfig {
|
|
4
|
+
mail: {
|
|
5
|
+
host: string;
|
|
6
|
+
port: number;
|
|
7
|
+
secure: boolean;
|
|
8
|
+
auth: {
|
|
9
|
+
user: string;
|
|
10
|
+
pass: string;
|
|
11
|
+
};
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export const configSchema = {
|
|
16
|
+
mail: {
|
|
17
|
+
host: {
|
|
18
|
+
doc: 'The host of the mail server.',
|
|
19
|
+
format: String,
|
|
20
|
+
default: 'mailhog',
|
|
21
|
+
env: 'MAIL_HOST',
|
|
22
|
+
},
|
|
23
|
+
port: {
|
|
24
|
+
doc: 'The port of the mail server.',
|
|
25
|
+
format: Number,
|
|
26
|
+
default: 1025,
|
|
27
|
+
env: 'MAIL_PORT',
|
|
28
|
+
},
|
|
29
|
+
secure: {
|
|
30
|
+
doc: 'Whether to use TLS or not.',
|
|
31
|
+
format: Boolean,
|
|
32
|
+
default: false,
|
|
33
|
+
env: 'MAIL_SECURE',
|
|
34
|
+
},
|
|
35
|
+
auth: {
|
|
36
|
+
user: {
|
|
37
|
+
doc: 'The username to use for authentication.',
|
|
38
|
+
format: String,
|
|
39
|
+
default: 'test',
|
|
40
|
+
env: 'MAIL_USER',
|
|
41
|
+
},
|
|
42
|
+
pass: {
|
|
43
|
+
doc: 'The password to use for authentication.',
|
|
44
|
+
format: String,
|
|
45
|
+
default: 'test',
|
|
46
|
+
env: 'MAIL_PASS',
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export const config = new Config<IMailConfig>([configSchema]);
|
package/src/main.ts
ADDED
package/src/send.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { errors, logger } from '@takaro/util';
|
|
2
|
+
import { createTransport } from 'nodemailer';
|
|
3
|
+
import { EMAIL_TEMPLATES } from './templates.js';
|
|
4
|
+
|
|
5
|
+
import { config } from './config.js';
|
|
6
|
+
|
|
7
|
+
export interface ISendOptions {
|
|
8
|
+
address: string;
|
|
9
|
+
template: keyof typeof EMAIL_TEMPLATES;
|
|
10
|
+
data: Record<string, unknown>;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const log = logger('email:send');
|
|
14
|
+
export const transporter = createTransport(config.get('mail'));
|
|
15
|
+
|
|
16
|
+
export async function send(opts: ISendOptions) {
|
|
17
|
+
const template = EMAIL_TEMPLATES[opts.template];
|
|
18
|
+
|
|
19
|
+
if (!template) {
|
|
20
|
+
log.error(`Template ${opts.template} does not exist`);
|
|
21
|
+
throw new errors.InternalServerError();
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const html = template.body(opts.data);
|
|
25
|
+
|
|
26
|
+
const result = await transporter.sendMail({
|
|
27
|
+
from: '"noreply@takaro.io" <noreply@takaro.io>',
|
|
28
|
+
to: opts.address,
|
|
29
|
+
subject: template.subject,
|
|
30
|
+
html,
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
log.info('Sent an email', { ...opts });
|
|
34
|
+
return result;
|
|
35
|
+
}
|
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