Mailman Suite Installation

Mailman 3 consists of a collection of separate-but-linked projects, each of which has its own setup guide. This is handy when you want to focus on development for a single piece of Mailman, but is less useful for setting up a complete installation suitable for production use.

Setting up Web UI

Postorius and Hyperkitty are Mailman’s official Web UI and Archiver. Both of them are Django based apps and can be integrated into an existing Django installation/website. Here are the parameters that will affect how they function. These parameters are configured in your Django Site’s settings.py.

  • MAILMAN_REST_API_URL : Complete URL to the Core’s REST API Server. Usually, Mailman Core listens on port 8001 for REST API. e.g. http://localhost:8001/

  • MAILMAN_REST_API_USER : Username for the Core’s REST API, default value in core is ‘restadmin’ if not set.

  • MAILMAN_REST_API_PASS : Password for Mailman REST API User, default value in core is ‘restpass’ if not set.

  • MAILMAN_ARCHIVER_KEY : The Key used to authenticate the emails for archiving in Hyperkitty. Its value should be exactly same as set in Core.

    Also note that the value in settings.py will be within single quotes, but in mailman.cfg it will be without any quotes.

  • FILTER_VHOST : Filter the list of available lists in Hyperkitty depending on the domain it is being currently served from. Mailman 3 supports multiple domains in a single installation.

  • Add compressor.finders.CompressorFinder to your STATICFILES_FINDERS.

  • LOGIN_URL = ‘account_login’

  • LOGIN_REDIRECT_URL = ‘list_index’

  • LOGOUT_URL = ‘account_logout’

  • This setting is for django-compressor which is used here to compile and compress static files:

    COMPRESS_PRECOMPILERS = (
      ('text/x-scss', 'sassc -t compressed {infile} {outfile}'),
      ('text/x-sass', 'sassc -t compressed {infile} {outfile}'),
    )
    
  • Hyperkitty uses `django-haystack`_ for its full text search:

    HAYSTACK_CONNECTIONS = {
          'default': {
          'ENGINE': 'haystack.backends.whoosh_backend.WhooshEngine',
          'PATH': os.path.join(BASE_DIR, "fulltext_index"),
          # You can also use the Xapian engine, it's faster and more accurate,
          # but requires another library.
          # http://django-haystack.readthedocs.io/en/v2.4.1/installing_search_engines.html#xapian
          # Example configuration for Xapian:
          #'ENGINE': 'xapian_backend.XapianEngine'
          },
    }
    
  • Hyperkitty uses `django_q`_ as a task queue. It supports various different backends like Redis, Disque, IronMQ, SQS etc. Please check the documentation to better understand how to configure it. The most basic setup where it uses Django orm as the queue can be configured using the settings below:

    Q_CLUSTER = {
       'timeout': 300,
       'save_limit': 100,
       'orm': 'default',
    }
    

These settings below are required by Django-Allauth:

  • ACCOUNT_AUTHENTICATION_METHOD = “username_email”
  • ACCOUNT_EMAIL_REQUIRED = True
  • ACCOUNT_EMAIL_VERIFICATION = “mandatory”
  • ACCOUNT_DEFAULT_HTTP_PROTOCOL = “http”
  • ACCOUNT_UNIQUE_EMAIL = True

Setting up mail server

In order to run Mailman you need have a mail transport agent (MTA), or mail server, setup on your server. It should be able to relay emails to and from Mailman. Both Mailman Core and your Django server should be configured to send emails through your MTA.

Mailman Core

Mailman Core handles all the tasks related to sending and receiving emails for the mailing lists. It supports various different MTAs.

  • `Postfix`_: To setup Postfix, add the following configuration to master.cf:

    # Support the default VERP delimiter.
    recipient_delimiter = +
    unknown_local_recipient_reject_code = 550
    owner_request_special = no
    transport_maps =
        hash:/path-to-mailman/var/data/postfix_lmtp
    local_recipient_maps =
        hash:/path-to-mailman/var/data/postfix_lmtp
    relay_domains =
        hash:/path-to-mailman/var/data/postfix_domains
    

    Mailman’s var directory can vary according your source of installation. Please refer to the documentation provide with your source or ask Mailman Developers at mailman-developers@python.org.

    To configure Core to use Postfix, add the following configuration to your mailman.cfg configuration, be sure to replace mail.example.com with your email domain:

    [mta]
    incoming: mailman.mta.postfix.LMTP
    outgoing: mailman.mta.deliver.deliver
    lmtp_host: mail.example.com
    lmtp_port: 8024
    smtp_host: mail.example.com
    smtp_port: 25
    
  • `Exim4`_: To setup Exim4, add the following files to your configuration as file names mentioned above:

    # /etc/exim4/conf.d/main/25_mm3_macros
    # The colon-separated list of domains served by Mailman.
    domainlist mm_domains=list.example.net
    
    MM3_LMTP_PORT=8024
    
    # MM3_HOME must be set to Mailman's var directory, wherever it is
    # according to your installation.
    MM3_HOME=/path-to-mailman/var/
    MM3_UID=list
    MM3_GID=list
    
    ################################################################
    # The configuration below is boilerplate:
    # you should not need to change it.
    
    # The path to the list receipt (used as the required file when
    # matching list addresses)
    MM3_LISTCHK=MM3_HOME/lists/${local_part}.${domain}
    
    # /etc/exim4/conf.d/router/455_mm3_router
    mailman3_router:
    driver = accept
    domains = +mm_domains
    require_files = MM3_LISTCHK
    local_part_suffix_optional
    local_part_suffix = \
    -bounces   : -bounces+* : \
    -confirm   : -confirm+* : \
    -join      : -leave     : \
    -owner     : -request   : \
    -subscribe : -unsubscribe
    transport = mailman3_transport
    
    # /etc/exim4/conf.d/transport/55_mm3_transport
    mailman3_transport:
    driver = smtp
    protocol = lmtp
    allow_localhost
    hosts = localhost
    port = MM3_LMTP_PORT
    rcpt_include_affixes = true
    

    You should note that Exim4 configuration above doesn’t support multiple domains like Postfix does. Please change the variables in the configuration above before installing it.

    To configure Mailman to use Exim4 add the following to your mailman.cfg

    [mta]
    incoming: mailman.mta.exim4.LMTP
    outgoing: mailman.mta.deliver.deliver
    lmtp_host: mail.example.com
    smtp_host: mail.example.com
    lmtp_port: 8024
    smtp_port: 25
    
  • Mailman also supports `Sendmail`_ and `qmail`_. Please check the Mailman Core documentation for `sendmail setup`_ and `qmail setup`_ to configure them.

Postorius & Hyperkitty

If your Django site is configured to send emails, there is no additional setup required for Postorius and Hyperkitty. Here are some settings that determine how your emails from them look like:

  • DEFAULT_FROM_EMAIL : This is the default address that used used as the FROM header in all the emails from your django installation.
  • SERVER_EMAIL : This is the address from which the errors emails will be sent to you.

Note that both of these are general Django related settings and will affect other parts of your Django installation too!

Setting up a web server

These instructions are to setup your Django website behind a webserver. We are using a uwsgi as the wsgi server to communicate between the webserver and Django. First setup uwsgi using the following configuration file:

[uwsgi]
# Port on which uwsgi will be listening.
http = :8000

# Move to the directory wher the django files are.
chdir = /path-to-django-directory/

# Use the wsgi file provided with the django project.
wsgi-file = wsgi.py

# Setup default number of processes and threads per process.
master = true
process = 2
threads = 2

# Drop privielges and don't run as root.
uid = 1000
gid = 1000

# Setup the django_q related worker processes.
attach-daemon = ./manage.py qcluster

# Setup the request log.
req-logger = file:/path-to-logs/logs/uwsgi.log

# Log cron seperately.
logger = cron file:/path-to-logs/logs/uwsgi-cron.log
log-route = cron uwsgi-cron

# Log qcluster commands seperately.
logger = qcluster file:/path-to-logs/logs/uwsgi-qcluster.log
log-route = qcluster uwsgi-daemons

# Last log and it logs the rest of the stuff.
logger = file:/path-to-logs/logs/uwsgi-error.log

Note that in the above configuration, there is a command called python manage.py qcluster which run the django-q processes. You can remove this from here if you want to manage this yourself via some other init process.

Have a look at `uwsgi`_ documentation to learn more about different configuration options. There are 1000s of them.

Nginx Configuration

You can reverse proxy the requests to uwsgi server using Nginx. Uwsgi has a special protocol called uwsgi protocol that is available in Nginx as a plugin. Add the following configuration to your sites-availbale in Nginx:

server {

      listen 443 ssl default_server;
      listen [::]:443 ssl default_server;

      server_name MY_SERVER_NAME;
      location /static/ {
           alias /path-to-djang-staticdir/static/;
      }
      ssl_certificate /path-to-ssl-certs/cert.pem;
      ssl_certificate_key /path-to-ssl-certs/privkey.pem;

      location / {
              # First attempt to serve request as file, then
                  include uwsgi_params;
              uwsgi_pass 172.19.199.3:8000;

      }

}

Fill in the appropriate paths above in the configuration before using it.