- Nature
- Outil interne
- Stack
- Next.jsNestJSPrismaPostgreSQLRedisSMTP / IMAPZodIA
Prospecter cinq produits avec cinq boîtes mail, c'est jongler entre des tableurs, des relances oubliées et des réponses noyées dans les webmails. KMail rassemble tout dans un cockpit local : un contact entre dans une séquence, chaque étape part depuis la vraie boîte de l'app, et tout s'arrête dès qu'une réponse arrive.
Ce que fait l'outil
- Contacts par app : import CSV avec aperçu (doublons, invalides, déjà présents) sans écriture, listes par tag, segments enregistrés comme critères rejouables, export CSV, chronologie fusionnée par contact.
- Séquences : étapes avec délais, variables
{{prenom}}et{{entreprise}}, fenêtre d'envoi en heure de Paris, plafond quotidien par boîte, bibliothèque de 39 modèles dont chaque fait vient d'un document de référence. - Simulation et planning : rendu de chaque email pour de vrais contacts avec sa date prévue, check-list d'activation (désinscription, variables, liens, SPF/DKIM), projection des envois sur 14 jours.
- Suivi des ouvertures, clics, réponses, rejets et désinscriptions, avec des taux affichés « — » tant que le dénominateur est nul.
- Boîte de réception : réponses rapprochées des envois, classement assisté par IA (suggestion, jamais appliquée seule), réponse depuis la boîte de l'app dans le même fil.
- Délivrabilité : vérification SPF, DKIM, DMARC et MX de chaque domaine, coût des appels IA suivi au micro-dollar.
Stack et architecture
- Monorepo pnpm et Turborepo : API NestJS sur Fastify, backoffice Next.js 16 (React 19, TanStack Query), Prisma sur PostgreSQL, Redis, schémas Zod partagés.
- Envoi en SMTP (nodemailer) depuis la boîte de chaque app, lecture des réponses en IMAP (imapflow, mailparser) : aucune API d'emailing tierce.
- Planificateur toutes les minutes ; ports et adaptateurs pour le transport, la source entrante et la signature des jetons, avec des fonctions pures pour le rendu, la fenêtre d'envoi et le rapprochement des réponses.
- Liens de suivi et désinscription signés en HMAC-SHA256, redirection uniquement vers l'URL stockée, en-têtes
List-Unsubscribeconformes à la RFC 8058. - Un seul compte administrateur créé depuis l'environnement, journal d'audit, secrets jamais en base. Une trentaine de fichiers de tests unitaires.
Ce qui a été difficile
Rattacher une réponse au bon envoi. Une réponse ne porte pas l'identifiant du contact : il faut retrouver le message d'origine par les en-têtes In-Reply-To et References, en écartant les notifications de non-remise et les réponses automatiques d'absence, qui ne sont pas des réponses. Le rapprochement est découpé en deux fonctions pures : la première dit quoi chercher en base, la seconde tranche à partir de ce qui a été trouvé, ce qui permet de tout tester sans boîte mail. Autre point délicat : une désinscription ou un rejet définitif vaut pour toutes les apps, la liste de suppression est donc globale et consultée avant chaque envoi.
État du projet
Outil interne, utilisé en local. Les captures montrent des données de démonstration fictives.
Captures réalisées sur une base de démonstration : les chiffres affichés sont fictifs.


