Perles de Mongueurs (50)

Article publié dans Linux Magazine 130, septembre 2010.

[+ del.icio.us] [+ Developers Zone] [+ Bookmarks.fr] [Digg this] [+ My Yahoo!]

La perle de ce mois-ci a été rédigée par Philippe "BooK" Bruhat (book@mongueurs.net), de Lyon.pm et Paris.pm.

Réparer Mailman avec Perl

Mailman est un gestionnaire de listes de diffusion. Mailman est écrit en Python. Mailman fonctionne. Mailman est utile. Mailman est partout. Un bon nombre de listes Perl sont gérée par Mailman. Je suis abonné à plus de cinquante listes gérées par Mailman.

Étape 1 : détester Mailman

Mais Mailman est quand même un logiciel, ce qui le rend détestable.

Voici plusieurs raisons de détester Mailman :

Quand je me plains de l'option nodupes, on me répond en général : « Ben, configure ton compte ! ». Mais configurer son compte, cela veut dire en général : requérir le renvoi du mot de passe (car on a depuis le temps oublié celui fourni automatiquement par Mailman), attendre l'arrivée du message, le lire, copier le mot de passe, aller sur la page de la liste, s'authentifier, aller sur la page des options, trouver l'option recherchée (nodupes est en bas de la page), valider. Même en excluant l'attente du message, cela va prendre plusieurs minutes. Multiplié par cinquante abonnements, on arrive rapidement à plusieurs heures perdues sur une tâche stupide et répétitive qui mériterait franchement d'être automatisée.

Étape 2 : programmer en Perl

Vous l'avez compris, en tant qu'utilisateur de Mailman, j'ai besoin d'un outil en ligne de commande pour configurer mes listes. Et en tant que programmeur paresseux, j'ai préféré passer quelques heures à programmer une bonne fois pour toutes cet outil, plutôt que de cliquer comme un idiot pendant une après-midi entière.

La distribution WWW-Mailman contient plusieurs exemples dans son répertoire eg/, condensés ici en un seul programme.

    #!/usr/bin/env perl
    use strict;
    use warnings;
    use WWW::Mailman;
    use Getopt::Long;
    use YAML::Tiny qw( LoadFile DumpFile Dump );

    # La table de distribution %action est définie comme suit:
    # nom => {
    #    description => 'Courte description',
    #    code        => sub { ...; },
    # }
    my %action = (
        # définition de %action
        # (voir la suite de la perle)
    );

    # paramètres de ligne de commande
    my %param = (
        config => 'mailman.yml',
        cookie => 'mailman.cookie',
    );
    GetOptions( \%param, 'config=s', 'cookie=s' )
        or die "Usage: $0 [ --config file ] [ --cookie file ] <action>\n";

    # pas d'action ou action inconnue
    my $action = shift;
    if ( !$action || !exists $action{$action} ) {
        print "Actions disponibles:\n",
            map { sprintf "  %10s: %s\n", $_, $action{$_}{description} }
            keys %action;
        exit !!$action;
    }

    # lecture des fichiers de configuration
    my $lists = LoadFile( $param{config} );
    my %opt = ( cookie_file => $param{cookie} );

    # appel de la commande de la table de distribution
    $action{$action}->( \%opt, $lists );

Le code ci-dessus est très simple. Il analyse les paramètres de ligne de commande pour trouver le fichier de configuration des listes Mailman et un éventuel fichier de sauvegarde des cookies (l'authentification par cookies accélère les choses en éliminant un certain nombre de requêtes intermédiaires).

Après lecture du fichier de configuration des listes, on définit les options par défaut de WWW::Mailman (le fichier de cookies) et on lance la commande demandée depuis la table de distribution.

Le fichier de configuration YAML ressemble à ceci :

    ---
    example:
      uri: http://lists.example.com/mailman/listinfo/example
      email: user@example.com
      password: s3kr3t

Étape 3 : profiter !

Il ne reste donc plus qu'à rajouter les entrées qui nous seront utiles dans la table de distribution.

Obtenir la liste de toutes mes listes

        othersubs => {
            description => q{Demande un rappel de mot de passe},
            code        => sub {
                my ( $opt, $lists ) = @_;
                for my $list ( values %$lists ) {

                    my $mm = WWW::Mailman->new( %opt, %$list );

                    for my $uri ( $mm->othersubs ) {
                        my $other = WWW::Mailman->new( %opt, uri => $uri );
                        $lists->{ $other->list }
                            ||= { uri => "$uri", email => $mm->email };
                    }
                }

                # met à jour le fichier de configuration
                DumpFile( $param{config}, $lists );
           }
       },

Pour chaque liste configurée, WWW::Mailman ira chercher les autres listes auxquelles l'utilisateur est abonné sur le serveur, et les ajoutera à sa configuration si elles n'y sont pas déjà.

Obtenir les mots de passes de toutes mes listes

        emailpw => {
            description => q{Demande un rappel de mot de passe},
            code        => sub {
                my ( $opt, $lists ) = @_;
                for my $list ( values %$lists ) {
                    next if exists $list->{password};
                    print "Demande de mot de passe pour $list->{uri}\n";
                    WWW::Mailman->new( %opt, %$list )->emailpw;
                }
            }
        },

Une fois la liste des listes obtenue, il nous faut les mots de passe. Cette commande va se connecter à chacune des listes pour obtenir un rappel de mot de passe.

J'avoue n'avoir pas été assez paresseux pour programmer un script de récupération des mots de passe dans ma boîte email (principalement parce c'est vraiment une opération que je ne ferai qu'une fois, et que désormais je mettrai mon fichier de configuration à jour au fur et à mesure).

Après une courte séance de copier/coller entre la messagerie et le fichier de configuration, on peut passer à la suite.

Reconfigurer toutes mes listes

        nodupes => {
            description => q{Désactive l'option <nodupes>},
            code        => sub {
                my ( $opt, $lists ) = @_;
                for my $list ( values %$lists ) {
                    my $mm = WWW::Mailman->new( %$opt, %$list );
                    $mm->options( { nodupes => 0 } );
                }
            },
        },

Cette commande reconfigure toutes les listes exactement comme j'en ai envie. :-)

Pour savoir exactement quels paramètres fournir à la référence de table de hachage en paramètre d'options(), le plus simple est de commencer par faire un script qui affiche le contenu du formulaire, et de comparer avec le formulaire sur le web. Cela donne en général une bonne idée des valeurs qu'on veut y mettre.

Et pour les administrateurs de listes ?

WWW::Mailman dispose également de méthodes donnant accès aux pages d'administration d'une liste. Comme pour un simple utilisateur la connexion est automatique, pourvu que l'objet ait été configuré avec les bons mots de passe.

L'ajout de commandes (d'entrées dans la table de distribution) d'administration à cet utilitaire est laissé en exercice au lecteur. ;-)

Références

À vous !

Envoyez vos perles à perles@mongueurs.net, elles seront peut-être publiées dans un prochain numéro de Linux Magazine.

[IE7, par Dean Edwards] [Validation du HTML] [Validation du CSS]