aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatarNoèl Köthe <noel@debian.org>2007-06-15 13:16:00 +0200
committerLibravatarUnit 193 <unit193@ubuntu.com>2019-12-05 16:35:14 -0500
commitbf81f8c7c3b1e680bee462eedd12695a7b438128 (patch)
tree4b7f12ed5d2b4f93f973216e016983da62f25599
parentdc97dccb98cf97044be59cca6040ccd2a7a498cf (diff)
parent98331030271c4c646e78bf302d9b870c56fa8d7e (diff)
downloadlistadmin-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--Makefile2
-rw-r--r--debian/changelog6
-rw-r--r--listadmin.man33
-rwxr-xr-xlistadmin.pl198
-rw-r--r--listadmin.txt61
5 files changed, 226 insertions, 74 deletions
diff --git a/Makefile b/Makefile
index 0396efd..9a43be4 100644
--- a/Makefile
+++ b/Makefile
@@ -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