#!/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 = < (-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); ¬ify ($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 () { # 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 () { 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); ¬ify ($user, $list, $host, $address); } else { print "debug no mail\n"; } } }