This commit is contained in:
Jonathan Barrow 2023-02-12 09:27:39 -05:00
commit 9801c8b59e
No known key found for this signature in database
GPG key ID: E86E9FE9049C741F
8 changed files with 460 additions and 5 deletions

View file

@ -0,0 +1,203 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" lang="en">
<html lang="en">
<head>
<meta name="color-scheme" content="light dark">
<meta http-equiv="Content-Type" content="text/html charset=UTF-8" />
<style>
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@400;700&display=swap');
:root {
color-scheme: light dark;
supported-color-schemes:light dark;
}
@media (prefers-color-scheme: light) {
body.email-body,
table.centerer,
table.wrapper {
background-color: #FFFFFF !important;
color: #FFFFFF !important;
}
table.card {
background-color: #673DB6 !important;
}
span.shoutout {
color: #D9C6FA !important;
}
td.confirm-link {
background-color: #9D6FF3 !important;
}
td.confirm-code {
background-color: #D9C6FA !important;
color: #45297A !important;
}
td.notice {
color: #9D6FF3 !important;
}
td.notice a {
color: #673DB6 !important;
}
img.logo {
content: url("https://assets.pretendo.cc/images/pretendo-wordmark-singlecolor-purple.png") !important;
}
}
@media (prefers-color-scheme: dark) {
body.email-body,
table.centerer,
table.wrapper {
background-color: #1B1F3B !important;
color: #FFFFFF !important;
}
table.card {
background-color: #23274A !important;
}
span.shoutout {
color: #CAB1FB !important;
}
td.confirm-link {
background-color: #673DB6 !important;
}
td.confirm-code {
background-color: #373C65 !important;
color: #ffffff !important;
}
td.notice {
color: #8990C1 !important;
}
td.notice a {
color: #CAC1F5 !important;
}
}
</style>
</head>
<body class="email-body" bgcolor="#1B1F3B" style="margin-left: 0; margin-right: 0; margin-top: 0; margin-bottom: 0; padding-left: 0; padding-right: 0; padding-top: 0; padding-bottom: 0; font-family: Poppins, Arial, Helvetica, sans-serif;">
<div style="display:none;">Hello {{username}}! Your Pretendo Network ID activation is almost complete. Please click the link in this email to confirm your e-mail address and complete the activation process.</div>
<table class="centerer" bgcolor="#1B1F3B" border="0" cellpadding="0" cellspacing="0" height="100%" width="100%">
<tr>
<td align="center">
<table class="wrapper" bgcolor="#1B1F3B" style="font-family: Poppins, Arial, Helvetica, sans-serif;" border="0" cellpadding="0" cellspacing="0" height="100%" width="420px">
<tr>
<td>
<table border="0" cellpadding="0" cellspacing="0" height="100%" width="100%">
<tr>
<td width="32px">&nbsp;</td>
<td>
<table border="0" cellpadding="0" cellspacing="0" height="100%" width="100%">
<tr>
<td height="36px" style="line-height: 36px;" width="100%">&nbsp;</td>
</tr>
<tr>
<td>
<table border="0" cellpadding="0" cellspacing="0" height="100%" width="100%">
<tr>
<td>
<a href="https://pretendo.network">
<img class="logo" width="auto" height="48px" src="https://assets.pretendo.cc/images/pretendo-wordmark-multicolor-purple+white.png" alt="Pretendo">
</a>
</td>
</tr>
<tr>
<td width="100%" height="36px" style="line-height: 36px;">&nbsp;</td>
</tr>
<tr>
<td>
<table class="card" bgcolor="#23274a" style="color: #ffffff; border-radius: 10px;" border="0" cellpadding="0" cellspacing="0" height="100%" width="100%">
<tr>
<td width="24px" height="100%">&nbsp;</td>
<td>
<table border="0" cellpadding="0" cellspacing="0" height="100%" width="100%">
<tr width="100%" height="48px" style="line-height: 48px;">
<td>&nbsp;</td>
</tr>
<tr style="font-size: 24px; font-weight: 700;">
<td>
Hello <span class="shoutout" style="color: #cab1fb;">{{username}}</span>!
</td>
</tr>
<tr>
<td width="100%" height="24px" style="line-height: 24px;">&nbsp;</td>
</tr>
<tr>
<td style="color: #ffffff; ">
Your Pretendo Network ID activation is almost complete. Please click the link below to confirm your e-mail address and complete the activation process.
</td>
</tr>
<tr>
<td width="100%" height="16px" style="line-height: 16px;">&nbsp;</td>
</tr>
<tr>
<td class="confirm-link" bgcolor="#673db6" style="font-size: 14px; font-weight: 700; border-radius: 10px; padding: 12px" align="center">
<a href="{{confirmation-href}}" style="text-decoration: none; color: #ffffff; " width="100%">
Confirm email address
</a>
</td>
</tr>
<tr>
<td width="100%" height="48px" style="line-height: 48px;">&nbsp;</td>
</tr>
<tr>
<td>
You may also enter the following 6-digit code on your console:
</td>
</tr>
<tr>
<td width="100%" height="16px" style="line-height: 16px;">&nbsp;</td>
</tr>
<tr>
<td class="confirm-code" bgcolor="#373c65" style="color: #ffffff; font-size: 14px; font-weight: 700; border-radius: 10px; padding: 12px" align="center">
{{confirmation-code}}
</td>
</tr>
<tr>
<td width="100%" height="48px" style="line-height: 48px;">&nbsp;</td>
</tr>
<tr>
<td>
We hope you have fun using our services!
</td>
</tr>
<tr>
<td width="100%" height="36px" style="line-height: 36px;">&nbsp;</td>
</tr>
<tr>
<td align="right">
The Pretendo Network team
</td>
</tr>
<tr>
<td width="100%" height="24px" style="line-height: 24px;">&nbsp;</td>
</tr>
</table>
</td>
<td width="24px" height="100%">&nbsp;</td>
</tr>
</table>
</td>
</tr>
<tr>
<td width="100%" height="18px" style="line-height: 18px;">&nbsp;</td>
</tr>
<tr>
<td class="notice" style="color: #8990c1; font-size: 12px;">
Note: this email message was auto-generated, please do not respond. For further assistance, please join our <a href="https://invite.gg/pretendo" style="text-decoration: none; color: #ffffff; ">Discord server</a>.
</td>
</tr>
<tr>
<td width="100%" height="48px" style="line-height: 48px;">&nbsp;</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
<td width="32px">&nbsp;</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>

View file

@ -0,0 +1,170 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" lang="en">
<html lang="en">
<head>
<meta name="color-scheme" content="light dark">
<meta http-equiv="Content-Type" content="text/html charset=UTF-8" />
<style>
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@400;700&display=swap');
:root {
color-scheme: light dark;
supported-color-schemes:light dark;
}
@media (prefers-color-scheme: light) {
body.email-body,
table.centerer,
table.wrapper {
background-color: #FFFFFF !important;
color: #FFFFFF !important;
}
table.card {
background-color: #673DB6 !important;
}
span.shoutout {
color: #D9C6FA !important;
}
td.confirm-link {
background-color: #9D6FF3 !important;
}
td.confirm-code {
background-color: #D9C6FA !important;
color: #45297A !important;
}
td.notice {
color: #9D6FF3 !important;
}
td.notice a {
color: #673DB6 !important;
}
img.logo {
content: url("https://assets.pretendo.cc/images/pretendo-wordmark-singlecolor-purple.png") !important;
}
}
@media (prefers-color-scheme: dark) {
body.email-body,
table.centerer,
table.wrapper {
background-color: #1B1F3B !important;
color: #FFFFFF !important;
}
table.card {
background-color: #23274A !important;
}
span.shoutout {
color: #CAB1FB !important;
}
td.confirm-link {
background-color: #673DB6 !important;
}
td.confirm-code {
background-color: #373C65 !important;
color: #ffffff !important;
}
td.notice {
color: #8990C1 !important;
}
td.notice a {
color: #CAC1F5 !important;
}
}
</style>
</head>
<body class="email-body" bgcolor="#1B1F3B" style="margin-left: 0; margin-right: 0; margin-top: 0; margin-bottom: 0; padding-left: 0; padding-right: 0; padding-top: 0; padding-bottom: 0; font-family: Poppins, Arial, Helvetica, sans-serif;">
<div style="display:none;">{{preview}}</div>
<table class="centerer" bgcolor="#1B1F3B" border="0" cellpadding="0" cellspacing="0" height="100%" width="100%">
<tr>
<td align="center">
<table class="wrapper" bgcolor="#1B1F3B" style="font-family: Poppins, Arial, Helvetica, sans-serif;" border="0" cellpadding="0" cellspacing="0" height="100%" width="420px">
<tr>
<td>
<table border="0" cellpadding="0" cellspacing="0" height="100%" width="100%">
<tr>
<td width="32px">&nbsp;</td>
<td>
<table border="0" cellpadding="0" cellspacing="0" height="100%" width="100%">
<tr>
<td height="36px" style="line-height: 36px;" width="100%">&nbsp;</td>
</tr>
<tr>
<td>
<table border="0" cellpadding="0" cellspacing="0" height="100%" width="100%">
<tr>
<td>
<a href="https://pretendo.network">
<img class="logo" width="auto" height="48px" src="https://assets.pretendo.cc/images/pretendo-wordmark-multicolor-purple+white.png" alt="Pretendo">
</a>
</td>
</tr>
<tr>
<td width="100%" height="36px" style="line-height: 36px;">&nbsp;</td>
</tr>
<tr>
<td>
<table class="card" bgcolor="#23274a" style="color: #ffffff; border-radius: 10px;" border="0" cellpadding="0" cellspacing="0" height="100%" width="100%">
<tr>
<td width="24px" height="100%">&nbsp;</td>
<td>
<table border="0" cellpadding="0" cellspacing="0" height="100%" width="100%">
<tr width="100%" height="48px" style="line-height: 48px;">
<td>&nbsp;</td>
</tr>
<tr style="font-size: 24px; font-weight: 700;">
<td>
Dear <span class="shoutout" style="color: #cab1fb;">{{username}}</span>,
</td>
</tr>
<tr>
<td width="100%" height="24px" style="line-height: 24px;">&nbsp;</td>
</tr>
<tr>
<td style="color: #ffffff; ">
{{paragraph}}
</td>
</tr>
<!--{{buttonPlaceholder}}-->
<tr>
<td width="100%" height="36px" style="line-height: 36px;">&nbsp;</td>
</tr>
<tr>
<td align="right">
The Pretendo Network team
</td>
</tr>
<tr>
<td width="100%" height="24px" style="line-height: 24px;">&nbsp;</td>
</tr>
</table>
</td>
<td width="24px" height="100%">&nbsp;</td>
</tr>
</table>
</td>
</tr>
<tr>
<td width="100%" height="18px" style="line-height: 18px;">&nbsp;</td>
</tr>
<tr>
<td class="notice" style="color: #8990c1; font-size: 12px;">
Note: this email message was auto-generated, please do not respond. For further assistance, please join our <a href="https://invite.gg/pretendo" style="text-decoration: none; color: #ffffff; ">Discord server</a>.
</td>
</tr>
<tr>
<td width="100%" height="48px" style="line-height: 48px;">&nbsp;</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
<td width="32px">&nbsp;</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

View file

@ -1,5 +1,9 @@
const nodemailer = require('nodemailer');
const { config, disabledFeatures } = require('./config-manager');
const path = require('path');
const fs = require("fs");
const genericEmailTemplate = fs.readFileSync(path.join(__dirname, './assets/emails/genericTemplate.html'), 'utf8');
const confirmationEmailTemplate = fs.readFileSync(path.join(__dirname, './assets/emails/confirmationTemplate.html'), 'utf8');
let transporter;
@ -7,11 +11,51 @@ if (!disabledFeatures.email) {
transporter = nodemailer.createTransport(config.email);
}
/**
@param {Object} options
@param {String} options.to The address to send the email to
@param {String} options.subject The subject of the email
@param {String} options.username The username of the user (shown in the greeting)
@param {String} options.preview The preview text of the email (shown in the inbox by the email client)
@param {String} options.text The text version of the email
@param {String} options.paragraph The main content of the email
@param {Object} options.confirmation Whether or not the email is a confirmation email
@param {String} options.confirmation.href The link to the confirmation page
@param {String} options.confirmation.code The confirmation code
@param {Object} options.link An object containing the link to be shown in the email
@param {String} options.link.href The URL of the link
@param {String} options.link.text The text of the link
*/
async function sendMail(options) {
if (!disabledFeatures.email) {
options.from = config.email.from;
const { to, subject, username, paragraph, preview, text, link, confirmation } = options;
let html = confirmation ? confirmationEmailTemplate : genericEmailTemplate;
await transporter.sendMail(options);
html = html.replace(/{{username}}/g, username);
html = html.replace(/{{paragraph}}/g, paragraph);
html = html.replace(/{{preview}}/g, (preview || ""));
html = html.replace(/{{confirmation-href}}/g, (confirmation?.href || ""));
html = html.replace(/{{confirmation-code}}/g, (confirmation?.code || ""));
if (link) {
const { href, text } = link;
const button = `<tr><td width="100%" height="16px" style="line-height: 16px;">&nbsp;</td></tr><tr><td class="confirm-link" bgcolor="#673db6" style="font-size: 14px; font-weight: 700; border-radius: 10px; padding: 12px" align="center"><a href="${href}" style="text-decoration: none; color: #ffffff; " width="100%">${text}</a></td></tr>`
html = html.replace(/<!--{{buttonPlaceholder}}-->/g, button);
}
await transporter.sendMail({
to,
subject,
text,
html
});
}
}

View file

@ -23,6 +23,7 @@ const nasc = require('./services/nasc');
const datastore = require('./services/datastore');
const api = require('./services/api');
const localcdn = require('./services/local-cdn');
const assets = require('./services/assets');
// START APPLICATION
@ -42,6 +43,7 @@ app.use(nasc);
app.use(datastore);
app.use(api);
app.use(localcdn);
app.use(assets);
// 404 handler
logger.info('Creating 404 status handler');

View file

@ -0,0 +1,22 @@
// handles serving assets
const express = require('express');
const subdomain = require('express-subdomain');
const logger = require('../../../logger');
const path = require('path');
// Router to handle the subdomain restriction
const assets = express.Router();
// Setup public folder
logger.info('[assets] Setting up public folder');
assets.use(express.static(path.join(__dirname, '../../assets')));
// Main router for endpoints
const router = express.Router();
// Create subdomains
logger.info('[conntest] Creating \'assets\' subdomain');
router.use(subdomain('assets', assets));
module.exports = router;

View file

@ -250,15 +250,23 @@ async function sendConfirmationEmail(pnid) {
await mailer.sendMail({
to: pnid.get('email.address'),
subject: '[Pretendo Network] Please confirm your email address',
html: `Hello,<br><br>Your Pretendo Network ID activation is almost complete.<br><br>Please click the link below to confirm your e-mail address and complete the activation process.<br><br>https://api.pretendo.cc/v1/email/verify?token=${pnid.get('identification.email_token')}<br><br>If you are unable to connect to the above URL, please enter the following confirmation code on the device to which your Prentendo Network ID is linked.<br><br>&lt;&lt;Confirmation code: ${pnid.get('identification.email_code')}&gt;&gt;`
username: pnid.get('username'),
confirmation: {
href: `https://api.pretendo.cc/v1/email/verify?token=${pnid.get('identification.email_token')}`,
code: pnid.get('identification.email_code')
},
text: `Hello ${pnid.get('username')}! \r\n\r\nYour Pretendo Network ID activation is almost complete. Please click the link to confirm your e-mail address and complete the activation process: \r\nhttps://api.pretendo.cc/v1/email/verify?token=${pnid.get('identification.email_token')} \r\n\r\nYou may also enter the following 6-digit code on your console: ${pnid.get('identification.email_code')}`
});
}
async function sendEmailConfirmedEmail(pnid) {
await mailer.sendMail({
to: pnid.get('email.address'),
subject: '[Pretendo Network] Email address confirmed',
html: 'Your email address has been confirmed!'
username: pnid.get('username'),
paragraph: 'your email address has been confirmed. We hope you have fun on Pretendo Network!',
text: `Dear ${pnid.get('username')}, \r\n\r\nYour email address has been confirmed. We hope you have fun on Pretendo Network!`
});
}
@ -285,7 +293,13 @@ async function sendForgotPasswordEmail(pnid) {
await mailer.sendMail({
to: pnid.get('email.address'),
subject: '[Pretendo Network] Forgot Password',
html: `Visit this link to reset your password ${config.website_base}/account/reset-password?token=${encodeURIComponent(passwordResetToken)}`
username: pnid.get('username'),
paragraph: 'a password reset has been requested from this account. If you did not request the password reset, please ignore this email. If you did request this password reset, please click the link below to reset your password.',
link: {
text: 'Reset password',
href: `${config.website_base}/account/reset-password?token=${encodeURIComponent(passwordResetToken)}`
},
text: `Dear ${pnid.get('username')}, a password reset has been requested from this account. \r\n\r\nIf you did not request the password reset, please ignore this email. \r\nIf you did request this password reset, please click the link to reset your password: ${config.website_base}/account/reset-password?token=${encodeURIComponent(passwordResetToken)}`
});
}