85.1.32. pepsi-stage-secretary

hold mail from unknown senders until they confirm by replying

Handbuchabschnitt:

1

85.1.32.1.1. Name

pepsi-stage-secretary - die Confirm-to-Send-Stage der Pepsi-Pipeline.

85.1.32.1.2. Übersicht

pepsi-stage-secretary [GLOBAL-OPTIONS] worker

85.1.32.1.3. Beschreibung

pepsi-stage-secretary ist ein Stage-Programm, das von pepsi-dispatch(1) als persistenter Worker ausgeführt wird, der Nachrichten-IDs von der Standardeingabe liest. Es implementiert Confirm-to-Send (Senden nach Bestätigung) nach dem Vorbild von qmails qsecretary: Mail von einem Absender, den keine weiße Liste kennt, wird zurückgehalten, und der Absender wird — in seiner Sprache — gebeten, durch eine Antwort zu bestätigen. Die Antwort fügt den Absender der weißen Liste hinzu und gibt jede für ihn zurückgehaltene Nachricht frei; spätere Mail von ihm wird von pepsi-stage-check-whitelist(1) vor dieser Stage erkannt und nie wieder zurückgehalten.

Ohne Antwort bis HOLD_TIME nimmt die zurückgehaltene Mail den Zeitüberschreitungspfad: Sie wird zu BOUNCE_STAGE umgeleitet, wenn eine solche angeschlossen ist (eine DSN, eine Quarantäne, ein Verwerfen — nach Wahl des Operators), und andernfalls gelöscht.

Der Header-Block wird geladen, der Nachrichtentext nie: Eine Challenge zitiert nichts von der zurückgehaltenen Nachricht außer einem kurzen Hinweis auf ihren Betreff.

85.1.32.1.4. Was sie aufhält und was nicht

Confirm-to-Send ist schwächer als Pay-to-Send (pepsi-stage-anti-spam(1)). Ein Spammer mit einem funktionierenden Postfach kann die Antwort automatisieren, und die Erklärung, der der Absender zustimmt (PENALTY), ist eine rechtliche Abschreckung, keine wirtschaftliche. Nützlich ist sie dennoch: Die meiste Massenmail kommt von Adressen, die nicht empfangen können, und einen legitimen Korrespondenten kostet sie eine Antwort, einmal. Beides lässt sich kombinieren — siehe UNCHALLENGEABLE_STAGE.

85.1.32.1.5. Je Nachricht

Die Stage entscheidet in dieser Reihenfolge:

  1. Eine Antwort auf eine Challenge. Ein Empfänger ist die Antwortadresse <CONTROL_LOCAL_PART>-<cookie>@<domain>, wobei <cookie> aus 32 Hexadezimalziffern besteht und <domain> eine der LOCAL_DOMAINS ist (Standardwert [pepsi-ingress] ACCEPTED_DOMAINS). Ein Datensatz, der Antwortadressen mit gewöhnlichen Empfängern mischt, wird zuerst aufgeteilt, wobei beide Hälften zu dieser Stage zurückkehren. Dann gilt:

    • Eine Antwort mit Null-Absender bedeutet, dass die Challenge gebounct ist: Ihre Adresse kann nicht empfangen, also werden die zurückgehaltenen Nachrichten geweckt und nehmen den Zeitüberschreitungspfad jetzt statt nach HOLD_TIME;

    • eine als automatisch gekennzeichnete Antwort — Auto-Submitted: mit einem anderen Wert als no, Precedence: bulk|list|junk, ein X-Auto-Response-Suppress:, das Auto-Antworten abdeckt, ein multipart/report-Nachrichtentext — wird ignoriert: Ein Abwesenheitsbeantworter, der From: statt des Null-Umschlagabsenders antwortet, darf nicht im Namen seines Inhabers zustimmen;

    • jede andere Antwort bestätigt, sofern ihr Umschlagabsender oder die Addr-spec ihres From: die herausgeforderte Adresse ist. Der Absender wird der weißen Liste hinzugefügt, jede für die Challenge zurückgehaltene Nachricht wird freigegeben, und die Challenge wird gelöscht. Eine Antwort auf ein unbekanntes oder abgelaufenes Cookie oder von irgendjemand anderem wird protokolliert und ändert nichts.

    Die Antwort selbst wird in jedem Fall verbraucht (gelöscht).

  2. Eine Nachricht mit Null-Absender (ein Bounce) und lokal eingelieferte Mail (state.local_origin) gehen zu NEXT_STAGE weiter.

  3. state.spam = false (ein Absender auf der weißen Liste) geht durch; eine durch eine Bestätigung freigegebene Nachricht geht ebenfalls durch und erhält state.spam = false, sodass eine nachgelagerte Pay-to-send-Stage zustimmt.

  4. state.spam = true nimmt sofort den Zeitüberschreitungspfad.

  5. Eine zurückgehaltene Nachricht, die aufwacht: aufgegeben (ihre Challenge ist gebounct) oder über ihre Frist hinaus → der Zeitüberschreitungspfad, wobei die Challenge mit der letzten von ihr zurückgehaltenen Nachricht gelöscht wird; vorzeitig geweckt → erneut bis zur Frist pausiert.

  6. Erste Begegnung. Die Empfänger werden nach der weißen Liste gruppiert, zu der WHITELIST_NAME für jeden expandiert (eine {login}/{localpart}-Vorlage kann je Empfänger eine andere Liste benennen), und eine Nachricht, deren Empfänger in mehrere Gruppen fallen, wird in einen Datensatz je Gruppe aufgefächert. Dann ist die Nachricht nicht herausforderbar und geht zu UNCHALLENGEABLE_STAGE, wenn:

    • eine RFC-3834-Regel besagt, dass sie nicht beantwortet werden darf (dieselben Regeln, die pepsi-stage-vacation(1) anwendet: Mailinglisten-Mail, Precedence: bulk, Auto-Submitted:, Dienstabsender wie noreply@, Zustellberichte);

    • der Absender zugleich einer der Empfänger ist;

    • From: nicht genau ein Postfach nennt oder seine Addr-spec nicht der Umschlagabsender ist — die Challenge geht an MAIL FROM, und die weiße Liste gleicht From: ab, also müssen beide eine Adresse sein;

    • REQUIRE_AUTHENTICATED an ist und weder state.auth.spf noch state.auth.dmarc pass ist;

    • dem Absender in den letzten 24 Stunden über alle weißen Listen hinweg MAX_CHALLENGES_PER_SENDER Challenges gesendet wurden;

    • WHITELIST_NAME für die Empfänger nicht expandiert (eine {login}-Vorlage und ein Empfänger ohne Konto) oder es keine bediente Domain gibt, unter die die Antwortadresse gesetzt werden kann.

    Andernfalls schließt sich die Nachricht der offenen Challenge für ihr Paar (weiße Liste, Absender) an oder eröffnet eine und sendet die Challenge, und sie wird pausiert, bis die Challenge abläuft. Eine Nachricht, die sich einer bestehenden Challenge anschließt, erbt deren Ablaufzeit, keine frische HOLD_TIME; nur die Nachricht, die eine Challenge eröffnet hat, sendet eine.

Ein zurückgehaltener Datensatz hält state.secretary fest: challenge (das Cookie), deadline (Epochensekunden) und whitelist, später confirmed oder abandoned; an UNCHALLENGEABLE_STAGE gesendete Mail trägt state.secretary.unchallengeable (den Grund). Der Zeitüberschreitungspfad entfernt state.secretary vollständig. Siehe pepsi.state(7).

85.1.32.1.6. Die Challenge

Die Challenge ist eine text/plain-Nachricht, injiziert bei RESPONSE_STAGE, wo sie wie jede ausgehende Mail signiert und weitergeleitet wird. Sie hat den Null-Umschlagabsender und Auto-Submitted: auto-replied (RFC 3834), sodass ein konformer Gegenüber — ein anderer Pepsi-Secretary eingeschlossen — sie nie beantwortet. Sie geht To: an den Umschlagabsender; From: ist die Antwortadresse, angezeigt mit der Adresse des geschützten Empfängers als Anzeigename, und Reply-To: wiederholt sie, sodass die Antworten-Funktion jedes Mail-Clients sie erreicht. Sie erscheint über In-Reply-To:/References: im Thread unter der zurückgehaltenen Nachricht und trägt Content-Language:.

Sie zitiert nie den Nachrichtentext oder die Anhänge der zurückgehaltenen Nachricht: Eine Challenge geht an eine Adresse, die bei Spam meist gefälscht ist, sodass alles, was sie zitierte, von uns an einen Fremden zugestellt würde.

85.1.32.1.6.1. Der Text

Je Sprache, höchste zuerst:

  1. MESSAGE_<LANG> im eigenen Abschnitt der Stage — je Adresse überschreibbar, also ein eigener Text des Benutzers über pepsi-settings(1) oder pepsi-stage-edit-settings(1);

  2. <TEMPLATE>.<lang>.body unter [pepsi] TEMPLATE_DIR (Standardwert secretary-challenge.<lang>.body).

Die erste Quelle gewinnt je Sprache, nicht insgesamt: Das MESSAGE_EN eines Benutzers verdrängt nicht die mitgelieferte deutsche Vorlage für einen deutschen Absender. Die Sprache wird so gewählt, wie pepsi-stage-vacation(1) sie wählt: state.language in absteigender Konfidenz, dann DEFAULT_LANGUAGE, jeweils nach exaktem Tag, primärem Subtag oder einem verfeinernden Regions-Tag. Es gelten dieselben Regeln wie dort: Zwei Leerzeichen in einem Text werden zu einem Zeilenumbruch, und die unten aufgeführten Felder werden unverändert ausgegeben, gleich welcher Klammerstil verwendet wird.

Der Betreff ist SUBJECT_<LANG> für die Sprache, in der der Text gewählt wurde, sonst SUBJECT; auch er ist ein Mustache-Text. Wird nichts gerendert (kein Text für die Sprache oder den Standardwert, oder eine Vorlage, die nicht kompiliert), wird der eingebaute englische Text gesendet und eine Warnung protokolliert — eine nicht gesendete Challenge kostet den Absender seine Nachricht.

85.1.32.1.6.2. Felder

{{SENDER_NAME}}

Der From:-Anzeigename des Absenders oder seine Adresse.

{{RECIPIENT}}

Der oder die Umschlagempfänger der zurückgehaltenen Nachricht, durch Kommas getrennt.

{{SUBJECT_HINT}}

Der Betreff der zurückgehaltenen Nachricht, RFC-2047-dekodiert und auf SUBJECT_HINT_LENGTH Zeichen gekürzt (mit …, wenn gekürzt) — genug, damit ein Korrespondent seine Mail wiedererkennt, zu wenig, um eine Nutzlast zu transportieren. Fehlt bei einem leeren Betreff oder einer Länge von 0.

{{ORIGINAL_DATE}}

Das Date: der zurückgehaltenen Nachricht — fehlt, wenn sie keines hat.

{{DEADLINE}}

Wann die Challenge abläuft, als YYYY-MM-DD HH:MM UTC.

{{REPLY_ADDRESS}}

Die Antwortadresse.

{{PENALTY}}

Die konfigurierte PENALTY — fehlt, wenn keine gesetzt ist, sodass eine Vorlage den Satz mit {{#PENALTY}}…{{/PENALTY}} weglässt.

85.1.32.1.6.3. Die Bestätigungsnotiz

Mit eingeschaltetem CONFIRM_NOTICE wird einem bestätigten Absender außerdem mitgeteilt, dass seine Mail zugestellt wurde: eine Notiz mit Null-Absender von <CONTROL_LOCAL_PART>@<domain>, deren Text aus CONFIRM_MESSAGE_<LANG> oder secretary-confirmed.<lang>.body stammt (mit einem eingebauten englischen Rückfall) und deren Betreff fest ist.

85.1.32.1.8. Optionen

All diese sind je Adresse überschreibbar.

NEXT_STAGE

Wohin durchgelassene, auf der weißen Liste stehende und bestätigte Mail geht. Erforderlich.

RESPONSE_STAGE

Stage, bei der die Challenge (und die Bestätigungsnotiz) injiziert wird, damit sie signiert und weitergeleitet wird. Erforderlich.

BOUNCE_STAGE

Der Zeitüberschreitungspfad. Nicht gesetzt, wird Mail nach Zeitüberschreitung gelöscht. Eine unbeantwortete Challenge bedeutet meist einen gefälschten Absender, sodass eine DSN hier ein zweites Stück Backscatter ist; der Assistent von pepsi-setup(1) lässt die Option ungesetzt.

UNCHALLENGEABLE_STAGE

Wohin Mail geht, die nicht herausgefordert werden darf (siehe oben). Nicht gesetzt, nimmt sie den Zeitüberschreitungspfad. Richten Sie sie auf eine pepsi-stage-anti-spam(1)-Stage, um solche Absender stattdessen um Zahlung zu bitten, auf NEXT_STAGE, um sie zuzustellen, oder auf einen Spamfilter.

WHITELIST_NAME

Die eine weiße Liste, zu der ein bestätigter Absender hinzugefügt wird; darf eine {login}/{localpart}-Vorlage sein, die je Empfänger expandiert wird, genau wie in pepsi-stage-check-whitelist(1). Erforderlich. Eine Check-Whitelist-Stage vor dieser muss sie konsultieren, sonst wird ein bestätigter Absender bei jeder Nachricht erneut herausgefordert (pepsi-setup(1) warnt).

Jeder Fremde, der eine Challenge beantwortet, wird in diese Liste eingetragen, daher darf ein Kontoinhaber sie nur in seinen eigenen Namensraum zeigen lassen: Ein Wert, den er per Mail über pepsi-stage-edit-settings(1) setzt, muss für seine Adresse zu einem Namen <login>/... des Kontos expandieren, zu dem diese Adresse aufgelöst wird (etwa {login}/friends), oder die Whitelist sein, die die Konfiguration des Operators bereits für ihn benennt. Ein globaler Name, die Liste eines anderen Benutzers oder irgendein Wert für eine Adresse, die kein lokales Konto ist, wird dort zurückgewiesen, und nichts ändert sich.

Der Operator darf jede Whitelist benennen, auch eine gemeinsame: in der INI-Datei, in pepsi.config_override in jedem Geltungsbereich (global, domain:, address:) und in einem mit pepsi-settings(1) geschriebenen pepsi.settings-Datensatz. Die Stage verwendet den effektiven Wert, so wie sie ihn vorfindet.

CONTROL_LOCAL_PART

Der Local-Part, mit dem Antwortadressen beginnen. Standardwert secretary. Höchstens 30 ASCII-Buchstaben, Ziffern, ., _ oder -.

HOLD_TIME

Wie lange eine zurückgehaltene Nachricht auf ihren Absender wartet. Standardwert 120 h. Verwenden Sie h/m/s-Einheiten.

REQUIRE_AUTHENTICATED

Nur einen Absender herausfordern, dessen Domain SPF oder DMARC bestanden hat. Standardwert yes: Dies ist die Schranke gegen Backscatter.

MAX_CHALLENGES_PER_SENDER

Challenges, die an eine Adresse je 24 Stunden über alle weißen Listen hinweg gesendet werden dürfen. Standardwert 5; 0 bedeutet keine Begrenzung. Eine gebouncte Challenge zählt dennoch.

DKIM_REQUIRED

auto (der Standardwert), yes oder no: das dkim_required des für einen bestätigten Absender geschriebenen Datensatzes der weißen Liste. auto spiegelt die zurückgehaltene Mail — erforderlich, wenn irgendeine für die Challenge zurückgehaltene Nachricht DKIM (oder ARC zusammen mit DMARC) bestanden hat.

CONFIRM_NOTICE

Einem bestätigten Absender mitteilen, dass seine Mail zugestellt wurde. Standardwert no.

PENALTY

Freitext, der benennt, was der Absender zu zahlen zustimmt, falls seine Nachricht unerwünscht war (z. B. EUR:50). Standardmäßig nicht gesetzt.

SUBJECT_HINT_LENGTH

Zeichen des zurückgehaltenen Betreffs, die in der Challenge zitiert werden. Standardwert 8; 0 lässt den Hinweis weg; höchstens 64.

TEMPLATE

Basisname der Vorlagendateien der Challenge. Standardwert secretary-challenge.

SUBJECT

Betreff der Challenge, wenn kein SUBJECT_<LANG> passt. Standardwert Please confirm your message to {{RECIPIENT}}.

DEFAULT_LANGUAGE

Sprache, die verwendet wird, wenn keine der erkannten Sprachen des Absenders einen Text hat. Standardwert en; pepsi-setup(1) verlangt einen Text dafür.

MESSAGE_<LANG>, SUBJECT_<LANG>, CONFIRM_MESSAGE_<LANG>

Überschreibungen je Sprache für den Challenge-Text, seinen Betreff und den Bestätigungstext.

LOCAL_DOMAINS, TARGETS, RECIPIENT_DELIMITER

Die gemeinsamen Lokalitätsoptionen: unter welchen Domains eine Antwortadresse liegen darf und wie {login}/{localpart} expandieren.

85.1.32.1.9. Platzierung

Auf dem eingehenden Pfad:

  • nach pepsi-stage-detect-language(1), damit die Challenge in der Sprache des Absenders verfasst ist;

  • nach pepsi-stage-check-whitelist(1), deren state.spam = false einen bekannten Absender passieren lässt — diese Stage fragt die Whitelist selbst nie ab;

  • vor pepsi-stage-aliases(1), dem Listen-Router und der lokalen Zustellung, von denen keiner eine Antwortadresse zuerst sehen darf (ein @domain-Catch-all oder ein - als RECIPIENT_DELIMITER würde sie umschreiben).

Der ausgehende Pfad sollte pepsi-stage-auto-whitelist(1) in denselben WHITELIST_NAME schreiben lassen, damit die Personen, an die Ihre Benutzer schreiben, beim Antworten nie eine Challenge erhalten. Spam-Milter laufen standardmäßig vor check-whitelist; der Abschnitt „Spam filters and the secretary“ des Handbuchs beschreibt, wie man sie hinter diese Stage verlegt.

85.1.32.1.10. Datenbank

Zwei Tabellen. pepsi.secretary_challenge enthält eine offene Challenge je (Whitelist, Absender): das Cookie, den Ablaufzeitpunkt und ob irgendeine zurückgehaltene Nachricht DKIM bestanden hat. pepsi.secretary_sent hält dass eine Challenge gesendet wurde, ohne ihr Cookie, für die 24-Stunden-Obergrenze fest — getrennt gehalten, damit eine Challenge, die beantwortet wird, bouncet oder abläuft, ihrem Absender das Kontingent nicht zurückgibt. Vier Funktionen erledigen die Arbeit mit je einer Anweisung: secretary_challenge_claim() (race-sicher: zwei Worker, die dasselbe Paar beanspruchen, eröffnen eine Challenge), secretary_confirm(), secretary_abandon() und secretary_expire(). Abgelaufene Zeilen werden beim Beanspruchen neuer Challenges aufgeräumt; es muss kein Cron-Job laufen.

85.1.32.1.11. Unterbefehle

worker

Läuft als persistenter pepsi-dispatch(1)-Worker, der Nachrichten-IDs von der Standardeingabe liest.

85.1.32.1.12. Globale Optionen

-c FILE, –config FILE

Liest die Konfiguration aus FILE, statt die Standardorte zu durchsuchen.

-L LOGLEVEL, –log LOGLEVEL

Setzt die Log-Ausführlichkeit (Standardwert info).

-v, –verbose

Zeigt Log-Meldungen aus allen Quellen.

-h, –help; -V, –version

Gibt eine Verwendungsübersicht / die Version aus und beendet sich.

85.1.32.1.13. Exit-Status

0

Die Nachricht wurde verarbeitet (weitergeleitet, zurückgehalten, umgeleitet oder verbraucht).

1

Ein Fehler ist aufgetreten (Nachricht nicht gefunden oder nicht running, oder eine Einstellung pro Adresse, die den Abschnitt der Stage unbrauchbar macht). Der Grund wird in das Log geschrieben.

Ein Fehler des Hosts (die Datenbank, eine Vorlage oder ein Helper, die sich nicht verwenden lassen) wird nicht als Fehlschlag gemeldet: Die Nachricht wird pausiert und wiederholt, wie es Stage-Fehler in pepsi-dispatch(1) beschreibt. Ein Abschnitt, der sich nicht parsen lässt, lässt den Worker den Start verweigern (Status 78), statt eine Nachricht nach der anderen fehlschlagen zu lassen.

Eine Challenge, die sich nicht einreihen lässt, ist ein solcher Fehler. Sie wird zurückgezogen — die Challenge gelöscht, sofern sich ihr nicht inzwischen eine andere zurückgehaltene Nachricht angeschlossen hat, und der MAX_CHALLENGES_PER_SENDER-Platz des Absenders zurückgegeben —, und die Nachricht wird wiederholt, statt sie für eine Antwort zurückzuhalten, um die niemand gebeten wurde.

85.1.32.1.14. Beispiele

Ein Pipeline-Abschnitt auf dem eingehenden Pfad:

[stage-check-whitelist]
PROGRAM = pepsi-stage-check-whitelist
NEXT_STAGE = secretary
WHITELIST_NAME = correspondents

[stage-secretary]
PROGRAM = pepsi-stage-secretary
NEXT_STAGE = local
RESPONSE_STAGE = dkim-sign
WHITELIST_NAME = correspondents
PENALTY = EUR:50

Der eigene Challenge-Text eines Benutzers, vom Operator eingetragen:

pepsi-settings -c /etc/pepsi/pepsi.conf set alice@example.org secretary \
    MESSAGE_EN "Hi {{SENDER_NAME}},  please reply once to reach me."

85.1.32.1.15. Siehe auch

pepsi-stage-check-whitelist(1), pepsi-stage-auto-whitelist(1), pepsi-stage-anti-spam(1), pepsi-stage-vacation(1), pepsi-whitelist(1), pepsi-settings(1), pepsi-dispatch(1), pepsi.conf(5), pepsi.state(7), pepsi-setup(1)

RFC 3834 (automatische Antworten).

85.1.32.1.16. Fehler

Melden Sie Fehler an den Pepsi-Issue-Tracker.