import { TFunction } from "next-i18next"; import nodemailer from "nodemailer"; import { getErrorFromUnknown } from "@lib/errors"; import { serverConfig } from "@lib/serverConfig"; import { emailHead } from "./common/head"; export type PasswordReset = { language: TFunction; user: { name?: string | null; email: string; }; resetLink: string; }; export const PASSWORD_RESET_EXPIRY_HOURS = 6; export default class ForgotPasswordEmail { passwordEvent: PasswordReset; constructor(passwordEvent: PasswordReset) { this.passwordEvent = passwordEvent; } public sendEmail() { new Promise((resolve, reject) => nodemailer .createTransport(this.getMailerOptions().transport) .sendMail(this.getNodeMailerPayload(), (_err, info) => { if (_err) { const err = getErrorFromUnknown(_err); this.printNodeMailerError(err); reject(err); } else { resolve(info); } }) ).catch((e) => console.error("sendEmail", e)); return new Promise((resolve) => resolve("send mail async")); } protected getMailerOptions() { return { transport: serverConfig.transport, from: serverConfig.from, }; } protected getNodeMailerPayload(): Record { return { to: `${this.passwordEvent.user.name} <${this.passwordEvent.user.email}>`, from: `Cal.com <${this.getMailerOptions().from}>`, subject: this.passwordEvent.language("reset_password_subject"), html: this.getHtmlBody(), text: this.getTextBody(), }; } protected printNodeMailerError(error: Error): void { console.error("SEND_PASSWORD_RESET_EMAIL_ERROR", this.passwordEvent.user.email, error); } protected getTextBody(): string { return ` ${this.passwordEvent.language("reset_password_subject")} ${this.passwordEvent.language("hi_user_name", { user: this.passwordEvent.user.name })}, ${this.passwordEvent.language("someone_requested_password_reset")} ${this.passwordEvent.language("change_password")}: ${this.passwordEvent.resetLink} ${this.passwordEvent.language("password_reset_instructions")} ${this.passwordEvent.language("have_any_questions")} ${this.passwordEvent.language( "contact_our_support_team" )} `.replace(/(<([^>]+)>)/gi, ""); } protected getHtmlBody(): string { const headerContent = this.passwordEvent.language("reset_password_subject"); return ` ${emailHead(headerContent)}

${this.passwordEvent.language("hi_user_name", { user: this.passwordEvent.user.name, })},

${this.passwordEvent.language( "someone_requested_password_reset" )}

${this.passwordEvent.language( "change_password" )}

${this.passwordEvent.language( "password_reset_instructions" )}

${this.passwordEvent.language( "have_any_questions" )} ${this.passwordEvent.language( "contact_our_support_team" )}

`; } }