Skip to content

Commit fca1a24

Browse files
committed
updated mailer configs
1 parent 6390f8e commit fca1a24

File tree

5 files changed

+142
-89
lines changed

5 files changed

+142
-89
lines changed
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import type { Email } from "../interfaces/email.interface";
2+
3+
export class EmailChangeNoticeEmail implements Email {
4+
constructor() { }
5+
6+
subject(): string {
7+
return 'Email Change Notice'
8+
}
9+
10+
html() {
11+
return /*html*/ `
12+
<html lang='en'>
13+
<head>
14+
<meta http-equiv='X-UA-Compatible' content='IE=edge' />
15+
<meta name='viewport' content='width=device-width, initial-scale=1.0' />
16+
<title>Email Change Request</title>
17+
</head>
18+
<body>
19+
<p class='title'>Email address change notice </p>
20+
<p>
21+
An update to your email address has been requested. If this is unexpected or you did not perform this action, please login and secure your account.</p>
22+
</body>
23+
<style>
24+
.title { font-size: 24px; font-weight: 700; } .token-text { font-size: 24px; font-weight: 700; margin-top: 8px; }
25+
.token-title { font-size: 18px; font-weight: 700; margin-bottom: 0px; }
26+
.center { display: flex; justify-content: center; align-items: center; flex-direction: column;}
27+
.token-subtext { font-size: 12px; margin-top: 0px; }
28+
</style>
29+
</html>
30+
`
31+
}
32+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import type { Email } from "../interfaces/email.interface";
2+
3+
export class LoginVerificationEmail implements Email {
4+
constructor(private readonly token: string) { }
5+
6+
subject(): string {
7+
return 'Email Verification'
8+
}
9+
10+
html() {
11+
return /*html*/ `
12+
<html lang='en'>
13+
<head>
14+
<meta http-equiv='X-UA-Compatible' content='IE=edge' />
15+
<meta name='viewport' content='width=device-width, initial-scale=1.0' />
16+
<title>Message</title>
17+
</head>
18+
<body>
19+
<p class='title'>Verify your email address</p>
20+
<p>
21+
Thanks for using example.com. We want to make sure it's really you. Please enter the following
22+
verification code when prompted. If you don't have an exmaple.com an account, you can ignore
23+
this message.</p>
24+
<div class='center'>
25+
<p class='token-title'>Verification Code</p>
26+
<p class='token-text'>${this.token}</p>
27+
<p class='token-subtext'>(This code is valid for 15 minutes)</p>
28+
</div>
29+
</body>
30+
<style>
31+
.title { font-size: 24px; font-weight: 700; } .token-text { font-size: 24px; font-weight: 700;
32+
margin-top: 8px; } .token-title { font-size: 18px; font-weight: 700; margin-bottom: 0px; }
33+
.center { display: flex; justify-content: center; align-items: center; flex-direction: column;}
34+
.token-subtext { font-size: 12px; margin-top: 0px; }
35+
</style>
36+
</html>
37+
`
38+
}
39+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import type { Email } from '../interfaces/email.interface';
2+
3+
export class WelcomeEmail implements Email {
4+
constructor() { }
5+
6+
subject(): string {
7+
return 'Welcome!'
8+
}
9+
10+
html(): string {
11+
return /*html*/ `
12+
<html lang='en'>
13+
<head>
14+
<meta http-equiv='X-UA-Compatible' content='IE=edge' />
15+
<meta name='viewport' content='width=device-width, initial-scale=1.0' />
16+
<title>Message</title>
17+
</head>
18+
<body>
19+
<p class='title'>Welcome to Example</p>
20+
<p>
21+
Thanks for using example.com. We want to make sure it's really you. Please enter the following
22+
verification code when prompted. If you don't have an exmaple.com an account, you can ignore
23+
this message.</p>
24+
</body>
25+
<style>
26+
.title { font-size: 24px; font-weight: 700; } .token-text { font-size: 24px; font-weight: 700;
27+
margin-top: 8px; } .token-title { font-size: 18px; font-weight: 700; margin-bottom: 0px; }
28+
.center { display: flex; justify-content: center; align-items: center; flex-direction: column;}
29+
.token-subtext { font-size: 12px; margin-top: 0px; }
30+
</style>
31+
</html>
32+
`;
33+
}
34+
}
35+
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
2+
3+
4+
export interface Email {
5+
subject(): string
6+
html(): string;
7+
}
Lines changed: 29 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -1,104 +1,44 @@
1-
import fs from 'fs';
2-
import path from 'path';
31
import nodemailer from 'nodemailer';
4-
import handlebars from 'handlebars';
5-
import { fileURLToPath } from 'url';
62
import { injectable } from 'tsyringe';
3+
import type { Email } from '../interfaces/email.interface';
4+
import { config } from '../common/config';
75

8-
/* -------------------------------------------------------------------------- */
9-
/* Service */
10-
/* -------------------------------------------------------------------------- */
11-
/* -------------------------------------------------------------------------- */
12-
/* ---------------------------------- About --------------------------------- */
13-
/*
14-
Services are responsible for handling business logic and data manipulation.
15-
They genreally call on repositories or other services to complete a use-case.
16-
*/
17-
/* ---------------------------------- Notes --------------------------------- */
18-
/*
19-
Services should be kept as clean and simple as possible.
206

21-
Create private functions to handle complex logic and keep the public methods as
22-
simple as possible. This makes the service easier to read, test and understand.
23-
*/
24-
/* -------------------------------------------------------------------------- */
25-
26-
type SendMail = {
27-
to: string | string[];
28-
subject: string;
29-
html: string;
30-
};
31-
32-
type SendTemplate<T> = {
7+
type SendProps = {
338
to: string | string[];
34-
props: T;
35-
};
9+
email: Email;
10+
}
3611

3712
@injectable()
3813
export class MailerService {
39-
private nodemailer = nodemailer.createTransport({
40-
host: 'smtp.ethereal.email',
41-
port: 587,
42-
secure: false, // Use `true` for port 465, `false` for all other ports
43-
auth: {
44-
45-
pass: 'dshNQZYhATsdJ3ENke'
46-
}
47-
});
48-
49-
sendEmailVerificationToken(data: SendTemplate<{ token: string }>) {
50-
const template = handlebars.compile(this.getTemplate('email-verification-token'));
51-
return this.send({
52-
to: data.to,
53-
subject: 'Email Verification',
54-
html: template({ token: data.props.token })
55-
});
56-
}
57-
58-
sendEmailChangeNotification(data: SendTemplate<null>) {
59-
const template = handlebars.compile(this.getTemplate('email-change-notice'));
60-
return this.send({
61-
to: data.to,
62-
subject: 'Email Change Notice',
63-
html: template(null)
64-
});
65-
}
66-
67-
sendLoginRequest(data: SendTemplate<{ token: string }>) {
68-
const template = handlebars.compile(this.getTemplate('email-verification-token'));
69-
return this.send({
70-
to: data.to,
71-
subject: 'Login Request',
72-
html: template({ token: data.props.token })
73-
});
74-
}
75-
76-
sendWelcome(data: SendTemplate<null>) {
77-
const template = handlebars.compile(this.getTemplate('welcome'));
78-
return this.send({
79-
to: data.to,
80-
subject: 'Welcome!',
81-
html: template(null)
82-
});
83-
}
84-
85-
private async send({ to, subject, html }: SendMail) {
86-
const message = await this.nodemailer.sendMail({
87-
from: '"Example" <[email protected]>', // sender address
14+
private async sendDev({ to, email }: SendProps) {
15+
const message = await nodemailer.createTransport({
16+
host: 'smtp.ethereal.email',
17+
port: 587,
18+
secure: false, // Use `true` for port 465, `false` for all other ports
19+
auth: {
20+
21+
pass: 'dshNQZYhATsdJ3ENke'
22+
}
23+
}).sendMail({
24+
from: '"Example" <[email protected]>',
8825
bcc: to,
89-
subject, // Subject line
90-
text: html,
91-
html
26+
subject: email.subject(),
27+
text: email.html(),
28+
html: email.html()
9229
});
9330
console.log(nodemailer.getTestMessageUrl(message));
9431
}
9532

96-
private getTemplate(template: string) {
97-
const __filename = fileURLToPath(import.meta.url); // get the resolved path to the file
98-
const __dirname = path.dirname(__filename); // get the name of the directory
99-
return fs.readFileSync(
100-
path.join(__dirname, `../infrastructure/email-templates/${template}.hbs`),
101-
'utf-8'
102-
);
33+
private async sendProd({ to, email }: SendProps) {
34+
// CONFIGURE MAILER
35+
}
36+
37+
async send({ to, email }: SendProps) {
38+
if (config.isProduction) {
39+
await this.sendProd({ to, email });
40+
} else {
41+
await this.sendDev({ to, email });
42+
}
10343
}
10444
}

0 commit comments

Comments
 (0)