Resend : envoie tes emails transactionnels avec React

Apprends à connecter Resend à ta boutique React Router 7 : installation du SDK, clé API, template HTML et envoi automatisé d’emails transactionnels.

4 min read
Déverrouillez votre potentiel

avec React Router 7

Vous en avez marre de...

❌ perdre du temps à chercher des informations éparpillées
❌ ne pas avoir de retour sur votre progression
Assistant IA spécialisé

Posez vos questions 24/7 à notre IA experte en React Router 7

Quiz interactifs

Validez vos acquis avec des quiz personnalisés et un feedback instantané

9 modules
76 leçons
Accès à vie
299.49
-35%

Pourquoi utiliser Resend ?

Courier.com offre 10 000 envois gratuits mais :

  • il agit comme un proxy SMTP (Mailgun, SES...) ;
  • beaucoup de configuration avant le premier mail.

Resend, lui :

  1. un SDK ;
  2. une clé API ;
  3. un envoi immédiat.

Parfait pour notre boutique (faible volume). Si un jour tu dépasses plusieurs centaines de milliers de mails : passe à Mailgun ou Amazon SES.

Étape 1 – installer le SDK

Terminal
1
npm install resend

Le paquet ajoute juste un client HTTP. Aucun serveur à maintenir.

Étape 2 – ajouter la clé API

{2}
1
RESEND_API_KEY=__TA_CLE__
2
RESEND_FROM_EMAIL=contact@shop-router.algomax.fr
  • RESEND_API_KEY : copiée dans Dashboard → API keys.
  • RESEND_FROM_EMAIL : domaine vérifié côté Resend.

Étape 3 – le client Resend

server/email.server.ts
1
import { Resend } from "resend";
2
3
export const resend = new Resend(process.env.RESEND_API_KEY);

Simple : une instance, typée, prête à envoyer.

Étape 4 – premier template : confirmation de commande

On crée un modèle HTML + fallback texte. Seule donnée dynamique : OrderEmailData.

server/email.server.ts
1
interface OrderEmailData {
2
orderId: string;
3
customerName: string;
4
customerEmail: string;
5
orderItems: Array<{
6
productName: string;
7
quantity: number;
8
totalPriceCents: number;
9
}>;
10
subtotalCents: number;
11
totalCents: number;
12
currency: string;
13
orderDate: Date;
14
}
15
16
const orderConfirmationTemplate = (d: OrderEmailData) => `
17
<h1 style="font-size:22px;margin:0 0 12px">✅ Commande confirmée</h1>
18
<p>Merci ${d.customerName} !</p>
19
<p>N° ${d.orderId} ${d.orderDate.toLocaleDateString("fr-FR")}</p>
20
${d.orderItems
21
.map(
22
(i) =>
23
`<p>${i.productName} ×${i.quantity} ${format(i.totalPriceCents, d.currency)}</p>`,
24
)
25
.join("")}
26
<p style="font-weight:bold">Total : ${format(d.totalCents, d.currency)}</p>
27
<a href="${process.env.FRONTEND_URL}/orders/${d.orderId}"
28
style="display:inline-block;padding:12px 24px;background:#2563eb;color:#fff;border-radius:6px">
29
Suivre ma commande
30
</a>
31
`;
32
33
const format = (cents: number, currency: string) =>
34
new Intl.NumberFormat("fr-FR", { style: "currency", currency }).format(cents / 100);

Étape 5 – fonction d’envoi

server/email.server.ts
1
export async function sendOrderConfirmationEmail(data: OrderEmailData) {
2
await resend.emails.send({
3
from: process.env.RESEND_FROM_EMAIL!,
4
to: data.customerEmail,
5
subject: `Confirmation de commande #${data.orderId}`,
6
html: orderConfirmationTemplate(data),
7
text: `Merci ${data.customerName}. Commande ${data.orderId}. Total : ${format(
8
data.totalCents,
9
data.currency,
10
)}`,
11
});
12
}
  • from : adresse vérifiée.
  • to : le client.
  • subject : clair et unique (numéro de commande).

Étape 6 – appeler l’envoi dans la création de commande

server/customer/orders.server.ts {47}
1
await prisma.order.update({ … });
2
await sendOrderConfirmationEmail({
3
orderId: order.id,
4
customerName: user?.name ?? "client",
5
customerEmail: user?.email ?? guestEmail!,
6
orderItems: order.items,
7
subtotalCents: order.subtotalCents,
8
totalCents: order.totalCents,
9
currency: order.currency,
10
orderDate: order.createdAt,
11
});

Pourquoi ici ?

  1. La commande est en base : on a l’ID.
  2. Les lignes sont définitives : prix et quantités figés.
  3. Si l’envoi échoue, on logue l’erreur mais la commande reste créée.

Étape 7 – tester en local

  1. Lance l’appli : npm run dev.
  2. Crée un compte (Email différent).
  3. Passe au checkout test Stripe → paiement.
  4. Resend Dashboard → Emails : un message apparaît.
  5. Vérifie la boîte mail : parfois en Spam (domaine tout neuf).

Étape 8 – autres mails (bonus)

Le même fichier contient déjà :

  • sendOrderStatusUpdateEmail()
  • sendPasswordResetEmail()
  • sendAccountCreatedEmail()

Ils partagent la même logique : template HTML + fallback texte. Tu pourras les appeler :

1
// après changement de statut
2
await sendOrderStatusUpdateEmail({ … });
3
4
// lors de la création du compte (hook Better-Auth)
5
await sendAccountCreatedForUser(email, name);

Checklist avant merge

  • RESEND_API_KEY + RESEND_FROM_EMAIL présents en production (Settings → Secrets GitHub).
  • Domaine vérifié dans Resend (MX + TXT propagés).
  • Fonction appelée après la création d’une commande.
  • Pas de clé Resend dans le dépôt public.
Inclus
Quiz interactif
Testez vos connaissances et validez votre compréhension du module avec notre quiz interactif.
1

Comprendre les concepts fondamentaux

Quelle est la principale différence entre les composants client et serveur dans React ?

Les composants client s'exécutent uniquement dans le navigateur
Les composants serveur peuvent utiliser useState
Les composants client sont plus rapides
Il n'y a aucune différence significative
2

Optimisation des performances

Quelle technique est recommandée pour éviter les rendus inutiles dans React ?

Utiliser React.memo pour les composants fonctionnels
Ajouter plus d'états locaux
Éviter d'utiliser les props
Toujours utiliser les class components
3

Architecture des données

Quel hook permet de gérer les effets de bord dans un composant React ?

useEffect
useState
useMemo
useContext
4

Gestion des erreurs

Comment implémenter la gestion des erreurs pour les requêtes API dans React ?

Utiliser try/catch avec async/await
Ignorer les erreurs
Toujours afficher un message d'erreur
Rediriger l'utilisateur
5

Déploiement et CI/CD

Quelle est la meilleure pratique pour déployer une application React en production ?

Utiliser un service CI/CD comme GitHub Actions
Copier les fichiers manuellement via FTP
Envoyer le code source complet
Ne jamais mettre à jour l'application

Débloquez ce quiz et tous les autres contenus inclus en achetant ce cours