authentication_milter - A Perl Mail Authentication Milter


version 3.20210324


  authentication_milter [-c|--control <command>] [-d|--daemon] [--pidfile <file>] [-h|--help] [--prefix <dir>] [-i|--ident <ident>]


-c|--control <command>
  Control a running daemon process or start a new one.


    Start a new daemon process, or restart an existing process.


    Stop an already running daemon process.


    Show the status of a running daemon process.

  Control implies --daemon, and takes account of --pidfile
  If no valid data is found in the pidfile then control will
  search the process list for a parent process.

  If you are running multiple distinct instances of authentication
  milter on a single host, each with differing configurations then you
  should use the --ident identifier to differentiate between them.
  Show this help.
-h|--help default_config
  Output an example default configuration, including
  config for all installed handler modules.
-h|--help installed
  Show a list of installed handler modules.
-h|--help <ModuleName>
  Show help for a particular handler module.

  Modules installed by default include the following.

  AddID Auth DKIM DMARC IPRev LocalIP PTR ReturnOK
  Sanitize SenderID SpamAssassin SPF TrustedIP TLS
  detach from shell and run as a daemon
--pidfile <file>
  Write the process PID to the given file.
  defaults to /run/
--prefix <dir>
  Read configuration from dir rather than /etc/
-i|--ident <ident>
  A string identifier for use in process management and logging

  This should be used when you are running multiple instances of
  authentication_milter on a single host, each with different configurations.


  The milter reads configuration from /etc/authentication_milter.json

  The configuration file format is as follows...

    "external_callback_processor" : "My::Module",       | Name of module containing external callback methods

    "debug"     : 0,                                    | Verbose debugging output
    "dryrun"    : 0,                                    | Dryrun (do not alter or reject mail)
    "logtoerr"  : 0,                                    | Also write logs to STDERR
    "error_log" : "/var/log/authentication_milter.err", | Capture STDERR to logfile

    "errors_to"   : "John Smith <>",    | If set, send exception emails when authmilter encounters
    "errors_from" : "AuthMilter <>",  | an unexpected error or timeout
    "errors_headers" : {}                               | optional headers for error emails

    "log_dispatchouli" : {},                            | Optional args to pass directly into Log::Dispatchouli->new()

    "connection"             : "inet:12345@localhost",  | The connection to use
    "umask"                  : "0000",                  | Set umask (for unix socket)

    "connections" : {                                   | Other than the default connection, also bind to
                                                        | these connections.

        "name_two" : {                                  | Name of connection
            "connection"   : "unix:/var/sock/a.sock",   | The connection to use
            "umask"        : "0000",                    | Set umask
        "name_one" : {                                  | Name of connection
            "connection"   : "inet:12346@localhost",    | The connection to use

    "runas"                  : "nobody",                | Drop privs and run as this user (root only)
    "rungroup"               : "nogroup",               | Drop privs and run as this group (root daemon only)
    "chroot"                 : "/path/to/chroot"        | Set chroot before forking (root only)
                                                        | N.B. This path will need to be setup with all required
                                                        | files or the server WILL segfault.
    "listen_backlog"         : 20,                      | socket listen backlog limit (default 20)
    "min_children"           : 20,                      | Max number of children to pre fork
    "max_children"           : 200,                     | Max number of children to pre fork
    "min_spare_children"     : 10,                      | Min number of spare children to maintain
    "max_spare_children"     : 20,                      | Max number of spare children to maintain
    "max_requests_per_child" : 200,                     | Max number of requests per child process (prefork)

    "metric_connection" : "inet:12346@localhost",       | Optional connection on which to expose metrics interface
    "metric_timeout"    : 10,                           | Timeout for metrics IPC (default 5)
    "metric_tempfile"   : "/tmpfs/authmilter_metrics",  | Path to shared metrics data, defaults to <lib_path>/metrics
    "metric_basic_http" : 1,                            | Disable extended http services such as config and grafana json pages

    "cache_dir"        : "/var/cache/auth_milter",      | Path to the shared cache directory
    "spool_dir"        : "/var/spool/auth_milter",      | Path to the shared spool directory
    "lib_dir"          : "/var/lib/auth_milter",        | Path to the shared lib directory

    # metric_port and metric_host are deprecated.
    # please use metric_connection instead
    "metric_port"            : 8081,                    | Optional port on which to expose metrics interface
    "metric_host"            : "",             | Optional host for binding metrics interface

    "protocol"               : "milter",                | The protocol the milter is to use
                                                        | can be either milter or smtp

    "milter_quarantine" : "0",                          | Allow Milter protocol quarantine when running in milter mode
                                                        | (experimental)

    "patch_net_server"  : "1",                          | If true, try and patch some Net::Server issues

    "smtp" : {                                          | Parameters for use when protocol is smtp
        "server_name"    : "",          | The server name to use for the server
        "sock_type"      : "inet",                      | Socket type (inet or unix)
        "sock_host"      : "localhost",                 | Host to connect to (when inet)
        "sock_port"      : "2525",                      | Port to connect to (when inet)
        "sock_path"      : "/var/run/smtp.sock",        | Socket path to connect to (when unix)
        "timeout_in"     : "10",                        | Timeout when waiting for inbound SMTP data
        "timeout_out"    : "10",                        | Timeout when waiting for outbound SMTP data
        "pipeline_limit" : "50",                        | Limit the number of transactions accepted in an SMTP pipeline
        "queue_type"     : "before",                    | SMTP Queue type, either before or after. After queues have
                                                        | an upstream queue ID, before queues do not.
        "temp_dir"       : "/tmp/",                     | Directory for temporary spool files, defaults to in memory
        "chunk_limit"    : 1048576,                     | Process body in chunks of approx this many bytes

        "tcp:12346" : {                                 | Outbound SMTP details can be set per inbound port/socket
                                                        | This allows outbound SMTP to be routed differently for
                                                        | different inbound ports. The key is the inbound port specified
                                                        | as unix:<socket path> or inet:<port>
                                                        | It is not currently possible to set based on listening host.
                                                        | If a specific config set is not found them we use the default
                                                        | set as defined above.
            "server_name" : "",         | The server name to use for the server
            "sock_type"   : "inet",                     | Socket type (inet or unix)
            "sock_host"   : "localhost",                | Host to connect to (when inet)
            "sock_port"   : "2526",                     | Port to connect to (when inet)
            "timeout_in"  : "10",                       | Timeout when waiting for inbound SMTP data
            "timeout_out" : "10"                        | Timeout when waiting for outbound SMTP data
        "unix:/var/sock/a.sock" : {
            "server_name" : "",
            "sock_type"   : "unix",
            "sock_path"   : "/var/run/smtp.sock",
            "timeout_in"  : "10",
            "timeout_out" : "10"


                                                        | Timeouts for callbacks, should be slightly lower
                                                        | than the corresponding timeouts in Postfix
                                                        | Timeouts are ignored if missing.
    "connect_timeout"       : 30,                       | Timeout in seconds for Connect callbacks
    "command_timeout"       : 30,                       | Timeout in seconds for Helo,Mail,Rcpt,Data and Unknown callbacks
    "content_timeout"       : 300,                      | Timeout in seconds Header,Eoh, Body and Eom callbacks
    "dequeue_timeout"       : 300,                      | Timeout in seconds for Dequeue callbacks

    "max_dequeue"           : 5,                        | How many dequeue processes can we run at once
    "check_for_dequeue"     : 60,                       | How often in seconds should a dequeue process be spawned

    "dns_resolvers"         : [                         | Explicit list of DNS resolvers to use
    "dns_timeout"           : 10,                       | Timeout in seconds for DNS lookups
    "dns_retry"             : 2,                        | Number of times a lookup will retry per call
    "dns_servfail_timeout"  : 1000000,                  | How long microseconds a SERVFAIL can take before being considered a timeout
                                                        |     by the internal resolver

    "authserv_id"           : "",         | The authserv-id value to use in Authentication-Results headers
                                                        | This value is optional, and overrides the authserv id set by the
                                                        | MTA in milter mode, and the server_name config option for SMTP
                                                        | mode connections. It is recommended to omit this value unless you
                                                        | have a specific need and understand the implications.

    "hide_none"             : 0,                        | Do not add the Authentication-Results header if the result is 'none'

    "header_indent_style"   : "entry",                  | Optional style to indent/fold Authentication-Results header by.
    "header_fold_at"        : 77,                       | Optional line length to attempt folding of Authentication-Results header at.
                                                        | Header lines over this size will be folded at token boundaries where possible.
    "header_indent_by"      : 4,                        | Optional number of spaces to indent/fold Authentication-Results header by.
                                                        | The style matches those defined in Mail::AuthenticationResults.
                                                        | options are none; no folding
                                                        |             entry; fold on each entry
                                                        |             subentry; fold on each subentry
                                                        |             full; fold on each item
                                                        | the default style is entry, and the default by is 4
                                                        | NB. This only apply when there are no handlers using the
                                                        | legacy string method of adding a section to the header.

    "tempfail_on_error"               : "1",            | Tempfail on errors
    "tempfail_on_error_authenticated" : "0",            | Tempfail on errors for Authenticated IP Connections
    "tempfail_on_error_local"         : "0",            | Tempfail on errors for Local IP Connections
    "tempfail_on_error_trusted"       : "0",            | Tempfail on errors for Trusted IP Connections

    "ip_map" : {                                        | List of IP Addresses or CIDR ranges to remap.
        "" : {                                   | Any incoming IP address which matches a given key
            "ip": "", "helo" : mx.test"          | will be remapped to use the value supplied
        },                                              | This is useful, for example, when internal infrastructure
        "dead:beef::/32" : {                            | connects to your MX via a private internal address, but you
            "ip" : "", "helo" : "mx.test"        | want to run IP based checks (eg SPF) against its external
            "helo_map" : {                              | Additionally match and remap based on a received HELO host
                "" : {                         | from a matching IP address, for milter protocol this is done at the HELO stage, ie
                    "ip" : "",                   | after the connect stage, so handlers which run in the connect stage will not see
                    "helo" : "mx2.test"                 | this remapped ip address. SMTP protocol runs both remaps before passing control to
                }                                       | the connect handlers, so connect handlers see ip addresses remapped by HELO.
        }                                               | IP address instead.

    "handlers" : {                                      | Config for each handlers, can be prefixed with !
                                                        | to disable that handler without having to remove
                                                        | its config.

        "ActiveModule" : {
            "foo" : "bar"
        "!InactiveModule" : {},
                                                        | Additionally, config for a module can be placed in a file
                                                        | with filename /etc/authentication_milter.d/ModuleName.json
                                                        | the contents of which should be the JSON assigned to the
                                                        | entry here.

                                                        | Please see the help for each handler for its individual
                                                        | configuration requirements.


This milter uses Mail::DMARC as a backend for DMARC checks, this module requires that a configuration file is setup.

You should create and populate /etc/mail-dmarc.ini

For DMARC reporting you are also required to setup a datastore, including creating a basic table structure. The detauls of this are to be found in the Mail::DMARC documentation.

At this time forensic reports are not supported by Mail::DMARC or this milter. Only aggregate reports will be generated.

To check reports please use the dmarc_view_reports command, to send reports please use the dmarc_send_reports command. These are included with the Mail::DMARC module.


Marc Bradshaw <>


This software is copyright (c) 2020 by Marc Bradshaw.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.