--- 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:
+////