From time to time, experimental features may be added to Exim. While a feature is experimental, there will be a build-time option whose name starts "EXPERIMENTAL_" that must be set in order to include the feature. This file contains information about experimental features, all of which are unstable and liable to incompatible change. DCC Support -------------------------------------------------------------- Distributed Checksum Clearinghouse; http://www.rhyolite.com/dcc/ *) Building exim In order to build exim with DCC support add EXPERIMENTAL_DCC=yes to your Makefile. (Re-)build/install exim. exim -d should show EXPERIMENTAL_DCC under "Support for". *) Configuration In the main section of exim.cf add at least dccifd_address = /usr/local/dcc/var/dccifd or dccifd_address = In the DATA ACL you can use the new condition dcc = * After that "$dcc_header" contains the X-DCC-Header. Return values are: fail for overall "R", "G" from dccifd defer for overall "T" from dccifd accept for overall "A", "S" from dccifd dcc = */defer_ok works as for spamd. The "$dcc_result" variable contains the overall result from DCC answer. There will an X-DCC: header added to the mail. Usually you'll use defer !dcc = * to greylist with DCC. If you set, in the main section, dcc_direct_add_header = true then the dcc header will be added "in deep" and if the spool file was already written it gets removed. This forces Exim to write it again if needed. This helps to get the DCC Header through to eg. SpamAssassin. If you want to pass even more headers in the middle of the DATA stage you can set $acl_m_dcc_add_header to tell the DCC routines to add more information; eg, you might set this to some results from ClamAV. Be careful. Header syntax is not checked and is added "as is". In case you've troubles with sites sending the same queue items from several hosts and fail to get through greylisting you can use $acl_m_dcc_override_client_ip Setting $acl_m_dcc_override_client_ip to an IP address overrides the default of $sender_host_address. eg. use the following ACL in DATA stage: warn set acl_m_dcc_override_client_ip = \ ${lookup{$sender_helo_name}nwildlsearch{/etc/mail/multipleip_sites}{$value}{}} condition = ${if def:acl_m_dcc_override_client_ip} log_message = dbg: acl_m_dcc_override_client_ip set to \ $acl_m_dcc_override_client_ip Then set something like # cat /etc/mail/multipleip_sites mout-xforward.gmx.net 82.165.159.12 mout.gmx.net 212.227.15.16 Use a reasonable IP. eg. one the sending cluster actually uses. DSN extra information --------------------- If compiled with EXPERIMENTAL_DSN_INFO extra information will be added to DSN fail messages ("bounces"), when available. The intent is to aid tracing of specific failing messages, when presented with a "bounce" complaint and needing to search logs. The remote MTA IP address, with port number if nonstandard. Example: Remote-MTA: X-ip; [127.0.0.1]:587 Rationale: Several addresses may correspond to the (already available) dns name for the remote MTA. The remote MTA connect-time greeting. Example: X-Remote-MTA-smtp-greeting: X-str; 220 the.local.host.name ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000 Rationale: This string sometimes presents the remote MTA's idea of its own name, and sometimes identifies the MTA software. The remote MTA response to HELO or EHLO. Example: X-Remote-MTA-helo-response: X-str; 250-the.local.host.name Hello localhost [127.0.0.1] Limitations: Only the first line of a multiline response is recorded. Rationale: This string sometimes presents the remote MTA's view of the peer IP connecting to it. The reporting MTA detailed diagnostic. Example: X-Exim-Diagnostic: X-str; SMTP error from remote mail server after RCPT TO:: 550 hard error Rationale: This string sometimes give extra information over the existing (already available) Diagnostic-Code field. Note that non-RFC-documented field names and data types are used. Queuefile transport ------------------- Queuefile is a pseudo transport which does not perform final delivery. It simply copies the exim spool files out of the spool directory into an external directory retaining the exim spool format. The spool files can then be processed by external processes and then requeued into exim spool directories for final delivery. However, note carefully the warnings in the main documentation on qpool file formats. The motivation/inspiration for the transport is to allow external processes to access email queued by exim and have access to all the information which would not be available if the messages were delivered to the process in the standard email formats. The mailscanner package is one of the processes that can take advantage of this transport to filter email. The transport can be used in the same way as the other existing transports, i.e by configuring a router to route mail to a transport configured with the queuefile driver. The transport only takes one option: * directory - This is used to specify the directory messages should be copied to. Expanded. The generic transport options (body_only, current_directory, disable_logging, debug_print, delivery_date_add, envelope_to_add, event_action, group, headers_add, headers_only, headers_remove, headers_rewrite, home_directory, initgroups, max_parallel, message_size_limit, rcpt_include_affixes, retry_use_local_part, return_path, return_path_add, shadow_condition, shadow_transport, transport_filter, transport_filter_timeout, user) are ignored. Sample configuration: (Router) scan: driver = accept transport = scan (Transport) scan: driver = queuefile directory = /var/spool/baruwa-scanner/input In order to build exim with Queuefile transport support add or uncomment EXPERIMENTAL_QUEUEFILE=yes to your Local/Makefile. (Re-)build/install exim. exim -d should show Experimental_QUEUEFILE in the line "Support for:". ARC support ----------- Specification: https://tools.ietf.org/html/draft-ietf-dmarc-arc-protocol-11 Note that this is not an RFC yet, so may change. [RFC 8617 was published 2019/06. Draft 11 was 2018/01. A review of the changes has not yet been done] ARC is intended to support the utility of SPF and DKIM in the presence of intermediaries in the transmission path - forwarders and mailinglists - by establishing a cryptographically-signed chain in headers. Normally one would only bother doing ARC-signing when functioning as an intermediary. One might do verify for local destinations. ARC uses the notion of a "ADministrative Management Domain" (ADMD). Described in RFC 5598 (section 2.3), this is essentially a set of mail-handling systems that mail transits that are all under the control of one organisation. A label should be chosen to identify the ADMD. Messages should be ARC-verified on entry to the ADMD, and ARC-signed on exit from it. Building with ARC Support -- Enable using EXPERIMENTAL_ARC=yes in your Local/Makefile. You must also have DKIM present (not disabled), and you very likely want to have SPF enabled. It is possible to build as a dynamic-load module: set also SUPPORT_ARC=2. Verification -- An ACL condition is provided to perform the "verifier actions" detailed in section 6 of the above specification. It may be called from the DATA ACL and succeeds if the result matches any of a given list. It also records the highest ARC instance number (the chain size) and verification result for later use in creating an Authentication-Results: standard header. verify = arc/ none:fail:pass add_header = :at_start:${authresults {}} Note that it would be wise to strip incoming messages of A-R headers that claim to be from our own . Eg: remove_header = \N^(?i)Authentication-Results\s*::\s*example.org;\N There are four new variables: $arc_state One of pass, fail, none $arc_state_reason (if fail, why) $arc_domains colon-sep list of ARC chain domains, in chain order. problematic elements may have empty list elements $arc_oldest_pass lowest passing instance number of chain Example: logwrite = oldest-p-ams: <${reduce {$lh_ARC-Authentication-Results:} \ {} \ {${if = {$arc_oldest_pass} \ {${extract {i}{${extract {1}{;}{$item}}}}} \ {$item} {$value}}} \ }> Receive log lines for an ARC pass will be tagged "ARC". Signing -- arc_sign = : : [ : ] An option on the smtp transport, which constructs and prepends to the message an ARC set of headers. The textually-first Authentication-Results: header is used as a basis (you must have added one on entry to the ADMD). Expanded as a whole; if unset, empty or forced-failure then no signing is done. If it is set, all of the first three elements must be non-empty. The fourth element is optional, and if present consists of a comma-separated list of options. The options implemented are timestamps Add a t= tag to the generated AMS and AS headers, with the current time. expire[=] Add an x= tag to the generated AMS header, with an expiry time. If the value is an plain number it is used unchanged. If it starts with a '+' then the following number is added to the current time, as an offset in seconds. If a value is not given it defaults to a one month offset. [As of writing, gmail insist that a t= tag on the AS is mandatory] Caveats: * There must be an Authentication-Results header, presumably added by an ACL while receiving the message, for the same ADMD, for arc_sign to succeed. This requires careful coordination between inbound and outbound logic. Only one A-R header is taken account of. This is a limitation versus the ARC spec (which says that all A-R headers from within the ADMD must be used). * If passing a message to another system, such as a mailing-list manager (MLM), between receipt and sending, be wary of manipulations to headers made by the MLM. + For instance, Mailman with REMOVE_DKIM_HEADERS==3 might improve deliverability in a pre-ARC world, but that option also renames the Authentication-Results header, which breaks signing. * Even if you use multiple DKIM keys for different domains, the ARC concept should try to stick to one ADMD, so pick a primary domain and use that for AR headers and outbound signing. Signing is not compatible with cutthrough delivery; any (before expansion) value set for the option will result in cutthrough delivery not being used via the transport in question. Dovecot authenticator via inet socket -------------------------------------------------------------- If Dovecot is configured similar to :- service auth { ... #SASL inet_listener { name = exim port = 12345 } ... } then an Exim authenticator can be configured :- dovecot-plain: driver = dovecot public_name = PLAIN server_socket = dovecot_server_name 12345 server_tls = true server_set_id = $auth1 If the server_socket does not start with a / it is taken as a hostname (or IP); and a whitespace-separated port number must be given. XCLIENT proxy support --------------------------------------------------------------- Per https://www.postfix.org/XCLIENT_README.html XCLIENT is an ESMTP extension supporting an inbound proxy. The only client immplementation known is in Nginx (https://nginx.org/en/docs/mail/ngx_mail_proxy_module.html) If compiled with EXPERIMENTAL_XCLIENT=yes :- As a server, Exim will advertise XCLIENT support (conditional on a new option "hosts_xclient") and service XCLIENT commands with parameters ADDR NAME PORT LOGIN DESTADDR DESTPORT A fresh HELO/EHLO is required after a succesful XCLIENT, and the usual values are derived from that (making the HELO and PROTO paramemters redundant). An XCLIENT command must give both ADDR and PORT parameters if no previous XCLIENT has succeeded in the SMTP session. After a success: $proxy_session variable becomes "yes" $proxy_local_address, $proxy_local_port have the proxy "inside" values $proxy_external_address, $proxy_external_port have the proxy "outside" values $sender_host_address, $sender_host_port have the remot client values SRV SMTPS --------------------------------------------------------------- Per https://www.ietf.org/archive/id/draft-nurpmeso-smtp-tls-srv-05.html If compiled with EXPERIMENTAL_SRV_SMTPS=yes :- This supports a DNS record which specifies that a given server for a domain accepts tls-on-connect connections on a specified port, or can do STARTTLS on the usual port (25). In either case the record is equivalent to an MX record. The Exim implementation uses the existing smtp transport "check_srv" option; if it has a value of "smtp-tls" and the SRV lookup succeeds with a port number other than 25 then that port is used for a tls-on-connect connection. If the connect fails then a fallback of STARTTLS on 25 (or the port from the transport option, if set) is tried. If the SRV-discovered port number is 25 a standard connection is used, with STARTTLS. In all cases, if the SRV lookup succeeds for the "smtp-tls" value only encrypted connections are used. Note that the "check_srv" option value can be a list. Elements are used in left-to-right order for SRV lookups, until one succeeds or there are none left. If a SRV lookup succeeds then no MX lookup is done. If none succeed then the normal sequence of MX and A/AAAA lookups is done. Requirement for TLS activated by this means takes priority over the "hosts_require_tls" transport option; requirement for tls-on-connect takes priority over the "protocol" option. Connections requiring STARTTLS acivated by this means will fail if the host matches the "hosts_avoid_tls" option or (if appropriate) the "hosts_verify_avoid_tls" option. There are no changes for server-side support; only suitable configuration for listening on a separate port (for tls-on-connect), opening any required firewall holes for that port, and provisioning a DNS record are needed. SPF using Perl Mail::SPF --------------------------------------------------------------- If compiled with EXPERIMENTAL_SPF_PERL=yes :- Instead of the traditional implementation using libspf2 (which has seen little recent signs of maintenance) an interface to the Perl Mail::SPF module is used. Compilation must not specify SUPPORT_SPF and must specify EXIM_PERL. Building as a loadable module, using EXPERIMENTAL_SPF_PERL=2 is also supported. The runtime system must have Mail::SPF installed. Variables $spf_header_comment, $spf_result and $spf_received are supported. The other spf_* variables are not. Currently they exist but with default values. The spf_* options currently exist but are ignored. Note that the perl module behaves differently to libspf2 - for example, it does not give localhost a free pass. There is no support for the "spf_guess" ACL condition; it replicates the plain "spf" condition. The embedded perl interpreter is started when an spf ACL condition or an spf lookup string-expansion is done, if not already running. Use of the perl_at_startup option should be considered (but is not required). DMARC native implementation --------------------------------------------------------------- If compiled with EXPERIMENTAL_DMARC_NATIVE=yes :- Instead of the traditional implementation using libopendmarc (which appears abandoned, and has open bugs) a freshly developed builtin implementation is used. *** some facilities of the library-based implementation may not be supported - known items: - "fo" tag - "pct" tag Compilation must not specify SUPPORT_DMARC. Building as a loadable module, with EXPERIMENTAL_DMARC_NATIVE=2 is also supported. The build must also include SPF and DKIM support, and regdom lookups. NMH Lookup --------------------------------------------------------------- If compiled with EXPERIMENTAL_NMH=yes (or =2) :- Ref: https://code.quatermass.co.uk/jgh/ipset_jgh.git A single-key lookup against an NMH daemon is included. The key is an IP address, with optional mask. A query returns whether the key is covered by data in the DB or not. The "file" for the lookup is the name of the unix-domain socket, or the hostname (or IP) if UDP is used, for the daemon. The DB maintained by NMH holds CIDRs, combining or splitting as required when additions and subtractions are done. Example: ${lookup {$sender_host_address} nmh {@nmhd}} (returns either "yes" or an empty string) List-syntax lookups: hosts = net-nmh;@nmhd (note the net- prefix, required to access the IP address rather than the name for the host) Custom options, specified in the usual way: - port=N UDP port number. Required when UDP rather than Unix-domain communication is wanted - tmo=N timeout in seconds - table=TABLE non-default table within database - add add entry to database - sub subtract entry from database - partial return true if there is any entry within the query CIDR Example: ${lookup {192.168.0.0/24} nmh,add,table=mylocal,tmo=10 {@nmhd}} host = net-nmh,port=1026,table=known_spammers;dbserver.local.net -------------------------------------------------------------- End of file --------------------------------------------------------------