feat(email): refactor email module and improve config handling

- Simplify `sendEmail` by extracting `resolveFrom` and `buildPayload` helpers
- Remove `sendAuthEmail` and `sendAppEmail` exports, keeping only `sendEmail` and `sendBatchEmails`
- Replace hardcoded fallback sender with env-based validation (throws if missing)
- Update `BaseLayout` to resolve `supportEmail` from `ZEN_SUPPORT_EMAIL` env var instead of hardcoded default
- Conditionally render support section only when a support email is available
- Remove verbose JSDoc comments and reduce overall code verbosity
This commit is contained in:
2026-04-13 18:37:06 -04:00
parent 59fce3cd91
commit 87a04db04b
10 changed files with 166 additions and 518 deletions
@@ -0,0 +1,28 @@
import { Section, Text } from "@react-email/components";
import { BaseLayout } from "../../core/email/templates/BaseLayout.jsx";
export const PasswordChangedEmail = ({ email, companyName }) => (
<BaseLayout
preview={`Votre mot de passe a été modifié ${companyName}`}
title="Mot de passe modifié"
companyName={companyName}
supportSection={true}
>
<Text className="text-[14px] leading-[24px] text-neutral-600 mt-[4px] mb-[24px]">
Ceci confirme que le mot de passe de votre compte <span className="font-medium text-neutral-900">{companyName}</span> a bien été modifié.
</Text>
<Section style={{ border: '1px solid #E5E5E5' }} className="bg-neutral-100 rounded-[12px] p-[20px] my-[24px]">
<Text className="text-[12px] font-medium text-neutral-400 m-0 mb-[4px] uppercase tracking-wider">
Compte
</Text>
<Text className="text-[14px] font-medium text-neutral-900 m-0">
{email}
</Text>
</Section>
<Text className="text-[12px] leading-[20px] text-neutral-400 m-0">
Si vous n'êtes pas à l'origine de cette modification, contactez immédiatement notre équipe de support.
</Text>
</BaseLayout>
);
@@ -0,0 +1,35 @@
import { Button, Section, Text, Link } from "@react-email/components";
import { BaseLayout } from "../../core/email/templates/BaseLayout.jsx";
export const PasswordResetEmail = ({ resetUrl, companyName }) => (
<BaseLayout
preview={`Réinitialisez votre mot de passe pour ${companyName}`}
title="Réinitialisation du mot de passe"
companyName={companyName}
supportSection={true}
>
<Text className="text-[14px] leading-[24px] text-neutral-600 mt-[4px] mb-[24px]">
Nous avons reçu une demande de réinitialisation du mot de passe pour votre compte <span className="font-medium text-neutral-900">{companyName}</span>. Cliquez sur le bouton ci-dessous pour en choisir un nouveau.
</Text>
<Section className="mt-[28px] mb-[32px]">
<Button
href={resetUrl}
className="bg-neutral-900 rounded-[8px] text-white font-medium px-[20px] py-[11px] no-underline text-[13px]"
>
Réinitialiser le mot de passe
</Button>
</Section>
<Text className="text-[12px] leading-[20px] text-neutral-400 m-0">
Ce lien expire dans 1 heure. Si vous n'êtes pas à l'origine de cette demande, ignorez ce message votre mot de passe ne sera pas modifié.
</Text>
<Text className="text-[12px] leading-[20px] text-neutral-400 m-0 mt-[8px]">
Lien :{' '}
<Link href={resetUrl} className="text-neutral-400 underline break-all">
{resetUrl}
</Link>
</Text>
</BaseLayout>
);
@@ -0,0 +1,35 @@
import { Button, Section, Text, Link } from "@react-email/components";
import { BaseLayout } from "../../core/email/templates/BaseLayout.jsx";
export const VerificationEmail = ({ verificationUrl, companyName }) => (
<BaseLayout
preview={`Confirmez votre adresse courriel pour ${companyName}`}
title="Confirmez votre adresse courriel"
companyName={companyName}
supportSection={true}
>
<Text className="text-[14px] leading-[24px] text-neutral-600 mt-[4px] mb-[24px]">
Merci de vous être inscrit sur <span className="font-medium text-neutral-900">{companyName}</span>. Cliquez sur le bouton ci-dessous pour confirmer votre adresse courriel.
</Text>
<Section className="mt-[28px] mb-[32px]">
<Button
href={verificationUrl}
className="bg-neutral-900 rounded-[8px] text-white font-medium px-[20px] py-[11px] no-underline text-[13px]"
>
Confirmer mon courriel
</Button>
</Section>
<Text className="text-[12px] leading-[20px] text-neutral-400 m-0">
Ce lien expire dans 24 heures. Si vous n'avez pas créé de compte, ignorez ce message.
</Text>
<Text className="text-[12px] leading-[20px] text-neutral-400 m-0 mt-[8px]">
Lien :{' '}
<Link href={verificationUrl} className="text-neutral-400 underline break-all">
{verificationUrl}
</Link>
</Text>
</BaseLayout>
);