Valid names and their types are listed below. All boolean values
is assumed if the name is specified but the
value is omitted. Most values default to
otherwise, the default
values are mentioned after the relevant description. To see default
values it is also possible to run:
- all_mode bool
Courier runs all-mode filters after non-all-mode ones, in alphabetical order.
Non-all-mode filters can be whitelisted by local filters. In addition, any
global filter can whitelist the filters running after it.
The value of this parameter determines in which directory zdkimfilter creates
the socket which connects it to Courier. Therefore, changing this parameter
will have no effect until the filter is reloaded.
- trust_a_r bool
Don't remove any Authentication-Results: (A-R) header field.
Courier renames existing A-R fields since 0.71.0 if ALLOW_EXCLUSIVE is set.
Set this option after enabling ALLOW_EXCLUSIVE in Courier's esmtpd.
- verbose int
Additional control on the amount of output.
The filter prints to stderr, assuming that Courier's logger will capture it and
send to syslog. Hence the amount of output can also be filtered by severity.
Verbosity and severity are not strictly related. Verbosity is tentatively
being used as follows (each level includes the preceding ones):
Startup issues and totally unexpected errors.
Failures and unexpected events.
Unexpected Authentication-Results fields found on verifying.
Missing domain on signing.
Start/stop info, relevant verify results, sign errors, responses except 250.
Response returned to Courier for each message.
Verify errors, except no signature found.
Domain/selector used on signing, any A-R field found.
No key on signing. Signature details and count of Authentication-Results fields
written on verifying.
More debugging; for example, key_choice_header processing.
default: verbose = 3.
- domain_keys string
Directory for domain private keys.
File names should match the domain name; for example, when signing for
firstname.lastname@example.org, zdkimfilter looks for a file named example.com in this
directory. If the file is a symbolic link, the basename of the target file
is be used as the selector. See the signing section of zdkimfilter(8) for
Default: domain_keys = /local/courier/etc/path/filters/keys
- header_canon_relaxed bool
- body_canon_relaxed bool
Canonicalization for header/body can be simple or relaxed. It is recommended
to use "relaxed", especially for the header, because both Courier's SMTP
client and some SMTP receivers alter white space in the header.
- sign_rsa_sha1 bool
The signing algorithm can be one of rsa-sha1, rsa-sha256, or
ed25519-sha256. If it set, signing will force rsa-sha1, which is
deprecated. If it is not set, signing will use a sha256 digest
and an algorithm, rsa or ed25519, compatible with the first key found.
- key_choice_header string
Header fields that determine the signing domain. This is an array
of strings. An element of the array can be either a header field name
leading to a mailbox name, or one two special tokens, dash ("-") and star
("*"), which have the following meaning:
Dash refers to the default_domain.
Star refers to the user domain, if any, or the default_domain. The user
domain is the domain of the user id, if it contains an "@". The user id,
in turn, is either the authenticated user id as set by Courier's SMTPAUTH
after calling the relevant authentication module, or the content of the
RELAYCLIENT environment variable as set, for example in smtpaccess files
if no SMTPAUTH takes place.
The array elements are in order of decreasing preference. Field names are
looked up in the message header, and the domain name is derived from any
mailbox specification found in their value.
This parameter is disabled when making ARC signatures.
For example, with
key_choice_header = from -
then if a key and possibly a selector are defined for the domain in the From:
header field, then they are used for signing, otherwise the default domain
is used, irrespectively of the user id.
If the array is empty, the default, the user domain is used. That is, the
filter behaves as if:
- default_domain string
It is used if no domain can be derived from the previous option, for
example if it has a dash ("-") or the user id has no at-sign ("@").
It is empty by default.
- let_relayclient_alone bool
If user is not authenticated, but has relay privileges and the content
of the RELAYCLIENT environment variable is an at ("@") followed by a
domain name, then zdkimfilter uses the domain name to sign the message,
and then rewrites recipient addresses removing such trailing string and
replacing the last percent ("%"), if any, with an at (<@>). This
behavior is new in version 1.6. It can be disabled by setting this
It is not necessary to set this parameter for typical "allow,RELAYCLIENT"
settings where "RELAYCLIENT" is empty or doesn't start with an at (<@>).
- selector string
In case a selector cannot be determined following a soft link, then the
selector specified here, if any, or the constant "s" will be used.
- sign_hfields array
header fields to be signed.
This is a space-separated list of header field names.
The default value is implemented in OpenDKIM according to RFC 6376 Sec. 5.4:
sign_hfields = From Reply-To Subject Date To Cc In-Reply-To References
Resent-Date Resent-From Resent-Sender Resent-To Resent-Cc
List-Id List-Help List-Unsubscribe List-Subscribe List-Post List-Owner
- oversign_hfields array
header fields to be oversigned, that is mentioned once more in the h=
tag. That way adding a header field with the same name breaks the signature.
The intent is to protect fields like From: which should be unique.
This is a space-separated list of header field names.
The default value is empty.
- skip_hfields array
header fields not to be signed; they are discarded at an earlier stage.
This is a space-separated list of header field names.
The default value is implemented in OpenDKIM according to RFC 6376 Sec. 5.4:
skip_hfields = Return-Path Received Comments Keywords
- no_signlen bool
Set this to avoid specifying the l= parameter of the body length. Specifying
the length enables the addition of text at the bottom of messages, so it was
considered more permissive. However, if Content-Type: is not signed,
having l= allows arbitrary modifications of the message, reducing the
original body to a MIME prologue.
Signing Content-Type: can hamper the ability to recover signatures
after mailing list transformations. So it is actually more flexible to
not set l=. On loading zdkimfilter, an error is logged if neither
no_signlen nor signing Content-Type: are set, and l= is not set.
- no_qp_conversion bool
Set this to disable quoted-printable to base64 conversion. This
conversion was introduced because quoted-printable encoding is very
hard to recover. Signing a base64 is provides for more robust
This parameter is automatically enabled when making ARC signatures.
- min_key_bits int
The minimal length of a DKIM key, in bits. This affects RSA keys used
for signing as well as for verifying. Ed25519 keys have size = 256.
The default value is 1024, according to RFC 8301 Sec. 3.2.
- redact_received_auth string
Rewrite the value of AUTH: in Courier's Received: header field. That value
is the login id, so it is useful to know it. However, it may be a privacy
violation and it may help password crackers. Full-featured redaction
provides for replacing the given value with an obscured string obtained by
scrambling the original value and a secret text. In that case, the redact
utility can reconstruct the value, possibly up to character case, if the
secret text did not change. If the redaction is not fully functional,
because it was not compiled in, a warning is logged on startup and the
obscured string is a constant.
Just the first Received: field where AUTH: matches the authenticated user
NOTE: don't configure for signing Received: or changing it will break the
NOTE: the scrambling used for obfuscation is NOT cryptographically secure.
To enable this behavior, specify some secret text (1 to 256 chars) here.
redact_received_auth = This is the secret text (change and uncomment)
- add_auth_pass bool
Add an A-R field to signed outgoing messages. The field just says auth=pass,
with the signing domain name, and no other details. It can be signed (see
sign_hfields). It may be useful for messages delivered on the same server,
which would get no A-R field otherwise.
The field may be placed on the top of the header, on the bottom, or
right before the header field which determined the key choice.
This parameter is disabled when zdkimfilter is wrapped by zdkimsign.
- tmp string
Temporary directory. libopendkim uses /var/tmp by default.
If you specify a value like /tmp/*, then zdkimfilter attempts to mkdir of
it if it cannot stat it, on loading.
- tempfail_on_error bool
On some errors, e.g. out of memory, return 432 to have the sender retry;
otherwise, just let the msg through unfiltered.
- split_verify string
Separate filter processes, one for verifying and one for signing. This is
useful if you need authentication results to be available to a third filter
which has to run before the signing filter.
The string contains the executable name of the verifying processes.
For example, to install "dkimfilter" (without ``z'') as a verifier, create a
link with that name to zdkimfilter, in /local/libexec/usr/path/filters. Then set
split_verify = dkimfilter
Invoke filterctl start dkimfilter to start the second process. Both
processes read the same configuration file, but create sockets and pid files
according to the executable name used to invoke them. In this example, the
first process stops verifying as soon as it reloads the configuration.
zdkimfilter can also run with a different configuration file. This
can be done by embedding the new configuration filename in the link name;
see ``MULTIPLE FILTERS'' in zdkimfilter. In that case, to have this filter
sign only, it is sufficient to define split_verify with any string
different from the program name. For example:
split_verify = sign only
- add_ztags bool
DKIM signatures can have a copy of signed header fields values inside the
signature field itself, tag "z=". That does not affect verification, but can
be useful when investigating the reasons why a signature does not verify.
- blocked_user_list string
Filename of the list of blocked users. Users on this list can only send to
the postmaster at the user's domain, if they authenticate. The user's
domain is the domain in the user-id, if any, or the default_domain. The list
is automatically updated when the query db_sql_check_user returns a non-zero
reason. It can be updated at any time (creating a temporary file and then
moving it can avoid race conditions.) zdkimfilter keeps the file in memory
and reloads it when it realizes that it changed.
A blocked_user_list could be used even without defining any database option,
but an alternative means to add users to it has to be devised in that case. In
any case, no mechanism is provided to remove users from such list. The
assumption is that user's credentials have been hijacked, so user's password
has to be changed, queued messages canceled, bounces removed, CSIRTs of any
third party's hacked site notified, and finally it is a nice idea to set up
monitoring and reporting of any further spam that the botnet will unwittingly
continue to submit using the stolen credentials. I'm really far from
automating such switch.
Using a query, this works as an alternative to Courier's native ratefilter.
See zfilter_db(8) for details on the query.
- no_spf bool
If Courier sets Received-SPF: pass for sender or helo, that is reported in
A-R. This option may prevent such behavior.
- save_from_anyway bool
Save the From: header field even if it's not authenticated. If true, this
can result in more incoming messages and domains being inserted in the database.
This setting is overridden by publicsuffix, which implies even more domains
can be stored although unauthenticated.
- add_a_r_anyway bool
Add an A-R field also if no signature nor other results had been found.
- report_all_sigs bool
If multiple signatures are found, normally only the most important ones
are reported in the A-R field. By enabling this option, all the signatures
are reported, in order of decreasing importance.
- verify_one_domain bool
If signatures by multiple domains are found, and database logging is enabled,
all domains are verified. By enabling this option, only the first domain is
verified, in order of decreasing importance.
- disable_experimental bool
Turn off experimental feature introduced in v3.0. For signing, this
disables "Original-*:" header fields and conversion to base64.
For verifying, it disables attempt to retry signatures with the
modified header and/or body of the message.
- noaddrrewrite bool
Turn off address rewriting of To:, Reply-To:, From:, and Cc: header
fields in outgoing mail.
Courier sometimes wraps these header fields in an attempt to stay within
70 columns width. So zdkimfilter can apply the same algorithm before
signing. Setting this parameter disables the rewriting. That is similar
to the parameter with the same name in Courier esmtpd* config files.
This parameter is automatically set when zdkimfilter is invoked via
zdkimsign, as it seems that Courier rewriting works differently for
messages submitted locally via sendmail.
- max_signatures int
The absolutely maximum number of signatures. Messages having more signatures
than that are considered denial of service (DoS) attacks and rejected
outright. The default value is 128.
- log_dkim_order_above int
The highest number of signatures you expect. If this is non-zero, a warning is
logged whenever an incoming message has more signers than that, if verbose is 3
or higher. This is to help a reasonable setting of db_sql_dmarc_agg_record.
The default value is 0.
- publicsuffix string
The full path to a file like effective_tld_names.dat that implements the
Public Suffix List as maintained by publicsuffix.org.
The default value is NULL, which may prevent checking DMARC alignment, as well
as discovering DMARC policy records published by the organizational domain
(also known as registered domain) if the author domain is a subdomain thereof.
Setting this value also enables storage of unauthenticated domains, in a way
similar to save_from_anyway.
- psddmarc string
The full path to a file similar in format to effective_tld_names.dat
whose contents implements the Public Suffix Domain DMARC, as maintained
Only domains actually having a _dmarc TXT record need to be listed.
The number of seconds between successive invocations of zaggregate, according
to cron settings. It is used to adjust a domain's dmarc_ri to a multiple of
this value. The default is 86400, which assumes zaggregate is run once a day.
- honor_dmarc bool
Honor DMARC policy, if any. This item can be changed on a per-domain basis.
- honor_author_domain bool
Honor ADSP policy, if any. This item can be changed on a per-domain basis.
- reject_on_nxdomain bool
This option can be set to complement ADSP, or independently of ADSP.
This catches invalid From:
like <john.doe@NOSPAM.example.com>, typical of some mailing lists.
The three conditions that drive the resulting behavior are as follows:
- 1 nxdomain
the author's address, as given in the "From:" header, contains
a non-existing domain name.
- 2 all
the author domain specifies a policy whereby all messages must
have an author domain signature, but this messages has none.
- 3 discardable
as case all, but the author domain further asks that
non-compliant messages be just discarded, in order to avoid
When reject_on_nxdomain is enabled, the filter rejects in case 1.
When honor_author_domain is enabled, the filter rejects in case 2
and drops in case 3. In any case, the action is retracted if an
authenticated domain is whitelisted in the database, vouched by a
trusted VBR (an outmoded protocol), or authenticated by dnswl=pass.
Any of SPF and DKIM authentications are valid to establish whitelisting,
but only ``MAIL FROM'' SPF and DKIM can be used for VBR.
If one of the cases above is detected, but the action not enforced,
an A-R field will have a line specifying the result as dkim-adsp=nxdomain
(for case 1), dkim-adsp=fail (case 2), or dkim-adsp=discard (3).
Recall that ADSP was declared ``Historic'' in November 2013.
- action_header string
An RFC 822 header field name that an upstream filter adds to the message to
mark it as bad. If that header is found, the message is dropped or rejected
according to the next option.
This option is meant to be a last resort for messages caught by anti-virus or
anti-phishing filters that add a given header field instead of discarding the
message tout-court. That way, a reject/drop decision can be undone according
to dnswl_worthiness_pass and/or whitelisted_pass.
- header_action_is_reject bool
Reject, rather than drop, if the action_header is found.
- save_drop string
Quarantine directory path. Messages dropped because of the action_header are
saved there, if set. Saved messages are named after the content of the header.
The message content is preceded by a "pre-header"; that is, a part of the
envelope separated by an empty line. The part of the envelope consists of a
possibly empty sender followed by the recipients. The pre-header enables
users to recover the message from quarantine in case of false positives;
see the scripts etc/resend-with-preheader.* in the tarball.
This item refers to the externally retrieved dnswl value.
A worthiness greater or equal than this causes acceptance of a message
even if it if it should have been rejected due to DMARC or ADSP policy,
action_header or shoot_on_sight. Must be a number between 0 and 255.
Default: 1 (low for dnswl.org)
An invalid IP is returned in some cases, e.g. if a name server issues too many
queries. Finding this is logged at LOG_CRIT if verbose is 1 or greater.
The ip has to be given as a 32bit integer, with the right endianness.
Default: -16777089, which works for dnswl.org
This is the octet in policy.ip where the worthiness value is found.
Must be a number between 0 and 3.
Default: 3, which works for dnswl.org
- trusted_dnswl array
A space-separated list of trusted dns zones. When an A-R field that contains
"dnswl=pass" is found, if the dns.zone is trusted and the result contains a
policy.txt with a domain name in it, the domain in the policy.txt is
associated to the message. At most one domain can get associated this way.
The default is "list.dnswl.zone". Unless you know a different operator that
does the same service, it shouldn't be necessary to modify this default,
because the lookup has to be configured in Courier's sysconfdir/esmtpd. If
you use a local server, e.g. downloading rbldns data from dnswl.org, you can
configure the correct display zone rather than change this default. For
(note the trailing comma, which is necessary to query the TXT record too.)
- whitelisted_pass int
This refers to the whitelisted value read by ``db_sql_domain_flags'' in zfilter_db,
not to be conflated with dnswl.
A value greater or equal than this configured value causes acceptance of a
message even if it should have been rejected due to DMARC or ADSP policy,
action_header or shoot_on_sight.
This value should be greater than 2, since a value of 1 can be set
automatically when a DKIM signature verifies, and a value of 2 is set
when sending to a domain from a personal address (not an rfc2142 address.)
Since version 3.6, the string whitelisted inside a parethesized
comment of Authentication-Results: is only added when this value is met.
This enables to control the placement of that string and possibly use it
for actual whitelisting.
For example, Maildrop recipes can limit trashing like so:
if (/^X-Spam-Flag: YES/:H && \