Une PME de 30 personnes reçoit 80 à 200 emails clients par jour. Réclamation produit, demande de devis, question technique, relance de facture, demande de documentation — tout arrive dans la même boîte. Quelqu'un lit, trie, crée un ticket, assigne au bon service. Temps moyen : 3 à 5 minutes par email. Résultat : un tiers des emails attendent plus de 24h avant d'être traités, les urgences se noient dans le flux, et les clients qui relancent passent devant ceux qui attendent poliment.

Ce guide détaille un système complet pour analyser chaque email entrant par IA, créer un ticket structuré avec catégorie, urgence, résumé et données extraites, router vers la bonne équipe, envoyer un accusé de réception personnalisé, et escalader automatiquement les cas critiques. Sans toucher à votre boîte mail — le système se branche dessus.

Tout est faisable en interne.


Ce que fait le système

Cinq étapes, de l'email au ticket résolu :

  1. Détection — Chaque nouvel email dans la boîte support/contact/commercial est capté en temps réel
  2. Analyse IA — Claude ou GPT-4 lit l'email et extrait : catégorie, urgence, résumé, données clés (numéro de commande, référence produit, nom du client), sentiment, langue
  3. Création ticket — Un ticket structuré est créé dans votre outil (HubSpot, Zendesk, Freshdesk, ou un simple tableur)
  4. Routage — Le ticket est assigné à la bonne équipe ou la bonne personne selon la catégorie et l'urgence
  5. Réponse immédiate — Un accusé de réception personnalisé part dans la minute, avec un numéro de ticket et un délai estimé

Temps humain par email : 0 pour le tri. L'humain intervient là où il a de la valeur — résoudre le problème, pas classer des emails. Les urgences sont escaladées en temps réel au lieu d'attendre qu'on les découvre dans la pile.


Les outils

Brique Option mainstream Option open source Coût
Détection email Gmail API / Microsoft Graph API IMAP polling Gratuit
Analyse IA Claude API (Anthropic) ou GPT-4 (OpenAI) Idem ~0,01 €/email
Ticketing HubSpot Tickets, Zendesk, Freshdesk Zammad, osTicket 0-50 €/mois
Orchestration Make (ex-Integromat) ou Zapier n8n auto-hébergé 0-30 €/mois
Notifications urgences Slack, Teams ou SMS (Twilio) Mattermost, Ntfy 0-10 €/mois
Base de suivi Intégrée au ticketing ou Google Sheets NocoDB Gratuit
Total 10-70 €/mois

Le coût IA est négligeable : un email moyen fait 200-500 mots. À 150 emails/jour, c'est ~3 €/mois en API Claude. Moins que le café de la personne qui triait les emails à la main.


Étape 1 — Capter les emails

Gmail (Google Workspace)

Option 1 — Gmail API avec Push Notifications (temps réel)

Configurez un watch sur la boîte mail via l'API Gmail + Google Cloud Pub/Sub :

// Activer le watch Gmail → Pub/Sub
// L'API envoie une notification à chaque nouvel email

POST https://gmail.googleapis.com/gmail/v1/users/me/watch

Body :
{
  "topicName": "projects/votre-projet/topics/gmail-notifications",
  "labelIds": ["INBOX"],
  "labelFilterBehavior": "INCLUDE"
}

Chaque nouvel email déclenche un message Pub/Sub → votre webhook n8n/Make récupère l'email.

Option 2 — Polling IMAP (plus simple)

// n8n — node IMAP Email Trigger
// Vérifie la boîte toutes les 2 minutes

Configuration :
  Host: imap.gmail.com
  Port: 993
  User: support@votreentreprise.com
  Password: mot de passe d'application Google
  Mailbox: INBOX
  Options: Unseen only

Le polling toutes les 2 minutes suffit dans 90% des cas. Un client qui envoie un email à 14h02 et reçoit un accusé de réception à 14h04 — c'est déjà impressionnant.

Microsoft 365 (Outlook)

// Microsoft Graph API — récupérer les nouveaux emails
GET https://graph.microsoft.com/v1.0/me/mailFolders/inbox/messages
    ?$filter=isRead eq false
    &$orderby=receivedDateTime desc
    &$top=50
    &$select=id,subject,from,body,receivedDateTime,hasAttachments

Headers : Authorization: Bearer {access_token}

Ou utilisez le trigger « Nouvel email » natif dans Make/n8n — c'est un nœud prêt à l'emploi pour Microsoft 365.

Multi-boîtes

Si vous avez plusieurs adresses (support@, contact@, commercial@, facturation@), configurez un trigger par boîte. L'information « boîte d'origine » est utile pour le routage : un email arrivé sur facturation@ est probablement une question de facturation, même si l'IA ne le détecte pas dans le contenu.

Filtre anti-bruit : excluez les emails automatiques (notifications, newsletters, accusés de réception, out-of-office) avant l'analyse IA. Un filtre sur les en-têtes (X-Auto-Response-Suppress, Auto-Submitted, List-Unsubscribe) élimine 30 à 50% du volume et vous économise des tokens inutiles.

Étape 2 — L'analyse IA

Le prompt d'analyse — version de base

Tu es un système de tri et d'analyse d'emails entrants
pour le service client d'une entreprise.

RÈGLES :
- Analyse UNIQUEMENT le contenu de l'email.
  N'invente aucune information.
- Si une donnée n'est pas mentionnée → null.
- Distingue l'email initial d'un fil de conversation
  (thread). Si c'est une réponse dans un fil, analyse
  uniquement le dernier message.
- Si l'email contient une pièce jointe mentionnée
  (facture, bon de commande, photo), signale-la
  mais n'analyse que le texte.

Structure JSON attendue :

{
  "analyse": {
    "langue": "fr",
    "categorie": "reclamation / demande_devis / question_technique / suivi_commande / facturation / partenariat / candidature / spam / autre",
    "sous_categorie": "produit_defectueux / retard_livraison / erreur_facture / ...",
    "urgence": "critique / haute / normale / basse",
    "sentiment": "positif / neutre / frustré / en_colere / menaçant",
    "resume": "Résumé en 1-2 phrases de la demande du client",
    "donnees_extraites": {
      "nom_client": "Jean Dupont",
      "entreprise": "Acme Corp",
      "numero_commande": "CMD-2025-1234",
      "reference_produit": "REF-ABC-456",
      "numero_facture": "FA-2025-789",
      "montant_mentionne": 1500.00,
      "date_mentionnee": "2025-01-15"
    },
    "pieces_jointes_mentionnees": ["photo du produit abîmé"],
    "action_requise": "Vérifier l'état de la commande et proposer un remplacement",
    "equipe_cible": "SAV / Commercial / Comptabilité / Technique / Direction",
    "necessite_escalade": false,
    "raison_escalade": null
  },
  "reponse_accusé": "Accusé de réception personnalisé (2-3 phrases)"
}

RÈGLES D'URGENCE :
- "critique" : le client mentionne un arrêt de production,
  un danger, une perte financière immédiate, un ultimatum,
  ou une action juridique.
- "haute" : le client relance pour la 2e+ fois, mentionne
  un délai dépassé, ou exprime une forte frustration.
- "normale" : demande standard sans pression temporelle.
- "basse" : demande d'information générale, partenariat,
  candidature.

RÈGLES D'ESCALADE (necessite_escalade = true) :
- Le client mentionne un avocat, un tribunal, la DGCCRF,
  ou menace de poursuites.
- Le montant en jeu dépasse 10 000 €.
- Le client est identifié comme un compte clé
  (à recouper côté CRM).
- Le problème impacte la sécurité ou la santé.
- Le client mentionne les réseaux sociaux ou la presse.
- 3e relance du client sur le même sujet.

Ce prompt fonctionne. Sur des emails standards, il catégorise correctement dans 85-90% des cas et extrait les données clés avec fiabilité. Mais il reste des angles morts.

Pourquoi le prompt de base ne suffit pas

Problème 1 — Les catégories ne collent pas à votre métier. « Réclamation » est trop vague. Un fabricant de menuiseries a besoin de distinguer « défaut produit », « erreur de cotes », « casse au transport », et « problème de pose ». Un cabinet comptable a besoin de « pièce manquante », « question TVA », « urgence déclaration ». Les catégories génériques produisent un routage générique.

Problème 2 — Les emails ambigus. « Bonjour, suite à notre conversation, je vous confirme notre accord sur le devis 2025-034, mais nous souhaitons modifier la quantité sur la ligne 3 et par ailleurs notre facture du mois dernier comporte une erreur. » — C'est une confirmation de commande, une modification de devis, ET une réclamation facturation. Le prompt de base va choisir une catégorie. Il en faut trois.

Problème 3 — Le contexte historique. Un email qui dit « Toujours pas de nouvelles de votre part » est une relance — mais relance de quoi ? Sans l'historique des échanges, l'IA ne peut pas qualifier correctement l'urgence ni résumer la situation.

Problème 4 — Les signatures et disclaimers. La moitié de l'email est souvent composée de signatures, mentions légales, et historique du fil de discussion. L'IA peut confondre le contenu actuel avec un message précédent dans le thread.

Le calibrage : comment passer de 85% à 98%

Itération 1 — Catégories métier. Remplacez les catégories génériques par les vôtres. Exemples selon les secteurs :

CATÉGORIES SPÉCIFIQUES À L'ENTREPRISE :

Pour un distributeur de matériel industriel :
- commande : nouvelle commande, modification, annulation
- livraison : suivi, retard, erreur, colis endommagé
- technique : panne matériel, compatibilité, documentation
- facturation : erreur, avoir, délai de paiement
- devis : demande, modification, relance
- sav : retour produit, garantie, réparation
- commercial : nouveau compte, conditions tarifaires

Pour un cabinet d'expertise comptable :
- piece_manquante : le client doit fournir un justificatif
- question_fiscale : TVA, IS, CFE, déclarations
- question_sociale : paie, URSSAF, contrats
- urgence_deadline : échéance déclarative proche
- bilan : questions sur les comptes annuels
- mission : demande de nouvelle prestation

Pour un fabricant agroalimentaire :
- qualite : réclamation produit, corps étranger, DLC
- logistique : retard, erreur de livraison, palette abîmée
- commercial : commande, tarifs, référencement
- reglementaire : fiches techniques, allergènes, certificats

[ADAPTEZ À VOTRE MÉTIER]

Itération 2 — Gestion des emails multi-sujets.

EMAILS MULTI-SUJETS :
Si l'email traite de plusieurs sujets distincts, retourne
un tableau d'analyses (une par sujet).
Chaque analyse a sa propre catégorie, urgence, et équipe cible.

Exemple : un email qui confirme une commande ET signale
une erreur de facturation → deux entrées dans le tableau,
l'une routée vers "Commercial", l'autre vers "Comptabilité".

JSON attendu dans ce cas :
{
  "multi_sujet": true,
  "analyses": [
    { "categorie": "commande", "resume": "...", ... },
    { "categorie": "facturation", "resume": "...", ... }
  ]
}

Pour un email mono-sujet, retourne :
{
  "multi_sujet": false,
  "analyses": [ { ... } ]
}

Itération 3 — Détection de contexte et relances.

DÉTECTION DES RELANCES :
- Si l'email contient des marqueurs de relance
  ("suite à mon précédent email", "je me permets de revenir",
  "toujours sans réponse", "relance", "3e demande"),
  ajoute le flag "est_relance": true.
- Si c'est une relance, augmente l'urgence d'un cran
  (normale → haute, haute → critique).
- Essaie d'identifier le sujet d'origine d'après le contenu
  et le fil de discussion.

NETTOYAGE DU CONTENU :
- Ignore tout ce qui suit les marqueurs de signature :
  "Cordialement", "Bien à vous", "Sent from my iPhone",
  "---", lignes de tirets.
- Ignore les mentions légales ("Ce message est confidentiel...").
- Dans un thread (Re: / Fwd:), analyse uniquement le premier
  bloc de texte (le message le plus récent).
  Utilise le reste du thread comme contexte, pas comme contenu
  principal.

Itération 4 — Règles d'escalade spécifiques.

ESCALADE — RÈGLES SPÉCIFIQUES :
- Client VIP : si l'email vient d'un domaine figurant dans
  cette liste → toujours urgence "haute" minimum :
  [domaine1.com, domaine2.fr, ...]
- Montant seuil : tout sujet impliquant > 5 000 € → escalade.
  (ADAPTEZ ce seuil à votre activité)
- Mots-clés d'escalade automatique :
  "avocat", "tribunal", "mise en demeure", "DGCCRF",
  "réseaux sociaux", "article de presse", "signalement"
- Secteur alimentaire : tout email mentionnant "allergie",
  "intoxication", "corps étranger", "rappel produit"
  → urgence critique + escalade direction qualité.
- Secteur BTP : tout email mentionnant "accident",
  "chantier arrêté", "mise en danger", "inspection"
  → urgence critique + escalade direction.

[AJOUTEZ VOS RÈGLES MÉTIER]

Le résultat après calibrage

Après ces 4 itérations (comptez 1 à 2 semaines de tests sur vos emails réels), le prompt catégorise correctement 95%+ des emails, extrait les données clés avec fiabilité, et le routage est pertinent dans 9 cas sur 10. Les 5% restants sont des emails vraiment ambigus que même un humain aurait du mal à trier du premier coup.

L'appel API

Anthropic (Claude) :

POST https://api.anthropic.com/v1/messages

Headers : x-api-key, anthropic-version: 2023-06-01
Body :
{
  "model": "claude-sonnet-4-20250514",
  "max_tokens": 2048,
  "temperature": 0,
  "system": "VOTRE PROMPT CALIBRÉ",
  "messages": [{
    "role": "user",
    "content": "Nouvel email reçu sur {{ boite_origine }}.\n\nDe : {{ from }}\nObjet : {{ subject }}\nDate : {{ date }}\n\nContenu :\n{{ body }}"
  }]
}

OpenAI (GPT-4 Turbo) : même logique, endpoint /v1/chat/completions, avec response_format: { type: "json_object" }.

Coût moyen : 0,005 à 0,02 € par email selon la longueur.


Étape 3 — Création du ticket

Le code de structuration

// n8n — node Code — transformer l'analyse IA en ticket(s)
const result = $('Node_Analyse_IA').first().json;
const emailData = $('Node_Email').first().json;

const tickets = [];

for (const analyse of result.analyses) {
  const ticket = {
    // Identifiant unique
    ticket_id: `TK-${Date.now()}-${Math.random().toString(36).substr(2, 4).toUpperCase()}`,

    // Source
    source: 'email',
    boite_origine: emailData.boite,
    email_from: emailData.from,
    email_subject: emailData.subject,
    email_date: emailData.date,
    email_id: emailData.messageId,  // pour retrouver le thread

    // Analyse IA
    categorie: analyse.categorie,
    sous_categorie: analyse.sous_categorie,
    urgence: analyse.urgence,
    sentiment: analyse.sentiment,
    resume: analyse.resume,
    action_requise: analyse.action_requise,

    // Données extraites
    nom_client: analyse.donnees_extraites?.nom_client,
    entreprise: analyse.donnees_extraites?.entreprise,
    numero_commande: analyse.donnees_extraites?.numero_commande,
    reference_produit: analyse.donnees_extraites?.reference_produit,
    numero_facture: analyse.donnees_extraites?.numero_facture,
    montant: analyse.donnees_extraites?.montant_mentionne,

    // Routage
    equipe_cible: analyse.equipe_cible,
    necessite_escalade: analyse.necessite_escalade,
    raison_escalade: analyse.raison_escalade,
    est_relance: analyse.est_relance || false,

    // Statut
    statut: 'nouveau',
    date_creation: new Date().toISOString(),
    sla_deadline: computeSLA(analyse.urgence)
  };

  tickets.push(ticket);
}

function computeSLA(urgence) {
  const now = new Date();
  const heures = {
    'critique': 2,
    'haute': 8,
    'normale': 24,
    'basse': 72
  };
  return new Date(now.getTime() + (heures[urgence] || 24) * 3600000).toISOString();
}

return tickets.map(t => ({ json: t }));

HubSpot — créer le ticket

// n8n — créer un ticket HubSpot
const ticket = $input.first().json;

// Mapping urgence → priorité HubSpot
const priorityMap = {
  'critique': 'HIGH',
  'haute': 'HIGH',
  'normale': 'MEDIUM',
  'basse': 'LOW'
};

// Mapping catégorie → pipeline stage (ADAPTEZ à votre pipeline)
const categoryPipelineMap = {
  'reclamation': 'hs_pipeline_stage_1',    // Nouveau
  'question_technique': 'hs_pipeline_stage_1',
  'facturation': 'hs_pipeline_stage_1',
  'demande_devis': 'hs_pipeline_stage_1',
  // etc.
};

// Chercher le contact existant dans HubSpot
let contactId = null;
if (ticket.email_from) {
  const contactSearch = await fetch(
    'https://api.hubapi.com/crm/v3/objects/contacts/search',
    {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${hubspotToken}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        filterGroups: [{
          filters: [{
            propertyName: 'email',
            operator: 'EQ',
            value: ticket.email_from
          }]
        }]
      })
    }
  );
  const contacts = await contactSearch.json();
  contactId = contacts.results?.[0]?.id || null;
}

// Créer le ticket
const res = await fetch('https://api.hubapi.com/crm/v3/objects/tickets', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${hubspotToken}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    properties: {
      subject: `[${ticket.categorie.toUpperCase()}] ${ticket.resume.substring(0, 100)}`,
      content: `**Résumé IA :** ${ticket.resume}\n\n`
        + `**Action requise :** ${ticket.action_requise}\n\n`
        + `**Données extraites :**\n`
        + (ticket.numero_commande ? `- Commande : ${ticket.numero_commande}\n` : '')
        + (ticket.reference_produit ? `- Réf produit : ${ticket.reference_produit}\n` : '')
        + (ticket.numero_facture ? `- Facture : ${ticket.numero_facture}\n` : '')
        + (ticket.montant ? `- Montant : ${ticket.montant} €\n` : '')
        + `\n---\n**Email original :**\n${ticket.email_subject}`,
      hs_pipeline: '0',  // pipeline par défaut
      hs_pipeline_stage: '1',  // Nouveau
      hs_ticket_priority: priorityMap[ticket.urgence] || 'MEDIUM',
      hs_ticket_category: ticket.categorie,
      source_type: 'EMAIL',
      // Propriétés custom
      urgence_ia: ticket.urgence,
      sentiment_client: ticket.sentiment,
      sla_deadline: ticket.sla_deadline
    }
  })
});

const newTicket = await res.json();

// Associer au contact si trouvé
if (contactId && newTicket.id) {
  await fetch(
    `https://api.hubapi.com/crm/v4/objects/tickets/${newTicket.id}/associations/contacts/${contactId}`,
    {
      method: 'PUT',
      headers: {
        'Authorization': `Bearer ${hubspotToken}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify([{
        associationCategory: 'HUBSPOT_DEFINED',
        associationTypeId: 16  // ticket → contact
      }])
    }
  );
}

return [{ json: { ticketId: newTicket.id, contactId } }];

Zendesk — créer le ticket

// Créer un ticket Zendesk
const ticket = $input.first().json;

const priorityMap = {
  'critique': 'urgent',
  'haute': 'high',
  'normale': 'normal',
  'basse': 'low'
};

await fetch(`https://${zendeskDomain}.zendesk.com/api/v2/tickets`, {
  method: 'POST',
  headers: {
    'Authorization': `Basic ${btoa(`${zendeskEmail}/token:${zendeskToken}`)}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    ticket: {
      subject: `[${ticket.categorie.toUpperCase()}] ${ticket.resume.substring(0, 100)}`,
      description: ticket.resume,
      priority: priorityMap[ticket.urgence],
      type: 'problem',
      tags: [ticket.categorie, ticket.sous_categorie, `sentiment_${ticket.sentiment}`],
      custom_fields: [
        { id: 123456, value: ticket.numero_commande },  // ADAPTEZ les IDs
        { id: 123457, value: ticket.urgence }
      ],
      requester: {
        name: ticket.nom_client || ticket.email_from,
        email: ticket.email_from
      }
    }
  })
});

Freshdesk — même logique

// Créer un ticket Freshdesk
const priorityMap = { 'basse': 1, 'normale': 2, 'haute': 3, 'critique': 4 };

await fetch(`https://${freshdeskDomain}.freshdesk.com/api/v2/tickets`, {
  method: 'POST',
  headers: {
    'Authorization': `Basic ${btoa(`${freshdeskToken}:X`)}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    subject: `[${ticket.categorie.toUpperCase()}] ${ticket.resume.substring(0, 100)}`,
    description: `<b>Résumé IA :</b> ${ticket.resume}<br><b>Action :</b> ${ticket.action_requise}`,
    email: ticket.email_from,
    priority: priorityMap[ticket.urgence],
    status: 2,  // Open
    tags: [ticket.categorie, ticket.sous_categorie],
    type: ticket.categorie
  })
});

Étape 4 — Le routage et l'escalade

Le routage par catégorie

// n8n — node Code — assigner le ticket à la bonne personne
const ticket = $input.first().json;

// Table de routage (ADAPTEZ à votre organisation)
const routingTable = {
  // Catégorie → { equipe, owner_id (HubSpot), slack_channel }
  'reclamation':        { equipe: 'SAV', ownerId: 12345, channel: '#sav' },
  'question_technique': { equipe: 'Technique', ownerId: 23456, channel: '#support-tech' },
  'facturation':        { equipe: 'Comptabilité', ownerId: 34567, channel: '#compta' },
  'demande_devis':      { equipe: 'Commercial', ownerId: 45678, channel: '#commercial' },
  'suivi_commande':     { equipe: 'Logistique', ownerId: 56789, channel: '#logistique' },
  'sav':                { equipe: 'SAV', ownerId: 12345, channel: '#sav' },
  'partenariat':        { equipe: 'Direction', ownerId: 67890, channel: '#direction' },
  'candidature':        { equipe: 'RH', ownerId: 78901, channel: '#rh' },
  'spam':               { equipe: null, ownerId: null, channel: null }
};

const route = routingTable[ticket.categorie] || routingTable['reclamation'];

// Si urgence critique ou escalade → notifier la direction aussi
const escalade = ticket.necessite_escalade || ticket.urgence === 'critique';

return [{
  json: {
    ...ticket,
    assigned_to: route.equipe,
    owner_id: route.ownerId,
    slack_channel: route.channel,
    escalade,
    escalade_channel: escalade ? '#urgences' : null
  }
}];

La notification Slack

// Message Slack structuré pour le nouveau ticket
const t = $input.first().json;

const urgenceEmoji = {
  'critique': '🔴',
  'haute': '🟠',
  'normale': '🟡',
  'basse': '🟢'
};

const sentimentEmoji = {
  'positif': '😊',
  'neutre': '😐',
  'frustré': '😤',
  'en_colere': '😡',
  'menaçant': '⚠️'
};

const blocks = [
  {
    type: 'header',
    text: {
      type: 'plain_text',
      text: `${urgenceEmoji[t.urgence]} Nouveau ticket — ${t.categorie.toUpperCase()}`
    }
  },
  {
    type: 'section',
    fields: [
      { type: 'mrkdwn', text: `*De :* ${t.nom_client || t.email_from}` },
      { type: 'mrkdwn', text: `*Entreprise :* ${t.entreprise || '—'}` },
      { type: 'mrkdwn', text: `*Urgence :* ${urgenceEmoji[t.urgence]} ${t.urgence}` },
      { type: 'mrkdwn', text: `*Sentiment :* ${sentimentEmoji[t.sentiment]} ${t.sentiment}` }
    ]
  },
  {
    type: 'section',
    text: { type: 'mrkdwn', text: `*Résumé :* ${t.resume}` }
  },
  {
    type: 'section',
    text: { type: 'mrkdwn', text: `*Action :* ${t.action_requise}` }
  }
];

// Ajouter les données extraites si pertinentes
const dataLines = [];
if (t.numero_commande) dataLines.push(`Commande : \`${t.numero_commande}\``);
if (t.reference_produit) dataLines.push(`Produit : \`${t.reference_produit}\``);
if (t.numero_facture) dataLines.push(`Facture : \`${t.numero_facture}\``);
if (t.montant) dataLines.push(`Montant : ${t.montant} €`);

if (dataLines.length > 0) {
  blocks.push({
    type: 'section',
    text: { type: 'mrkdwn', text: `*Données extraites :*\n${dataLines.join('\n')}` }
  });
}

// Bouton vers le ticket
blocks.push({
  type: 'actions',
  elements: [{
    type: 'button',
    text: { type: 'plain_text', text: '📋 Voir le ticket' },
    url: `https://app.hubspot.com/contacts/${portalId}/ticket/${t.ticketId}`,
    style: 'primary'
  }]
});

L'escalade temps réel

Pour les cas critiques, le workflow envoie une notification séparée dans un canal dédié (ou par SMS) :

// Si escalade → notification supplémentaire
if (t.escalade) {
  // Slack #urgences
  await sendSlack('#urgences', {
    text: `🚨 ESCALADE — ${t.categorie.toUpperCase()}\n`
      + `Client : ${t.nom_client || t.email_from}\n`
      + `Raison : ${t.raison_escalade || t.urgence}\n`
      + `Résumé : ${t.resume}\n`
      + `SLA : réponse avant ${new Date(t.sla_deadline).toLocaleString('fr-FR')}`
  });

  // SMS au responsable (optionnel — Twilio)
  if (t.urgence === 'critique') {
    await fetch('https://api.twilio.com/2010-04-01/Accounts/{sid}/Messages.json', {
      method: 'POST',
      headers: {
        'Authorization': `Basic ${btoa(`${twilioSid}:${twilioToken}`)}`,
        'Content-Type': 'application/x-www-form-urlencoded'
      },
      body: new URLSearchParams({
        To: '+33612345678',  // mobile du responsable
        From: '+33700000000',
        Body: `🚨 Ticket critique : ${t.resume.substring(0, 120)} — ${t.email_from}`
      })
    });
  }
}

Étape 5 — L'accusé de réception

Pourquoi c'est important

Un client qui envoie un email et reçoit une réponse personnalisée dans la minute se dit « ils sont réactifs ». Un client qui attend 24h sans signe de vie se dit « ils s'en fichent ». L'accusé de réception automatique n'est pas du luxe — c'est le minimum.

Mais attention : un accusé de réception générique (« Votre demande a bien été prise en compte, nous reviendrons vers vous dans les meilleurs délais ») est à peine mieux que rien. L'IA peut faire mieux.

Le prompt de l'accusé de réception

L'IA a déjà analysé l'email. Elle sait de quoi parle le client, son niveau de frustration, et ce qu'il attend. L'accusé de réception en tient compte :

ACCUSÉ DE RÉCEPTION — RÈGLES :
- 2-3 phrases maximum. Court, précis, humain.
- Reprends le sujet spécifique du client (pas de réponse
  passe-partout).
- Inclus le numéro de ticket.
- Donne un délai de réponse réaliste selon l'urgence :
  • critique → "dans les 2 prochaines heures"
  • haute → "dans la journée"
  • normale → "sous 24 à 48 heures"
  • basse → "sous 72 heures"
- Si le client est frustré ou en colère → empathie d'abord.
  "Nous comprenons votre frustration concernant [sujet]."
- Ne fais aucune promesse de résolution.
- Signe avec le nom de l'entreprise, pas un nom de personne
  (puisque c'est automatique).

Exemples :

Email : réclamation sur un retard de livraison, client frustré
→ "Bonjour [prénom], nous avons bien reçu votre message
   concernant le retard de votre commande [n°]. Nous comprenons
   votre frustration et notre équipe logistique examine la
   situation — vous recevrez une réponse dans la journée.
   [Réf. ticket : TK-XXXX]"

Email : demande de devis, ton neutre
→ "Bonjour [prénom], merci pour votre demande de devis.
   Notre équipe commerciale la prend en charge et reviendra
   vers vous sous 48 heures. [Réf. ticket : TK-XXXX]"

Envoi de l'accusé

// n8n — Envoyer l'accusé de réception par email
const ticket = $input.first().json;
const analyse = $('Node_Analyse_IA').first().json;

// Ne pas envoyer d'accusé pour :
// - les spams
// - les emails automatiques
// - les candidatures (circuit séparé)
const skipCategories = ['spam', 'candidature'];
if (skipCategories.includes(ticket.categorie)) {
  return [];  // pas d'accusé
}

const replyBody = analyse.reponse_accusé
  .replace('[prénom]', ticket.nom_client?.split(' ')[0] || 'Madame, Monsieur')
  .replace('TK-XXXX', ticket.ticket_id);

// Répondre dans le thread original (Reply-To + In-Reply-To)
await sendEmail({
  to: ticket.email_from,
  subject: `Re: ${ticket.email_subject}`,
  html: `<p>${replyBody}</p>
    <br>
    <p style="color:#888;font-size:12px;">
      Référence : ${ticket.ticket_id}<br>
      Cet accusé de réception est automatique.
      Un membre de notre équipe prendra en charge votre demande.
    </p>`,
  headers: {
    'In-Reply-To': ticket.email_id,
    'References': ticket.email_id
  }
});
Point important : l'accusé de réception s'insère dans le fil de conversation existant (grâce aux headers In-Reply-To et References). Le client ne reçoit pas un email séparé qui casse le thread — il voit la réponse apparaître dans le même fil. C'est un détail technique, mais ça change tout côté expérience client.

Workflow complet (résumé n8n)

[Trigger : Nouvel email (IMAP / Gmail API / Graph API)]
    ↓
[Filtre : Exclure emails automatiques (headers check)]
    ↓
[Claude API : Analyse + catégorie + urgence + extraction]
    ↓
[Code : Structurer le(s) ticket(s)]
    ↓
[Pour chaque ticket :]
    ↓
┌──────────────────┬──────────────────┬──────────────────┐
│ CRM :            │ Slack :          │ Email :          │
│ Créer ticket     │ Notification     │ Accusé de        │
│ + Associer       │ dans le canal    │ réception        │
│ contact          │ de l'équipe      │ personnalisé     │
└──────────────────┴──────────────────┴──────────────────┘
    ↓
[Si escalade :]
    ↓
┌──────────────────┬──────────────────┐
│ Slack #urgences  │ SMS Twilio       │
│ Notification     │ (si critique)    │
│ direction        │                  │
└──────────────────┴──────────────────┘

Ce que ça donne en vrai

Avant Après
Temps de tri par email 3-5 min (lecture + classement + assignation) 0 (automatique)
Délai avant premier traitement 2-8 heures (dépend de qui lit la boîte) < 5 minutes
Accusé de réception Jamais ou générique Personnalisé, dans la minute
Urgences détectées Quand quelqu'un tombe dessus Escalade temps réel (Slack + SMS)
Données extraites Saisie manuelle dans le ticket Automatique (n° commande, ref, montant)
Emails multi-sujets Traités partiellement Chaque sujet = un ticket séparé
Coût mensuel (150 emails/jour) ~1 ETP partiel (~1 500 €/mois en temps salarié) 10-70 €/mois

Le gain le plus sous-estimé : la réduction du temps moyen de résolution. Quand le ticket arrive déjà structuré (catégorie, résumé, données clés, contexte), la personne qui le prend en charge gagne 3 à 5 minutes de lecture et de recherche d'informations. Sur 150 tickets/jour, c'est 7 à 12 heures redistribuées de la lecture vers la résolution.


Ça marche pour quel type d'entreprise ?

Le système s'adapte à tous les secteurs qui reçoivent des emails clients. Ce qui change, c'est la grille de catégories et les règles d'escalade :

Distributeur de matériel électrique — Les emails couvrent les commandes, les ruptures de stock, les questions techniques sur les produits, et les erreurs de livraison. L'IA extrait les références produit et les numéros de commande pour pré-remplir le ticket.

Cabinet comptable — Le flux est saisonnier (pic en janvier-avril). Les emails concernent les pièces manquantes, les questions fiscales, et les échéances déclaratives. L'IA détecte les deadlines et marque les urgences temporelles automatiquement.

Fabricant alimentaire — Les réclamations qualité (DLC, allergènes, corps étranger) nécessitent une escalade immédiate. L'IA identifie les termes critiques et envoie une alerte au responsable qualité en temps réel.

Agence immobilière — Les demandes de visite, les questions sur les biens, et les relances acquéreurs/locataires arrivent en vrac. L'IA extrait les références de biens et route vers le bon négociateur.

Entreprise de maintenance industrielle — Les demandes d'intervention urgente (panne machine, arrêt de production) doivent être détectées en quelques minutes. L'IA distingue la demande planifiable de l'urgence terrain et déclenche le bon circuit.

E-commerce — Retours, SAV, questions sur les produits, suivi de colis. L'IA extrait le numéro de commande et interroge le système de suivi avant même que l'agent ne prenne le ticket.


Les limites

L'IA ne comprend pas le contexte historique complet. Elle analyse l'email isolé. Si le client fait référence à un échange téléphonique ou à un ticket précédent, l'IA ne peut pas recouper. Solution partielle : injecter les dernières interactions CRM du contact dans le prompt (augmente le coût token mais améliore significativement le résumé).

Les pièces jointes ne sont pas analysées. Le système extrait le texte de l'email, pas le contenu des PDF ou images joints. Si le client envoie une facture en PJ sans rien écrire dans le corps du mail, l'IA n'a rien à analyser. Piste d'amélioration : ajouter un nœud d'extraction PDF/OCR pour les pièces jointes courantes.

Les emails très courts sont ambigus. « OK pour moi » — réponse à quoi ? Sans le thread complet, l'IA ne peut pas catégoriser. Le nettoyage du thread (itération 3 du calibrage) aide, mais les one-liners restent le cas le plus difficile.

Le prompt n'est pas plug-and-play. Les catégories génériques ne marchent pas. Il faut les adapter à votre métier — c'est le calibrage le plus important et le plus long (1-2 semaines).

Faux positifs d'urgence. L'IA a tendance à surclasser l'urgence plutôt qu'à la sous-classer (ce qui est préférable). Mais trop d'escalades = plus personne ne les prend au sérieux. Calibrez les seuils sur vos vrais emails.

Maintenance. Mise à jour de la table de routage quand l'équipe change, ajout de nouvelles catégories quand de nouveaux types de demandes apparaissent, suivi des performances du prompt. Prévoir 1-2h/mois.


Troubleshooting

Problème Solution
Emails automatiques traités comme des tickets Améliorez le filtre d'en-têtes (X-Auto-Response-Suppress, Auto-Submitted, List-Unsubscribe)
Mauvaise catégorisation Ajoutez des catégories spécifiques à votre métier + exemples dans le prompt
Urgence systématiquement surévaluée Ajustez les critères d'urgence dans le prompt. Soyez plus spécifique sur ce qui constitue une urgence dans votre contexte
Données mal extraites (n° commande) Ajoutez le format de vos références dans le prompt : « Les numéros de commande suivent le format CMD-AAAA-NNNN »
Emails multi-sujets → un seul ticket Vérifiez que le prompt multi-sujets est bien implémenté (itération 2)
Accusé de réception hors thread Vérifiez les headers In-Reply-To et References — ils doivent reprendre le Message-ID de l'email original
Tickets en double (même email) Ajoutez un dédoublonnage sur email_id (Message-ID) avant la création
Slack non notifié Vérifiez le token bot Slack et les permissions chat:write sur les canaux cibles
SLA non respecté (pas d'alerte) Ajoutez un workflow séparé qui vérifie toutes les heures les tickets dont le sla_deadline est dépassé
Token Gmail/Microsoft expiré Implémentez le refresh automatique du token OAuth (même logique que pour l'article avis Google)

Le budget

Poste Coût
API IA (~150 emails/jour, 20 jours/mois) 30-60 €/mois
Orchestration (Make/Zapier ou n8n) 0-30 €/mois
Ticketing (HubSpot Starter ou Freshdesk) 0-50 €/mois
Notifications SMS escalade (optionnel) 0-10 €/mois
Total 10-70 €/mois

Pour les gros volumes (500+ emails/jour), le coût IA monte à 100-200 €/mois. Ça reste 10 à 20 fois moins cher que le temps humain de tri. Et contrairement à un humain, le système ne fait pas de pause café, ne part pas en vacances, et traite le email du vendredi 18h avec la même rigueur que celui du lundi 9h.


Tout est là

Ce guide contient l'architecture, les appels API (Gmail, Microsoft, Claude, HubSpot, Zendesk, Freshdesk, Slack, Twilio), le prompt d'analyse (avec la méthode de calibrage en 4 itérations), le code de routage et d'escalade, l'accusé de réception intelligent, et le troubleshooting. Si vous avez quelqu'un en interne qui maîtrise les outils d'automatisation — lancez-vous.

Le point clé, c'est la grille de catégories. Des catégories génériques donnent un routage générique — et un système que personne n'utilise au bout de 2 semaines. Des catégories calibrées sur votre métier, avec les bons seuils d'urgence et d'escalade, donnent un système que l'équipe adopte parce qu'il leur facilite vraiment la vie.

Si vous préférez gagner du temps : on branche le système sur votre boîte mail pendant 5 jours, en mode shadow. Le système analyse et structure les emails en parallèle, sans rien publier. À la fin de la semaine, on vous montre les tickets qu'il aurait créés, le routage qu'il aurait fait, et les escalades qu'il aurait déclenchées. Vous comparez avec ce que votre équipe a réellement fait. Si c'est mieux — on active. Si ça ne l'est pas, vous n'avez rien dépensé.

Demander le test gratuit


Marketing Robot — systèmes d'automatisation pour PME. Des process, des outils, des résultats mesurables.