#!/usr/local/bin/taintperl # $Id: mailback.pl,v 1.5 2006/02/12 21:54:43 erik Exp $ # # Author: Erik C. Thauvin # # Thanks to David Walker and Robert Dinse # for the great suggestions. # # This script will mail the content of any HTML form to its author. # # Based on "mailback.pl" by Phillip Moore # Source available at http://www.erc.msstate.edu/~phil/src/mailback.pl # # Also based on "sendmail-cgi.pl" by Erik C. Thauvin # Copyright (C) 1995-2006 Erik C. Thauvin. All rights reserved. # # Date: 2006-02-06 # # Usage: You must reference this script in your HTML forms with # the method=POST option. Options are passed inside the # the document with the input tag, as follows: # # # # The variable-name represents parameters for this script. # The following are reserved names used by the script and # must be specified in your HTML documents/forms: # # mailitto (req) - Full internet mail address of mail recipient. # This MUST be your email address on Eskimo. # # namefrom (req) - Name of the person the submission is from. # # mailfrom (req) - Email address of the person the submission # is from. # # subject (req) - Subject of the email message. # # bcc - If defined, sends a blind carbon copy of the # mail message to the person submitting the form. # # showreport - If defined, a mail status report is shown upon # submission; otherwise a generic confirmation # message is displayed. # # returngraphic - Inline image to be displayed at the bottom of # the mail confirmation/status report. # # returntext - If "retrungraphic" is defined, the text is used # as an alternate to the "returngraphic" for non- # graphical browsers, such as lynx. # If "returngraphic" is not defined, the text is # displayed instead of the image. # # returnurl - The URL of "returngraphic" and/or "returntext". # If not defined, the URL of the previous page is # used. # # returnmsg - The actual confirmation message. If not defined, # a generic message is used. # # returntitle - The confirmation message's title. If not defined, # "Mail Confirmation" is used. # # returnpage - The URL of a custom "Mail Confirmation" page. # Overrides "showreport", "returntext", "returnurl", # "returngraphic", "returnmsg" and "returntitle". # # subtag - The name of one of the form's input tag. If valid, # the tag's value will be affixed to the subject of # the mail. # # bodytags - The HTML elements to be included in the tag # of the confirmation/error messages. Example: # # ... value="bgcolor=#FFFFFF vlink=#008000" ... # # base - The URL to be used in the HTML tag of the # confirmation/error messages. # # nozeros - Suppresses input tags whose values are 0. # # noblanks - Suppresses input tags whose values are blank. # # notags - Suppresses input tags from email message. # # senderinfo - Includes "namefrom" and "mailfrom" in the body # of the email message. # # The ones with (req) are required but may be written into the HTML # form so that users cannot change them. For example: # # # Mailback Sample Form # #
# # # # # # Your Name:
# Your Email Address:
# Subject:

# Your Message:
#

# # #

# # # # This software is provided "as is" without express or implied warranties. # # Permission is granted to use, copy, modify and distribute this software, # provided this disclaimer and copyright are preserved on all copies. This # software may not, however, be sold or distributed for profit, or included # with other software which is sold or distributed for profit, without the # permission of the author. # $ENV{'PATH'} = '/bin:/usr/bin:/usr/lib'; $ENV{'IFS'} = ''; # # Mail server address & port # $mailserv = 'mail.eskimo.com'; $mailport = 25; # # CRLF # $eol = "\015\012"; # # Try SMTP? # $trysmtp = 0; # # Valid mail server hosts # @validhosts = ( 'eskimo.com', 'skytouch.com' ); # # Print text/html error message # sub error { local($msg) = @_; &printheader('Error'); print "


Error

\n
\n$msg\n
\n

\n"; &printfooter; exit 1; } # # Return error if mail could not be sent # sub mailerror { close(SOCK); &error("An timeout error (ID=@_) occurred while sending mail. Please try " . "again later or notify " . "the creator of this page.\n

\n

\nThank you."); } # # Print detailed text/html error message # sub notenoughinfo { local($msg) = @_; if ($infoerr == 0) { &printheader("Error"); print "


Error

\n" . "

Not Enough Information:

" . "
\n$msg\n
\n"; } else { print "

And

\n
\n$msg\n
\n"; } $infoerr++; } # # Print html header # sub printheader { local($title) = @_; print "Content-Type: text/html$eol$eol" . "\n\n"; if (defined($posted{base})) { print "\n"; } print "$title\n"; if (defined($posted{bodytags})) { print "\n\n"; } else { print "\n\n"; } } # # Print html footer # sub printfooter { if (!defined($posted{skipRSLlink})) { print "\"Designed"; } else { print "\"Designed"; } print "
\n"; if (defined($posted{returnurl})) { if (defined($posted{returngraphic}) && defined($posted{returntext})) { print "\"$posted{returntext}\"\n"; } elsif (defined($posted{returngraphic})) { print "\n"; } elsif (defined($posted{returntext})) { print "$posted{returntext}\n"; } else { print "Follow this link to continue.\n"; } } else { print "Back to the previous page.\n"; } print "\n"; } # # Get mail server result code # sub getresultcode { local($buff, $resultcode, $bits) = ""; local($timeout, $nbr) = 0; vec($bits, fileno(SOCK), 1) = 1; LOOP: { if ($timeout <= 2) { ($nfound, $bits) = select($bits, undef, undef, 3); if ($nfound) { $nbr = sysread(SOCK, $buff, 1024); if ($nbr > 0) { if (length($resultcode) < 3) { $resultcode .= substr($buff, 0, 3); if ($resultcode == 220) { $timeout++; redo LOOP; } } if (substr($buff, -1, 1) ne "\012") { $timeout++; redo LOOP; } } } else { $timeout++; redo LOOP; } } else { if ($resultcode != 220) { $resultcode = 554; } } } return $resultcode; } # # Get host address # sub getaddress { local($host) = @_; local(@addrs); @addrs = gethostbyname($host); return(unpack("C4", $addrs[4])); } # # Verify mail host validity # sub isvalidhost { local($email) = @_; local($name, $host) = split('@', $email); foreach (@validhosts) { if ( /$host/i ) { return 1; } } return 0; } # # Ensure that the proper environment variables are defined # if (!defined($ENV{REQUEST_METHOD}) || $ENV{REQUEST_METHOD} ne "POST") { &error("This script should be referenced with a METHOD of POST. If you " . "don't understand this, see the forms overview" . ".\n

\n

\nThank you."); } # # More environment variables # if (!defined($ENV{CONTENT_TYPE}) || $ENV{CONTENT_TYPE} ne "application/x-www-form-urlencoded") { &error("This script can only be used to decode form results."); } # # Read in the message based on the CONTENT_LENGTH in the header. # If no CONTENT_LENGTH, complain about the error. # if (defined($ENV{CONTENT_LENGTH}) && $ENV{CONTENT_LENGTH} != 0) { $bytes = read(STDIN, $all, $ENV{CONTENT_LENGTH}); foreach $pair (split("&", $all)) { ($key, $val) = split("=", $pair); $val =~ tr/+/ /; $val =~ s/%(..)/pack("c", hex($1))/eg; # $val =~ s/\n/\n /g; if (defined($posted{$key})) { $posted{$key} = "$posted{$key}\n$val"; } else { $posted{$key} = $val; push(@keylist, $key) if ( $key ne "mailitto" && $key ne "errorsto" && $key ne "namefrom" && $key ne "mailfrom" && $key ne "subject" && $key ne "bcc" && $key ne "showreport" && $key ne "returnurl" && $key ne "returntext" && $key ne "returngraphic" && $key ne "skipRSLlink" && $key ne "returnmsg" && $key ne "returntitle" && $key ne "returnpage" && $key ne "subtag" && $key ne "bodytags" && $key ne "base" && $key ne "nozeros" && $key ne "noblanks" && $key ne "senderinfo" && $key ne "notags" ); } } } else { &error("This script, the URL, or the fields given in the form returned " . "an error. Please notify the creator of this page.\n

\n

\n" . "Thank you."); } # # Check that each of the four required fields are entered properly # Make sure user has entered "mailitto" , "mailfrom", "namefrom" # and "subject" # ### To: ### if (!defined($posted{mailitto}) || !&isvalidhost($posted{mailitto})) { ¬enoughinfo("The creator of the form you are using failed to provide " . "a valid e-mail address. Please try again later, or send " . "mail to the person who created this form.

"); } ### From ### if (!defined($posted{namefrom}) || $posted{namefrom} =~ /^\s*$/) { ¬enoughinfo("Please provide your first and/or last name to help the " . "reader of this message identify you.

"); } else { $posted{namefrom} =~ s/^\s*//; $posted{namefrom} =~ s/\s*$//; } ### From: ### if (!defined($posted{mailfrom}) || $posted{mailfrom} !~ /^[-._%!*\/+0-9A-Za-z]+@[-0-9A-Za-z.]+\.[A-Za-z][A-Za-z]+$/) { ¬enoughinfo("Please provide a full internet mail address so the reader " . "of this message may reply to you.

"); } else { $posted{mailfrom} =~ s/^\s*//; $posted{mailfrom} =~ s/\s*$//; } ### Subject: ### if (!defined($posted{subject}) || $posted{subject} =~ /^\s*$/) { ¬enoughinfo("Please provide a subject to give the reader of this " . "message some clue as to its content.

"); } else { $posted{subject} =~ s/^\s*//; $posted{subject} =~ s/\s*$//; $posted{subject} =~ s/(\r|\n)//g; } # # As long as those four fields are non-empty, and in a valid format, send it # if ($infoerr > 0) { &printfooter; exit 1; } else { # # Connect to the mail server # local($sockaddr, $addr) = ("Snc4x8"); local($mailagent) = 'sendmail'; if ($trysmtp) { $addr = pack($sockaddr, 2, $mailport, &getaddress($mailserv)); if (socket(SOCK, 2, 1, 6)) { if (connect(SOCK, $addr)) { select(SOCK); $| = 1; select(STDOUT); $| = 1; if (&getresultcode == 220) { $mailagent = 'smtp'; } } } } # # Send mail message # if ($mailagent eq 'sendmail') { close(SOCK); open(SOCK, "| /usr/lib/sendmail -t"); } else { print SOCK "HELO mailback$eol"; do { &mailerror(1200); } if (&getresultcode != 250); print SOCK "RSET$eol"; do { &mailerror(1300); } if (&getresultcode != 250); print SOCK "MAIL FROM:<>$eol"; do { &mailerror(1400); } if (&getresultcode != 250); print SOCK "RCPT TO:<$posted{mailitto}>$eol"; do { &mailerror(1500); } if (&getresultcode != 250); if (defined($posted{bcc})) { print SOCK "RCPT TO:<$posted{mailfrom}>$eol"; do { &mailerror(1500); } if (&getresultcode != 250); } print SOCK "DATA$eol"; do { &mailerror(1600); } if (&getresultcode != 354); } print SOCK "From: $posted{mailfrom} ($posted{namefrom})$eol" . "To: $posted{mailitto}$eol"; if (defined($posted{bcc})) { print SOCK "Bcc: $posted{mailfrom}$eol"; } if (defined($posted{$posted{subtag}})) { $posted{$posted{subtag}} =~ s/(\r|\n)//g; print SOCK "Subject: $posted{subject} ($posted{$posted{subtag}})$eol"; } else { print SOCK "Subject: $posted{subject}$eol"; } if (defined($ENV{REMOTE_ADDR})) { print SOCK "X-Remote-Address: $ENV{REMOTE_ADDR}$eol"; } if (defined($ENV{REMOTE_HOST})) { print SOCK "X-Remote-Host: $ENV{REMOTE_HOST}$eol"; } if (defined($ENV{REMOTE_IDENT})) { print SOCK "X-Remote-Ident: $ENV{REMOTE_IDENT}$eol"; } if (defined($ENV{REMOTE_USER})) { print SOCK "X-Remote-User: $ENV{REMOTE_USER}$eol"; } if (defined($ENV{HTTP_REFERER})) { print SOCK "X-URL: $ENV{HTTP_REFERER}$eol"; } print SOCK "X-Mailback-Agent: $mailagent$eol"; if (defined($posted{senderinfo})) { if (defined($posted{notags})) { print SOCK "$eol$posted{namefrom}$eol" . "$eol$posted{mailfrom}$eol"; } else { print SOCK "$eol--- Sender's Name ---$eol$posted{namefrom}$eol" . "$eol--- Sender's Email Address ---$eol$posted{mailfrom}$eol"; } } foreach $key (@keylist) { $keyval = $posted{$key}; if (!(defined($posted{noblanks}) && (length($keyval) == 0))) { $keyval =~ s/\012\.\015/\012\.\.\015/g; $keyval =~ s/\012\.$/\012\.\./; if (!(defined($posted{nozeros}) && ($keyval eq "0"))) { if (defined($posted{notags})) { print SOCK "$eol$keyval$eol"; } else { print SOCK "$eol--- $key ---$eol$keyval$eol"; } } } } print SOCK ".$eol"; if ($mailagent eq 'smtp') { do { &mailerror(1700); } if (&getresultcode != 250); print SOCK "QUIT$eol"; } close(SOCK); } # # If "returnpage" is defined... # if (defined($posted{returnpage})) { print "Location: $posted{returnpage}$eol$eol"; } # # If "showreport" is defined then show the mail report and have a link # to return back to some page # elsif (defined($posted{showreport})) { &printheader("Mail Status Report"); print "


Mail Status Report

\n\n

\n" . "From: $posted{mailfrom} ($posted{namefrom})\n
\n" . "Sent To: " . "$posted{mailitto}
\n"; if (defined($posted{$posted{subtag}})) { print "Subject: $posted{subject} ($posted{$posted{subtag}})$eol"; } else { print "Subject: $posted{subject}$eol"; } print "

\n
";
    
    foreach $key (@keylist)
    {
        $keyval = $posted{$key};

        if (!(defined($posted{noblanks}) && (length($keyval) == 0)))
        {
            $keyval =~ s/\&/\&\;/g;
            $keyval =~ s/\/\>\;/g;

            if (!(defined($posted{nozeros}) && ($keyval eq "0")))
            {
                if (defined($posted{notags}))
                {
                    print "$keyval\n";
                }
                else
                {
                    print "$key: $keyval\n";
                }
            }
        }
    }
    print "

Thank You!

\n"; &printfooter; } # # If "showreport" is not defined then just show a message # of confirmation and have a link to another page # else { if (defined($posted{returntitle})) { &printheader($posted{returntitle}); print "


$posted{returntitle}

\n

\n"; } else { &printheader("Mail Confirmation"); print "


Mail Confirmation

\n

\n"; } if (defined($posted{returnmsg})) { print $posted{returnmsg}; } else { print "

\nYour message was sent to " . "$posted{mailitto}\n
\n

Thank You!

\n"; } print "\n

\n"; &printfooter; } exit 0;