+DCC Support
+--------------------------------------------------------------
+
+*) 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 acutally uses.
+
+DMARC Support
+--------------------------------------------------------------
+
+DMARC combines feedback from SPF, DKIM, and header From: in order
+to attempt to provide better indicators of the authenticity of an
+email. This document does not explain the fundamentals, you
+should read and understand how it works by visiting the website at
+http://www.dmarc.org/.
+
+DMARC support is added via the libopendmarc library. Visit:
+
+ http://sourceforge.net/projects/opendmarc/
+
+to obtain a copy, or find it in your favorite rpm package
+repository. If building from source, this description assumes
+that headers will be in /usr/local/include, and that the libraries
+are in /usr/local/lib.
+
+1. To compile Exim with DMARC support, you must first enable SPF.
+Please read the above section on enabling the EXPERIMENTAL_SPF
+feature. You must also have DKIM support, so you cannot set the
+DISABLE_DKIM feature. Once both of those conditions have been met
+you can enable DMARC in Local/Makefile:
+
+EXPERIMENTAL_DMARC=yes
+LDFLAGS += -lopendmarc
+# CFLAGS += -I/usr/local/include
+# LDFLAGS += -L/usr/local/lib
+
+The first line sets the feature to include the correct code, and
+the second line says to link the libopendmarc libraries into the
+exim binary. The commented out lines should be uncommented if you
+built opendmarc from source and installed in the default location.
+Adjust the paths if you installed them elsewhere, but you do not
+need to uncomment them if an rpm (or you) installed them in the
+package controlled locations (/usr/include and /usr/lib).
+
+
+2. Use the following global settings to configure DMARC:
+
+Required:
+dmarc_tld_file Defines the location of a text file of valid
+ top level domains the opendmarc library uses
+ during domain parsing. Maintained by Mozilla,
+ the most current version can be downloaded
+ from a link at http://publicsuffix.org/list/.
+
+Optional:
+dmarc_history_file Defines the location of a file to log results
+ of dmarc verification on inbound emails. The
+ contents are importable by the opendmarc tools
+ which will manage the data, send out DMARC
+ reports, and expire the data. Make sure the
+ directory of this file is writable by the user
+ exim runs as.
+
+dmarc_forensic_sender The email address to use when sending a
+ forensic report detailing alignment failures
+ if a sender domain's dmarc record specifies it
+ and you have configured Exim to send them.
+ Default: do-not-reply@$default_hostname
+
+
+3. By default, the DMARC processing will run for any remote,
+non-authenticated user. It makes sense to only verify DMARC
+status of messages coming from remote, untrusted sources. You can
+use standard conditions such as hosts, senders, etc, to decide that
+DMARC verification should *not* be performed for them and disable
+DMARC with a control setting:
+
+ control = dmarc_disable_verify
+
+A DMARC record can also specify a "forensic address", which gives
+exim an email address to submit reports about failed alignment.
+Exim does not do this by default because in certain conditions it
+results in unintended information leakage (what lists a user might
+be subscribed to, etc). You must configure exim to submit forensic
+reports to the owner of the domain. If the DMARC record contains a
+forensic address and you specify the control statement below, then
+exim will send these forensic emails. It's also advised that you
+configure a dmarc_forensic_sender because the default sender address
+construction might be inadequate.
+
+ control = dmarc_forensic_enable
+
+(AGAIN: You can choose not to send these forensic reports by simply
+not putting the dmarc_forensic_enable control line at any point in
+your exim config. If you don't tell it to send them, it will not
+send them.)
+
+There are no options to either control. Both must appear before
+the DATA acl.
+
+
+4. You can now run DMARC checks in incoming SMTP by using the
+"dmarc_status" ACL condition in the DATA ACL. You are required to
+call the spf condition first in the ACLs, then the "dmarc_status"
+condition. Putting this condition in the ACLs is required in order
+for a DMARC check to actually occur. All of the variables are set
+up before the DATA ACL, but there is no actual DMARC check that
+occurs until a "dmarc_status" condition is encountered in the ACLs.
+
+The dmarc_status condition takes a list of strings on its
+right-hand side. These strings describe recommended action based
+on the DMARC check. To understand what the policy recommendations
+mean, refer to the DMARC website above. Valid strings are:
+
+ o accept The DMARC check passed and the library recommends
+ accepting the email.
+ o reject The DMARC check failed and the library recommends
+ rejecting the email.
+ o quarantine The DMARC check failed and the library recommends
+ keeping it for further inspection.
+ o none The DMARC check passed and the library recommends
+ no specific action, neutral.
+ o norecord No policy section in the DMARC record for this
+ sender domain.
+ o nofrom Unable to determine the domain of the sender.
+ o temperror Library error or dns error.
+ o off The DMARC check was disabled for this email.
+
+You can prefix each string with an exclamation mark to invert its
+meaning, for example "!accept" will match all results but
+"accept". The string list is evaluated left-to-right in a
+short-circuit fashion. When a string matches the outcome of the
+DMARC check, the condition succeeds. If none of the listed
+strings matches the outcome of the DMARC check, the condition
+fails.
+
+Of course, you can also use any other lookup method that Exim
+supports, including LDAP, Postgres, MySQL, etc, as long as the
+result is a list of colon-separated strings.
+
+Several expansion variables are set before the DATA ACL is
+processed, and you can use them in this ACL. The following
+expansion variables are available:
+
+ o $dmarc_status
+ This is a one word status indicating what the DMARC library
+ thinks of the email. It is a combination of the results of
+ DMARC record lookup and the SPF/DKIM/DMARC processing results
+ (if a DMARC record was found). The actual policy declared
+ in the DMARC record is in a separate expansion variable.
+
+ o $dmarc_status_text
+ This is a slightly longer, human readable status.
+
+ o $dmarc_used_domain
+ This is the domain which DMARC used to look up the DMARC
+ policy record.
+
+ o $dmarc_domain_policy
+ This is the policy declared in the DMARC record. Valid values
+ are "none", "reject" and "quarantine". It is blank when there
+ is any error, including no DMARC record.
+
+ o $dmarc_ar_header
+ This is the entire Authentication-Results header which you can
+ add using an add_header modifier.
+
+
+5. How to enable DMARC advanced operation:
+By default, Exim's DMARC configuration is intended to be
+non-intrusive and conservative. To facilitate this, Exim will not
+create any type of logging files without explicit configuration by
+you, the admin. Nor will Exim send out any emails/reports about
+DMARC issues without explicit configuration by you, the admin (other
+than typical bounce messages that may come about due to ACL
+processing or failure delivery issues).
+
+In order to log statistics suitable to be imported by the opendmarc
+tools, you need to:
+a. Configure the global setting dmarc_history_file.
+b. Configure cron jobs to call the appropriate opendmarc history
+ import scripts and truncating the dmarc_history_file.
+
+In order to send forensic reports, you need to:
+a. Configure the global setting dmarc_forensic_sender.
+b. Configure, somewhere before the DATA ACL, the control option to
+ enable sending DMARC forensic reports.
+
+
+6. Example usage:
+(RCPT ACL)
+ warn domains = +local_domains
+ hosts = +local_hosts
+ control = dmarc_disable_verify
+
+ warn !domains = +screwed_up_dmarc_records
+ control = dmarc_enable_forensic
+
+ warn condition = (lookup if destined to mailing list)
+ set acl_m_mailing_list = 1
+
+(DATA ACL)
+ warn dmarc_status = accept : none : off
+ !authenticated = *
+ log_message = DMARC DEBUG: $dmarc_status $dmarc_used_domain
+ add_header = $dmarc_ar_header
+
+ warn dmarc_status = !accept
+ !authenticated = *
+ log_message = DMARC DEBUG: '$dmarc_status' for $dmarc_used_domain
+
+ warn dmarc_status = quarantine
+ !authenticated = *
+ set $acl_m_quarantine = 1
+ # Do something in a transport with this flag variable
+
+ deny condition = ${if eq{$dmarc_domain_policy}{reject}}
+ condition = ${if eq{$acl_m_mailing_list}{1}}
+ message = Messages from $dmarc_used_domain break mailing lists
+
+ deny dmarc_status = reject
+ !authenticated = *
+ message = Message from $domain_used_domain failed sender's DMARC policy, REJECT
+
+
+
+Event Actions
+--------------------------------------------------------------
+
+(Renamed from TPDA, Transport post-delivery actions)
+
+An arbitrary per-transport string can be expanded upon various transport events.
+Additionally a main-section configuration option can be expanded on some
+per-message events.
+This feature may be used, for example, to write exim internal log information
+(not available otherwise) into a database.
+
+In order to use the feature, you must compile with
+
+EXPERIMENTAL_EVENT=yes
+
+in your Local/Makefile
+
+and define one or both of
+- the event_action option in the transport
+- the event_action main option
+to be expanded when the event fires.
+
+A new variable, $event_name, is set to the event type when the
+expansion is done. The current list of events is:
+
+ msg:complete after main per message
+ msg:delivery after transport per recipient
+ msg:host:defer after transport per attempt
+ msg:fail:delivery after main per recipient
+ msg:fail:internal after main per recipient
+ tcp:connect before transport per connection
+ tcp:close after transport per connection
+ tls:cert before both per certificate in verification chain
+ smtp:connect after transport per connection
+
+The expansion is called for all event types, and should use the $event_name
+value to decide when to act. The variable data is a colon-separated
+list, describing an event tree.
+
+There is an auxilary variable, $event_data, for which the
+content is event_dependent:
+
+ msg:delivery smtp confirmation mssage
+ msg:host:defer error string
+ tls:cert verification chain depth
+ smtp:connect smtp banner
+
+The msg:host:defer event populates one extra variable, $event_defer_errno.
+
+The following variables are likely to be useful depending on the event type:
+
+ router_name, transport_name
+ local_part, domain
+ host, host_address, host_port
+ tls_out_peercert
+ lookup_dnssec_authenticated, tls_out_dane
+ sending_ip_address, sending_port
+ message_exim_id, verify_mode
+
+
+An example might look like:
+
+event_action = ${if eq {msg:delivery}{$event_name} \
+{${lookup pgsql {SELECT * FROM record_Delivery( \
+ '${quote_pgsql:$sender_address_domain}',\
+ '${quote_pgsql:${lc:$sender_address_local_part}}', \
+ '${quote_pgsql:$domain}', \
+ '${quote_pgsql:${lc:$local_part}}', \
+ '${quote_pgsql:$host_address}', \
+ '${quote_pgsql:${lc:$host}}', \
+ '${quote_pgsql:$message_exim_id}')}} \
+} {}}
+
+The string is expanded when each of the supported events occur
+and any side-effects of the expansion will happen.
+Note that for complex operations an ACL expansion can be used.
+
+
+The expansion of the event_action option should normally
+return an empty string. Should it return anything else the
+following will be forced:
+
+ msg:delivery (ignored)
+ msg:host:defer (ignored)
+ msg:fail:delivery (ignored)
+ tcp:connect do not connect
+ tcp:close (ignored)
+ tls:cert refuse verification
+ smtp:connect close connection
+
+No other use is made of the result string.
+
+
+Known issues:
+- the tls:cert event is only called for the cert chain elements
+ received over the wire, with GnuTLS. OpenSSL gives the entire
+ chain including thse loaded locally.
+
+
+Redis Lookup
+--------------------------------------------------------------
+
+Redis is open source advanced key-value data store. This document
+does not explain the fundamentals, you should read and understand how
+it works by visiting the website at http://www.redis.io/.
+
+Redis lookup support is added via the hiredis library. Visit:
+
+ https://github.com/redis/hiredis
+
+to obtain a copy, or find it in your operating systems package repository.
+If building from source, this description assumes that headers will be in
+/usr/local/include, and that the libraries are in /usr/local/lib.
+
+1. In order to build exim with Redis lookup support add
+
+EXPERIMENTAL_REDIS=yes
+
+to your Local/Makefile. (Re-)build/install exim. exim -d should show
+Experimental_Redis in the line "Support for:".
+
+EXPERIMENTAL_REDIS=yes
+LDFLAGS += -lhiredis
+# CFLAGS += -I/usr/local/include
+# LDFLAGS += -L/usr/local/lib
+
+The first line sets the feature to include the correct code, and
+the second line says to link the hiredis libraries into the
+exim binary. The commented out lines should be uncommented if you
+built hiredis from source and installed in the default location.
+Adjust the paths if you installed them elsewhere, but you do not
+need to uncomment them if an rpm (or you) installed them in the
+package controlled locations (/usr/include and /usr/lib).
+
+
+2. Use the following global settings to configure Redis lookup support:
+
+Required:
+redis_servers This option provides a list of Redis servers
+ and associated connection data, to be used in
+ conjunction with redis lookups. The option is
+ only available if Exim is configured with Redis
+ support.
+
+For example:
+
+redis_servers = 127.0.0.1/10/ - using database 10 with no password
+redis_servers = 127.0.0.1//password - to make use of the default database of 0 with a password
+redis_servers = 127.0.0.1// - for default database of 0 with no password
+
+3. Once you have the Redis servers defined you can then make use of the
+experimental Redis lookup by specifying ${lookup redis{}} in a lookup query.
+
+4. Example usage:
+
+(Host List)
+hostlist relay_from_ips = <\n ${lookup redis{SMEMBERS relay_from_ips}}
+
+Where relay_from_ips is a Redis set which contains entries such as "192.168.0.0/24" "10.0.0.0/8" and so on.
+The result set is returned as
+192.168.0.0/24
+10.0.0.0/8
+..
+.
+
+(Domain list)
+domainlist virtual_domains = ${lookup redis {HGET $domain domain}}
+
+Where $domain is a hash which includes the key 'domain' and the value '$domain'.
+
+(Adding or updating an existing key)
+set acl_c_spammer = ${if eq{${lookup redis{SPAMMER_SET}}}{OK}}
+
+Where SPAMMER_SET is a macro and it is defined as
+
+"SET SPAMMER <some_value>"
+
+(Getting a value from Redis)
+
+set acl_c_spam_host = ${lookup redis{GET...}}
+
+
+Proxy Protocol Support
+--------------------------------------------------------------
+
+Exim now has Experimental "Proxy Protocol" support. It was built on
+specifications from:
+http://haproxy.1wt.eu/download/1.5/doc/proxy-protocol.txt
+Above URL revised May 2014 to change version 2 spec:
+http://git.1wt.eu/web?p=haproxy.git;a=commitdiff;h=afb768340c9d7e50d8e
+
+The purpose of this function is so that an application load balancer,
+such as HAProxy, can sit in front of several Exim servers and Exim
+will log the IP that is connecting to the proxy server instead of
+the IP of the proxy server when it connects to Exim. It resets the
+$sender_address_host and $sender_address_port to the IP:port of the
+connection to the proxy. It also re-queries the DNS information for
+this new IP address so that the original sender's hostname and IP
+get logged in the Exim logfile. There is no logging if a host passes or
+fails Proxy Protocol negotiation, but it can easily be determined and
+recorded in an ACL (example is below).
+
+1. To compile Exim with Proxy Protocol support, put this in
+Local/Makefile:
+
+EXPERIMENTAL_PROXY=yes
+
+2. Global configuration settings:
+
+proxy_required_hosts = HOSTLIST
+
+The proxy_required_hosts option will require any IP in that hostlist
+to use Proxy Protocol. The specification of Proxy Protocol is very
+strict, and if proxy negotiation fails, Exim will not allow any SMTP
+command other than QUIT. (See end of this section for an example.)
+The option is expanded when used, so it can be a hostlist as well as
+string of IP addresses. Since it is expanded, specifying an alternate
+separator is supported for ease of use with IPv6 addresses.
+
+To log the IP of the proxy in the incoming logline, add:
+ log_selector = +proxy
+
+A default incoming logline (wrapped for appearance) will look like this:
+
+ 2013-11-04 09:25:06 1VdNti-0001OY-1V <= me@example.net
+ H=mail.example.net [1.2.3.4] P=esmtp S=433
+
+With the log selector enabled, an email that was proxied through a
+Proxy Protocol server at 192.168.1.2 will look like this:
+
+ 2013-11-04 09:25:06 1VdNti-0001OY-1V <= me@example.net
+ H=mail.example.net [1.2.3.4] P=esmtp PRX=192.168.1.2 S=433
+
+3. In the ACL's the following expansion variables are available.
+
+proxy_host_address The (internal) src IP of the proxy server
+ making the connection to the Exim server.
+proxy_host_port The (internal) src port the proxy server is
+ using to connect to the Exim server.
+proxy_target_address The dest (public) IP of the remote host to
+ the proxy server.
+proxy_target_port The dest port the remote host is using to
+ connect to the proxy server.
+proxy_session Boolean, yes/no, the connected host is required
+ to use Proxy Protocol.
+
+There is no expansion for a failed proxy session, however you can detect
+it by checking if $proxy_session is true but $proxy_host is empty. As
+an example, in my connect ACL, I have:
+
+ warn condition = ${if and{ {bool{$proxy_session}} \
+ {eq{$proxy_host_address}{}} } }
+ log_message = Failed required proxy protocol negotiation \
+ from $sender_host_name [$sender_host_address]
+
+ warn condition = ${if and{ {bool{$proxy_session}} \
+ {!eq{$proxy_host_address}{}} } }
+ # But don't log health probes from the proxy itself
+ condition = ${if eq{$proxy_host_address}{$sender_host_address} \
+ {false}{true}}
+ log_message = Successfully proxied from $sender_host_name \
+ [$sender_host_address] through proxy protocol \
+ host $proxy_host_address
+
+ # Possibly more clear
+ warn logwrite = Remote Source Address: $sender_host_address:$sender_host_port
+ logwrite = Proxy Target Address: $proxy_target_address:$proxy_target_port
+ logwrite = Proxy Internal Address: $proxy_host_address:$proxy_host_port
+ logwrite = Internal Server Address: $received_ip_address:$received_port
+
+
+4. Recommended ACL additions:
+ - Since the real connections are all coming from your proxy, and the
+ per host connection tracking is done before Proxy Protocol is
+ evaluated, smtp_accept_max_per_host must be set high enough to
+ handle all of the parallel volume you expect per inbound proxy.
+ - With the smtp_accept_max_per_host set so high, you lose the ability
+ to protect your server from massive numbers of inbound connections
+ from one IP. In order to prevent your server from being DOS'd, you
+ need to add a per connection ratelimit to your connect ACL. I
+ suggest something like this:
+
+ # Set max number of connections per host
+ LIMIT = 5
+ # 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
+
+
+5. Runtime issues to be aware of:
+ - The proxy has 3 seconds (hard-coded in the source code) to send the
+ required Proxy Protocol header after it connects. If it does not,
+ the response to any commands will be:
+ "503 Command refused, required Proxy negotiation failed"
+ - If the incoming connection is configured in Exim to be a Proxy
+ Protocol host, but the proxy is not sending the header, the banner
+ does not get sent until the timeout occurs. If the sending host
+ sent any input (before the banner), this causes a standard Exim
+ synchronization error (i.e. trying to pipeline before PIPELINING
+ was advertised).
+ - This is not advised, but is mentioned for completeness if you have
+ a specific internal configuration that you want this: If the Exim
+ server only has an internal IP address and no other machines in your
+ organization will connect to it to try to send email, you may
+ simply set the hostlist to "*", however, this will prevent local
+ mail programs from working because that would require mail from
+ localhost to use Proxy Protocol. Again, not advised!
+
+6. Example of a refused connection because the Proxy Protocol header was
+not sent from a host configured to use Proxy Protocol. In the example,
+the 3 second timeout occurred (when a Proxy Protocol banner should have
+been sent), the banner was displayed to the user, but all commands are
+rejected except for QUIT:
+
+# nc mail.example.net 25
+220-mail.example.net, ESMTP Exim 4.82+proxy, Mon, 04 Nov 2013 10:45:59
+220 -0800 RFC's enforced
+EHLO localhost
+503 Command refused, required Proxy negotiation failed
+QUIT
+221 mail.example.net closing connection
+
+
+
+
+DANE
+------------------------------------------------------------
+DNS-based Authentication of Named Entities, as applied
+to SMTP over TLS, provides assurance to a client that
+it is actually talking to the server it wants to rather
+than some attacker operating a Man In The Middle (MITM)
+operation. The latter can terminate the TLS connection
+you make, and make another one to the server (so both
+you and the server still think you have an encrypted
+connection) and, if one of the "well known" set of
+Certificate Authorities has been suborned - something
+which *has* been seen already (2014), a verifiable
+certificate (if you're using normal root CAs, eg. the
+Mozilla set, as your trust anchors).
+
+What DANE does is replace the CAs with the DNS as the
+trust anchor. The assurance is limited to a) the possibility
+that the DNS has been suborned, b) mistakes made by the
+admins of the target server. The attack surface presented
+by (a) is thought to be smaller than that of the set
+of root CAs.
+
+It also allows the server to declare (implicitly) that
+connections to it should use TLS. An MITM could simply
+fail to pass on a server's STARTTLS.
+
+DANE scales better than having to maintain (and
+side-channel communicate) copies of server certificates
+for every possible target server. It also scales
+(slightly) better than having to maintain on an SMTP
+client a copy of the standard CAs bundle. It also
+means not having to pay a CA for certificates.
+
+DANE requires a server operator to do three things:
+1) run DNSSEC. This provides assurance to clients
+that DNS lookups they do for the server have not
+been tampered with. The domain MX record applying
+to this server, its A record, its TLSA record and
+any associated CNAME records must all be covered by
+DNSSEC.
+2) add TLSA DNS records. These say what the server
+certificate for a TLS connection should be.
+3) offer a server certificate, or certificate chain,
+in TLS connections which is traceable to the one
+defined by (one of?) the TSLA records
+
+There are no changes to Exim specific to server-side
+operation of DANE.
+
+The TLSA record for the server may have "certificate
+usage" of DANE-TA(2) or DANE-EE(3). The latter specifies
+the End Entity directly, i.e. the certificate involved
+is that of the server (and should be the sole one transmitted
+during the TLS handshake); this is appropriate for a
+single system, using a self-signed certificate.
+ DANE-TA usage is effectively declaring a specific CA
+to be used; this might be a private CA or a public,
+well-known one. A private CA at simplest is just
+a self-signed certificate which is used to sign
+cerver certificates, but running one securely does
+require careful arrangement. If a private CA is used
+then either all clients must be primed with it, or
+(probably simpler) the server TLS handshake must transmit
+the entire certificate chain from CA to server-certificate.
+If a public CA is used then all clients must be primed with it
+(losing one advantage of DANE) - but the attack surface is
+reduced from all public CAs to that single CA.
+DANE-TA is commonly used for several services and/or
+servers, each having a TLSA query-domain CNAME record,
+all of which point to a single TLSA record.
+
+The TLSA record should have a Selector field of SPKI(1)
+and a Matching Type field of SHA2-512(2).
+
+At the time of writing, https://www.huque.com/bin/gen_tlsa
+is useful for quickly generating TLSA records; and commands like
+
+ openssl x509 -in -pubkey -noout <certificate.pem \
+ | openssl rsa -outform der -pubin 2>/dev/null \
+ | openssl sha512 \
+ | awk '{print $2}'
+
+are workable for 4th-field hashes.
+
+For use with the DANE-TA model, server certificates
+must have a correct name (SubjectName or SubjectAltName).
+
+The use of OCSP-stapling should be considered, allowing
+for fast revocation of certificates (which would otherwise
+be limited by the DNS TTL on the TLSA records). However,
+this is likely to only be usable with DANE-TA. NOTE: the
+default of requesting OCSP for all hosts is modified iff
+DANE is in use, to:
+
+ hosts_request_ocsp = ${if or { {= {0}{$tls_out_tlsa_usage}} \
+ {= {4}{$tls_out_tlsa_usage}} } \
+ {*}{}}
+
+The (new) variable $tls_out_tlsa_usage is a bitfield with
+numbered bits set for TLSA record usage codes.
+The zero above means DANE was not in use,
+the four means that only DANE-TA usage TLSA records were
+found. If the definition of hosts_request_ocsp includes the
+string "tls_out_tlsa_usage", they are re-expanded in time to
+control the OCSP request.
+
+This modification of hosts_request_ocsp is only done if
+it has the default value of "*". Admins who change it, and
+those who use hosts_require_ocsp, should consider the interaction
+with DANE in their OCSP settings.
+
+
+For client-side DANE there are two new smtp transport options,
+hosts_try_dane and hosts_require_dane. They do the obvious thing.
+[ should they be domain-based rather than host-based? ]
+
+DANE will only be usable if the target host has DNSSEC-secured
+MX, A and TLSA records.
+
+A TLSA lookup will be done if either of the above options match
+and the host-lookup succeded using dnssec.
+If a TLSA lookup is done and succeeds, a DANE-verified TLS connection
+will be required for the host.
+
+(TODO: specify when fallback happens vs. when the host is not used)
+
+If DANE is requested and useable (see above) the following transport
+options are ignored:
+ hosts_require_tls
+ tls_verify_hosts
+ tls_try_verify_hosts
+ tls_verify_certificates
+ tls_crl
+ tls_verify_cert_hostnames
+
+If DANE is not usable, whether requested or not, and CA-anchored
+verification evaluation is wanted, the above variables should be set
+appropriately.
+
+Currently dnssec_request_domains must be active (need to think about that)
+and dnssec_require_domains is ignored.
+
+If verification was successful using DANE then the "CV" item
+in the delivery log line will show as "CV=dane".
+
+There is a new variable $tls_out_dane which will have "yes" if
+verification succeeded using DANE and "no" otherwise (only useful
+in combination with EXPERIMENTAL_EVENT), and a new variable
+$tls_out_tlsa_usage (detailed above).
+
+