diff --git a/apps/app/src/api/auth/mutations.ts b/apps/app/src/api/auth/mutations.ts index 8062f787..7ea82dfa 100644 --- a/apps/app/src/api/auth/mutations.ts +++ b/apps/app/src/api/auth/mutations.ts @@ -11,16 +11,20 @@ import { verifyTotpSchema, } from "@/api/auth/schemas" import { emailVerificationExpiration, lastLocaleExpirationInSeconds, otpWindow, rolesAsObject } from "@/constants" +import { logoUrl } from "@/constants/medias" import { hash } from "@/lib/bcrypt" import { env } from "@/lib/env" +import { Locale } from "@/lib/i18n-config" +import { _getDictionary } from "@/lib/langs" import { sendMail } from "@/lib/mailer" import { prisma } from "@/lib/prisma" import { redis } from "@/lib/redis" -import { html, plainText, subject } from "@/lib/templates/mail/verify-email" import { ApiError, ensureLoggedIn, generateRandomSecret, handleApiError } from "@/lib/utils/server-utils" import { apiInputFromSchema } from "@/types" +import VerifyEmail from "@next-boilerplate/emails/emails/verify-email" import { logger } from "@next-boilerplate/lib" import { Prisma } from "@prisma/client" +import { render } from "@react-email/render" import { signUpResponseSchema } from "../me/schemas" @@ -55,13 +59,39 @@ export const register = async ({ input }: apiInputFromSchema`, to: email.toLowerCase(), - subject: subject, - text: plainText(url, input.locale), - html: html(url, input.locale), + subject: dictionary.verifyYourEmailAddress, + text, + html, }) } else { logger.debug("Email verification disabled, skipping email sending on registration") diff --git a/apps/app/src/api/me/email/mutations.ts b/apps/app/src/api/me/email/mutations.ts index c6c88810..c127652f 100644 --- a/apps/app/src/api/me/email/mutations.ts +++ b/apps/app/src/api/me/email/mutations.ts @@ -3,14 +3,17 @@ import { z } from "zod" import { sendVerificationEmailSchema, verifyEmailResponseSchema, verifyEmailSchema } from "@/api/me/schemas" import { emailVerificationExpiration, resendEmailVerificationExpiration } from "@/constants" +import { logoUrl } from "@/constants/medias" import { env } from "@/lib/env" -import { i18n } from "@/lib/i18n-config" +import { i18n, Locale } from "@/lib/i18n-config" +import { _getDictionary } from "@/lib/langs" import { sendMail } from "@/lib/mailer" import { prisma } from "@/lib/prisma" -import { html, plainText, subject } from "@/lib/templates/mail/verify-email" import { ApiError, handleApiError } from "@/lib/utils/server-utils" import { apiInputFromSchema } from "@/types" +import VerifyEmail from "@next-boilerplate/emails/emails/verify-email" import { logger } from "@next-boilerplate/lib" +import { render } from "@react-email/render" export const sendVerificationEmail = async ({ input }: apiInputFromSchema) => { try { @@ -65,13 +68,39 @@ export const sendVerificationEmail = async ({ input }: apiInputFromSchema`, to: email.toLowerCase(), - subject: subject, - text: plainText(url, user.lastLocale ?? i18n.defaultLocale), - html: html(url, user.lastLocale ?? i18n.defaultLocale), + subject: dictionary.verifyYourEmailAddress, + text, + html, }) } else { logger.debug("Email verification disabled") diff --git a/apps/app/src/api/me/password/mutations.ts b/apps/app/src/api/me/password/mutations.ts index 30cad4f8..3d27a417 100644 --- a/apps/app/src/api/me/password/mutations.ts +++ b/apps/app/src/api/me/password/mutations.ts @@ -3,15 +3,18 @@ import { z } from "zod" import { forgotPasswordSchema, resetPasswordResponseSchema, resetPasswordSchema } from "@/api/me/schemas" import { resendResetPasswordExpiration, resetPasswordExpiration, rolesAsObject } from "@/constants" +import { logoUrl } from "@/constants/medias" import { hash } from "@/lib/bcrypt" import { env } from "@/lib/env" -import { i18n } from "@/lib/i18n-config" +import { i18n, Locale } from "@/lib/i18n-config" +import { _getDictionary } from "@/lib/langs" import { sendMail } from "@/lib/mailer" import { prisma } from "@/lib/prisma" -import { html, plainText, subject } from "@/lib/templates/mail/reset-password" import { ApiError, handleApiError } from "@/lib/utils/server-utils" import { apiInputFromSchema } from "@/types" +import ResetPasswordTemplate from "@next-boilerplate/emails/emails/reset-password" import { logger } from "@next-boilerplate/lib" +import { render } from "@react-email/render" export const forgotPassword = async ({ input }: apiInputFromSchema) => { try { @@ -61,20 +64,37 @@ export const forgotPassword = async ({ input }: apiInputFromSchema`, to: email, - subject: subject, - text: plainText( - user.username ?? email, - `${env.VERCEL_URL ?? env.NEXT_PUBLIC_BASE_URL}/reset-password/${resetPasswordToken}`, - user.lastLocale ?? i18n.defaultLocale - ), - html: html( - user.username ?? email, - `${env.VERCEL_URL ?? env.NEXT_PUBLIC_BASE_URL}/reset-password/${resetPasswordToken}`, - user.lastLocale ?? i18n.defaultLocale - ), + subject: mailDict.resetYourPassword, + text, + html, }) return { email } diff --git a/apps/app/src/api/me/schemas.ts b/apps/app/src/api/me/schemas.ts index 4197054d..41dc2764 100644 --- a/apps/app/src/api/me/schemas.ts +++ b/apps/app/src/api/me/schemas.ts @@ -144,6 +144,7 @@ export const sendVerificationEmailSchema = (dictionary?: TDictionary import("../langs/errors/en.json").then((module) => module.default), fr: () => import("../langs/errors/fr.json").then((module) => module.default), }, + transactionals: { + en: () => import("../langs/transactionals/en.json").then((module) => module.default), + fr: () => import("../langs/transactionals/fr.json").then((module) => module.default), + }, } export type TPossibleNamespaces = keyof typeof dictionaries diff --git a/apps/app/src/lib/templates/mail/reset-password.ts b/apps/app/src/lib/templates/mail/reset-password.ts deleted file mode 100644 index 26680bc2..00000000 --- a/apps/app/src/lib/templates/mail/reset-password.ts +++ /dev/null @@ -1,261 +0,0 @@ -import { env } from "@/lib/env" - -export const subject = "Reset your password" - -export const plainText = (username: string, resetLink: string, locale: string) => { - const en = `Password Reset - -Hello ${username}, - -We received a request to reset your password. You can reset your password by clicking the following link: - -${resetLink} - -If you did not request this password reset, you can safely ignore this email. - -This email was sent to you as part of our account services.${ - env.SUPPORT_EMAIL ? ` If you have any questions, please contact us at ${env.SUPPORT_EMAIL}.` : "" - } -` - const fr = `Réinitialiser votre mot de passe - -Bonjour ${username}, - -Nous avons reçu une demande de réinitialisation de votre mot de passe. Vous pouvez réinitialiser votre mot de passe en cliquant sur le lien suivant : - -${resetLink} - -Si vous n'avez pas demandé cette réinitialisation de mot de passe, vous pouvez ignorer cet e-mail en toute sécurité. - -Ce courriel vous a été envoyé dans le cadre de nos services de compte.${ - env.SUPPORT_EMAIL ? ` Si vous avez des questions, veuillez nous contacter à l'adresse ${env.SUPPORT_EMAIL}.` : "" - } -` - if (locale === "fr") return fr - return en -} - -export const html = (username: string, resetLink: string, locale: string) => ` - - - - - - - - - - - - - - - - - - - - -` diff --git a/apps/app/src/lib/templates/mail/verify-email.ts b/apps/app/src/lib/templates/mail/verify-email.ts deleted file mode 100644 index a4e8a3fa..00000000 --- a/apps/app/src/lib/templates/mail/verify-email.ts +++ /dev/null @@ -1,257 +0,0 @@ -import { env } from "@/lib/env" - -export const subject = "Verify your email address" - -export const plainText = (verificationLink: string, locale: string) => { - const en = `Email Verification - -Hello, - -Thank you for signing up with us. Please verify your email address by clicking the following link: - -${verificationLink} - -If you did not sign up for an account, you can safely ignore this email. - -This email was sent to you as part of our account services. ${ - env.SUPPORT_EMAIL ? ` If you have any questions, please contact us at ${env.SUPPORT_EMAIL}.` : "" - } -` - - const fr = `Vérification de l'adresse e-mail - -Bonjour, - -Merci de vous être inscrit chez nous. Veuillez vérifier votre adresse e-mail en cliquant sur le lien suivant : - -${verificationLink} - -Si vous ne vous êtes pas inscrit pour un compte, vous pouvez ignorer cet e-mail en toute sécurité. - -Cet e-mail vous a été envoyé dans le cadre de nos services de compte. ${ - env.SUPPORT_EMAIL ? ` Si vous avez des questions, veuillez nous contacter à ${env.SUPPORT_EMAIL}.` : "" - } -` - - if (locale === "fr") return fr - return en -} - -export const html = (verificationLink: string, locale: string) => ` - - - - - - - - - - - - - - - - - - - -` diff --git a/packages/emails/contants.ts b/packages/emails/contants.ts index d5f8f987..eac1f99d 100644 --- a/packages/emails/contants.ts +++ b/packages/emails/contants.ts @@ -1,5 +1,5 @@ -export const primary = "#6AD2E7" -export const background = "#E2EFF1" +export const primary = "#006FEE" +export const background = "#FFFFFF" export const content1 = "#FFFFFF" export const content2 = "#f4f4f5" export const content3 = "#e4e4e7"