diff --git a/cloudflare-worker/hubspot-proxy.js b/cloudflare-worker/hubspot-proxy.js index c43af1c..8eddb81 100644 --- a/cloudflare-worker/hubspot-proxy.js +++ b/cloudflare-worker/hubspot-proxy.js @@ -131,7 +131,7 @@ export default { // ── action: requestVerification ────────────────────────── // Génère un token unique, le stocke en KV avec les infos du contact, - // et envoie un email de validation via Resend (avec un lien de + // et envoie un email de validation via Brevo (avec un lien de // confirmation). Le contact ne reçoit la référence et l'adresse // Paris qu'APRÈS avoir cliqué sur le lien. // Anti-bot : Turnstile vérifié d'abord. @@ -170,7 +170,7 @@ export default { // ── action: verifyToken ────────────────────────────────── // Appelé par confirmation.html quand l'utilisateur clique sur // le lien dans l'email de validation. Lit le token en KV, - // envoie le welcome (avec ref + adresse Paris) via Resend, + // envoie le welcome (avec ref + adresse Paris) via Brevo, // puis supprime le token (one-time use). if (action === 'verifyToken') { if (!body.token) return jsonResponse({ error: 'token requis' }, 400); @@ -184,7 +184,7 @@ export default { const tokenData = JSON.parse(raw); try { - await sendWelcomeViaResend(env, tokenData); + await sendWelcomeViaBrevo(env, tokenData); // Marque le token consommé (gardé 7j pour idempotence en cas de // double clic du lien, mais avec flag "used") await env.WELCOME_KV.put(key, JSON.stringify({ ...tokenData, used: true, usedAt: new Date().toISOString() }), { @@ -426,38 +426,47 @@ async function sendWelcomeEmail(env, params) { } // ============================================================= -// Resend : envoi d'emails (verification + welcome) +// Brevo (ex-Sendinblue) : envoi d'emails (verification + welcome) // ============================================================= -// Resend est utilisé pour envoyer les emails car il ne nécessite -// pas de template séparé (on construit le HTML directement dans le -// Worker). Free tier : 100 emails/jour, 3000/mois. +// Brevo est utilisé pour l'envoi car il accepte la "single-sender +// verification" : on valide juste une adresse email (mvaglobalfret@gmail.com) +// au lieu de devoir vérifier tout un domaine. Free tier : 300 emails/jour. // // Setup requis : -// - env.RESEND_API_KEY = clé API Resend (re_...) -// - env.RESEND_FROM = adresse expéditrice vérifiée chez Resend -// (ex: "MVA Global Fret ") -// Pour test : "onboarding@resend.dev" -// - env.SITE_URL = base URL du site (ex: "https://mva-global-fret.github.io/site-mva-global-fret") +// - env.BREVO_API_KEY = clé API Brevo (xkeysib-...) +// - env.BREVO_SENDER_EMAIL = adresse expéditrice validée chez Brevo +// (ex: "mvaglobalfret@gmail.com") +// - env.BREVO_SENDER_NAME = nom affiché à l'expéditeur (ex: "MVA Global Fret") +// - env.SITE_URL = base URL du site (ex: "https://mva-global-fret.github.io/site-mva-global-fret") +// +// API doc : https://developers.brevo.com/reference/sendtransacemail -const RESEND_API = 'https://api.resend.com/emails'; +const BREVO_API = 'https://api.brevo.com/v3/smtp/email'; -async function resendSend(env, { to, subject, html }) { - if (!env.RESEND_API_KEY) { - throw new Error('RESEND_API_KEY env var not set'); +async function brevoSend(env, { to, subject, html }) { + if (!env.BREVO_API_KEY) { + throw new Error('BREVO_API_KEY env var not set'); } - const from = env.RESEND_FROM || 'MVA Global Fret '; + const senderEmail = env.BREVO_SENDER_EMAIL || 'mvaglobalfret@gmail.com'; + const senderName = env.BREVO_SENDER_NAME || 'MVA Global Fret'; - const res = await fetch(RESEND_API, { + const res = await fetch(BREVO_API, { method: 'POST', headers: { - 'Authorization': `Bearer ${env.RESEND_API_KEY}`, - 'Content-Type': 'application/json', + 'api-key' : env.BREVO_API_KEY, + 'accept' : 'application/json', + 'content-type': 'application/json', }, - body: JSON.stringify({ from, to: [to], subject, html }), + body: JSON.stringify({ + sender : { name: senderName, email: senderEmail }, + to : [{ email: to }], + subject : subject, + htmlContent: html, + }), }); if (!res.ok) { const text = await res.text(); - throw new Error(`Resend ${res.status}: ${text}`); + throw new Error(`Brevo ${res.status}: ${text}`); } return res.json(); } @@ -504,14 +513,14 @@ async function sendVerificationEmail(env, contact, verToken) { `; - return resendSend(env, { + return brevoSend(env, { to: contact.email, subject: 'Confirmez votre inscription chez MVA Global Fret', html, }); } -async function sendWelcomeViaResend(env, contact) { +async function sendWelcomeViaBrevo(env, contact) { const firstname = escapeHtml(contact.firstname || ''); const ref = escapeHtml(contact.reference_client || ''); const parisAddrRaw = env.PARIS_DEPOT_ADDRESS || ''; @@ -559,7 +568,7 @@ async function sendWelcomeViaResend(env, contact) { `; - return resendSend(env, { + return brevoSend(env, { to: contact.email, subject: `Bienvenue chez MVA Global Fret — Votre référence ${ref}`, html, diff --git a/js/confirmation.js b/js/confirmation.js index dcf78d7..40215b2 100644 --- a/js/confirmation.js +++ b/js/confirmation.js @@ -2,7 +2,7 @@ // MVA Global Fret — Page de confirmation post-validation email // ============================================================ // Cette page est la cible du lien dans l'email de validation -// (envoyé par Resend après soumission du formulaire). +// (envoyé par Brevo après soumission du formulaire). // // URL : https://mva-global-fret.github.io/site-mva-global-fret/confirmation.html?token=XXX // @@ -10,7 +10,7 @@ // 1. Lire le token depuis l'URL // 2. POST au Worker avec action 'verifyToken' // 3. Worker valide le token, envoie le welcome email (avec ref + -// adresse Paris) via Resend, puis renvoie OK +// adresse Paris) via Brevo, puis renvoie OK // 4. Page affiche "Inscription confirmée !" // // Si le token est invalide / expiré : affichage d'un message d'erreur diff --git a/js/form-handler.js b/js/form-handler.js index ffded90..c0a6d55 100644 --- a/js/form-handler.js +++ b/js/form-handler.js @@ -304,7 +304,7 @@ function showSuccess(refNumber, clientData) { // ── EMAIL DE VÉRIFICATION ───────────────────────────────────────────────────── // Le Worker génère un token unique, le stocke en KV, et envoie un email -// de validation via Resend (avec un lien de confirmation). Le contact ne +// de validation via Brevo (avec un lien de confirmation). Le contact ne // reçoit la référence et l'adresse Paris qu'APRÈS avoir cliqué sur le lien. async function sendWelcomeEmail(data) { if (!WORKER_PROXY_URL) return;