Ajoute des notifications par e-mail à ton site de réservation IA

Envoie des e-mails de confirmation de réservation et des alertes au propriétaire en utilisant Supabase, Resend et Edge Functions.

Feuille de route et ressources

Tu débutes ? Commence ici en premier

Ce guide enrichit le projet du site de réservation IA avec des notifications par e-mail automatiques. Si tu n'as pas encore construit le site de réservation, commence d'abord par le guide principal.

Crée un site de réservation avec l'IA

Ouvre le guide principal

MAIN GUIDE

https://profitstudio.app/video/build-booking-website-ai

Configurer Resend pour les e-mails de réservation

Crée et configure ton compte Resend

Ouvrir Resend

https://resend.com/

Créez un compte Resend Générez une clé API Resend Copiez et enregistrez la clé API en lieu sûr

IMPORTANT

Garde la clé API Resend privée. Ne l'ajoute jamais au code frontend et ne la partage jamais publiquement.

Ajoute et vérifie ton domaine d'envoi

Ajoutez le domaine de votre site de réservation Sélectionnez la région la plus proche Copiez les enregistrements DNS depuis Resend Ajoutez les enregistrements chez votre fournisseur de domaine Revenez sur Resend et confirmez que le domaine est vérifié

La vérification DNS peut prendre quelques minutes, voire plus, selon ton fournisseur de domaine.

Créer la fonction d'e-mail de réservation

Crée l'Edge Function d'e-mail de réservation

Ouvrir Supabase

https://supabase.com/?utm_source=partner&utm_medium=social&utm_campaign=supasquad&dub_id=faVfKdcLWvKCbYNp

Ouvrez votre projet Supabase Ouvrez Edge Functions Créez une nouvelle fonction avec l'éditeur du navigateur Nommez la fonction `send-booking-email` Supprimez le code de démarrage par défaut

Personnalise et ajoute le code de la fonction

Saisissez l'e-mail du propriétaire Saisissez le domaine Resend vérifié Saisissez le nom de l'entreprise expéditrice Personnalisez les modèles d'e-mail si nécessaire Copiez et collez le code de fonction généré

Fonction d'e-mail de réservation

import { serve } from "https://deno.land/std/http/server.ts"; serve(async (req) => { try { const body = await req.json(); const record = body.record || {}; const resendKey = Deno.env.get("RESEND_API_KEY"); const supabaseUrl = Deno.env.get("SUPABASE_URL"); const supabaseServiceRoleKey = Deno.env.get("SUPABASE_SERVICE_ROLE_KEY"); if (!resendKey) { return new Response( JSON.stringify({ error: "Missing RESEND_API_KEY secret" }), { status: 500, headers: { "Content-Type": "application/json" }, } ); } const ownerEmail = "YOUR_OWNER_EMAIL"; const customerEmail = record.email || ""; const customerName = record.full_name || record.name || "Customer"; const phone = record.phone || ""; const appointmentDate = record.appointment_date || record.date || ""; const startTime = record.start_time || record.time || ""; const endTime = record.end_time || ""; const notes = record.notes || ""; const status = record.status || "New"; let serviceName = record.service_name || record.service || record.service_title || ""; // If the appointment only has service_id, fetch the service name from the services table if (!serviceName && record.service_id && supabaseUrl && supabaseServiceRoleKey) { try { const serviceId = encodeURIComponent(record.service_id); const serviceResponse = await fetch( `${supabaseUrl}/rest/v1/services?id=eq.${serviceId}&select=name`, { method: "GET", headers: { apikey: supabaseServiceRoleKey, Authorization: `Bearer ${supabaseServiceRoleKey}`, "Content-Type": "application/json", }, } ); const serviceData = await serviceResponse.json(); if (Array.isArray(serviceData) && serviceData.length > 0) { serviceName = serviceData[0].name || ""; } } catch (_serviceError) { serviceName = ""; } } if (!serviceName) { serviceName = "Appointment"; } // 1) Email to business owner const ownerResponse = await fetch("https://api.resend.com/emails", { method: "POST", headers: { Authorization: `Bearer ${resendKey}`, "Content-Type": "application/json", }, body: JSON.stringify({ from: "Bookings <bookings@YOUR_DOMAIN_NAME>", to: [ownerEmail], subject: "OWNER_NOTIFICATION_SUBJECT", html: ` <h2>OWNER_NOTIFICATION_HEADING</h2> <p>OWNER_NOTIFICATION_INTRO</p> <p><b>Customer Name:</b> ${customerName}</p> <p><b>Email:</b> ${customerEmail}</p> <p><b>Phone:</b> ${phone}</p> <p><b>Service:</b> ${serviceName}</p> <p><b>Date:</b> ${appointmentDate}</p> <p><b>Start Time:</b> ${startTime}</p> <p><b>End Time:</b> ${endTime}</p> <p><b>Notes:</b> ${notes}</p> <p><b>Status:</b> ${status}</p> `, }), }); const ownerData = await ownerResponse.json(); // 2) Email to customer let customerData = null; if (customerEmail) { const customerResponse = await fetch("https://api.resend.com/emails", { method: "POST", headers: { Authorization: `Bearer ${resendKey}`, "Content-Type": "application/json", }, body: JSON.stringify({ from: "YOUR_BUSINESS_NAME <bookings@YOUR_DOMAIN_NAME>", to: [customerEmail], subject: "CUSTOMER_CONFIRMATION_SUBJECT", html: ` <h2>CUSTOMER_CONFIRMATION_HEADING</h2> <p>Hi ${customerName},</p> <p>CUSTOMER_CONFIRMATION_INTRO</p> <p><b>Service:</b> ${serviceName}</p> <p><b>Date:</b> ${appointmentDate}</p> <p><b>Start Time:</b> ${startTime}</p> <p><b>End Time:</b> ${endTime}</p> <p>If you need to make any changes, please contact us before your appointment.</p> <p>CUSTOMER_CONFIRMATION_CLOSING</p> `, }), }); customerData = await customerResponse.json(); } return new Response( JSON.stringify({ success: true, ownerEmailSent: ownerData, customerEmailSent: customerData, }), { headers: { "Content-Type": "application/json" }, } ); } catch (error) { return new Response( JSON.stringify({ success: false, error: String(error), }), { status: 500, headers: { "Content-Type": "application/json" }, } ); } });

E-mail du propriétaire

owner@example.com

Domaine Resend vérifié

yourdomain.com

Nom du business expéditeur

Clinique dentaire Bright

Objet de l'e-mail au propriétaire

En-tête de l'e-mail au propriétaire

Texte d'introduction de l'e-mail au propriétaire

Objet de l'e-mail client

En-tête de l'e-mail client

Texte d'introduction de l'e-mail client

Texte de clôture de l'e-mail client

Déploie et configure la fonction

Déployez la fonction Ouvrez les paramètres de la fonction Désactivez `Verify JWT With Legacy Secret` Enregistrez les modifications Copiez et conservez l'URL de l'endpoint de la fonction pour la configuration du webhook

IMPORTANT

Désactive « Verify JWT With Legacy Secret » pour que le Database Webhook puisse appeler la fonction.

Ajouter la clé API Resend à Supabase

Ajoute la clé API Resend comme secret Supabase

Ouvrez Edge Function Secrets Créez un nouveau secret Définissez le nom sur `RESEND_API_KEY` Collez la clé API Resend Enregistrez le secret

IMPORTANT

Utilise exactement le nom de secret `RESEND_API_KEY`. La moindre faute de frappe empêchera la fonction d'accéder à Resend.

Connecter les e-mails aux nouvelles réservations

Crée le webhook d'e-mail de réservation

Déclenche la fonction d'e-mail de réservation à chaque nouveau rendez-vous ajouté.

Integrations Database Webhooks

Ouvrez Database Webhooks Activez Database Webhooks Créez un nouveau webhook Nommez-le `send-booking-email-webhook` Sélectionnez la table `public.appointments` Choisissez `Insert` comme événement Conservez `HTTP Request` comme type Utilisez `POST` comme méthode de requête Collez l'URL de l'endpoint de l'Edge Function Créez le webhook

Tester le système d'e-mail de réservation

Teste le flux complet d'e-mails de réservation

Teste le flux de réservation complet et vérifie que les deux e-mails sont bien distribués.

Ouvrez le site de réservation en ligne Envoyez un rendez-vous de test Confirmez que la réservation est enregistrée dans Supabase Vérifiez l'e-mail de confirmation du client Vérifiez l'e-mail de notification du propriétaire Vérifiez que les détails de la réservation sont corrects dans les deux e-mails Confirmez que la réservation apparaît dans le tableau de bord admin