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 handlebars from 'handlebars';
|
||||
import { fileURLToPath } from 'url';
|
||||
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
|
||||
simple as possible. This makes the service easier to read, test and understand.
|
||||
*/
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
type SendMail = {
|
||||
type SendProps = {
|
||||
to: string | string[];
|
||||
subject: string;
|
||||
html: string;
|
||||
};
|
||||
|
||||
type SendTemplate<T> = {
|
||||
to: string | string[];
|
||||
props: T;
|
||||
};
|
||||
email: Email;
|
||||
}
|
||||
|
||||
@injectable()
|
||||
export class MailerService {
|
||||
private nodemailer = nodemailer.createTransport({
|
||||
private async sendDev({ to, email }: SendProps) {
|
||||
const message = await nodemailer.createTransport({
|
||||
host: 'smtp.ethereal.email',
|
||||
port: 587,
|
||||
secure: false, // Use `true` for port 465, `false` for all other ports
|
||||
|
|
@ -44,61 +20,25 @@ export class MailerService {
|
|||
user: 'adella.hoppe@ethereal.email',
|
||||
pass: 'dshNQZYhATsdJ3ENke'
|
||||
}
|
||||
});
|
||||
|
||||
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
|
||||
}).sendMail({
|
||||
from: '"Example" <example@ethereal.email>',
|
||||
bcc: to,
|
||||
subject, // Subject line
|
||||
text: html,
|
||||
html
|
||||
subject: email.subject(),
|
||||
text: email.html(),
|
||||
html: email.html()
|
||||
});
|
||||
console.log(nodemailer.getTestMessageUrl(message));
|
||||
}
|
||||
|
||||
private getTemplate(template: string) {
|
||||
const __filename = fileURLToPath(import.meta.url); // get the resolved path to the file
|
||||
const __dirname = path.dirname(__filename); // get the name of the directory
|
||||
return fs.readFileSync(
|
||||
path.join(__dirname, `../infrastructure/email-templates/${template}.hbs`),
|
||||
'utf-8'
|
||||
);
|
||||
private async sendProd({ to, email }: SendProps) {
|
||||
// CONFIGURE MAILER
|
||||
}
|
||||
|
||||
async send({ to, email }: SendProps) {
|
||||
if (config.isProduction) {
|
||||
await this.sendProd({ to, email });
|
||||
} else {
|
||||
await this.sendDev({ to, email });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue