snapshot
authorHeiko Schlittermann (JUMPER) <hs@schlittermann.de>
Mon, 20 Apr 2015 16:00:34 +0200
changeset 10 905843405257
parent 9 57a706b1a320
child 11 6fa8b31d1c12
snapshot
.hgignore
Makefile
abstract.conf
abstract.txt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.hgignore	Mon Apr 20 16:00:34 2015 +0200
@@ -0,0 +1,2 @@
+syntax:glob
+out/
--- a/Makefile	Fri Apr 17 15:43:36 2015 +0200
+++ b/Makefile	Mon Apr 20 16:00:34 2015 +0200
@@ -1,7 +1,8 @@
 TXT = abstract.txt
 HTML = out/abstract.html
 
-REVISION = ${shell hg id -tibB}
+#REVISION = ${shell hg id -tibB}
+REVISION = ${shell hg log -r . --template '{latesttag}-{latesttagdistance}-{node|short}'}
 DATE = ${shell date -I}
 
 
--- a/abstract.conf	Fri Apr 17 15:43:36 2015 +0200
+++ b/abstract.conf	Mon Apr 20 16:00:34 2015 +0200
@@ -2,3 +2,10 @@
 subs=verbatim,quotes
 
 
+[quotes]
+$|=vars
+
+[paradef-literal]
+
+[tags]
+vars=<code><em>$|</em></code>
--- a/abstract.txt	Fri Apr 17 15:43:36 2015 +0200
+++ b/abstract.txt	Mon Apr 20 16:00:34 2015 +0200
@@ -1,264 +1,313 @@
 Kurzer Konfigurationsritt
 =========================
 :Author: Heiko Schlittermann
-:Toc:
+:toc:
 :data-uri:
 :icons:
 :numbered:
 
-
-== Konfig im Detail ==
+_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
 
-Welche Konfiguration wird eingelesen? Je nach Installation kann das
-ein anderes File sind.
+== Konfiguration
+
+=== File
 
-.aktive Konfiguration ermitteln:
-----
-> exim -bV | tail -n 1
-> exim -bP configure_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
 
-.aktive Konfiguration ändern
-----
-> exim -C `pwd`/test.config …
-----
+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.
 
-Die Konfiguration öfter gelesen, als vielleicht erwartet:
+ exim -C <Pfadname> …
 
-* Klar - beim Start
+Die Konfiguration wird öfter gelesen als vielleicht erwartet:
+
+* Beim Start
 * Aber - wann wird gestartet?
     ** Start des Daemon
-    ** Signal HUP
+    ** Signal _HUP_ 
     ** re-exec for verschiedene Zwecke
-* Achtung: 
-    ** exim4.conf + .include ist "statisch"
-    ** lists, lookups, … "dynamisch"
 
-Der Config-Parser ist ziemlich einfach.
+CAUTION: Inhalt der Datei _exim.conf_ footnote:[Debian verwendet hier _exim4.conf_] 
+und eventuell über +.include+ eingelesener Files
+ist statisch. Dynamisch sind dann Expansionen, Lookups.
+
+=== Syntax
 
-* einfache Syntax-Checks
-* Erst „de-comment“, dann „trimm“, dann Fortsetzungszeilen mit `\`
-  am Ende
-
-== Syntax der Konfiguration ==
+Der Parser der Konfigurationsdatei ist ziemlich einfach.
 
-Es gibt Macros.
+. Kommentarzeilen werden entfernt
+. Führende und anhängige Leerzeichen werden entfernt
+. Forsetzungszeilen („\“ am Zeilenende) werden zusammengefasst
+. einfache Syntax-Checks
 
-* Macros - Text-Ersatz während des Einlesens,
-  ggf. bedingt über `.ifdef`
-* `.include`, `.include_ifexists`
+Die Konfiguration besteht aus mehreren Abschnitten. Nicht alle Abschnitte
+sind identisch aufgebaut.
 
-.Macro-Ersetzungen
-----
-FOO = foo               <1>
-FOO == bar              <2>
-primary_hostname = FOO
-----
-<1> Definition
-<2> Re-Definition
+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)
 
-Es gibt weitere Elemente:
+== 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.
 
-* Optionsnamen
-* benamste Listen
-* Instanzen von Routern, Transports, …
-
-== Werte ==
+=== 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.
 
-Optionen und Listen haben Werte. Es gibt _bool_, _integer_, _fixed-point_, _time_ und _string_.
+ 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
 
-=== Bool ===
+Und beim Aufruf:
 
-_bool_ sind einfache Schalter.
+ exim -DTESTING …
+ exim -DFOO=bar …
 
-.Format 
-----
-true
-false
-<option>
-no_<option>
-not_<option>
-----
+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. 
 
-----
-split_spool_directory
-not_split_spool_directory
-split_spool_directory = true
-split_spool_directory = no
-----
+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
 
-.spect.txt
- +---------------------+---------+-------------+--------------+ 
- |split_spool_directory|Use: main|Type: boolean|Default: false|
- +---------------------+---------+-------------+--------------+
+ 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 
 
-=== Integer ===
+ 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:
 
-Zahlen halt. Ganze Zahlen.
+ 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.
 
-.Format
-----
-  <n>[<suffix>]
- 0<n>[<suffix>]
-0x<n>[<suffix>]
-       suffix: k|m
-----
+ begin transports
+ …
+ remote_smtp:
+    driver = smtp
+    command_timeout = 20s
+
+=== ACL und Rewrite-Regeln
 
-----
-check_spool_space = 10M
-----
+Diese beiden Teile der Konfiguration haben ihre eigene Syntax.
+
+== Werte
 
-.spec.txt
- +-----------------+---------+-------------+----------+
- |check_spool_space|Use: main|Type: integer|Default: 0|
- +-----------------+---------+-------------+----------+
+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_
 
 
-### fixed-point
-    Format: <i>[.d[d[d]]]     eg: 0.234
+=== Bool
+
+Werte vom Typ _bool_ sind einfache Schalter.
+
+.Format 
+ <option> = true
+ <option> = false
+ <option>
+ no_<option>
+ not_<option>
 
-    +----------------------+---------+-----------------+--------------+
-    |deliver_queue_load_max|Use: main|Type: fixed-point|Default: unset|
-    +----------------------+---------+-----------------+--------------+
-    > exim -C <(echo deliver_queue_load_max = 3.3) -bP deliver_queue_load_max
+.Beispiel
+ split_spool_directory
+ not_split_spool_directory
+ split_spool_directory = true
+ split_spool_directory = no
+
+=== Integer
+
+Zahlen. Ganze Zahlen.
 
-### time intervals
-    Format: n<suffix>...      eg: 2w3d
-            suffix: s|m|h|d|w
+.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
 
-    +---------+---------+----------+-----------+
-    |auto_thaw|Use: main|Type: time|Default: 0s|
-    +---------+---------+----------+-----------+
-    > exim -C <(echo auto_thaw = 1w7s) -bP auto_thaw
+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>]…
 
-### strings
-    Fromat: <string>           eg: localhost
-            <"string">         eg: " A\x42C"
+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.
 
-    Quoting für \\, \n, \r, \t, \ddd, \xdd und führende oder baumelnde Spaces
+=== Zeichenketten
 
-    - Vorsicht: Expansion
-    - Vorsicht: User/Groups
+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">
 
-    +----------------+---------+------------+------------------+
-    |primary_hostname|Use: main|Type: string|Default: see below|
-    +----------------+---------+------------+------------------+
-    > exim -C <(echo 'primary_hostname = a\x41b')   -bP primary_hostname
-    > exim -C <(echo 'primary_hostname = "a\x41b"') -bP primary_hostname
+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
 
-    Steuerzeichen werden für die Ausgabe escaped:
-    > exim -C <(echo 'primary_hostname = "a\x091b"') -bP primary_hostname
+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>
 
-### Lists
-    Format: <item>:…            eg:   a:b:c:d vs. a:b::c:d
-                                eg:   :   -> ein leeres Element
-        [<<sep> <item><sep>…]   eg:   <, a,b,c
+<1> leere Liste
+<2> Liste mit einem leeren Element
+
+////
+> 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>
 
-      - leere Felder am Ende werden „gestrippt“
-      - Whitespace der Felder wird gestrippt
-      - leeres Feld in der Mitte: a: :b
-      - leeres Felder am Anfang bleibt
-      - "Escapen" des Listentrenners durch Verdoppeln
+.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
 
-      a : b::c : d -> (a) (b:c) (d)
+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“). 
 
-    > 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}'
+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).
 
 
-### Regexp
-    Format ^…
-
-    Beginnt mit ^, damit es sich von einem normalen String unterscheidet!
-    Achtung, Backslash ggf. vom String-Expander gefressen,
-    hauptsächlich in Listen, die RE enthalten dürfen
-
-    Ggf. mit \N..\N 
-
-## Lookups
-
-    - 2 Syntaxen
-    - 2 Types
-    => 4 Varianten
-
-### Syntax 1: explizit - der Key oder die Frage wird ausdrücklich formuliert
-              es ist ein String-Expansion. s.u.
-
-    ${lookup{<key>}<type>{file}}    eg: ${lookup{$domain}dsearch{/etc/exim4/domains}}
-    ${lookup <type> {<query>}}      eg: ${lookup ldap {ldap:///o=roka?mail?sub?uid=${quote_ldap:$local_part}}}
-
-    Liefert eine Liste zurück, ggf. Listentrenner unorthodox und muss massiert werden
-
-### Syntax 2: implizit - der Key ergibt sich aus dem Kontext
-              keine Stringexpansion, sondern ein Element für sich
-
-
-    <type>;<file>                   eg: domains = dsearch;/etc/exim4/domains
-    <type>;<query>                  eg: domains = sqlite;/etc/db.sqlite SELECT … WHERE ${quote_sqlite:$local_part} …
-                                        domains = ldap;ldap:///o=roka?mail?sub?…
-
-    - Auffindes des "impliziten" Keys
-    - Query: Success der Query ist entscheidend, nicht der Resultat-Wert
-    - Achtung: In einer Liste ggf. an den Listentrenner denken!
-               domains = ldap;ldap::///o=…
-
-### Style 1: Single Key
-
-    ${lookup{<key>}<type>{<file>}   eg: ${lookup{$sender_host_address}iplsearch{/etc/exim4/blacklist}}
-    <type>;<file>                   eg: hosts = iplsearch;/etc/exim4/blacklist
-
-    <type> ist dann lsearch, dsearch, iplsearch, …
-    
-### Style 2: Query Style
-
-    ${lookup <type> {<query>}}      eg: ${lookup dnsdb{mxh=roka.net}}
-    <type>;<query>                  eg: dnsdb;mxh=roka.net
-
-
-    Matrix
-
-        style|  single key                    | query style
-    syntax  \|                                |
-    ---------+--------------------------------+---------------------------
-    explicit |  ${lookup{<key>}<type>{<file>} | ${lookup <type> {<query>}}
-    implizit |  <type>;<file>                 | [ <type>;<query> ]
-
-
-    eg. config:
-
-    domains = ${lookup{$domain}lsearch{/etc/exim4/local_domains}}   # WRONG
-            = <\n ${lookup mysql { SELECT domain FROM domains }}    # BETTER
-            = ${lookup mysql { SELECT DISTINCT(domain) FROM domains WHERE domain = $domain}} # ggf BEST
-    vs
-    domains = lsearch;/etc/exim4/local_domains                      # OK
-
-
-## Named Lists
-   Format: <listtype> <name>
-           <listtype>_cache <name>
-           Bezug: +<name>
-
-    Typen: domainlist, hostlist, addresslist, localpartlist
-    Caching nur wenn die RHS keine '$' enthält, also konstante Ergebnisse zu erwarten sind.
-
-    Jeder Listtyp hat seine Eigenarten.
-
-    > exim -bP +<name>
-
-### domainlist
-
-    domainlist - @, @mx_primary, @mx_secondary, @mx_any, <pattern>, lookup, literal
-    hostlist   - Namen, Adressen spec(10.11 ff)
-
-
-## String-Expansion
-
-    - von links nach rechts: $ und \ wirken als Trigger
-
+////
     > exim -be [<string>]
     > exim -bem <message-file> [<string>]
     > exim -be -Mset <spool-id> [<string>]
@@ -269,80 +318,521 @@
 
     Expansionen liefern neuen Text zurück oder können „forced expansion failure“
     bewirken
+////
 
-## Expansions-Items
+=== 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]
 
-### Variablen
-    Format: $<variable>           eg: $localhost_number
-            ${<variable>}     
+ ${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
+
 
-### Operatoren
-    Format: ${<op>:<string>}
-    Für einfache Expansionen, lc, uc, hash, …
+=== 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!
 
-### Funktionen
-    Format ${<function>{string1}...}
+.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
 
-# Debugging
+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]
 
-## Konfiguration
-   
-   - > exim -bV
+.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
 
-## Routing / Transport
+.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}}}
 
-    > exim -bt  <address>
-    > exim -bts <address>
+
+=== Ü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>
+|=======================================================================
 
-    > exim -bv  <address>
-    > exim -bvs <address>
+== 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.
 
-    Routing, Fake-Delivery
-    > exim -N < <message-file>
+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
 
-    Fake-SMTP-Session
-    > exim -bh <sender-ip>
-    > swaks --pipe 'exim -bh <sender-ip>' -f <sender> -t <rcpt>
-    (note: --tls-cert, --tls-key Optionen sind für SWAKS vorhanden, um ein 
-    Client-Zertifikat mitzuschicken, aber offenbar erst in neueren Versionen
-    von swaks)
-    
-   - debug_print Option für Router und Transports
+.Häufige ACL-Bedingungen
++hosts+::
+    Sender-Host-IP wird geprüft
++domains+::
+    Empfänger-Domain wird geprüft
++senders+::
+    Absender-Mailadresse wird geprüft
++malware+::
+    Malware-Content-Scan liefert einen Treffer
++spam+::
+    SPAM-Content-Scan (_SpamAssassin_)
++verify+::
+    Empfänger- oder Absenderüberprüfung, eventuell auch mit _callout_.
++ratelimit+::
+    Limitierungen aller Art (Menge, Größe, …)
+
+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
+
+== Transports
+
+== 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.)
 
 
-### Minimalkonfiguration
+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
 
-       .-[ m.conf ]-------- {{{
-       |exim_user = exim
-       |spool_directory = /tmp/exim-spool
-       |log_file_path = 
-       |
-       |begin routers
-       |
-       |    default:
-       |        driver = accept
-       |        transport = null
-       |        no_more
-       |
-       |begin transports
-       |
-       |    null:
-       |        driver = appendfile
-       |        file = /dev/null
-       `-------------        }}}
+ 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>
 
 
-# Routing
+=== 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
 
-  - Preconditions
-  - Driver und Driver-Options
-    Result: - accept  -> DONE (transport oder neue Adresse)
-            - pass    -> pass_router (bzw. nächster Router)
-            - decline -> nächster Router (or fail, wenn no_more)
-            - fail    -> DONE (bounce)
-            - defer   -> Semi-DONE (re-queue)
-            - error   -> wie defer
+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>
+
+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}}'
+
+////
 # Hint-Databases
   
   liegen in $spool_directory/db
@@ -1049,4 +1539,5 @@
 
 Cheat sheet: http://www.datadisk.co.uk/html_docs/exim/exim_cs.htm
 
-# vim:tw=0:et:ts=4:sw=4:fdm=marker:ft=asciidoc:
+# vim:tw=80:et:ts=4:sw=4:et:fdm=marker:ft=asciidoc:
+////