Merge branch '4.next'
authorJeremy Harris <jgh146exb@wizmail.org>
Mon, 1 Jun 2020 16:07:44 +0000 (17:07 +0100)
committerJeremy Harris <jgh146exb@wizmail.org>
Mon, 1 Jun 2020 16:15:31 +0000 (17:15 +0100)
32 files changed:
doc/doc-docbook/spec.xfpt
doc/doc-txt/ChangeLog
doc/doc-txt/NewStuff
doc/doc-txt/OptionLists.txt
src/README.UPDATING
src/src/EDITME
src/src/configure.default
src/src/exim.c
src/src/expand.c
src/src/globals.c
src/src/globals.h
src/src/lookups/README
src/src/readconf.c
src/src/smtp_in.c
src/src/spf.c
src/src/tls-openssl.c
test/confs/2610
test/confs/3901
test/log/0453
test/log/0566
test/log/0901
test/log/4600
test/rejectlog/0453
test/rejectlog/0566
test/rejectlog/0901
test/runtest
test/scripts/0000-Basic/0002
test/scripts/2610-MySQL/2610
test/stderr/0453
test/stderr/2610
test/stdout/0002
test/stdout/2610

index 68f3b5b5a87f54af20f1aeef71e795e679846fd7..28c8b14626e0a59ee0297c98a58b17160788ffe5 100644 (file)
@@ -45,7 +45,7 @@
 . Update the Copyright year (only) when changing content.
 . /////////////////////////////////////////////////////////////////////////////
 
-.set previousversion "4.93"
+.set previousversion "4.94"
 .include ./local_params
 
 .set ACL "access control lists (ACLs)"
@@ -1409,11 +1409,9 @@ the set of local parts that it defines. If &%local_part_prefix%& or
 &%local_part_suffix%& is in use, the prefix or suffix is removed from the local
 part before this check. If you want to do precondition tests on local parts
 that include affixes, you can do so by using a &%condition%& option (see below)
-.new
 that uses the variables &$local_part$&, &$local_part_prefix$&,
 &$local_part_prefix_v$&, &$local_part_suffix$&
 and &$local_part_suffix_v$& as necessary.
-.wen
 .next
 .vindex "&$local_user_uid$&"
 .vindex "&$local_user_gid$&"
@@ -3871,13 +3869,11 @@ This option is not intended for use by external callers. It is used internally
 by Exim in conjunction with the &%-MC%& option. It signifies that the
 remote host supports the ESMTP &_DSN_& extension.
 
-.new
 .vitem &%-MCd%&
 .oindex "&%-MCd%&"
 This option is not intended for use by external callers. It is used internally
 by Exim in conjunction with the &%-d%& option
 to pass on an information string on the purpose of the process.
-.wen
 
 .vitem &%-MCG%&&~<&'queue&~name'&>
 .oindex "&%-MCG%&"
@@ -4404,7 +4400,6 @@ written. When &%-oX%& is used with &%-bd%&, or when &%-q%& with a time is used
 without &%-bd%&, this is the only way of causing Exim to write a pid file,
 because in those cases, the normal pid file is not used.
 
-.new
 .vitem &%-oPX%&
 .oindex "&%-oPX%&"
 .cindex "pid (process id)" "of daemon"
@@ -4413,7 +4408,6 @@ This option is not intended for general use.
 The daemon uses it when terminating due to a SIGTEM, possibly in
 combination with &%-oP%&&~<&'path'&>.
 It causes the pid file to be removed.
-.wen
 
 .vitem &%-or%&&~<&'time'&>
 .oindex "&%-or%&"
@@ -4531,13 +4525,11 @@ stage, the queue is scanned as if the &%queue_smtp_domains%& option matched
 every domain. Addresses are routed, local deliveries happen, but no remote
 transports are run.
 
-.new
 Performance will be best if the &%queue_run_in_order%& option is false.
 If that is so and the &%queue_fast_ramp%& option is true then
 in the first phase of the run,
 once a threshold number of messages are routed for a given host,
 a delivery process is forked in parallel with the rest of the scan.
-.wen
 
 .cindex "hints database" "remembering routing"
 The hints database that remembers which messages are waiting for specific hosts
@@ -5917,13 +5909,13 @@ messages that are submitted by SMTP from local processes using the standard
 input and output (that is, not using TCP/IP). A number of MUAs operate in this
 manner.
 .code
-deny    message       = Restricted characters in address
-        domains       = +local_domains
+deny    domains       = +local_domains
         local_parts   = ^[.] : ^.*[@%!/|]
+        message       = Restricted characters in address
 
-deny    message       = Restricted characters in address
-        domains       = !+local_domains
+deny    domains       = !+local_domains
         local_parts   = ^[./|] : ^.*[@%!] : ^.*/\\.\\./
+        message       = Restricted characters in address
 .endd
 These statements are concerned with local parts that contain any of the
 characters &"@"&, &"%"&, &"!"&, &"/"&, &"|"&, or dots in unusual places.
@@ -6027,10 +6019,10 @@ require verify = recipient
 This statement requires the recipient address to be verified; if verification
 fails, the address is rejected.
 .code
-# deny    message     = rejected because $sender_host_address \
+# deny    dnslists    = black.list.example
+#         message     = rejected because $sender_host_address \
 #                       is in a black list at $dnslist_domain\n\
 #                       $dnslist_text
-#         dnslists    = black.list.example
 #
 # warn    dnslists    = black.list.example
 #         add_header  = X-Warning: $sender_host_address is in \
@@ -6403,13 +6395,11 @@ local_delivery:
 This &(appendfile)& transport is used for local delivery to user mailboxes in
 traditional BSD mailbox format.
 
-.new
 We prefer to avoid using &$local_part$& directly to define the mailbox filename,
 as it is provided by a potential bad actor.
 Instead we use &$local_part_data$&,
 the result of looking up &$local_part$& in the user database
 (done by using &%check_local_user%& in the the router).
-.wen
 
 By default &(appendfile)& runs under the uid and gid of the
 local user, which requires the sticky bit to be set on the &_/var/mail_&
@@ -6701,17 +6691,16 @@ Two different types of data lookup are implemented:
 The &'single-key'& type requires the specification of a file in which to look,
 and a single key to search for. The key must be a non-empty string for the
 lookup to succeed. The lookup type determines how the file is searched.
-.new
 .cindex "tainted data" "single-key lookups"
 The file string may not be tainted
 
+.cindex "tainted data" "de-tainting"
 All single-key lookups support the option &"ret=key"&.
 If this is given and the lookup
 (either underlying implementation or cached value)
 returns data, the result is replaced with a non-tainted
 version of the lookup key.
 .cindex "tainted data" "de-tainting"
-.wen
 .next
 .cindex "query-style lookup" "definition of"
 The &'query-style'& type accepts a generalized database query. No particular
@@ -6804,15 +6793,12 @@ by default, but has an option to omit them (see section &<<SECTdbmbuild>>&).
 .cindex "lookup" "dsearch"
 .cindex "dsearch lookup type"
 &(dsearch)&: The given file must be an
-.new
 absolute
-.wen
 directory path; this is searched for an entry
 whose name is the key by calling the &[lstat()]& function.
 The key may not
 contain any forward slash characters.
 If &[lstat()]& succeeds then so does the lookup.
-.new
 .cindex "tainted data" "dsearch result"
 The result is regarded as untainted.
 
@@ -6836,7 +6822,6 @@ ${lookup {passwd} dsearch,filter=file {/etc}}
 .endd
 The default matching is for any entry type, including directories
 and symlinks.
-.wen
 
 An example of how this
 lookup can be used to support virtual domains is given in section
@@ -7110,7 +7095,6 @@ passed to a Redis database. See section &<<SECTsql>>&.
 &(sqlite)&: The format of the query is
 new
 an optional filename
-.wen
 followed by an SQL statement
 that is passed to an SQLite database. See section &<<SECTsqlite>>&.
 
@@ -8073,14 +8057,12 @@ The &%quote_redis%& expansion operator
 escapes whitespace and backslash characters with a backslash.
 
 .section "Specifying the server in the query" "SECTspeserque"
-.new
 For MySQL, PostgreSQL and Redis lookups (but not currently for Oracle and InterBase),
 it is possible to specify a list of servers with an individual query. This is
 done by appending a comma-separated option to the query type:
 .display
 .endd
 &`,servers=`&&'server1:server2:server3:...'&
-.wen
 Each item in the list may take one of two forms:
 .olist
 If it contains no slashes it is assumed to be just a host name. The appropriate
@@ -8114,7 +8096,6 @@ option, you can still update it by a query of this form:
 ${lookup pgsql,servers=master/db/name/pw {UPDATE ...} }
 .endd
 
-.new
 An older syntax places the servers speciification before the qury,
 semicolon separated:
 .code
@@ -8123,7 +8104,6 @@ ${lookup mysql{servers=master; UPDATE ...} }
 The new version avoids potential issues with tainted
 arguments in the query, for explicit expansion.
 &*Note*&: server specifications in list-style lookups are still problematic.
-.wen
 
 
 .section "Special MySQL features" "SECID73"
@@ -8175,12 +8155,10 @@ SQLite is different to the other SQL lookups because a filename is required in
 addition to the SQL query. An SQLite database is a single file, and there is no
 daemon as in the other SQL databases.
 
-.new
 .oindex &%sqlite_dbfile%&
 The preferred way of specifying the file is by using the
 &%sqlite_dbfile%& option, set to
 an absolute path.
-.wen
 A deprecated method is available, prefixing the query with the filename
 separated by white space.
 This means that the path name cannot contain white space.
@@ -8189,7 +8167,6 @@ It also means that the query cannot use any tainted values, as that taints
 the entire query including the filename - resulting in a refusal to open
 the file.
 
-.new
 Here is a lookup expansion example:
 .code
 sqlite_dbfile = /some/thing/sqlitedb
@@ -8201,7 +8178,6 @@ In a list, the syntax is similar. For example:
 domainlist relay_to_domains = sqlite;\
    select * from relays where ip='$sender_host_address';
 .endd
-.wen
 The only character affected by the &%quote_sqlite%& operator is a single
 quote, which it doubles.
 
@@ -8391,7 +8367,6 @@ in the previous section. You could also use the &(wildlsearch)& or
 
 
 
-.new
 .section "Results of list checking" SECTlistresults
 The primary result of doing a list check is a truth value.
 In some contexts additional information is stored
@@ -8415,7 +8390,6 @@ will store a result in the &$recipient_data$& variable.
 
 The detail of the additional information depends on the
 type of match and is given below as the &*value*& information.
-.wen
 
 
 
@@ -8478,7 +8452,6 @@ domainlist  dom2 = !a.b : *.b
 where &'x.y'& does not match. It's best to avoid negation altogether in
 referenced lists if you can.
 
-.new
 .cindex "hiding named list values"
 .cindex "named lists" "hiding value of"
 Some named list definitions may contain sensitive data, for example, passwords for
@@ -8488,7 +8461,6 @@ word &"hide"&. For example:
 .code
 hide domainlist filter_for_domains = ldap;PASS=secret ldap::/// ...
 .endd
-.wen
 
 
 Named lists may have a performance advantage. When Exim is routing an
@@ -8583,9 +8555,7 @@ as set by the &%primary_hostname%& option (or defaulted). This makes it
 possible to use the same configuration file on several different hosts that
 differ only in their names.
 
-.new
 The value for a match will be the primary host name.
-.wen
 
 
 .next
@@ -8600,9 +8570,7 @@ control which of a host's several IP addresses are treated as local.
 In today's Internet, the use of domain literals is controversial;
 see the &%allow_domain_literals%& main option.
 
-.new
 The value for a match will be the string &`@[]`&.
-.wen
 
 
 .next
@@ -8653,9 +8621,7 @@ involved, it is easiest to change the delimiter for the main list as well:
 domains = <? @mx_any/ignore=<;127.0.0.1;::1 ? \
           an.other.domain ? ...
 .endd
-.new
 The value for a match will be the list element string (starting &`@mx_`&).
-.wen
 
 
 .next
@@ -8670,11 +8636,9 @@ matching works only in terms of dot-separated components. For example, a domain
 list item such as &`*key.ex`& matches &'donkey.ex'& as well as
 &'cipher.key.ex'&.
 
-.new
 The value for a match will be the list element string (starting with the asterisk).
 Additionally, &$0$& will be set to the matched string
 and &$1$& to the variable portion which the asterisk matched.
-.wen
 
 .next
 .cindex "regular expressions" "in domain list"
@@ -8693,11 +8657,9 @@ use the special &`\N`& sequence (see chapter &<<CHAPexpand>>&) to specify that
 it is not to be expanded (unless you really do want to build a regular
 expression by expansion, of course).
 
-.new
 The value for a match will be the list element string (starting with the circumflex).
 Additionally, &$0$& will be set to the string matching the regular expression,
 and &$1$& (onwards) to any submatches identified by parentheses.
-.wen
 
 
 
@@ -8758,13 +8720,11 @@ variable and can be referred to in other options.
 The value will be untainted.
 
 .next
-.new
 If the pattern starts with the name of a lookup type
 of either kind (single-key or query-style) it may be
 followed by a comma and options,
 The options are lookup-type specific and consist of a comma-separated list.
 Each item starts with a tag and and equals "=".
-.wen
 
 .next
 .cindex "domain list" "matching literal domain name"
@@ -10073,11 +10033,9 @@ newline at the very end. For the &%header%& and &%bheader%& expansion, for
 those headers that contain lists of addresses, a comma is also inserted at the
 junctions between headers. This does not happen for the &%rheader%& expansion.
 
-.new
 .cindex "tainted data"
 When the headers are from an incoming message,
 the result of expanding any of these variables is tainted.
-.wen
 
 
 .vitem &*${hmac{*&<&'hashname'&>&*}{*&<&'secret'&>&*}{*&<&'string'&>&*}}*&
@@ -10427,7 +10385,6 @@ Example:
 ${readsocket{/socket/name}{request string}{3s:shutdown=no}}
 .endd
 
-.new
 The following option names are recognised:
 .ilist
 &*cache*&
@@ -10449,7 +10406,6 @@ Controls the use of TLS on the connection.
 Values are &"yes"& or &"no"& (the default).
 If it is enabled, a shutdown as descripbed above is never done.
 .endlist
-.wen
 
 
 A fourth argument allows you to change any newlines that are in the data
@@ -10933,8 +10889,7 @@ a decimal representation of the answer (without &"K"&, &"M"& or &"G"&). For exam
 
 As a more realistic example, in an ACL you might have
 .code
-deny   message = Too many bad recipients
-       condition =                    \
+deny   condition =                    \
          ${if and {                   \
            {>{$rcpt_count}{10}}       \
            {                          \
@@ -10943,6 +10898,7 @@ deny   message = Too many bad recipients
              {${eval:$rcpt_count/2}}  \
            }                          \
          }{yes}{no}}
+       message = Too many bad recipients
 .endd
 The condition is true if there have been more than 10 RCPT commands and
 fewer than half of them have resulted in a valid recipient.
@@ -12380,13 +12336,6 @@ contain the trailing slash. If &$config_file$& does not contain a slash,
 .vindex "&$config_file$&"
 The name of the main configuration file Exim is using.
 
-.vitem &$dmarc_domain_policy$& &&&
-       &$dmarc_status$& &&&
-       &$dmarc_status_text$& &&&
-       &$dmarc_used_domains$&
-Results of DMARC verification.
-For details see section &<<SECDMARC>>&.
-
 .vitem &$dkim_verify_status$&
 Results of DKIM verification.
 For details see section &<<SECDKIMVFY>>&.
@@ -12419,6 +12368,13 @@ When a message has been received this variable contains
 a colon-separated list of signer domains and identities for the message.
 For details see section &<<SECDKIMVFY>>&.
 
+.vitem &$dmarc_domain_policy$& &&&
+       &$dmarc_status$& &&&
+       &$dmarc_status_text$& &&&
+       &$dmarc_used_domains$&
+Results of DMARC verification.
+For details see section &<<SECDMARC>>&.
+
 .vitem &$dnslist_domain$& &&&
        &$dnslist_matched$& &&&
        &$dnslist_text$& &&&
@@ -12487,14 +12443,12 @@ When the &%smtp_etrn_command%& option is being expanded, &$domain$& contains
 the complete argument of the ETRN command (see section &<<SECTETRN>>&).
 .endlist
 
-.new
 .cindex "tainted data"
 If the origin of the data is an incoming message,
 the result of expanding this variable is tainted.
 When un untainted version is needed, one should be obtained from
 looking up the value in a local (therefore trusted) database.
 Often &$domain_data$& is usable in this role.
-.wen
 
 
 .vitem &$domain_data$&
@@ -12590,7 +12544,7 @@ result of the lookup is made available in the &$host_data$& variable. This
 allows you, for example, to do things like this:
 .code
 deny  hosts = net-lsearch;/some/file
-message = $host_data
+      message = $host_data
 .endd
 .vitem &$host_lookup_deferred$&
 .cindex "host name" "lookup, failure of"
@@ -12689,7 +12643,6 @@ Global address rewriting happens when a message is received, so the value of
 because a message may have many recipients and the system filter is called just
 once.
 
-.new
 .cindex "tainted data"
 If the origin of the data is an incoming message,
 the result of expanding this variable is tainted.
@@ -12707,7 +12660,6 @@ rather than this variable.
 Often &$local_part_data$& is usable in this role.
 If needed, use a router &%address_data%& or &%set%& option for
 the retrieved data.
-.wen
 
 When a message is being delivered to a file, pipe, or autoreply transport as a
 result of aliasing or forwarding, &$local_part$& is set to the local part of
@@ -12749,9 +12701,7 @@ router as &$local_part_data$&. In addition, if the driver routes the address
 to a transport, the value is available in that transport. If the transport is
 handling multiple addresses, the value from the first address is used.
 
-.new
 The &%check_local_user%& router option also sets this variable.
-.wen
 
 &$local_part_data$& is also set when the &%local_parts%& condition in an ACL
 matches a local part by means of a lookup. The data read by the lookup is
@@ -12767,7 +12717,6 @@ If a local part prefix or suffix has been recognized, it is not included in the
 value of &$local_part$& during routing and subsequent delivery. The values of
 any prefix or suffix are in &$local_part_prefix$& and
 &$local_part_suffix$&, respectively.
-.new
 .cindex "tainted data"
 If the specification did not include a wildcard then
 the affix variable value is not tainted.
@@ -12776,7 +12725,6 @@ If the affix specification included a wildcard then the portion of
 the affix matched by the wildcard is in
 &$local_part_prefix_v$& or &$local_part_suffix_v$& as appropriate,
 and both the whole and varying values are tainted.
-.wen
 
 .vitem &$local_scan_data$&
 .vindex "&$local_scan_data$&"
@@ -12942,9 +12890,9 @@ header and the body).
 
 Here is an example of the use of this variable in a DATA ACL:
 .code
-deny message   = Too many lines in message header
-     condition = \
+deny condition = \
       ${if <{250}{${eval:$message_linecount - $body_linecount}}}
+     message   = Too many lines in message header
 .endd
 In the MAIL and RCPT ACLs, the value is zero because at that stage the
 message has not yet been received.
@@ -13433,7 +13381,6 @@ library, by setting:
 dns_dnssec_ok = 1
 .endd
 
-.new
 In addition, on Linux with glibc 2.31 or newer the resolver library will
 default to stripping out a successful validation status.
 This will break a previously working Exim installation.
@@ -13443,7 +13390,6 @@ glibc to pass through any successful validation with a new option in
 .code
 options trust-ad
 .endd
-.wen
 
 Exim does not perform DNSSEC validation itself, instead leaving that to a
 validating resolver (e.g. unbound, or bind with suitable configuration).
@@ -14644,6 +14590,7 @@ listed in more than one group.
 .row &%percent_hack_domains%&        "recognize %-hack for these domains"
 .row &%spamd_address%&               "set interface to SpamAssassin"
 .row &%strict_acl_vars%&             "object to unset ACL variables"
+.row &%spf_smtp_comment_template%&   "template for &$spf_smtp_comment$&"
 .endtable
 
 
@@ -14730,6 +14677,9 @@ See also the &'Policy controls'& section above.
 .row &%dkim_verify_keytypes%&        "DKIM key types accepted for signatures"
 .row &%dkim_verify_min_keysizes%&    "DKIM key sizes accepted for signatures"
 .row &%dkim_verify_signers%&         "DKIM domains for which DKIM ACL is run"
+.row &%dmarc_forensic_sender%&       "DMARC sender for report messages"
+.row &%dmarc_history_file%&          "DMARC results log"
+.row &%dmarc_tld_file%&              "DMARC toplevel domains file"
 .row &%host_lookup%&                 "host name looked up for these hosts"
 .row &%host_lookup_order%&           "order of DNS and local name lookups"
 .row &%recipient_unqualified_hosts%& "may send unqualified recipients"
@@ -15160,11 +15110,9 @@ required, it must come from the &%-oA%& command line option.
 This option defines a template file containing paragraphs of text to be used
 for constructing bounce messages.  Details of the file's contents are given in
 chapter &<<CHAPemsgcust>>&.
-.new
 .cindex bounce_message_file "tainted data"
 The option is expanded to give the file path, which must be
 absolute and untainted.
-.wen
 See also &%warn_message_file%&.
 
 
@@ -15491,11 +15439,9 @@ etc. are ignored. If IP literals are enabled, the &(ipliteral)& router declines
 to handle IPv6 literal addresses.
 
 
-.new
 .option dkim_verify_hashes main "string list" "sha256 : sha512"
 .cindex DKIM "selecting signature algorithms"
 This option gives a list of hash types which are acceptable in signatures,
-.wen
 and an order of processing.
 Signatures with algorithms not in the list will be ignored.
 
@@ -15514,14 +15460,12 @@ and an order of processing.
 Signatures with algorithms not in the list will be ignored.
 
 
-.new
 .option dkim_verify_min_keysizes main "string list" "rsa=1024 ed25519=250"
 This option gives a list of key sizes which are acceptable in signatures.
 The list is keyed by the algorithm type for the key; the values are in bits.
 Signatures with keys smaller than given by this option will fail verification.
 
 The default enforces the RFC 8301 minimum key size for RSA signatures.
-.wen
 
 .option dkim_verify_minimal main boolean false
 If set to true, verification of signatures will terminate after the
@@ -15535,6 +15479,14 @@ the ACL once for each signature in the message.
 See section &<<SECDKIMVFY>>&.
 
 
+.option dmarc_forensic_sender main string&!! unset
+.option dmarc_history_file main string unset
+.option dmarc_tld_file main string unset
+.cindex DMARC "main section options"
+These options control DMARC processing.
+See section &<<SECDMARC>>& for details.
+
+
 .option dns_again_means_nonexist main "domain list&!!" unset
 .cindex "DNS" "&""try again""& response; overriding"
 DNS lookups give a &"try again"& response for the DNS errors
@@ -15605,7 +15557,6 @@ default. A value of 0 coerces DNSSEC off, a value of 1 coerces DNSSEC on.
 
 If the resolver library does not support DNSSEC then this option has no effect.
 
-.new
 On Linux with glibc 2.31 or newer this is insufficient, the resolver library
 will default to stripping out a successful validation status.
 This will break a previously working Exim installation.
@@ -15615,7 +15566,6 @@ glibc to pass through any successful validation with a new option in
 .code
 options trust-ad
 .endd
-.wen
 
 
 .option dns_ipv4_lookup main "domain list&!!" unset
@@ -15714,10 +15664,8 @@ and RET and ORCPT options on MAIL FROM commands.
 A NOTIFY=SUCCESS option requests success-DSN messages.
 A NOTIFY= option with no argument requests that no delay or failure DSNs
 are sent.
-.new
 &*Note*&: Supplying success-DSN messages has been criticised
 on privacy grounds; it can leak details of internal forwarding.
-.wen
 
 .option dsn_from main "string&!!" "see below"
 .cindex "&'From:'& header line" "in bounces"
@@ -16681,7 +16629,6 @@ harm. This option overrides the &%pipe_as_creator%& option of the &(pipe)&
 transport driver.
 
 
-.new
 .option notifier_socket main string "$spool_directory/exim_daemon_notify"
 This option gives the name for a unix-domain socket on which the daemon
 listens for work and information-requests.
@@ -16696,7 +16643,6 @@ to Exim.
 
 If the Exim command line uses a &%-oX%& option and does not use &%-oP%&
 then a notifier socket is not created.
-.wen
 
 
 .option openssl_options main "string list" "+no_sslv2 +no_sslv3 +single_dh_use +no_ticket +no_renegotiation"
@@ -17640,12 +17586,10 @@ example:
 smtp_etrn_command = /etc/etrn_command $domain \
                     $sender_host_address
 .endd
-.new
 If the option is not set, the argument for the ETRN command must
 be a &'#'& followed by an address string.
 In this case an &'exim -R <string>'& command is used;
 if the ETRN ACL has set up a named-queue then &'-MCG <queue>'& is appended.
-.wen
 
 A new process is created to run the command, but Exim does not wait for it to
 complete. Consequently, its status cannot be checked. If the command cannot be
@@ -17828,6 +17772,46 @@ See section &<<SECTscanspamass>>& for more details.
 This option is available when Exim is compiled with SPF support.
 See section &<<SECSPF>>& for more details.
 
+.option spf_smtp_comment_template main string&!! "Please%_see%_http://www.open-spf.org/Why"
+This option is available when Exim is compiled with SPF support.  It
+allows the customisation of the SMTP comment that the SPF library
+generates.  You are strongly encouraged to link to your own explanative
+site. The template must not contain spaces. If you need spaces in the
+output, use the proper placeholder. If libspf2 can not parse the
+template, it uses a built-in default broken link. The following placeholders
+(along with Exim variables (but see below)) are allowed in the template:
+.ilist
+&*%_*&: A space.
+.next
+&*%{L}*&: Envelope sender's local part.
+.next
+&*%{S}*&: Envelope sender.
+.next
+&*%{O}*&: Envelope sender's domain.
+.next
+&*%{D}*&: Current(?) domain.
+.next
+&*%{I}*&: SMTP client Ip.
+.next
+&*%{C}*&: SMTP client pretty IP.
+.next
+&*%{T}*&: Epoch time (UTC).
+.next
+&*%{P}*&: SMTP client domain name.
+.next
+&*%{V}*&: IP version.
+.next
+&*%{H}*&: EHLO/HELO domain.
+.next
+&*%{R}*&: Receiving domain.
+.endlist
+The capitalized placeholders do proper URL encoding, if you use them
+lowercased, no encoding takes place.  This list was compiled from the
+libspf2 sources.
+
+A note on using Exim variables: As
+currently the SPF library is initialized before the SMTP EHLO phase,
+the variables useful for expansion are quite limited.
 
 
 .option split_spool_directory main boolean false
@@ -18555,11 +18539,9 @@ for constructing the warning message which is sent by Exim when a message has
 been in the queue for a specified amount of time, as specified by
 &%delay_warning%&. Details of the file's contents are given in chapter
 &<<CHAPemsgcust>>&.
-.new
 .cindex warn_message_file "tainted data"
 The option is expanded to give the file path, which must be
 absolute and untainted.
-.wen
 See also &%bounce_message_file%&.
 
 
@@ -19045,9 +19027,7 @@ colon-separated (by default, changeable in the usual way &<<SECTlistsepchange>>&
 that is associated with any addresses that are accepted by the router.
 However, the option has no effect when an address is just being verified.
 Each list item is separately expanded, at transport time.
-.new
 If an item ends in *, it will match any header with the given prefix.
-.wen
 The way in which
 the text is used to remove header lines at transport time is described in
 section &<<SECTheadersaddrem>>&. Header lines are not actually removed until
@@ -19160,11 +19140,9 @@ command for LMTP, SMTP, and BSMTP deliveries has the prefix removed by default.
 This behaviour can be overridden by setting &%rcpt_include_affixes%& true on
 the relevant transport.
 
-.new
 .vindex &$local_part_prefix_v$&
 If wildcarding (above) was used then the part of the prefix matching the
 wildcard is available in &$local_part_prefix_v$&.
-.wen
 
 When an address is being verified, &%local_part_prefix%& affects only the
 behaviour of the router. If the callout feature of verification is in use, this
@@ -20999,7 +20977,6 @@ is not the case when the file contains syntactically valid items that happen to
 yield empty addresses, for example, items containing only RFC 2822 address
 comments.
 
-.new
 .cindex "tainted data" "in filenames"
 .cindex redirect "tainted data"
 Tainted data may not be used for a filename.
@@ -21010,7 +20987,6 @@ as they are provided by a potential attacker.
 In the examples above, &$local_part$& is used for looking up data held locally
 on the system, and not used directly (the second example derives &$home$& via
 the passsword file or database, using &$local_part$&).
-.wen
 
 
 
@@ -21237,11 +21213,9 @@ It must be given as
 .code
 list1:   :include:/opt/lists/list1
 .endd
-.new
 .cindex "tainted data" "in filenames"
 .cindex redirect "tainted data"
 Tainted data may not be used for a filename.
-.wen
 .next
 .cindex "address redirection" "to black hole"
 .cindex "delivery" "discard"
@@ -22250,9 +22224,7 @@ Each list item is separately expanded.
 If the result of the expansion is an empty string, or if the expansion
 is forced to fail, no action is taken. Other expansion failures are treated as
 errors and cause the delivery to be deferred.
-.new
 If an item ends in *, it will match any header with the given prefix.
-.wen
 
 Matching headers are omitted from the message as it is transported, as described
 in section &<<SECTheadersaddrem>>&. Header removal can also be specified by
@@ -22807,14 +22779,12 @@ If &%file%& or &%directory%& is set for a delivery from a redirection, it is
 used to determine the file or directory name for the delivery. Normally, the
 contents of &$address_file$& are used in some way in the string expansion.
 .endlist
-.new
 .cindex "tainted data" "in filenames"
 .cindex appendfile "tainted data"
 Tainted data may not be used for a file or directory name.
 This means that, for instance, &$local_part$& cannot be used directly
 as a component of a path.  It can however be used as the key for a lookup
 which returns a path (or component).
-.wen
 
 
 .cindex "Sieve filter" "configuring &(appendfile)&"
@@ -24252,11 +24222,9 @@ directories are also controllable. See chapter &<<CHAPenvironment>>& for
 details of the local delivery environment and chapter &<<CHAPbatching>>&
 for a discussion of local delivery batching.
 
-.new
 .cindex "tainted data" "in pipe command"
 .cindex pipe "tainted data"
 Tainted data may not be used for the command name.
-.wen
 
 
 .section "Concurrent delivery" "SECID140"
@@ -25398,9 +25366,7 @@ unauthenticated. See also &%hosts_require_auth%&, and chapter
 .cindex "RFC 3030" "CHUNKING"
 This option provides a list of servers to which, provided they announce
 CHUNKING support, Exim will attempt to use BDAT commands rather than DATA.
-.new
 Unless DKIM signing is being done,
-.wen
 BDAT will not be used in conjunction with a transport filter.
 
 .option hosts_try_dane smtp "host list&!!" *
@@ -27933,7 +27899,6 @@ connection, a client certificate has been verified, the &"valid-client-cert"&
 option is passed. When authentication succeeds, the identity of the user
 who authenticated is placed in &$auth1$&.
 
-.new
 The Dovecot configuration to match the above wil look
 something like:
 .code
@@ -27953,7 +27918,6 @@ conf.d/10-auth.conf :-
 
 auth_mechanisms = plain login ntlm
 .endd
-.wen
 
 .ecindex IIDdcotauth1
 .ecindex IIDdcotauth2
@@ -27980,7 +27944,6 @@ scale to handle future authentication mechanisms, so no guarantee can be
 made that any particular new authentication mechanism will be supported
 without code changes in Exim.
 
-.new
 The library is expected to add support in an upcoming
 realease for the SCRAM-SHA-256 method.
 The macro _HAVE_AUTH_GSASL_SCRAM_SHA_256 will be defined
@@ -28004,9 +27967,7 @@ the password to be used, in clear.
 .option client_username gsasl string&!! unset
 This option is exapanded before use, and should result in
 the account name to be used.
-.wen
 
-.new
 .option client_spassword gsasl string&!! unset
 If a SCRAM mechanism is being used and this option is set
 it is used in preference to &%client_password%&.
@@ -28015,7 +27976,6 @@ a 40 (for SHA-1) or 64 (for SHA-256) character string
 with the PBKDF2-prepared password, hex-encoded.
 Note that this value will depend on the salt and iteration-count
 supplied by the server.
-.wen
 
 
 
@@ -28033,12 +27993,10 @@ This should have meant that certificate identity and verification becomes a
 non-issue, as a man-in-the-middle attack will cause the correct client and
 server to see different identifiers and authentication will fail.
 
-.new
 This is
 only usable by mechanisms which support "channel binding"; at time of
 writing, that's the SCRAM family.
 When using this feature the "-PLUS" variants of the method names need to be used.
-.wen
 
 This defaults off to ensure smooth upgrade across Exim releases, in case
 this option causes some clients to start failing.  Some future release
@@ -28094,7 +28052,6 @@ Some mechanisms will use this data.
 
 .option server_scram_iter gsasl string&!! 4096
 This option provides data for the SCRAM family of mechanisms.
-.new
 The &$auth1$&, &$auth2$& and &$auth3$& variables are available
 when this option is expanded.
 
@@ -28105,21 +28062,17 @@ a compute cost factor imposed on the client
 either the iteration count or the salt).
 A minimum value of 4096 is required by the standards
 for all current SCRAM mechanism variants.
-.wen
 
 .option server_scram_salt gsasl string&!! unset
 This option provides data for the SCRAM family of mechanisms.
-.new
 The &$auth1$&, &$auth2$& and &$auth3$& variables are available
 when this option is expanded.
 The value should be a base64-encoded string,
 of random data typically 4-to-16 bytes long.
 If unset or empty after expansion the library will provides a value for the
 protocol conversation.
-.wen
 
 
-.new
 .option server_key gsasl string&!! unset
 .option server_skey gsasl string&!! unset
 These options can be used for the SCRAM family of mechanisms
@@ -28145,7 +28098,6 @@ If unset or not of the right length, &%server_password%& will be used.
 
 The libgsasl library release includes a utility &'gsasl'& which can be used
 to generate these values.
-.wen
 
 
 .option server_service gsasl string &`smtp`&
@@ -30443,8 +30395,8 @@ The &%message%& modifier operates exactly as it does for &%accept%&.
 &%drop%&: This verb behaves like &%deny%&, except that an SMTP connection is
 forcibly closed after the 5&'xx'& error message has been sent. For example:
 .code
-drop   message   = I don't take more than 20 RCPTs
-       condition = ${if > {$rcpt_count}{20}}
+drop   condition = ${if > {$rcpt_count}{20}}
+       message   = I don't take more than 20 RCPTs
 .endd
 There is no difference between &%deny%& and &%drop%& for the connect-time ACL.
 The connection is always dropped after sending a 550 response.
@@ -31254,7 +31206,6 @@ response to an EHLO command. Therefore, it should normally appear in an ACL
 controlled by &%acl_smtp_connect%& or &%acl_smtp_helo%&. See also
 &%pipelining_advertise_hosts%&.
 
-.new
 .vitem &*control&~=&~queue/*&<&'options'&>* &&&
        &*control&~=&~queue_only*&
 .oindex "&%queue%&"
@@ -31279,7 +31230,6 @@ able to send all such messages on a single connection.
 
 The control only applies to the current message, not to any subsequent ones that
  may be received in the same SMTP connection.
-.wen
 
 .vitem &*control&~=&~submission/*&<&'options'&>
 .cindex "message" "submission"
@@ -31680,7 +31630,7 @@ of the lookup is made available in the &$host_data$& variable. This
 allows you, for example, to set up a statement like this:
 .code
 deny  hosts = net-lsearch;/some/file
-message = $host_data
+      message = $host_data
 .endd
 which gives a custom error message for each denied host.
 
@@ -31824,8 +31774,8 @@ section &<<SECTaddressverification>>& (callouts are described in section
 condition to restrict it to bounce messages only:
 .code
 deny    senders = :
-        message = A valid sender header is required for bounces
        !verify  = header_sender
+        message = A valid sender header is required for bounces
 .endd
 
 .vitem &*verify&~=&~header_syntax*&
@@ -32007,8 +31957,8 @@ Testing the list of domains stops as soon as a match is found. If you want to
 warn for one list and block for another, you can use two different statements:
 .code
 deny  dnslists = blackholes.mail-abuse.org
-warn  message  = X-Warn: sending host is on dialups list
-      dnslists = dialups.mail-abuse.org
+warn  dnslists = dialups.mail-abuse.org
+      message  = X-Warn: sending host is on dialups list
 .endd
 .cindex caching "of dns lookup"
 .cindex DNS TTL
@@ -32049,8 +31999,8 @@ addresses (see, e.g., the &'domain based zones'& link at
 with these lists. You can change the name that is looked up in a DNS list by
 listing it after the domain name, introduced by a slash. For example,
 .code
-deny  message  = Sender's domain is listed at $dnslist_domain
-      dnslists = dsn.rfc-ignorant.org/$sender_address_domain
+deny  dnslists = dsn.rfc-ignorant.org/$sender_address_domain
+      message  = Sender's domain is listed at $dnslist_domain
 .endd
 This particular example is useful only in ACLs that are obeyed after the
 RCPT or DATA commands, when a sender address is available. If (for
@@ -32114,13 +32064,13 @@ dnslists = black.list.tld/a.domain::b.domain
 However, when the data for the list is obtained from a lookup, the second form
 is usually much more convenient. Consider this example:
 .code
-deny message  = The mail servers for the domain \
+deny dnslists = sbl.spamhaus.org/<|${lookup dnsdb {>|a=<|\
+                                   ${lookup dnsdb {>|mxh=\
+                                   $sender_address_domain} }} }
+     message  = The mail servers for the domain \
                 $sender_address_domain \
                 are listed at $dnslist_domain ($dnslist_value); \
                 see $dnslist_text.
-     dnslists = sbl.spamhaus.org/<|${lookup dnsdb {>|a=<|\
-                                   ${lookup dnsdb {>|mxh=\
-                                   $sender_address_domain} }} }
 .endd
 Note the use of &`>|`& in the dnsdb lookup to specify the separator for
 multiple DNS records. The inner dnsdb lookup produces a list of MX hosts
@@ -32193,7 +32143,7 @@ very meaningful. See section &<<SECTmordetinf>>& for a way of obtaining more
 information.
 
 You can use the DNS list variables in &%message%& or &%log_message%& modifiers
-&-- although these appear before the condition in the ACL, they are not
+&-- even if these appear before the condition in the ACL, they are not
 expanded until after it has failed. For example:
 .code
 deny    hosts = !+local_networks
@@ -32379,12 +32329,12 @@ restrictions, to get the TXT record. As a byproduct of this, there is also
 a check that the IP being tested is indeed on the first list. The first
 domain is the one that is put in &$dnslist_domain$&. For example:
 .code
-deny message  = \
-         rejected because $sender_host_address is blacklisted \
-         at $dnslist_domain\n$dnslist_text
-       dnslists = \
+deny   dnslists = \
          sbl.spamhaus.org,sbl-xbl.spamhaus.org=127.0.0.2 : \
          dul.dnsbl.sorbs.net,dnsbl.sorbs.net=127.0.0.10
+       message  = \
+         rejected because $sender_host_address is blacklisted \
+         at $dnslist_domain\n$dnslist_text
 .endd
 For the first blacklist item, this starts by doing a lookup in
 &'sbl-xbl.spamhaus.org'& and testing for a 127.0.0.2 return. If there is a
@@ -32574,12 +32524,12 @@ new rate.
 .code
 acl_check_connect:
  deny ratelimit = 100 / 5m / readonly
-    log_message = RATE CHECK: $sender_rate/$sender_rate_period \
+      log_message = RATE CHECK: $sender_rate/$sender_rate_period \
                   (max $sender_rate_limit)
 # ...
 acl_check_mail:
  warn ratelimit = 100 / 5m / strict
-    log_message = RATE UPDATE: $sender_rate/$sender_rate_period \
+      log_message = RATE UPDATE: $sender_rate/$sender_rate_period \
                   (max $sender_rate_limit)
 .endd
 
@@ -32689,16 +32639,16 @@ deny authenticated = *
      ratelimit = 100 / 1d / strict / $authenticated_id
 
 # System-wide rate limit
-defer message = Sorry, too busy. Try again later.
-     ratelimit = 10 / 1s / $primary_hostname
+defer ratelimit = 10 / 1s / $primary_hostname
+      message = Sorry, too busy. Try again later.
 
 # Restrict incoming rate from each host, with a default
 # set using a macro and special cases looked up in a table.
-defer message = Sender rate exceeds $sender_rate_limit \
-               messages per $sender_rate_period
-     ratelimit = ${lookup {$sender_host_address} \
+defer ratelimit = ${lookup {$sender_host_address} \
                    cdb {DB/ratelimits.cdb} \
                    {$value} {RATELIMIT} }
+      message = Sender rate exceeds $sender_rate_limit \
+               messages per $sender_rate_period
 .endd
 &*Warning*&: If you have a busy server with a lot of &%ratelimit%& tests,
 especially with the &%per_rcpt%& option, you may suffer from a performance
@@ -33331,16 +33281,16 @@ list called &%batv_senders%&. Then, in the ACL for RCPT commands, you could
 use this:
 .code
 # Bounces: drop unsigned addresses for BATV senders
-deny message = This address does not send an unsigned reverse path
-     senders = :
+deny senders = :
      recipients = +batv_senders
+     message = This address does not send an unsigned reverse path
 
 # Bounces: In case of prvs-signed address, check signature.
-deny message = Invalid reverse path signature.
-     senders = :
+deny senders = :
      condition  = ${prvscheck {$local_part@$domain}\
                   {PRVSCHECK_SQL}{1}}
      !condition = $prvscheck_result
+     message = Invalid reverse path signature.
 .endd
 The first statement rejects recipients for bounce messages that are addressed
 to plain BATV sender addresses, because it is known that BATV senders do not
@@ -33877,13 +33827,13 @@ imposed by your anti-virus scanner.
 
 Here is a very simple scanning example:
 .code
-deny message = This message contains malware ($malware_name)
-     malware = *
+deny malware = *
+     message = This message contains malware ($malware_name)
 .endd
 The next example accepts messages when there is a problem with the scanner:
 .code
-deny message = This message contains malware ($malware_name)
-     malware = */defer_ok
+deny malware = */defer_ok
+     message = This message contains malware ($malware_name)
 .endd
 The next example shows how to use an ACL variable to scan with both sophie and
 aveserver. It assumes you have set:
@@ -33892,13 +33842,13 @@ av_scanner = $acl_m0
 .endd
 in the main Exim configuration.
 .code
-deny message = This message contains malware ($malware_name)
-     set acl_m0 = sophie
+deny set acl_m0 = sophie
      malware = *
+     message = This message contains malware ($malware_name)
 
-deny message = This message contains malware ($malware_name)
-     set acl_m0 = aveserver
+deny set acl_m0 = aveserver
      malware = *
+     message = This message contains malware ($malware_name)
 .endd
 
 
@@ -34027,8 +33977,8 @@ is set to record the actual address used.
 .section "Calling SpamAssassin from an Exim ACL" "SECID206"
 Here is a simple example of the use of the &%spam%& condition in a DATA ACL:
 .code
-deny message = This message was classified as SPAM
-     spam = joe
+deny spam = joe
+     message = This message was classified as SPAM
 .endd
 The right-hand side of the &%spam%& condition specifies a name. This is
 relevant if you have set up multiple SpamAssassin profiles. If you do not want
@@ -34060,9 +34010,9 @@ large ones may cause significant performance degradation. As most spam messages
 are quite small, it is recommended that you do not scan the big ones. For
 example:
 .code
-deny message = This message was classified as SPAM
-     condition = ${if < {$message_size}{10K}}
+deny condition = ${if < {$message_size}{10K}}
      spam = nobody
+     message = This message was classified as SPAM
 .endd
 
 The &%spam%& condition returns true if the threshold specified in the user's
@@ -34120,8 +34070,8 @@ failed. If you want to treat DEFER as FAIL (to pass on to the next ACL
 statement block), append &`/defer_ok`& to the right-hand side of the
 spam condition, like this:
 .code
-deny message = This message was classified as SPAM
-     spam    = joe/defer_ok
+deny spam    = joe/defer_ok
+     message = This message was classified as SPAM
 .endd
 This causes messages to be accepted even if there is a problem with &%spamd%&.
 
@@ -34139,9 +34089,9 @@ warn  spam = nobody
       add_header = Subject: *SPAM* $h_Subject:
 
 # reject spam at high scores (> 12)
-deny  message = This message scored $spam_score spam points.
-      spam = nobody:true
+deny  spam = nobody:true
       condition = ${if >{$spam_score_int}{120}{1}{0}}
+      message = This message scored $spam_score spam points.
 .endd
 
 
@@ -34345,10 +34295,10 @@ As an example, the following will ban &"HTML mail"& (including that sent with
 alternative plain text), while allowing HTML files to be attached. HTML
 coverletter mail attached to non-HTML coverletter mail will also be allowed:
 .code
-deny message = HTML mail is not accepted here
-!condition = $mime_is_rfc822
-condition = $mime_is_coverletter
-condition = ${if eq{$mime_content_type}{text/html}{1}{0}}
+deny !condition = $mime_is_rfc822
+     condition = $mime_is_coverletter
+     condition = ${if eq{$mime_content_type}{text/html}{1}{0}}
+     message = HTML mail is not accepted here
 .endd
 
 .vitem &$mime_is_multipart$&
@@ -34401,8 +34351,8 @@ expanded before being used, you must also escape dollar signs and backslashes
 with more backslashes, or use the &`\N`& facility to disable expansion.
 Here is a simple example that contains two regular expressions:
 .code
-deny message = contains blacklisted regex ($regex_match_string)
-     regex = [Mm]ortgage : URGENT BUSINESS PROPOSAL
+deny regex = [Mm]ortgage : URGENT BUSINESS PROPOSAL
+     message = contains blacklisted regex ($regex_match_string)
 .endd
 The conditions returns true if any one of the regular expressions matches. The
 &$regex_match_string$& expansion variable is then set up and contains the
@@ -34470,10 +34420,8 @@ HAVE_LOCAL_SCAN=yes
 LOCAL_SCAN_SOURCE=Local/local_scan.c
 .endd
 for example. The function must be called &[local_scan()]&;
-.new
 the source file(s) for it should first #define LOCAL_SCAN
 and then #include "local_scan.h".
-.wen
 It is called by
 Exim after it has received a message, when the success return code is about to
 be sent. This is after all the ACLs have been run. The return code from your
@@ -35154,7 +35102,6 @@ dropping of a TCP/IP connection), you can call &'smtp_fflush()'&, which has no
 arguments. It flushes the output stream, and returns a non-zero value if there
 is an error.
 
-.new
 .vitem &*void&~*store_get(int,BOOL)*&
 This function accesses Exim's internal store (memory) manager. It gets a new
 chunk of memory whose size is given by the first argument.
@@ -35163,7 +35110,6 @@ data possibly coming from an attacker (eg. the message content),
 FALSE if it is locally-sourced.
 Exim bombs out if it ever
 runs out of memory. See the next section for a discussion of memory handling.
-.wen
 
 .vitem &*void&~*store_get_perm(int,BOOL)*&
 This function is like &'store_get()'&, but it always gets memory from the
@@ -37277,13 +37223,11 @@ virtual:
   data = ${lookup{$local_part}lsearch{/etc/mail/virtual/$domain_data}}
   no_more
 .endd
-.new
 The &%domains%& option specifies that the router is to be skipped, unless there
 is a file in the &_/etc/mail/virtual_& directory whose name is the same as the
 domain that is being processed.
 The &(dsearch)& lookup used results in an untainted version of &$domain$&
 being placed into the &$domain_data$& variable.
-.wen
 
 When the router runs, it looks up the local
 part in the file to find a new address (or list of addresses). The &%no_more%&
@@ -40866,9 +40810,7 @@ When unspecified, the header names listed in RFC4871 will be used,
 whether or not each header is present in the message.
 The default list is available for the expansion in the macro
 &"_DKIM_SIGN_HEADERS"&
-.new
 and an oversigning variant is in &"_DKIM_OVERSIGN_HEADERS"&.
-.wen
 
 If a name is repeated, multiple headers by that name (or the absence thereof)
 will be signed.  The textually later headers in the headers part of the
@@ -41119,10 +41061,8 @@ Notes from the key record (tag n=).
 
 .vitem &%$dkim_key_length%&
 Number of bits in the key.
-.new
 Valid only once the key is loaded, which is at the time the header signature
 is verified, which is after the body hash is.
-.wen
 
 Note that RFC 8301 says:
 .code
@@ -41146,10 +41086,10 @@ verb to a group of domains or identities. For example:
 
 .code
 # Warn when Mail purportedly from GMail has no gmail signature
-warn log_message = GMail sender without gmail.com DKIM signature
-     sender_domains = gmail.com
+warn sender_domains = gmail.com
      dkim_signers = gmail.com
      dkim_status = none
+     log_message = GMail sender without gmail.com DKIM signature
 .endd
 
 Note that the above does not check for a total lack of DKIM signing;
@@ -41161,10 +41101,10 @@ results against the actual result of verification. This is typically used
 to restrict an ACL verb to a list of verification outcomes, for example:
 
 .code
-deny message = Mail from Paypal with invalid/missing signature
-     sender_domains = paypal.com:paypal.de
+deny sender_domains = paypal.com:paypal.de
      dkim_signers = paypal.com:paypal.de
      dkim_status = none:invalid:fail
+     message = Mail from Paypal with invalid/missing signature
 .endd
 
 The possible status keywords are: 'none','invalid','fail' and 'pass'. Please
@@ -41248,13 +41188,16 @@ deny spf = fail
      message = $sender_host_address is not allowed to send mail from \
                ${if def:sender_address_domain \
                     {$sender_address_domain}{$sender_helo_name}}.  \
-               Please see http://www.open-spf.org/Why?scope=\
-               ${if def:sender_address_domain {mfrom}{helo}};\
+               Please see http://www.open-spf.org/Why;\
                identity=${if def:sender_address_domain \
                              {$sender_address}{$sender_helo_name}};\
                ip=$sender_host_address
 .endd
 
+Note: The above mentioned URL may not be as helpful as expected. You are
+encouraged to replace the link with a link to a site with more
+explanations.
+
 When the spf condition has run, it sets up several expansion
 variables:
 
@@ -41289,8 +41232,11 @@ variables:
 
 .vitem &$spf_smtp_comment$&
 .vindex &$spf_smtp_comment$&
+.vindex &%spf_smtp_comment_template%&
   This contains a string that can be used in a SMTP response
   to the calling party. Useful for "fail".
+  The string is generated by the SPF library from the template configured in the main config
+  option &%spf_smtp_comment_template%&.
 .endlist
 
 
@@ -41487,10 +41433,8 @@ during domain parsing. Maintained by Mozilla,
 the most current version can be downloaded
 from a link at &url(https://publicsuffix.org/list/public_suffix_list.dat).
 See also the util/renew-opendmarc-tlds.sh script.
-.new
 The default for the option is unset.
 If not set, DMARC processing is disabled.
-.wen
 
 
 The &%dmarc_history_file%& option, if set
@@ -41765,8 +41709,8 @@ A possible solution is:
   # Or do some kind of IP lookup in a flat file or database
   # LIMIT = ${lookup{$sender_host_address}iplsearch{/etc/exim/proxy_limits}}
 
-  defer   message        = Too many connections from this IP right now
-          ratelimit      = LIMIT / 5s / per_conn / strict
+  defer   ratelimit      = LIMIT / 5s / per_conn / strict
+          message        = Too many connections from this IP right now
 .endd
 
 
@@ -42019,9 +41963,7 @@ Events have names which correspond to the point in process at which they fire.
 The name is placed in the variable &$event_name$& and the event action
 expansion must check this, as it will be called for every possible event type.
 
-.new
 The current list of events is:
-.wen
 .display
 &`dane:fail              after    transport  `& per connection
 &`msg:complete           after    main       `& per message
index e8f7048399073af9181f136e3eb6ff40a0623cb8..a4526ca5cc1b55768100285da6f1476b094620b1 100644 (file)
@@ -3,8 +3,8 @@ affect Exim's operation, with an unchanged configuration file.  For new
 options, and new features, see the NewStuff file next to this ChangeLog.
 
 
-Since Exim version 4.94
-----------------------
+Exim version 4.95
+-----------------
 
 JH/01 Bug 1329: Fix format of Maildir-format filenames to match other mail-
       related applications.  Previously an "H" was used where available info
@@ -207,6 +207,14 @@ JH/42 Internationalisation: change the default for downconversion in the smtp
       transport.  The change does mean that addresses needing conversion will
       be converted when previously a delivery failure would occur.
 
+JH/43 Fix possible long line in DSN.  Previously when a very long SMTP error
+      response was received it would be used unchecked in a fail-DSN, violating
+      standards on line-length limits.  Truncate if needed.
+
+HS/01 Remove parameters of the link to www.open-spf.org. The linked form
+      doesn't work. (Additionally add a new main config option to configure the
+      spf_smtp_comment)
+
 
 Exim version 4.93
 -----------------
index 9797e97db3a5ae9c8caf54e7c4bff387ff9f62c5..5769a9733f264d024a19409dc7e0624620d1f0fb 100644 (file)
@@ -41,7 +41,7 @@ Version 4.94
 
  3. A msg:defer event.
 
- 4. Client-side support in the gsasl authenticator.  Tested against the 
+ 4. Client-side support in the gsasl authenticator.  Tested against the
     plaintext driver for PLAIN; only against itself for SCRAM-SHA-1 and
     SCRAM-SHA-1-PLUS methods.
 
@@ -95,6 +95,9 @@ Version 4.94
 
 21. bounce_message_file and warn_message_file are now expanded before use.
 
+22. New main config option spf_smtp_comment_template to customise the
+    $spf_smtp_comment variable
+
 
 
 Version 4.93
@@ -135,7 +138,7 @@ Version 4.93
 15: Support under OpenSSL for writing NSS-style key files for packet-capture
     decode.  The environment variable SSLKEYLOGFILE is used; if an absolute path
     it must indicate a file under the spool directory; if relative the the spool
-    directory is prepended.  Works on the server side only.  Support under 
+    directory is prepended.  Works on the server side only.  Support under
     GnuTLS was already there, being done purely by the library (server side
     only, and exim must be run as root).
 
index cfb3cd0f0c6bade7bd140fa7884294a1b438f973..183f6b7220e3c0e12ab6e328709972bc26bb3408 100644 (file)
@@ -555,6 +555,10 @@ smtp_reserve_hosts                   host list       unset         main
 smtp_return_error_details            boolean         false         main              4.11
 socket                               string*         unset         lmtp              4.11
 spamd_address                        string*         +             main              4.50 with content scan
+spf_guess                           string          "v=spf1 a/24 mx/24 ptr ?all"
+                                                                  main              4.91 with SUPPORT_SPF
+spf_smtp_comment_template           string*         "Please see http://www.open-spf.org/Why"
+                                                                  main              4.94 with SUPPORT_SPF
 split_spool_directory                boolean         false         main              1.70
 spool_directory                      string          ++            main
 spool_wireformat                     boolean         false         main              4.90
index f99afc1bd27614c7fa19ab55086990f20cc9f385..a0afa8df0679945688becabca0c5c21736423910 100644 (file)
@@ -33,7 +33,7 @@ Some Transports now refuse to use tainted data in constructing their delivery
 location; this WILL BREAK configurations which are not updated accordingly.
 In particular: any Transport use of $local_user which has been relying upon
 check_local_user far away in the Router to make it safe, should be updated to
-replace $local_user with $local_part_verified.
+replace $local_user with $local_part_data.
 
 Attempting to remove, in router or transport, a header name that ends with
 an asterisk (which is a standards-legal name) will now result in all headers
index d7be01cd6b166d83245a23b5e7660ecd006eb831..13dc494144151e30344423a5c193d801f64ba2e5 100644 (file)
 
 # Things that depend on the operating system have default settings in
 # OS/Makefile-Default, but these are overridden for some OS by files
-# called called OS/Makefile-<osname>. You can further override these by
-# creating files called Local/Makefile-<osname>, and
-# Local/Makefile-<buildname> (where "<osname>" stands for the name of
-# your operating system - look at the names in the OS directory to see
-# which names are recognized, and "<buildname>" is derived from the
-# environment variable "build")
+# called OS/Makefile-<osname>. You can further override these settings by
+# creating files Local/Makefile-<osname>, and Local/Makefile-<build>.
+# The suffix "<osname>" stands for the name of your operating system - look
+# at the names in the OS directory to see which names are recognized,
+# and "<build>" is the content of the environment variable "build".
 
 # However, if you are building Exim for a single OS only, you don't need to
 # worry about setting up Local/Makefile-<osname>. Any build-time configuration
index 733a37615e52455ec22eece67a705603fd1fba60..946137fc9ff838c9eff24b01bc12c51e8e9ea675 100644 (file)
@@ -516,8 +516,8 @@ acl_check_rcpt:
   # examples of how you can get Exim to perform a DNS black list lookup at this
   # point. The first one denies, whereas the second just warns.
   #
-  # deny    message       = rejected because $sender_host_address is in a black list at $dnslist_domain\n$dnslist_text
-  #         dnslists      = black.list.example
+  # deny    dnslists      = black.list.example
+  #         message       = rejected because $sender_host_address is in a black list at $dnslist_domain\n$dnslist_text
   #
   # warn    dnslists      = black.list.example
   #         add_header    = X-Warning: $sender_host_address is in a black list at $dnslist_domain
@@ -587,9 +587,9 @@ acl_check_data:
   # Deny if the message contains an overlong line.  Per the standards
   # we should never receive one such via SMTP.
   #
-  deny    message    = maximum allowed line length is 998 octets, \
+  deny    condition  = ${if > {$max_received_linelength}{998}}
+          message    = maximum allowed line length is 998 octets, \
                        got $max_received_linelength
-          condition  = ${if > {$max_received_linelength}{998}}
 
   # Deny if the headers contain badly-formed addresses.
   #
@@ -815,9 +815,6 @@ remote_smtp:
   driver = smtp
 .ifdef _HAVE_TLS_RESUME
   tls_resumption_hosts = *
-#endif
-.ifdef _HAVE_PRDR
-  hosts_try_prdr = *
 .endif
 
 
@@ -859,9 +856,6 @@ smarthost_smtp:
   tls_resumption_hosts = *
 .endif
 .endif
-.ifdef _HAVE_PRDR
-  hosts_try_prdr = *
-.endif
 
 
 # This transport is used for local delivery to user mailboxes in traditional
index 4e7aae69a0f7143edd3e510ef9b07a2372eeda96..2f4149f6f55bb23fdf0de097b4333bb0514861a1 100644 (file)
@@ -4324,8 +4324,10 @@ else
     if (!(unprivileged || removed_privilege))
       exim_fail("exim: changing group failed: %s\n", strerror(errno));
     else
+      {
       DEBUG(D_any) debug_printf("changing group to %ld failed: %s\n",
           (long int)exim_gid, strerror(errno));
+      }
   }
 
 /* Handle a request to scan a file for malware */
index 732e20f972074d80769b63c42af15e2cc8b01318..b014533c928d3df9c687dd593190f7702b39f336 100644 (file)
@@ -2066,7 +2066,8 @@ switch (vp->type)
   case vtype_string_func:
     {
     stringptr_fn_t * fn = (stringptr_fn_t *) val;
-    return fn();
+    uschar* s = fn();
+    return s ? s : US"";
     }
 
   case vtype_pspace:
@@ -6186,11 +6187,12 @@ while (*s != 0)
         case 2:
         case 3: goto EXPAND_FAILED;
         }
-      for (uschar sep = *sub[0], c; c = *sub[1]; sub[1]++)
+      if (*sub[1]) for (uschar sep = *sub[0], c; c = *sub[1]; sub[1]++)
        {
        if (c == sep) yield = string_catn(yield, sub[1], 1);
        yield = string_catn(yield, sub[1], 1);
        }
+      else yield = string_catn(yield, US" ", 1);
       continue;
       }
 
index 1a4e3c8ed56b923cd834c53530c0e56cb3e7bbc3..1b2333053f62ad4b379cd6379b29ada40b23bea0 100644 (file)
@@ -1499,6 +1499,10 @@ uschar *spf_header_comment     = NULL;
 uschar *spf_received           = NULL;
 uschar *spf_result             = NULL;
 uschar *spf_smtp_comment       = NULL;
+uschar *spf_smtp_comment_template
+                    /* Used to be: "Please%_see%_http://www.open-spf.org/Why?id=%{S}&ip=%{C}&receiver=%{R}" */
+                               = US"Please%_see%_http://www.open-spf.org/Why";
+
 #endif
 
 FILE   *spool_data_file               = NULL;
index 3dfbbc2b1889294537e7bcc2e79a789cbc00ad41..0c85c11501976d9e53d2cab033425d857906cbc8 100644 (file)
@@ -92,7 +92,7 @@ typedef struct {
   uschar *cipher;             /* Cipher used */
   const uschar *cipher_stdname; /* Cipher used, RFC version */
   const uschar *ver;         /* TLS version */
-  
+
   BOOL    on_connect;         /* For older MTAs that don't STARTTLS */
   uschar *on_connect_ports;   /* Ports always tls-on-connect */
   void   *ourcert;            /* Certificate we presented, binary */
@@ -983,6 +983,8 @@ extern uschar *spf_received;           /* Received-SPF: header */
 extern uschar *spf_result;             /* spf result in string form */
 extern BOOL    spf_result_guessed;     /* spf result is of best-guess operation */
 extern uschar *spf_smtp_comment;       /* spf comment to include in SMTP reply */
+extern uschar *spf_smtp_comment_template;
+                                       /* template to construct the spf comment by libspf2 */
 #endif
 extern BOOL    split_spool_directory;  /* TRUE to use multiple subdirs */
 extern FILE   *spool_data_file;               /* handle for -D file */
index dad69dcc0696bd32dc02184c7f1d3b3329d6dac9..2e87edadd5bf61605311972f9147f2271264195f 100644 (file)
@@ -135,6 +135,8 @@ DEFER. The arguments are:
                       If set to a nonzero number of seconds, the cached value
                       becomes unusable after this time. Currently the dnsdb
                       lookup uses this to support the TTL value.
+  uschar *opts       options, a comma-separated list of tagged values for
+                      modifying the search operation
 
 Even though the key is zero-terminated, the length is passed because in the
 common case it has been computed already and is often needed.
index 7b474f51d4300ba4a7485f9b3916688a174554b5..a8f13350a8567a179abcb4778dd8f4cec1abac5d 100644 (file)
@@ -326,6 +326,7 @@ static optionlist optionlist_config[] = {
 #endif
 #ifdef SUPPORT_SPF
   { "spf_guess",                opt_stringptr,   {&spf_guess} },
+  { "spf_smtp_comment_template",opt_stringptr,   {&spf_smtp_comment_template} },
 #endif
   { "split_spool_directory",    opt_bool,        {&split_spool_directory} },
   { "spool_directory",          opt_stringptr,   {&spool_directory} },
index ce27c5f3e520b267f280e2bb227ab0c8903a1284..8b0902b5d9fe0224a1ba1b52e72f87f19482287f 100644 (file)
@@ -1816,6 +1816,29 @@ return g;
 }
 #endif
 
+
+
+static gstring *
+s_connhad_log(gstring * g)
+{
+uschar * sep = smtp_connection_had[SMTP_HBUFF_SIZE-1] != SCH_NONE
+  ? US" C=..." : US" C=";
+
+for (int i = smtp_ch_index; i < SMTP_HBUFF_SIZE; i++)
+  if (smtp_connection_had[i] != SCH_NONE)
+    {
+    g = string_append(g, 2, sep, smtp_names[smtp_connection_had[i]]);
+    sep = US",";
+    }
+for (int i = 0; i < smtp_ch_index; i++)
+  {
+  g = string_append(g, 2, sep, smtp_names[smtp_connection_had[i]]);
+  sep = US",";
+  }
+return g;
+}
+
+
 /*************************************************
 *      Log lack of MAIL if so configured         *
 *************************************************/
@@ -1831,7 +1854,7 @@ Returns:     nothing
 void
 smtp_log_no_mail(void)
 {
-uschar * sep, * s;
+uschar * s;
 gstring * g = NULL;
 
 if (smtp_mailcmd_count > 0 || !LOGGING(smtp_no_mail))
@@ -1847,20 +1870,7 @@ if (sender_host_authenticated)
 g = s_tlslog(g);
 #endif
 
-sep = smtp_connection_had[SMTP_HBUFF_SIZE-1] != SCH_NONE ?  US" C=..." : US" C=";
-
-for (int i = smtp_ch_index; i < SMTP_HBUFF_SIZE; i++)
-  if (smtp_connection_had[i] != SCH_NONE)
-    {
-    g = string_append(g, 2, sep, smtp_names[smtp_connection_had[i]]);
-    sep = US",";
-    }
-
-for (int i = 0; i < smtp_ch_index; i++)
-  {
-  g = string_append(g, 2, sep, smtp_names[smtp_connection_had[i]]);
-  sep = US",";
-  }
+g = s_connhad_log(g);
 
 if (!(s = string_from_gstring(g))) s = US"";
 
@@ -3103,15 +3113,17 @@ synprot_error(int type, int code, uschar *data, uschar *errmess)
 int yield = -1;
 
 log_write(type, LOG_MAIN, "SMTP %s error in \"%s\" %s %s",
-  (type == L_smtp_syntax_error)? "syntax" : "protocol",
+  type == L_smtp_syntax_error ? "syntax" : "protocol",
   string_printing(smtp_cmd_buffer), host_and_ident(TRUE), errmess);
 
 if (++synprot_error_count > smtp_max_synprot_errors)
   {
   yield = 1;
   log_write(0, LOG_MAIN|LOG_REJECT, "SMTP call from %s dropped: too many "
-    "syntax or protocol errors (last command was \"%s\")",
-    host_and_ident(FALSE), string_printing(smtp_cmd_buffer));
+    "syntax or protocol errors (last command was \"%s\", %s)",
+    host_and_ident(FALSE), string_printing(smtp_cmd_buffer),
+    string_from_gstring(s_connhad_log(NULL))
+    );
   }
 
 if (code > 0)
@@ -4159,8 +4171,10 @@ while (done <= 0)
        if (++synprot_error_count > smtp_max_synprot_errors)
          {
          log_write(0, LOG_MAIN|LOG_REJECT, "SMTP call from %s dropped: too many "
-           "syntax or protocol errors (last command was \"%s\")",
-           host_and_ident(FALSE), string_printing(smtp_cmd_buffer));
+           "syntax or protocol errors (last command was \"%s\", %s)",
+           host_and_ident(FALSE), string_printing(smtp_cmd_buffer),
+           string_from_gstring(s_connhad_log(NULL))
+           );
          done = 1;
          }
 
index f120f722c81106274966517b09423ca6c920f2e0..3e121678ca5611b34e9f025eb735b919287a005c 100644 (file)
@@ -91,7 +91,7 @@ switch (dns_rc = dns_lookup(dnsa, US domain, rr_type, NULL))
   case DNS_NODATA:     srr.herrno = NO_DATA;           break;
   case DNS_FAIL:
   default:             srr.herrno = NO_RECOVERY;       break;
-  } 
+  }
 
 for (dns_record * rr = dns_next_rr(dnsa, &dnss, RESET_ANSWERS); rr;
      rr = dns_next_rr(dnsa, &dnss, RESET_NEXT))
@@ -218,6 +218,7 @@ spf_init(void)
 {
 SPF_dns_server_t * dc;
 int debug = 0;
+const uschar *s;
 
 DEBUG(D_receive) debug = 1;
 
@@ -240,11 +241,16 @@ if (!(spf_server = SPF_server_new_dns(dc, debug)))
   DEBUG(D_receive) debug_printf("spf: SPF_server_new() failed.\n");
   return FALSE;
   }
-  /* Quick hack to override the outdated explanation URL.
-  See https://www.mail-archive.com/mailop@mailop.org/msg08019.html */
-  SPF_server_set_explanation(spf_server, "Please%_see%_http://www.open-spf.org/Why?id=%{S}&ip=%{C}&receiver=%{R}", &spf_response);
-  if (SPF_response_errcode(spf_response) != SPF_E_SUCCESS)
-    log_write(0, LOG_MAIN|LOG_PANIC_DIE, "%s", SPF_strerror(SPF_response_errcode(spf_response)));
+  /* Override the outdated explanation URL.
+  See https://www.mail-archive.com/mailop@mailop.org/msg08019.html
+  Used to work as "Please%_see%_http://www.open-spf.org/Why?id=%{S}&ip=%{C}&receiver=%{R}",
+  but is broken now (May 18th, 2020) */
+if (!(s = expand_string(spf_smtp_comment_template)))
+  log_write(0, LOG_MAIN|LOG_PANIC_DIE, "expansion of spf_smtp_comment_template failed");
+
+SPF_server_set_explanation(spf_server, s, &spf_response);
+if (SPF_response_errcode(spf_response) != SPF_E_SUCCESS)
+  log_write(0, LOG_MAIN|LOG_PANIC_DIE, "%s", SPF_strerror(SPF_response_errcode(spf_response)));
 
 return TRUE;
 }
index 673768a56fd034b1b244fdb7c65e376a4a9c5981..a1d299b69d39fc7827d9a5a25e7c422e01254f2b 100644 (file)
@@ -3458,6 +3458,7 @@ int inbytes;
 DEBUG(D_tls) debug_printf("Calling SSL_read(%p, %p, %u)\n", server_ssl,
   ssl_xfer_buffer, ssl_xfer_buffer_size);
 
+ERR_clear_error();
 if (smtp_receive_timeout > 0) ALARM(smtp_receive_timeout);
 inbytes = SSL_read(server_ssl, CS ssl_xfer_buffer,
                  MIN(ssl_xfer_buffer_size, lim));
@@ -3607,6 +3608,7 @@ int error;
 DEBUG(D_tls) debug_printf("Calling SSL_read(%p, %p, %u)\n", ssl,
   buff, (unsigned int)len);
 
+ERR_clear_error();
 inbytes = SSL_read(ssl, CS buff, len);
 error = SSL_get_error(ssl, inbytes);
 
@@ -3696,6 +3698,7 @@ if ((more || corked))
 for (int left = len; left > 0;)
   {
   DEBUG(D_tls) debug_printf("SSL_write(%p, %p, %d)\n", ssl, buff, left);
+  ERR_clear_error();
   outbytes = SSL_write(ssl, CS buff, left);
   error = SSL_get_error(ssl, outbytes);
   DEBUG(D_tls) debug_printf("outbytes=%d error=%d\n", outbytes, error);
index 5a964276e86a73196bc547ad6fe60f9e1adf14df..98a93b63b4b075064146f5ceba158ce53ad2cdf1 100644 (file)
@@ -12,7 +12,7 @@ hostlist   relay_hosts = net-mysql;select * from them where id='$sender_host_add
 acl_smtp_rcpt = check_recipient
 
 PARTIAL = 127.0.0.1::PORT_N
-SSPEC = PARTIAL/test/root/
+SSPEC = PARTIAL/test/root/pass
 mysql_servers = SSPEC
 
 
index 5c7e7298a7be266085f69308cba30869cc578b67..bdcfbce1f967658abf49fce6e24ea439d5520c04 100644 (file)
@@ -10,11 +10,13 @@ primary_hostname = myhost.test.ex
 
 acl_smtp_rcpt = check_recipient
 
+.ifdef TRUSTED
 tls_certificate = ${if eq {SERVER}{server}{DIR/aux-fixed/cert1}fail}
 tls_privatekey = ${if eq {SERVER}{server}{DIR/aux-fixed/cert1}fail}
 
 tls_verify_hosts = HOSTIPV4
 tls_verify_certificates = ${if eq {SERVER}{server}{DIR/aux-fixed/cert2}fail}
+.endif
 
 queue_only
 
index 5a2a8915545658dd9e2e5f1460da1c7ec6de750a..4ca61142b89986566d53d2fb997cff9d1b2bf75c 100644 (file)
@@ -2,5 +2,5 @@
 1999-03-02 09:44:33 rejected HELO from CALLER: syntactically invalid argument(s): (no argument given)
 1999-03-02 09:44:33 rejected HELO from CALLER: syntactically invalid argument(s): (no argument given)
 1999-03-02 09:44:33 rejected HELO from CALLER: syntactically invalid argument(s): (no argument given)
-1999-03-02 09:44:33 SMTP call from CALLER dropped: too many syntax or protocol errors (last command was "helo")
-1999-03-02 09:44:33 SMTP call from CALLER dropped: too many syntax or protocol errors (last command was "mail from:<>")
+1999-03-02 09:44:33 SMTP call from CALLER dropped: too many syntax or protocol errors (last command was "helo",  C=HELO,HELO,HELO,HELO)
+1999-03-02 09:44:33 SMTP call from CALLER dropped: too many syntax or protocol errors (last command was "mail from:<>",  C=MAIL,MAIL,MAIL)
index 0922615b32f17cd1a503e6373c295afac3890d8d..119b2d264190058a52907328336ccec963c21f51 100644 (file)
@@ -12,4 +12,4 @@
 1999-03-02 09:44:33 10HmaZ-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local-esmtp S=sss M8S=8
 1999-03-02 09:44:33 10HmaZ-0005vi-00 => userx <userx@test.ex> R=r2 T=local_delivery
 1999-03-02 09:44:33 10HmaZ-0005vi-00 Completed
-1999-03-02 09:44:33 SMTP call from CALLER dropped: too many syntax or protocol errors (last command was "foo")
+1999-03-02 09:44:33 SMTP call from CALLER dropped: too many syntax or protocol errors (last command was "foo",  C=EHLO,MAIL,RCPT,DATA)
index af07e730cf1a3cd95bc94a533bd8c6d3fea9125a..e4bb6a243159033bd610dd5327611d6a93ad5ae2 100644 (file)
@@ -11,5 +11,5 @@
 1999-03-02 09:44:33 SMTP connection from (tester) [127.0.0.1] lost while reading message data
 1999-03-02 09:44:33 10HmbD-0005vi-00 <= someone8@some.domain H=(tester) [127.0.0.1] P=esmtp K S=sss for CALLER@test.ex
 1999-03-02 09:44:33 SMTP protocol synchronization error (next input sent too soon: pipelining was not advertised): rejected "BDAT 1" H=(tester) [127.0.0.1] next input="BDAT 87 last\r\no: Susan@random.co"...
-1999-03-02 09:44:33 SMTP call from (tester) [127.0.0.1] dropped: too many syntax or protocol errors (last command was "From: Sam@random.com")
+1999-03-02 09:44:33 SMTP call from (tester) [127.0.0.1] dropped: too many syntax or protocol errors (last command was "From: Sam@random.com",  C=EHLO,MAIL,RCPT,BDAT)
 1999-03-02 09:44:33 SMTP connection from (tester) [127.0.0.1] lost while reading message data (header)
index 1e8af6531879b5fc5f60665d5fd09dc9a5af7ef1..de8432e4934475b331860b4adb552fac1e43ed61 100644 (file)
@@ -18,7 +18,7 @@
 1999-03-02 09:44:33 Authentication-Results: myhost.test.ex;\n  spf=pass smtp.mailfrom=example.com
 1999-03-02 09:44:33 spf_result         neutral (guess <yes>)
 1999-03-02 09:44:33 spf_header_comment myhost.test.ex: ip4.ip4.ip4.ip4 is neither permitted nor denied by domain of test.example.com
-1999-03-02 09:44:33 spf_smtp_comment   Please see http://www.open-spf.org/Why?id=b%40test.example.com&ip=ip4.ip4.ip4.ip4&receiver=myhost.test.ex : Reason: mechanism
+1999-03-02 09:44:33 spf_smtp_comment   Please see http://www.open-spf.org/Why : Reason: mechanism
 1999-03-02 09:44:33 spf_received       Received-SPF: neutral (myhost.test.ex: ip4.ip4.ip4.ip4 is neither permitted nor denied by domain of test.example.com) client-ip=ip4.ip4.ip4.ip4; envelope-from=b@test.example.com; helo=testclient;
 1999-03-02 09:44:33 Authentication-Results: myhost.test.ex;\n  spf=neutral (best guess record for domain) smtp.mailfrom=test.example.com
 1999-03-02 09:44:33 H=(testclient) [ip4.ip4.ip4.ip4] F=<b@test.example.com> rejected RCPT <fred@test.ex>
index 5a2a8915545658dd9e2e5f1460da1c7ec6de750a..4ca61142b89986566d53d2fb997cff9d1b2bf75c 100644 (file)
@@ -2,5 +2,5 @@
 1999-03-02 09:44:33 rejected HELO from CALLER: syntactically invalid argument(s): (no argument given)
 1999-03-02 09:44:33 rejected HELO from CALLER: syntactically invalid argument(s): (no argument given)
 1999-03-02 09:44:33 rejected HELO from CALLER: syntactically invalid argument(s): (no argument given)
-1999-03-02 09:44:33 SMTP call from CALLER dropped: too many syntax or protocol errors (last command was "helo")
-1999-03-02 09:44:33 SMTP call from CALLER dropped: too many syntax or protocol errors (last command was "mail from:<>")
+1999-03-02 09:44:33 SMTP call from CALLER dropped: too many syntax or protocol errors (last command was "helo",  C=HELO,HELO,HELO,HELO)
+1999-03-02 09:44:33 SMTP call from CALLER dropped: too many syntax or protocol errors (last command was "mail from:<>",  C=MAIL,MAIL,MAIL)
index 7a420d042386720a7d466b8499c700ce0a0f3301..bb4af83efc46d6a7e090fbde344de9d6b2e4556c 100644 (file)
@@ -1,3 +1,3 @@
 1999-03-02 09:44:33 U=CALLER F=<x@y> rejected RCPT <userx@test.ex>: SIZE value too big
 1999-03-02 09:44:33 U=CALLER F=<x@y> rejected RCPT <userx@test.ex>: SIZE value too big
-1999-03-02 09:44:33 SMTP call from CALLER dropped: too many syntax or protocol errors (last command was "foo")
+1999-03-02 09:44:33 SMTP call from CALLER dropped: too many syntax or protocol errors (last command was "foo",  C=EHLO,MAIL,RCPT,DATA)
index a4185a966bc0f0c3db1f3c893b131e2cae1bb997..79ecb9650e0c5400d46a024518feeba4982a2844 100644 (file)
@@ -3,6 +3,6 @@
 1999-03-02 09:44:33 SMTP protocol synchronization error (next input sent too soon: pipelining was not advertised): rejected "BDAT 1" H=(tester) [127.0.0.1] next input="BDAT 87 last\r\no: Susan@random.co"...
 Envelope-from: <someone9@some.domain>
 Envelope-to: <CALLER@test.ex>
-1999-03-02 09:44:33 SMTP call from (tester) [127.0.0.1] dropped: too many syntax or protocol errors (last command was "From: Sam@random.com")
+1999-03-02 09:44:33 SMTP call from (tester) [127.0.0.1] dropped: too many syntax or protocol errors (last command was "From: Sam@random.com",  C=EHLO,MAIL,RCPT,BDAT)
 Envelope-from: <someone9@some.domain>
 Envelope-to: <CALLER@test.ex>
index 1e206f5d0a50615fad15a8afd76854d6ecb484ba..e4cf7ad6da5f65e79d0356dd479d56823d9e850a 100755 (executable)
@@ -1324,6 +1324,9 @@ RESET_AFTER_EXTRA_LINE_READ:
     next if /^Waiting for MySQL server to answer/;
     next if /mysqladmin: CREATE DATABASE failed; .* database exists/;
 
+    # Postgres version-dependent differences
+    s/^initdb: warning: (enabling "trust" authentication for local connections)$/\nWARNING: $1/;
+
     # Not all builds include DMARC
     next if /^DMARC: no (dmarc_tld_file|sender_host_address)$/ ;
 
index db8d709811c1b4ba7e16ca10f3448552e9d49e24..a8fc0bcb274770b166eb3496a73e8a64950b4240 100644 (file)
@@ -133,6 +133,7 @@ listquote: ${listquote{:}{ab::cd}}
 listquote: ${listquote{;}{ab:cd}}
 listquote: ${listquote{;}{ab;cd}}
 listquote: ${listquote{ }{ ab cd}}
+listquote: <${listquote{:}{}}>
 
 sort: ${sort{3:2:1:4}{<}{$item}}
 sort: ${sort {<, 3,2,1,4}{>}{$item}}
index c9e0d5977ab95e0a112a5d904091580f5691a7d2..ec7b4548f5ccd41d7a8020839e97d3f28b8e1d5f 100644 (file)
@@ -10,28 +10,40 @@ system 'mysql_install_db --no-defaults --datadir=DIR/mysql --user=CALLER';
 ****
 sudo rm test-stdout test-stderr
 #
-# start a db server
+### start a db server
 echo Starting DB server
 background
 DIR/bin.sys/mysqld --datadir=DIR/mysql --log-error=DIR/mysql/log --bind-address=* --port=PORT_N --socket=DIR/mysql/sock --pid-file=DIR/mysql/pidfile
 ****
 #
-# wait for db startup, insert some data
+### wait for db startup, set password on the root user
 echo Waiting for DB server startup
+sudo perl
+system 'mysql --protocol=socket --socket=`pwd`/mysql/sock --connect_timeout=10 -u root -e "set password = password(\"pass\")"';
+****
+#
+### create testdb and extra users
+echo Create testdb and extra users
 perl
-system 'mysqladmin --protocol=TCP -P PORT_N --connect_timeout=2 --wait=5 -u root create test';
+system 'mysqladmin --protocol=TCP -P PORT_N -u root -ppass create test';
 my $fh;
-open($fh, '-|', 'mysql --protocol=TCP -P PORT_N -u root -D test -e "select 1 from mysql.user where User = \'root\' and Host = \'HOSTIPV4\'"');
+open($fh, '-|', 'mysql --protocol=TCP -P PORT_N -u root -ppass -D test -e "select 1 from mysql.user where User = \'root\' and Host = \'HOSTIPV4\'"');
 my $line = <$fh>;
 if (length($line) == 0) {
-  system 'mysql --protocol=TCP -P PORT_N -u root -D test -e "create user \'root\'@\'HOSTIPV4\'"';
+  system 'mysql --protocol=TCP -P PORT_N -u root -ppass -D test -e "create user \'root\'@\'HOSTIPV4\'"';
 }
-open($fh, '-|', 'mysql --protocol=TCP -P PORT_N -u root -D test -e "select 1 from mysql.user where User = \'CALLER\' and Host = \'HOSTIPV4\'"');
+open($fh, '-|', 'mysql --protocol=TCP -P PORT_N -u root -ppass -D test -e "select 1 from mysql.user where User = \'CALLER\' and Host = \'HOSTIPV4\'"');
 $line = <$fh>;
 if (length($line) == 0) {
-  system 'mysql --protocol=TCP -P PORT_N -u root -D test -e "create user \'CALLER\'@\'HOSTIPV4\'"';
+  system 'mysql --protocol=TCP -P PORT_N -u root -ppass -D test -e "create user \'CALLER\'@\'HOSTIPV4\'"';
 }
-system 'mysql --protocol=TCP -P PORT_N -u root -D test \
+****
+#
+#
+# wait for db startup, insert some data
+echo Insert some data
+perl
+system 'mysql --protocol=TCP -P PORT_N -u root -ppass -D test \
  -e "CREATE TABLE them ( name text, id text ); \
      INSERT INTO them VALUES ( \'Philip Hazel\', \'ph10\' ); \
      INSERT INTO them VALUES ( \'Aristotle\',    \'aaaa\' ); \
@@ -63,7 +75,7 @@ ${lookup mysql {servers=x:127.0.0.1::PORT_N; select name from them where id='ph1
 ${lookup mysql {servers=127.0.0.1::PORT_N:x; select name from them where id='ph10';}}
 ${lookup mysql {servers=127.0.0.1::PORT_N/test/root/:x; select name from them where id='ph10';}}
 ${lookup mysql {servers=HOSTIPV4::PORT_N/test/root/:127.0.0.1::PORT_N; select name from them where id='ph10';}}
-${lookup mysql {servers=localhost(DIR/mysql/sock)/test/root/; select name from them where id='ph10';}}
+${lookup mysql {servers=localhost(DIR/mysql/sock)/test/root/pass; select name from them where id='ph10';}}
 x
 ${lookup mysql {SELECT name FROM them WHERE id IN ('ph10', 'aaaa');}}
 ${lookup mysql {SELECT *    FROM them WHERE id IN ('ph10', 'aaaa');}}
@@ -80,7 +92,7 @@ Test message
 ****
 #
 perl
-system 'mysqladmin --protocol=TCP -P PORT_N -u root shutdown';
+system 'mysqladmin --protocol=TCP -P PORT_N -u root -ppass shutdown';
 ****
 killdaemon
 sudo rm -fr DIR/mysql
index 1911c67f21608ac37ebb36f80f76e0018f6ae3f9..dee833923492f5ee596b6e71bd2935778e0cf147 100644 (file)
@@ -7,4 +7,4 @@
 >>> host in helo_try_verify_hosts? no (option unset)
 >>> host in helo_accept_junk_hosts? no (option unset)
 >>> xxxx in helo_lookup_domains? no (end of list)
-LOG: SMTP call from (xxxx) [V4NET.0.0.1] dropped: too many syntax or protocol errors (last command was "rcpt to:<bad syntax@x.y.z>")
+LOG: SMTP call from (xxxx) [V4NET.0.0.1] dropped: too many syntax or protocol errors (last command was "rcpt to:<bad syntax@x.y.z>",  C=HELO,MAIL,RCPT,RCPT,RCPT,RCPT)
index 4cc8801f710ef37e81762bcf611c3c01ea7546a3..657f115e9cf4104db9d57dd1d677d2e21422cac5 100644 (file)
@@ -1,3 +1,6 @@
+### start a db server
+### wait for db startup, set password on the root user
+### create testdb and extra users
 Exim version x.yz ....
 configuration file is TESTSUITE/test-config
 admin user
@@ -172,12 +175,12 @@ dropping to exim gid; retaining priv uid
  search_open: mysql "NULL"
    cached open
  search_find: file="NULL"
-   key="servers=localhost(TESTSUITE/mysql/sock)/test/root/; select name from them where id='ph10';" partial=-1 affix=NULL starflags=0 opts=NULL
+   key="servers=localhost(TESTSUITE/mysql/sock)/test/root/pass; select name from them where id='ph10';" partial=-1 affix=NULL starflags=0 opts=NULL
  LRU list:
  internal_search_find: file="NULL"
-   type=mysql key="servers=localhost(TESTSUITE/mysql/sock)/test/root/; select name from them where id='ph10';" opts=NULL
- database lookup required for servers=localhost(TESTSUITE/mysql/sock)/test/root/; select name from them where id='ph10';
- MySQL query: "servers=localhost(TESTSUITE/mysql/sock)/test/root/; select name from them where id='ph10';" opts 'NULL'
+   type=mysql key="servers=localhost(TESTSUITE/mysql/sock)/test/root/pass; select name from them where id='ph10';" opts=NULL
+ database lookup required for servers=localhost(TESTSUITE/mysql/sock)/test/root/pass; select name from them where id='ph10';
+ MySQL query: "servers=localhost(TESTSUITE/mysql/sock)/test/root/pass; select name from them where id='ph10';" opts 'NULL'
  MYSQL new connection: host=localhost port=0 socket=TESTSUITE/mysql/sock database=test user=root
  creating new cache entry
  lookup yielded: Philip Hazel
@@ -275,17 +278,17 @@ check set acl_m0 = ok:   ${lookup mysql                    {select name from the
  search_open: mysql "NULL"
    cached open
  search_find: file="NULL"
-   key="select name from them where id = 'c'" partial=-1 affix=NULL starflags=0 opts="servers=127.0.0.1::1223/test/root/"
+   key="select name from them where id = 'c'" partial=-1 affix=NULL starflags=0 opts="servers=127.0.0.1::1223/test/root/pass"
  LRU list:
  internal_search_find: file="NULL"
-   type=mysql key="select name from them where id = 'c'" opts="servers=127.0.0.1::1223/test/root/"
+   type=mysql key="select name from them where id = 'c'" opts="servers=127.0.0.1::1223/test/root/pass"
  cached data found but wrong opts;  database lookup required for select name from them where id = 'c'
- MySQL query: "select name from them where id = 'c'" opts 'servers=127.0.0.1::1223/test/root/'
+ MySQL query: "select name from them where id = 'c'" opts 'servers=127.0.0.1::1223/test/root/pass'
  MYSQL using cached connection for 127.0.0.1:1223/test/root
  MYSQL: no data found
  replacing old cache entry
  lookup failed
-check set acl_m0 = ok:   ${lookup mysql,servers=127.0.0.1::1223/test/root/      {select name from them where id = '$local_part'}}
+check set acl_m0 = ok:   ${lookup mysql,servers=127.0.0.1::1223/test/root/pass      {select name from them where id = '$local_part'}}
                  = ok:   
  search_open: mysql "NULL"
    cached open
@@ -305,16 +308,16 @@ check set acl_m0 = ok:   ${lookup mysql,servers=127.0.0.1::1223    {select name
  search_open: mysql "NULL"
    cached open
  search_find: file="NULL"
-   key="servers=127.0.0.1::1223/test/root/; select name from them where id = 'c'" partial=-1 affix=NULL starflags=0 opts=NULL
+   key="servers=127.0.0.1::1223/test/root/pass; select name from them where id = 'c'" partial=-1 affix=NULL starflags=0 opts=NULL
  LRU list:
  internal_search_find: file="NULL"
-   type=mysql key="servers=127.0.0.1::1223/test/root/; select name from them where id = 'c'" opts=NULL
- database lookup required for servers=127.0.0.1::1223/test/root/; select name from them where id = 'c'
- MySQL query: "servers=127.0.0.1::1223/test/root/; select name from them where id = 'c'" opts 'NULL'
- lookup deferred: MySQL server "127.0.0.1:1223/test/root/" is tainted
+   type=mysql key="servers=127.0.0.1::1223/test/root/pass; select name from them where id = 'c'" opts=NULL
+ database lookup required for servers=127.0.0.1::1223/test/root/pass; select name from them where id = 'c'
+ MySQL query: "servers=127.0.0.1::1223/test/root/pass; select name from them where id = 'c'" opts 'NULL'
+ lookup deferred: MySQL server "127.0.0.1:1223/test/root/pass" is tainted
 warn: condition test deferred in ACL "check_recipient"
 LOG: MAIN
-  H=[10.0.0.0] Warning: ACL "warn" statement skipped: condition test deferred: MySQL server "127.0.0.1:1223/test/root/" is tainted
+  H=[10.0.0.0] Warning: ACL "warn" statement skipped: condition test deferred: MySQL server "127.0.0.1:1223/test/root/pass" is tainted
 processing "warn" (TESTSUITE/test-config 36)
 check set acl_m0 = ok:   hostlist
 check hosts = net-mysql;select * from them where id='$local_part'
@@ -335,38 +338,38 @@ host in "net-mysql;select * from them where id='c'"? no (end of list)
 warn: condition test failed in ACL "check_recipient"
 processing "warn" (TESTSUITE/test-config 39)
 check set acl_m0 = FAIL: hostlist
-check hosts = <& net-mysql;servers=127.0.0.1::1223/test/root/; select * from them where id='$local_part'
+check hosts = <& net-mysql;servers=127.0.0.1::1223/test/root/pass; select * from them where id='$local_part'
 search_open: mysql "NULL"
   cached open
 search_find: file="NULL"
-  key="servers=127.0.0.1::1223/test/root/; select * from them where id='c'" partial=-1 affix=NULL starflags=0 opts=NULL
+  key="servers=127.0.0.1::1223/test/root/pass; select * from them where id='c'" partial=-1 affix=NULL starflags=0 opts=NULL
 LRU list:
 internal_search_find: file="NULL"
-  type=mysql key="servers=127.0.0.1::1223/test/root/; select * from them where id='c'" opts=NULL
-database lookup required for servers=127.0.0.1::1223/test/root/; select * from them where id='c'
-MySQL query: "servers=127.0.0.1::1223/test/root/; select * from them where id='c'" opts 'NULL'
-lookup deferred: MySQL server "127.0.0.1:1223/test/root/" is tainted
-host in "<& net-mysql;servers=127.0.0.1::1223/test/root/; select * from them where id='c'"? list match deferred for net-mysql;servers=127.0.0.1::1223/test/root/; select * from them where id='c'
+  type=mysql key="servers=127.0.0.1::1223/test/root/pass; select * from them where id='c'" opts=NULL
+database lookup required for servers=127.0.0.1::1223/test/root/pass; select * from them where id='c'
+MySQL query: "servers=127.0.0.1::1223/test/root/pass; select * from them where id='c'" opts 'NULL'
+lookup deferred: MySQL server "127.0.0.1:1223/test/root/pass" is tainted
+host in "<& net-mysql;servers=127.0.0.1::1223/test/root/pass; select * from them where id='c'"? list match deferred for net-mysql;servers=127.0.0.1::1223/test/root/pass; select * from them where id='c'
 warn: condition test deferred in ACL "check_recipient"
 LOG: MAIN
-  H=[10.0.0.0] Warning: ACL "warn" statement skipped: condition test deferred: MySQL server "127.0.0.1:1223/test/root/" is tainted
+  H=[10.0.0.0] Warning: ACL "warn" statement skipped: condition test deferred: MySQL server "127.0.0.1:1223/test/root/pass" is tainted
 processing "warn" (TESTSUITE/test-config 44)
 check set acl_m0 = FAIL: hostlist
-check hosts = <& net-mysql,servers=127.0.0.1::1223/test/root/; select * from them where id='$local_part'
+check hosts = <& net-mysql,servers=127.0.0.1::1223/test/root/pass; select * from them where id='$local_part'
 search_open: mysql "NULL"
   cached open
 search_find: file="NULL"
-  key=" select * from them where id='c'" partial=-1 affix=NULL starflags=0 opts="servers=127.0.0.1::1223/test/root/"
+  key=" select * from them where id='c'" partial=-1 affix=NULL starflags=0 opts="servers=127.0.0.1::1223/test/root/pass"
 LRU list:
 internal_search_find: file="NULL"
-  type=mysql key=" select * from them where id='c'" opts="servers=127.0.0.1::1223/test/root/"
+  type=mysql key=" select * from them where id='c'" opts="servers=127.0.0.1::1223/test/root/pass"
 database lookup required for  select * from them where id='c'
-MySQL query: " select * from them where id='c'" opts 'servers=127.0.0.1::1223/test/root/'
-lookup deferred: MySQL server "127.0.0.1:1223/test/root/" is tainted
-host in "<& net-mysql,servers=127.0.0.1::1223/test/root/; select * from them where id='c'"? list match deferred for net-mysql,servers=127.0.0.1::1223/test/root/; select * from them where id='c'
+MySQL query: " select * from them where id='c'" opts 'servers=127.0.0.1::1223/test/root/pass'
+lookup deferred: MySQL server "127.0.0.1:1223/test/root/pass" is tainted
+host in "<& net-mysql,servers=127.0.0.1::1223/test/root/pass; select * from them where id='c'"? list match deferred for net-mysql,servers=127.0.0.1::1223/test/root/pass; select * from them where id='c'
 warn: condition test deferred in ACL "check_recipient"
 LOG: MAIN
-  H=[10.0.0.0] Warning: ACL "warn" statement skipped: condition test deferred: MySQL server "127.0.0.1:1223/test/root/" is tainted
+  H=[10.0.0.0] Warning: ACL "warn" statement skipped: condition test deferred: MySQL server "127.0.0.1:1223/test/root/pass" is tainted
 processing "accept" (TESTSUITE/test-config 47)
 check domains = +local_domains
 d in "@"? no (end of list)
index ea918aebb7b92f89745e437f6af2dad9573b17c3..b8ff36122c53752ec4bc3a0499e206f2f90c1b54 100644 (file)
 > listquote: ab:cd
 > listquote: ab;;cd
 > listquote:   ab  cd
+> listquote: < >
 > 
 > sort: 1:2:3:4
 > sort: 4,3,2,1
index f0774a81a72f2c85172d3360b7aca5d2ea778d7e..fb89752f54d3bc31c2dd6836cd3f3a513c01ff41 100644 (file)
@@ -1,3 +1,6 @@
+### start a db server
+### wait for db startup, set password on the root user
+### create testdb and extra users
 > Philip Hazel
 > Philip Hazel
 > 
@@ -29,3 +32,8 @@ name=Aristotle id=aaaa
 250 OK\r
 550 relay not permitted\r
 221 myhost.test.ex closing connection\r
+
+******** SERVER ********
+### start a db server
+### wait for db startup, set password on the root user
+### create testdb and extra users