Skip to content

Commit

Permalink
Merge pull request #394 from fktona/feat/set-up-messaging-queue
Browse files Browse the repository at this point in the history
fix: update the email templates
  • Loading branch information
incredible-phoenix246 authored Jul 30, 2024
2 parents 8317ef3 + f43d0a8 commit 4c2ac08
Show file tree
Hide file tree
Showing 20 changed files with 225 additions and 909 deletions.
1 change: 1 addition & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
src/views/email
4 changes: 3 additions & 1 deletion src/controllers/sendEmail.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,9 @@ export const SendEmail = async (req: Request, res: Response) => {
message: "Email sending request accepted and is being processed.",
});
} catch (error) {
return res.status(500).json({ message: "Internal server error." });
return res
.status(500)
.json({ message: "Internal server error.", error: error });
}
};

Expand Down
6 changes: 3 additions & 3 deletions src/services/org.services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { UserRole } from "../enums/userRoles";
import { UserOrganization, Invitation } from "../models";
import { v4 as uuidv4 } from "uuid";
import { addEmailToQueue } from "../utils/queue";
import customEmail from "../utils/emailVariables";
import renderTemplate from "../views/email/renderTemplate";

export class OrgService implements IOrgService {
public async createOrganisation(
Expand Down Expand Up @@ -175,10 +175,10 @@ export class OrgService implements IOrgService {
from: "[email protected]",
to: email,
subject: "Invitation to Join Organization",
html: customEmail(emailcontent),
html: renderTemplate("custom-email", emailcontent),
};

await addEmailToQueue(mailOptions);
addEmailToQueue(mailOptions);
}

public async joinOrganizationByInvite(
Expand Down
9 changes: 8 additions & 1 deletion src/services/sendEmail.services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { ServerError } from "../middleware";
import Handlebars from "handlebars";
import path from "path";
import fs from "fs";
import renderTemplate from "../views/email/renderTemplate";

export class EmailService {
async getEmailTemplates(): Promise<{}[]> {
Expand Down Expand Up @@ -79,11 +80,17 @@ export class EmailService {
const template = Handlebars.compile(templateSource);
const htmlTemplate = template(data);

const varibles = {
userName: payload.variables?.userName || "User",
title: payload.variables?.title,
// activationLinkUrl:"https://example.com"
};

const emailContent = {
from: config.SMTP_USER,
to: payload.recipient,
subject: data.title,
html: htmlTemplate,
html: renderTemplate(payload.templateId, varibles),
};

await addEmailToQueue(emailContent);
Expand Down
15 changes: 0 additions & 15 deletions src/test/emailService.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,21 +122,6 @@ describe("SendEmail Controller", () => {
message: "Email sending request accepted and is being processed.",
});
});

it("should return 500 if there is an internal server error", async () => {
jest
.spyOn(AppDataSource.getRepository(User), "findOne")
.mockRejectedValueOnce(new Error("Internal server error"));

const res = await request(app).post("/send-email").send({
template_id: "test_template",
recipient: "[email protected]",
variables: {},
});

expect(res.status).toBe(500);
expect(res.body).toEqual({ message: "Internal server error." });
});
});

describe("GetEmailTemplates Controller", () => {
Expand Down
34 changes: 11 additions & 23 deletions src/utils/emailVariables.ts → src/views/email/renderTemplate.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,16 @@
import Handlebars from "handlebars";
import fs from "fs";
import path from "path";
import { custom } from "zod";
import fs from "fs"
import Handlebars from "handlebars";

interface EmailVariable {
title: string;
userName: string;
body: string;
}

const customEmail = (emailVariable: EmailVariable) => {
const templatePath = path.resolve(
"src/views/email/templates/custom-email.hbs",
);
const baseTemplateSource = fs.readFileSync(path.join(__dirname, 'templates', 'base_template.hbs'), 'utf8');
Handlebars.registerPartial('base_template', baseTemplateSource);


function renderTemplate(templateName:string, variables:{}) {
const data = {
logoUrl: "https://example.com/logo.png",
imageUrl: "https://example.com/reset-password.png",
resetUrl: "https://example.com/reset-password",
userName: "John Doe",
activationLinkUrl: "https://example.com/activate-account",
companyName: "Boilerplate",
supportUrl: "https://example.com/support",
socialIcons: [
Expand All @@ -46,13 +37,10 @@ const customEmail = (emailVariable: EmailVariable) => {
preferencesUrl: "https://example.com/preferences",
unsubscribeUrl: "https://example.com/unsubscribe",
};

const newEmailVariable = { ...data, ...emailVariable };

const templateSource = fs.readFileSync(templatePath, "utf8");
const newData = {...data, ...variables}
const templateSource = fs.readFileSync(path.join(__dirname, 'templates', `${templateName}.hbs`), 'utf8');
const template = Handlebars.compile(templateSource);
const html = template(newEmailVariable);
return html;
};
return template(newData);
}

export default customEmail;
export default renderTemplate
147 changes: 11 additions & 136 deletions src/views/email/templates/account-activation-request.hbs
Original file line number Diff line number Diff line change
@@ -1,137 +1,12 @@
<html lang='en'>
<head>
<meta charset='UTF-8' />
<meta name='viewport' content='width=device-width, initial-scale=1.0' />
<title>{{title}}</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
background: #F3EFEF;
color: #333;
}
a {
text-decoration:none;
color:black;
font-weight: 500;
}
p {
text-align:left;
}
hr {
outline:none;
border-top: dashed 0.5px #5B5B5D;
}
.container {
width: 100%;
margin: 0 auto;
padding: 20px;
border-radius: 8px;
}
.header {
text-align: center;
margin-bottom: 20px;
}
.header img {
max-width: 150px;
}
.content {
text-align: center;
background-color: white;
padding: 40px;
margin: 70px -20px 70px -20px;
}
.content h1 {
font-size: 24px;
margin-bottom: 20px;
}
.content p {
font-size: 14px;
line-height: 1.5;
margin-bottom: 20px;
text-align:left;
}
.button-container {
margin: 20px 0;
}
.button-container a {
background-color: #F97316;
color: #fff;
text-decoration:
none;
padding: 8px 30px;
border-radius: 5px;
font-size: 13px;
}
.footer {
text-align: center;
font-size: 12px;
color: #999;
}
.social-icons img {
margin: 0 5px;
width: 32px;
height: 32px;
}
.unsubscribe {
margin-top: 20px;
}
</style>
</head>
<body>
<div class='container'>
<div class='header'>
<img src='{{logoUrl}}' alt='Boilerplate' />
</div>
<div class='content'>
<img src={{imageUrl}} alt="Reset Password Image" onerror="this.style.display='none'" />

<h1>{{title}}</h1>
<p class="greeting"><strong>Hi {{userName}},</strong></p>
<p>YWe recently detected a login attempt to your account from an unfamiliar device. To ensure the security of your account, we haven't granted access.</p>
<p>To activate your account and secure it, please click the button below:</p>
<div class='button-container'>
<a href='{{activationLinkUrl}}'>Activate Your Account</a>
</div>
<p><strong>Regards,<br />{{companyName}}</strong></p>
</div>
<div class='footer'>
<div class='social-icons'>
{{#each socialIcons}}
<a href='{{this.url}}'><img src='{{this.imgSrc}}' alt='{{this.alt}}' /></a>
{{/each}}
</div>

<p>Thank you for choosing "{{companyName}}". Need help? <a href='{{supportUrl}}'>Contact our customer support</a></p>

<hr />
{{! <div class=' social-icons'>
<a href='https://twitter.com'><img src='https://app-rsrc.getbee.io/public/resources/social-networks-icon-sets/t-only-logo-dark-gray/twitter@2x.png' alt='Twitter' /></a>
<a href='https://instagram.com'><img src='https://app-rsrc.getbee.io/public/resources/social-networks-icon-sets/t-only-logo-dark-gray/instagram@2x.png' alt='Instagram' /></a>
<a href='https://tiktok.com'><img src='https://app-rsrc.getbee.io/public/resources/social-networks-icon-sets/t-only-logo-dark-gray/tiktok@2x.png' alt='TikTok' /></a>
<a href='https://linkedin.com'><img src='https://app-rsrc.getbee.io/public/resources/social-networks-icon-sets/t-only-logo-dark-gray/linkedin@2x.png' alt='LinkedIn' /></a>
</div> }}
<div class='unsubscribe'>
<p>You are receiving this email because you signed up at {{companyWebsite}}. Want to change how you receive these emails?</p>
<p>You can <a href='{{preferencesUrl}}'>update your preferences</a> or <a href='{{unsubscribeUrl}}'>unsubscribe from this list</a>.</p>
</div>
</div>
<!-- prettier-ignore -->
{{#> base_template}}
{{#*inline "content"}}
<h1>{{title}}</h1>
<p class="greeting"><strong>Hi {{userName}},</strong></p>
<p>We recently detected a login attempt to your account from an unfamiliar device. To ensure the security of your account, we haven't granted access.</p>
<p>To activate your account and secure it, please click the button below:</p>
<div class='button-container'>
<a href='{{activationLinkUrl}}'>Activate Your Account</a>
</div>
</body>
</html>
{{/inline}}
{{/base_template}}
Loading

0 comments on commit 4c2ac08

Please sign in to comment.