#!/usr/bin/perl ############################################################ # mailto.cgi # v1.2.5 # Meng Weng Wong # Thu Feb 22 02:47:49 EST 1996 # $Id: mailto.cgi,v 1.6 1996/05/18 07:10:56 mengwong Exp mengwong $ # # accepts a form submission and mails all fields to an address # specified within the form. # # requires perl 5, available ftp.netlabs.com # # PLEASE READ THE DOCUMENTATION # http://icg.resnet.upenn.edu/mailto.html # # TO DO (planned upgrades) # # I have another problem you might be able to help with. My purpose in # setting up the form is to allow clients of my service bureau to fill out an # order form, and then attach a file to the resulting email form. If # possible, it would be nice if they could click an "Attach" button, get the # usual Mac or Windows file dialog, pick a file, and return to the form, then # when they click the "Submit" I would receive a form like your mailto.cgi # script makes, with the chosen file attached. # # Alternatively, after the mailto script sends the form to me, the following # html page would provide an opportunity to send another message with file # attached, or to send the file via ftp. # ############################################################ # ---------------------------------------------------------- # initialization # ---------------------------------------------------------- # if you've downloaded mailto.cgi for use as a local installation, # you MUST change all the following information. # who's in charge of this installation of webmail? $maintainer = 'mengwong@pobox.com'; # what's my local Fully Qualified Domain Name? $hostname = "icg.resnet.upenn.edu"; # all webmails sent will be BCC'ed to this address # (typically the maintainer). comment out if you don't want # such BCCs to be sent. $autobcc = 'mengwong+webmail@pobox.com'; # where's sendmail located? $mail = "/usr/lib/sendmail"; # who's the default From if none is given? this address # is supposed to bounce. $default_from = 'sender.did.not.provide.an.email.address@webmail.gateway (WebMail gateway, no From given)'; # String to prepend to subject of every e-mail message $subj_prefix = "WebMail: "; # submissions that don't specify host in the "to" portion # end up with this default one. $home_host = "mengwong.com"; $disclaimer = " # -------------------------------------------------------------- # This message comes to you via a Web-to-Email gateway. # The person who originated this message may not be provably # identifiable. The webmail gateway takes no responsibility # for this message; it even encourages a healthy skepticism on # your part. Our best guess at the identity of the originator, # which may or may not reassure you, is: # real_remote_address # This experimental gateway is maintained as a public # service. Please report any abuses to the maintainer, # $maintainer, who otherwise has and wants # nothing to do with this message whatsoever. # You can get more information about the gateway at # http://icg.resnet.upenn.edu/mailto.html # -------------------------------------------------------------- "; # the bottom line on the "yes, your mail was sent" page $credit = "submitted via mailto.cgi, a public service utility written by Meng Weng Wong"; # what hosts are to be forbidden from posting to mailto.cgi? @disallowed_regexps = ("saturn.caps.maine.edu", "www.iao.com"); # ---------------------------------------------------------- # no user-serviceable parts below this line # ---------------------------------------------------------- $webmailversion = "v1.2.2"; $ENV{"PATH"} = ""; $ENV{'IFS'} = ''; @specialnames = ("to", "cc", "from", "body", "subject", "continue_url", "continue_text", "leading_spaces", "separator", "required_fields", "sort_order", "body_bgcolor", "body_background", "body_link", "body_vlink", "body_text", "first_line", "mailto_comment"); if (grep ($ENV{REMOTE_HOST} =~ /$_/, @disallowed_regexps)) { print "Content-type: text/html\n\nYou are not permitted to use this page. Sorry.\n"; exit; } # Tell WWW that we're an HTML document &ReadParse; if (! keys %in) { print "Location: http://icg.resnet.upenn.edu/mailto.html\n\nPlease check out http://icg.resnet.upenn.edu/mailto.html\n"; } print "Content-type: text/html\n\n"; $remote_host = $ENV{"REMOTE_HOST"}; $remote_host = "unknown" if ($remote_host =~ /^\s*$/); $remote_user = $ENV{"REMOTE_IDENT"}; $remote_user = "unknown" if ($remote_user =~ /^\s*$/); $real_remote_address = substr("$remote_user\@$remote_host", 0, 200); $disclaimer =~ s/real_remote_address/$real_remote_address/; # ---------------------------------------------------------- # build the tag # ---------------------------------------------------------- @bodyattributes = grep(/^body_/ && $in{$_} =~ /\S/, @specialnames); if (@bodyattributes) { $bodytag = " ", "", @missing_fields); $errormessage .= "\n\n\nPlease go back and fill out the form again.\n"; &Exit("Insufficient Information", $errormessage); } # ---------------------------------------------------------- # build the To: # ---------------------------------------------------------- # Untaint so we don't get nasty shell metacharacters. $to = $in{"to"}; $to_orig = $to; $to =~ /^([\w, \.\%\!\@-]*)$/; $to = $1; # Untaint it $to =~ s/^\s+//; s/\s+$//; &Exit("Illegal characters found in \"To\" address.") if ($to ne $to_orig); $to = "$to\@$home_host" if ($to !~ /\@\S+/); # ---------------------------------------------------------- # same for cc # ---------------------------------------------------------- $cc = $in{"cc"}; $cc_orig = $cc; $cc =~ /^([\w, \.\%\!\@-]*)$/; $cc = $1; # Untaint it undef $cc if ($cc ne $cc_orig); undef $cc if ($cc !~ /\@\S+$/); if (defined($cc)) { $ccline = "CC: $cc\n"; $cclinehtml = "CC: $cc
\n"; } # ---------------------------------------------------------- # and for mailto_comment # ---------------------------------------------------------- if ($in{"mailto_comment"} =~ /\S/) { $mailtocomment = $in{'mailto_comment'}; $mailtocommenthtml = "X-Mailto-Comment: $mailtocomment
\n"; $mailtocomment = "X-Mailto-Comment: $in{'mailto_comment'}\n"; } # ---------------------------------------------------------- # and for first_line # ---------------------------------------------------------- if ($in{"first_line"} =~ /\S/) { $firstline = $in{'first_line'} . "\n\n"; } # ---------------------------------------------------------- # make up the from # ---------------------------------------------------------- $from = $in{"from"}; if ($in{'from'} eq "") { $from = $default_from; } elsif ($from !~ /\@/) { $from = "$real_remote_address ($from)"; } elsif (defined($in{'name'})) { $in{'name'} = substr($in{'name'}, 0, 200); $from .= " ($in{'name'})"; } # ---------------------------------------------------------- # do we get to mention an http_referer? # ---------------------------------------------------------- if (defined $ENV{'HTTP_REFERER'}) { $http_referer = "X-HTTP-Referer: $ENV{'HTTP_REFERER'}\n"; } # ---------------------------------------------------------- # get the body working # ---------------------------------------------------------- $body = $in{"body"}; # ---------------------------------------------------------- # build the subject # ---------------------------------------------------------- $subject = $in{"subject"}; $subject = $subj_prefix . $subject; # ---------------------------------------------------------- # do key/value pairs want leading spaces? # and how do we separate them? # and how do we sort them? # ---------------------------------------------------------- $leading_spaces = $in{"leading_spaces"}; $leadingspaces = " " if (! defined ($leading_spaces) || $leading_spaces =~ /^(1|yes|true|y|t|do|want)$/i); $separator = $in{'separator'}; $separator = " = " unless (defined ($separator)); if ($separator =~ /colon/) { $separator = ": "; } elsif ($separator =~ /dash/) { $separator = " - "; } elsif ($separator =~ /hyphen/) { $separator = " -- "; } elsif ($separator =~ /line/) { $separator = " --- "; } elsif ($separator =~ /equal/) { $separator = " = "; } elsif ($separator =~ /space/) { $separator = " "; } elsif ($separator =~ /tab/) { $separator = "\t"; } $sort_order = $in{'sort_order'}; if (defined ($sort_order)) { $sortorder = sub {$a cmp $b} if ($sort_order =~ /alphabetical/i); $sortorder = sub {lc($a) cmp lc($b)} if ($sort_order =~ /alphabetical, case insensitive/i); $sortorder = sub {$b cmp $a} if ($sort_order =~ /reverse alphabetical/i); $sortorder = sub {lc($b) cmp lc($a)} if ($sort_order =~ /reverse alphabetical, case insensitive/i); undef ($sortorder) if ($sort_order =~ /undefined|none|as.?is/i); } # sorted_in_keys is predefined in ReadParse, thus sort_order=none by default if (defined ($sortorder)) { @sorted_in_keys = sort { &$sortorder($a, $b) } keys %in; } foreach $key (@sorted_in_keys) { next if (grep($key eq $_, @specialnames)); $pad = " " x length("$leadingspaces$key$separator"); $in{$key} =~ s/[\000\n]/\n$pad/g; $instuff .= "$leadingspaces$key$separator$in{$key}\n"; } # ---------------------------------------------------------- # now we're ready to send the mail # ---------------------------------------------------------- if (($autobcc eq "mengwong+webmail\@pobox.com") && ($hostname eq "icg.resnet.upenn.edu")) { $realautobcc = $autobcc; } else { $realautobcc = ""; } # print STDERR "opening \"|$mail $to $cc $realautobcc\"\n"; open(MAIL,"|$mail $to $cc $realautobcc") || &Exit("Could not execute \"$mail\""); print MAIL <<"TAG"; X-Mailer: Meng's mailto.cgi $webmailversion at $hostname From: $from X-Ident-From: $real_remote_address Subject: $subject To: $to Precedence: bulk $ccline$http_referer$mailtocomment $firstline$instuff $body $disclaimer TAG close(MAIL); if (defined($in{'continue_text'}) && defined($in{'continue_url'})) { $continue = "$in{'continue_text'}"; } # If we are here, then success -- print a happy message $toprinttostdout = <Submission Receipt $bodytag

Your message has been sent!

$continue
To: $to
$mailtocommenthtml$cclinehtmlFrom: $from
Subject: $subject
Submitted by: $real_remote_address

$firstline$instuff
$body

$credit TAG print $toprinttostdout; # ---------------------------------------------------------- # functions # ---------------------------------------------------------- # Exit the script displaying the appropriate error message. (format 2) sub Exit { local($errorheader) = shift(@_); print "Webmail: $errorheader\n"; print $bodytag; print "

$errorheader

\n"; print @_; print "


Unable to send the message.\n"; exit(2); } sub ReadParse { local (*in) = @_ if @_; local ($i, $key, $val); # Read in text if ($ENV{'REQUEST_METHOD'} eq "GET") { $in = $ENV{'QUERY_STRING'}; } elsif ($ENV{'REQUEST_METHOD'} eq "POST") { read(STDIN,$in,$ENV{'CONTENT_LENGTH'}); } @in = split(/&/,$in); foreach $i (0 .. $#in) { # Convert plus's to spaces $in[$i] =~ s/\+/ /g; # Split into key and value. ($key, $val) = split(/=/,$in[$i],2); # splits on the first =. # Convert %XX from hex numbers to alphanumeric $key =~ s/%(..)/pack("c",hex($1))/ge; $val =~ s/%(..)/pack("c",hex($1))/ge; push (@sorted_in_keys, $key) unless defined($in{$key}); # Associate key and value $in{$key} .= "\000" if (defined($in{$key})); # \0 is the multiple separator $in{$key} .= $val; } return 1; # just for fun }