# Configuring Mailman

Mailman is configured via an “ini”-style configuration file, usually called `mailman.cfg`. Most of the defaults produce a usable system, but you will almost certainly have to set up a few things before you run Mailman for the first time. You only need to include those settings which you want to change; everything else is inherited.

These file system paths are searched in the following order to find your site’s custom `mailman.cfg` file. The first file found is used.

- The file system path specified by the environment variable `$MAILMAN_CONFIG_FILE`
- `mailman.cfg` in the current working directory
- `var/etc/mailman.cfg` relative to the current working directory
- `$HOME/.mailman.cfg`
- `/etc/mailman.cfg`
- `/etc/mailman3/mailman.cfg`
- `../../etc/mailman.cfg` relative to the working directory of `argv[0]`

You can also use the `-C` option to specify an explicit path, and this always takes precedence. See `mailman --help` for more details.

You must restart Mailman for any changes to take effect.

## Which configuration file is in use?

Mailman itself will tell you which configuration file is being used when you run the `mailman info` command:

    $ mailman info
    GNU Mailman 3.1.0b4 (Between The Wheels)
    Python 3.5.3 (default, Jan 19 2017, 14:11:04)
    [GCC 6.3.0 20170118]
    config file: /home/mailman/var/etc/mailman.cfg
    db url: sqlite:////home/mailman/var/data/mailman.db
    devmode: DISABLED
    REST root url: http://localhost:8001/3.1/
    REST credentials: restadmin:restpass

The first time you run this command it will create the configuration file and directory using the built-in defaults, so use `-C` to specify an alternative location. Of course the `info` subcommand shows you other interesting things about your Mailman instance.

## Schemas, templates, and master sections

Mailman’s configuration system is built on top of lazr.config although in general the details aren’t important. Basically there is a `schema.cfg` file included in the source tree, which defines all the available sections and variables, along with global defaults. There is a built-in base `mailman.cfg` file also included in the source tree, which further refines the defaults.

Your custom `mailman.cfg` file, found using the search locations described above, provides the final override for these settings.

The `schema.cfg` file describes every section, variable, and permissible values, so you should consult this for more details. The `schema.cfg` file is included verbatim below.

You will notice two types of special sections in the `schema.cfg` files; those that end with the `.template` suffix, and others which end in a `.master` suffix. There are no other special sections.

Templates provide exactly that: a template for other similarly named sections. So for example, you will see a section labeled `logging.template` which provides some configuration variables and some basic defaults. You will also see a section called `logging.bounce` which refines the `logging.template` section by overriding one or more settings.

If you wanted to change the default logging level for the database component in Mailman, say from `warn` to `info`, you would add this to your `mailman.cfg` file:

    [logging.database]
    level: info

Generally you won’t add new template specialization sections; everything you need is already defined.

You will also see sections labeled with the `.master` suffix. For the most part you can treat these exactly the same as `.template` sections; the differences are only relevant for Mailman developers [1]. An example of a `.master` section is `[runner.master]` which is used to define the defaults for all the runner processes. This is specialized in the built-in `mailman.cfg` file, where you’ll see sections like `[runner.archive]` and `[runner.in]`. You won’t need to specially the master section yourself, but instead you can override some settings in the individual runner sections.

## How do I change a setting?

If you think you want to change something, it can be a little tricky to find exactly the setting you’ll need. The first step is to use the `mailman conf` command to print all the current variables and their values. With no options, this will print all the hundreds of (sorted!) available settings to standard output. You can narrow this down in two ways. You can print just the values of a particular section:

    $ mailman conf -s webservice
    [webservice] admin_pass: restpass
    [webservice] admin_user: restadmin
    [webservice] api_version: 3.1
    [webservice] hostname: localhost
    [webservice] port: 8001
    [webservice] show_tracebacks: yes
    [webservice] use_https: no

Let’s say you wanted to change the port the REST API listens on. Just add this to your `mailman.cfg` file:

    [webservice]
    port: 8080

You can also search for a specific setting:

    $ mailman conf -k prompt
    [shell] prompt: >>>

The `mailman conf` command does not provide documentation about sections or variables. In order to get more information about what a particular variable controls, read the `schema.cfg` and built-in base `mailman.cfg` file.

## schema.cfg

`schema.cfg` defines the ini-file schema and contains documentation for every section and configuration variable.

    # Copyright (C) 2008-2017 by the Free Software Foundation, Inc.
    #
    # This file is part of GNU Mailman.
    #
    # GNU Mailman is free software: you can redistribute it and/or modify it under
    # the terms of the GNU General Public License as published by the Free
    # Software Foundation, either version 3 of the License, or (at your option)
    # any later version.
    #
    # GNU Mailman is distributed in the hope that it will be useful, but WITHOUT
    # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    # FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
    # more details.
    #
    # You should have received a copy of the GNU General Public License along with
    # GNU Mailman.  If not, see <http://www.gnu.org/licenses/>.

    # This is the GNU Mailman configuration schema.  It defines the default
    # configuration options for the core system and plugins.  It uses ini-style
    # formats under the lazr.config regime to define all system configuration
    # options.  See <https://launchpad.net/lazr.config> for details.

    [mailman]
    # This address is the "site owner" address.  Certain messages which must be
    # delivered to a human, but which can't be delivered to a list owner (e.g. a
    # bounce from a list owner), will be sent to this address.  It should point to
    # a human.
    site_owner: changeme@example.com

    # This is the local-part of an email address used in the From field whenever a
    # message comes from some entity to which there is no natural reply recipient.
    # Mailman will append '@' and the host name of the list involved.  This
    # address must not bounce and it must not point to a Mailman process.
    noreply_address: noreply

    # The default language for this server.
    default_language: en

    # Membership tests for posting purposes are usually performed by looking at a
    # set of headers, passing the test if any of their values match a member of
    # the list.  Headers are checked in the order given in this variable.  The
    # value From_ means to use the envelope sender.  Field names are case
    # insensitive.  This is a space separate list of headers.
    sender_headers: from from_ reply-to sender

    # Mail command processor will ignore mail command lines after designated max.
    email_commands_max_lines: 10

    # Default length of time a pending request is live before it is evicted from
    # the pending database.
    pending_request_life: 3d

    # How long should files be saved before they are evicted from the cache?
    cache_life: 7d

    # A callable to run with no arguments early in the initialization process.
    # This runs before database initialization.
    pre_hook:

    # A callable to run with no arguments late in the initialization process.
    # This runs after adapters are initialized.
    post_hook:

    # Which paths.* file system layout to use.
    layout: here

    # Can MIME filtered messages be preserved by list owners?
    filtered_messages_are_preservable: no

    # How should text/html parts be converted to text/plain when the mailing list
    # is set to convert HTML to plaintext?  This names a command to be called,
    # where the substitution variable $filename is filled in by Mailman, and
    # contains the path to the temporary file that the command should read from.
    # The command should print the converted text to stdout.
    html_to_plain_text_command: /usr/bin/lynx -dump $filename

    # Specify what characters are allowed in list names.  Characters outside of
    # the class [-_.+=!$*{}~0-9a-z] matched case insensitively are never allowed,
    # but this specifies a subset as the only allowable characters.  This must be
    # a valid character class regexp or the effect on list creation is
    # unpredictable.
    listname_chars: [-_.0-9a-z]

    [shell]
    # `mailman shell` (also `withlist`) gives you an interactive prompt that you
    # can use to interact with an initialized and configured Mailman system.  Use
    # --help for more information.  This section allows you to configure certain
    # aspects of this interactive shell.

    # Customize the interpreter prompt.
    prompt: >>>

    # Banner to show on startup.
    banner: Welcome to the GNU Mailman shell

    # Use IPython as the shell, which must be found on the system.  Valid values
    # are `no`, `yes`, and `debug` where the latter is equivalent to `yes` except
    # that any import errors will be displayed to stderr.
    use_ipython: no

    # Set this to allow for command line history if readline is available.  This
    # can be as simple as $var_dir/history.py to put the file in the var directory.
    history_file:

    [paths.master]
    # Important directories for Mailman operation.  These are defined here so that
    # different layouts can be supported.   For example, a developer layout would
    # be different from a FHS layout.  Most paths are based off the var_dir, and
    # often just setting that will do the right thing for all the other paths.
    # You might also have to set spool_dir though.
    #
    # Substitutions are allowed, but must be of the form $var where 'var' names a
    # configuration variable in the paths.* section.  Substitutions are expanded
    # recursively until no more $-variables are present.  Beware of infinite
    # expansion loops!
    #
    # This is the root of the directory structure that Mailman will use to store
    # its run-time data.
    var_dir: /var/tmp/mailman
    # This is where the Mailman queue files directories will be created.
    queue_dir: $var_dir/queue
    # This is the directory containing the Mailman 'runner' and 'master' commands
    # if set to the string '$argv', it will be taken as the directory containing
    # the 'mailman' command.
    bin_dir: $argv
    # All list-specific data.
    list_data_dir: $var_dir/lists
    # Directory where log files go.
    log_dir: $var_dir/logs
    # Directory for system-wide locks.
    lock_dir: $var_dir/locks
    # Directory for system-wide data.
    data_dir: $var_dir/data
    # Cache files.
    cache_dir: $var_dir/cache
    # Directory for configuration files and such.
    etc_dir: $var_dir/etc
    # Directory containing Mailman plugins.
    ext_dir: $var_dir/ext
    # Directory where the default IMessageStore puts its messages.
    messages_dir: $var_dir/messages
    # Directory for archive backends to store their messages in.  Archivers should
    # create a subdirectory in here to store their files.
    archive_dir: $var_dir/archives
    # Root directory for site-specific template override files.
    template_dir: $var_dir/templates
    # There are also a number of paths to specific file locations that can be
    # defined.  For these, the directory containing the file must already exist,
    # or be one of the directories created by Mailman as per above.
    #
    # This is where PID file for the master runner is stored.
    pid_file: $var_dir/master.pid
    # Lock file.
    lock_file: $lock_dir/master.lck

    [devmode]
    # Setting enabled to true enables certain safeguards and other behavior
    # changes that make developing Mailman easier.  For example, it forces the
    # SMTP RCPT TO recipients to be a test address so that no messages are
    # accidentally sent to real addresses.
    enabled: no

    # Set this to an address to force the SMTP RCPT TO recipents when devmode is
    # enabled.  This way messages can't be accidentally sent to real addresses.
    recipient:

    # This gets set by the testing layers so that the runner subprocesses produce
    # predictable dates and times.
    testing: no

    # Time-outs for starting up various test subprocesses, such as the LMTP and
    # REST servers.  This is only used for the test suite, so if you're seeing
    # test failures, try increasing the wait time.
    wait: 60s

    [passwords]
    # Where can we find the passlib configuration file?  The path can be either a
    # file system path or a Python import path.  If the value starts with python:
    # then it is a Python import path, otherwise it is a file system path.  File
    # system paths must be absolute since no guarantees are made about the current
    # working directory.  Python paths should not include the trailing .cfg, which
    # the file must end with.
    configuration: python:mailman.config.passlib

    # When Mailman generates them, this is the default length of passwords.
    password_length: 8

    [runner.master]
    # Define which runners, and how many of them, to start.

    # The full import path to the class for this runner.
    class: mailman.core.runner.Runner

    # The queue directory path that this runner scans.  This is ignored for
    # runners that don't manage a queue directory.
    path: $QUEUE_DIR/$name

    # The number of parallel runners.  This must be a power of 2.  This is ignored
    # for runners that don't manage a queue directory.
    instances: 1

    # Whether to start this runner or not.
    start: yes

    # The maximum number of restarts for this runner.  When the runner exits
    # because of an error or other unexpected problem, it is automatically
    # restarted, until the maximum number of restarts has been reached.
    max_restarts: 10

    # The sleep interval for the runner.  It wakes up once every interval to
    # process the files in its slice of the queue directory.  Some runners may
    # ignore this.
    sleep_time: 1s

    [database]
    # The class implementing the IDatabase.
    class: mailman.database.sqlite.SQLiteDatabase

    # Use this to set the Storm database engine URL.  You generally have one
    # primary database connection for all of Mailman.  List data and most rosters
    # will store their data in this database, although external rosters may access
    # other databases in their own way.  This string supports standard
    # 'configuration' substitutions.
    url: sqlite:///$DATA_DIR/mailman.db
    debug: no

    [logging.template]
    # This defines various log settings.  The options available are:
    #
    # - level     -- Overrides the default level; this may be any of the
    #                standard Python logging levels, case insensitive.
    # - format    -- Overrides the default format string
    # - datefmt   -- Overrides the default date format string
    # - path      -- Overrides the default logger path.  This may be a relative
    #                path name, in which case it is relative to Mailman's LOG_DIR,
    #                or it may be an absolute path name.  You cannot change the
    #                handler class that will be used.
    # - propagate -- Boolean specifying whether to propagate log message from this
    #                logger to the root "mailman" logger.  You cannot override
    #                settings for the root logger.
    #
    # In this section, you can define defaults for all loggers, which will be
    # prefixed by 'mailman.'.  Use subsections to override settings for specific
    # loggers.  The names of the available loggers are:
    #
    # - archiver        --  All archiver output
    # - bounce          --  All bounce processing logs go here
    # - config          --  Configuration issues
    # - database        --  Database logging (SQLAlchemy and Alembic)
    # - debug           --  Only used for development
    # - error           --  All exceptions go to this log
    # - fromusenet      --  Information related to the Usenet to Mailman gateway
    # - http            --  Internal wsgi-based web interface
    # - locks           --  Lock state changes
    # - mischief        --  Various types of hostile activity
    # - runner          --  Runner process start/stops
    # - smtp            --  Successful SMTP activity
    # - smtp-failure    --  Unsuccessful SMTP activity
    # - subscribe       --  Information about leaves/joins
    # - vette           --  Message vetting information
    format: %(asctime)s (%(process)d) %(message)s
    datefmt: %b %d %H:%M:%S %Y
    propagate: no
    level: info
    path: mailman.log

    [logging.root]

    [logging.archiver]

    [logging.bounce]
    path: bounce.log

    [logging.config]

    [logging.database]
    level: warn

    [logging.debug]
    path: debug.log
    level: info

    [logging.error]

    [logging.fromusenet]

    [logging.http]

    [logging.locks]

    [logging.mischief]

    [logging.runner]

    [logging.smtp]
    path: smtp.log

    # The smtp logger defines additional options for handling the logging of each
    # attempted delivery.  These format strings specify what information is logged
    # for every message, every successful delivery, every refused delivery and
    # every recipient failure.  To disable a status message, set the value to 'no'
    # (without the quotes).
    #
    # These template strings accept the following set of substitution
    # placeholders, if available.
    #
    # msgid     -- the Message-ID of the message in question
    # listname  -- the fully-qualified list name
    # sender    -- the sender if available
    # recip     -- the recipient address if available, or the number of
    #              recipients being delivered to
    # size      -- the approximate size of the message in bytes
    # seconds   -- the number of seconds the operation took
    # refused   -- the number of refused recipients
    # smtpcode  -- the SMTP success or failure code
    # smtpmsg   -- the SMTP success or failure message

    every: $msgid smtp to $listname for $recip recips, completed in $time seconds
    success: $msgid post to $listname from $sender, $size bytes
    refused: $msgid post to $listname from $sender, $size bytes, $refused failures
    failure: $msgid delivery to $recip failed with code $smtpcode, $smtpmsg

    [logging.subscribe]

    [logging.vette]

    [webservice]
    # The hostname at which admin web service resources are exposed.
    hostname: localhost

    # The port at which the admin web service resources are exposed.
    port: 8001

    # Whether or not requests to the web service are secured through SSL.
    use_https: no

    # Whether or not to show tracebacks in an HTTP response for a request that
    # raised an exception.
    show_tracebacks: yes

    # The API version number for the current (highest) API.
    api_version: 3.1

    # The administrative username.
    admin_user: restadmin

    # The administrative password.
    admin_pass: restpass

    [language.master]
    # Template for language definitions.  The section name must be [language.xx]
    # where xx is the 2-character ISO code for the language.

    # The English name for the language.
    description: English (USA)
    # And the default character set for the language.
    charset: us-ascii
    # Whether the language is enabled or not.
    enabled: yes

    # Language charsets as imported from Mailman 2.1 defaults
    # Ref: http://www.lingoes.net/en/translator/langcode.htm
    [language.ar]
    description: Arabic
    charset: utf-8
    enabled: yes

    [language.ast]
    description: Asturian
    charset: iso-8859-1
    enabled: yes

    [language.ca]
    description: Catalan
    charset: utf-8
    enabled: yes

    [language.cs]
    description: Czech
    charset: iso-8859-2
    enabled: yes

    [language.da]
    description: Danish
    charset: iso-8859-1
    enabled: yes

    [language.de]
    description: German
    charset: iso-8859-1
    enabled: yes

    [language.el]
    description: Greek
    charset: iso-8859-7
    enabled: yes

    [language.es]
    description: Spanish
    charset: iso-8859-1
    enabled: yes

    [language.et]
    description: Estonian
    charset: iso-8859-15
    enabled: yes

    [language.eu]
    # Basque
    description: Euskara
    charset: iso-8859-15
    enabled: yes

    [language.fi]
    description: Finnish
    charset: iso-8859-1
    enabled: yes

    [language.fr]
    description: French
    charset: iso-8859-1
    enabled: yes

    [language.gl]
    description: Galician
    charset: utf-8
    enabled: yes

    [language.he]
    description: Hebrew
    charset: utf-8
    enabled: yes

    [language.hr]
    description: Croatian
    charset: iso-8859-2
    enabled: yes

    [language.hu]
    description: Hungarian
    charset: iso-8859-2
    enabled: yes

    [language.ia]
    description: Interlingua
    charset: iso-8859-15
    enabled: yes

    [language.it]
    description: Italian
    charset: iso-8859-1
    enabled: yes

    [language.ja]
    description: Japanese
    charset: euc-jp
    enabled: yes

    [language.ko]
    description: Korean
    charset: euc-kr
    enabled: yes

    [language.lt]
    description: Lithuanian
    charset: iso-8859-13
    enabled: yes

    [language.nl]
    description: Dutch
    charset: iso-8859-1
    enabled: yes

    [language.no]
    description: Norwegian
    charset: iso-8859-1
    enabled: yes

    [language.pl]
    description: Polish
    charset: iso-8859-2
    enabled: yes

    [language.pt]
    description: Protuguese
    charset: iso-8859-1
    enabled: yes

    [language.pt_BR]
    description: Protuguese (Brazil)
    charset: iso-8859-1
    enabled: yes

    [language.ro]
    description: Romanian
    charset: iso-8859-2
    enabled: yes

    [language.ru]
    description: Russian
    charset: koi8-r
    enabled: yes

    [language.sk]
    description: Slovak
    charset: utf-8
    enabled: yes

    [language.sl]
    description: Slovenian
    charset: iso-8859-2
    enabled: yes

    [language.sr]
    description: Serbian
    charset: utf-8
    enabled: yes

    [language.sv]
    description: Swedish
    charset: iso-8859-1
    enabled: yes

    [language.tr]
    description: Turkish
    charset: iso-8859-9
    enabled: yes

    [language.uk]
    description: Ukrainian
    charset: utf-8
    enabled: yes

    [language.vi]
    description: Vietnamese
    charset: utf-8
    enabled: yes

    [language.zh_CN]
    description: Chinese
    charset: utf-8
    enabled: yes

    [language.zh_TW]
    description: Chinese (Taiwan)
    charset: utf-8
    enabled: yes

    [antispam]
    # This section defines basic antispam detection settings.

    # This value contains lines which specify RFC 822 headers in the email to
    # check for spamminess.  Each line contains a `key: value` pair, where the key
    # is the header to check and the value is a Python regular expression to match
    # against the header's value.  Multiple checks should be entered as multiline
    # value with leading spaces:
    #
    # header_checks:
    #   X-Spam: (yes|maybe)
    #   Authentication-Results: mail.example.com; dmarc=(fail|quarantine)
    #
    # The header value and regular expression are always matched
    # case-insensitively.
    header_checks:

    # The chain to jump to if any of the header patterns matches.  This must be
    # the name of an existing chain such as 'discard', 'reject', 'hold', or
    # 'accept', otherwise 'hold' will be used.
    jump_chain: hold

    [mta]
    # The class defining the interface to the incoming mail transport agent.
    incoming: mailman.mta.postfix.LMTP

    # The callable implementing delivery to the outgoing mail transport agent.
    # This must accept three arguments, the mailing list, the message, and the
    # message metadata dictionary.
    outgoing: mailman.mta.deliver.deliver

    # How to connect to the outgoing MTA.  If smtp_user and smtp_pass is given,
    # then Mailman will attempt to log into the MTA when making a new connection.
    smtp_host: localhost
    smtp_port: 25
    smtp_user:
    smtp_pass:

    # Where the LMTP server listens for connections.  Use 127.0.0.1 instead of
    # localhost for Postfix integration, because Postfix only consults DNS
    # (e.g. not /etc/hosts).
    lmtp_host: 127.0.0.1
    lmtp_port: 8024

    # Ceiling on the number of recipients that can be specified in a single SMTP
    # transaction.  Set to 0 to submit the entire recipient list in one
    # transaction.
    max_recipients: 500

    # Ceiling on the number of SMTP sessions to perform on a single socket
    # connection.  Some MTAs have limits.  Set this to 0 to do as many as we like
    # (i.e. your MTA has no limits).  Set this to some number great than 0 and
    # Mailman will close the SMTP connection and re-open it after this number of
    # consecutive sessions.
    max_sessions_per_connection: 0

    # Maximum number of simultaneous subthreads that will be used for SMTP
    # delivery.  After the recipients list is chunked according to max_recipients,
    # each chunk is handed off to the SMTP server by a separate such thread.  If
    # your Python interpreter was not built for threads, this feature is disabled.
    # You can explicitly disable it in all cases by setting max_delivery_threads
    # to 0.
    max_delivery_threads: 0

    # How long should messages which have delivery failures continue to be
    # retried?  After this period of time, a message that has failed recipients
    # will be dequeued and those recipients will never receive the message.
    delivery_retry_period: 5d

    # These variables control the format and frequency of VERP-like delivery for
    # better bounce detection.  VERP is Variable Envelope Return Path, defined
    # here:
    #
    # http://cr.yp.to/proto/verp.txt
    #
    # This involves encoding the address of the recipient as Mailman knows it into
    # the envelope sender address (i.e. RFC 5321 MAIL FROM).  Thus, no matter what
    # kind of forwarding the recipient has in place, should it eventually bounce,
    # we will receive an unambiguous notice of the bouncing address.
    #
    # However, we're technically only "VERP-like" because we're doing the envelope
    # sender encoding in Mailman, not in the MTA.  We do require cooperation from
    # the MTA, so you must be sure your MTA can be configured for extended address
    # semantics.
    #
    # The first variable describes how to encode VERP envelopes.  It must contain
    # these three string interpolations, which get filled in by Mailman:
    #
    # $bounces -- the list's -bounces robot address will be set here
    # $local   -- the recipient address's local mailbox part will be set here
    # $domain  -- the recipient address's domain name will be set here
    #
    # This example uses the default below.
    #
    # FQDN list address is: mylist@dom.ain
    # Recipient is:         aperson@a.nother.dom
    #
    # The envelope sender will be mylist-bounces+aperson=a.nother.dom@dom.ain
    #
    # Note that your MTA /must/ be configured to deliver such an addressed message
    # to mylist-bounces!
    verp_delimiter: +
    verp_format: ${bounces}+${local}=${domain}

    # For nicer confirmation emails, use a VERP-like format which encodes the
    # confirmation cookie in the reply address.  This lets us put a more user
    # friendly Subject: on the message, but requires cooperation from the MTA.
    # Format is like verp_format, but with the following substitutions:
    #
    # $address  -- the list-confirm address
    # $cookie   -- the confirmation cookie
    verp_confirm_format: $address+$cookie

    # This regular expression unambiguously decodes VERP addresses, which will be
    # placed in the To: (or other, depending on the MTA) header of the bounce
    # message by the bouncing MTA.  Getting this right is critical -- and tricky.
    # Learn your Python regular expressions.  It must define exactly three named
    # groups, `bounces`, `local` and `domain`, with the same definition as above.
    # It will be compiled case-insensitively.
    verp_regexp: ^(?P<bounces>[^+]+?)\+(?P<local>[^=]+)=(?P<domain>[^@]+)@.*$

    # This is analogous to verp_regexp, but for splitting apart the
    # verp_confirm_format.  MUAs have been observed that mung
    #
    # From: local_part@host
    #
    # into
    #
    # To: "local_part" <local_part@host>
    #
    # when replying, so we skip everything up to '<' if any.
    verp_confirm_regexp: ^(.*<)?(?P<addr>[^+]+?)\+(?P<cookie>[^@]+)@.*$

    # Set this to 'yes' to enable VERP-like (more user friendly) confirmations.
    verp_confirmations: no

    # Another good opportunity is when regular delivery is personalized.  Here
    # again, we're already incurring the performance hit for addressing each
    # individual recipient.  Set this to 'yes' to enable VERPs on all personalized
    # regular deliveries (personalized digests aren't supported yet).
    verp_personalized_deliveries: no

    # And finally, we can VERP normal, non-personalized deliveries.  However,
    # because it can be a significant performance hit, we allow you to decide how
    # often to VERP regular deliveries.  This is the interval, in number of
    # messages, to do a VERP recipient address.  The same variable controls both
    # regular and digest deliveries.  Set to 0 to disable occasional VERPs, set to
    # 1 to VERP every delivery, or to some number > 1 for only occasional VERPs.
    verp_delivery_interval: 0

    # VERP format and regexp for probe messages.
    verp_probe_format: $bounces+$token@$domain
    verp_probe_regexp: ^(?P<bounces>[^+]+?)\+(?P<token>[^@]+)@.*$
    # Set this 'yes' to activate VERP probe for disabling by bounce.
    verp_probes: no

    # This is the maximum number of automatic responses sent to an address because
    # of -request messages or posting hold messages.  This limit prevents response
    # loops between Mailman and misconfigured remote email robots.  Mailman
    # already inhibits automatic replies to any message labeled with a header
    # "Precendence: bulk|list|junk".  This is a fallback safety valve so it should
    # be set fairly high.  Set to 0 for no limit (probably useful only for
    # debugging).
    max_autoresponses_per_day: 10

    # Some list posts and mail to the -owner address may contain DomainKey or
    # DomainKeys Identified Mail (DKIM) signature headers <http://www.dkim.org/>.
    # Various list transformations to the message such as adding a list header or
    # footer or scrubbing attachments or even reply-to munging can break these
    # signatures.  It is generally felt that these signatures have value, even if
    # broken and even if the outgoing message is resigned.  However, some sites
    # may wish to remove these headers by setting this to 'yes'.
    remove_dkim_headers: no

    # Where can we find the mail server specific configuration file?  The path can
    # be either a file system path or a Python import path.  If the value starts
    # with python: then it is a Python import path, otherwise it is a file system
    # path.  File system paths must be absolute since no guarantees are made about
    # the current working directory.  Python paths should not include the trailing
    # .cfg, which the file must end with.
    configuration: python:mailman.config.postfix

    [bounces]
    # How often should the bounce runner process queued detected bounces?
    register_bounces_every: 15m

    [archiver.master]
    # To add new archivers, define a new section based on this one, overriding the
    # following values.

    # The class implementing the IArchiver interface.
    class:

    # Set this to 'yes' to enable the archiver.
    enable: no

    # Additional configuration for the archiver.  The path can be either a file
    # system path or a Python import path.  If the value starts with python: then
    # it is a Python import path, otherwise it is a file system path.  File system
    # paths must be absolute since no guarantees are made about the current
    # working directory.  Python paths should not include the trailing .cfg, which
    # the file must end with.
    configuration: changeme

    # When sending the message to the archiver, you have the option of
    # "clobbering" the Date: header, specifically to make it more sane.  Some
    # archivers can't handle dates that are wildly off from reality.  This does
    # not change the Date: header for any other delivery vector except this
    # specific archive.
    #
    # When the original Date header is clobbered, it will always be stored in
    # X-Original-Date.  The new Date header will always be set to the date at
    # which the messages was received by the Mailman server, in UTC.
    #
    # Your options here are:
    # * never  -- Leaves the original Date header alone.
    # * always -- Always override the Date header.
    # * maybe  -- Override the Date only if it is outside the clobber_skew period.
    clobber_date: maybe
    clobber_skew: 1d

    [archiver.mhonarc]
    # This is the stock MHonArc archiver.
    class: mailman.archiving.mhonarc.MHonArc
    configuration: python:mailman.config.mhonarc

    [archiver.mail_archive]
    # This is the stock mail-archive.com archiver.
    class: mailman.archiving.mailarchive.MailArchive
    configuration: python:mailman.config.mail_archive

    [archiver.prototype]
    # This is a prototypical sample archiver.
    class: mailman.archiving.prototype.Prototype

    [styles]
    # Python import paths inside which components are searched for which implement
    # the IStyle interface.  Use one path per line.
    paths:
        mailman.styles

    # The default style to apply if nothing else was requested.  The value is the
    # name of an existing style.  If no such style exists, no style will be
    # applied.
    default: legacy-default

    [digests]
    # Headers which should be kept in both RFC 1153 (plain) and MIME digests.  RFC
    # 1153 also specifies these headers in this exact order, so order matters.
    # These are space separated and case insensitive.
    mime_digest_keep_headers:
        Date From To Cc Subject Message-ID Keywords
        In-Reply-To References Content-Type MIME-Version
        Content-Transfer-Encoding Precedence Reply-To
        Message List-Post

    plain_digest_keep_headers:
        Message Date From
        Subject To Cc
        Message-ID Keywords
        Content-Type

    [nntp]
    # Set these variables if you need to authenticate to your NNTP server for
    # Usenet posting or reading.  Leave these blank if no authentication is
    # necessary.
    user:
    password:

    # Host and port of the NNTP server to connect to.  Leave these blank to use
    # the default localhost:119.
    host:
    port:

    # This controls how headers must be cleansed in order to be accepted by your
    # NNTP server.  Some servers like INN reject messages containing prohibited
    # headers, or duplicate headers.  The NNTP server may reject the message for
    # other reasons, but there's little that can be programmatically done about
    # that.
    #
    # These headers (case ignored) are removed from the original message.  This is
    # a whitespace separate list of headers.
    remove_headers:
        nntp-posting-host nntp-posting-date x-trace
        x-complaints-to xref date-received posted
        posting-version relay-version received

    # These headers are left alone, unless there are duplicates in the original
    # message.  Any second and subsequent headers are rewritten to the second
    # named header (case preserved).  This is a list of header pairs, one pair per
    # line.
    rewrite_duplicate_headers:
        To X-Original-To
        CC X-Original-CC
        Content-Transfer-Encoding X-Original-Content-Transfer-Encoding
        MIME-Version X-MIME-Version

    [dmarc]
    # RFC 7489 - Domain-based Message Authentication, Reporting, and Conformance.
    # https://en.wikipedia.org/wiki/DMARC

    # Parameters for DMARC DNS lookups.  If you are seeing 'DNSException: Unable
    # to query DMARC policy ...' entries in your error log, you may need to adjust
    # these.
    #
    # The time to wait for a response from a name server before timeout.
    resolver_timeout: 3s
    # The total time to spend trying to get an answer to the DNS question.
    resolver_lifetime: 5s

    # A URL from which to retrieve the data for the algorithm that computes
    # Organizational Domains for DMARC policy lookup purposes.  This can be
    # anything handled by the Python urllib.request.urlopen function.  See
    # https://publicsuffix.org/list/ for info.
    org_domain_data_url: https://publicsuffix.org/list/public_suffix_list.dat

    # How long should the local suffix list be used before it's considered out of
    # date.  After this amount of time a new list will be downloaded, but if it
    # can't be accessed, old data will still be used.
    cache_lifetime: 7d

## mailman.cfg

Configuration settings provided in the built-in base `mailman.cfg` file overrides those provided in `schema.cfg`.

    # Copyright (C) 2008-2017 by the Free Software Foundation, Inc.
    #
    # This file is part of GNU Mailman.
    #
    # GNU Mailman is free software: you can redistribute it and/or modify it under
    # the terms of the GNU General Public License as published by the Free
    # Software Foundation, either version 3 of the License, or (at your option)
    # any later version.
    #
    # GNU Mailman is distributed in the hope that it will be useful, but WITHOUT
    # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    # FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
    # more details.
    #
    # You should have received a copy of the GNU General Public License along with
    # GNU Mailman.  If not, see <http://www.gnu.org/licenses/>.

    # This is the absolute bare minimum base configuration file.  User supplied
    # configurations are pushed onto this.

    [paths.local]
    # Directories as specified in schema.cfg, putting most stuff in
    # /var/tmp/mailman

    [paths.dev]
    # Convenient development layout where everything is put in a directory above
    # where the mailman.cfg file lives.
    var_dir: $cfg_file/../..

    [paths.here]
    # Layout where the var directory is put in the current working directory.
    var_dir: $cwd/var

    [paths.fhs]
    # Filesystem Hiearchy Standard 2.3
    # http://www.pathname.com/fhs/pub/fhs-2.3.html
    bin_dir: /sbin
    var_dir: /var/lib/mailman
    queue_dir: /var/spool/mailman
    log_dir: /var/log/mailman
    lock_dir: /var/lock/mailman
    etc_dir: /etc
    ext_dir: /etc/mailman.d
    pid_file: /var/run/mailman/master.pid

    [language.en]

    [runner.archive]
    class: mailman.runners.archive.ArchiveRunner

    [runner.bad]
    class: mailman.runners.fake.BadRunner
    # The bad runner is just a placeholder for its switchboard.
    start: no

    [runner.bounces]
    class: mailman.runners.bounce.BounceRunner

    [runner.command]
    class: mailman.runners.command.CommandRunner

    [runner.in]
    class: mailman.runners.incoming.IncomingRunner

    [runner.lmtp]
    class: mailman.runners.lmtp.LMTPRunner
    path:

    [runner.nntp]
    class: mailman.runners.nntp.NNTPRunner

    [runner.out]
    class: mailman.runners.outgoing.OutgoingRunner

    [runner.pipeline]
    class: mailman.runners.pipeline.PipelineRunner

    [runner.rest]
    class: mailman.runners.rest.RESTRunner
    path:

    [runner.retry]
    class: mailman.runners.retry.RetryRunner
    sleep_time: 15m

    [runner.shunt]
    class: mailman.runners.fake.ShuntRunner
    # The shunt runner is just a placeholder for its switchboard.
    start: no

    [runner.virgin]
    class: mailman.runners.virgin.VirginRunner

    [runner.digest]
    class: mailman.runners.digest.DigestRunner

[1] | The technical differences are described in the lazr.config package, upon which Mailman’s configuration system is based.