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 = <ip> <port>

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:<d3@myhost.test.ex>: 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/<acceptable_list>   none:fail:pass

  add_header = :at_start:${authresults {<admd-identifier>}}

	Note that it would be wise to strip incoming messages of A-R headers
	that claim to be from our own <admd-identifier>.  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 = <admd-identifier> : <selector> : <privkey> [ : <options> ]
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[=<val>]	Add an x= tag to the generated AMS header, with an expiry time.
			If the value <val> 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

If the proxy has accepted a login then the name appears in $authenticated_id
and $sender_host_authenticated is set to "xclient". Note that this is delegating
authentication to the proxy; values should only be used without further checking
if the proxy and the connection with the proxy are trusted.


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
--------------------------------------------------------------
