72. pepsi-stage-list-post¶
Moderiert eine Listennachricht, wandelt sie um und verteilt sie an die Mitglieder.
72.1. Aufgabe¶
pepsi-stage-list-post erhält eine Nachricht, die pepsi-stage-list als Listennachricht eingeordnet hat, und tut zwei Dinge mit ihr, in dieser Reihenfolge und unter diesen Namen: eine Chain aus Rules entscheidet, ob die Nachricht angenommen, zurückgehalten, zurückgewiesen oder verworfen wird, und anschließend entscheidet eine Pipeline aus Handlern, wie eine angenommene Nachricht umgewandelt und zugestellt wird. Moderation und Verarbeitung sind verschiedene Schritte mit verschiedenen Vokabularen, und sie zu vermischen ergibt etwas, das nicht Mailman ist – die Namen von Rule, Chain, Handler und Pipeline sind ein Kompatibilitätsmerkmal, das die REST-API meldet und das posting_chain und posting_pipeline einer Liste benennen. Referenz: pepsi-stage-list-post(1).
Dieses Subsystem ist eine Neuimplementierung von GNU Mailman 3; siehe Mailinglisten, wo benannt ist, was von upstream übernommen wurde.
72.2. Moderation¶
Die voreingestellte Posting-Chain durchläuft die DMARC-Abmilderungsprüfung, die Prüfung auf fehlende Absender, die Umgehung per Moderatorpasswort (approved), die Rules für Schleife und gesperrte Adresse, die serverweiten und listenbezogenen Header-Regeln, das Notfall-Flag sowie die Moderations-Rules für Mitglieder und Nichtmitglieder. Danach halten acht Rules nur fest, was sie finden — Administrivia, impliziter Empfänger, maximale Empfängerzahl, Maximalgröße, News-Moderation, leerer Betreff, Digests und verdächtige Header —, und ein abschließendes any hält die Nachricht zurück, wenn eine davon angeschlagen hat: achtzehn Rules und vier abschließende Chains (accept, hold, reject, discard).
Warnung
Ein korrektes Moderatorpasswort umgeht die Sperrliste. Das ist das Verhalten von upstream und Kompatibilität verlangt es, aber es ist eine scharfe Kante: ein Approved:-Header mit dem Moderatorpasswort der Liste springt direkt zu accept, über die Sperrliste, die Header-Regeln, das Notfall-Flag und beide Moderations-Rules hinweg.
Das Freigabepasswort überlebt nie. Ein Moderator darf eine Nachricht mit dem Passwort in einem Approved:-Header oder in der ersten Zeile des Nachrichtentexts freigeben; in welcher Form es auch eintraf, es wird entfernt, bevor die Nachricht archiviert oder zugestellt wird – im Header, im Klartextteil und in der HTML-Alternative, die ein Mailprogramm daneben erzeugt hat. Ein Passwort, das in ein öffentliches Archiv gelangt, ist dauerhaft veröffentlicht, und die archivierte Kopie zu löschen holt die Kopien in fünftausend Postfächern nicht zurück. Die Rule entfernt, was sie gefunden hat, und der cleanse-Handler löscht anschließend alle vier Headernamen (Approve, Approved, X-Approve, X-Approved) bedingungslos, was das Einzige ist, das ein falsches Passwort entfernt.
72.3. Handler¶
Die Pipeline ist die von upstream, in der Reihenfolge von upstream: validate-authenticity, mime-delete, tagger, member-recipients, avoid-duplicates, cleanse, cleanse-dkim, cook-headers, subject-prefix, rfc-2369, to-archive, to-digest, to-usenet, after-delivery, acknowledge, dmarc, to-outgoing.
decorate und arc-sign fehlen, weil upstream sie in der eigenen Standard-Pipeline auskommentiert hat, und zwar aus den Gründen von upstream: alle Ausschmückung geschieht bei der Zustellung, und Ausschmückung bei der Zustellung würde eine hier angebrachte Signatur brechen. Beides gehört zu pepsi-stage-list-deliver und zum Signaturende der Pipeline. to-usenet ist eine ausdrückliche, protokollierte Leeroperation – gateway_to_news bleibt setzbar, weil seine Entfernung die Ressource verändern würde, die ein REST-Client sieht, aber Pepsi hat kein NNTP-Gateway, und eine stille Leeroperation würde einen Betreiber in dem Glauben lassen, sein Gateway funktioniere.
72.4. Geschriebene Header¶
Mailmans Namensraum X-Mailman-* ist zu X-Pepsi-List-* umbenannt – Version, Rule-Hits, Rule-Misses, Approved-At, Hash-ID, Duplicate, Copy –, weil nichts in Postorius oder HyperKitty davon etwas liest und der einzige Abnehmer ein Mensch ist, der eine zurückgehaltene Nachricht liest. Message-ID-Hash und seine alte Schreibweise X-Message-ID-Hash behalten ihre Namen: sie tragen den Namen keines Projekts, jede Archiv-URL wird aus ihnen abgeleitet, und sie sind diejenigen, auf denen ein Dritter am ehesten etwas aufgebaut hat.
X-Pepsi-List-Hops hat kein Gegenstück bei upstream und ist der einzige Header, den die Software wieder einliest. Er ist die Rückfallsicherung gegen einen Abonnementkreis über zwei oder mehr Listen – die loop-Rule erkennt nur eine Nachricht, die zur gleichen Liste zurückkehrt – und er reist in einem Header, weil ein Geschwisterdatensatz per SMTP hinausgeht und als gewöhnliche Post wieder eintritt, wo der Zustand des Datensatzes nicht überlebt. Da ein Header fälschbar ist, entfernt pepsi-ingress eine eingehende Kopie von einem nicht authentifizierten Absender.
72.5. Das Fan-out¶
Jedes gewöhnliche Mitglied mit aktivierter Zustellung, das keine Sammelnachricht bezieht, erhält bedingungslos einen Datensatz, jeder mit seinem einzigen Empfänger und seinem eigenen VERP-Umschlagabsender <list>-bounces+<local>=<domain>@<host> – und genau das erlaubt es dem Bounce-Pfad, einen Fehler genau einem Abonnement zuzuordnen, ohne den Bounce zu parsen. Über die Leitung geht die Empfängerliste, nicht die Nachricht: Header und Nachrichtentext werden innerhalb der Datenbank kopiert, eine Nachricht an fünftausend Mitglieder sendet also eine Nachricht und fünftausend kleine JSON-Objekte an PostgreSQL.
Das Fan-out erfolgt in Stapeln: es werden höchstens [pepsi-list] LIST_FANOUT_BATCH Datensätze (Standard 256) auf einmal erzeugt, und die Nachricht pausiert zwischen den Stapeln mit den verbleibenden Empfängern in ihrem eigenen state. Der Spitzenbedarf an flüchtigem Speicher ist damit Stapelgröße mal Nachrichtengröße statt Mitgliederzahl mal Nachrichtengröße – eine Nachricht an 5 000 Mitglieder mit 5 MB Anhang erreicht rund 1,3 GB statt 25 GB –, und pepsi-queue zeigt ein laufendes Fan-out und nicht eine Datenbank, die plötzlich gewachsen ist. Die Empfängerliste wird beim ersten Stapel festgeschrieben, sodass eine Abmeldung mitten in einem großen Versand keinen Nachbarn überspringen und keinen doppelt bedienen kann, und der Ausgangsdatensatz wird erst von dem Stapel gelöscht, der die Liste beendet, sodass ein Absturz genau diesen Stapel wiederholt und nichts weiter.
72.6. Der Autoresponder für Listennachrichten¶
autorespond_postings ist der dritte der drei Autoresponder, auf derselben Karenzzeit-Maschinerie wie -request und -owner, und der, über den man lesen sollte: er feuert auf der Absendeadresse, ein falsch eingestellter antwortet also allen, die an die Liste schreiben. Auf einer Absendeadresse bedeutet respond_and_discard, dass die Nachricht beantwortet und nicht verteilt wird – gelegentlich will ein Verwalter genau das (eine stillgelegte Liste, die „wir sind umgezogen“ antwortet) und niemals versehentlich, weshalb das Verwerfen mit warn protokolliert wird und die Verwalteroberfläche den Wert klar benennt. Zwei nicht offensichtliche Regeln: ein unbekannter Wert ist ``none`` (eine Antwortaktion, die niemand richtig schreiben kann, ist keine Erlaubnis, an eine Mitgliederschaft zu schreiben), und eine Nachricht, die nicht beantwortet werden konnte, wird dennoch zugestellt – lehnt der Autoresponder ab, verwirft respond_and_discard nicht, denn eine Liste, die wegen eines Autoresponders jede Nachricht stillschweigend verschluckt, wäre der schlimmere Fehler. Jede automatische Antwort durchläuft zuerst das gemeinsame Regelwerk nach RFC 3834 (pepsi_common::autoreply); siehe pepsi-stage-vacation.
72.7. Konfiguration¶
[stage-<name>]: PROGRAM = pepsi-stage-list-post, DELIVERY_STAGE (erforderlich, und dort muss pepsi-stage-list-deliver laufen), BOUNCE_STAGE (erforderlich – hier bedeutet es das, was es überall außer bei pepsi-stage-list bedeutet), RESPONSE_STAGE (erforderlich, und es muss das Signaturende sein: die Zustellstage nimmt nur die Kopie eines Mitglieds aus dem Fan-out an, eine dorthin gesendete Benachrichtigung geht also nie hinaus), REMOVE_DKIM_HEADERS (Standard no), SITE_HEADER_MATCH_CHAIN (Standard hold, serverweit, damit ein Listenverwalter die Spamregeln des Servers nicht in ein Verwerfen verwandeln kann) und die beiden Verfügbarkeitslimits SENDER_POSTS_PER_HOUR (Standard 30: Beiträge eines Absenders an eine Liste, die darüber hinaus innerhalb einer Stunde eingehen, werden für den Moderator zurückgehalten, statt an jedes Mitglied gesendet zu werden) und MAX_HELD_MESSAGES (Standard 1000 pro Liste: ein Beitrag, der darüber hinaus zurückgehalten würde, wird verworfen, sodass eine offene Liste nicht zum Füllen der Festplatte missbraucht werden kann; verworfen wird der neue Beitrag, nicht der älteste, sodass eine Flut nicht hinausspülen kann, was ein Moderator noch nicht gesehen hat). pepsi-setup prüft alle drei Ziele und verweigert ein ``NEXT_STAGE``: jeder Weg aus dieser Stage heraus ist ein Endpunkt.
REMOVE_DKIM_HEADERS ist standardmäßig aus, weil eine Liste, die nichts umschreibt, eine gültige Signatur hinterlässt und sie zu entfernen echte Belege verwirft; schalten Sie es für Listen ein, die eine Fußzeile oder ein Betreffpräfix hinzufügen, wo die überlebende Signatur fehlschlagen würde – und eine fehlschlagende Signatur ist schlimmer als keine, denn ein Fehlschlag ist ein Hinweis auf Manipulation und ein Fehlen nicht.
72.8. State¶
Eingaben:
state.list.id(von pepsi-stage-list geschrieben),state.auth(die von ingress aufgezeichneten SPF/DKIM/DMARC-Ergebnisse) undstate.list.pending_rcptbei einem fortgesetzten Fan-out.Ausgaben: ein
state.list-Deskriptor auf jedem Geschwisterdatensatz – die Mitglieds-ID, die Sprache des Mitglieds, seine Abmelde-Seriennummer und das Duplikat-Flag.Übergänge: Abschließen (der letzte Stapel eines Fan-outs, ein Zurückhalten, ein Verwerfen), Abschließen mit einem Nebenklon (die Zustellungsstatusbenachrichtigung einer Zurückweisung) oder Pausieren (ein Fan-out mit verbleibenden Empfängern).
72.9. Siehe auch¶
Mailinglisten, Archive, pepsi-stage-list, pepsi-stage-list-deliver, pepsi-list, pepsi-archive, pepsi-stage-list-post(1).