short.txt
changeset 13 95ecb62b93e6
parent 12 86e315be5b57
child 15 f0138e72be4e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/short.txt	Mon Apr 20 23:07:59 2015 +0200
@@ -0,0 +1,1565 @@
+Kurzer Konfigurationsritt
+=========================
+:Author: Heiko Schlittermann
+:toc:
+:data-uri:
+:icons:
+:numbered:
+:ascii-ids:
+
+_italic_::
+    Namen von Dateien, Programmen, Hosts, Domains, Mail-Header, URLS: _example.com_, _From:_
+*bold*::
+    Namen von Exim-Routern, Transports, Authenticators: *dnslookup*-Router
++fixed+::
+    Kommandos, Code-Beispiele, Exim-Konfigurations-Optionen: +primary_hostname+
+
+*+fixed bold+*::
+    Hervorhebung von Kommandos, Nutzereingaben: *+exim -bV+*
+
+'+slanted+'::
+    Exim-Variablen im Text: '+$local_part+' oder '+$sender_address+'
+
+== Konfiguration
+
+=== File
+
+Das Konfigurationsfile wird in der Build-Konfiguration (_EDITME_) festgelegt.
+Es ist auch eine Liste von Konfigurationsfiles möglich, der erste Treffer gewinnt.
+Das verwendete File läßt sich ermitteln mit
+
+ exim -bP configure_file
+
+Das aktive Konfigurationsfile kann auch auf der Kommandozeile festgelegt
+werden. Für einige Operationen muss der Pfad ein absoluter sein.  Auch
+_/dev/null_ ist eine gültige Konfiguration.
+
+ exim -C <Pfadname> …
+
+Die Konfiguration wird öfter gelesen als vielleicht erwartet:
+
+* Beim Start
+* Aber - wann wird gestartet?
+    ** Start des Daemon
+    ** Signal _HUP_ 
+    ** re-exec for verschiedene Zwecke
+
+CAUTION: Inhalt der Datei _exim.conf_ footnote:[Debian verwendet häufig exim4 an
+stelle von exim.]
+und eventuell über +.include+ eingelesener Files
+ist statisch. Dynamisch sind dann Expansionen, Lookups.
+
+=== Syntax
+
+Der Parser der Konfigurationsdatei ist ziemlich einfach.
+
+. Kommentarzeilen werden entfernt
+. Führende und anhängige Leerzeichen werden entfernt
+. Forsetzungszeilen („\“ am Zeilenende) werden zusammengefasst
+. einfache Syntax-Checks
+
+Die Konfiguration besteht aus mehreren Abschnitten. Nicht alle Abschnitte
+sind identisch aufgebaut.
+
+Globale Optionen::
+    Allgemeine Parameter wir Listendefinitionen, Optionen für den Mailempfang,
+    Datenbank-Verbindungsparameter
+Access Control Lists::
+    Kontrolle der Nachrichtenannahme
+Router::
+    Steuerung des Nachrichten-Routings (Ermittlung des Zielhosts und des
+    Transportmechanismus)
+Transports::
+    Konfiguration der Transportmechanismen
+Rewrite::
+    Umschreiben von Envelope und Kopfzeilen
+Authentifizierung::
+    Parameter für die SMTP-Authentifizierung (sowohl Client als auch Server)
+
+== Syntax der Konfiguration
+
+=== Kommentare
+Alle Zeilen, die mit einem „#“ beginnen (nach optionalem Whitespace), sind Kommentarzeilen.
+An anderen Stellen der Konfiguration hat das „#“-Zeichen keine besondere Bedeutung.
+
+=== Macros
+Macros sind für einen einfachen statischen Textersetzungsmechanismus und für das
+bedingte Parsen von Konfigurationsteilen. Macros können in der Konfiguration definiert werden, aber
+auch auf der Kommandozeile. (Auf der Kommandozeile gibt es jedoch wegen eventueller Sicherheitsimplikationen
+einige Besonderheiten zu beachten.) Macros werden generell groß geschrieben.
+
+ LDAP_BASE = ou=ousers,o=acme
+ LDAP = ldap:///LDAPBASE
+ …
+ data = ${lookup ldap{LDAP?mail?sub?uid=${quote_ldap:$local_part}}}
+ …
+ .ifdef TESTING
+ testrouter:
+    driver = dnslookup
+    …
+ .endif
+
+Und beim Aufruf:
+
+ exim -DTESTING …
+ exim -DFOO=bar …
+
+Macros können neu definiert werden („==“ statt „=“). Macros von der Kommandozeile haben Vorrang.
+
+=== Optionen
+Es gibt ca. 250 globale Optionen, hinzu kommen noch weitere Optionen für Router, Transports, …
+Optionen haben einen bestimmten <<types,Datentyp>>. Optionen werden generell klein geschrieben.
+
+ primary_hostname = foo.example.com
+
+=== Listen
+Listen bestehen aus der Angabe des Listentypes, eines Namens und dem Listeninhalt.
+Es gibt 4 verschiedenen Listentypen. 
+
+Domains::
+  Liste von Domain-Namen. Es gibt einige spezielle Tokens, die in einer solchen
+  Liste auftauchen dürfen.
+
+ domainlist local_domains = @ : schlittermann.de : @mx_primary
+
+Hosts::
+    Hosts oder IP-Adressen, z.B. für vertrauenswürdige Absender-Netze
+
+ hostlist trusted_hosts = 192.168.0.0/24 : 127.0.0.1
+
+Mail-Adressen::
+    Mailadressen
+
+ addresslist blocked_senders = ad@bestholiday.de : *@mailgun.com
+
+Local Parts::
+    Local Parts von Mail-Adressen, z.B. von ACL-Checks ausgenommene lokale Empfänger 
+
+ localpartlist rfc = postmaster : abuse
+
+Listen-Lookups werden nur gecacht, wenn die Liste keine Expansions-Items entält
+(also kein '\$'). Um ein Caching zu erwzingen, kann dem Listentyp ein +_cache+
+nachgesetzt werden:
+
+ domainlist_cache local_domain = ${lookup …}
+
+=== Instanzen von Routern, Transports, Authentificators
+
+Router, Transports und Authenificators werden in einzelnen „Funktionsblöcken“
+definiert.  Diese Blöcke haben selbstgewählte Namen und eine Liste von
+Optionen, die das Verhalten des jeweiligen Routers, Transports oder
+Authenicators bestimmen.
+
+ begin transports
+ …
+ remote_smtp:
+    driver = smtp
+    command_timeout = 20s
+
+=== ACL und Rewrite-Regeln
+
+Diese beiden Teile der Konfiguration haben ihre eigene Syntax.
+
+[[types]]
+== Werte und ihre Typen
+
+ALle Optionen der Konfigurationsdatei haben einen spezifischen Werte-Typ.
+
+* _bool_, _integer_, _fixed-point_, _time_ und _string_
+* Listen sind immer String-Listen
+* Werte, die der Expansion unterliegen, sind immer vom Typ _string_
+
+
+=== Bool
+
+Werte vom Typ _bool_ sind einfache Schalter.
+
+.Format 
+ <option> = true
+ <option> = false
+ <option>
+ no_<option>
+ not_<option>
+
+.Beispiel
+ split_spool_directory
+ not_split_spool_directory
+ split_spool_directory = true
+ split_spool_directory = no
+
+=== Integer
+
+Zahlen. Ganze Zahlen.
+
+.Format
+  … = <digits>[<suffix>]
+        = 0<oct digts>[<suffix>]
+        = 0x<hex digts>[<suffix>]
+
+Erlaubte Suffixe sind 'k' (2^10^) und 'm' (2^20^).
+
+.Beipiel
+ check_spool_space = 10M
+
+=== Fixed-Point
+
+Fixkomma-Zahlen, maximal 3 Nachkommastellen
+
+.Format
+ … = <digits>[.<max 3 digits>]
+
+Diese Werte erlauben *keine* Einheitensuffixe.
+
+.Beispiel
+ deliver_queue_load_max = 2.5
+
+=== Zeitintervalle
+
+Zeitintervalle sind Zeitintervalle.
+
+.Format: 
+ … = <digits><suffix>[<digits><suffix>]…
+
+Erlaubte Suffixe sind 's', 'm', 'h', 'd', 'w', also für
+Intervalle, die sich zweifelsfrei in Sekunden umrechnen lassen.
+
+.Beispiel
+ auto_thaw = 3d12h
+
+CAUTION: Bei der Ausgabe von Intervall-Optionen werden die Zeiten normalisiert.
+
+=== Zeichenketten
+
+Zeichenketten gibt es in zwei Formen: Literale Zeichenketten und gequotet.
+Zeichenketten, die später noch expandiert werden, werden _immer_ als gequotete
+Zeichenketten behandelt.
+
+.Format
+ … = <string>
+ … = <"string">
+
+Die gequotete Form ist notwendig, wenn die Zeichenkette mit Leerzeichen enden
+oder beginnen soll, oder wenn eine der folgenden Sequenzen interpretiert
+werden soll: '\\', '\n', '\r', '\t', '\ddd' (oktaler Zeichenwert), '\xdd'
+(hexadezimaler Zeichenwert).
+
+.Beispiel
+ bounce_message_file = /etc/exim/bounce-message.txt
+ bounce_message_text = "Sorry.\nI'm really sorry.\n"
+ message = User $local_part does not exist.
+
+CAUTION: Bei der Ausgabe von String-Optionen werden eventuell vorhandene Steuerzeichen
+durch korrenspondierende Escape-Sequenzen ersetzt.
+
+=== Listen
+
+Listen sind immer Listen zuerst eine _einzige_ Zeichenkette, unterliegen also
+den Zeichenketten-Interpretationsregeln.  Der Feldtrenner ist standardmäßig
+ein ':'. Wird der Feldtrenner als Teil eines Listenelements benötigt, muss er
+verdoppelt werden (oder es wird ein anderer Trenner gewält.)
+Umschließender Leerraum an den einzelnen Elementen wird ignoriert. Leere
+Elemente in der Liste und am _Ende_ der Liste werden ignoriert.
+
+.Format
+ … = <item> : <item> …
+ … = <item> : <i::tem> …
+ … = <<separator> <item> ; <item> …
+
+.Beispiel
+ local_interfaces = 127.0.0.1 : ::::1
+ local_interfaces = <; 127.0.0.1 ; ::1
+ domains = <\n ${lookup mysql{…}}
+ senders =   <1>
+ senders = : <2>
+
+<1> leere Liste
+<2> Liste mit einem leeren Element
+
+.Debugging
+ exim -be '${map{:a:b:c,}{<$item>}}'
+ exim -be '${map{<,,a,b,c,}{<$item>}}'
+ exim -C <(echo domainlist local_domains = 'a:b::c:d') -be '${listnamed:local_domains}'
+
+=== Reguläre Ausdrücke
+
+Reguläre Ausdrücke werden durch 'libpcre' ausgewertet, sie sind also kompatibel
+mit den von Perl bekannten regulären Ausdrücken. Reguläre Ausdrücke werden immer
+zuerst als String evaluiert, eventuelle Backslash-Sequenzen müssen also ggf. geschützt
+werden.
+
+.Format
+ … = ^<regexp>
+
+.Beispiel
+ domains = example.com : ^\\d{3}
+ domains = example.com : \N^\d{3}\N
+
+Im Beispiel wird der Backslash verdoppelt, da die +domains+ Option zuerst
+expandiert wird.
+
+== Expansion von Zeichenketten
+
+Viele Stellen der Konfiguration verwenden String-Expansion (Typ 'string*' im
+_spec.txt_). String-Expansion wird von '\$' getriggert.  Das Ergebnis ist dann
+ein neuer String oder 'forced failure'. 
+Die Expansion der Strings erfolgt in der Regel erst im Bedarfsfall („late
+binding“). 
+
+CAUTION: Es stehen aber nicht in jeder Phase alle Items zur Verfügung. (z.B.
+wird der Wert der globalen Option +message_size_limit+ expandiert, aber bereits
+während der Antwort auf das SMTP-HELO, in dieser Phase gibt es noch keinen
+'+$local_part+').
+
+.Debugging
+ exim -be [<string>]
+ exim -bem <message-file> [<string>]
+ exim -be -Mset <spool-id> [<string>]
+ 
+ eg: exim -be '$primary_hostname'
+     exim -be '$tod_full'
+     exim -bem <(echo 'Subject: Hi') '$h_subject:'
+
+=== Expansions-Items
+
+Aus Sicht des Expanders ist alles, was mit einem '\$' beginnt, ein
+Expansions-Item.
+
+Variablen::
+    Das sind operative Parameter, Information über die aktuelle Nachricht,
+    den aktuellen Systemzustand, Rückgabewerte.
+    http://www.exim.org/exim-html-current/doc/html/spec_html/ch-string_expansions.html#SECTexpvar[spec]
+
+ $local_part
+ ${local_part}
+
+Operatoren::
+    Einfache Funktionen wie die Transformation einer Zeichenkette von Klein- auf
+    Großbuchstaben.
+    http://www.exim.org/exim-html-current/doc/html/spec_html/ch-string_expansions.html#SECTexpop[spec]
+
+ ${hex2b64:<string>}
+
+Bedingungen::
+    Fluss-Steuerung
+    http://www.exim.org/exim-html-current/doc/html/spec_html/ch-string_expansions.html#SECTexpcond[spec]
+
+ ${if <condition>…}
+
+Funktionen::
+    Komplexere Umwandlungen mit mehreren Eingangsparametern
+    http://www.exim.org/exim-html-current/doc/html/spec_html/ch-string_expansions.html#SECTexpansionitems[spec]
+
+ ${readsocket{<socket>}}
+
+Lookups::
+    Informationsgewinnung aus externen Quellen (Files, Datenbanken)
+    http://www.exim.org/exim-html-current/doc/html/spec_html/ch-file_and_database_lookups.html[spec]
+
+ ${lookup{<item>}lsearch{<file>}}
+ lsearch;<file>
+
+== Lookups
+
+Mit Lookups werden Daten aus externen Quellen gewonnen. Lookups gibt es in zwei
+Syntaxvarianten und in zwei Stilen.
+
+* Syntax
+** implizit
+** explizit
+* Stil
+** Single-Key 
+** Query-Style
+
+
+=== Syntax
+
+==== explizit
+
+Der Key oder die Frage wird ausdrücklich formuliert, es ist eine gewöhnliche
+String-Expansion. Als Resultat wird das Ergebnis des Lookups zurückgeliefert.
+
+.Format
+ … = ${lookup{<key>}<type>{<file>}}
+ … = ${lookup <type>{<query>}}
+
+.Beispiel
+ domainlist local_domains = ${lookup{$domain}dsearch{/etc/vmail/domains}}
+ local_parts = ${lookup ldap{ldap:///o=foo?uid?sub?uid=${quote_ldap:$local_part}}}
+
+Im Beispiel wird der Umstand genutzt, dass in vielen Fällen lediglich 
+die aktuell behandelte Adresse in der Liste vorhanden sein muss. 
+
+Die explizite Syntax kann natürlich auch eine komplette Liste zurückliefern,
+diese muss dann eventuell massiert werden, damit die Feldtrenner den Erwartungen 
+von Exim entsprechen.
+
+==== implizit
+
+Der Key ergibt sich aus dem Kontext, das Lookup wird dennoch durch den
+String-Expander behandelt. Wenn das Lookup erfolgreich ist, wird als Resultat
+der Key zurückgeliefert, nicht ein eventuell vorhandener Wert!
+
+.Format
+ … = <type>;<file> 
+ … = <type>;<query>
+
+.Beispiel
+ domains = lsearch;/etc/vmail/domainlist
+ domains = mysql;SELECT COUNT(*) FROM domains WHERE domain = ${quote_mysql:$domain}
+
+=== Style
+
+==== Single Key
+
+Single-Key Lookups beziehen sich auf einfach (und meist schnelle) Key/Value
+Daten. Das sind Dateien im Format der _/etc/aliases_, das sind Verzeichnisse und
+DBM-Files.
+http://www.exim.org/exim-html-current/doc/html/spec_html/ch-file_and_database_lookups.html#SECTsinglekeylookups[spec]
+
+.Wichtige Single Key Lookups
+_lsearch_::
+    Lineare Suche in einer Datei. Suche nach einem Default-Wert mit _lsearch*_,
+    Suche nach Teilzeichenketten (Domain) mit _partial-lsearch_.
+_dsearch_::
+    Verzeichnis-Lookup: Suche nach einem spezifischen Verzeichniseintrag
+_iplsearch::
+    Suche nach IP-Adressen oder Netzen unter Beachtung von Netzmasken
+_dbm_::
+    Suche in Berkeley-DBM Files
+
+.Beispiel
+ data = ${lookup{$local_part}lsearch*{/etc/aliases}}
+
+==== Query Style
+
+Komplexe Anfragen im Sinne einer „Query“.
+http://www.exim.org/exim-html-current/doc/html/spec_html/ch-file_and_database_lookups.html#SECTquerystylelookups[spec]
+
+.Wichtige Query-Style Lookups
+_mysql_::
+    Eben MySQL…
+
+ ${lookup mysql{SELECT … WHERE … like ${quote_mysql:$local_part}}
+
+_dnsdb_::
+    Pseudo-Queries
+
+ ${lookup dnsdb{a=$sender_host}}
+ dnsdb;mxh=example.com
+
+_ldap_::
+    Anfragen an LDAP. Erwartet wird ein Object (_ldap_) oder mehrere Objekte
+    (_ldap_)
+
+ ${lookup ldap{ldap:///ou=foo?mail?sub?uid=${quote_ldap:$local_part}}}
+
+
+=== Überblick
+
+Es gibt also vier Möglichkeiten, Daten aus externen Quellen zu gewinnen.
+
+[cols="h,m,m",options="header"]
+|=======================================================================
+|            |  single key                    | query style
+|  explizit  |  ${lookup{<key>}<type>{<file>} | ${lookup <type> {<query>}}
+|  implizit  |  <type>;<file>                 | <type>;<query>
+|=======================================================================
+
+== Acess Control Lists
+
+ACL wirken für alle Phasen der SMTP-Session. Im globalen Teil werden die
+Einstiegspunkte mit +acl_smtp_connect+ usw. definiert. Im ACL-Abschnitt der
+Konfiguration muss dann ein entsprechend genannter Block existieren.
+
+Die häufigsten Einstiegspunkte sind
+
++acl_smtp_rcpt+::
+    Überprüfung beim +RCPT TO+ Kommando.
+
++acl_smtp_data+::
+    Überprüfung am Ende der +DATA+ Phase, also Content-Scan.
+
+Eine ACL ist eine Folge von Bedingungsblöcken. Sind _alle_ Bedingungen eines
+Blocks erfüllt, gilt die für diesen Block festgelegte Aktion.
+Die Bedingungen werden in der Reihenfolge ihres Auftretens bearbeitet. Sobald
+eine nicht zutrifft, wird der nächste Block untersucht.
+
+.Beispiel
+ accept  domains = +local_domains
+         local_parts = postmaster : abuse
+
+.Mögliche ACL-Aktionen
+_accept_::
+    Alles ist ok. Es geht zur nächsten Phase der Verbindung
+_deny_::
+    Fehler 5xx wird zurückgeliefert (nicht zwingend ein Ende der Verbindung!)
+_defer_::
+    Fehler 4xx wird zurückgeliefert
+_drop_::
+    Fehler 5xx wird generiert und Verbindung wird abgebrochen
+_warn_::
+    Keine finale Entscheidung, NOOP
+_require_::
+    Wenn eine der Bedingungen *nicht* erfüllt ist, Abbruch mit 5xx, 
+    andernfalls weiter zum nächsten Block
+_discard_::
+    Wie _accept_, aber Empfänger, bzw. Nachricht wird verworfen!
+
+.Häufige ACL-Bedingungen
++hosts+::
+    Sender-Host-IP wird geprüft
+
+ hosts = +trusted_hosts
+
++domains+::
+    Empfänger-Domain wird geprüft
+
+ domains = +local_domains
+
++senders+::
+    Absender-Mailadresse wird geprüft
+
+ senders = postmaster@example.com : hans@foo.bar
+
++malware+::
+    Malware-Content-Scan liefert einen Treffer
+
+ malware = *
+
++spam+::
+    SPAM-Content-Scan (_SpamAssassin_)
+
+ spam = nobody/true
+
++verify+::
+    Empfänger- oder Absenderüberprüfung, eventuell auch mit _callout_.
+
+ verify = recipient/callout=use_sender,defer_ok
+
++ratelimit+::
+    Limitierungen aller Art (Menge, Größe, …)
+
+ ratelimit = 10/1h/$sender_address
+
++condition+::
+    Sonstige Bedingungen aller Art
+
+ condition = ${run{perl}{graylist}{$sender_address/$local_part@$domain}}
+
+.ACL-Modifier
++message+::
+    Der Nachrichtenpuffer wird mit einem Text gefüllt.
+
+ message = 550 Sorry
+
++log_message+::
+    Der Nachritenpuffer für das Protokoll wird mit einem Text gefüllt.
+    Sonst identisch zu +message+.
+
++logwrite+:: 
+    Sofort einen Log-Eintrag
+
++control+::
+    Steuert das weitere Verhalten
+
+ control = submission
+
++set+:: 
+    ACL-Variablen setzen
+
+ set acl_m_domain = $domain
+ set acl_c_host = $sender_host_address
+
++add_header+::
+    Header zum Hinzufügen vormerken    
+
++remove_header+::
+    Header zum Entfernen vormerken
+    
++delay+::
+    Fügt eine kurze Verarbeitungspause ein
+
+Ziel der ACL-Operations sollte es sein, möglichst viele Dinge zur SMTP-Zeit zu
+entscheiden und dann die SMTP-Verbindung mit 5xx zu beenden. Damit bleibt die
+Verantwortung für die Bounce beim Absender.
+
+== Router
+
+Im Router-Abschnitt wird durch einzelne Blöcke das Routing-Verhalten gesteuert.
+Die Reihenfolge der Blöcke ist wichtig. Das Verhalten eines jeden Blocks wird
+durch den Treiber bestimmt.
+
+.Routing als Pseudoprogramm
+
+ if (check preconditions == FAIL) goto NEXT ROUTER
+
+ switch route($address) 
+    case ACCEPT:      schedule $address for transport
+    case NEW ADDRESS: goto FIRST ROUTER
+    case PASS:        goto NEXT ROUTER
+    case FAIL:        generate bounce
+    case DEFER:       back to queue
+    case DECLINE:     if (more?) goto NEXT ROUTER
+                      generate bounce
+
+.Beispiel
+ external:
+    driver = dnslookup
+    domains = !+local_domains
+    transport = remote_smtp
+    ignore_target_hosts = <; 127.0.0.1 : ::1
+
+Eine Liste der konfigurierten Router erhält man mit:
+
+ exim -bP router_list
+
+== Transports
+
+Die Transport-Blöcke werden von den Routern referenziert, ihre Reihenfolge ist
+egal. Auch hier wird das grundlegende Verhalten eins Blocks durch den Treiber
+bestimmt. 
+
+.Beispiel
+ remote_smtp
+   driver = smtp
+   command_timeout = 10s
+
+Die Liste der konfigurierten Transports:
+ 
+ exim -bP transport_list
+
+== Filter
+
+Es gibt das _System_-Filter und _User_-Filter. Das System-Filter wird *vor* dem 
+Routing der Nachricht aktiv. Das User-Filter dann, wenn ein Router für diesen
+Nutzer aktiv wird und das User-Filter auswertet.
+
+Wenn eine Nachricht nicht zugestellt werden kann, dann wird bei einem späteren
+Queue-Run der Filter-Prozess wiederholt! (Es gibt aber einen +first_delivery+
+Test, mit dem man das behandeln kann.)
+
+
+System-Filter verwenden immer
+http://www.exim.org/exim-html-current/doc/html/spec_html/filter_ch-exim_filter_files.html[Exim-Filter-Syntax].
+User-Filter können Exim-Filter-Syntax verwenden, oder eine Teilmenge der
+http://www.exim.org/exim-html-current/doc/html/spec_html/filter_ch-sieve_filter_files.html[Sieve-Filter-Syntax].
+
+Dem Filter steht die Nachricht schon zur Verfügung, es kann also auf Variablen
+aus den ACL und auf die Header der Nachricht zugreifen..
+
+=== Exim-Filter-Syntax
+
+* 1. Zeile
+
+ # Exim filter
+
+* Keyword/Value, separiert durch Whitespace oder an einigen Stellen durch
+  '('/')'
+* Zeilenumbrüche haben keine Sonderbedeutung
+* Kommentare von '<separator>#' bis zum Zeilenende
+* Data-Values
+** verbatim, wenn sie keine Separatoren enthalten
+** quoted mit '"'
+*** Leerzeichen und die Zeichen '\n', '\r', '\t',
+*** '\ddd' oder '\xdd'
+*** alle anderen Backspace-Squenzen werden daruch das
+   dem Backspace folgende Zeichen ersetzt
+** Strings-Expansion wie in der Exim-Konfiguration
+** max 1024 Zeichen *vor* der Expansion
+
+=== Filter-Kommandos
+
++add+::
+    Nutzer-Variable inkrementieren. Diese Variablen stehen dann später als
+    '+$sn1+' - '+$sn9+' in den Routern und Transports zur Verfügung
+
+ add 27 to to n3
+
++deliver+::
+    Mail weiterleiten, Vorsicht mit den Absendern (SPF). Signifikant.
+
+ deliver "Fred <fred@example.com>"
+
++fail+::
+    Mail abweisen
++finish+::
+    Keine weitere Bearbeitung
++freeze+::
+    Mail einfrieren
++headers+::
+    Header-Verarbeitung konfigurieren (Zeichensatz)
+
+ headers charset UTF-8
+
++if+::
+    Bedingte Verarbeitung mit +if+, +then+, +elif+, +else+, +endif+.
+    * String-Conditions sind +begins+, +contains+, +ends+, +matches+, bzw. +does not …+. 
+    * Numerische Bedingungen sind +is above+, +is below+ bzw. +is not …+
+    * Andere Bedingunge: +is_delivered+, +error_message+, +personal+,
+      +first_delivery+
+    * Listen: +forany+
+
++logfile+::
+    Logfile definieren
++logwrite+::
+    Schreiben ins Logfile
++mail+::
+    Antwort-Nachricht erzeugen
+
+ mail text "Danke für Ihre Nachricht mit $h_subject:"
+
++pipe+::
+    Nachricht per Pipeline weiterverarbeiten. Signifikant.
+
+ pipe "/usr/bin/mailstat"
+
++save+::
+    Nachricht in File/Mailbox sichern, das Format der Sicherung hängt vom
+    +filter_file_transport+ in der Konfiguration ab. Signifikant.
+
+ save bcc
+
++testprint+::
+    Testausgabe im Filter-Test-Modus
++vacation+::
+    Urlaubsnachricht erzeugen. Sonderform von +mail+.
+
+
+== Operating
+
+Exim legt alle wichtigen Daten in Text-Dateien ab. Trotzdem sind einige Optionen
+und Tools hilfreich im Umgang mit den operativen Daten des Exim.
+
+=== Prozesse
+
+Mit
+
+ exiwhat
+
+erhält man eine gute Übersicht über die aktuellen Aktivitäten des Exim.
+
+=== Queue
+
+Alle operativen Daten liegen unter dem Spool-Directory:
+
+ exim -bP spool_directory
+
+'input'::
+    Message-Spool. Wichtig! Je Message 2 Dateien.
+'db'::
+    Hint-Files, nicht wichtig. 
+'msglog'::
+    Nachrichten-Logs, solange die Nachricht noch nicht 'completed' ist.
+
+Mit dem klassischen 'mailq' lässt sich die aktuelle Queue anzeichen. Oder auch
+mit
+
+ exim -bp
+ exim -bpc
+
+Besser ist 'exipick', das verfügt über viele Möglichkeiten, Queue-Inhalte zu
+selektieren:
+
+ exipick
+ exipick -c
+ exipick -zi
+ exipick -f foo
+
+.Einzelne Nachrichten untersuchen
+ exim -Mvh <queue-id>
+ exim -Mvb <queue-id>
+ exim -Mvc <queue-id>
+
+.Löschen von Nachrichten
+ exim -Mrm <queue-id>
+
+
+=== Protokolle
+
+Protokolle liegen in
+ 
+ exim -bP log_file_path
+
+'mainlog'::
+    Logfile über alle Transaktionen, dokumentiertes und maschinenlesbares Format
+'rejectlog'::
+    Etwas mehr Details bei 5xx/4xx (Headerzeilen)
+'paniclog'::
+    ... wenn nichts mehr geht.
+
+Zum Suchen und Zusammenfassen dieser Informationen eignet sich 'exigrep' am besten.
+
+.Beispiel
+ exigrep 'hannes@example.com' /var/log/exim/mainlog
+ exigrep 'fred@foobar.de' $(ls -tr /var/log/exim/mainlog*)
+
+Solange die Nachricht noch in der Queue ist:
+
+ exim -Mvl <spool-id>
+
+=== Hint-Data
+
+Die Hint-Data-Files sind Berkeley-DB-Files. Die dafür vorhandenen Werkzeuge sind
+eher spartanisch. Im Zweifelsfall können diese Files auch gelöscht werden.
+
+'exim_dumpdb'::
+    Textdump der jeweiligen Datenbank, Ausgabeformat ist je nach DB-Format
+    leicht unterschiedlich
+
+.Beispiel
+ exim_dumpdb /var/spool/exim retry
+
+'exim_fixdb'::
+    Mit diesem Werkzeug können gezielt einzelne Datensätze einer Hint-DB
+    gelöscht werden
+
+.Beispiel
+ # exim_fixdb /var/spool/exim4 retry
+ Modifying Exim hints database /var/spool/exim4/db/retry
+ > T:mx1.bmw.c3s2.iphmx.com:2620:101:200a:d100::e
+ 13-Apr-2015 08:16:36
+ 0 error number: 101 Network is unreachable
+ 1 extra data:   77
+ 2 first failed: 12-Apr-2015 18:09:35
+ 3 last try:     13-Apr-2015 08:16:36
+ 4 next try:     13-Apr-2015 10:16:36
+ 5 expired:      no
+ > d
+ deleted
+
+'exim_tidydb'::
+    Wird regelmäßig über Cron aufgerufen um die Inhalte der Datenbankfiles
+    aufzuräumen. Die Files werden dabei nicht zwangsläufig kleiner!
+
+
+== Debugging
+
+=== Konfiguration 
+
+Die syntaktische Korrektheit der Konfiguration wird mit 
+
+ exim -bV
+
+geprüft.
+In Routern und Transports kann die +debug_print+ Option verwendet werden, um
+während der Test-Sessions noch angepasste Ausgaben zu erhalten.
+
+CAUTION: Viele Fehler treten erst später bei der Expansion auf!
+
+Teile der Konfiguration können mit:
+
+ exim -bP <option>
+ exim -bP 
+ exim -bP transports
+ exim -bP routers
+
+ausgelesen werden.
+
+=== Routing im Trockentest
+
+Das nützlichste Werkzeug ist sicher der Routing-Trockentest.
+Mit
+
+ exim -bt <address> 
+
+wird ein Address-Test gemacht. Das entspricht dem Routing-Vorgang. Im
+Unterschied zum echten Routing-Vorgang stehen diesem Test aber keine
+Header-Daten zur Verfügung. Die Absender-Adresse kann mit _-f <sender>_
+eingesetzt werden:
+
+ exim -f <sender> -bt <address>
+
+Mit 
+
+ exim -bv <address>
+
+findet eine Adress-Verification statt. Das ist normalerweise identisch zum
+Adresstest. Aber Router können so konfiguriert sein, dass sie nur zum
+Adress-Test oder nur zur Verification verwendet werden. Adress-Verification
+findet u.a. über das ACL-Statement  +verify = recipient+ statt.
+
+.Beispiel
+ exim -bt postmaster@schlittermann.de  <1>
+ exim -bts postmaster@schlittermann.de <2>
+
+<1> Recipient-Test
+<2> Sender-Test 
+
+=== Fake-Delivery für Filter/Router/Rewriting
+
+Bei Fake-Deliveries werden alle Schritte vom Routing über Filter und Rewriting
+ausgeführt, aber es findet keine Delivery statt. 
+
+.Beispiel
+ exim -N 1Yk9s3-00048G-4a
+ exim -N <message.eml
+
+=== Fake-SMTP-Session zum ACL-Test
+
+Exim kann SMTP-Sessions zum Test über STDIN/STDOUT abwickeln.
+
+ exim -bh <sender-ip>
+ exim -bhc <sender-ip> <1>
+
+<1> Callouts werden durchgeführt
+
+Dabei schaltet er automatisch in den Debug-Modus für ACL.
+
+.Beispiel
+ swaks -f hs@schlittermann.de -t fred@example.com \
+       --pipe 'exim -bh 1.2.3.4' 
+
+=== Filter-Tests
+
+Mit +exim -bf+ bzw. +exim -bF+ lassen sich die Filter-Scripte debuggen.
+
+.Beispiel
+
+ exim -f sender@example.com .de -bf ./filter <message
+ exim -bfd <domain> -bfl <local_part> … -bf
+
+=== Rewrite-Tests
+
+Wenn Rewrite-Regeln verwendet werden, dann können diese mit
+
+ exim -brw <address>
+
+getestet werden.
+
+=== String-Expansion
+
+Der String-Expander steht auf der Kommandozeile zur Verfügung:
+
+ exim -be <string>
+
+.Beispiel
+ exim -be '${lookup{root}lsearch{/etc/aliases}}'
+
+////
+
+    implizit "deny" am Ende jeder ACL!
+
+
+## Test
+
+   > exim -bh <ip>  # ohne callouts
+   > exim -bhc <ip> # mit callouts
+   > swaks --pipe 'exim -bh <ip> -C <config>' -f <sender> -t <rcpt>
+
+   exim -N hilft nicht, ist nicht für die SMTP acl
+   relevant!
+
+## Format
+
+   <aclverb>    [<condition>]
+                …
+                [<modifier]
+
+   Bedingungen müssen erfüllt sein, Order matters, Abbruch
+   bei nicht erfüllter Bedingung! Modifier sind immer "true"
+
+### Verb
+
+   accept, defer, deny, discard, drop, require, warn
+
+### Modifier
+
+    message = [code] text
+    log_message = text
+
+    Immediate:
+        logwrite      = …
+        control       = …
+        set           = …
+        add_header    = …
+        remove_header = …
+        delay         = …
+
+### Conditions
+
+    <condition> = <value>
+
+        eg: deny  hosts = !192.168.3.8  # neg. Liste
+            deny !hosts = 192.168.3.8   # neg. Resultat
+
+        vs: deny !verify = recipient    # works
+            deny  verify = !recipient   # FALSCH
+
+
+    Wert der Condition und von Modifiern wird expandiert.
+    Force Failure bedeutet: Condition war nicht anwesend!
+
+    Reihenfolge ist wichtig! Short Circuit.
+    Position der Modifier ist wichtig!
+
+
+
+# DNS Lookups
+
+## DNSSEC
+  dns_dnssec_ok = 1
+
+  dnslookup.dnssec_require_domains =        # leider noch falsche Syntax
+       smtp.dnssec_require_domains =        # leider noch falsche Syntax
+  dnslookup.dnssec_request_domains =        # leider noch falsche Syntax
+       smtp.dnssec_request_domains =        # leider noch falsche Syntax
+
+# Anhang
+
+## Misc
+
+    Spec.txt durchsuchen (less):
+    - Option         /^.<option>         eg: |exim_user|
+    - Variable       /^\$<variable       eg: $localhost_number
+    - Operators:     /^\$\{<operator>:   eg: ${hash:<string>} …
+    - Condition:     /^<condition> \{    eg: eq {<string1>}{<string2>} …
+    - Functions:     /^\$\{<function\{   eg: ${map{<string1>}{<string2>}} …
+    - ACL conditions /^<condition> =     eg: malware = …
+
+// Die folgenden Listen sind durch einfaches Greppen im Spec-File bzw. 
+// im spec.xfpt enstanden, also weder vollständig noch zwingend korrekt!
+
+## Liste globaler Optionen {{{
+
+    accept_8bitmime
+    acl_not_smtp
+    acl_not_smtp_mime
+    acl_not_smtp_start
+    acl_smtp_auth
+    acl_smtp_connect
+    acl_smtp_data
+    acl_smtp_data_prdr
+    acl_smtp_etrn
+    acl_smtp_expn
+    acl_smtp_helo
+    acl_smtp_mail
+    acl_smtp_mailauth
+    acl_smtp_mime
+    acl_smtp_predata
+    acl_smtp_quit
+    acl_smtp_rcpt
+    acl_smtp_starttls
+    acl_smtp_vrfy
+    admin_groups
+    allow_domain_literals
+    allow_mx_to_ip
+    allow_utf8_domains
+    auth_advertise_hosts
+    auto_thaw
+    av_scanner
+    bi_command
+    bounce_message_file
+    bounce_message_text
+    bounce_return_body
+    bounce_return_message
+    bounce_return_size_limit
+    bounce_sender_authentication
+    callout_domain_negative_expire
+    callout_domain_positive_expire
+    callout_negative_expire
+    callout_positive_expire
+    callout_random_local_part
+    check_log_inodes
+    check_log_space
+    check_rfc2047_length
+    check_spool_inodes
+    check_spool_space
+    daemon_smtp_ports
+    daemon_startup_retries
+    daemon_startup_sleep
+    delay_warning
+    delay_warning_condition
+    deliver_drop_privilege
+    deliver_queue_load_max
+    delivery_date_remove
+    disable_fsync
+    disable_ipv6
+    dns_again_means_nonexist
+    dns_check_names_pattern
+    dns_csa_search_limit
+    dns_csa_use_reverse
+    dns_dnssec_ok
+    dns_ipv4_lookup
+    dns_retrans
+    dns_retry
+    dns_use_edns0
+    drop_cr
+    dsn_from
+    envelope_to_remove
+    errors_copy
+    errors_reply_to
+    exim_group
+    exim_path
+    exim_user
+    extra_local_interfaces
+    finduser_retries
+    freeze_tell
+    gecos_name
+    gecos_pattern
+    gnutls_compat_mode
+    header_line_maxsize
+    header_maxsize
+    headers_charset
+    helo_accept_junk_hosts
+    helo_allow_chars
+    helo_lookup_domains
+    helo_try_verify_hosts
+    helo_verify_hosts
+    hold_domains
+    host_lookup
+    host_lookup_order
+    host_reject_connection
+    hosts_connection_nolog
+    hosts_treat_as_local
+    ibase_servers
+    ignore_bounce_errors_after
+    ignore_fromline_hosts
+    ignore_fromline_local
+    keep_malformed
+    ldap_ca_cert_dir
+    ldap_ca_cert_file
+    ldap_cert_file
+    ldap_cert_key
+    ldap_cipher_suite
+    ldap_default_servers
+    ldap_require_cert
+    ldap_start_tls
+    ldap_version
+    local_from_check
+    local_from_prefix
+    local_from_suffix
+    local_interfaces
+    local_scan_timeout
+    local_sender_retain
+    localhost_number
+    log_file_path
+    log_selector
+    log_timezone
+    lookup_open_max
+    max_username_length
+    message_body_newlines
+    message_body_visible
+    message_id_header_domain
+    message_id_header_text
+    message_logs
+    message_size_limit
+    move_frozen_messages
+    mua_wrapper
+    mysql_servers
+    never_users
+    openssl_options
+    oracle_servers
+    percent_hack_domains
+    perl_at_start
+    perl_startup
+    pgsql_servers
+    pid_file_path
+    pipelining_advertise_hosts
+    prdr_enable
+    preserve_message_logs
+    primary_hostname
+    print_topbitchars
+    process_log_path
+    prod_requires_admin
+    qualify_domain
+    qualify_recipient
+    queue_domains
+    queue_list_requires_admin
+    queue_only
+    queue_only_file
+    queue_only_load
+    queue_only_load_latch
+    queue_only_override
+    queue_run_in_order
+    queue_run_max
+    queue_smtp_domains
+    receive_timeout
+    received_header_text
+    received_headers_max
+    recipient_unqualified_hosts
+    recipients_max
+    recipients_max_reject
+    remote_max_parallel
+    remote_sort_domains
+    retry_data_expire
+    retry_interval_max
+    return_path_remove
+    return_size_limit
+    rfc1413_hosts
+    rfc1413_query_timeout
+    sender_unqualified_hosts
+    smtp_accept_keepalive
+    smtp_accept_max
+    smtp_accept_max_nonmail
+    smtp_accept_max_nonmail_hosts
+    smtp_accept_max_per_connection
+    smtp_accept_max_per_host
+    smtp_accept_queue
+    smtp_accept_queue_per_connection
+    smtp_accept_reserve
+    smtp_active_hostname
+    smtp_banner
+    smtp_check_spool_space
+    smtp_connect_backlog
+    smtp_enforce_sync
+    smtp_etrn_command
+    smtp_etrn_serialize
+    smtp_load_reserve
+    smtp_max_synprot_errors
+    smtp_max_unknown_commands
+    smtp_ratelimit_hosts
+    smtp_ratelimit_mail
+    smtp_ratelimit_rcpt
+    smtp_receive_timeout
+    smtp_reserve_hosts
+    smtp_return_error_details
+    spamd_address
+    split_spool_directory
+    spool_directory
+    sqlite_lock_timeout
+    strict_acl_vars
+    strip_excess_angle_brackets
+    strip_trailing_dot
+    syslog_duplication
+    syslog_facility
+    syslog_processname
+    syslog_timestamp
+    system_filter
+    system_filter_directory_transport
+    system_filter_file_transport
+    system_filter_group
+    system_filter_pipe_transport
+    system_filter_reply_transport
+    system_filter_user
+    tcp_nodelay
+    timeout_frozen_after
+    timezone
+    tls_advertise_hosts
+    tls_certificate
+    tls_crl
+    tls_dh_max_bits
+    tls_dhparam
+    tls_ocsp_file
+    tls_on_connect_ports
+    tls_privatekey
+    tls_remember_esmtp
+    tls_require_ciphers
+    tls_try_verify_hosts
+    tls_verify_certificates
+    tls_verify_hosts
+    trusted_groups
+    trusted_users
+    unknown_login
+    unknown_username
+    untrusted_set_sender
+    uucp_from_pattern
+    uucp_from_sender
+    warn_message_file
+    write_rejectlog
+
+
+    }}}
+
+## Liste von Expansionsvariablen {{{
+
+    $acl_narg
+    $acl_verify_message
+    $address_data
+    $address_file
+    $address_pipe
+    $authenticated_fail_id
+    $authenticated_id
+    $authenticated_sender
+    $authentication_failed
+    $av_failed
+    $body_linecount
+    $body_zerocount
+    $bounce_recipient
+    $bounce_return_size_limit
+    $caller_gid
+    $caller_uid
+    $compile_date
+    $compile_number
+    $demime_errorlevel
+    $demime_errorlevel
+    $demime_reason
+    $demime_reason
+    $dnslist_domain
+    $domain
+    $domain_data
+    $exim_gid
+    $exim_path
+    $exim_uid
+    $found_extension
+    $found_extension
+    $header_
+    $headers_added
+    $home
+    $host
+    $host_address
+    $host_data
+    $host_lookup_deferred
+    $host_lookup_failed
+    $host_port
+    $inode
+    $interface_address
+    $interface_port
+    $item
+    $ldap_dn
+    $load_average
+    $local_part
+    $local_part_data
+    $local_part_prefix
+    $local_part_suffix
+    $local_scan_data
+    $local_user_gid
+    $local_user_uid
+    $localhost_number
+    $log_inodes
+    $log_space
+    $lookup_dnssec_authenticated
+    $mailstore_basename
+    $malware_name
+    $max_received_linelength
+    $message_age
+    $message_body
+    $message_body_end
+    $message_body_size
+    $message_exim_id
+    $message_headers
+    $message_headers_raw
+    $message_id
+    $message_linecount
+    $message_size
+    $mime_
+    $mime_boundary
+    $mime_charset
+    $mime_content_description
+    $mime_content_disposition
+    $mime_content_id
+    $mime_content_size
+    $mime_content_transfer_encoding
+    $mime_content_type
+    $mime_decoded_filename
+    $mime_filename
+    $mime_is_coverletter
+    $mime_is_multipart
+    $mime_is_rfc822
+    $mime_part_count
+    $original_domain
+    $original_local_part
+    $originator_gid
+    $originator_uid
+    $parent_domain
+    $parent_local_part
+    $pid
+    $pipe_addresses
+    $primary_hostname
+    $prvscheck_address
+    $prvscheck_keynum
+    $prvscheck_result
+    $qualify_domain
+    $qualify_recipient
+    $rcpt_count
+    $rcpt_defer_count
+    $rcpt_fail_count
+    $received_count
+    $received_for
+    $received_ip_address
+    $received_port
+    $received_protocol
+    $received_time
+    $recipient_data
+    $recipient_verify_failure
+    $recipients
+    $recipients_count
+    $regex_match_string
+    $reply_address
+    $return_path
+    $return_size_limit
+    $router_name
+    $runrc
+    $self_hostname
+    $sender_address
+    $sender_address_data
+    $sender_address_domain
+    $sender_address_local_part
+    $sender_data
+    $sender_fullhost
+    $sender_helo_name
+    $sender_host_address
+    $sender_host_authenticated
+    $sender_host_dnssec
+    $sender_host_name
+    $sender_host_port
+    $sender_ident
+    $sender_rate_
+    $sender_rcvhost
+    $sender_verify_failure
+    $sending_ip_address
+    $sending_port
+    $smtp_active_hostname
+    $smtp_command
+    $smtp_command_argument
+    $smtp_count_at_connection_start
+    $spam_
+    $spam_bar
+    $spam_report
+    $spam_score
+    $spam_score_int
+    $spool_directory
+    $spool_inodes
+    $spool_space
+    $thisaddress
+    $tls_in_bits
+    $tls_in_certificate_verified
+    $tls_in_cipher
+    $tls_in_ocsp
+    $tls_in_ourcert
+    $tls_in_peercert
+    $tls_in_peerdn
+    $tls_in_sni
+    $tls_out_bits
+    $tls_out_certificate_verified
+    $tls_out_cipher
+    $tls_out_ocsp
+    $tls_out_ourcert
+    $tls_out_peercert
+    $tls_out_peerdn
+    $tls_out_sni
+    $tod_bsdinbox
+    $tod_epoch
+    $tod_epoch_l
+    $tod_full
+    $tod_log
+    $tod_logfile
+    $tod_zone
+    $tod_zulu
+    $transport_name
+    $value
+    $verify_mode
+    $version_number
+    $warn_message_delay
+    $warn_message_recipients
+
+    }}}
+
+## Liste von Operatoren {{{
+
+    ${address:
+    ${addresses:
+    ${base62:
+    ${base62d:
+    ${domain:
+    ${escape:
+    ${eval:
+    ${expand:
+    ${from_utf8:
+    ${hex2b64:
+    ${hexquote:
+    ${lc:
+    ${listcount:
+    ${listnamed:
+    ${local_part:
+    ${mask:
+    ${md5:
+    ${quote:
+    ${quote_local_part:
+    ${randint:
+    ${reverse_ip:
+    ${rfc2047:
+    ${rfc2047d:
+    ${rxquote:
+    ${sha1:
+    ${sha256:
+    ${stat:
+    ${str2b64:
+    ${strlen:
+    ${time_eval:
+    ${time_interval:
+    ${uc:
+    ${utf8clean:
+
+    }}}
+
+## List of Conditions {{{
+
+    acl
+    and
+    bool
+    bool_lax
+    crypteq
+    eq
+    exists
+    ge
+    gt
+    inlist
+    isip
+    ldapauth
+    le
+    lt
+    match
+    match_address
+    match_domain
+    match_ip
+    match_local_part
+    or
+    pam
+    pwcheck
+    radius
+
+    }}}
+
+## List of Functions {{{
+
+    ${acl
+    ${certextract
+    ${dlfunc
+    ${extract
+    ${extract
+    ${filter
+    ${hash
+    ${hmac
+    ${length
+    ${listextract
+    ${lookup
+    ${map
+    ${nhash
+    ${perl
+    ${prvs
+    ${prvscheck
+    ${readfile
+    ${readsocket
+    ${reduce
+    ${run
+    ${sg
+    ${sort
+    ${substr
+    ${tr
+
+        }}}
+
+## Routing Pre-Conditions {{{
+
+    address_test
+    check_local_user
+    condition
+    domains
+    expn
+    local_part_prefix
+    local_part_suffix
+    local_parts
+    require_files
+    senders
+    verify
+    verify_only
+    verify_recipient
+    verify_sender
+
+    }}}
+
+
+Cheat sheet: http://www.datadisk.co.uk/html_docs/exim/exim_cs.htm
+
+# vim:tw=80:et:ts=4:sw=4:et:fdm=marker:ft=asciidoc:
+////