quest'n'click 4.5.0 · r1

Construite pour quest'n'click 4.5.0, révision r1. Si elle est publiée, et laquelle est la courante, est dit par publication.json.

Connecteur e-mail

English · Type : procédure + référence · Public : administrateur · Contexte : Reality Bridge · Statut : prête · S'applique depuis : 4.2.5

Les connecteurs (email, Telnet, SSH, Open Badges) · contrat : expérimental · vérifié par la CI (matrice de support de la 4.4.0, 2026-10-23) : Node 22 sous Ubuntu (Telnet et SSH pas sous Windows) · vérifications automatiques : jobs connectors, connector-archive-e2e ; plan de CI reality ; 3 fichiers de tests · passes humaines : connectors-real-security pas faite (#79) · limites connues : aucune listée sur cette page

Le connecteur e-mail transforme une lettre en signal : un joueur répond au jeu par e-mail, et les mots de sa réponse proposent le signal que le jeu leur associe. Il lit les messages depuis le webhook signé d’un fournisseur ou depuis une boîte qu’il relève en IMAP, et n’envoie aucune réponse. Il est expérimental, comme tous les connecteurs (Vue d’ensemble des connecteurs).

Ce que vous obtenez

Un processus quest-n-click-connector email qui lie un joueur par un code d’appairage envoyé en sujet d’un e-mail, puis propose letter.door (ou le signal que le jeu déclare) pour chaque message dont les mots correspondent à une réponse, une fois par message : un message livré deux fois fait un seul signal.

Contexte et versions

Prérequis

Où lancer les commandes

grant là où est le dossier du Bridge ; le connecteur sur la machine qui reçoit le webhook ou atteint la boîte, dans un dossier qui contient sa configuration, son jeton et son secret (mode 600). npm run connector -- email … dans le dépôt du moteur, npx quest-n-click-connector email … avec le paquet quest-n-click-connectors.

Étapes

  1. Donnez au connecteur son jeton, pour les signaux e-mail seulement, avec l’appairage :

    # dans le dépôt du moteur (le dossier du Bridge est .cache/bridge)
    npm run bridge -- grant --connector=gate-mail --source=email --signals=letter.door,letter.unclear --pair > email.token
    
  1. Écrivez le secret partagé du webhook dans un fichier (ou, pour IMAP, le mot de passe de la boîte) :

    # dans le dossier du connecteur
    node -e 'process.stdout.write(require("node:crypto").randomBytes(32).toString("hex"))' > webhook.secret
    chmod 600 webhook.secret
    
  1. Écrivez sa configuration, email.json. Le mode webhook :

    {
      "bridge": { "url": "http://127.0.0.1:8787/", "tokenFile": "email.token" },
      "gameId": "signals",
      "health": { "port": 9302 },
      "email": { "mode": "webhook", "domain": "game.example.org", "webhook": { "port": 8789, "secretFile": "webhook.secret" } }
    }
    

    Ou le mode IMAP :

    {
      "bridge": { "url": "http://127.0.0.1:8787/", "tokenFile": "email.token" },
      "gameId": "signals",
      "email": { "mode": "imap", "imap": { "host": "imap.example.org", "user": "gate@example.org", "passwordFile": "imap.password", "pollS": 60 } }
    }
    
  1. Lancez-le :

    # dans le dépôt du moteur
    npm run connector -- email --config email.json
    

    Il journalise {"event":"email.started","connector":"email","mode":"webhook"}.

  1. Essayez le webhook avec un envoi signé. La signature est sha256= suivi du HMAC-SHA256, sous le secret, de <horodatage>.<message brut> ; l’horodatage est en secondes Unix, à moins de cinq minutes de l’horloge du connecteur :

    # dans le dossier du connecteur, answer.eml contenant un message brut (en-têtes, une ligne vide, le texte)
    node -e '
    const { createHmac } = require("node:crypto");
    const { readFileSync } = require("node:fs");
    const body = readFileSync(process.argv[1]);
    const secret = readFileSync("webhook.secret", "utf8").trim();
    const t = Math.floor(Date.now() / 1000);
    const signature = "sha256=" + createHmac("sha256", secret).update(`${t}.`).update(body).digest("hex");
    fetch("http://127.0.0.1:8789/v1/inbound", { method: "POST", body,
      headers: { "X-Web-Scumm-Timestamp": String(t), "X-Web-Scumm-Signature": signature } })
      .then(async (r) => console.log(r.status, await r.text()));
    ' answer.eml
    

    Un message dont le sujet est PAIR ABCD2345 (le code que montre le jeu) lie son expéditeur : 202 {"status":"paired"}. Un message suivant du même expéditeur qui dit « open the door » : 202 {"status":"accepted"}. Le même message de nouveau : 200 {"status":"duplicate"}.

Résultat attendu, et comment le vérifier

Erreurs fréquentes

SymptômeCauseCorrection
email: "mode" is "webhook" or "imap" au démarragePas de modeDéfinir email.mode
email: webhook mode needs "webhook.secretFile" / email: imap mode needs "imap.passwordFile"Le secret manqueNommer son fichier
email: "imap.tls": false is allowed for a loopback host only (127.0.0.1, ::1, localhost)TLS coupé vers un serveur distantGarder TLS
401 {"error":"stale"}L’horodatage manque ou est à plus de cinq minutesEnvoyer des secondes Unix ; vérifier les horloges
401 {"error":"signature"}Un autre secret, ou le corps a changé en routeSigner les octets exacts envoyés
422 {"error":"no-player"}L’expéditeur n’a envoyé aucun code d’appairage, et aucune étiquette de destinataire de domain ne nomme un joueurS’appairer d’abord, ou définir domain
422 {"error":"attachment"} / "too-large" / "unreadable"Un message avec pièce jointe, de plus de 256 Ko, ou refusé par le lecteurDu texte simple, sans pièce jointe
422 {"error":"pairing-pairing"}Le code d’appairage est inconnu, expiré ou déjà confirméUn nouveau code depuis le jeu
429 {"error":"rate"}Plus de 120 envois par minute depuis une adresseRalentir

Fichiers ou données modifiés

Garantie · bridge-email-unseen-when-away · référencée · exécutée sur aff6caab7514 · portée vérifiée par son auteur (IA), pas relue Un message dont le signal n’a pas pu atteindre le Bridge (Bridge absent) reste non lu et est relu par un relevé suivant ; un message refusé pour de bon est signalé.

Reprise ou retour en arrière

Arrêtez le processus (SIGTERM). Révoquez son jeton sur le Bridge (revoke --token=<id de révocation>) s’il a fuité, et donnez-en un nouveau. Rien dans le jeu ne dépend du connecteur : un jeu où letter.door est facultatif continue sans lui.

Référence de la configuration

La section email :

ChampDéfautSens
mode(obligatoire)webhook ou imap
domainaucunLe domaine des adresses par joueur <boîte>+p-<16 hex>@<domaine> ; sans lui, les étiquettes ne sont pas lues
maxBytes262 144 (256 Ko)Le plus gros message brut lu ; jamais plus de 4 Mo, quoi qu’il dise
linkDays30Combien de temps un expéditeur qui a envoyé un code d’appairage reste lié à son joueur, en mémoire
webhook.port, webhook.host—, 127.0.0.1Où écoute POST /v1/inbound
webhook.secretFile(obligatoire)Le fichier du secret HMAC
webhook.toleranceS300L’écart permis entre l’horodatage et maintenant, en secondes
webhook.perMinutePerIp120Envois par minute et par adresse
imap.host, imap.port—, 993Le serveur de la boîte, en TLS
imap.user, imap.passwordFile(obligatoires)Son identifiant
imap.mailboxINBOXLe dossier relevé
imap.tlstruefalse seulement vers cette machine
imap.pollS60Secondes entre deux relevés (50 messages non lus au plus chacun)
imap.keepDays00 : supprimer une fois accepté ; N : garder N jours

Comment un message est lu

Ce qu’il garde

Références


Modifier la source de cette page · Signaler une erreur