Table of Contents

Mailing list con Mailman

L'interfaccia web di mailman si trova su http://<hostname>/cgi-bin/mailman/listinfo

Per il sito principale e per eventuali VirtualHost si può impostare un indirizzo migliore (sia per il sito principale che per eventuali VirtualHost) con una direttiva

ScriptAlias /mailman/ /usr/lib/cgi-bin/mailman/

Controllare anche se servono i seguenti alias per visualizzare le immagini dell'interfaccia web e per accedere all'archivio pubblico di una lista:

Alias /images/mailman/ /usr/share/images/mailman/
Alias /pipermail/ /var/lib/mailman/archives/public/

Per ogni lista creata si devono gestire i seguenti alias:

lista
lista-admin
lista-bounces
lista-confirm
lista-join
lista-leave
lista-owner
lista-request
lista-subscribe
lista-unsubscribe

Exim

Ma noi si usa Exim con i domini virtuali, leggere le istruzioni /usr/share/doc/mailman/README.EXIM.gz.

Nel file di configurazione di exim4 si devono aggiungere un router e un transport. Attenzione al router: conviene metterlo subito prima di quello che seleziona i virtual domains.

######################################################################
# Mailman router: accepts mail for all the lists addresses
# (list, list-admin, list-owner, etc.). Actual handling of messages
# is performed by the mailman_transport.
######################################################################
mailman_router:
    driver = accept
    domains = /etc/exim4/domains-mailman.lst
    require_files = /var/lib/mailman/lists/${lc::$local_part}/config.pck
    local_part_suffix_optional
    local_part_suffix = -admin     : \
                    -bounces   : -bounces+* : \
                    -confirm   : -confirm+* : \
                    -join      : -leave     : \
                    -owner     : -request   : \
                    -subscribe : -unsubscribe
    transport = mailman_transport
######################################################################
# Mailman transport: messages for mailing lists addresses are feed
# to the mailman wrapper program.
######################################################################
mailman_transport:
    driver = pipe
    command = /var/lib/mailman/mail/mailman \
        '${if def:local_part_suffix \
            {${sg{$local_part_suffix}{-(\\w+)(\\+.*)?}{\$1}}} \
            {post}}' \
        $local_part
    current_directory = /var/lib/mailman
    home_directory = /var/lib/mailman
    user = list
    group = daemon

Ogni dominio gestito da Mailman (si consiglia di crearne di appositi, del tipo lists.dominio.org) deve essere elencato nel file /etc/exim4/domains-mailman.lst oltre che tra i domini virtuali normali (parametro dc_other_hostnames del file /etc/exim4/update-exim4.conf.conf).

Questa configurazione non supporta l'esistenza di liste con lo stesso nome sotto domini differenti, è in generale una limitazione di mailman.

In /etc/mailman/mm_cfg.py si mette la direttiva MTA=None per evitare che il comando newlist mostri messaggi fuorvianti che invitano a creare gli alias.

Postfix

Con /etc/aliases

Questo metodo non gestisce i domini virtuali. Ad esempio è impossibile avere un indirizzo tipo info@ condiviso tra un dominio e una lista. Basta aggiungere alcune righe in /etc/aliases (ricordarsi poi di eseguire newaliases):

## Mailing list listname
listname:              "|/var/lib/mailman/mail/mailman post listname"
listname-admin:        "|/var/lib/mailman/mail/mailman admin listname"
listname-bounces:      "|/var/lib/mailman/mail/mailman bounces listname"
listname-confirm:      "|/var/lib/mailman/mail/mailman confirm listname"
listname-join:         "|/var/lib/mailman/mail/mailman join listname"
listname-leave:        "|/var/lib/mailman/mail/mailman leave listname"
listname-owner:        "|/var/lib/mailman/mail/mailman owner listname"
listname-request:      "|/var/lib/mailman/mail/mailman request listname"
listname-subscribe:    "|/var/lib/mailman/mail/mailman subscribe listname"
listname-unsubscribe:  "|/var/lib/mailman/mail/mailman unsubscribe listname"

Con filtro di trasporto

Si usa un filtro di trasporto specifico postfix-mailman. Anzitutto occorre un file /etc/postfix/transport che indica quale dominio viene gestito dal filtro mailman:

lists.domain.org  mailman:

Per sicurezza verificare che in /etc/postfix/master.cf sia effettivamente definito il trasporto mailman. Il file deve essere compilato con postmap:

postmap transport

Infine si aggiunge la configurazione in /etc/postfix/main.cf:

# Mailing lists with MailMan:
relay_domains = lists.domain.org
transport_maps = hash:/etc/postfix/transport
# Feed the MailMan transport with one mail at time.
mailman_destination_recipient_limit = 1

In questo modo non ci si deve preoccupare di aggiungere gli alias per ogni lista che si crea o si elimina.

Creare una lista

Anzitutto si deve creare la lista chiamata mailman, altrimenti mailman non si avvia. Si usa il comando:

newlist <lista> <niccolo@rigacci.org> <SecretPassword>

Una volta avviato /etc/init.d/mailman start ci sarà il processo mailmanctl e alcune istanze di qrunner.

Password

Per creare nuove liste dall'interfaccia web si va all'URL http://<hostname>/cgi-bin/mailman/create, viene chiesta una password di list creator o la più potente site password. Le password sono memorizzate in /var/lib/mailman/data/*.pw (hash, ma senza seed), si impostano con mmsitepass:

mmsitepass
mmsitepass --listcreator

Ciascuna lista ha poi la propria list password per l'amministrazione, si cambia dall'interfaccia web oppure con l'utility withlist:

# /usr/lib/mailman/bin/withlist -l mylist
Loading list mylist (locked)
The variable `m' is the mylist MailList instance
>>> import sha
>>> m.password = sha.new('newsecret').hexdigest()
>>> m.Save()
>>>(Ctrl+D)

Amministrazione

L'amministratore puo' configurare il funzionamento della lista dall'URL http://<hostname>/cgi-bin/mailman/admin/lista. Le informazioni sulle liste esistenti sono in /var/lib/mailman/lists/.

Per eliminare una lista si usa “man rmlist”.

Rimozione automatica messaggi in sospeso

Dalla versione 2.1.6 esiste l'opzione max_days_to_hold (opzioni generali interfaccia web di amministrazione), per cui i messaggi in sospeso vengono automaticamente eliminati dopo alcuni giorni. Per le versioni precedenti si può allestire uno script da eseguire sotto cronjob del tipo:

#!/bin/sh
# Remove held messages after some time.
# Mailman version < 2.1.6 does not have an max_days_to_hold option.
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
find /var/lib/mailman/lists -type d -maxdepth 1 | while read directory; do
    listname="$(basename $directory)"
    find /var/lib/mailman/data -name "heldmsg-$listname-*" -mtime +10 -print \
        | xargs /var/lib/mailman/bin/discard
done

Cambio configurazione URL

Se si cambia DEFAULT_URL_PATTERN in /etc/mailman/mm_cfg.py si devono aggiornare i file esistenti relativi alla lista…

withlist -l -r fix_url <listname>

Se voglio specificare l'URL sulla riga di comando:

/var/lib/mailman/bin/withlist -l -r fix_url <listname> -u <new_url>

Domini virtuali

Nel file di configurazione /etc/mailman/mm_cfg.py si devono dichiarare tutti i domini virtuali sotto cui lavora Mailman, con delle direttive del tipo:

add_virtualhost(DEFAULT_URL_HOST, DEFAULT_EMAIL_HOST)
add_virtualhost('lists.geocaching-italia.com', 'lists.geocaching-italia.com')

E' indispensabile farlo prima di creare una nuova lista, altrimenti la procedura web fallisce con un messaggio di errore comprensbile se in inglese, assurdo se in italiano:

Error: Unknown virtual host: lists.geocaching-italia.com
Errore: Lista ignota: geocaching

Linugua italiana

Attenzione a come viene installato il pacchetto Debian!

Se durante l'installazione si sceglie solo la lingua inglese (en), per attivare l'italiano non è sufficiente modificare il file /etc/mailman/mm_cfg.py impostando it:

DEFAULT_SERVER_LANGUAGE = 'it'
DEFAULT_PREFERRED_LANGUAGE = 'it'
DEFAULT_AVAILABLE_LANGUAGES = ['it', 'en']

Bisogna ANCHE copiare in /etc/mailman (o fare un symlink) i template che stanno in /usr/share/mailman.

Infatti Mailman cerca i template per i messaggi di notifica in /var/lib/mailman/templates, che in Debian è un link simbolico a /etc/mailman.

Il sintomo del problema è che i messaggi di notifica vengono scritti con il Subject in italiano, ma il contenuto in inglese.

Charset UTF-8

Disgraziatamente Mailman prevede per l'italiano la codifica ISO-8859-1, quindi l'archivio web delle mail viene prodotto in questa codifica e le pagine web contengono il seguente meta tag:

<META http-equiv="Content-Type" content="text/html; charset=iso-8859-1">

Tale impostazione è contenuta in /usr/lib/mailman/Mailman/Defaults.py, per non dover modificare questo file si procede come segue:

  1. Verificare che i file in /etc/mailman/it/ siano in ASCII oppure in UTF-8, eventualmente usare iconv per convertirli.
  2. Impostare in /etc/mailman/mm_cfg.py le seguenti direttive:
    DEFAULT_SERVER_LANGUAGE = 'it'
    DEFAULT_CHARSET = 'utf-8'
    add_language('it', 'Italian', 'utf-8', 'ltr')

Rimane il problema dei messaggi in /var/lib/mailman/messages/ che dopo averli convertiti vanno anche ricompilati:

cd /var/lib/mailman/messages/it/LC_MESSAGES/
mv mailman.po mailman.po.bak
mv mailman.mo mailman.mo.bak
cat mailman.po.bak | iconv -f ISO_8859-1 -t UTF-8 > mailman.po
msgfmt -o mailman.mo mailman.po

Il comando msgfmt(1) è fornito dal pacchetto Debian gettext.

Newsletter (one-way mailing list)

Per ottenere che una mailing list si comporti come una newsletter (lista chiusa, moderata, ecc.) ci sono diverse impostazioni da modificare dopo averla creata. In questo documento ci sono alcune linee guida: How do I create a newsletter, announcement, or one-way list?.

Se vogliamo che tutte le nuove liste create abbiano queste impostazioni si possono definire diversi valori in /etc/mailman/mm_cfg.py:

DEFAULT_MSG_FOOTER = """_______________________________________________
Lista %(real_name)s@%(host_name)s
Per cancellarsi scrivere a: %(real_name)s-leave@%(host_name)s
To unsubscribe write to: %(real_name)s-leave@%(host_name)s
"""
DEFAULT_DIGESTABLE = No
DEFAULT_ANONYMOUS_LIST = 1
DEFAULT_FIRST_STRIP_REPLY_TO = 1
DEFAULT_REPLY_GOES_TO_LIST = 2
DEFAULT_REPLY_TO_ADDRESS = 'info@lists.rigacci.org'
DEFAULT_INCLUDE_LIST_POST_HEADER = 0
DEFAULT_RESPOND_TO_POST_REQUESTS = 0
DEFAULT_SEND_WELCOME_MSG = 0
DEFAULT_SEND_GOODBYE_MSG = 0
DEFAULT_RESPOND_TO_POST_REQUESTS = 0
DEFAULT_NEW_MEMBER_OPTIONS = 274
DEFAULT_MAX_DAYS_TO_HOLD = 5
DEFAULT_PREFERRED_LANGUAGE = 'it'
DEFAULT_AVAILABLE_LANGUAGES = ['it']
DEFAULT_ENCODE_ASCII_PREFIXES = 2
DEFAULT_LIST_ADVERTISED = 1
DEFAULT_SUBSCRIBE_POLICY = 2
DEFAULT_PRIVATE_ROSTER = 2
DEFAULT_OBSCURE_ADDRESSES = 1
DEFAULT_DEFAULT_MEMBER_MODERATION = 1

Purtroppo tre parametri importanti non accettano un default in mm_cfg.py:

Per fare in modo che tutti i DEFAULT_* vengano riconosciuti ho proposto una modifica a MailMan. La modifica comporta modificare due file:

/var/lib/mailman/Mailman/Defaults.py (aggiungere le definizioni)

DEFAULT_REPLY_TO_ADDRESS = ''
DEFAULT_INCLUDE_LIST_POST_HEADER = 1
DEFAULT_RESPOND_TO_POST_REQUESTS = 1

/usr/lib/mailman/Mailman/MailList.py (cercare le righe dove sono definite le variabili e modificarle):

self.reply_to_address = mm_cfg.DEFAULT_REPLY_TO_ADDRESS
self.include_list_post_header = mm_cfg.DEFAULT_INCLUDE_LIST_POST_HEADER
self.respond_to_post_requests = mm_cfg.DEFAULT_RESPOND_TO_POST_REQUESTS

Migrazione

Per spostare una mailing list da un server ad un altro (stessa versione di MailMan), questi sono i file e le directory da copiare:

Se cambia l'URL della lista eseguire anche:

/var/lib/mailman/bin/withlist -l -r fix_url <listname> -u <new_url>

Abuso della form di registrazione (SPAM)

Capita di vedere tentativi automatizzati e malevoli di sottoscrivere indirizzi email ad una lista. Non è chiara l'utilità di questi tentativi, ma la conferma di registrazione viene inviata ad un destinatario che eventualmente segnala il messaggio come SPAM con tutte le conseguenze del caso (il server finisce in qualche blacklist).

Come spiegato in questo articolo Fighting Mailman Subscription Spam: The Easy Way è sufficiente aggiungere una riga al file /etc/mailman/mm_cfg.py:

SUBSCRIBE_FORM_SECRET = "Kw4Qb4MF9Yoe2Tvldu7O8KFK"

Questa impostazione attiva un CSRF token nella form di registrazione che impone il caricamento della form prima della sottomissione. Se questo parametro esiste, viene controllato anche il tempo intercorso fra il caricamento della form e la sua sottimissione: se è inferiore ai 5 secondi il submit viene rifiutato. In generale un bot agisce molto rapidamente e quindi fallirà il sumbit del form.