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:

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 []. 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:

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 defines the ini-file schema and contains documentation for every section and configuration variable.

# Copyright (C) 2008-2020 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 <>.

# 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 <> for details.

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

# 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

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

# These hooks are deprecated, but are kept here so as not to break existing
# configuration files.  However, these hooks are not run.  Define a plugin
# instead.

# Plugin configuration section template.
# To add a plugin, instantiate this section (changing `master` to whatever
# your plugin's name is), and define at least a `path` and a `class`.  When
# the plugin is loaded, its subpackages will be search for components matching
# the following interfaces:
# - IChain for new chains
# - ICliSubCommand - `mailman` subcommands
# - IEmailCommand - new email commands
# - IHandler for new handlers
# - IPipeline for new pipelines
# - IRule for new rules
# - IStyle for new styles.
# See the IPlugin interface for more details.

# The full Python import path for you IPlugin implementing class.  It is
# required to provide this.

# Whether to enable this plugin or not.
enabled: no

# Additional configuration file for this plugin.  If the value starts with
# `python:` it is a Python import path, in which case the value should not
# include the trailing .cfg (although the file is required to have this
# suffix).  Without `python:`, it is a file system path, and must be an
# absolute path, since no guarantees are made about the current working
# directory.

# Package (as a dotted Python import path) to search for components that this
# plugin wants to add, such as ISTyles, IRules, etc.  If not given, the
# plugin's name is used.

# `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 commit() to commit changes.
 Use abort() to discard changes since the last commit.
 Exit with ctrl+D does an implicit commit() but exit() does not.

# 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/ to put the file in the var directory.

# 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/
# Lock file.
lock_file: $lock_dir/master.lck

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

# 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

# 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

# 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

# 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

# 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
# - plugins         --  Plugin logs
# - runner          --  Runner process start/stops
# - smtp            --  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



path: bounce.log


level: warn

path: debug.log
level: info



format: %(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s"



path: plugins.log


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



# 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

# Number of workers to start.
workers: 2

# Configuration for webservice.
configuration: python:mailman.config.gunicorn

# 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:
description: Arabic
charset: utf-8
enabled: yes

description: Asturian
charset: iso-8859-1
enabled: yes

description: Catalan
charset: utf-8
enabled: yes

description: Czech
charset: iso-8859-2
enabled: yes

description: Danish
charset: iso-8859-1
enabled: yes

description: German
charset: utf-8
enabled: yes

description: Greek
charset: iso-8859-7
enabled: yes

description: Spanish
charset: iso-8859-1
enabled: yes

description: Estonian
charset: iso-8859-15
enabled: yes

# Basque
description: Euskara
charset: iso-8859-15
enabled: yes

description: Finnish
charset: iso-8859-1
enabled: yes

description: French
charset: utf-8
enabled: yes

description: Galician
charset: utf-8
enabled: yes

description: Hebrew
charset: utf-8
enabled: yes

description: Croatian
charset: iso-8859-2
enabled: yes

description: Hungarian
charset: iso-8859-2
enabled: yes

description: Interlingua
charset: iso-8859-15
enabled: yes

description: Italian
charset: iso-8859-1
enabled: yes

description: Japanese
charset: euc-jp
enabled: yes

description: Korean
charset: euc-kr
enabled: yes

description: Lithuanian
charset: iso-8859-13
enabled: yes

description: Dutch
charset: iso-8859-1
enabled: yes

description: Norwegian
charset: iso-8859-1
enabled: yes

description: Polish
charset: iso-8859-2
enabled: yes

description: Protuguese
charset: iso-8859-1
enabled: yes

description: Protuguese (Brazil)
charset: iso-8859-1
enabled: yes

description: Romanian
charset: iso-8859-2
enabled: yes

description: Russian
charset: koi8-r
enabled: yes

description: Slovak
charset: utf-8
enabled: yes

description: Slovenian
charset: iso-8859-2
enabled: yes

description: Serbian
charset: utf-8
enabled: yes

description: Swedish
charset: iso-8859-1
enabled: yes

description: Turkish
charset: iso-8859-9
enabled: yes

description: Ukrainian
charset: utf-8
enabled: yes

description: Vietnamese
charset: utf-8
enabled: yes

description: Chinese
charset: utf-8
enabled: yes

description: Chinese (Taiwan)
charset: utf-8
enabled: yes

# This section defines email authetication parameters, in particular, with
# respect to the ARC(Authenticated-Recieved-Chain) protocol. See
# for reference.
# The DMARC protocol is the industry standard for cryptographically validating
# both the content and originating source of email. However it is regularly
# the case that mailing lists break this source of authentication via modifying
# the From, and possibly other headers, and altering the contents of
# emails by, say, adding a common footer to outgoing mail.
# The ARC protocol is the industry standard for rectify this.
# ARC cryptographically seals the outgoing emails by adding a collection
# of headers.  These headers act quite analagously to a chain of DKIM
# signatures, where each intermediary validates the ARC signature(if one exists)
# of the incomming message, and then appends its own collection of header fields.
# Enabling this protocol makes it possible for email service providers
# to validate the content & originator of an email, even if it has taken multiple
# steps from the originator to the recipient.
# The general implementation of ARC within Mailman is addition of two
# additional handlers to the pipeline.  One, ate the very beginning of the
# pipeline cryptographically validaties the incomming ARC headers before the
# message has been modified, and appends its results to the
# Authentication-Results header.
# The second handler is at the end of the pipeline.  It cryptographically
# signs the message, with all modifications that have been made, along
# with the analysis of the validation handler, and adds its output as
# a new set of ARC header fields.

# This flag globally enables ARC signing & validation. To enable, set this to
# yes.
enabled: no

# DKIM & DMARC authentication checks on incoming email is critical to using ARC
# successfully. Mailman can do these check on its own, but if you already perform
# these checks earlier in your pipeline, say via a milter previous to Mailman,
# they can be used instead, as long as you specify your domain as a trusted
# domain below.  If those checks are not placed in an Authentication-Results
# header from a trusted domain they will be ignored.
dmarc: yes
dkim: yes

# This is the domain name of your mailserver.  Necessary to set correctly.
# authserv_id:

# This list should include all additional domains
# that you manage that may be handling your incoming mail
# Only necessary to update if there are local domains or subdomains
# that are performing DKIM, DMARC, or SPF checks.

# trusted_authserv_ids:,

# In order for your server to be able to cryptographical sign its messages
# a DKIM public/private key pair will need to be created.
# See:
# for reference.  The following parameters let the software find your
# private & public keys

# privkey: /some/location/yourprivatekey.pem
# selector: test
# domain:


# This configures the headers that will be cryptographically signed
# This list is what is recommended by the DKIM & ARC specifications.
# Inclusion of the From header is mandatory.
sig_headers: From, Sender, Reply-To, Subject, Date, Message-ID, To, Cc, MIME-Version, Content-Type, Content-Transfer-Encoding, Content-ID, Content-Description, Resent-Date, Resent-From, Resent-Sender, Resent-To, Resent-Cc, Resent-Message-ID, In-Reply-To, References, List-Id, List-Help, List-Unsubscribe, List-Subscribe, List-Post, List-Owner, List-Archive

# 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:; dmarc=(fail|quarantine)
# The header value and regular expression are always matched
# case-insensitively.

# 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

# 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

# One of smtp/smtps/starttls, specifies the protocol Mailman will use when
# connecting.  Typically will correspond to smtp_port: 25 -> smtp, 465 -> smtps,
# 587 -> starttls.
smtp_secure_mode: smtp

# When smtp_secure_mode is smtps or starttls, whether to require a server cert
# and verify it.
smtp_verify_cert: yes

# When smtp_secure_mode is smtps or starttls, whether to check that the
# server certificate specifies the same hostname as smtp_host.
smtp_verify_hostname: yes

# Where the LMTP server listens for connections.  Use instead of
# localhost for Postfix integration, because Postfix only consults DNS
# (e.g. not /etc/hosts).
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:
# 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 <>.
# 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

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

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

# The class implementing the IArchiver interface.

# 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

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

# This is the stock archiver.
class: mailman.archiving.mailarchive.MailArchive
configuration: python:mailman.config.mail_archive

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

# 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

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

    Message Date From
    Subject To Cc
    Message-ID Keywords

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

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

# 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.
    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.
    To X-Original-To
    CC X-Original-CC
    Content-Transfer-Encoding X-Original-Content-Transfer-Encoding
    MIME-Version X-MIME-Version

# RFC 7489 - Domain-based Message Authentication, Reporting, and Conformance.

# 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
# for info.

# 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


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

# Copyright (C) 2008-2020 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 <>.

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

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

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

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

# Filesystem Hiearchy Standard 2.3
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/


class: mailman.runners.archive.ArchiveRunner

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

class: mailman.runners.bounce.BounceRunner
sleep_time: 2m

class: mailman.runners.command.CommandRunner

class: mailman.runners.incoming.IncomingRunner

class: mailman.runners.lmtp.LMTPRunner

class: mailman.runners.nntp.NNTPRunner

class: mailman.runners.outgoing.OutgoingRunner

class: mailman.runners.pipeline.PipelineRunner


class: mailman.runners.retry.RetryRunner
sleep_time: 15m

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


class: mailman.runners.digest.DigestRunner
[1]The technical differences are described in the lazr.config package, upon which Mailman’s configuration system is based.