#!/usr/imports/bin/perl ($user, $passwd, $uid, $gid, $quota, $comment, $gcos, $home, $shell) = getpwnam($ARGV[0]); umask(0077); # Set umask for new files $delivered = 0; # Message has not yet been delivered $errno = 0; # Delivery error $errmsg = ''; # Delivery error message ## These are customizable variables # The perl package that parses headers and such (this should not change) $AUDIT_PACKAGE = "$home/bin/audit.pl"; # The file containing the list of "friends" $FRIENDS = "$home/MailFriends"; # The command to print a message $PRINT_CMD = "/usr/local/bin/imprint -q imagen13 -n -J -h 'E-mail for Dr. Rosenfeld'"; # Directory where mail gets saved $MAILDIR = "$home/Mail"; if (! -e "$AUDIT_PACKAGE") { &abort();} require "$AUDIT_PACKAGE" || &abort(); # If we get this far, then the audit package has been found &initialize(); ##### Beginning of the rules (the interesting part) # # If the message was sent to >= 10 addresses, it qualifies as # a mailing list message # if (@to + @cc >= 10) { $delivered = &append_to_file("$MAILDIR/mailing-lists"); } # # If the message was Cc-ed to Azriel, ... # if (!$delivered && grep(/^(cvl\.)?($user|azriel|rosenfeld)\b/i, @cc)) { if ($from =~ /^ar\b/) { # # if Azriel sent it, print it (and keep an emergency # backup copy). # $delivered = &printit() && &append_to_file("$MAILDIR/from_ar"); } else { # # otherwise, just save it under "cc" # $delivered = &append_to_file("$MAILDIR/cc"); } } # # If the mail was sent to a mailing list, and not to Azriel directly, # put it in an appropriate mailbox. # if ( !$delivered && !grep(/^(cvl\.)?($user|azriel|rosenfeld)\b/i, @to)) { # # Extract the mailing list name. # ($mailinglist = $to[0]) =~ s/^([\w-]+).*/$1/; # if ($mailinglist =~ /^\s*$/) # { # # Paranoid case # $mailinglist = "Unknown"; # } # $delivered = &append_to_file("$MAILDIR/lists/$mailinglist"); $delivered = &append_to_file("$MAILDIR/mailing-lists"); } # # If the mail was sent from anywhere at umd.edu, print it out. # This would be any host @.*.umd.edu, or anything without a domain. # if (!$delivered && (($from =~ /umd\.edu$/i) || ($from =~ /^[\w-]+$/))) { $delivered = &printit() && &append_to_file("$MAILDIR/from_umd"); } # # If it's from a VIP and addressed to Azriel personally, # print it out. # if (!$delivered) { &read_friends("$FRIENDS"); # Put list of friends in @friends for (@friends) { next unless $from =~ /$_/i; # Yup, it comes from a friend, all right if (grep(/^(cvl\.)?($user|azriel|rosenfeld)\b/i, @to, @cc)) { # And it's addressed to Azriel personally. Print it. $delivered = &printit() && &append_to_file("$MAILDIR/from_friend"); } last; } } # # If none of the above, then save as unwanted mail # if (!$delivered) { open(MAIL,">>$MAILDIR/junkmail") || do { $errno = $!+0; $errmsg = "Can't process unwanted mail: $!"; $delivered = -1; &die_cleanly(); }; print MAIL "$header$body\n"; close(MAIL); } print STDERR "$errmsg\n"; exit(0); ##### End of rules (this is where the support functions begin) # read_friends # This file reads the file given as argument, converts each one into # a matchable pattern, sub read_friends { local($fname) = @_; if (!open(FRIENDS, "$fname")) { # Error case: assume there are no friends :-( @friends = (); return; } while () { s/#.*//; # Remove comments chop; # Remove trailing s/\./\\./g; # Escape .s since it's a regexp s/\@/\\@/g; # ...and @s s/\+/\\+/g; # ...and +s s/\*/[^.]+/g; # ...and replace * with [^.]+ tr/A-Z/a-z/; # Lowercase it all s/\s//g; # Remove whitespace next unless /./; # Ignore empty lines push(@friends,$_); } } # printit # Make a hardcopy of the message sub printit { local(@msg); local($") = "\n"; local($*) = 1; $= = 49; # open(PRINTER, ">>$home/WouldHaveBeenPrinted.log") || do { open(PRINTER, "|$PRINT_CMD") || do { $errno = $!+0; $errmsg = "Can't append to $home/WouldHaveBeenPrinted.log: $!"; $delivered = -1; return 0; }; # If the message is < 2 pages, print it out. Otherwise, # print only the first page. @msg = split(/\n/,$header.$body); for ($i = 0; $i <= $#msg; $i++) { if ($msg[$i] =~ /^(.{78})/) { splice(@msg,$i,1,$1,$'); } } if ($#msg <= 2 * $=) { $" = "\n"; print PRINTER "@msg\n\n"; } else { splice(@msg,$=-1); print PRINTER "@msg\n[Rest of message deleted to conserve paper]\n\n"; } close(PRINTER); return 1; } # append_to_file # Append the message to a file. Returns 1 if successful, 0 otherwise. sub append_to_file { local($fname) = @_; open(FOLDER,">>$fname") || do { $errno = $!+0; $errmsg = "Can't append to $fname: $!"; $delivered = -1; return 0; }; print FOLDER "$header$body\n"; close(FOLDER); return 1; } # abort # This function is sort of an equivalent to 'panic()': if the # audit stuff can't be found, it saves incoming mail to the # user's mailbox. # sub abort { open(MAIL, ">>/usr/spool/mail/$user") || open(MAIL, ">>$home/mbox") || open(MAIL, "| /usr/ucb/Mail -s 'Forwarded mail for Dr. Rosenfeld' postmaster'") || die("Reality has failed. Dying"); $/ = ''; $_ = <>; print MAIL; # Write the message header $/ = "\n"; print MAIL <<_EndOfPrologue_; ***** This message could not be delivered normally. Please check ***** .forward, $0, mail and perl setups, and the general ***** structure of reality. ***** Error: $errno -- $errmsg _EndOfPrologue_ while(<>) { print MAIL; # Write the message body } close(MAIL); } # die_cleanly # This is very similar to abort(), but is called after the message # has been &initialize-d. # sub die_cleanly { open(MAIL, ">>/usr/spool/mail/$user") || open(MAIL, ">>$home/mbox") || open(MAIL, "| /usr/ucb/Mail -s 'Forwarded mail for Dr. Rosenfeld' postmaster'") || die("Reality has failed. Dying"); print MAIL "$header\n"; # Write the message header print MAIL <<_EndOfPrologue_; ***** This message could not be delivered normally. Please check ***** .forward, $0, mail and perl setups, and the general ***** structure of reality. ***** Error: $errno -- $errmsg _EndOfPrologue_ print MAIL "$body\n"; # Write the message body close(MAIL); }