Case Study

Construire un SaaS
d'email marketing
de zero

Comment j'ai concu et developpe Maestro, une plateforme complete d'email marketing avec scoring algorithmique, architecture micro-services et modele SaaS multi-tenant.

PHP 8.3 / Symfony 7.2 Python 3 / Flask MySQL PWA REST API

01 — Probleme

Les outils existants ne repondent pas
aux besoins reels

Les plateformes d'email marketing imposent des quotas, des tarifs progressifs et des boites noires algorithmiques. L'utilisateur paye de plus en plus cher a mesure qu'il grandit, sans comprendre pourquoi certains contacts sont "qualifies".

💸

Tarification punitive

Les leaders du marche (Mailchimp, Brevo, Sendinblue) facturent par palier de contacts ou d'envois. Plus on grandit, plus on paye — sans valeur ajoutee proportionnelle.

🔍

Scoring opaque

Le "lead scoring" repose sur des algorithmes IA proprietaires. Impossible de comprendre pourquoi un contact est "chaud" ou "froid", ni d'ajuster les criteres.

🔒

Dependance SMTP

L'utilisateur est lie au serveur SMTP du fournisseur. Pas de possibilite d'utiliser son propre serveur, d'ou un controle limite sur la delivrabilite.

📊

Analytics fragmentees

Les metriques d'engagement (ouvertures, clics, bounces) vivent dans des CSV Mailjet ou des dashboards separes. Pas de reconciliation automatique.


02 — Reflexion

Chaque decision technique
a ete un arbitrage

Avant d'ecrire la moindre ligne de code, chaque choix a ete pese : cout, complexite, scalabilite, experience utilisateur.

⚖ Monolithe ou micro-services ?

Full monolithe PHP Full micro-services ✓ Hybride : Symfony + micro-service Python

Le scoring et la segmentation necessitent des calculs complexes (pipelines, ponderation, classification). Python excelle ici. Le reste (auth, CRUD, envoi SMTP, UI) est du domaine de Symfony. Communication via REST interne — simple, testable, decouple.

⚖ Scoring IA ou algorithmique deterministe ?

Machine Learning (modele entraine) ✓ Algorithme deterministe a regles

Un modele ML necessite des donnees d'entrainement massives et reste une boite noire. L'algorithme deterministe est transparent : l'utilisateur comprend exactement pourquoi un contact est "Hot" (score 0.85) ou "Dead" (hard bounce detecte). Regles claires, reproductibles, ajustables.

⚖ Quotas ou anti-partage ?

Quotas par contacts/envois Limites par volume ✓ Limitation a 2 appareils par compte

Les quotas punissent l'utilisateur honnete qui grandit. Au lieu de limiter l'usage, on limite le partage : 2 appareils max (bureau + laptop), enregistrement par cookie token UUID v4. L'utilisateur honnete ne voit jamais la limite. Le partage frauduleux est bloque naturellement.

⚖ Docker / Kubernetes ou SaaS mutualise ?

Docker par tenant Kubernetes ✓ Multi-tenant sur VPS unique

Docker par tenant = overhead enorme pour un SaaS a 12€/mois. L'isolation se fait par la couche applicative (filtrage user_id sur chaque requete Doctrine), pas par l'infrastructure. Un VPS 8 vCores / 16 Go RAM supporte des centaines d'utilisateurs.

⚖ Flutter ou PWA ?

Application Flutter native ✓ PWA (Progressive Web App)

Flutter aurait necessite un projet separe, une double maintenance, et une captation des KPIs complexe (API intermediaire). La PWA reutilise 100% du code existant : manifest, service worker, mode offline — installable sur mobile et desktop sans friction.


03 — Solution

Maestro : une plateforme
pensee pour l'autonomie

12€/mois, sans quotas, sans limites de contacts ou d'envois. L'utilisateur branche son propre SMTP et garde le controle total.

Scoring transparent et deterministe

Chaque contact recoit un score de 0 a 100% base sur des regles explicites. L'utilisateur voit exactement pourquoi.

  • Domaine professionnel = +10%, generique (info@) = -15%
  • Clic dans un email = +25%, ouverture = +12%
  • Hard bounce ou spam = score force a 0 (Dead)
  • Completude du profil (prenom, nom, tel) = jusqu'a +15%
Hot
35%
Warm
28%
Cold
25%
Dead
12%
Hot Warm Cold Dead

SMTP autonome avec throttling intelligent

L'utilisateur branche n'importe quel serveur SMTP. Le systeme gere le reste.

  • Presets : Gmail, OVH, Mailjet, Brevo, Outlook 365
  • Throttle : 800ms entre chaque email, pause de 30s tous les 30 emails
  • Reprise automatique : si l'envoi echoue, reprise sans doublons
  • DSN dynamique par utilisateur (multi-tenant)
MailerFactory.php
// DSN construit dynamiquement par user match($encryption) { 'ssl' => "smtps://user:pass@host:port", 'tls' => "smtp://user:pass@host:587", 'none' => "smtp://...?verify_peer=0", };

Tracking temps reel via webhooks

Chaque interaction (ouverture, clic, bounce, spam) remonte en temps reel depuis Mailjet.

  • Reconciliation automatique via Message ID
  • Fallback par email si le Message ID manque
  • 7 types d'evenements : sent, open, click, bounce, spam, unsub, blocked
  • Analyse multi-campagnes pour identifier les contacts les plus engages
Mailjet
evenement
Webhook
/webhook/mailjet
SendLog
Message ID
CampaignEvent
persistance

Anti-partage intelligent

Au lieu de punir l'utilisateur avec des quotas, on limite le nombre d'appareils.

  • 2 appareils max par compte (bureau + laptop)
  • Token UUID v4 en cookie (1 an de duree)
  • L'utilisateur renomme ses appareils ("Bureau", "Laptop maison")
  • 3e appareil = page de gestion, pas de blocage brutal
🖥
Bureau
Chrome — Derniere activite : aujourd'hui
● Actif
💻
Laptop maison
Firefox — Derniere activite : hier
● Actif
2/2 appareils utilises

04 — Architecture

Deux langages, un systeme

Symfony gere l'interface et la logique metier. Python gere le calcul. Ils communiquent via REST interne avec un token partage.

Navigateur | | HTTP v Symfony 7.2 ─────────── REST (localhost:5050) ──────────> Flask / Python | X-Analytics-Token | | Doctrine ORM | Pipelines v v MySQL 9.1 Scoring engine campaign_analyzer reconciliation relance_analyzer segmentation
PHP 8.3 / Symfony 7.2
Python 3 / Flask
MySQL 9.1
Vanilla JS / Chart.js

Flux utilisateur

Inscription

Formulaire simple (email + mot de passe). Compte cree en mode trial pour 7 jours. Cookie device enregistre automatiquement.

Onboarding

Wizard 3 etapes (SMTP, profil, pret). Skippable a tout moment — l'utilisateur peut configurer plus tard dans Parametres.

Utilisation quotidienne

Import contacts CSV, creation de campagnes, envoi, suivi temps reel via webhooks, scoring automatique. PWA installable sur mobile.

Analyse et optimisation

Dashboard avec KPI, analyse par campagne, analyse multi-campagnes (relance), reconciliation Mailjet, segmentation automatique.

Fin de l'essai (J+7)

Redirection vers la page d'abonnement. 12€/mois pour continuer. Pas de quotas, pas de limites.


05 — Resultats

Ce que le projet demontre

8
Entites Doctrine
12
Controllers
4
Pipelines Python
2
Langages serveur
🏗

Architecture micro-services

Decouplage PHP/Python avec communication REST, token d'authentification, et degradation gracieuse si Python est offline.

🧠

Algorithmique

Moteur de scoring deterministe avec ponderation multi-criteres : profil, domaine email, engagement, historique d'envoi. Classification Hot/Warm/Cold/Dead.

🛡

Securite applicative

CSRF, isolation des donnees par user_id, hachage bcrypt, validation stricte des entrees, gestion des appareils par token UUID.

📱

PWA & Responsive

Service worker (network-first), manifest installable, page offline, design mobile-first avec sidebar retractable.

📨

Integration tierce

Webhooks Mailjet en temps reel, import/export CSV, reconciliation des donnees entre systemes, presets SMTP multi-fournisseurs.

💰

Modelisation SaaS

Multi-tenant applicatif, gestion d'essai (7j), abonnement, anti-partage, onboarding guide — toute la logique business d'un vrai SaaS.