85.1.21. pepsi-stage-list-deliver

finalise one member’s copy of a mailing-list post

Section du manuel:

1

85.1.21.1.1. Nom

pepsi-stage-list-deliver - l’étape de remise par membre du pipeline de listes de diffusion de Pepsi.

85.1.21.1.2. Synopsis

pepsi-stage-list-deliver [OPTIONS-GLOBALES] worker

85.1.21.1.3. Description

pepsi-stage-list-deliver est un programme d’étape exécuté par pepsi-dispatch(1). pepsi-stage-list-post(1) a déjà produit un enregistrement par destinataire ; c’est cette étape qui fait de chacun d’eux la copie de ce membre plutôt qu’une copie de plus du même message. Un enregistrement entre, un enregistrement sort.

Trois choses se produisent :

  • ``List-Unsubscribe`` est achevé avec l’URI https: en un clic propre à ce membre, à côté de la forme mailto:, et List-Unsubscribe-Post: List-Unsubscribe=One-Click est ajouté (RFC 8058).

  • Le message est décoré — l’en-tête et le pied de page de la liste, dans la langue du membre — lorsque le personalize de la liste vaut individual ou full.

  • ``To:`` est réécrit pour nommer le membre, pour full uniquement. Le personalize_to d’amont est une opération vide pour individual, et celui-ci aussi.

Une copie signalée par avoid-duplicates — le membre figurait déjà dans le To ou le Cc du message et a conservé malgré tout sa copie de liste — porte X-Pepsi-List-Copy: yes, pour que le lecteur voie pourquoi il en a deux.

Avertissement

Cette étape doit s’exécuter avant la signature. Chaque en-tête qu’elle touche appartient à la liste h= de DKIM, et List-Unsubscribe est précisément l’en-tête qu’un fournisseur de boîtes inspecte pour décider s’il affiche un bouton de désabonnement. Un pipeline qui signerait d’abord produirait du courrier signé puis modifié, qui échoue à DKIM partout. NEXT_STAGE pointe donc vers pepsi-stage-dkim-sign(1), et non vers un relais, et pepsi-setup refuse l’inverse. Amont dit la même chose dans le commentaire qui retire arc-sign de son propre pipeline.

85.1.21.1.4. Désabonnement en un clic

Le jeton de l’URI https: est un condensé à clé calculé sur la liste, l’adresse du membre et un numéro de série que le membre peut faire tourner. Il n’est pas stocké : une URI List-Unsubscribe est émise une fois par membre et par message, une table de ces URI croîtrait donc avec les remises et non avec les membres. Trois conséquences :

  • le jeton ne voyage jamais entre les étapes — celle-ci détient le secret et le calcule pour chaque copie ;

  • révoquer toutes les URI jamais émises pour un abonnement consiste à incrémenter le unsubscribe_serial de ce membre, une mise à jour de compteur et non un balayage de table ;

  • et il n’y a rien à faire expirer, car un abonnement qui n’existe plus échoue à la recherche d’appartenance, quoi que dise le jeton.

Le secret est [pepsi-list] UNSUBSCRIBE_SECRET. Sans secret, ou sans BASE_URL pour construire une URI, la forme mailto: reste seule, comme chez amont : une URI invérifiable est pire que pas d’URI. Changer le secret invalide toutes les URI déjà présentes dans la boîte de chaque abonné.

85.1.21.1.5. Décoration

L’en-tête et le pied de page sont produits depuis [pepsi] TEMPLATE_DIR sous les noms list-header.<lang>.body et list-footer.<lang>.body, la langue du membre étant choisie d’abord et en servant de recours. Une liste sans fichiers de modèle n’est pas décorée, ce qui est le cas courant et ne coûte rien. Un modèle qui existe mais ne peut être lu ou rendu est une erreur, et la copie est réessayée plutôt qu’envoyée sans le pied de page configuré par le propriétaire.

Le pied de page est ajouté à la première partie ``text/plain`` et à rien d’autre. Ajouté à une partie multipart/signed il casse la signature, ajouté à un PDF il le corrompt : un message sans partie en texte brut est donc remis sans décoration plutôt qu’abîmé.

85.1.21.1.6. Deux invariants

Les enregistrements frères commencent ici, jamais en tête de pipeline. Rentrer à init relancerait la vérification ARC et repasserait par le routeur, ce qui explose de façon combinatoire sur une liste chapeau.

Les préférences personnelles d’un membre ne reconfigurent pas la remise de liste. Pepsi superpose automatiquement les redéfinitions pepsi.settings par adresse, et l’unique destinataire d’un enregistrement frère est un membre, dont la redéfinition d’absence ou de langue n’a pas à changer les cibles de cette étape — un NEXT_STAGE qui en serait tiré pourrait faire passer la copie à côté de la signature. NEXT_STAGE, les options [pepsi-list] et [pepsi] TEMPLATE_DIR sont donc lus dans la configuration globale du site, qu’aucune redéfinition de configuration domain: ou address: ni aucun enregistrement pepsi.settings n’atteint, et la langue du membre vient du descripteur écrit par l’éclatement. Rien n’est pris dans la surcouche.

85.1.21.1.7. Configuration

NEXT_STAGE (obligatoire)

La queue de signature. pepsi-setup refuse un relais ici.

Tout le reste dont cette étape a besoin est le descripteur de membre écrit par l’éclatement et les attributs propres de la liste ; [pepsi-list] BASE_URL et UNSUBSCRIBE_SECRET sont lus dans la section du site.

85.1.21.1.8. État

Entrées : state.list — l’identifiant de liste, la langue du membre, son numéro de série de désabonnement et l’indicateur de doublon — ainsi que l’unique rcpt_to de l’enregistrement, qui fait autorité sur l’adresse.

Sorties : un bloc d’en-têtes et un corps réécrits. Aucun state n’est modifié.

Transitions : passage à NEXT_STAGE, la seule transition.

85.1.21.1.9. Commandes

worker

Exécuté comme un worker persistant de pepsi-dispatch(1), lisant les identifiants de message sur l’entrée standard.

85.1.21.1.10. Options globales

L’ensemble habituel — -c/–config, -L/–log, -v/–verbose, -h/–help et -V/–version — qui se comporte comme pour tout programme Pepsi ; voir pepsi-config(1).

85.1.21.1.11. Erreurs et réessais

  • Une copie dont la liste a été supprimée après l’éclatement est abandonnée, avec un avertissement dans le journal : le propriétaire a supprimé la liste, une copie remise maintenant porterait un lien de désabonnement vers rien, et il ne reste personne à qui le signaler.

  • Une copie qui ne peut être analysée pour la décoration est remise sans décoration, avec un avertissement. L’éclatement a construit ces octets à partir d’un message qu’il avait analysé ; ce n’est donc pas le fait de l’expéditeur et un réessai ne peut rien y changer ; la copie porte toujours les en-têtes List-* propres à la liste (y compris le désabonnement mailto:), et l’abandonner ferait perdre son courrier au membre.

  • Une ligne sans descripteur de membre est mise en échec immédiatement.

  • Toute autre erreur (la base de données, un modèle) est réessayée avec un back-off jusqu’à MAX_LIFETIME (voir pepsi-dispatch(1)). Une copie finalement abandonnée est supprimée par pepsi-failure-bouncer(1), et non renvoyée en rebond, et ne compte donc jamais contre le membre.

85.1.21.1.12. Code de sortie

0

La copie a été achevée et a avancé.

1

Le worker n’a pas pu s’exécuter (sa base de données n’a pas pu être ouverte, ou l’entrée/sortie standard a échoué). La raison est écrite dans le journal.

85.1.21.1.13. Exemples

[stage-list-deliver]
PROGRAM = pepsi-stage-list-deliver
NEXT_STAGE = dkim-sign

85.1.21.1.14. Voir aussi

pepsi-list(1), pepsi-stage-list-post(1), pepsi-stage-list(1), pepsi-stage-dkim-sign(1), pepsi-stage-arc(1), pepsi-dispatch(1), pepsi.conf(5), pepsi.state(7), pepsi-setup(1)

85.1.21.1.15. Bogues

Signalez les bogues au gestionnaire de tickets de Pepsi.