diff --git a/assets/email_templates/new_login_location.html b/assets/email_templates/new_login_location.html
index 701196cd..e597ac6c 100644
--- a/assets/email_templates/new_login_location.html
+++ b/assets/email_templates/new_login_location.html
@@ -4,108 +4,108 @@
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
+ <meta http-equiv="Content-Type" content="text/html charset=UTF-8" />
<title>Verify {instanceName} Login from New Location</title>
<style>
* {
font-size: 16px;
line-height: 24px;
- }
- body {
- color: white;
font-family: Arial, Helvetica, sans-serif;
- background-color: #202225;
}
- .btn {
- font-size: 15px;
- border: none;
- border-radius: 3px;
- text-decoration: none;
+ p {
color: white;
- cursor: pointer;
- padding: 15px 19px;
- background-color: #ff5f00;
- border-radius: 5px;
- box-shadow: 0 0 10px rgba(255, 61, 0, 0.1);
}
- .btn:hover {
- background-color: hsl(22.4, 80%, 50%);
- }
- .btn:active {
- background-color: hsl(22.4, 60%, 50%);
+ .ExternalClass {
+ width: 100%;
}
</style>
</head>
<body>
- <img
- src="https://raw.githubusercontent.com/fosscord/fosscord/master/assets-rebrand/svg/Fosscord-Wordmark-Orange.svg"
- alt="Branding"
- style="
- width: 100%;
- max-width: 200px;
- margin: 0 auto;
- display: block;
- padding: 20px;
- "
- />
- <div
- style="
- width: 100%;
- max-width: 500px;
- margin: 0 auto;
- padding: 40px 50px;
- background-color: rgba(50, 53, 59, 1);
- border-radius: 5px;
- "
- >
- <p
+ <div style="background-color: #202225;">
+ <img
+ src="https://raw.githubusercontent.com/fosscord/fosscord/master/assets-rebrand/svg/Fosscord-Wordmark-Orange.svg"
+ alt="Branding"
style="
- font-weight: 600;
- font-size: 20px;
- letter-spacing: 0.27px;
- line-height: 24px;
+ width: 100%;
+ max-width: 200px;
+ margin: 0 auto;
+ display: block;
+ padding: 20px;
+ "
+ />
+ <div
+ style="
+ width: 100%;
+ max-width: 500px;
+ margin: 0 auto;
+ padding: 40px 50px;
+ background-color: #32353b;
+ border-radius: 5px;
"
>
- Hey {username},
- </p>
- <p>
- It looks like someone tried to log into your {instanceName}
- account from a new location. If this is you, follow the link
- below to authorize logging in from this location on your
- account. If this isn't you, we suggest changing your password as
- soon as possible.
- </p>
- <p>
- <strong>IP Address:</strong> {ip}
- <br />
- <strong>Location:</strong> {location}
- </p>
- <div>
- <div
+ <p
style="
- display: flex;
- justify-content: center;
- padding-bottom: 10px;
+ font-weight: 600;
+ font-size: 20px;
+ letter-spacing: 0.27px;
+ line-height: 24px;
"
>
- <a class="btn" href="{verifyUrl}" target="_blank"
- >Verify Login</a
+ Hey {userUsername},
+ </p>
+ <p>
+ It looks like someone tried to log into your {instanceName}
+ account from a new location. If this is you, follow the link
+ below to authorize logging in from this location on your
+ account. If this isn't you, we suggest changing your
+ password as soon as possible.
+ </p>
+ <p>
+ <strong>IP Address:</strong> {ipAddress}
+ <br />
+ <strong>Location:</strong> {locationCity}, {locationRegion},
+ {locationCountryName}
+ </p>
+ <div>
+ <div
+ style="
+ text-align: center;
+ justify-content: center;
+ padding-bottom: 10px;
+ "
>
- </div>
- <hr />
- <div
- style="
- display: flex;
- justify-content: center;
- flex-direction: column;
- text-align: center;
- "
- >
- <p>
- Alternatively, you can directly paste this link into
- your browser:
- </p>
- <a href="{verifyUrl}" target="_blank">{verifyUrl}</a>
+ <a
+ href="{verifyUrl}"
+ target="_blank"
+ style="
+ font-size: 15px;
+ border: none;
+ border-radius: 3px;
+ text-decoration: none;
+ color: white;
+ cursor: pointer;
+ padding: 15px 19px;
+ background-color: #ff5f00;
+ border-radius: 5px;
+ "
+ >Verify Login</a
+ >
+ </div>
+ <hr />
+ <div
+ style="
+ text-align: center;
+ justify-content: center;
+ padding-bottom: 10px;
+ "
+ >
+ <p>
+ Alternatively, you can directly paste this link into
+ your browser:
+ </p>
+ <a href="{verifyUrl}" target="_blank">{verifyUrl}</a>
+ </div>
</div>
</div>
</div>
diff --git a/assets/email_templates/password_changed.html b/assets/email_templates/password_changed.html
index 3f762702..399108a2 100644
--- a/assets/email_templates/password_changed.html
+++ b/assets/email_templates/password_changed.html
@@ -4,57 +4,62 @@
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
+ <meta http-equiv="Content-Type" content="text/html charset=UTF-8" />
<title>{instanceName} Password Changed</title>
<style>
* {
font-size: 16px;
line-height: 24px;
+ font-family: Arial, Helvetica, sans-serif;
}
- body {
+ p {
color: white;
- font-family: Arial, Helvetica, sans-serif;
- background-color: #202225;
+ }
+ .ExternalClass {
+ width: 100%;
}
</style>
</head>
<body>
- <img
- src="https://raw.githubusercontent.com/fosscord/fosscord/master/assets-rebrand/svg/Fosscord-Wordmark-Orange.svg"
- alt="Branding"
- style="
- width: 100%;
- max-width: 200px;
- margin: 0 auto;
- display: block;
- padding: 20px;
- "
- />
- <div
- style="
- width: 100%;
- max-width: 500px;
- margin: 0 auto;
- padding: 40px 50px;
- background-color: rgba(50, 53, 59, 1);
- border-radius: 5px;
- "
- >
- <p
+ <div style="background-color: #202225;">
+ <img
+ src="https://raw.githubusercontent.com/fosscord/fosscord/master/assets-rebrand/svg/Fosscord-Wordmark-Orange.svg"
+ alt="Branding"
+ style="
+ width: 100%;
+ max-width: 200px;
+ margin: 0 auto;
+ display: block;
+ padding: 20px;
+ "
+ />
+ <div
style="
- font-weight: 600;
- font-size: 20px;
- letter-spacing: 0.27px;
- line-height: 24px;
+ width: 100%;
+ max-width: 500px;
+ margin: 0 auto;
+ padding: 40px 50px;
+ background-color: #32353b;
+ border-radius: 5px;
"
>
- Hey {username},
- </p>
- <p>Your {instanceName} password has been changed.</p>
- <p>
- If this wasn't done by you, please immediately reset the
- password to your {instanceName} account.
- </p>
+ <p
+ style="
+ font-weight: 600;
+ font-size: 20px;
+ letter-spacing: 0.27px;
+ line-height: 24px;
+ "
+ >
+ Hey {userUsername},
+ </p>
+ <p>Your {instanceName} password has been changed.</p>
+ <p>
+ If this wasn't done by you, please immediately reset the
+ password to your {instanceName} account.
+ </p>
+ </div>
</div>
</body>
</html>
diff --git a/assets/email_templates/password_reset_request.html b/assets/email_templates/password_reset_request.html
index fc77b47b..ab8f4d23 100644
--- a/assets/email_templates/password_reset_request.html
+++ b/assets/email_templates/password_reset_request.html
@@ -4,103 +4,96 @@
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
+ <meta http-equiv="Content-Type" content="text/html charset=UTF-8" />
<title>Password Reset Request for {instanceName}</title>
<style>
* {
font-size: 16px;
line-height: 24px;
- }
- body {
- color: white;
font-family: Arial, Helvetica, sans-serif;
- background-color: #202225;
}
- .btn {
- font-size: 15px;
- border: none;
- border-radius: 3px;
- text-decoration: none;
+ p {
color: white;
- cursor: pointer;
- padding: 15px 19px;
- background-color: #ff5f00;
- border-radius: 5px;
- box-shadow: 0 0 10px rgba(255, 61, 0, 0.1);
}
- .btn:hover {
- background-color: hsl(22.4, 80%, 50%);
- }
- .btn:active {
- background-color: hsl(22.4, 60%, 50%);
+ .ExternalClass {
+ width: 100%;
}
</style>
</head>
<body>
- <img
- src="https://raw.githubusercontent.com/fosscord/fosscord/master/assets-rebrand/svg/Fosscord-Wordmark-Orange.svg"
- alt="Branding"
- style="
- width: 100%;
- max-width: 200px;
- margin: 0 auto;
- display: block;
- padding: 20px;
- "
- />
- <div
- style="
- width: 100%;
- max-width: 500px;
- margin: 0 auto;
- padding: 40px 50px;
- background-color: rgba(50, 53, 59, 1);
- border-radius: 5px;
- "
- >
- <p
+ <div style="background-color: #202225;">
+ <img
+ src="https://raw.githubusercontent.com/fosscord/fosscord/master/assets-rebrand/svg/Fosscord-Wordmark-Orange.svg"
+ alt="Branding"
style="
- font-weight: 600;
- font-size: 20px;
- letter-spacing: 0.27px;
- line-height: 24px;
+ width: 100%;
+ max-width: 200px;
+ margin: 0 auto;
+ display: block;
+ padding: 20px;
+ "
+ />
+ <div
+ style="
+ width: 100%;
+ max-width: 500px;
+ margin: 0 auto;
+ padding: 40px 50px;
+ background-color: #32353b;
+ border-radius: 5px;
"
>
- Hey {username},
- </p>
- <p>
- Your {instanceName} password can be reset by clicking the button
- below. If you did not request a new password, please ignore this
- email.
- </p>
- <div>
- <div
- style="
- display: flex;
- justify-content: center;
- padding-bottom: 10px;
- "
- >
- <a class="btn" href="{passwordResetUrl}" target="_blank"
- >Reset Password</a
- >
- </div>
- <hr />
- <div
+ <p
style="
- display: flex;
- justify-content: center;
- flex-direction: column;
- text-align: center;
+ font-weight: 600;
+ font-size: 20px;
+ letter-spacing: 0.27px;
+ line-height: 24px;
"
>
- <p>
- Alternatively, you can directly paste this link into
- your browser:
- </p>
- <a href="{passwordResetUrl}" target="_blank"
- >{passwordResetUrl}</a
+ Hey {userUsername},
+ </p>
+ <p>
+ Your {instanceName} password can be reset by clicking the
+ button below. If you did not request a new password, please
+ ignore this email.
+ </p>
+ <div>
+ <div
+ style="
+ text-align: center;
+ justify-content: center;
+ padding-bottom: 10px;
+ "
>
+ <a
+ href="{passwordResetUrl}"
+ target="_blank"
+ style="
+ font-size: 15px;
+ border: none;
+ border-radius: 3px;
+ text-decoration: none;
+ color: white;
+ cursor: pointer;
+ padding: 15px 19px;
+ background-color: #ff5f00;
+ border-radius: 5px;
+ "
+ >Reset Password</a
+ >
+ </div>
+ <hr />
+ <div style="text-align: center">
+ <p>
+ Alternatively, you can directly paste this link into
+ your browser:
+ </p>
+ <a href="{passwordResetUrl}" target="_blank"
+ >{passwordResetUrl}</a
+ >
+ </div>
</div>
</div>
</div>
diff --git a/assets/email_templates/phone_removed.html b/assets/email_templates/phone_removed.html
index 1eb52fbe..65807e29 100644
--- a/assets/email_templates/phone_removed.html
+++ b/assets/email_templates/phone_removed.html
@@ -4,61 +4,66 @@
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
+ <meta http-equiv="Content-Type" content="text/html charset=UTF-8" />
<title>Phone Removed From {instanceName} Account</title>
<style>
* {
font-size: 16px;
line-height: 24px;
+ font-family: Arial, Helvetica, sans-serif;
}
- body {
+ p {
color: white;
- font-family: Arial, Helvetica, sans-serif;
- background-color: #202225;
+ }
+ .ExternalClass {
+ width: 100%;
}
</style>
</head>
<body>
- <img
- src="https://raw.githubusercontent.com/fosscord/fosscord/master/assets-rebrand/svg/Fosscord-Wordmark-Orange.svg"
- alt="Branding"
- style="
- width: 100%;
- max-width: 200px;
- margin: 0 auto;
- display: block;
- padding: 20px;
- "
- />
- <div
- style="
- width: 100%;
- max-width: 500px;
- margin: 0 auto;
- padding: 40px 50px;
- background-color: rgba(50, 53, 59, 1);
- border-radius: 5px;
- "
- >
- <p
+ <div style="background-color: #202225;">
+ <img
+ src="https://raw.githubusercontent.com/fosscord/fosscord/master/assets-rebrand/svg/Fosscord-Wordmark-Orange.svg"
+ alt="Branding"
+ style="
+ width: 100%;
+ max-width: 200px;
+ margin: 0 auto;
+ display: block;
+ padding: 20px;
+ "
+ />
+ <div
style="
- font-weight: 600;
- font-size: 20px;
- letter-spacing: 0.27px;
- line-height: 24px;
+ width: 100%;
+ max-width: 500px;
+ margin: 0 auto;
+ padding: 40px 50px;
+ background-color: #32353b;
+ border-radius: 5px;
"
>
- Hey {username},
- </p>
- <p>
- Your phone number ********{phoneNumber} was recently removed
- from this account and added to a different {instanceName}
- account.
- </p>
- <p>
- Please note that your phone number can only be linked to one
- {instanceName} account at a time.
- </p>
+ <p
+ style="
+ font-weight: 600;
+ font-size: 20px;
+ letter-spacing: 0.27px;
+ line-height: 24px;
+ "
+ >
+ Hey {userUsername},
+ </p>
+ <p>
+ Your phone number ********{phoneNumber} was recently removed
+ from this account and added to a different {instanceName}
+ account.
+ </p>
+ <p>
+ Please note that your phone number can only be linked to one
+ {instanceName} account at a time.
+ </p>
+ </div>
</div>
</body>
</html>
diff --git a/assets/email_templates/verify_email.html b/assets/email_templates/verify_email.html
index f0c11e52..604242c4 100644
--- a/assets/email_templates/verify_email.html
+++ b/assets/email_templates/verify_email.html
@@ -4,103 +4,97 @@
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
+ <meta http-equiv="Content-Type" content="text/html charset=UTF-8" />
<title>Verify Email Address for {instanceName}</title>
<style>
* {
font-size: 16px;
line-height: 24px;
- }
- body {
- color: white;
font-family: Arial, Helvetica, sans-serif;
- background-color: #202225;
}
- .btn {
- font-size: 15px;
- border: none;
- border-radius: 3px;
- text-decoration: none;
+ p {
color: white;
- cursor: pointer;
- padding: 15px 19px;
- background-color: #ff5f00;
- border-radius: 5px;
- box-shadow: 0 0 10px rgba(255, 61, 0, 0.1);
}
- .btn:hover {
- background-color: hsl(22.4, 80%, 50%);
- }
- .btn:active {
- background-color: hsl(22.4, 60%, 50%);
+ .ExternalClass {
+ width: 100%;
}
</style>
</head>
<body>
- <img
- src="https://raw.githubusercontent.com/fosscord/fosscord/master/assets-rebrand/svg/Fosscord-Wordmark-Orange.svg"
- alt="Branding"
- style="
- width: 100%;
- max-width: 200px;
- margin: 0 auto;
- display: block;
- padding: 20px;
- "
- />
- <div
- style="
- width: 100%;
- max-width: 500px;
- margin: 0 auto;
- padding: 40px 50px;
- background-color: rgba(50, 53, 59, 1);
- border-radius: 5px;
- "
- >
- <p
+ <div style="background-color: #202225;">
+ <img
+ src="https://raw.githubusercontent.com/fosscord/fosscord/master/assets-rebrand/svg/Fosscord-Wordmark-Orange.svg"
+ alt="Branding"
style="
- font-weight: 600;
- font-size: 20px;
- letter-spacing: 0.27px;
- line-height: 24px;
+ width: 100%;
+ max-width: 200px;
+ margin: 0 auto;
+ display: block;
+ padding: 20px;
+ "
+ />
+ <div
+ style="
+ width: 100%;
+ max-width: 500px;
+ margin: 0 auto;
+ padding: 40px 50px;
+ background-color: #32353b;
+ border-radius: 5px;
"
>
- Hey {username},
- </p>
- <p>
- Thanks for registering for an account on {instanceName}! Before
- we get started, we just need to confirm that this is you. Click
- below to verify your email address:
- </p>
- <div>
- <div
- style="
- display: flex;
- justify-content: center;
- padding-bottom: 10px;
- "
- >
- <a class="btn" href="{verificationUrl}" target="_blank"
- >Verify Email</a
- >
- </div>
- <hr />
- <div
+ <p
style="
- display: flex;
- justify-content: center;
- flex-direction: column;
- text-align: center;
+ font-weight: 600;
+ font-size: 20px;
+ letter-spacing: 0.27px;
+ line-height: 24px;
"
>
- <p>
- Alternatively, you can directly paste this link into
- your browser:
- </p>
- <a href="{verificationUrl}" target="_blank"
- >{verificationUrl}</a
+ Hey {userUsername},
+ </p>
+ <p>
+ Thanks for registering for an account on {instanceName}!
+ Before we get started, we just need to confirm that this is
+ you. Click below to verify your email address:
+ </p>
+ <div>
+ <div
+ style="
+ text-align: center;
+ justify-content: center;
+ padding-bottom: 10px;
+ "
>
+ <a
+ class="btn"
+ href="{emailVerificationUrl}"
+ target="_blank"
+ style="
+ font-size: 15px;
+ border: none;
+ border-radius: 3px;
+ text-decoration: none;
+ color: white;
+ cursor: pointer;
+ padding: 15px 19px;
+ background-color: #ff5f00;
+ border-radius: 5px;
+ "
+ >Verify Email</a
+ >
+ </div>
+ <hr />
+ <div style="text-align: center">
+ <p>
+ Alternatively, you can directly paste this link into
+ your browser:
+ </p>
+ <a href="{emailVerificationUrl}" target="_blank"
+ >{emailVerificationUrl}</a
+ >
+ </div>
</div>
</div>
</div>
diff --git a/src/api/routes/auth/verify/resend.ts b/src/api/routes/auth/verify/resend.ts
index 0c8c4ed9..d9a9cda5 100644
--- a/src/api/routes/auth/verify/resend.ts
+++ b/src/api/routes/auth/verify/resend.ts
@@ -33,7 +33,7 @@ router.post("/", route({}), async (req: Request, res: Response) => {
throw new HTTPError("User does not have an email address", 400);
}
- await Email.sendVerificationEmail(req.user_id, user.email)
+ await Email.sendVerificationEmail(user, user.email)
.then((info) => {
console.log("Message sent: %s", info.messageId);
return res.sendStatus(204);
diff --git a/src/util/entities/User.ts b/src/util/entities/User.ts
index 66e10297..4a399ed9 100644
--- a/src/util/entities/User.ts
+++ b/src/util/entities/User.ts
@@ -386,7 +386,7 @@ export class User extends BaseClass {
// send verification email if users aren't verified by default and we have an email
if (!Config.get().defaults.user.verified && email) {
- await Email.sendVerificationEmail(user.id, email)
+ await Email.sendVerificationEmail(user, email)
.then((info) => {
console.log("Message sent: %s", info.messageId);
})
diff --git a/src/util/util/Email.ts b/src/util/util/Email.ts
index 371ba827..9688c3c5 100644
--- a/src/util/util/Email.ts
+++ b/src/util/util/Email.ts
@@ -16,10 +16,14 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
+import fs from "node:fs";
+import path from "node:path";
import nodemailer, { Transporter } from "nodemailer";
+import { User } from "../entities";
import { Config } from "./Config";
import { generateToken } from "./Token";
+const ASSET_FOLDER_PATH = path.join(__dirname, "..", "..", "..", "assets");
export const EMAIL_REGEX =
/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
@@ -51,7 +55,20 @@ export function adjustEmail(email?: string): string | undefined {
export const Email: {
transporter: Transporter | null;
init: () => Promise<void>;
- sendVerificationEmail: (id: string, email: string) => Promise<any>;
+ generateVerificationLink: (id: string, email: string) => Promise<string>;
+ sendVerificationEmail: (user: User, email: string) => Promise<any>;
+ doReplacements: (
+ template: string,
+ user: User,
+ emailVerificationUrl?: string,
+ passwordResetUrl?: string,
+ ipInfo?: {
+ ip: string;
+ city: string;
+ region: string;
+ country_name: string;
+ },
+ ) => string;
} = {
transporter: null,
init: async function () {
@@ -78,25 +95,109 @@ export const Email: {
console.log(`[SMTP] Ready`);
});
},
- sendVerificationEmail: async function (
- id: string,
- email: string,
- ): Promise<any> {
- if (!this.transporter) return;
+ /**
+ * Replaces all placeholders in an email template with the correct values
+ */
+ doReplacements: function (
+ template: string,
+ user: User,
+ emailVerificationUrl?: string,
+ passwordResetUrl?: string,
+ ipInfo?: {
+ ip: string;
+ city: string;
+ region: string;
+ country_name: string;
+ },
+ ) {
+ const { instanceName } = Config.get().general;
+ template = template.replaceAll("{instanceName}", instanceName);
+ template = template.replaceAll("{userUsername}", user.username);
+ template = template.replaceAll(
+ "{userDiscriminator}",
+ user.discriminator,
+ );
+ template = template.replaceAll("{userId}", user.id);
+ if (user.phone)
+ template = template.replaceAll(
+ "{phoneNumber}",
+ user.phone.slice(-4),
+ );
+ if (user.email)
+ template = template.replaceAll("{userEmail}", user.email);
+
+ // template specific replacements
+ if (emailVerificationUrl)
+ template = template.replaceAll(
+ "{emailVerificationUrl}",
+ emailVerificationUrl,
+ );
+ if (passwordResetUrl)
+ template = template.replaceAll(
+ "{passwordResetUrl}",
+ passwordResetUrl,
+ );
+ if (ipInfo) {
+ template = template.replaceAll("{ipAddress}", ipInfo.ip);
+ template = template.replaceAll("{locationCity}", ipInfo.city);
+ template = template.replaceAll("{locationRegion}", ipInfo.region);
+ template = template.replaceAll(
+ "{locationCountryName}",
+ ipInfo.country_name,
+ );
+ }
+
+ return template;
+ },
+ /**
+ *
+ * @param id user id
+ * @param email user email
+ * @returns a verification link for the user
+ */
+ generateVerificationLink: async function (id: string, email: string) {
const token = (await generateToken(id, email)) as string;
const instanceUrl =
Config.get().general.frontPage || "http://localhost:3001";
const link = `${instanceUrl}/verify#token=${token}`;
+ return link;
+ },
+ sendVerificationEmail: async function (
+ user: User,
+ email: string,
+ ): Promise<any> {
+ if (!this.transporter) return;
+
+ // generate a verification link for the user
+ const verificationLink = await this.generateVerificationLink(
+ user.id,
+ email,
+ );
+ // load the email template
+ const rawTemplate = fs.readFileSync(
+ path.join(
+ ASSET_FOLDER_PATH,
+ "email_templates",
+ "verify_email.html",
+ ),
+ { encoding: "utf-8" },
+ );
+ // replace email template placeholders
+ const html = this.doReplacements(rawTemplate, user, verificationLink);
+
+ // extract the title from the email template to use as the email subject
+ const subject = html.match(/<title>(.*)<\/title>/)?.[1] || "";
+
+ // // construct the email
const message = {
from:
Config.get().general.correspondenceEmail || "noreply@localhost",
to: email,
- subject: `Verify Email Address for ${
- Config.get().general.instanceName
- }`,
- html: `Please verify your email address by clicking the following link: <a href="${link}">Verify Email</a>`,
+ subject,
+ html,
};
+ // // send the email
return this.transporter.sendMail(message);
},
};
|