#!/usr/local/bin/perl

#  unsubscribe
#
# A perl script by Kim Holburn, University of Canberra 1996.
# kim@canberra.edu.au
# Feel free to use this and adjust it.  If you make any useful adjustments or
# additions send them back to me.
#
# This script will unsubscribe users in bulk from whatever mail lists they are 
# subscribed to.  It also mails them that it has done this.
# It is useful for sys admins of large systems with many accounts and
# floating populations, like student servers.
# This script must be run by root although I don't check for this.
# You have to be root to read someone else's mailbox and to
# su to their account, both of which this script need to do.
#
# This script when applied to a mailbox will look through it to find
# any emails sent by mailing lists, attempt to determine the address of the
# mailing list and then send an unsubscribe message from that user.
# If invoked with no options only the mailbox name(s) it will assume 
# the mailbox filename is the same as the username, as it is on a sun.
#
# Technical details:
# To find emails from mailing lists it looks for "owner" as part of
# the originating email address in the BSD From line (envelope).
# list servers that don't do this will be missed if you can figure a way
# round this let me know.
# The script doesn't do any file locking but then it only reads the mailbox
# file.

sub fail_usage {
  if (@_ ne '') { print "Error : ", @_, "\n"; }
  print "Usage : $0 [-d] mailboxes\n"; 
  print "Usage : $0 [-d] -u user mailbox\n"; 
  print "Usage : $0 [-d] -u user -l listname -h host -a listserver\n"; 
  print "where listserver is the full email address of the listserver\n";
  exit;
}

sub unsub {
  local ($myuser, $mylist, $myhost, $myaddress) = @_;

  if (!$debug) {
    if (!open (SEND,
 "|(USER=$myuser;LOGNAME=$myuser;su $myuser -c \"/usr/ucb/mail $myaddress\")")) 
      { print "Couldn't open mailer for user \"$myuser\"\n"; next; }
    print SEND "unsubscribe $mylist\n" ;
    close SEND;
  } else {
    print "No unsub \"$myuser\" on \"$mylist@$myhost\" to :\n";
    print "      $myaddress\n";
  }
}

sub notify {
  local($myuser, $mylist, $myhost, $myaddress) = @_;
  if (!$debug) {
    if (!open (SEND, "|/usr/ucb/mail -s \"unsubscribed $mylist\" $myuser"))
      { print "Couldn't open mailer for user \"$myuser\"\n"; next; }
    $mess = <<EOM;
You have been automatically unsubscribed from the mailing list :
$mylist@$myhost
to resubscribe follow the original directions or 
EOM
    print SEND $mess;
    if ($myaddress !~ /,/) {
      print SEND "send a message to the address $myaddress \n" ;
    } else {
      print SEND "send a message to the appropriate one of the addresses:\n";
      print SEND "$myaddress \n" ;
    }
    $mess4 = <<EOM2;
with no subject, no signature and a single line :
subscribe (your name)

EOM2
    print SEND $mess4 ;
    close SEND;
  } else {
    print "No notify \"$myuser\" on \"$mylist@$myhost\" to :\n";
    print "      $myaddress\n";
  }
}

$debug=0;
$usersupplied=0;
while (($#ARGV > (-1)) && ($ARGV[0] =~ /^-/)) {
  if ($ARGV[0] eq '-d') { shift ARGV; $debug=1; }
  elsif ($#ARGV < 1) { &fail_usage("option \"$ARGV[0]\" needs an argument"); }
  elsif ($ARGV[0] eq '-u') { shift ARGV; $user=shift ARGV; }
  elsif ($ARGV[0] eq '-l') { shift ARGV; $list=shift ARGV; }
  elsif ($ARGV[0] eq '-h') { shift ARGV; $host=shift ARGV; }
  elsif ($ARGV[0] eq '-a') { shift ARGV; $address=shift ARGV; }
  else { &fail_usage(); }
}
$usersupplied = ($user ne '') ;

#print "debug d=\"$debug\" u=\"$user\" l=\"$list\" h=\"$host\"\n";
#print "debug \$#ARGV=$#ARGV a=\"$address\" \n";
if ($#ARGV == (-1)) {
  if ($usersupplied && $list ne '' && $host ne '' && $address ne '' && $#ARGV) {
    $list =~ s/@.*$//;
    $user =~ s/@.*$//;
    $host =~ s/^.*@//;
    if ($address !~ /@/) { &fail_usage("bad address"); }
    &unsub ($user, $list, $host, $address);
    &notify ($user, $list, $host, $address);
    exit;
  } else { &fail_usage("no files and no addresses"); }
}

if ($usersupplied && $#ARGV > 0) { &fail_usage(); }

foreach $file (@ARGV) {
  %addresses=();
  if (!$usersupplied) { $user=$file; }
  $user =~ s@^.*/@@;
  if ($file =~ /^\./) { print "skipping wrong type of file \"$file\"\n"; next; }
  if ($file =~ /\.lock/)
    { print "skipping lock file \"$file\"\n"; next; }
  if ($file =~ /\./) { print "skipping wrong type of file \"$file\"\n"; next; }
  $user =~ s/^\.//;
  $user =~ s/\..*$//;
  if (!open (MYFILE, "<$file" )) 
    { print "Couldn't open file \"$file\"\n"; next; }
  print "--------------------------opening file \"$file\"\n";
  while (<MYFILE>) {
#    if (/(\bnews-[-\w.]+@)|([-\w.]+-news@)/i) 
#    if (/(\brequest-[-\w.]+@)|([-\w.]+-request@)/i) 
    if (/(\bowner-[-\w.]+@)|([-\w.]+-owner@)/i) {
      chop;
      tr/A-Z/a-z/;
      if (/\bowner-[-\w.]+@/) { s/^.*\bowner-([-\w.]+@[\w.]+)\b.*$/\1/; }
      else { s/(^|^.*[^-\w.])([-\w.]+)-owner(@[\w.]+)\b.*$/\2\3/; }
      if (/[^a-z0-9@.-]/) { next; }
      if (!defined ($addresses{$_})) { $addresses{$_}=""; }
    }
    if (/(\bl-[-\w.]+@)|([-\w.]+-l@)/i) {
      chop;
      tr/A-Z/a-z/;
      if (/\bl-[-\w.]+@/) { s/^.*\bl-([-\w.]+@[\w.]+)\b.*$/\1/; }
      else { s/(^|^.*[^-\w.])([-\w.]+)-l(@[\w.]+)\b.*$/\2\3/; }
      if (/[^a-z0-9@.-]/) { next; }
      if (!defined ($addresses{$_})) { $addresses{$_}=""; }
    }
  }
  close MYFILE;
  while (($key,$value)=each %addresses) { print "$key\n"; }
  if (! keys %addresses ) { print "no listservers\n";  next; }
  if (! open (MYFILE, "<$file" ))
   { print "Couldn't open file \"$file\"\n"; next; }
  print "looking for listserver addresses\n";
  while (<MYFILE>) {
    foreach $address (keys %addresses) {
      $host=$address;
      $host =~ s/^.*@//;
      if (/(listserv|listproc|majordomo)@$host/i) {
        $addresses{$address}=$1;
#        print "found 1 = \"$1\"\n";
      }
    }
  }
  close MYFILE;
  while (($key,$value)=each %addresses) {
    $host=$key;
    $host=~s/^.*@//;
    $list=$key;
    $list=~s/@.*$//;
#    print "$value@$host key=\"$key\" list=\"$list\" \n";
    if ($value eq '')
      { $address="listserv@$host,listproc@$host,majordomo@$host"; }
    else { $address="$value@$host"; }
    print "address=\"$address\"\n";
    print "unsubscribe $list\n";

    if (!$debug) {
      print "Mailing $user\n";
      &unsub ($user, $list, $host, $address);
      &notify ($user, $list, $host, $address);
    }  else {
      print "debug no mail\n";
    }
  }
}
