diff options
author | Noèl Köthe <noel@debian.org> | 2007-06-15 13:16:00 +0200 |
---|---|---|
committer | Unit 193 <unit193@ubuntu.com> | 2019-12-05 16:35:14 -0500 |
commit | bf81f8c7c3b1e680bee462eedd12695a7b438128 (patch) | |
tree | 4b7f12ed5d2b4f93f973216e016983da62f25599 | |
parent | dc97dccb98cf97044be59cca6040ccd2a7a498cf (diff) | |
parent | 98331030271c4c646e78bf302d9b870c56fa8d7e (diff) | |
download | listadmin-bf81f8c7c3b1e680bee462eedd12695a7b438128.tar.bz2 listadmin-bf81f8c7c3b1e680bee462eedd12695a7b438128.tar.xz listadmin-bf81f8c7c3b1e680bee462eedd12695a7b438128.tar.zst |
Import Debian changes 2.37-1debian/2.37-1
listadmin (2.37-1) unstable; urgency=low
* new upstream release
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | debian/changelog | 6 | ||||
-rw-r--r-- | listadmin.man | 33 | ||||
-rwxr-xr-x | listadmin.pl | 198 | ||||
-rw-r--r-- | listadmin.txt | 61 |
5 files changed, 226 insertions, 74 deletions
@@ -1,7 +1,7 @@ SHELL = /bin/sh INSTALL = install -c -VERSION = 2.36 +VERSION = 2.37 PREFIX = /usr/local BINDIR = $(PREFIX)/bin diff --git a/debian/changelog b/debian/changelog index 4b289c1..b1394a8 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +listadmin (2.37-1) unstable; urgency=low + + * new upstream release + + -- Noèl Köthe <noel@debian.org> Fri, 15 Jun 2007 13:16:00 +0200 + listadmin (2.36-1) unstable; urgency=low * new upstream release diff --git a/listadmin.man b/listadmin.man index 9325df5..72c79d4 100644 --- a/listadmin.man +++ b/listadmin.man @@ -6,8 +6,9 @@ .SH NAME listadmin \- process messages held by Mailman for approval .SH SYNOPSIS -.B "listadmin [-f \fIconfigfile\fP] [-t \fIminutes\fP] [{-a|-r} \fIfile\fP] - [-l] [\fIlistname\fP]" +.B listadmin [-?] [-V] [-f \fIconfigfile\fP] [-t \fIminutes\fP] \ +[--mail] [--nomail] [{-a|-r} \fIfile\fP] [--add-member \fIaddress\fP] \ +[--remove-member \fIaddress\fP] [-l] [\fIlistname\fP] .SH DESCRIPTION .I listadmin is a textual alternative to Mailman's WWW interface for administering @@ -19,17 +20,29 @@ default (\fB~/.listadmin.ini\fP). .IP "-t \fIminutes\fP" Stop processing after \fIminutes\fP has passed. Mostly useful for completely automated configurations of \fBlistadmin\fP. +.IP "--mail" +Addresses added as subscribers will have \fInomail\fP turned off. +.IP "--nomail" +Addresses added as subscribers will have \fInomail\fP turned on. .IP "-a \fIfile\fP" Add e-mail addresses listed in \fIfile\fP (one address per line) to -subscriber list. The welcome message is suppressed. +the subscriber list. The welcome message is suppressed. +.IP "--add-member \fIaddress\fP" +Add \fIaddress\fP to the subscriber list, works as above. .IP "-r \fIfile\fP" Remove e-mail addresses listed in \fIfile\fP (one address per line) from the subscriber list. +.IP "--remove-member \fIaddress\fP" +Remove \fIaddress\fP from the subscriber list. .IP "-l" Display the subscriber list. .IP "\fIlistname\fP" Only process the lists matching \fIlistname\fP. Specify a complete address, a substring or a regular expression. +.IP "-? or --help" +Display short usage description. +.IP "-V or --version" +Output version number. .SH CONFIGURATION SYNTAX The configuration file contains lines which can contain either a @@ -190,8 +203,10 @@ As above, but backwards. .IP . Redisplay information about current message. .IP add [\fIaddress\fP] -Add \fIaddress\fP as subscriber to the list with "nomail" enabled. If -\fIaddress\fP is left out, use the sender of the current message. +Add \fIaddress\fP as subscriber to the list. If \fIaddress\fP is left +out, use the sender of the current message. +.IP nomail [\fIaddress\fP] +As \fIadd\fP, but adds \fIaddress\fP with "nomail" enabled. .IP list [\fIpattern\fP] List subscriber addresses matching \fIpattern\fP, or the full list if no \fIpattern\fP is specified. @@ -259,6 +274,14 @@ An example configuration file: foo-announce@example.net .fi +.SH ENVIRONMENT +.IP "\fBhttp_proxy\fP or \fBHTTP_PROXY\fP" +Specifies a proxy to use for HTTP. +.IP "\fBhttps_proxy\fP or \fBHTTPS_PROXY\fP" +Specifies a proxy to use for HTTPS. +.IP \fBLC_CTYPE\fP +The character set support is deduced from this variable. + .SH FILES \fB$HOME/.listadmin.ini\fP .PP diff --git a/listadmin.pl b/listadmin.pl index f037b54..e4390ed 100755 --- a/listadmin.pl +++ b/listadmin.pl @@ -1,6 +1,6 @@ #! /usr/bin/perl -w # -# listadmin version 2.36 +# listadmin - process messages held by Mailman for approval # Written 2003 - 2007 by # Kjetil Torgrim Homme <kjetilho+listadmin@ifi.uio.no> # @@ -9,13 +9,16 @@ # # Released into public domain. +my $version = "2.37"; + use HTML::TokeParser; use LWP::UserAgent; +# use LWP::Debug qw(+trace); use MIME::Base64; use MIME::QuotedPrint; use Data::Dumper; use Term::ReadLine; -use Getopt::Std; +use Getopt::Long; use Text::Reform; use I18N::Langinfo qw(langinfo CODESET); # appeared in Perl 5.7.2 use Encode; # appeared in perl 5.7.1 @@ -25,35 +28,73 @@ use English; my $rc = $ENV{"HOME"}."/.listadmin.ini"; sub usage { + my ($exit_val) = @_; print STDERR <<_end_; Usage: $0 [-f CONFIGFILE] [-t MINUTES] [{-a|-r} FILE] [-l] [LISTNAME] -f CONFIGFILE Read configuration from CONFIGFILE. (default: $rc) -t MINUTES Stop processing after MINUTES minutes. Decimals are allowed. + --mail Turn off "nomail" flag for the specified addresses + --nomail Turn on "nomail" flag for the specified addresses -a FILE Add e-mail addresses in FILE to list -r FILE Remove e-mail addresses in FILE to list + --add-member ADDRESS + Add ADDRESS as member to list + --remove-member ADDRESS + Remove ADDRESS from member list -l List subscribers LISTNAME Only process lists with name matching LISTNAME. -If -a, -r or -l is given, LISTNAME must match exactly one list. +If options which modify members are used, LISTNAME must match exactly +one list. _end_ - exit (64); + exit(defined $exit_val ? $exit_val : 64); } -our ($opt_f, $opt_t, $opt_a, $opt_r, $opt_l); - -usage() unless getopts('f:t:a:r:l'); +my ($opt_help, $opt_version, $opt_f, $opt_t, $opt_a, $opt_r, + @opt_add_member, @opt_remove_member, $opt_l); +my $opt_mail = 1; + +GetOptions("help|?" => \$opt_help, + "version|V" => \$opt_version, + "f=s" => \$opt_f, + "t=i" => \$opt_t, + "mail!" => \$opt_mail, + "a=s" => \$opt_a, + "r=s" => \$opt_r, + "add-member=s" => \@opt_add_member, + "remove-member=s" => \@opt_remove_member, + "l" => \$opt_l) + or usage(); + +usage(0) if $opt_help; +if ($opt_version) { + print "listadmin version $version\n"; + exit(0); +} $rc = $opt_f if $opt_f; usage() if defined $opt_t && $opt_t !~ /\d/ && $opt_t !~ /^\d*(\.\d*)?$/; -usage() if defined $opt_a && defined $opt_r; -usage() if defined $opt_l && (defined $opt_a || defined $opt_r); -my $ua = new LWP::UserAgent ("timeout" => 900); +push(@opt_add_member, read_address_file($opt_a, 1)) if defined $opt_a; +push(@opt_remove_member, read_address_file($opt_r, 1)) if defined $opt_r; + +my $will_modify_membership = 0; +++$will_modify_membership if @opt_add_member; +++$will_modify_membership if @opt_remove_member; + +usage() if $will_modify_membership > 1; +usage() if defined $opt_l && $will_modify_membership; + +my $ua = new LWP::UserAgent("timeout" => 900, "env_proxy" => 1); my $time_limit = time + 60 * ($opt_t || 24*60); my $term; my $term_encoding = langinfo(CODESET()); + +# the C and POSIX locale in Solaris uses the charset "646", but Perl +# doesn't support it. +$term_encoding = "ascii" if $term_encoding eq "646"; binmode STDOUT, ":encoding($term_encoding)"; # Turn on autoflush on STDOUT $| = 1; @@ -79,19 +120,22 @@ if (@ARGV) { @lists = sort config_order keys %{$config} } -if (@lists > 1 && (defined $opt_r || defined $opt_a || defined $opt_l)) { +if (@lists > 1 && ($will_modify_membership || defined $opt_l)) { print STDERR "Too many matching lists\n"; + print Dumper(\@lists); usage(); } my $list = $lists[0]; + my $subscribe_result; -if (defined $opt_a) { - my @addresses = read_address_file($opt_a, 1); - $subscribe_result = add_subscribers($list, $config->{$list}, 0, @addresses); -} elsif (defined $opt_r) { - my @addresses = read_address_file($opt_r, 1); - $subscribe_result = remove_subscribers($list, $config->{$list}, @addresses); +if (@opt_add_member) { + $subscribe_result = add_subscribers($list, $config->{$list}, $opt_mail, + @opt_add_member); +} +if (@opt_remove_member) { + $subscribe_result = remove_subscribers($list, $config->{$list}, + @opt_remove_member); } if (defined $subscribe_result) { for my $addr (keys %{$subscribe_result}) { @@ -392,9 +436,10 @@ _end_ } print join("\n ", @list); print "\n$member_count members in total\n"; - } elsif ($ans =~ /^add(\s+|$)/) { + } elsif ($ans =~ /^(add|nomail)(\s+|$)/) { + my $mail = $1 eq "add"; my $addr = $POSTMATCH || $from; - my $res = add_subscribers($list, $config, 1, $addr); + my $res = add_subscribers($list, $config, $mail, $addr); for my $addr (keys %{$res}) { print "$addr: $res->{$addr}\n"; } @@ -462,8 +507,8 @@ _end_ } elsif ($ans eq "f") { # Since the raw bytes aren't really Unicode, we set # the replacement sequence to be "<?>" unconditionally. - print degrade_charset($info->{$id}{"headers"} . "\n\n" . $info->{$id}{"body"}, - "questionmark"); + print degrade_charset($info->{$id}{"headers"} . "\n\n" . + $info->{$id}{"body"}, "questionmark"); } elsif ($ans eq "b") { my $head = $info->{$id}{"headers"}; my $text = $info->{$id}{"body"}; @@ -524,7 +569,8 @@ and pressing Return. /pattern -- search for next message with matching From or Subject ?pattern -- search for previous message with matching From or Subject . -- redisplay entry - add [address] -- add nomail subscription for address (defaults to From) + add [address] -- add subscription for address (defaults to From) + nomail [address] -- add nomail subscription for address (defaults to From) list [pattern] -- list mailing list members matching optional pattern rem address -- remove list member q Quit -- go on to the next list @@ -1309,7 +1355,7 @@ sub log_timestamp { } sub add_subscribers { - my ($list, $config, $nomail, @addresses) = @_; + my ($list, $config, $mail, @addresses) = @_; die unless @addresses; @@ -1326,19 +1372,31 @@ sub add_subscribers { my $result = parse_subscribe_response($resp->content); - if ($nomail) { + if (!$mail) { my %left = map { $_ => 1 } @addresses; for my $failed (keys %{$result}) { - delete $left{$failed}; + unless ($result->{$failed} =~ /Already a member/) { + delete $left{$failed}; + } } @addresses = keys %left; - + } else { + # We only need to reset "nomail" on the users who already were + # members. + @addresses = (); + for my $failed (keys %{$result}) { + if ($result->{$failed} =~ /Already a member/) { + push(@addresses, $failed); + } + } + } + if (@addresses) { %params = (username => $config->{user}, adminpw => $config->{password}, user => \@addresses, setmemberopts_btn => "submit"); # Mailman 2.x for my $a (@addresses) { - $params{$a . "_nomail"} = "on"; + $params{$a . "_nomail"} = "on" unless $mail; $params{$a . "_subscribed"} = "on"; # Mailman 1.2 } $resp = $ua->post($url, \%params); @@ -1391,7 +1449,7 @@ sub parse_subscribe_response { $parse->get_tag ("ul") || die; my $ul = $parse->get_text ("/ul") || die; - if ($h5 =~ /Successfully (un)?subscribed/i) { + if ($h5 =~ /Successfully ((un)?subscribed|Removed)/i) { # hooray! } elsif ($h5 =~ /Error (un)?subscribing/i) { for (split(/\n/, $ul)) { @@ -1427,33 +1485,69 @@ sub list_subscribers { my @addresses = (); my ($parse, $page, $tag); - my $chunk = 0; - - member_chunk: - while ($resp->is_success) { - $page = $resp->content; - $parse = HTML::TokeParser->new(\$page); - my $count = 0; - while ($tag = $parse->get_tag("input")) { - my $attr = $tag->[1]; - if ($attr->{type} =~ /^hidden$/i && - $attr->{name} =~ /^user$/i) { - ++$count; - my $address = $attr->{value}; - unless ($address =~ /\@/) { - # Mailman 2.x adds URL-encoding - $address =~ s/%([0-9a-fA-F]{2})/sprintf("%c", hex($1))/ge; - } - if (grep { $_ eq $address } @addresses) { - last member_chunk; - } else { - push(@addresses, $address); + + member_letter: + for my $letter ("a" .. "z") { + my $chunk = 0; + + $params{chunk} = $chunk; + + # Mailman 2.x specifically looks at QUERY_STRING, so chunk and + # letter can't be parameters to POST. However, Mailman 1.x + # only looks at chunk in the POST parameters. + $resp = $ua->post("$url?letter=$letter&chunk=$chunk", \%params) + unless $letter eq "a"; + + while ($resp->is_success) { + $page = $resp->content; + $parse = HTML::TokeParser->new(\$page); + my $count = 0; + my $repeated = 0; + my $later_letter = 0; + while ($tag = $parse->get_tag("input")) { + my $attr = $tag->[1]; + if ($attr->{type} =~ /^hidden$/i && + $attr->{name} =~ /^user$/i) { + ++$count; + my $address = $attr->{value}; + unless ($address =~ /\@/) { + # Mailman 2.x adds URL-encoding + $address =~ s/%([0-9a-fA-F]{2})/sprintf("%c", hex($1))/ge; + } + ++$later_letter if lc(substr($address, 0, 1)) gt $letter; + if (grep { $_ eq $address } @addresses) { + ++$repeated; + } else { + push(@addresses, $address); + } } } + last if $count == 0; + + # In Mailman 1.x, "letter" is a no-op, so $later_letter + # will ~always be true and should be ignored. Increase + # chunk until we see repeats. + + # In Mailman 2.x, we need to iterate through both letter + # and chunk, but if the list has few members, they will + # all be listed and letter and chunk are ignored. Also, + # if there are no members for a given letter, the whole + # list will be returned. + + if ($repeated) { + last member_letter if $later_letter; + next member_letter; + } + + # The maximum number of addresses on each page can be + # configured, by default it is set to 30, but it could in + # theory be less. To save time, we assume that we have + # all the members if we got less than 20 addresses. + next member_letter if $count < 20; + + ++$chunk; $params{chunk} = $chunk; + $resp = $ua->post("$url?letter=$letter&chunk=$chunk", \%params); } - last if $count == 0; - ++$params{chunk}; - $resp = $ua->post($url, \%params); } return @addresses; } diff --git a/listadmin.txt b/listadmin.txt index 8072f43..ffe92f6 100644 --- a/listadmin.txt +++ b/listadmin.txt @@ -4,11 +4,12 @@ NAME listadmin - process messages held by Mailman for approval SYNOPSIS - listadmin [-f configfile] [-t minutes] [{-a|-r} file] [-l] - [listname]" + listadmin [-?] [-V] [-f configfile] [-t minutes] [--mail] [--nomail] + [{-a|-r} file] [--add-member address] [--remove-member address] [-l] + [listname] DESCRIPTION - listadmin is a textual alternative to Mailman’s WWW interface for + listadmin is a textual alternative to Mailman's WWW interface for administering mailing lists. OPTIONS @@ -20,20 +21,37 @@ OPTIONS Stop processing after minutes has passed. Mostly useful for completely automated configurations of listadmin. + --mail Addresses added as subscribers will have nomail turned off. + + --nomail + Addresses added as subscribers will have nomail turned on. + -a file Add e-mail addresses listed in file (one address per line) to - subscriber list. The welcome message is suppressed. + the subscriber list. The welcome message is suppressed. + + --add-member address + Add address to the subscriber list, works as above. -r file Remove e-mail addresses listed in file (one address per line) from the subscriber list. + --remove-member address + Remove address from the subscriber list. + -l Display the subscriber list. listname Only process the lists matching listname. Specify a complete address, a substring or a regular expression. + -? or --help + Display short usage description. + + -V or --version + Output version number. + CONFIGURATION SYNTAX The configuration file contains lines which can contain either a comment, a directive, or a mailing list address. @@ -86,9 +104,9 @@ DIRECTIVES reject Notify sender that the message was rejected. discard - Throw message away, don’t notify sender. + Throw message away, don't notify sender. - skip Don’t decide now, leave it for later. + skip Don't decide now, leave it for later. none Reset to no default action. @@ -97,7 +115,7 @@ DIRECTIVES the other rules apply (e.g., spamlevel, discard_if_from etc.), ie., whenever the user would have been asked what to do. The same actions as for default are available, - although reject isn’t very useful. + although reject isn't very useful. spamlevel number This specifies the threshold for automatic discard of @@ -115,7 +133,7 @@ DIRECTIVES default will restore this behaviour. not_spam_if_from pattern - If the message’s From header matches the pattern, all + If the message's From header matches the pattern, all automatic actions will be cancelled and you will be asked what action to take explicitly. The pattern can use Perl regexp syntax. If enclosed in slashes, some modifiers @@ -126,14 +144,14 @@ DIRECTIVES As above, but matches against the Subject header. discard_if_from pattern - If the message’s From header matches the pattern, it will + If the message's From header matches the pattern, it will be discarded automatically. discard_if_subject pattern As above, but matches against the Subject header. discard_if_reason pattern - As above, but matches against Mailman’s reason for + As above, but matches against Mailman's reason for holding the message for approval. subscription_default action @@ -146,7 +164,7 @@ DIRECTIVES reject Notify sender that s/he was not allowed to join the list. - skip Don’t decide now, leave it for later. + skip Don't decide now, leave it for later. none Reset to no default action. @@ -164,7 +182,7 @@ DIRECTIVES unprintable questionmark|unicode If the subject or sender address contains characters the - terminal can’t display, they will be replaced by either + terminal can't display, they will be replaced by either "<?>" (in questionmark mode, the default) or something like "<U+86a8>" (in unicode mode). @@ -192,7 +210,7 @@ INTERACTIVE USE r Reject the message and notify sender of the decision. - d Discard the message silently, don’t notify sender. + d Discard the message silently, don't notify sender. s Skip the message, leave its status as pending unchanged. @@ -218,9 +236,10 @@ INTERACTIVE USE . Redisplay information about current message. - add Add address as subscriber to the list with "nomail" - enabled. If address is left out, use the sender of the - current message. + add Add address as subscriber to the list. If address is + left out, use the sender of the current message. + + nomail As add, but adds address with "nomail" enabled. list List subscriber addresses matching pattern, or the full list if no pattern is specified. @@ -278,6 +297,16 @@ EXAMPLES confirm no foo-announce@example.net +ENVIRONMENT + http_proxy or HTTP_PROXY + Specifies a proxy to use for HTTP. + + https_proxy or HTTPS_PROXY + Specifies a proxy to use for HTTPS. + + LC_CTYPE + The character set support is deduced from this variable. + FILES $HOME/.listadmin.ini |