#pragma keywords créer, mailing, list, Mailing, List, Créer = Mailman 3 = {{{#!wiki caution Cette page décrit des aspects techniques de la gestion du crans, pour des informations d'utilisation d'un point de vue utilisateur, allez plutôt sur https://wiki.crans.org/CransTechnique/ServicesMineurs/MailMan3/Utilisation. }}} <> Mailman 3 est le service de listes de diffusions utilisé au Crans. Il vient remplacer [[CransTechnique/ServicesMineurs/MailMan|Mailman 2]], après près de 20 ans de bons et loyaux services. Mailman est déployé sur le serveur [[CransTechnique/LesServeurs/Virtuels/ServeurMailman|mailman]]. L'interface web de Mailman est disponible sur https://lists.crans.org/ ou sur https://mailman.crans.org/. Les listes de diffusion sont dans le domaine {{{@lists.crans.org}}} (certaines ont des alias {{{@crans.org}}}). == Installation == === Mailman === Mailman 3 est gentiment packagé sous Debian, on se contente donc d'installer le paquet depuis APT. Les données de Mailman seront stockées dans {{{/var/lib/mailman3}}}. On prévoie donc un disque dédié monté sur ce chemin. Sur un Debian Bullseye propre, il suffit de faire : {{{ $ sudo apt update $ sudo apt install --no-install-recommends mailman3-full }}} Mailman est désormais déjà prêt à être configuré et utilisé :) Il est bon de vérifier néanmoins que le dossier {{{/var/lib/mailman3}}} appartient bien à {{{list:list}}}. Pour des raisons de confort d'utilisation d'un terminal Django, installer iPython via le paquet {{{python3-ipython}}} peut se révéler très pratique. === Installation de la base de données === Mailman est essentiellement séparé en deux cœurs : {{{mailman}}} qui gère les listes et {{{mailman-web}}} qui gère l'affichage web avec Django. Les deux parties ont besoin de leur propre base de données. Sur le serveur qui héberge [[CransTechnique/Services/PostGreSQL|PostgreSQL]] ([[CransTechnique/LesServeurs/ServeurTealc|tealc]] au Crans), il faut donc créer les deux bases de données : {{{ $ sudo -u postgres createuser -P mailman3 $ sudo -u postgres createdb -O mailman3 mailman3 $ sudo -u postgres createuser -P mailman3web $ sudo -u postgres createdb -O mailman3web mailman3web }}} On n'oublie pas d'autoriser les connexions dans {{{/etc/postgresql/11/main/pg_hba.conf}}} : {{{ host mailman3 mailman3 172.16.10.0/24 md5 host mailman3 mailman3 fd00:0:0:10::/64 md5 host mailman3web mailman3web 172.16.10.0/24 md5 host mailman3web mailman3web fd00:0:0:10::/64 md5 }}} === Configuration de Mailman === Sa configuration se trouve dans {{{/etc/mailman/mailman.cfg}}}, qui doit appartenir à {{{root:list}}} et avoir pour permissions {{{0640}}}. On définit dans la partie {{{[database]}}} les paramètres de connexion à la base de données : {{{ [database] class: mailman.database.postgresql.PostgreSQLDatabase url: postgres://mailman3:PASSWORD@172.16.10.1:5432/mailman3 }}} Dans la partie {{{[webservice]}}}, on définit un mot de passe pour la connexion à l'API nommé {{{admin_pass}}}. On configure enfin la réception et l'envoi de mails : {{{ [mta] incoming: mailman.mta.postfix.LMTP outgoing: mailman.mta.deliver.deliver smtp_host: localhost # Postfix local smtp_port: 25 smtp_user: smtp_pass: lmtp_host: 127.0.0.1 lmtp_port: 8024 configuration: python:mailman.config.postfix }}} Les mails sont reçus localement par LMTP et pour l'envoi mailman s'adresse à son propre serveur Postfix. === Configuration de Hyperkitty === Hyperkitty est le service d'archivage de Mailman. Pour l'activer, il faut ajouter dans le fichier de configuration de Mailman : {{{ [archiver.hyperkitty] class: mailman_hyperkitty.Archiver enable: yes configuration: /etc/mailman3/mailman-hyperkitty.cfg }}} Et renseigner le mot de passe dans {{{/etc/mailman3/mailman-hyperkitty.cfg}}} : {{{ [general] base_url: http://localhost/hyperkitty/ api_key: {{ mailman3.archiver_key }} }}} === Configuration de Mailman-web === Sa configuration se trouve dans {{{/etc/mailman/mailman-web.py}}}, qui doit appartenir à {{{root:www-data}}} et avoir pour permissions {{{0640}}}. {{{ SECRET_KEY = '{{ mailman3.web_secret_key }}' ADMINS = ( ('Mailman Suite Admin', 'root@crans.org'), ) ALLOWED_HOSTS = [ "localhost", # Archiving API from Mailman, keep it. "mailman.crans.org", "lists.crans.org", ] # Mailman API credentials MAILMAN_REST_API_URL = 'http://localhost:8001' MAILMAN_REST_API_USER = 'restadmin' MAILMAN_REST_API_PASS = '{{ mailman3.restadmin_pass }}' MAILMAN_ARCHIVER_KEY = '{{ mailman3.archiver_key }}' MAILMAN_ARCHIVER_FROM = ('127.0.0.1', '::1') INSTALLED_APPS = ( 'mailman_crans_theme', # override templates 'hyperkitty', 'postorius', 'django_mailman3', 'django.contrib.admin', 'django.contrib.admindocs', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.sites', 'django.contrib.messages', 'django.contrib.staticfiles', 'rest_framework', 'django_gravatar', 'compressor', 'haystack', 'django_extensions', 'django_q', 'allauth', 'allauth.account', 'allauth.socialaccount', 'allauth_cas', 'allauth_cas_crans', ) # Database configuration DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql_psycopg2', 'NAME': 'mailman3web', 'USER': 'mailman3web', 'PASSWORD': 'PASSWORD', 'HOST': '172.16.10.1', 'PORT': 5432, 'OPTIONS': { }, } } # Reverse-proxy configuration USE_X_FORWARDED_HOST = True SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_SCHEME', 'https') LANGUAGE_CODE = 'en-us' TIME_ZONE = 'UTC' USE_I18N = True USE_L10N = True USE_TZ = True EMAILNAME = 'crans.org' DEFAULT_FROM_EMAIL = f'contact@crans.org' SERVER_EMAIL = f'root@crans.org' ACCOUNT_DEFAULT_HTTP_PROTOCOL = "https" SOCIALACCOUNT_PROVIDERS = { 'crans': {}, } COMPRESS_PRECOMPILERS = ( ('text/less', 'lessc {infile} {outfile}'), ('text/x-scss', 'sassc -t compressed {infile} {outfile}'), ('text/x-sass', 'sassc -t compressed {infile} {outfile}'), ) COMPRESS_OFFLINE = True POSTORIUS_TEMPLATE_BASE_URL = 'http://localhost/mailman3/' }}} Certains paramètres concernent la connexion au CAS, voir ci-dessous. === Connexion via le CAS === On souhaite que les adhérents se connectent sur l'interface web via le CAS du Crans. On comment pour cela par installer l'exension nécessaire pour {{{django-allauth}}}, qui n'existe malheureusement pas dans les paquets Debian, avec son module spécial Crans : {{{ $ sudo apt install --no-install-recommends python3-pip python3-lxml $ sudo pip3 install django-allauth-cas git+https://gitlab.crans.org/nounous/allauth-cas-crans.git }}} On ajoute alors le module {{{allauth_cas}}} et {{{allauth_cas_crans}}} aux applications installées (voir ci-dessus). On n'oubliera pas d'autoriser https://mailman.crans.org/ et https://lists.crans.org/ d'accéder au CAS. === Thèmes Crans personnalisés === De la même manière, on installe le paquet PIP personnalisé : {{{ $ sudo pip install git+https://gitlab.crans.org/nounous/mailman-crans-theme.git }}} Il suffit ensuite d'ajouter en première application {{{mailman_theme_crans}}} pour remplacer les thèmes par défaut. === Migration de la base de données, collecte des fichiers statiques === Pour migrer la base de données et créer les différentes tables, une fois Mailman bien configuré, il suffit de lancer : {{{ $ sudo -u www-data mailman-web migrate }}} Pour importer les fichiers statiques : {{{ $ sudo -u www-data mailman-web collectstatic }}} Et enfin, pour compresser et mettre en cache certaines ressources (afin d'optimiser le délai de réponse) : {{{ $ sudo -u www-data mailman-web compress }}} Toutes ces opérations sont à faire après chaque mise à jour de mailman. === Redémarrer mailman === Les services sont gérés par systemd : {{{ $ sudo systemctl restart mailman $ sudo systemctl restart mailman-web }}} === Définition du site === Par défaut, le site s'appelle {{{example.com}}}. On peut le changer en ligne de commande : {{{ $ sudo mailman-web shell_plus [1]: site = Site.objects.first() [2]: site.name = "Listes Crans" [3]: site.domain = "mailman.crans.org" [4]: site.save() }}} === Ajout d'un super-utilisateur === Avant d'avoir un super-utilisateur capable d'accéder à l'interface d'administration, on peut déjà essayer d'ajouter des droits en ligne de commande. On commande par ouvrir un shell Django : {{{ $ sudo mailman-web shell_plus }}} On peut ensuite récupérer l'utilisateur voulu et lui donner les droits super-utilisateur et les droits staff (nécessaires pour accéder à l'interface d'administration) : {{{ [1]: user = User.objects.get(username="ynerant") [2]: user.is_superuser = True [3]: user.is_staff = True [4]: user.save() }}} L'utilisateur a désormais les pleins pouvoirs sur la plateforme. === Postfix === ==== Configuration standard ==== On installe un serveur Postfix qui servira uniquement à recevoir les mails (comme indiqué plus haut, l'envoi des mails se fait en contactant directement redisdead). On commence par installer {{{postfix}}} : {{{ $ sudo apt install --no-install-recommends postfix }}} Sa configuration se fait dans {{{/etc/postfix/main.cf}}}. Le début de la configration est assez standard : {{{ # See /usr/share/postfix/main.cf.dist for a commented, more complete version # This postfix configuration set up a MTA only to send and receive mailing list mails # When a mail is sent to @localhost, this domain will be used myorigin = crans.org smtpd_banner = $myhostname ESMTP $mail_name (Debian/GNU) biff = no # Uncomment the next line to generate "delayed mail" warnings delay_warning_time = 4h # See http://www.postfix.org/COMPATIBILITY_README.html -- default to 2 on # fresh installs. compatibility_level = 2 # TLS parameters smtpd_tls_cert_file=/etc/letsencrypt/live/crans.org/fullchain.pem smtpd_tls_key_file=/etc/letsencrypt/live/crans.org/privkey.pem smtpd_use_tls=yes smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache # OpenDKIM smtpd_milters = inet:localhost:12301 non_smtpd_milters = inet:localhost:12301 # See /usr/share/doc/postfix/TLS_README.gz in the postfix-doc package for # information on enabling SSL in the smtp client. # Limit to 200Mo by message message_size_limit = 209715200 # Default aliases alias_maps = hash:/etc/aliases alias_database = hash:/etc/aliases # Only localhost mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128 # Listen on IPv4 and IPv6 inet_interfaces = all inet_protocols = all # Do not use gethostname myhostname = mailman.adm.crans.org mydomain = crans.org # Softbounce, ask remote mail server to send the mail again if error # Do not keep it active in production! soft_bounce = no }}} On veillera en particulier à bien générer un certificat TLS via certbot nommé {{{crans.org}}}. On ajoute la configuration spécifique à Mailman 3 : {{{ # Mailman3 integration recipient_delimiter = + unknown_local_recipient_reject_code = 550 owner_request_special = no transport_maps = hash:/var/lib/mailman3/data/postfix_lmtp local_recipient_maps = hash:/var/lib/mailman3/data/postfix_lmtp relay_domains = hash:/var/lib/mailman3/data/postfix_domains }}} Il suffit ensuite de recharger Postfix. ==== Configuration de Open DKIM ==== DKIM permet de signer les messages afin d'attester qu'ils ont bien été émis depuis les serveurs du Crans. Dans les en-têtes de chaque message, une signature du message générée par une clé privée est ajoutée. La signature peut-être contrôlée par la clé publique accessible dans la zone DNS ({{{dig -t TXT lists._domainkey.lists.crans.org}}}). La clé publique du serveur Mailman est : {{{ "v=DKIM1; h=sha256; k=rsa; " "p=MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA7jkgGjxZvQDbgFIuqb59lt7O1Jg6DFTSBxFlTfBW+3MF+AFjBR3AZ/UXwDA1vH4UTZqq0fWN6y6wqE/F7+HDjpqZGGuygZWTGVbBxwiKSjc2kq2mz7kLisE3a/jP8kyQDdb7fWrtTw9fxYu+Ygs0744otjRsui/ZK6zbrO8XQfd5UYnj4IGALeIuVFVLmwTY+VL/xWR/Ujcfxg" "AprRfH0ec8PGlrxhpeLhUSJxw3Q6QfTnDsIpWLfJdgxILGa58TmhH6d+faxa1OIP37wswPjkDykmMFsCQJX9P7mXXR0+1FIRhhNpfCRXXj37udbIezDEMfA15rWSoYinPU+x7i6LhfJD7G40p1oDBiaOimZ8D/PUDAtoWRQeFiNOOQmNqDaVwlaOMvIZH2ZFD2I0eJIDb2FBYqhTb5GVyhKPePqT5FZE0s8SXqvYRNUWHuomS79kfo4TC7" "4UPlavIbyCVTFlLi5ujc5RANm/FuH2w3ns1+YAlCeoblzwVdgN+h4/DI5kI88+0Hf+HCfQg+rPQL7ak7Wszo0iWvYUZ8t+IPbNDcVm5YI6koqkWGgfMrC0bDI5r+ZQACK15Fi6x3tV0umhytgRQWG9MyK61diNIc1LFsyL2lD0oOAjlpDlVSpUnXKhjRPq4YdaIojlgGSsWsq8sBhQTCY5DNHUuJLL1iPqsCAwEAAQ==" }}} Le support de DKIM est géré le service {{{opendkim}}} : {{{ sudo apt install --no-install-recommends opendkim opendkim-tools }}} Pour générer une paire de clés : {{{ sudo opendkim-genkey -s lists -d lists.crans.org }}} Le fichier {{{lists.txt}}} contient directement l'enregistrement TXT à rentrer dans les champs DNS. Ces clés sont à placer dans le dossier {{{/etc/opendkim/keys/lists.crans.org/}}}. Le dossier {{{/etc/opendkim/}}} doit appartenir à {{{opendkim:opendkim}}}, {{{/etc/opendkim/keys/}}} doit avoir pour permissions {{{0750}}} et les clés {{{0600}}}. Dans {{{/etc/opendkim/KeyTable}}} : {{{ lists._domainkey.lists.crans.org lists.crans.org:lists:/etc/opendkim/keys/lists.crans.org/lists.private }}} Dans {{{/etc/opendkim/SigningTable}}} : {{{ *@lists.crans.org lists._domainkey.lists.crans.org }}} Dans {{{/etc/opendkim/TrustedHosts}}} : {{{ 127.0.0.1 localhost ::1 138.231.136.0/21 138.231.144.0/21 10.231.136.0/24 10.2.9.0/24 2a0c:700:0:1::/64 2a0c:700:0:2::/64 2a0c:700:0:21::/64 2a0c:700:0:22::/64 2a0c:700:0:23::/64 *.crans.org *.crans.fr *.crans.eu }}} Pour charger ces fichiers de configuration, on ajoute dans {{{/etc/opendkim.conf}}} : {{{ ExternalIgnoreList refile:/etc/opendkim/TrustedHosts InternalHosts refile:/etc/opendkim/TrustedHosts KeyTable refile:/etc/opendkim/KeyTable SigningTable refile:/etc/opendkim/SigningTable }}} ===== Lien Postfix - Open DKIM ===== On souhaite désormais que Postfix signe et vérifie les signatures avec DKIM. On démarre alors un socket d'écoute du serveur DKIM, en ajoutant dans {{{/etc/opendkim.conf}}} : {{{ socket inet:12301@localhost }}} Et il suffit d'ajouter dans {{{/etc/postfix/main.cf}}}, comme indiqué ci-dessus : {{{ smtpd_milters = inet:localhost:12301 non_smtpd_milters = inet:localhost:12301 }}} En rechargeant {{{postfix}}} et {{{opendkim}}}, les messages seront désormais signés. ==== Configuration des relais SMTP ==== Les messages sont reçus directement sur le serveur, via son IP publique. Toutefois, en cas de coupure du serveur, on ne souhaite pas perdre de mails, simplement les délayer. On définit alors {{{freebox.crans.org}}} et {{{sputnik.crans.org}}} en MX alternatifs On souhaite que les mails soient reçus par le serveur mail principal, à savoir redisdead, afin de faire un premier tri et de gérer lui-même la sécurité des mails. On ajoute alors {{{redisdead.crans.org}}}, {{{freebox.crans.org}}} et {{{sputnik.crans.org}}} en serveurs MX pour {{{lists.crans.org}}}, avec des priorités plus grandes pour qu'ils ne servent que de relais / backups. Dans le fichier {{{/etc/postfix/main.cf}}} de ces serveurs, on pense bien à ajouter {{{lists.crans.org}}} dans le champ {{{$relay_domains}}}. Dans {{{/etc/postfix/transport}}}, on indique à postfix de transporter les mails envoyer sur une adresse {{{@lists.crans.org}}} sur le serveur de Mailman : {{{ lists.crans.org smtp:[172.16.10.110] }}} Après un rechargement de postfix, les mails sont prêts à être distribués. En cas de coupure de mailman, les mails seront stockés dans une file sur le serveur avant d'être redistribués plus tard. === Configuration des DNS === Les noms de domaines doivent être bien configurés pour permettre le transport de mails. On doit commencer par définir une nouvelle zone {{{lists.crans.org}}}, qui contient un champ A et un champ AAAA pointant vers les IP de {{{hodaur.crans.org}} : {{{ $TTL 3600 $ORIGIN lists2.crans.org. lists.crans.org. IN SOA silice.crans.org. root.crans.org. 2020304021 86400 7200 3600000 3600 @ IN NS silice.crans.org. @ IN NS freebox.crans.org. @ IN NS sputnik.crans.org. @ IN A 185.230.79.10 @ IN AAAA 2a0c:700:2::ff:fe01:4502 }}} On ajoute ensuite un champ MX, indiquant que l'on souhaite que les mails délivrés à une adresse en {{{@lists.crans.org}}} soient délivrés au serveur sur {{{mailman.crans.org}}}. On fait de même pour les serveurs de backup, avec des priorités supérieures : {{{ @ IN MX 10 mailman.crans.org. @ IN MX 15 sputnik.crans.org. @ IN MX 25 freebox.crans.org. }}} On pense bien sûr à définir des champs A et AAAA derrière {{{mailman.crans.org}}} pour pointer sur les IP publiques du serveur mailman : 185.230.79.40 et 2a0c:700:2::ff:fe01:1002. On renseigne ensuite le champ SPF ainsi que la politique DMARC : {{{ @ IN TXT "v=spf1 mx ~all" _dmarc IN TXT v=DMARC1\; p=none }}} Enfin, on ajoute la clé publique DKIM : {{{ lists._domainkey IN TXT ( "v=DKIM1; h=sha256; k=rsa; " "p=MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA7jkgGjxZvQDbgFIuqb59lt7O1Jg6DFTSBxFlTfBW+3MF+AFjBR3AZ/UXwDA1vH4UTZqq0fWN6y6wqE/F7+HDjpqZGGuygZWTGVbBxwiKSjc2kq2mz7kLisE3a/jP8kyQDdb7fWrtTw9fxYu+Ygs0744otjRsui/ZK6zbrO8XQfd5UYnj4IGALeIuVFVLmwTY+VL/xWR/Ujcfxg" "AprRfH0ec8PGlrxhpeLhUSJxw3Q6QfTnDsIpWLfJdgxILGa58TmhH6d+faxa1OIP37wswPjkDykmMFsCQJX9P7mXXR0+1FIRhhNpfCRXXj37udbIezDEMfA15rWSoYinPU+x7i6LhfJD7G40p1oDBiaOimZ8D/PUDAtoWRQeFiNOOQmNqDaVwlaOMvIZH2ZFD2I0eJIDb2FBYqhTb5GVyhKPePqT5FZE0s8SXqvYRNUWHuomS79kfo4TC7" "4UPlavIbyCVTFlLi5ujc5RANm/FuH2w3ns1+YAlCeoblzwVdgN+h4/DI5kI88+0Hf+HCfQg+rPQL7ak7Wszo0iWvYUZ8t+IPbNDcVm5YI6koqkWGgfMrC0bDI5r+ZQACK15Fi6x3tV0umhytgRQWG9MyK61diNIc1LFsyL2lD0oOAjlpDlVSpUnXKhjRPq4YdaIojlgGSsWsq8sBhQTCY5DNHUuJLL1iPqsCAwEAAQ==" ) }}} Ces paramètres suffisent à se prémunir contre la fausse détection de spam. == Migration == Les données de Mailman 2 vers Mailman 3 seront migrées dans la nuit du dimanche 11 au lundi 12 avril 2021. Le plan de migration est accessible sur la page [[/Migration]]. == Renommer une ML == Cette action est non triviale et non supportée officiellement par Mailman. Elle n'est en général pas recommandée et doit présenter une bonne justification. Je place ces quelques lignes ici afin de ne pas les perdre, ne sachant pas où les mettre. On se place ici dans la cas où l'on souhaite renommer la liste {{{tresorier.lists.crans.org}}} en {{{tresorerie.lists.crans.org}}}, afin de la rendre plus inclusive. On commence par modifier les lignes de base de données concernant Mailman 3 : {{{ _ynerant@tealc:~$ sudo -u postgres psql mailman3 BEGIN; UPDATE mailinglist SET list_name='Trésorerie', list_id='tresorerie.lists.crans.org' WHERE list_id = 'tresorier.lists.crans.org'; UPDATE member SET list_id='tresorerie.lists.crans.org' WHERE list_id = 'tresorier.lists.crans.org'; UPDATE ban SET list_id='tresorerie.lists.crans.org' WHERE list_id = 'tresorier.lists.crans.org'; UPDATE template SET context='tresorerie.lists.crans.org' WHERE context='tresorier.lists.crans.org'; COMMIT; }}} On peut ensuite en faire de même pour Hyperkitty, dans Mailman 3 Web : {{{ _ynerant@tealc:~$ sudo -u postgres psql mailman3 BEGIN; UPDATE hyperkitty_mailinglist SET name='tresorerie@lists.crans.org', list_id='tresorerie.lists.crans.org', display_name='Trésorerie' WHERE list_id='tresorier.lists.crans.org'; COMMIT; }}} Enfin, il faut bouger le dossier de données de la liste sur le serveur Mailman : {{{ _ynerant@mailman:~$ sudo mv /var/lib/mailman3/lists/tresorier.lists.crans.org /var/lib/mailman3/lists/tresorerie.lists.crans.org }}} Il suffit enfin de redémarrer le service {{{mailman3}}} afin de notamment regénérer la configuration Postfix. ---- CatégorieCrans CatégoriePagePublique