diff options
Diffstat (limited to 'contrib/majordomo2mailman.pl')
| -rw-r--r-- | contrib/majordomo2mailman.pl | 691 |
1 files changed, 0 insertions, 691 deletions
diff --git a/contrib/majordomo2mailman.pl b/contrib/majordomo2mailman.pl deleted file mode 100644 index c874862e7..000000000 --- a/contrib/majordomo2mailman.pl +++ /dev/null @@ -1,691 +0,0 @@ -#!/usr/bin/perl -w - -# majordomo2mailman.pl - Migrate Majordomo mailing lists to Mailman 2.0 -# Copyright (C) 2002 Heiko Rommel (rommel@suse.de) - -# BAW: Note this probably needs to be upgraded to work with MM2.1 - -# -# License: -# -# This program 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 1, or (at your option) -# any later version. - -# -# Warranty: -# -# There's absolutely no warranty. -# - -# comments on possible debug messages during the conversion: -# -# "not an valid email address" : those addresses are rejected, i.e. not imported into the Mailman list -# "not a numeric value" : such a value will be converted to 0 (z.B. maxlength) -# "already subscribed" : will only once be subscribed on the Mailman list -# "...umbrella..." or "...taboo..." -> Mailman-Admin-Guide - -use strict; -use Getopt::Long; -use Fcntl; -use POSIX qw (tmpnam); - -use vars qw ( - $majordomo $mydomain $myurl - $aliasin $listdir - $aliasout $mailmanbin - $umbrella_member_suffix $private - $newsserver $newsprefix - $susehack $susearchuser - $help $debug $update $all $usagemsg - *FH - %mlaliases %mlowners %mlapprovers - %defaultmlconf %mlconf - %defaultmmconf %mmconf -); - -# -# adjust your site-specific settings here -# - -$mydomain = "my.domain"; -$majordomo = "majordomo"; # the master Majordomo address for your site -$aliasin = "/var/lib/majordomo/aliases"; -$listdir = "/var/lib/majordomo/lists"; -$aliasout = "/tmp/aliases"; -$myurl = "http://my.domain/mailman/"; -$mailmanbin = "/usr/lib/mailman/bin"; -$umbrella_member_suffix = "-owner"; -$private = "yes"; # is this a private/Intranet site ? -$newsserver = "news.my.domain"; -$newsprefix = "intern."; - -$susehack = "no"; -$susearchuser = "archdummy"; - -# -# 0) -# parse the command line arguments -# - -$usagemsg = "usage: majordomo2mailman [-h|--help] [-d|--debug] [-u|--update] < (-a|--all) | list-of-mailinglists >"; - -GetOptions( - "h|help" => \$help, - "d|debug" => \$debug, - "a|all" => \$all, - "u|update" => \$update -) or die "$usagemsg\n"; - -if (defined($help)) { die "$usagemsg\n"; } - -if ((not defined($all)) and (@ARGV<1)) { die "$usagemsg\n"; } - -if ($<) { die "this script must be run as root!\n"; } - -# -# 1) -# build a list of all aliases and extract the name of mailing lists plus their owners -# - -%mlaliases = %mlowners = %mlapprovers = (); - -open (FH, "< $aliasin") or die "can't open $aliasin\n"; - -while (<FH>) { - # first, build a list of all active aliases and their resolution - if (/^([^\#:]+)\s*:\s*(.*)$/) { - $mlaliases{$1} = $2; - } -} - -my $mlalias; -for $mlalias (keys %mlaliases) { - # if we encounter an alias with :include: as expansion - # it is save to assume that the alias has the form - # <mailinglist>-outgoing - - # that way we find the names of all active mailing lists - if ($mlaliases{$mlalias} =~ /\:include\:/) { - my $ml; - ($ml = $mlalias) =~ s/-outgoing//g; - $mlowners{$ml} = $mlaliases{"owner-$ml"}; - $mlapprovers{$ml} = $mlaliases{"$ml-approval"}; - } -} - -close (FH); - -# -# 2) -# for each list read the Majordomo configuration params -# and create a Mailman clone -# - -my $ml; -for $ml ((defined ($all)) ? sort keys %mlowners : @ARGV) { - - init_defaultmlconf($ml); - %mlconf = %defaultmlconf; - - init_defaultmmconf($ml); - %mmconf = %defaultmmconf; - - my @privileged; # addresses that are mentioned in restrict_post - my @members; - my ($primaryowner, @secondaryowner); - my ($primaryapprover, @secondaryapprover); - - my ($skey, $terminator); - my $filename; - my @args; - - # - # a) - # parse the configuration file - # - - open (FH, "< $listdir/$ml.config") or die "can't open $listdir/$ml.config\n"; - - while (<FH>) { - # key = value ? - if (/^\s*([^=\#\s]+)\s*=\s*(.*)\s*$/) { - $mlconf{$1} = $2; - } - # key << EOF - # value - # EOF ? - elsif (/^\s*([^<\#\s]+)\s*<<\s*(.*)\s*$/) { - ($skey, $terminator) = ($1, $2); - while (<FH>) { - last if (/^$terminator\s*$/); - $mlconf{$skey} .= $_; - } - chomp $mlconf{$skey}; - } - } - - close (FH); - - # - # b) - # test if there are so-called flag files (clue that this is an old-style Majordomo lists) - # and overwrite previously parsed values - # (stolen from majordomo::config_parse.pl: handle_flag_files()) - # - - if ( -e "$listdir/$ml.private") { - $mlconf{"get_access"} = "closed"; - $mlconf{"index_access"} = "closed"; - $mlconf{"who_access"} = "closed"; - $mlconf{"which_access"} = "closed"; - } - - $mlconf{"subscribe_policy"} = "closed" if ( -e "$listdir/$ml.closed"); - $mlconf{"unsubscribe_policy"} = "closed" if ( -e "$listdir/$ml.closed"); - - if ( -e "$listdir/$ml.auto" && -e "$listdir/$ml.closed") { - print STDERR "sowohl $ml.auto als auch $ml.closed existieren. Wähle $ml.closed\n"; - } - else { - $mlconf{"subscribe_policy"} = "auto" if ( -e"$listdir/$ml.auto"); - $mlconf{"unsubscribe_policy"} = "auto" if ( -e"$listdir/$ml.auto"); - } - - $mlconf{"strip"} = 1 if ( -e "$listdir/$ml.strip"); - $mlconf{"noadvertise"} = "/.*/" if ( -e "$listdir/$ml.hidden"); - - # admin_passwd: - $filename = "$listdir/" . $mlconf{"admin_passwd"}; - if ( -e "$listdir/$ml.passwd" ) { - $mlconf{"admin_passwd"} = read_from_file("$listdir/$ml.passwd"); - } - elsif ( -e "$filename" ) { - $mlconf{"admin_passwd"} = read_from_file("$filename"); - } - # else take it verbatim - - # approve_passwd: - $filename = "$listdir/" . $mlconf{"approve_passwd"}; - if ( -e "$listdir/$ml.passwd" ) { - $mlconf{"approve_passwd"} = read_from_file("$listdir/$ml.passwd"); - } - elsif ( -e "$filename" ) { - $mlconf{"approve_passwd"} = read_from_file("$filename"); - } - # else take it verbatim - - # - # c) - # add some information from additional configuration files - # - - # restrict_post - if (defined ($mlconf{"restrict_post"})) { - @privileged = (); - for $filename (split /\s+/, $mlconf{"restrict_post"}) { - open (FH, "< $listdir/$filename") or die "can't open $listdir/$filename\n"; - push (@privileged, <FH>); - chomp @privileged; - close (FH); - } - } - - if ($susehack =~ m/yes/i) { - @privileged = grep(!/$susearchuser\@$mydomain/i, @privileged); - } - - $mlconf{"privileged"} = \@privileged; - - # members - @members = (); - open (FH, "< $listdir/$ml") or die "can't open $listdir/$ml\n"; - push (@members, <FH>); - chomp @members; - close (FH); - - $mlconf{"gated"} = "no"; - - if ($susehack =~ m/yes/i) { - if (grep(/$susearchuser\@$mydomain/i, @members)) { - $mlconf{"gated"} = "yes"; - } - @members = grep(!/$susearchuser\@$mydomain/i, @members); - } - - $mlconf{"members"} = \@members; - - # intro message - if (open (FH, "< $listdir/$ml.intro")) { - { local $/; $mlconf{"intro"} = <FH>; } - } - else { $mlconf{"intro"} = ""; } - - # info message - if (open (FH, "< $listdir/$ml.info")) { - { local $/; $mlconf{"info"} = <FH>; } - } - else { $mlconf{"info"} = ""; } - - # - # d) - # take over some other params into the configuration table - # - - $mlconf{"name"} = "$ml"; - - ($primaryowner, @secondaryowner) = - expand_alias (split (/\s*,\s*/, aliassub($mlowners{$ml}))); - - ($primaryapprover, @secondaryapprover) = - expand_alias (split (/\s*,\s*/, aliassub($mlapprovers{$ml}))); - - $mlconf{"primaryowner"} = $primaryowner; - $mlconf{"secondaryowner"} = \@secondaryowner; - - $mlconf{"primaryapprover"} = $primaryapprover; - $mlconf{"secondaryapprover"} = \@secondaryapprover; - - # - # debugging output - # - - if (defined ($debug)) { - print "##################### $ml ####################\n"; - for $skey (sort keys %mlconf) { - if (defined ($mlconf{$skey})) { print "$skey = $mlconf{$skey}\n"; } - else { print "$skey = (?)\n"; } - } - my $priv; - for $priv (@privileged) { - print "\t$ml: $priv\n"; - } - } - - # - # e) - # with the help of Mailman commands - create a new list and subscribe the old staff - # - - if (defined($update)) { - print "updating configuration of \"$ml\"\n"; - } - else { - # Mailman lists can initially be only created with one owner - @args = ("$mailmanbin/newlist", "-q", "-o", "$aliasout", "$ml", $mlconf{"primaryowner"}, $mlconf{"admin_passwd"}); - system (@args) == 0 or die "system @args failed: $?"; - } - - # Mailman accepts only subscriber lists > 0 - if (@members > 0) { - $filename = tmpnam(); - open (FH, "> $filename") or die "can't open $filename\n"; - for $skey (@members) { - print FH "$skey" . "\n"; - } - close (FH); - @args = ("$mailmanbin/add_members", "-n", "$filename", "--welcome-msg=n", "$ml"); - system (@args) == 0 or die "system @args failed: $?"; - } - - # - # f) - # "translate" the Majordomo list configuration - # - - m2m(); - - # write the Mailman config - - $filename = tmpnam(); - - open (FH, "> $filename") or die "can't open $filename\n"; - for $skey (sort keys %mmconf) { - print FH "$skey = " . $mmconf{$skey} . "\n"; - } - close (FH); - - @args = ("$mailmanbin/config_list", "-i", "$filename", "$ml"); - system (@args) == 0 or die "system @args failed: $?"; - - unlink($filename) or print STDERR "unable to unlink \"$filename\"!\n"; - -} - -exit 0; - -############# -# subs -############# - -# -# I don't know how to write Perl code -# therefor I need this stupid procedure to cleanly read a value from file -# - -sub read_from_file { - my $value; - local *FH; - - open (FH, "< $_[0]") or die "can't open $_[0]\n"; - $value = <FH>; - chomp $value; - close (FH); - - return $value; -} - - -# -# add "@$mydomain" to each element that does not contain a "@" -# - -sub expand_alias { - return map { (not $_ =~ /@/) ? $_ .= "\@$mydomain" : $_ } @_; -} - -# -# replace the typical owner-majordomo aliases -# - -sub aliassub { - my $string = $_[0]; - - $string =~ s/(owner-$majordomo|$majordomo-owner)/mailman-owner/gi; - - return $string; -} - -# -# default values of Majordomo mailing lists -# (stolen from majordomo::config_parse.pl: %known_keys) -# - -sub init_defaultmlconf { - my $ml = $_[0]; - - %defaultmlconf=( - 'welcome', "yes", - 'announcements', "yes", - 'get_access', "open", - 'index_access', "open", - 'who_access', "open", - 'which_access', "open", - 'info_access', "open", - 'intro_access', "open", - 'advertise', "", - 'noadvertise', "", - 'description', "", - 'subscribe_policy', "open", - 'unsubscribe_policy', "open", - 'mungedomain', "no", - 'admin_passwd', "$ml.admin", - 'strip', "yes", - 'date_info', "yes", - 'date_intro', "yes", - 'archive_dir', "", - 'moderate', "no", - 'moderator', "", - 'approve_passwd', "$ml.pass", - 'sender', "owner-$ml", - 'maxlength', "40000", - 'precedence', "bulk", - 'reply_to', "", - 'restrict_post', "", - 'purge_received', "no", - 'administrivia', "yes", - 'resend_host', "", - 'debug', "no", - 'message_fronter', "", - 'message_footer', "", - 'message_headers', "", - 'subject_prefix', "", - 'taboo_headers', "", - 'taboo_body', "", - 'digest_volume', "1", - 'digest_issue', "1", - 'digest_work_dir', "", - 'digest_name', "$ml", - 'digest_archive', "", - 'digest_rm_footer', "", - 'digest_rm_fronter', "", - 'digest_maxlines', "", - 'digest_maxdays', "", - 'comments', "" - ); -} - - -# -# Mailman mailing list params that are not derived from Majordomo mailing lists params -# (e.g. bounce_matching_headers+forbbiden_posters vs. taboo_headers+taboo_body) -# If you need one of this params to be variable remove it here and add some code to the -# main procedure; additionally, you should compare it with what you have in -# /usr/lib/mailman/Mailman/mm_cfg.py -# - -sub init_defaultmmconf { - - %defaultmmconf=( - 'goodbye_msg', "\'\'", - 'umbrella_list', "0", - 'umbrella_member_suffix', "\'$umbrella_member_suffix\'", - 'send_reminders', "0", - 'admin_immed_notify', "1", - 'admin_notify_mchanges', "0", - 'dont_respond_to_post_requests', "0", - 'obscure_addresses', "1", - 'require_explicit_destination', "1", - 'acceptable_aliases', "\"\"\"\n\"\"\"\n", - 'max_num_recipients', "10", - 'forbidden_posters', "[]", - 'bounce_matching_headers', "\"\"\"\n\"\"\"\n", - 'anonymous_list', "0", - 'nondigestable', "1", - 'digestable', "1", - 'digest_is_default', "0", - 'mime_is_default_digest', "0", - 'digest_size_threshhold', "40", - 'digest_send_periodic', "1", - 'digest_header', "\'\'", - 'bounce_processing', "1", - 'minimum_removal_date', "4", - 'minimum_post_count_before_bounce_action', "3", - 'max_posts_between_bounces', "5", - 'automatic_bounce_action', "3", - 'archive_private', "0", - 'clobber_date', "1", - 'archive_volume_frequency', "1", - 'autorespond_postings', "0", - 'autoresponse_postings_text', "\'\'", - 'autorespond_admin', "0", - 'autoresponse_admin_text', "\'\'", - 'autorespond_requests', "0", - 'autoresponse_request_text', "\'\'", - 'autoresponse_graceperiod', "90" - ); -} - -# -# convert a Majordomo mailing list configuration (%mlconf) into a -# Mailman mailing list configuration (%mmconf) -# only those params are affected which can be derived from Majordomo -# mailing list configurations -# - -sub m2m { - - my $elem; - my $admin; - - $mmconf{"real_name"} = "\'" . $mlconf{"name"} . "\'"; - - # Mailman does not know the difference between owner and approver - for $admin (($mlconf{"primaryowner"}, @{$mlconf{"secondaryowner"}}, - $mlconf{"primaryapprover"}, @{$mlconf{"secondarapprover"}})) { - # merging owners and approvers may result in a loop: - if (lc($admin) ne lc("owner-" . $mlconf{"name"} . "\@" . $mydomain)) { - $mmconf{"owner"} .= ",\'" . "$admin" . "\'"; - } - } - $mmconf{"owner"} =~ s/^,//g; - $mmconf{"owner"} = "\[" . $mmconf{"owner"} . "\]"; - - # remove characters that will break Python - ($mmconf{"description"} = $mlconf{"description"}) =~ s/\'/\\\'/g; - $mmconf{"description"} = "\'" . $mmconf{"description"} . "\'"; - - $mmconf{"info"} = "\"\"\"\n" . $mlconf{"info"} . "\"\"\"\n"; - - $mmconf{"subject_prefix"} = "\'" . $mlconf{"subject_prefix"} . "\'"; - - $mmconf{"welcome_msg"} = "\"\"\"\n" . $mlconf{"intro"} . "\"\"\"\n"; - - # I don't know how to handle this because the reply_to param in the lists - # I had were not configured consistently - if ($mlconf{"reply_to"} =~ /\S+/) { - if ($mlconf{"name"} . "\@" =~ m/$mlconf{"reply_to"}/i) { - $mmconf{"reply_goes_to_list"} = "1"; - $mmconf{"reply_to_address"} = "\'\'"; - } - else { - $mmconf{"reply_goes_to_list"} = "2"; - $mmconf{"reply_to_address"} = "\'" . $mlconf{"reply_to"} . "\'"; - } - } - else { - $mmconf{"reply_goes_to_list"} = "0"; - $mmconf{"reply_to_address"} = "\'\'"; - } - - $mmconf{"administrivia"} = ($mlconf{"administrivia"} =~ m/yes/i) ? "1" : "0"; - $mmconf{"send_welcome_msg"} = ($mlconf{"welcome"} =~ m/yes/i) ? "1" : "0"; - - $mmconf{"max_message_size"} = int ($mlconf{"maxlength"} / 1000); - - $mmconf{"host_name"} = ($mlconf{"resend_host"} =~ /\S+/) ? - $mlconf{"resend_host"} : "\'" . $mydomain . "\'"; - - $mmconf{"web_page_url"} = "\'" . $myurl . "\'"; - - # problematic since Mailman does not know access patterns - # I assume, that if there was given a noadvertise pattern, the - # list shouldn't be visible at all - $mmconf{"advertised"} = ($mlconf{"noadvertise"} =~ /\.\*/) ? "0" : "1"; - - # confirm+approval is much to long winded for private sites - $mmconf{"subscribe_policy"} = - ($mlconf{"subscribe_policy"} =~ m/(open|auto)/i) ? "1" : - ($private =~ m/yes/i) ? "2" : "3"; - - # in case this is a private site allow list visiblity at most - $mmconf{"private_roster"} = - ($mlconf{"who_access"} =~ m/open/i and not $private =~ m/yes/i) ? "0" : - ($mlconf{"who_access"} =~ m/open|list/i) ? "1" : "2"; - - $mmconf{"moderated"} = ($mlconf{"moderate"} =~ m/yes/i) ? "1" : "0"; - # there is no way to a set a separate moderator in Mailman - - # external, since lengthy - mm_posters(); - - if ($mlconf{"message_fronter"} =~ /\S+/) { - $mmconf{"msg_header"} = "\"\"\"\n" . $mlconf{"message_fronter"} . "\"\"\"\n"; - } - else { - $mmconf{"msg_header"} = "\'\'"; - } - - if ($mlconf{"message_footer"} =~ /\S+/) { - $mmconf{"msg_footer"} = "\"\"\"\n" . $mlconf{"message_footer"} . "\"\"\"\n"; - } - else { - $mmconf{"msg_footer"} = "\'\'"; - } - - # gateway to news - $mmconf{"nntp_host"} = "\'" . $newsserver . "\'"; - $mmconf{"linked_newsgroup"} = "\'" . $newsprefix . $mlconf{"name"} . "\'"; - - if ($mlconf{"gated"} =~ m/yes/i) { - $mmconf{"gateway_to_news"} = "1"; - $mmconf{"gateway_to_mail"} = "1"; - $mmconf{"archive"} = "1"; - } - else { - $mmconf{"gateway_to_news"} = "0"; - $mmconf{"gateway_to_mail"} = "0"; - $mmconf{"archive"} = "0"; - } - - # print warnings if this seems to be an umbrella list - for $elem (@{$mlconf{"privileged"}}, @{$mlconf{"members"}}) { - $elem =~ s/\@$mydomain//gi; - if (defined($mlaliases{$elem . $umbrella_member_suffix})) { - print STDERR "\"" . $mlconf{"name"} . - "\" possibly forms part off/is an umbrella list, since \"$elem\" is a local mailing list alias\n"; - } - } - - # print warnings if we encountered a Taboo-Header or Taboo-Body - if ($mlconf{"taboo_headers"} =~ /\S+/ or $mlconf{"taboo_body"} =~ /\S+/) { - print STDERR "\"" . $mlconf{"name"} . "\" taboo_headers or taboo_body seem to be set - please check manually.\n"; - } -} - -# -# with some set theory on the member and priviliged list try to determine the params -# $mmconf{"member_posting_only"} and $mmconf{"posters"} -# - -sub mm_posters { - if ($mlconf{"restrict_post"} =~ /\S+/) { - my %privileged = (); - my %members = (); - my $key; - - foreach $key (@{$mlconf{"privileged"}}) { $privileged{$key} = "OK"; } - foreach $key (@{$mlconf{"members"}}) { $members{$key} = "OK"; } - - # are all members privileged, too ? - my $included = 1; - foreach $key (keys %members) { - if (not exists $privileged{$key}) { - $included = 0; - last; - } - } - if ($included) { - $mmconf{"member_posting_only"} = "1"; - - # posters = privileged - members: - my %diff = %privileged; - foreach $key (keys %members) { - delete $diff{$key} if exists $members{$key}; - } - - $mmconf{"posters"} = ""; - for $key (sort keys %diff) { - $mmconf{"posters"} .= ",\'" . $key . "\'"; - } - $mmconf{"posters"} =~ s/^,//g; - $mmconf{"posters"} = "[" . $mmconf{"posters"} . "]"; - } - else { - $mmconf{"member_posting_only"} = "0"; - - # posters = privileged: - $mmconf{"posters"} = ""; - for $key (sort keys %privileged) { - $mmconf{"posters"} .= ",\'" . $key . "\'"; - } - $mmconf{"posters"} =~ s/^,//g; - $mmconf{"posters"} = "[" . $mmconf{"posters"} . "]"; - } - } - else { - $mmconf{"member_posting_only"} = "0"; - $mmconf{"posters"} = "[]"; - } -} - |
