diff --git a/cloudflare-worker/hubspot-proxy.js b/cloudflare-worker/hubspot-proxy.js
index 04db6c7..cb9e473 100644
--- a/cloudflare-worker/hubspot-proxy.js
+++ b/cloudflare-worker/hubspot-proxy.js
@@ -53,8 +53,9 @@
//
// ============================================================
-// Fallbacks utilisés uniquement si les env vars ne sont pas définies dans Cloudflare
-const FALLBACK_TOKEN = 'pat-eu1-e3c92146-bb17-45fe-8d77-0c665fc4df3b';
+// Fallbacks pour les valeurs publiques d'EmailJS (déjà visibles dans le
+// JavaScript du site). Le token HubSpot, lui, doit OBLIGATOIREMENT venir
+// de la variable d'environnement Cloudflare `HUBSPOT_TOKEN` (sinon erreur).
const FALLBACK_EMAILJS_PUBLIC_KEY = '8KUlaQ7BDVIbkZRyP';
const FALLBACK_EMAILJS_SERVICE_ID = 'service_aeamo3x';
const FALLBACK_EMAILJS_TEMPLATE_ID= 'template_s1kr2et';
@@ -81,7 +82,10 @@ export default {
return new Response('Method Not Allowed', { status: 405 });
}
- const token = env.HUBSPOT_TOKEN || FALLBACK_TOKEN;
+ const token = env.HUBSPOT_TOKEN;
+ if (!token) {
+ return jsonResponse({ error: 'HUBSPOT_TOKEN env var not set' }, 500);
+ }
try {
const body = await request.json();
@@ -98,6 +102,62 @@ export default {
return jsonResponse({ ok: true, stats });
}
+ // ── action: sendWelcomeNow ───────────────────────────────
+ // Envoi immédiat du welcome email via EmailJS (avec l'adresse
+ // Paris depuis env var). Appelé par form-handler.js après
+ // soumission du formulaire. L'adresse n'apparaît jamais dans
+ // le code JS public — elle vient des secrets Cloudflare.
+ if (action === 'sendWelcomeNow') {
+ if (!body.email) return jsonResponse({ error: 'email requis' }, 400);
+ try {
+ await sendWelcomeEmail(env, {
+ firstname : body.firstname || '',
+ email : body.email,
+ reference_client : body.reference_client || '',
+ });
+ return jsonResponse({ ok: true });
+ } catch (err) {
+ return jsonResponse({ ok: false, error: err.message }, 500);
+ }
+ }
+
+ // ── action: listSubscriptions (debug : trouver les IDs) ──
+ if (action === 'listSubscriptions') {
+ // Endpoint legacy email/public/v1 nécessite scope content au lieu de
+ // communication_preferences (que notre token n'a pas)
+ const r = await fetch(`${HUBSPOT_API}/email/public/v1/subscriptions`, {
+ headers: { 'Authorization': `Bearer ${token}` },
+ });
+ return jsonResponse(await r.json());
+ }
+
+ // ── action: subscribe ────────────────────────────────────
+ // Inscrit un contact à un type d'abonnement marketing (déclenche
+ // l'envoi du mail de double opt-in si DOI activé au niveau compte).
+ if (action === 'subscribe') {
+ if (!email || typeof email !== 'string') {
+ return jsonResponse({ error: 'Email requis' }, 400);
+ }
+ const subId = body.subscriptionId;
+ if (!subId) return jsonResponse({ error: 'subscriptionId requis' }, 400);
+
+ const r = await fetch(`${HUBSPOT_API}/communication-preferences/v3/subscribe`, {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ 'Authorization': `Bearer ${token}`,
+ },
+ body: JSON.stringify({
+ emailAddress: email.toLowerCase().trim(),
+ subscriptionId: subId,
+ legalBasis: 'LEGITIMATE_INTEREST_CLIENT',
+ legalBasisExplanation: 'Soumission du formulaire MVA Global Fret',
+ }),
+ });
+ const data = await r.text();
+ return jsonResponse({ status: r.status, body: data });
+ }
+
// ── action par défaut : vérification doublon par email ──
if (!email || typeof email !== 'string') {
return jsonResponse({ error: 'Email requis' }, 400);
@@ -123,7 +183,7 @@ export default {
// File d'attente : envoi du welcome aux contacts confirmés
// =============================================================
async function processWelcomeQueue(env) {
- const token = env.HUBSPOT_TOKEN || FALLBACK_TOKEN;
+ const token = env.HUBSPOT_TOKEN;
const stats = { scanned: 0, sent: 0, skipped: 0, errors: 0 };
// Liste des contacts qui ont CONFIRMÉ leur opt-in marketing
@@ -236,7 +296,7 @@ async function getNextRef(token) {
},
body: JSON.stringify({
filterGroups: [{
- filters: [{ propertyName: 'reference_client', operator: 'HAS_PROPERTY', value: '' }],
+ filters: [{ propertyName: 'reference_client', operator: 'HAS_PROPERTY' }],
}],
properties: ['reference_client'],
limit: 100,
diff --git a/contact.html b/contact.html
index 79a0dce..909981a 100644
--- a/contact.html
+++ b/contact.html
@@ -76,10 +76,10 @@
Remplissez ce formulaire pour recevoir votre numéro de référence client et l'adresse de dépôt à Paris.
diff --git a/js/form-handler.js b/js/form-handler.js
index 527a8fa..91b854c 100644
--- a/js/form-handler.js
+++ b/js/form-handler.js
@@ -283,24 +283,34 @@ function showSuccess(refNumber, clientData) {
}
if (form) form.style.display = 'none';
- // L'email de bienvenue avec la référence client n'est plus envoyé ici.
- // HubSpot envoie d'abord un email de double opt-in, et le numéro de
- // référence apparaît dans cet email (token {{contact.reference_client}}).
- // → la référence ne fuite plus avant validation de l'email.
+ // Envoi de l'email de bienvenue (avec la référence + l'adresse Paris)
+ // directement après inscription. Les bots qui soumettent avec un faux
+ // email ne reçoivent rien (boîte inexistante = bounce). Pour bloquer
+ // les bots qui utilisent de vrais emails, voir la protection honeypot
+ // dans validateForm() + le rate limit côté worker.
+ if (clientData) sendWelcomeEmail(clientData);
}
// ── EMAIL DE BIENVENUE ────────────────────────────────────────────────────────
+// Envoyé via le Cloudflare Worker pour que l'adresse Paris ne soit JAMAIS
+// présente dans le JS public. Le Worker fait le call EmailJS REST avec
+// le PARIS_DEPOT_ADDRESS depuis ses variables d'environnement.
async function sendWelcomeEmail(data) {
- if (typeof emailjs === 'undefined') return;
+ if (!WORKER_PROXY_URL) return;
try {
- await emailjs.send(EMAILJS_SERVICE_ID, EMAILJS_TEMPLATE_ID, {
- firstname: data.firstname,
- email: data.email,
- reference_client: data.reference_client,
+ await fetch(WORKER_PROXY_URL, {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({
+ action: 'sendWelcomeNow',
+ firstname: data.firstname,
+ email: data.email,
+ reference_client: data.reference_client,
+ }),
});
} catch (err) {
// L'email de bienvenue est un bonus — on ne bloque pas l'inscription si ça échoue
- console.warn('EmailJS welcome email failed:', err);
+ console.warn('Welcome email failed:', err);
}
}
diff --git a/js/translations.js b/js/translations.js
index d1ae64a..dcad552 100644
--- a/js/translations.js
+++ b/js/translations.js
@@ -150,11 +150,11 @@ const translations = {
placeholderAdresse: "Adresse complète...",
submitBtn: "S'inscrire",
submitLoading: "Envoi en cours...",
- successTitle: "Vérifiez votre boîte mail !",
- successMsg: "Pour finaliser votre inscription, cliquez sur le lien de confirmation que nous venons de vous envoyer par email. Vous recevrez ensuite votre numéro de référence client.",
+ successTitle: "Inscription réussie !",
+ successMsg: "Merci ! Votre inscription a bien été enregistrée. Un email de bienvenue avec votre numéro de référence client et l'adresse de dépôt à Paris vient de vous être envoyé.",
refLabel: "VOTRE NUMÉRO DE RÉFÉRENCE CLIENT",
successNote: "Conservez ce numéro précieusement — il vous sera utile pour suivre vos colis.",
- emailSent: "📧 Email envoyé — pensez aussi à vérifier vos spams.",
+ emailSent: "📧 Vérifiez votre boîte mail (et vos spams).",
alreadyTitle: "Vous êtes déjà client !",
alreadyMsg: "Votre adresse email est déjà enregistrée dans notre système.",
alreadyRefLabel: "VOTRE NUMÉRO DE RÉFÉRENCE EXISTANT",
@@ -502,11 +502,11 @@ const translations = {
placeholderAdresse: "Full address...",
submitBtn: "Register",
submitLoading: "Sending...",
- successTitle: "Check your inbox!",
- successMsg: "To complete your registration, click the confirmation link we just sent to your email. You'll then receive your client reference number.",
+ successTitle: "Registration successful!",
+ successMsg: "Thank you! Your registration has been recorded. A welcome email with your client reference number and the Paris depot address has just been sent to you.",
refLabel: "YOUR CLIENT REFERENCE NUMBER",
successNote: "Keep this number safe — you'll need it to track your parcels.",
- emailSent: "📧 Email sent — don't forget to check your spam folder.",
+ emailSent: "📧 Check your inbox (and your spam folder).",
alreadyTitle: "You are already a client!",
alreadyMsg: "Your email address is already registered in our system.",
alreadyRefLabel: "YOUR EXISTING REFERENCE NUMBER",
@@ -854,11 +854,11 @@ const translations = {
placeholderAdresse: "Adiresy feno...",
submitBtn: "Hisoratra anarana",
submitLoading: "Alefa...",
- successTitle: "Jereo ny boaty mailaka!",
- successMsg: "Mba hahafenitra ny fisoratana anarana, tsindrio ny rohy fanamafisana nalefa tao amin'ny mailakao. Avy eo dia handray ny laharanao mpanjifa ianao.",
+ successTitle: "Vita ny fisoratana anarana!",
+ successMsg: "Misaotra! Voaray tsara ny fisoratana anaranareo. Nisy mailaka fandraisana miaraka amin'ny laharanao mpanjifa sy ny adiresy fametrahana any Paris vao nalefa ho anao.",
refLabel: "NY LAHARANAO MPANJIFA",
successNote: "Tehirizo tsara ity laharana ity — ilaina amin'ny fanaraha-maso ny entanao.",
- emailSent: "📧 Nalefa ny mailaka — jereo koa ao amin'ny spam.",
+ emailSent: "📧 Jereo ny boaty mailaka (sy ny spam).",
alreadyTitle: "Efa mpanjifa ianao!",
alreadyMsg: "Efa voasoratra ao amin'ny rafitra ny adiresy mailaka.",
alreadyRefLabel: "NY LAHARANAO EFA MISY",