#!/usr/local/bin/perl ## ## bottled_reply - serve files by email ## ## Usage (in /etc/aliases): ## owner-alias: bounceaddr ## alias: "|progpath alias replydir bounceaddr" ## or ## alias: "|progpath alias replydir bounceaddr", /archive ## where: ## ## - progpath = full pathname of this script ## ## - alias = name of alias @ actual host, ## like: book-info-request@online.ora.com ## ## - replydir = directory containing files we're allowed to send ## back to the user. The file "default" in that directory ## is sent if we no get request is included. ## File should start with NO BLANK LINE, then From:, Subject: ## and any other header except To: (which this program fills in). ## Then, before message in file, put a single blank line. ## ## - bounceaddr = address (envelope sender) to send bounces to ## ## - /archive = full pathname of archive file to save all incoming messages ## (usually needs to be mode 666 unless no messages come from local host) ## ## by Alan Schwartz 5/16/96 ## based on canned_reply by Jerry Peek, 8/17/93 # TABSTOPS IN THIS SCRIPT SET AT 4 (IN vi, USE :se ts=4 sw=4) # Modify $mailer for your system if necessary: $mailer = "/usr/lib/sendmail -f$ARGV[2] -oi"; $* = 1; # # $replydir = $ARGV[1]; # # If wrong number of args or unreadable canned reply file, # send error and sender's mail message to postmaster: # complain_and_die("need 3 arguments, got:\n\t@ARGV") if (scalar(@ARGV) != 3); complain_and_die("Direcotry $replydir not a full path") unless $replydir =~ m#^/#; complain_and_die("no directory $replydir") unless -d $replydir; complain_and_die("can't search $replydir") unless chdir($replydir); # # Read (only) header into the variables $from (for envelope sender) # and $header (for the rest of the header) # while () { last if /^$/; # Make key lower-case: if (/^From /) { # listproc system is case-sensitive on first line; # if it's "from" instead of "From", it's a syntax error. # So, save From line separately. @from = (split(/^([-\w]+)[ ]*/)); } elsif (/^\S/) { @part = (split(/^([-\w]+:?)[ ]*/)); $part[1] =~ tr/A-Z/a-z/; $header .= "$part[1] $part[2]"; } else { $header .= $_; } } # # Put headers into array. Note: values (but not keys) end with newlines. # (Adapted from "Programming Perl" chapter 4.) # Note: loses multiple lines with same key (like Received:): # $header =~ s/\n\s+/ /g; # Merge continuation lines. %head = ('FRONTSTUFF', split(/^([-\w]+:?)[ ]*/, $header)); # Now we can read body from if we need to... # # Get address to use: # if (defined($head{'reply-to:'})) { $useaddr = $head{'reply-to:'}; } elsif (defined($head{'from:'})) { $useaddr = $head{'from:'}; } elsif (defined($head{'apparently-from:'})) { $useaddr = $head{'apparently-from:'}; } # # Does the subject contain "get filename"? # if ($head{'subject:'} =~ /^get\s+(\S+)\s+$/) { $filename = $1; if ($filename =~ m#^[\./]# || $filename =~ m#..# || $filename =~ m#[^-\w\.]#) { $reply = "Bad filename: $filename\n"; } elsif (! open(REPLY, $filename)) { $reply = "No such file: $filename\n"; } } elsif (! open(REPLY,"default")) { $reply = "I don't know what to send you.\n"; } # # If we got an address, use it. Else, bounce to bounceaddr: # if (defined($useaddr)) { chop $useaddr; open(MAIL, "|$mailer -t") || die; print MAIL "To: $useaddr\n"; if ($reply) { print MAIL "Subject: file server error\n"; print MAIL "\n"; print MAIL $reply,"\n"; } else { # REPLY file may start with From:, Subject:; MUST then have blank line: print MAIL ; } print MAIL "\n\n ----------- Your original message is below ----------\n\n"; print MAIL ; close(MAIL); close(REPLY) unless $reply; } else { # BOUNCE TO bounceaddr open(MAIL, "|$mailer $ARGV[2]") || die; print MAIL "$0 aborting: can't find address to reply to.\n\n"; print MAIL "Would have sent: $reply\n" if $reply; # End string with > to prefix the From line in the message: print MAIL "This message needs a reply:\n\n>"; print MAIL ; close(MAIL); } exit(0); # We don't want sender to know that something went wrong sub complain_and_die { local($complaint) = $_[0]; open(MAIL, "|$mailer postmaster") || die; print MAIL "$0 aborting from '$ARGV[0]' alias:\n\t$complaint\n\n"; # End string with > to prefix the From line in the message: print MAIL "This message needs a reply:\n\n>"; print MAIL ; close(MAIL); exit(0); # We don't want sender to know that something went wrong }