85.1.31. pepsi-stage-vacation

answer mail that arrives while the recipient is away

Handbuchabschnitt:

1

85.1.31.1.1. Name

pepsi-stage-vacation - die Abwesenheits-Stage der Pepsi-Pipeline.

85.1.31.1.2. Übersicht

pepsi-stage-vacation [GLOBAL-OPTIONS] worker

85.1.31.1.3. Beschreibung

pepsi-stage-vacation ist ein Stage-Programm, das von pepsi-dispatch(1) als persistenter Worker ausgeführt wird, der Nachrichten-IDs von der Standardeingabe liest. Es lädt diesen pepsi.workqueue-Datensatz (und weigert sich zu handeln, sofern sein status nicht running ist), liest seinen [stage-<stage>]-Abschnitt und sendet — wenn der Umschlagempfänger abwesend ist — die Abwesenheitsnotiz dieses Empfängers an den Absender.

Die Nachricht selbst geht immer zu NEXT_STAGE weiter. Diese Stage fügt eine Antwort hinzu; sie hält, verwirft oder bounct Mail nie, und NEXT_STAGE ist daher verpflichtend. Wenn eine Notiz gesendet wurde, erhält das Subject: der weitergeleiteten Kopie VACATION_TAG (Standardwert [VACATION]), sodass der Empfänger bei seiner Rückkehr sehen kann, welche Mail für ihn beantwortet wurde.

Der Header-Block wird geladen, der Nachrichtentext nie: Eine Notiz zitiert nichts vom Original.

85.1.31.1.4. Wessen Abwesenheit

Die Konfiguration wird über die Überschreibungsschicht je Adresse gelesen, es ist also die wirksame Konfiguration des Umschlagempfängers. Die Schichten, niedrigste Präzedenz zuerst:

[stage-<name>] in pepsi.conf     the operator's default: normally nobody away
  < config_override 'global'       a national holiday, for everybody
  < config_override 'domain:<d>'   a holiday for one served domain
  < config_override 'address:<a>'  a leave the operator enters for someone
  < pepsi.settings[<a>]            the account owner's own leave dates

Nichts davon ist für diese Stage spezifisch — pepsi-config(1) und pepsi-settings(1) bauen dieselbe Kette für jede Stage —, aber dies ist die Stage, in der jede Schicht genutzt wird: eine Funktion je Benutzer, deren globaler Standardwert „niemand ist abwesend“ und deren globale Einstellung ein Feiertag ist. Die Stage in den EDITABLE_STAGES von pepsi-stage-edit-settings(1) aufzuführen erlaubt Kontoinhabern, ihre eigenen Urlaubsdaten per E-Mail zu setzen.

Wenn die Empfänger einer Nachricht über die Optionen dieser Stage uneins sind, hat das Gerüst sie bereits vor dem Lauf der Stage in einen Datensatz je eigener Konfiguration aufgeteilt. Ein Datensatz kann dennoch mehrere Empfänger tragen, die sich eine Konfiguration teilen (zwei Aliase einer Person oder alle während eines nationalen Feiertags); trifft eine Abwesenheit zu, teilt die Stage auch diese auf, denn jede Notiz kommt von einer Adresse und jede Ratenbegrenzung gilt für eine Adresse.

85.1.31.1.5. Wann eine Notiz gesendet wird

Der heutige Tag fällt in einen der VACATION_RANGES, und jede der folgenden Bedingungen gilt. Jede ist ein dokumentierter Grund, nicht zu antworten, und jede wird protokolliert, wenn sie greift, sodass „warum hat niemand meine Abwesenheitsantwort bekommen“ aus dem Journal heraus beantwortbar ist.

  • Die Nachricht ist eingehend. Eine lokal eingelieferte Nachricht (state.local_origin) wird nie beantwortet — die Einstellungsschicht schlüsselt eine solche Nachricht auf ihren Absender, sodass ohne dies die eigenen Urlaubsdaten des Kontoinhabers seine eigene ausgehende Mail beantworten würden.

  • Keine RFC-3834-Regel verbietet, sie zu beantworten:

    • der Null-Absender <> — ein Bounce wird nie beantwortet;

    • Auto-Submitted: mit jedem Wert außer no (RFC 3834 §5) — das Feld existiert, damit Beantworter einander erkennen, und jede Notiz, die Pepsi sendet, trägt auto-replied, was zwei aufeinander gerichtete Pepsi-Instanzen sicher macht;

    • Precedence: bulk, list oder junk;

    • X-Auto-Response-Suppress:, das All, OOF oder AutoReply nennt;

    • irgendein List-Id:/List-Post:/List-Unsubscribe:/…-Feld, d. h. die Nachricht kam über eine Mailingliste;

    • ein Dienstabsender — MAILER-DAEMON, postmaster, noreply, owner-<list>, <list>-request, <list>-bounces+… (einschließlich der VERP-Formen) —, der niemandes Postfach ist und oft ein Roboter, der zurückantwortet;

    • ein multipart/report-Nachrichtentext, der ein Zustellbericht ist, selbst wenn er mit einem nicht leeren Umschlagabsender eintrifft;

    • dass die Nachricht von der antwortenden Adresse selbst stammt;

    • ein vorgelagertes state.spam = true-Urteil: Spam zu beantworten ist Backscatter, und es bestätigt demjenigen, der ihn gesendet hat, ein lebendiges Postfach.

  • Der Empfänger erscheint in To:, Cc:, Resent-To: oder Resent-Cc: (RFC 3834 §2/§3; Bcc: und Resent-Bcc: sind bewusst ausgenommen), sofern REQUIRE_ADDRESSED_TO nicht aus ist. Mail, die ein Postfach erreicht, ohne es dort zu nennen, kam per Blindkopie, über einen Alias, den der Absender nie gesehen hat, oder von einer geernteten Liste.

  • Diesem Korrespondenten wurde nicht bereits innerhalb von SUPPRESS_DAYS geantwortet.

Die Notiz ist eine text/plain-Nachricht mit Null-Absender, injiziert bei RESPONSE_STAGE, wo sie wie jede andere ausgehende Mail signiert und weitergeleitet wird. Sie ist From: der abwesenden Adresse, To: dem Umschlagabsender, trägt Auto-Submitted: auto-replied und zitiert die Message-ID: des Originals in In-Reply-To:/References:, sodass sie im Thread unter der Nachricht erscheint, die sie beantwortet. Ihr Betreff ist SUBJECT_PREFIX, gefolgt vom ursprünglichen Betreff (RFC 5230 §4.5). Die weitergereichte Kopie hält unter state.vacation fest, dass sie beantwortet wurde (notified, der recipient, die zutreffende range und die verwendete language); siehe pepsi.state(7).

Nichts wird gesendet, keine Abfrage gemacht und kein Header untersucht, wenn VACATION_RANGES leer ist, was der Standardwert ist und der Zustand jedes Empfängers, der nie eine Abwesenheit konfiguriert hat.

85.1.31.1.6. Schleifen- und Flutkontrolle

Ein Abwesenheitsbeantworter ist der eine Teil eines Mailsystems, der je empfangener Nachricht eine Nachricht erzeugt, also der eine Teil, der aus dem Nichts eine Schleife bauen kann. Vier unabhängige Mechanismen begrenzen ihn:

  1. Der Null-Umschlagabsender. Ein entfernter Beantworter hat nichts, worauf er antworten könnte: Die Adresse, die er beantworten würde, existiert nicht.

  2. ``Auto-Submitted:``, beim Hereinkommen beachtet und beim Hinausgehen gesetzt.

  3. Die Ratenbegrenzung. Selbst ein entfernter Beantworter, der beides ignoriert, wird höchstens einmal je SUPPRESS_DAYS beantwortet, sodass eine Schleife nicht davonlaufen kann — sie kostet eine Nachricht pro Woche.

  4. Das Warteschlangentoken. Die Notiz wird unter dem Token <token>-vacation injiziert, und diese Spalte ist UNIQUE, sodass eine nach einem Absturz wiederholte Stage keine zweite Kopie senden kann.

85.1.31.1.7. Abwesenheitszeiträume

VACATION_RANGES ist eine durch Kommas oder Leerraum getrennte Liste von YYYY-MM-DD:YYYY-MM-DD-Spannen. Beide Endpunkte sind eingeschlossene ganze Tage, sodass 2026-08-01:2026-08-14 den ersten und den vierzehnten vollständig abdeckt. Zwei Kurzformen: ein leeres Ende (2026-08-01:) ist offen, für einen Urlaub ohne festes Rückkehrdatum, und ein bloßes Datum (2026-08-01) ist dieser einzelne Tag.

„Heute“ ist das aktuelle Datum in der Zeitzone des Servers (aus /etc/localtime): Ein Operator, der 2026-08-14 schreibt, meint den Vierzehnten dort, wo er lebt, nicht den Vierzehnten in UTC, was östlich von Greenwich den Feiertag am Nachmittag zuvor enden ließe. Eine Installation, die UTC-Grenzen will, läuft mit TZ=UTC, was eine Entscheidung über die Maschine ist statt eine Option einer Stage.

Das Datum wird aufgelöst, wenn die Stage läuft, nicht, als die Nachricht ankam, sodass eine zwei Tage von pepsi-stage-anti-spam(1) oder einer Schlüsselabfrage zurückgehaltene Nachricht an dem Tag beurteilt wird, an dem sie diese Stage schließlich erreicht — was auch die sichere Lesart ist, denn die Alternative beantwortet Mail im Namen von jemandem, der schon wieder am Schreibtisch sitzt.

Überlappende Zeiträume sind erlaubt; der erste, der passt, ist derjenige, dessen Daten die Notiz zitiert. Ein Zeitraum, dessen Ende vor seinem Anfang liegt, ist ein Konfigurationsfehler.

85.1.31.1.8. Die Nachricht

Der Notiztext ist eine Mustache-Vorlage, die in einer INI-Option liegt, nicht in einer Datei. Dies ist die eine Nachricht in Pepsi, die Menschen selbst schreiben, und der einzige Kanal, den ein Kontoinhaber hat — sein pepsi.settings-Datensatz, ob mit pepsi-settings(1) gesetzt oder per Mail über pepsi-stage-edit-settings(1) —, trägt Optionen des eigenen Abschnitts dieser Stage.

Zwei Quellen werden für jede Kandidatensprache in dieser Reihenfolge herangezogen:

  1. MESSAGE_<LANG> im eigenen Abschnitt der Stage (MESSAGE_EN, MESSAGE_DE_CH, …) — je Adresse überschreibbar, also der eigene Text des Benutzers;

  2. <LANG> in dem Abschnitt, den DEFAULT_MESSAGE_SECTION benennt (Standardwert [pepsi-vacation-default-message], ausgeliefert in ${DATADIR}/config.d, sodass er unangetastet existiert). Dieser Abschnitt wird aus der Basis-Konfiguration gelesen: Die adressweise Einstellungsschicht kann nur [stage-*]-Optionen tragen, sodass allein die obige Form MESSAGE_<LANG> der eigene Text eines Benutzers ist.

Die erste Quelle gewinnt je Sprache, nicht pauschal: Ein Benutzer, der nur MESSAGE_DE schreibt, bekommt für englischsprachige Korrespondenten weiterhin den englischen Text des Operators.

85.1.31.1.8.1. Die Sprache wählen

Kandidaten sind die erkannten Sprachen des Absenders — state.language, die Accept-Language-förmige Zeichenkette, die pepsi-stage-detect-language(1) festhält — in absteigender Konfidenz, dann DEFAULT_LANGUAGE. Für jeden Kandidaten wird die nächstgelegene verfügbare Nachricht verwendet: das exakte Tag, dann sein primäres Subtag (de-ch fällt auf de zurück), dann jedes Tag, das es verfeinert (de akzeptiert ein alleinstehendes DE_CH, sodass ein Operator, der nur Schweizerdeutsch geschrieben hat, dennoch Deutschsprachige erreicht). Tags dürfen mit beiden Trennzeichen geschrieben werden: DE_CH und DE-CH sind dieselbe Sprache.

Beachten Sie, dass pepsi-stage-detect-language(1) nur primäre Subtags meldet (en, de), nie Regionen, sodass eine regionsqualifizierte Nachricht über die Verfeinerungsregel oder durch Setzen von DEFAULT_LANGUAGE darauf erreicht wird.

85.1.31.1.8.2. Felder

{{SENDER_NAME}}

Der From:-Anzeigename des Absenders oder seine vollständige Adresse, wenn das From: keinen Namen trägt.

{{VACATION_START}}

Erster Tag der Abwesenheit, als YYYY-MM-DD.

{{VACATION_END}}

Letzter Tag der Abwesenheit — bei einem offenen Urlaub nicht vorhanden.

{{EMERGENCY_CONTACT}}

Der konfigurierte EMERGENCY_CONTACT — nicht vorhanden, wenn es keinen gibt.

Die beiden, die fehlen können, sind nicht vorhanden und nicht leer, sodass eine Vorlage mit {{#VACATION_END}}…{{/VACATION_END}} und {{^VACATION_END}}…{{/VACATION_END}} darauf verzweigt, statt einen Satz mit einem Loch zu rendern. Daten sind ISO YYYY-MM-DD: in jeder Locale eindeutig, was ein lokalisierter Monatsname nicht wäre.

Escaping ist kein Thema: Diese vier Felder rendern wortgetreu, welcher Klammerstil auch verwendet wird, denn die Notiz ist text/plain. (Mustaches {{x}} maskiert normalerweise HTML, was einen Korrespondenten namens O'Brien als O&#39;Brien begrüßen würde.)

85.1.31.1.8.3. Die Zwei-Leerzeichen-Regel

Eine INI-Option ist eine einzelne Zeile, daher werden zwei Leerzeichen zu einem Zeilenumbruch — und vier Leerzeichen zu zwei Zeilenumbrüchen, also einem Absatzumbruch. Die Ersetzung wird auf die Vorlage vor der Mustache-Expansion angewandt, nie auf das Ergebnis, sodass ein Anzeigename, der zufällig zwei Leerzeichen enthält, die Nachricht nicht umstrukturieren kann.

Der taler-Parser trimmt die ganze Zeile, sodass ein abschließendes Doppelleerzeichen verloren geht, sofern der Wert nicht in Anführungszeichen steht (MESSAGE_EN = "…  " — genau ein umgebendes Anführungszeichenpaar wird entfernt).

85.1.31.1.9. Optionen

Alle diese sind je Adresse überschreibbar.

VACATION_RANGES

Durch Kommas oder Leerraum getrennte YYYY-MM-DD:YYYY-MM-DD-Spannen (siehe oben). Standardmäßig leer, was die Stage für diese Adresse abschaltet.

RESPONSE_STAGE

Stage, bei der die Notiz injiziert wird, damit sie signiert und weitergeleitet wird. Erforderlich.

DEFAULT_LANGUAGE

Sprache, die verwendet wird, wenn keine der erkannten Sprachen des Absenders eine Nachricht hat. Standardwert en.

DEFAULT_MESSAGE_SECTION

Konfigurationsabschnitt, der je Sprache eine eingebettete Nachricht enthält. Standardwert pepsi-vacation-default-message.

EMERGENCY_CONTACT

Eine einzelne bloße Adresse, unter der man während der Abwesenheit des Empfängers erreichbar ist, der Vorlage angeboten. Standardmäßig nicht gesetzt, in welchem Fall der {{#EMERGENCY_CONTACT}}-Block einer Vorlage übersprungen wird.

VACATION_TAG

An das Subject: der weitergeleiteten Nachricht angehängt, wenn eine Notiz gesendet wurde. Standardwert [VACATION]; der Wert none deaktiviert die Markierung. Das Anhängen ist idempotent — ein Korrespondent, der auf eine markierte Nachricht antwortet, zitiert die Markierung zurück, und ein zweiter Durchlauf hängt keine zweite an.

Ein leerer Wert deaktiviert es nicht: Der taler-Parser behandelt einen leeren Wert als abwesende Option, was den Standardwert erneut anwendet. Deshalb gibt es einen Sentinel.

SUPPRESS_DAYS

Wie lange nach der Beantwortung eines Korrespondenten er erneut beantwortet werden darf. Standardwert 7 (der Standardwert von Sieves vacation, RFC 5230 §4.1). 0 beantwortet jede Nachricht; das Maximum ist 3650 (zehn Jahre).

REQUIRE_ADDRESSED_TO

Nur antworten, wenn der Empfänger in To:, Cc:, Resent-To: oder Resent-Cc: erscheint (RFC 3834 §2/§3). Standardmäßig an.

SUBJECT_PREFIX

Dem ursprünglichen Betreff vorangestellt, um den Betreff der Notiz zu bilden. Standardwert Auto: (RFC 5230 §4.5). Eine Nachricht ohne Betreff ergibt allein das Präfix, und einem Betreff, der das Präfix bereits trägt, wird es nicht ein zweites Mal vorangestellt.

85.1.31.1.10. Platzierung

Auf dem eingehenden Pfad:

  • nach pepsi-stage-detect-language(1), das state.language liefert, sodass die Notiz in der Sprache des Absenders sein kann;

  • nach pepsi-stage-check-whitelist(1) und pepsi-stage-anti-spam(1), sodass Spam und unbezahlte Mail keine Antwort nach sich ziehen;

  • nach pepsi-stage-aliases(1), falls Aliase im Einsatz sind: Die Konfiguration ist auf den Umschlagempfänger geschlüsselt, sodass dieser dann die eigene Adresse des Benutzers sein muss und nicht der Alias.

Eine Folge davon, nach pepsi-stage-arc(1) zu laufen: Das Subject: umzuschreiben entwertet die DKIM-Signatur des Urhebers und die ARC-Nachrichtensignatur, die Pepsi selbst angebracht hat, da beide Subject abdecken (und übersignieren). Das ist auf einem Zweig, der in lokaler Zustellung endet, harmlos — die obige Platzierung, und die, auf die sich pepsi-stage-decrypt(1) aus demselben Grund bereits verlässt. Auf einem Zweig, der die Nachricht weiterleitet, wird der nächste Hop diese Signaturen scheitern sehen; setzen Sie dort also VACATION_TAG = none.

85.1.31.1.11. Datenbank

Eine Tabelle, pepsi.vacation_reply, die (recipient, sender, last_sent) hält, und eine Funktion, vacation_should_reply(), die in derselben Anweisung entscheidet und festhält — zwei Worker mit zwei Nachrichten desselben Korrespondenten fänden sonst beide keine vorherige Notiz und sendeten beide eine. Sie räumt zudem im Vorbeigehen auf: die Datensätze dieses Empfängers, die älter als sein eigenes Fenster sind, dazu ein Durchgang über alle Datensätze, die älter als ein Jahr sind, für einen Empfänger, der aufhört zu verreisen; es gibt keine Cron-Aufgabe auszuführen. Ein Anspruch, der für eine Notiz genommen wurde, die sich dann nicht bauen oder einreihen lässt, wird wieder gelöscht, sodass der Korrespondent nicht als beantwortet vermerkt wird, ohne es zu sein. Eine Nachricht, die wiederholt wird, nachdem ihre Notiz eingereiht wurde, sendet keine zweite: Innerhalb von SUPPRESS_DAYS lehnt der Anspruch sie ab, und bei SUPPRESS_DAYS = 0 sorgt das aus dem der Nachricht abgeleitete Token der Notiz dafür, dass die Warteschlange die bereits vorhandene Notiz zurückgibt.

85.1.31.1.12. Unterbefehle

worker

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

85.1.31.1.13. 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.31.1.14. Exit-Status

0

Die Nachricht wurde verarbeitet (weitergeleitet, mit oder ohne gesendete Notiz).

1

Ein Fehler ist aufgetreten (Nachricht nicht gefunden oder nicht running, oder eine Einstellung pro Adresse, die den Abschnitt der Stage unbrauchbar macht — etwa ein fehlerhafter Datumsbereich). Der Grund wird in das Journal 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 Notiz, die nicht gebaut oder eingereiht werden kann, ist kein Fehler: Sie wird als Warnung protokolliert, und die Nachricht wird unverändert weitergeleitet. Die Mail des Empfängers zählt mehr als die Höflichkeitsantwort an den Absender.

85.1.31.1.15. Beispiele

Eine Nachricht beantworten (sie muss running sein):

echo 42 | pepsi-stage-vacation -c /etc/pepsi/pepsi.conf worker

Ein Pipeline-Abschnitt auf dem eingehenden Pfad, ohne konfigurierte Abwesenheit — der Operator verdrahtet die Stage einmal, und Benutzer schalten sie für sich selbst ein:

[stage-vacation]
PROGRAM = pepsi-stage-vacation
NEXT_STAGE = local
RESPONSE_STAGE = dkim-sign

Ein nationaler Feiertag, für jede Adresse, die die Instanz bedient:

pepsi-config -c /etc/pepsi/pepsi.conf set --scope global \
    stage-vacation VACATION_RANGES 2026-12-24:2026-12-26

Der Urlaub eines Benutzers, vom Operator eingetragen:

pepsi-settings -c /etc/pepsi/pepsi.conf \
    set alice@example.org vacation VACATION_RANGES 2026-08-01:2026-08-14
pepsi-settings -c /etc/pepsi/pepsi.conf \
    set alice@example.org vacation EMERGENCY_CONTACT ops@example.org

…oder vom Benutzer selbst, wenn der Operator vacation in den EDITABLE_STAGES von pepsi-stage-edit-settings(1) aufgeführt hat — eine Mail an pepsi@example.org mit dem Betreff Pepsi und diesem Nachrichtentext:

[stage-vacation]
VACATION_RANGES = 2026-08-01:2026-08-14
MESSAGE_EN = Hi {{SENDER_NAME}},  I am off sailing until {{VACATION_END}}.

85.1.31.1.16. Siehe auch

pepsi-config(1), pepsi-settings(1), pepsi-stage-detect-language(1), pepsi-stage-edit-settings(1), pepsi-stage-aliases(1), pepsi-dispatch(1), pepsi.conf(5), pepsi.state(7), pepsi-setup(1)

RFC 3834 (automatische Antworten), RFC 5230 §4 (die Sieve-vacation-Aktion, deren :days- und Betreffregeln diese Stage befolgt).

85.1.31.1.17. Fehler

Melden Sie Fehler an den Pepsi-Issue-Tracker.