X-Git-Url: https://git.exim.org/users/heiko/exim.git/blobdiff_plain/83e8da8c07f783c7d677166940be3fc9b3f7d0ab..2c09c380e6ba3b1d694359e6ae2437d1a7a8ac81:/doc/doc-docbook/spec.xfpt diff --git a/doc/doc-docbook/spec.xfpt b/doc/doc-docbook/spec.xfpt index f1940bb1e..4f5c119f6 100644 --- a/doc/doc-docbook/spec.xfpt +++ b/doc/doc-docbook/spec.xfpt @@ -5905,13 +5905,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. @@ -6015,10 +6015,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 \ @@ -6663,6 +6663,13 @@ If the value of &$sender_host_address$& is 192.168.5.6, expansion of the first &%domains%& setting above generates the second setting, which therefore causes a second lookup to occur. +.new +The lookup type may optionally be followed by a comma +and a comma-separated list of options. +Each option is a &"name=value"& pair. +Whether an option is meaningful depands on the lookup type. +.wen + The rest of this chapter describes the different lookup types that are available. Any of them can be used in any part of the configuration where a lookup is permitted. @@ -6680,6 +6687,13 @@ 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. .wen .next .cindex "query-style lookup" "definition of" @@ -8024,8 +8038,8 @@ For MySQL, PostgreSQL and Redis lookups (but not currently for Oracle and InterB 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:...'& +.endd .wen Each item in the list may take one of two forms: .olist @@ -10156,6 +10170,18 @@ extracted is used. You can use &`fail`& instead of {<&'string3'&>} as in a string extract. +.new +.vitem &*${listquote{*&<&'separator'&>&*}{*&<&'string'&>&*}}*" +.citem quoting "for list" +.citem list quoting +This item doubles any occurrence of the separator character +in the given string. +An empty string is replaced with a single space. +This converts the string into a safe form for use as a list element, +in a list using the given separator. +.wen + + .vitem "&*${lookup{*&<&'key'&>&*}&~*&<&'search&~type'&>&*&~&&& {*&<&'file'&>&*}&~{*&<&'string1'&>&*}&~{*&<&'string2'&>&*}}*&" This is the first of one of two different types of lookup item, which are both @@ -10871,8 +10897,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}} \ { \ @@ -10881,6 +10906,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. @@ -11908,15 +11934,12 @@ request, for a password, so the data consists of just two strings. There can be problems if any of the strings are permitted to contain colon characters. In the usual way, these have to be doubled to avoid being taken as -separators. If the data is being inserted from a variable, the &%sg%& expansion -item can be used to double any existing colons. For example, the configuration +separators. +The &%listquote%& expansion item can be used for this. +For example, the configuration of a LOGIN authenticator might contain this setting: .code -server_condition = ${if pam{$auth1:${sg{$auth2}{:}{::}}}} -.endd -For a PLAIN authenticator you could use: -.code -server_condition = ${if pam{$auth2:${sg{$auth3}{:}{::}}}} +server_condition = ${if pam{$auth1:${listquote{:}{$auth2}}}} .endd In some operating systems, PAM authentication can be done only from a process running as root. Since Exim is running as the Exim user when receiving @@ -12311,13 +12334,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 &<>&. - .vitem &$dkim_verify_status$& Results of DKIM verification. For details see section &<>&. @@ -12350,6 +12366,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 &<>&. +.vitem &$dmarc_domain_policy$& &&& + &$dmarc_status$& &&& + &$dmarc_status_text$& &&& + &$dmarc_used_domains$& +Results of DMARC verification. +For details see section &<>&. + .vitem &$dnslist_domain$& &&& &$dnslist_matched$& &&& &$dnslist_text$& &&& @@ -12521,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" @@ -12873,9 +12896,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. @@ -14564,6 +14587,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 @@ -14650,6 +14674,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" @@ -15454,6 +15481,14 @@ the ACL once for each signature in the message. See section &<>&. +.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 &<>& 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 @@ -17736,6 +17771,48 @@ See section &<>& for more details. This option is available when Exim is compiled with SPF support. See section &<>& for more details. +.new +.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. +.wen .option split_spool_directory main boolean false @@ -30227,8 +30304,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. @@ -31464,7 +31541,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. @@ -31608,8 +31685,8 @@ section &<>& (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*& @@ -31791,8 +31868,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 @@ -31833,8 +31910,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 @@ -31898,13 +31975,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 @@ -31977,7 +32054,7 @@ very meaningful. See section &<>& 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 @@ -32163,12 +32240,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 @@ -32358,12 +32435,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 @@ -32473,16 +32550,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 @@ -33071,16 +33148,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 @@ -33617,13 +33694,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: @@ -33632,13 +33709,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 @@ -33767,8 +33844,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 @@ -33800,9 +33877,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 @@ -33860,8 +33937,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%&. @@ -33879,9 +33956,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 @@ -34085,10 +34162,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$& @@ -34141,8 +34218,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 @@ -40873,10 +40950,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; @@ -40888,10 +40965,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 @@ -40975,13 +41052,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: @@ -41016,8 +41096,13 @@ 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". +.new + The string is generated by the SPF library from the template configured in the main config + option &%spf_smtp_comment_template%&. +.wen .endlist @@ -41390,8 +41475,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