mailstail ou comment unifier et prioriser vos boîtes mail

Jongler entre plusieurs boîtes mail devient vite un enfer. J'ai développé mailstail, une interface légère qui centralise Gmail, Yahoo, IMAP et autres, avec un scoring automatique pour prioriser l'important. Un PoC open source pour reprendre le contrôle de sa messagerie.

Cet article prend 8 minutes à lire et comporte 1891 mots.

J’ai récem­ment trou­vé, quelque part sur le web, des infos con­cer­nant gmail­tail – un petit out­il malin capa­ble d’ex­traire au for­mat JSON les cour­riels reçus dans votre boîte Gmail.

Mais cet out­il est lim­ité à Gmail. Or moi, ce que je voulais, c’é­tait un client mail intel­li­gent trans­ver­sal : Gmail, Yahoo, Exchange, Free, Orange, ou tout sim­ple­ment ma boîte mail per­so en IMAP, hébergée chez un four­nisseur classique.

Alors j’ai posé mon idée.

Puis j’ai com­mencé à pro­to­typer un out­il, que j’ai appelé mail­stail. Une inter­face mail mul­ti-comptes légère, intel­li­gente, capa­ble de me mon­tr­er en un coup d’œil ce qui est impor­tant… ou pas.

Objectifs fonctionnels

Ce que je voulais pour cette inter­face mail mul­ti-comptes, c’é­tait très sim­ple (du moins en apparence) :

  • voir les derniers cour­riels reçus (toutes boîtes confondues)
  • pri­oris­er les emails automa­tique­ment (impor­tant / moyen / faible)
  • répon­dre directe­ment depuis l’interface
  • sup­primer un indésir­able en un clic
  • éventuelle­ment : pro­pos­er une réponse automa­tique (LLM) ou un résumé intelligent

Panorama des solutions existantes

Aujour­d’hui, si vous con­sul­tez vos mails, vous avez plus ou moins deux choix :

  • soit vous utilisez l’in­ter­face web du four­nisseur (Gmail, Out­look, Free, etc.)
  • soit vous passez par un client mail lourd comme Thun­der­bird ou Outlook

Mais dès que vous avez plus d’une boîte mail, ça devient un enfer :

J’ai une adresse per­so, une autre « offi­cielle » (four­nisseurs de ser­vices, impôts, CAF, avo­cat…), une adresse uni­ver­si­taire, une adresse pro… et chaque jour, je dois pass­er d’un onglet à l’autre, ou d’un compte à l’autre.

Soit je passe d’on­glet en onglet dans un nav­i­ga­teur web, en ayant devant les yeux une masse informe de cour­riels venus d’i­ci et d’ailleurs, soit je con­sulte mon appli­ca­tion (Thun­der­bird), mais dans chaque dossier, j’ai la même masse informe de cour­riels à traiter. Et en plus, je ne pense pas for­cé­ment à con­sul­ter chaque dossier.

Autant dire que la décou­verte de cet out­il m’a inter­pelé, et que j’ai eu envie de dévelop­per une inter­face mail intel­li­gente qui me per­me­tte d’op­ti­miser mon temps de consultation.

Je passe :

  • d’une masse informe de mails dans tous les sens,
  • sans aucun repère visuel,
  • sans aucune aide à la décision

à :

  • une infor­ma­tion structurée,
  • une visu­al­i­sa­tion rapi­de des mes­sages importants
  • avec une pos­si­bil­ité d’in­ter­a­gir en temps réel

Les outils d’analyse automatique pour emails

En creu­sant, j’ai décou­vert plusieurs briques tech­nologiques pour le scor­ing automa­tique des emails :

  • Let­tria : puis­sante, mais un peu usine à gaz pour un besoin simple
  • spa­Cy : rapi­de, fiable, per­son­nal­is­able (et open source)
  • Camem­BERT : effi­cace, mais plus lourd (Trans­form­ers, GPU, RAM…)
  • Mail​pars​er​.io : intéres­sant pour des for­mu­laires ou flux structurés

Mon choix : rester léger avec spa­Cy NLP, en inté­grant un sys­tème de scor­ing pondéré basé sur les mots-clés et les entités nommées.

Architecture globale

Un seul mot d’or­dre : sim­plic­ité et robustesse.

graph TD
  A["Récupération IMAP/API"] --> B["Scoring spaCy"]
  B --> C["Affichage frontend (React)"]
  C --> D["Réponse manuelle ou auto"]
  C --> E["Suppression / action"]

Choix techniques initiaux

Le back­end est con­stru­it en Python, un lan­gage que je maîtrise bien et qui offre un excel­lent écosys­tème pour tout ce qui est traite­ment de texte, NLP et ges­tion d’emails (IMAP, encodage, pars­ing mul­ti­part…). C’est aus­si un lan­gage bien doc­u­men­té, idéal pour con­stru­ire une base robuste et évolutive.

Pour la couche API, j’ai opté pour FastAPI. Pourquoi FastAPI et pas Flask ? D’abord pour la vitesse de développe­ment, ensuite pour la détec­tion automa­tique des types, la doc­u­men­ta­tion Swag­ger inté­grée, et enfin parce qu’il est conçu pour du asyn­chrone – ce qui me per­me­t­tra plus tard de scaler ou de pass­er à du mul­ti-thread sans tout refaire.

Côté fron­tend, le choix s’est porté sur React pour sa large com­mu­nauté et sa sou­p­lesse. Asso­cié à Vite (plutôt que Web­pack), le com­bo per­met une com­pi­la­tion rapi­de, un recharge­ment ultra-flu­ide en développe­ment, et une inter­face respon­sive mod­erne mais légère. J’avais aus­si envis­agé Vue, mais React reste à mes yeux plus robuste et plus main­tenu à long terme.

Enfin, Dock­er s’est imposé pour encap­suler le tout. Avec Dock­er Com­pose, je peux builder, lancer, déploy­er et met­tre à jour l’ensem­ble du pro­jet (fron­tend + back­end + proxy) en une seule ligne. Ce n’é­tait pas indis­pens­able au début, mais c’est vite devenu essen­tiel pour tester sur dif­férents environnements.

Architecture technique détaillée

Un seul mot d’or­dre : sim­plic­ité et robustesse.

Récupéra­tion IMAP/API → Scor­ing spa­Cy → Affichage fron­tend (React) → Réponse manuelle ou auto → Sup­pres­sion / action

  • IMAP + OAuth2 pour com­pat­i­bil­ité avec Gmail, Yahoo, etc.
  • Fall­back avec mot de passe (Free, Orange, etc.)
  • Affichage mul­ti-comptes mail, avec icône col­orée selon la source
  • Pri­or­i­sa­tion automa­tique par niveau d’importance
  • Logs des mails analysés pour audit ou rétroaction

Détails techniques

L’un des enjeux dès le départ était de faire tourn­er ce pro­jet même sur des con­fig­u­ra­tions mod­estes (ex. : VPS à 1 vCPU, 512 Mo de RAM). Il fal­lait donc éviter les solu­tions trop lour­des ou trop exigeantes.

Côté back­end, j’ai préféré un traite­ment séquen­tiel sim­ple au départ, plutôt que d’im­plé­menter de l’a­syn­chrone ou du mul­ti­thread trop tôt. FastAPI per­met de faire du async pro­pre­ment, mais encore fal­lait-il ne pas com­pli­quer inutile­ment la logique de traite­ment dès la pre­mière ver­sion. La struc­ture actuelle pour­rait facile­ment bas­culer vers du async ou de la file de tâch­es plus tard, mais ce n’est pas une pri­or­ité à ce stade.

Pour les con­nex­ions IMAP, j’ai inté­gré un ges­tion­naire de ses­sion capa­ble de dis­tinguer les con­nex­ions OAuth2 (pour Gmail, Out­look, Yahoo…) des con­nex­ions par mot de passe appli­catif plus clas­siques. Le principe est sim­ple : si les vari­ables d’en­vi­ron­nement con­ti­en­nent un token OAuth2 valide, on utilise ce mode d’au­then­tifi­ca­tion, sinon, on revient à une authen­tifi­ca­tion clas­sique. Le back­end est donc capa­ble d’a­juster dynamique­ment sa méth­ode d’au­then­tifi­ca­tion sans que l’u­til­isa­teur n’ait à faire le moin­dre choix manuel.

Le pars­ing des emails a néces­sité pas mal de soin pour gér­er toutes les vari­antes : encodage bizarre, con­tenus mul­ti­part avec pièces jointes, HTML crades, etc. Là encore, un traite­ment robuste mais léger était le bon compromis.

Côté scor­ing intel­li­gent, spa­Cy est rapi­de, mais il a fal­lu cal­i­br­er la pondéra­tion pour obtenir des résul­tats per­ti­nents sans tomber dans le sur-appren­tis­sage ou le scor­ing gad­get. J’ai aus­si log­gué tous les mails traités dans un fichi­er .jsonl pour pou­voir analyser et ajuster le scor­ing a posteriori.

Sur le fron­tend React, React m’a per­mis de découper pro­pre­ment l’af­fichage des mes­sages (aperçu, détail, réponse), et d’a­jouter facile­ment des fonc­tion­nal­ités inter­ac­tives (bou­ton « Répon­dre », champ rich text caché par défaut, pri­or­i­sa­tion par couleur). Le choix de Vite a per­mis un cycle de développe­ment très flu­ide et des builds rapi­des, même sur machine modeste.

Backend FastAPI

Le back­end FastAPI est le cœur du traite­ment de l’ap­pli­ca­tion. Il est conçu pour recevoir des requêtes REST via FastAPI, traiter les mails (con­nex­ion IMAP ou via API), extraire leur con­tenu, appli­quer un scor­ing automa­tique et ren­voy­er les don­nées sous forme de JSON au frontend.

FastAPI a été choisi pour :

  • sa rapid­ité de développement,
  • son sup­port natif de l’a­syn­chrone (utile pour gér­er plusieurs con­nex­ions IMAP en par­al­lèle à terme),
  • sa doc­u­men­ta­tion automa­tique (Swag­ger UI très utile en développement),
  • et sa très bonne inté­gra­tion avec Pydan­tic pour la val­i­da­tion des modèles.

Les routes prin­ci­pales exposées sont :

  • GET /api/messages : récupère les mails triés et scorés
  • POST /api/reply : envoie une réponse à un mail donné

Le back­end est égale­ment respon­s­able de :

  • l’authen­tifi­ca­tion OAuth2 (avec refresh automatique),
  • la ges­tion mul­ti-comptes,
  • l’analyse des emails avec spa­Cy (entités + mots-clés pondérés),
  • le log­ging dans un fichi­er JSONL (audit, débo­gage, entraîne­ment futur).

Il est conçu pour tourn­er dans un con­teneur Dock­er isolé, avec son mod­èle spa­Cy préchargé et mon­té via volume.

Fonc­tion­nal­ités principales :

  • Authen­tifi­ca­tion dynamique selon les cre­den­tials disponibles (mot de passe ou OAuth2)
  • Pars­ing robuste des mails (mul­ti­part, charset, encodage…)
  • Scor­ing pondéré (key­words + entités via spaCy)
  • Expo­si­tion des mails via API REST /api/messages
  • Sup­port de la réponse via /api/reply

Logging JSONL pour le scoring

Chaque mail analysé est log­gué sous forme d’un objet JSON com­pact, stocké ligne par ligne dans un fichi­er .jsonl. Cela permet :

    Ne man­quez plus un article… 

    Abon­nez-vous à la newsletter ! 

    • de con­serv­er un his­torique léger et exploitable,
    • de recal­culer le scor­ing avec de nou­veaux paramètres,
    • de visu­alis­er les entités détec­tées et le niveau de pri­or­ité attribué,
    • d’en­traîn­er éventuelle­ment un mod­èle de clas­si­fi­ca­tion super­visée à l’avenir.

    Chaque entrée com­prend typ­ique­ment : timestamp, expediteur, sujet, score_final, entites, mots_cles_detectes, id_message.

    Frontend React

    Le fron­tend React repose sur React, avec Vite comme out­il de com­pi­la­tion. L’ob­jec­tif était d’avoir une inter­face légère à charg­er, réac­tive, sans fioritures.

    Les choix structurants :

    • util­i­sa­tion de com­posants React légers,
    • charge­ment pro­gres­sif des con­tenus (aperçu → détail → réponse),
    • inté­gra­tion de Quill.js pour le champ de réponse en rich text,
    • design respon­sive et com­pact pour pou­voir affich­er l’essen­tiel même sur petit écran.

    Par­mi les élé­ments nota­bles de l’inter­face mail :

    • un indi­ca­teur col­oré : 🔴 🟠 ⚪ pour la priorité,
    • une icône indi­quant le compte d’o­rig­ine (Gmail, Yahoo, etc.),
    • une ges­tion des mails par aperçu, avec les 3 pre­mières lignes vis­i­bles avec un bou­ton ou un lien « dévelop­per / replier »,
    • un bou­ton « Répon­dre » qui déclenche le charge­ment con­di­tion­nel de Quill.js (non mon­té par défaut, pour ne pas alour­dir le DOM).

    L’ensem­ble com­mu­nique avec le back­end via fetch sur les routes /api/messages et /api/reply. Les erreurs de token, de quo­ta ou de for­mat de mail sont gérées pro­pre­ment côté interface.

    Fonc­tion­nal­ités principales :

    • Liste des mails avec code couleur + source visuelle
    • Affichage des 3 pre­mières lignes avec bou­ton « Voir la suite »
    • Champ de réponse rich text inté­gré (Quill.js)
    • Com­posants réac­t­ifs et légers (Vite)

    Docker & Nginx

    Avant de choisir Nginx, j’ai pris le temps d’é­val­uer ce qu’of­fraient Apache et Open­Lite­Speed. Apache, aurait pu faire l’af­faire. Mais il est plus lourd, plus ver­beux, et néces­site plus de con­fig­u­ra­tion pour un sim­ple reverse proxy.

    Quant à Open­Lite­Speed, que je con­nais bien, il est rapi­de et mod­erne, mais sa con­fig­u­ra­tion en con­tain­er est un peu capricieuse, surtout quand il s’ag­it d’un pro­jet découpé en microservices.

    Finale­ment, j’ai choisi Nginx pour sa sim­plic­ité, sa sta­bil­ité, et sa doc­u­men­ta­tion ultra-com­plète. Il s’est imposé comme le bon choix pour :

    • Servir le fron­tend React compilé,
    • Prox­i­fi­er les requêtes vers /api/ vers FastAPI,
    • Offrir un point d’en­trée unique (idéal pour la ges­tion des CORS et des cer­ti­fi­cats SSL).

    Il est inté­gré au pro­jet via Dock­er Com­pose, avec une con­fig­u­ra­tion min­i­male mais robuste, et peut être rem­placé ou ignoré si l’on déploie sur une stack dif­férente (par exem­ple un héberge­ment man­agé avec son pro­pre reverse proxy).

    Gestion du rafraîchissement des tokens OAuth2

    L’un des points cru­ci­aux avec OAuth2, c’est que le token d’ac­cès fourni par le provider (comme Google ou Yahoo) a une durée de vie lim­itée – sou­vent autour d’une heure. Pour éviter de devoir rede­man­der une autori­sa­tion à l’u­til­isa­teur à chaque fois, il faut donc gér­er un refresh token.

    Dans mail­stail, j’ai mis en place un mécan­isme automa­tique dans le backend :

    • Le token d’ac­cès est véri­fié à chaque appel.
    • Si le token est expiré, une requête est faite vers le serveur OAuth2 (via requests​.post) pour obtenir un nou­veau token d’ac­cès à par­tir du refresh token.
    • Les nou­veaux tokens sont mis à jour dans un petit fichi­er de cache sécurisé, de manière trans­par­ente pour l’utilisateur.

    Cela per­met de main­tenir une con­nex­ion sta­ble et con­tin­ue, sans inter­ven­tion manuelle.

    Défis rencontrés & solutions apportées

    DéfiSolu­tion
    Rafraîchisse­ment des tokens OAuth2Automa­tisé dans backend
    Pars­ing HTML/texte complexeFall­back vers con­tenu brut
    Cal­i­brage du scor­ingPondéra­tion pro­gres­sive selon entités
    Quo­tas Gmail APIFall­back IMAP natif sécurisé
    UI lis­i­ble mal­gré la complexitéCom­posants React mod­u­laires + pro­gres­sive disclosure

    Perspectives d’évolution

    • Moteur de règles per­son­nal­is­ables (par l’utilisateur)
    • Envoi direct depuis l’inter­face mail
    • Résumés + propo­si­tions de réponse via LLM (option­nel)
    • Mul­ti­lingue
    • Portage mobile + noti­fi­ca­tions push

    Pourquoi aucune solution « clé en main » ne suffisait ?

    Parce qu’au­cune ne pro­po­sait à la fois :

    • une inter­face ultra-légère et rapide
    • le sup­port mul­ti-comptes IMAP
    • un scor­ing intel­li­gent mais lisible
    • un back­end open-source personnalisable

    Conclusion

    Ce pro­jet m’a per­mis de con­cili­er plusieurs choses :

    • mes besoins d’u­til­isa­teur exigeant
    • mes com­pé­tences tech­niques (Python, NLP, React)
    • mon envie de rester maître de mes données

    Et surtout : il m’a fait gag­n­er du temps.

    📦 Le pro­jet est libre, sous licence MIT.
    🔗 [ Dépôt GitHub : https://​github​.com/​p​c​e​s​c​a​t​o​/​m​a​i​l​s​t​ail ]
    💬 Sug­ges­tions bien­v­enues, issues ouvertes !

    Tu veux toi aus­si repren­dre le con­trôle sur ta mes­sagerie ? Alors bien­v­enue dans mail­stail.

    Pas­cal CESCATO

    Je ne me con­tente pas de refor­muler des com­mu­niqués ou de dérouler des specs. Je teste, je creuse, je démonte quand il faut – parce qu’un sujet mal com­pris est un sujet mal écrit. J’écris avec les mains dans le cam­bouis, sans sim­pli­fi­er à out­rance ni recracher du mar­ket­ing. Mon truc, c’est de ren­dre clair sans trahir, lis­i­ble sans liss­er. Et non, je ne “fais pas du con­tenu”. Pas pour faire du con­tenu, en tout cas.

    S’abonner
    Notification pour
    guest
    0 Commentaires
    Le plus ancien
    Le plus récent Le plus populaire
    Commentaires en ligne
    Afficher tous les commentaires
    Table des matières
    Retour en haut
    Les cookies que nous utilisons sont indispensables au bon fonctionnement de ce site. Il n'y a aucun pistage publicitaire et les données statistiques recueillies sont anonymisées.
    J'ai compris