mirror of
https://github.com/BradNut/TofuStack
synced 2025-09-08 17:40:26 +00:00
updated mailer configs
This commit is contained in:
parent
6390f8e19a
commit
fca1a2444a
5 changed files with 142 additions and 89 deletions
32
src/lib/server/api/emails/email-change-notice.email.ts
Normal file
32
src/lib/server/api/emails/email-change-notice.email.ts
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
import type { Email } from "../interfaces/email.interface";
|
||||||
|
|
||||||
|
export class EmailChangeNoticeEmail implements Email {
|
||||||
|
constructor() { }
|
||||||
|
|
||||||
|
subject(): string {
|
||||||
|
return 'Email Change Notice'
|
||||||
|
}
|
||||||
|
|
||||||
|
html() {
|
||||||
|
return /*html*/ `
|
||||||
|
<html lang='en'>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv='X-UA-Compatible' content='IE=edge' />
|
||||||
|
<meta name='viewport' content='width=device-width, initial-scale=1.0' />
|
||||||
|
<title>Email Change Request</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p class='title'>Email address change notice </p>
|
||||||
|
<p>
|
||||||
|
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>
|
||||||
|
</body>
|
||||||
|
<style>
|
||||||
|
.title { font-size: 24px; font-weight: 700; } .token-text { font-size: 24px; font-weight: 700; margin-top: 8px; }
|
||||||
|
.token-title { font-size: 18px; font-weight: 700; margin-bottom: 0px; }
|
||||||
|
.center { display: flex; justify-content: center; align-items: center; flex-direction: column;}
|
||||||
|
.token-subtext { font-size: 12px; margin-top: 0px; }
|
||||||
|
</style>
|
||||||
|
</html>
|
||||||
|
`
|
||||||
|
}
|
||||||
|
}
|
||||||
39
src/lib/server/api/emails/login-verification.email.ts
Normal file
39
src/lib/server/api/emails/login-verification.email.ts
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
import type { Email } from "../interfaces/email.interface";
|
||||||
|
|
||||||
|
export class LoginVerificationEmail implements Email {
|
||||||
|
constructor(private readonly token: string) { }
|
||||||
|
|
||||||
|
subject(): string {
|
||||||
|
return 'Email Verification'
|
||||||
|
}
|
||||||
|
|
||||||
|
html() {
|
||||||
|
return /*html*/ `
|
||||||
|
<html lang='en'>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv='X-UA-Compatible' content='IE=edge' />
|
||||||
|
<meta name='viewport' content='width=device-width, initial-scale=1.0' />
|
||||||
|
<title>Message</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p class='title'>Verify your email address</p>
|
||||||
|
<p>
|
||||||
|
Thanks for using example.com. We want to make sure it's really you. Please enter the following
|
||||||
|
verification code when prompted. If you don't have an exmaple.com an account, you can ignore
|
||||||
|
this message.</p>
|
||||||
|
<div class='center'>
|
||||||
|
<p class='token-title'>Verification Code</p>
|
||||||
|
<p class='token-text'>${this.token}</p>
|
||||||
|
<p class='token-subtext'>(This code is valid for 15 minutes)</p>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
<style>
|
||||||
|
.title { font-size: 24px; font-weight: 700; } .token-text { font-size: 24px; font-weight: 700;
|
||||||
|
margin-top: 8px; } .token-title { font-size: 18px; font-weight: 700; margin-bottom: 0px; }
|
||||||
|
.center { display: flex; justify-content: center; align-items: center; flex-direction: column;}
|
||||||
|
.token-subtext { font-size: 12px; margin-top: 0px; }
|
||||||
|
</style>
|
||||||
|
</html>
|
||||||
|
`
|
||||||
|
}
|
||||||
|
}
|
||||||
35
src/lib/server/api/emails/welcome.email.ts
Normal file
35
src/lib/server/api/emails/welcome.email.ts
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
import type { Email } from '../interfaces/email.interface';
|
||||||
|
|
||||||
|
export class WelcomeEmail implements Email {
|
||||||
|
constructor() { }
|
||||||
|
|
||||||
|
subject(): string {
|
||||||
|
return 'Welcome!'
|
||||||
|
}
|
||||||
|
|
||||||
|
html(): string {
|
||||||
|
return /*html*/ `
|
||||||
|
<html lang='en'>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv='X-UA-Compatible' content='IE=edge' />
|
||||||
|
<meta name='viewport' content='width=device-width, initial-scale=1.0' />
|
||||||
|
<title>Message</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p class='title'>Welcome to Example</p>
|
||||||
|
<p>
|
||||||
|
Thanks for using example.com. We want to make sure it's really you. Please enter the following
|
||||||
|
verification code when prompted. If you don't have an exmaple.com an account, you can ignore
|
||||||
|
this message.</p>
|
||||||
|
</body>
|
||||||
|
<style>
|
||||||
|
.title { font-size: 24px; font-weight: 700; } .token-text { font-size: 24px; font-weight: 700;
|
||||||
|
margin-top: 8px; } .token-title { font-size: 18px; font-weight: 700; margin-bottom: 0px; }
|
||||||
|
.center { display: flex; justify-content: center; align-items: center; flex-direction: column;}
|
||||||
|
.token-subtext { font-size: 12px; margin-top: 0px; }
|
||||||
|
</style>
|
||||||
|
</html>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
7
src/lib/server/api/interfaces/email.interface.ts
Normal file
7
src/lib/server/api/interfaces/email.interface.ts
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export interface Email {
|
||||||
|
subject(): string
|
||||||
|
html(): string;
|
||||||
|
}
|
||||||
|
|
@ -1,42 +1,18 @@
|
||||||
import fs from 'fs';
|
|
||||||
import path from 'path';
|
|
||||||
import nodemailer from 'nodemailer';
|
import nodemailer from 'nodemailer';
|
||||||
import handlebars from 'handlebars';
|
|
||||||
import { fileURLToPath } from 'url';
|
|
||||||
import { injectable } from 'tsyringe';
|
import { injectable } from 'tsyringe';
|
||||||
|
import type { Email } from '../interfaces/email.interface';
|
||||||
|
import { config } from '../common/config';
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
|
||||||
/* Service */
|
|
||||||
/* -------------------------------------------------------------------------- */
|
|
||||||
/* -------------------------------------------------------------------------- */
|
|
||||||
/* ---------------------------------- About --------------------------------- */
|
|
||||||
/*
|
|
||||||
Services are responsible for handling business logic and data manipulation.
|
|
||||||
They genreally call on repositories or other services to complete a use-case.
|
|
||||||
*/
|
|
||||||
/* ---------------------------------- Notes --------------------------------- */
|
|
||||||
/*
|
|
||||||
Services should be kept as clean and simple as possible.
|
|
||||||
|
|
||||||
Create private functions to handle complex logic and keep the public methods as
|
type SendProps = {
|
||||||
simple as possible. This makes the service easier to read, test and understand.
|
|
||||||
*/
|
|
||||||
/* -------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
type SendMail = {
|
|
||||||
to: string | string[];
|
to: string | string[];
|
||||||
subject: string;
|
email: Email;
|
||||||
html: string;
|
}
|
||||||
};
|
|
||||||
|
|
||||||
type SendTemplate<T> = {
|
|
||||||
to: string | string[];
|
|
||||||
props: T;
|
|
||||||
};
|
|
||||||
|
|
||||||
@injectable()
|
@injectable()
|
||||||
export class MailerService {
|
export class MailerService {
|
||||||
private nodemailer = nodemailer.createTransport({
|
private async sendDev({ to, email }: SendProps) {
|
||||||
|
const message = await nodemailer.createTransport({
|
||||||
host: 'smtp.ethereal.email',
|
host: 'smtp.ethereal.email',
|
||||||
port: 587,
|
port: 587,
|
||||||
secure: false, // Use `true` for port 465, `false` for all other ports
|
secure: false, // Use `true` for port 465, `false` for all other ports
|
||||||
|
|
@ -44,61 +20,25 @@ export class MailerService {
|
||||||
user: 'adella.hoppe@ethereal.email',
|
user: 'adella.hoppe@ethereal.email',
|
||||||
pass: 'dshNQZYhATsdJ3ENke'
|
pass: 'dshNQZYhATsdJ3ENke'
|
||||||
}
|
}
|
||||||
});
|
}).sendMail({
|
||||||
|
from: '"Example" <example@ethereal.email>',
|
||||||
sendEmailVerificationToken(data: SendTemplate<{ token: string }>) {
|
|
||||||
const template = handlebars.compile(this.getTemplate('email-verification-token'));
|
|
||||||
return this.send({
|
|
||||||
to: data.to,
|
|
||||||
subject: 'Email Verification',
|
|
||||||
html: template({ token: data.props.token })
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
sendEmailChangeNotification(data: SendTemplate<null>) {
|
|
||||||
const template = handlebars.compile(this.getTemplate('email-change-notice'));
|
|
||||||
return this.send({
|
|
||||||
to: data.to,
|
|
||||||
subject: 'Email Change Notice',
|
|
||||||
html: template(null)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
sendLoginRequest(data: SendTemplate<{ token: string }>) {
|
|
||||||
const template = handlebars.compile(this.getTemplate('email-verification-token'));
|
|
||||||
return this.send({
|
|
||||||
to: data.to,
|
|
||||||
subject: 'Login Request',
|
|
||||||
html: template({ token: data.props.token })
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
sendWelcome(data: SendTemplate<null>) {
|
|
||||||
const template = handlebars.compile(this.getTemplate('welcome'));
|
|
||||||
return this.send({
|
|
||||||
to: data.to,
|
|
||||||
subject: 'Welcome!',
|
|
||||||
html: template(null)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private async send({ to, subject, html }: SendMail) {
|
|
||||||
const message = await this.nodemailer.sendMail({
|
|
||||||
from: '"Example" <example@ethereal.email>', // sender address
|
|
||||||
bcc: to,
|
bcc: to,
|
||||||
subject, // Subject line
|
subject: email.subject(),
|
||||||
text: html,
|
text: email.html(),
|
||||||
html
|
html: email.html()
|
||||||
});
|
});
|
||||||
console.log(nodemailer.getTestMessageUrl(message));
|
console.log(nodemailer.getTestMessageUrl(message));
|
||||||
}
|
}
|
||||||
|
|
||||||
private getTemplate(template: string) {
|
private async sendProd({ to, email }: SendProps) {
|
||||||
const __filename = fileURLToPath(import.meta.url); // get the resolved path to the file
|
// CONFIGURE MAILER
|
||||||
const __dirname = path.dirname(__filename); // get the name of the directory
|
}
|
||||||
return fs.readFileSync(
|
|
||||||
path.join(__dirname, `../infrastructure/email-templates/${template}.hbs`),
|
async send({ to, email }: SendProps) {
|
||||||
'utf-8'
|
if (config.isProduction) {
|
||||||
);
|
await this.sendProd({ to, email });
|
||||||
|
} else {
|
||||||
|
await this.sendDev({ to, email });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue