Resend est devenu le défaut pour envoyer du transactionnel depuis une stack JS moderne. L'API tient sur une fonction, les templates s'écrivent en React, et le tier gratuit couvre les 3000 premiers emails par mois. Cet article te montre comment brancher Resend dans une app Next.js, générer tes templates avec Claude, et éviter les pièges qui envoient tes emails dans le spam. Si tu débutes avec Claude, commence par le guide complet pour apprendre Claude, on suppose ici que tu sais déjà lui demander du code.
Objectif : que ton app envoie ses premiers emails de confirmation cet après-midi, avec un domaine vérifié et un webhook de monitoring qui tourne.
Pourquoi Resend plutôt que SendGrid ou Mailgun
SendGrid fait le job depuis 2009, mais l'interface est devenue une usine à gaz orientée marketeurs. Mailgun a le même problème avec une couche vieillissante par-dessus. Postmark reste solide sur la deliverability mais démarre plus haut en prix. Resend a été construit après ces trois-là, avec une hypothèse claire : le client type est un dev qui vit dans Next.js, tRPC ou SvelteKit.
Concrètement, Resend te donne un SDK JS et Python propres, des templates en React (via React Email), des webhooks bien documentés, et un dashboard qui affiche le corps réel de l'email envoyé, avec le HTML rendu. Le tier gratuit couvre 3000 emails par mois et 100 par jour, largement de quoi lancer un SaaS.
Quand ce n'est pas le bon choix : campagnes marketing lourdes vers une liste de 200k contacts, séquences automatisées avec segmentation avancée, ou emails transactionnels à volume industriel type Uber. Pour ces cas, Postmark ou Amazon SES avec un ESP par-dessus sont plus adaptés.
Créer son compte Resend et vérifier son domaine
L'inscription prend deux minutes. Une fois connecté, tu vas dans API Keys et tu crées une clé avec permission Sending access uniquement. Tu la copies dans .env.local sous RESEND_API_KEY. Ne la commit jamais.
L'étape critique, c'est le domaine. Tant que tu envoies depuis onboarding@resend.dev, tu es en mode test : tu peux uniquement envoyer à l'email associé à ton compte. En prod, tu envoies depuis ton propre domaine, disons hello@tondomaine.com.
Dans Domains, tu ajoutes ton domaine. Resend te donne trois enregistrements à copier chez ton registrar (Cloudflare, OVH, Gandi, peu importe) :
- Un TXT pour SPF, qui autorise les serveurs Resend à envoyer pour ton domaine.
- Un TXT DKIM, qui signe cryptographiquement tes emails.
- Un TXT DMARC, qui dit aux serveurs destinataires quoi faire si SPF ou DKIM échoue.
Colle les valeurs exactes, sans espace en trop. La propagation DNS prend entre 5 minutes et 24 heures selon le registrar. Cloudflare est quasi-instantané, OVH peut prendre une heure. Une fois vert dans le dashboard Resend, tu es prêt.
Premier envoi depuis Next.js : code minimal
Dans ton projet Next.js (App Router) :
npm install resendPuis crée app/api/send/route.ts :
import { Resend } from 'resend';
import { NextResponse } from 'next/server';
const resend = new Resend(process.env.RESEND_API_KEY);
export async function POST(req: Request) {
const { to, subject, html } = await req.json();
const { data, error } = await resend.emails.send({
from: 'hello@tondomaine.com',
to,
subject,
html,
});
if (error) return NextResponse.json({ error }, { status: 500 });
return NextResponse.json({ id: data?.id });
}Test rapide avec curl :
curl -X POST http://localhost:3000/api/send \
-H "Content-Type: application/json" \
-d '{"to":"toi@gmail.com","subject":"Test","html":"<p>Hello</p>"}'Deux erreurs classiques à ce stade : le 403 ("domain not verified") signifie que tu envoies depuis un domaine non validé, retourne à l'étape DNS. Le 429 ("rate limit exceeded") arrive si tu dépasses 2 requêtes par seconde en free tier. Un simple setTimeout entre deux envois règle le problème pour un cas basique.
Générer ses templates avec React Email et Claude
Un email HTML propre en 2026, ça reste des tables imbriquées et du CSS inline pour survivre à Outlook. Personne n'a envie d'écrire ça à la main. React Email résout le problème : tu écris des composants JSX (Html, Head, Body, Container, Text, Button), et la lib compile en HTML compatible.
npm install react-email @react-email/componentsLe prompt Claude type que j'utilise :
Génère un template React Email pour un email de bienvenue SaaS. Composants @react-email/components uniquement. Contraintes : largeur 600px, police Inter avec fallback Arial, un CTA principal en bouton, un lien de désinscription en pied, palette sobre (fond blanc, accent orange #F97316). Retourne un fichier .tsx complet.
Claude sort un template propre en une passe. Si tu veux itérer, tu ouvres le rendu dans react-email dev (server local sur port 3001), tu screenshotte, tu recolles dans Claude avec "le padding du bouton est trop serré, augmente-le et refais le contraste du texte secondaire". Deux ou trois allers-retours et le template est en prod.
Pour un workflow encore plus rapide, Claude Code peut lire ton dossier emails/, appliquer une charte cohérente à tous les templates existants, et créer les nouveaux par imitation. C'est là que ça devient sérieux pour un dev qui veut expédier.
Les 4 emails transactionnels que toute app doit envoyer
Avant de partir dans les templates créatifs, couvre ces quatre-là. Ils représentent 90 % du volume transactionnel d'un SaaS classique.
| Trigger | Sujet type | Ouverture attendue | |
|---|---|---|---|
| Confirmation d'inscription | POST /signup réussi | Confirme ton adresse pour activer ton compte | 70 à 85 % |
| Reset password | POST /forgot-password | Réinitialise ton mot de passe | 80 à 90 % |
| Reçu de paiement | Webhook Stripe invoice.paid | Reçu de paiement, facture 2026-0142 | 55 à 70 % |
| Notification événement | Événement métier (commande, invitation) | Nouvelle commande de Marie L., 89 € | 40 à 60 % |
Deux règles simples : évite les sujets type "Action requise" ou "Important", qui sonnent phishing. Évite les templates vides avec juste un logo et "Merci !", qui n'apportent rien. Un email transactionnel contient l'information dans les 3 premières lignes, avant même que le destinataire n'ouvre.
Si tu veux voir un cas complet sur l'email post-achat côté e-commerce, on l'a détaillé dans ce guide dédié.
Deliverability : ne pas finir en spam
SPF/DKIM/DMARC configurés, ce n'est que la moitié du travail. Le reste dépend de comportements côté envoi.
Warm-up du domaine : les 15 premiers jours, monte progressivement. Jour 1, envoie 50 emails. Jour 3, 200. Jour 7, 1000. Un domaine neuf qui envoie 10 000 emails d'un coup finit en dossier promotions ou spam chez Gmail, même avec DNS parfaits.
Ratio texte/HTML : Resend te laisse fournir une version text en plus du html. Fais-le. Les filtres anti-spam pénalisent les emails HTML pur sans équivalent texte. Claude te génère la version texte à partir du HTML en une requête.
Mots à éviter dans le sujet et le premier paragraphe : gratuit, urgent, cliquez ici, félicitations, garanti, argent facile. Pour un email transactionnel, tu n'en as pas besoin de toute façon.
Tests avant prod :
- mail-tester.com : envoie ton email à l'adresse qu'il te donne, tu obtiens un score sur 10. Vise 9+.
- Google Postmaster Tools : une fois en prod, monitore ton domain reputation chez Gmail. Si ça descend sous "Medium", quelque chose ne va pas.
Prompt Claude d'audit : "Voici mon template React Email. Identifie les éléments qui risquent de déclencher les filtres anti-spam (mots piégés, ratio image/texte, absence de désinscription, liens raccourcis). Propose des corrections concrètes."
Logs, webhooks et monitoring
Le dashboard Resend liste chaque email envoyé avec son statut. Utile pour débugger un cas isolé, insuffisant pour du monitoring sérieux. Pour ça, tu branches les webhooks.
Dans Webhooks, tu ajoutes l'URL https://ton-app.com/api/resend-webhook et tu coches les événements qui t'intéressent : email.delivered, email.bounced, email.complained (marqué comme spam), email.opened si tu veux le tracking.
// app/api/resend-webhook/route.ts
import { NextResponse } from 'next/server';
import { supabase } from '@/lib/supabase';
export async function POST(req: Request) {
const event = await req.json();
await supabase.from('email_events').insert({
email_id: event.data.email_id,
type: event.type,
to: event.data.to,
created_at: event.created_at,
});
if (event.type === 'email.bounced' || event.type === 'email.complained') {
// Alerte Slack ici
}
return NextResponse.json({ ok: true });
}Une table Postgres, une requête agrégée quotidienne, et tu as ton taux de bounce et de plainte. Alerte Slack si bounce > 5 % sur 24h, c'est le seuil où les fournisseurs commencent à dégrader ta réputation. Pas besoin de Datadog pour ça.
Automatiser encore plus avec Claude et MCP
La partie amusante commence quand tu branches Claude sur ta base de logs Resend via MCP. Le Model Context Protocol te permet de connecter Claude à des outils tiers comme ta base Postgres, Slack, ou directement l'API Resend si tu écris un serveur MCP dédié.
Une fois branché, tu poses des questions en langage naturel dans Claude : "Combien d'emails ont bouncé cette semaine ?", "Quels sont les domaines destinataires avec le plus de plaintes ?", "Génère un rapport de deliverability pour octobre en tableau markdown". Claude interroge ta base, formate le résultat, et te le rend. Pour construire ton propre serveur, on détaille le pattern dans ce guide.
L'autre gain : Claude Code écrit lui-même l'intégration. Tu lui donnes accès au dossier de ton projet, tu lui pointes la doc Resend, et tu lui demandes "crée une route webhook qui stocke les événements en Supabase et alerte Slack sur bounce". Il lit la doc, écrit le code, teste avec un payload d'exemple, corrige. Une session de 30 minutes pour ce que tu aurais mis un après-midi à écrire.
Passer à la pratique
Résumé de la stack minimale pour partir en prod cet après-midi : Resend + domaine vérifié (SPF/DKIM/DMARC), une route /api/send, des templates React Email générés avec Claude, un webhook qui stocke les événements en Postgres, un test mail-tester à 9+. Pas besoin de plus pour un SaaS qui démarre.
Si tu veux aller plus loin : versionne tes templates, ajoute un système d'A/B testing sur les sujets, branche Segment ou PostHog pour croiser envois et comportement produit. Mais commence par la version basique qui tourne.
Cette intégration Resend fait partie d'un ensemble plus large : automatiser sa stack avec Claude et MCP couvre les autres briques (Stripe, Notion, Slack). Si tu veux construire ton produit IA complet en travaillant avec Claude comme copilote, notre parcours Claude Builders te permet de construire ton produit en 5 semaines, avec les intégrations transactionnelles incluses dans les livrables.
