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 concer­nant gmail­tail – un petit outil malin capable d’ex­traire au for­mat JSON les cour­riels reçus dans votre boîte Gmail.

Mais cet outil est limi­té à Gmail. Or moi, ce que je vou­lais, 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éber­gée chez un four­nis­seur classique.

Alors j’ai posé mon idée.

Puis j’ai com­men­cé à pro­to­ty­per un outil, que j’ai appe­lé mail­stail. Une inter­face mail mul­ti-comptes légère, intel­li­gente, capable de me mon­trer en un coup d’œil ce qui est impor­tant… ou pas.

Objectifs fonctionnels

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

  • voir les der­niers cour­riels reçus (toutes boîtes confondues)
  • prio­ri­ser les emails auto­ma­ti­que­ment (impor­tant / moyen / faible)
  • répondre direc­te­ment depuis l’interface
  • sup­pri­mer un indé­si­rable en un clic
  • éven­tuel­le­ment : pro­po­ser une réponse auto­ma­tique (LLM) ou un résu­mé intelligent

Panorama des solutions existantes

Aujourd’­hui, si vous consul­tez vos mails, vous avez plus ou moins deux choix :

  • soit vous uti­li­sez l’in­ter­face web du four­nis­seur (Gmail, Out­look, Free, etc.)
  • soit vous pas­sez 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­nis­seurs de ser­vices, impôts, CAF, avo­cat…), une adresse uni­ver­si­taire, une adresse pro… et chaque jour, je dois pas­ser d’un onglet à l’autre, ou d’un compte à l’autre.

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

Autant dire que la décou­verte de cet outil m’a inter­pe­lé, et que j’ai eu envie de déve­lop­per une inter­face mail intel­li­gente qui me per­mette d’op­ti­mi­ser 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 visua­li­sa­tion rapide des mes­sages importants
  • avec une pos­si­bi­li­té d’in­te­ra­gir en temps réel

Les outils d’analyse automatique pour emails

En creu­sant, j’ai décou­vert plu­sieurs briques tech­no­lo­giques pour le sco­ring auto­ma­tique des emails :

  • Let­tria : puis­sante, mais un peu usine à gaz pour un besoin simple
  • spa­Cy : rapide, fiable, per­son­na­li­sable (et open source)
  • Camem­BERT : effi­cace, mais plus lourd (Trans­for­mers, GPU, RAM…)
  • Mail​par​ser​.io : inté­res­sant pour des for­mu­laires ou flux structurés

Mon choix : res­ter léger avec spa­Cy NLP, en inté­grant un sys­tème de sco­ring pon­dé­ré basé sur les mots-clés et les enti­tés nommées.

Architecture globale

Un seul mot d’ordre : sim­pli­ci­té 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 backend est construit en Python, un lan­gage que je maî­trise bien et qui offre un excellent éco­sys­tème pour tout ce qui est trai­te­ment de texte, NLP et ges­tion d’emails (IMAP, enco­dage, par­sing mul­ti­part…). C’est aus­si un lan­gage bien docu­men­té, idéal pour construire une base robuste et évolutive.

Pour la couche API, j’ai opté pour Fas­tA­PI. Pour­quoi Fas­tA­PI et pas Flask ? D’a­bord pour la vitesse de déve­lop­pe­ment, ensuite pour la détec­tion auto­ma­tique des types, la docu­men­ta­tion Swag­ger inté­grée, et enfin parce qu’il est conçu pour du asyn­chrone – ce qui me per­met­tra plus tard de sca­ler ou de pas­ser à du mul­ti-thread sans tout refaire.

Côté fron­tend, le choix s’est por­té sur React pour sa large com­mu­nau­té et sa sou­plesse. Asso­cié à Vite (plu­tôt que Web­pack), le com­bo per­met une com­pi­la­tion rapide, un rechar­ge­ment ultra-fluide en déve­lop­pe­ment, et une inter­face res­pon­sive moderne mais légère. J’a­vais aus­si envi­sa­gé Vue, mais React reste à mes yeux plus robuste et plus main­te­nu à long terme.

Enfin, Docker s’est impo­sé pour encap­su­ler le tout. Avec Docker Com­pose, je peux buil­der, lan­cer, déployer et mettre à jour l’en­semble du pro­jet (fron­tend + backend + proxy) en une seule ligne. Ce n’é­tait pas indis­pen­sable au début, mais c’est vite deve­nu essen­tiel pour tes­ter sur dif­fé­rents environnements.

Architecture technique détaillée

Un seul mot d’ordre : sim­pli­ci­té et robustesse.

Récu­pé­ra­tion IMAP/API → Sco­ring spa­Cy → Affi­chage fron­tend (React) → Réponse manuelle ou auto → Sup­pres­sion / action

  • IMAP + OAuth2 pour com­pa­ti­bi­li­té avec Gmail, Yahoo, etc.
  • Fall­back avec mot de passe (Free, Orange, etc.)
  • Affi­chage mul­ti-comptes mail, avec icône colo­rée selon la source
  • Prio­ri­sa­tion auto­ma­tique par niveau d’importance
  • Logs des mails ana­ly­sés pour audit ou rétroaction

Détails techniques

L’un des enjeux dès le départ était de faire tour­ner ce pro­jet même sur des confi­gu­ra­tions modestes (ex. : VPS à 1 vCPU, 512 Mo de RAM). Il fal­lait donc évi­ter les solu­tions trop lourdes ou trop exigeantes.

Côté backend, j’ai pré­fé­ré un trai­te­ment séquen­tiel simple au départ, plu­tôt que d’im­plé­men­ter de l’a­syn­chrone ou du mul­ti­thread trop tôt. Fas­tA­PI per­met de faire du async pro­pre­ment, mais encore fal­lait-il ne pas com­pli­quer inuti­le­ment la logique de trai­te­ment dès la pre­mière ver­sion. La struc­ture actuelle pour­rait faci­le­ment bas­cu­ler vers du async ou de la file de tâches plus tard, mais ce n’est pas une prio­ri­té à ce stade.

Pour les connexions IMAP, j’ai inté­gré un ges­tion­naire de ses­sion capable de dis­tin­guer les connexions OAuth2 (pour Gmail, Out­look, Yahoo…) des connexions par mot de passe appli­ca­tif plus clas­siques. Le prin­cipe est simple : si les variables d’en­vi­ron­ne­ment contiennent un token OAuth2 valide, on uti­lise ce mode d’au­then­ti­fi­ca­tion, sinon, on revient à une authen­ti­fi­ca­tion clas­sique. Le backend est donc capable d’a­jus­ter dyna­mi­que­ment sa méthode d’au­then­ti­fi­ca­tion sans que l’u­ti­li­sa­teur n’ait à faire le moindre choix manuel.

Le par­sing des emails a néces­si­té pas mal de soin pour gérer toutes les variantes : enco­dage bizarre, conte­nus mul­ti­part avec pièces jointes, HTML crades, etc. Là encore, un trai­te­ment robuste mais léger était le bon compromis.

Côté sco­ring intel­li­gent, spa­Cy est rapide, mais il a fal­lu cali­brer la pon­dé­ra­tion pour obte­nir des résul­tats per­ti­nents sans tom­ber dans le sur-appren­tis­sage ou le sco­ring gad­get. J’ai aus­si log­gué tous les mails trai­tés dans un fichier .jsonl pour pou­voir ana­ly­ser et ajus­ter le sco­ring a posteriori.

Sur le fron­tend React, React m’a per­mis de décou­per pro­pre­ment l’af­fi­chage des mes­sages (aper­çu, détail, réponse), et d’a­jou­ter faci­le­ment des fonc­tion­na­li­tés inter­ac­tives (bou­ton « Répondre », champ rich text caché par défaut, prio­ri­sa­tion par cou­leur). Le choix de Vite a per­mis un cycle de déve­lop­pe­ment très fluide et des builds rapides, même sur machine modeste.

Backend FastAPI

Le backend Fas­tA­PI est le cœur du trai­te­ment de l’ap­pli­ca­tion. Il est conçu pour rece­voir des requêtes REST via Fas­tA­PI, trai­ter les mails (connexion IMAP ou via API), extraire leur conte­nu, appli­quer un sco­ring auto­ma­tique et ren­voyer les don­nées sous forme de JSON au frontend.

Fas­tA­PI a été choi­si pour :

  • sa rapi­di­té de développement,
  • son sup­port natif de l’a­syn­chrone (utile pour gérer plu­sieurs connexions IMAP en paral­lèle à terme),
  • sa docu­men­ta­tion auto­ma­tique (Swag­ger UI très utile en développement),
  • et sa très bonne inté­gra­tion avec Pydan­tic pour la vali­da­tion des modèles.

Les routes prin­ci­pales expo­sées sont :

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

Le backend est éga­le­ment res­pon­sable de :

    Ne man­quez plus un article… 

    Abon­nez-vous à la newsletter ! 

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

    Il est conçu pour tour­ner dans un conte­neur Docker iso­lé, avec son modèle spa­Cy pré­char­gé et mon­té via volume.

    Fonc­tion­na­li­tés principales :

    • Authen­ti­fi­ca­tion dyna­mique selon les cre­den­tials dis­po­nibles (mot de passe ou OAuth2)
    • Par­sing robuste des mails (mul­ti­part, char­set, encodage…)
    • Sco­ring pon­dé­ré (key­words + enti­té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 ana­ly­sé est log­gué sous forme d’un objet JSON com­pact, sto­cké ligne par ligne dans un fichier .jsonl. Cela permet :

    • de conser­ver un his­to­rique léger et exploitable,
    • de recal­cu­ler le sco­ring avec de nou­veaux paramètres,
    • de visua­li­ser les enti­tés détec­tées et le niveau de prio­ri­té attribué,
    • d’en­traî­ner éven­tuel­le­ment un modèle de clas­si­fi­ca­tion super­vi­sée à l’avenir.

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

    Frontend React

    Le fron­tend React repose sur React, avec Vite comme outil de com­pi­la­tion. L’ob­jec­tif était d’a­voir une inter­face légère à char­ger, réac­tive, sans fioritures.

    Les choix structurants :

    • uti­li­sa­tion de com­po­sants React légers,
    • char­ge­ment pro­gres­sif des conte­nus (aper­çu → détail → réponse),
    • inté­gra­tion de Quill.js pour le champ de réponse en rich text,
    • desi­gn res­pon­sive et com­pact pour pou­voir affi­cher l’es­sen­tiel même sur petit écran.

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

    • un indi­ca­teur colo­ré : 🔴 🟠 ⚪ pour la priorité,
    • une icône indi­quant le compte d’o­ri­gine (Gmail, Yahoo, etc.),
    • une ges­tion des mails par aper­çu, avec les 3 pre­mières lignes visibles avec un bou­ton ou un lien « déve­lop­per / replier »,
    • un bou­ton « Répondre » qui déclenche le char­ge­ment condi­tion­nel de Quill.js (non mon­té par défaut, pour ne pas alour­dir le DOM).

    L’en­semble com­mu­nique avec le backend 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­na­li­tés principales :

    • Liste des mails avec code cou­leur + source visuelle
    • Affi­chage des 3 pre­mières lignes avec bou­ton « Voir la suite »
    • Champ de réponse rich text inté­gré (Quill.js)
    • Com­po­sants réac­tifs et légers (Vite)

    Docker & Nginx

    Avant de choi­sir Nginx, j’ai pris le temps d’é­va­luer ce qu’of­fraient Apache et Open­Li­teS­peed. Apache, aurait pu faire l’af­faire. Mais il est plus lourd, plus ver­beux, et néces­site plus de confi­gu­ra­tion pour un simple reverse proxy.

    Quant à Open­Li­teS­peed, que je connais bien, il est rapide et moderne, mais sa confi­gu­ra­tion en contai­ner est un peu capri­cieuse, sur­tout quand il s’a­git d’un pro­jet décou­pé en microservices.

    Fina­le­ment, j’ai choi­si Nginx pour sa sim­pli­ci­té, sa sta­bi­li­té, et sa docu­men­ta­tion ultra-com­plète. Il s’est impo­sé comme le bon choix pour :

    • Ser­vir le fron­tend React compilé,
    • Proxi­fier les requêtes vers /api/ vers Fas­tA­PI,
    • 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 Docker Com­pose, avec une confi­gu­ra­tion mini­male mais robuste, et peut être rem­pla­cé ou igno­ré si l’on déploie sur une stack dif­fé­rente (par exemple un héber­ge­ment mana­gé avec son propre reverse proxy).

    Gestion du rafraîchissement des tokens OAuth2

    L’un des points cru­ciaux avec OAuth2, c’est que le token d’ac­cès four­ni par le pro­vi­der (comme Google ou Yahoo) a une durée de vie limi­tée – sou­vent autour d’une heure. Pour évi­ter de devoir rede­man­der une auto­ri­sa­tion à l’u­ti­li­sa­teur à chaque fois, il faut donc gérer un refresh token.

    Dans mail­stail, j’ai mis en place un méca­nisme auto­ma­tique dans le backend :

    • Le token d’ac­cès est véri­fié à chaque appel.
    • Si le token est expi­ré, une requête est faite vers le ser­veur OAuth2 (via requests​.post) pour obte­nir un nou­veau token d’ac­cès à par­tir du refresh token.
    • Les nou­veaux tokens sont mis à jour dans un petit fichier de cache sécu­ri­sé, de manière trans­pa­rente pour l’utilisateur.

    Cela per­met de main­te­nir une connexion stable et conti­nue, sans inter­ven­tion manuelle.

    Défis rencontrés & solutions apportées

    DéfiSolu­tion
    Rafraî­chis­se­ment des tokens OAuth2Auto­ma­ti­sé dans backend
    Par­sing HTML/texte complexeFall­back vers conte­nu brut
    Cali­brage du sco­ringPon­dé­ra­tion pro­gres­sive selon entités
    Quo­tas Gmail APIFall­back IMAP natif sécurisé
    UI lisible mal­gré la complexitéCom­po­sants React modu­laires + pro­gres­sive disclosure

    Perspectives d’évolution

    • Moteur de règles per­son­na­li­sables (par l’utilisateur)
    • Envoi direct depuis l’inter­face mail
    • Résu­més + pro­po­si­tions de réponse via LLM (option­nel)
    • Mul­ti­lingue
    • Por­tage 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 sco­ring intel­li­gent mais lisible
    • un backend open-source personnalisable

    Conclusion

    Ce pro­jet m’a per­mis de conci­lier plu­sieurs choses :

    • mes besoins d’u­ti­li­sa­teur exigeant
    • mes com­pé­tences tech­niques (Python, NLP, React)
    • mon envie de res­ter maître de mes données

    Et sur­tout : il m’a fait gagner 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­ve­nues, issues ouvertes !

    Tu veux toi aus­si reprendre le contrôle sur ta mes­sa­ge­rie ? Alors bien­ve­nue dans mail­stail.

    Pas­cal CESCATO

    Je ne me contente pas de refor­mu­ler des com­mu­ni­qués ou de dérou­ler 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­fier à outrance ni recra­cher du mar­ke­ting. Mon truc, c’est de rendre clair sans tra­hir, lisible sans lis­ser. Et non, je ne “fais pas du conte­nu”. Pas pour faire du conte­nu, 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