#!/usr/bin/perl -T
###########################################################
#
# Example of a cgi program that sends email.
#
# I've tried to handle security issues properly here.
# In particular,
# (1) I apply "escapeHTML" to user input before printing
#     it back as html, so that nothing the user has typed does anything funny.
# (2) The whole script is run under taint mode (-T), 
#     and the PATH is set explicity.
# (3) I verify the form of the destination user input, and bail if 
#     it looks like it has characters I don't like.
#
# The actual mail is sent via an SMTP socket connection to 
# a mail server, in this case the campus server smtp.marlboro.edu.
# The module that does this is Mail::Sendmail, which can either be
# installed system wide as a regular CPAN module (it is on cs.marlboro.edu)
# or located somewhere nearby.  
# In particular, "use Mail::Sendmail" will look for ./Mail/Sendmail.pm
#
# Jim Mahoney, 
#   October 2004
#   uses campus smtp server smtp.marlboro.edu and Mail::Sendmail
#
###########################################################
use strict;
use warnings;
$ENV{PATH}="";                          # make taintmode happy
use CGI qw(:standard);                  # use function interface to CGI
use CGI::Carp qw(fatalsToBrowser);
my $SMTPserver = 'smtp.marlboro.edu';   # who we send the mail to 
my $result = '';                        # summary report to user

# --- process user input and send the email ---------------------
if (param) {
  my $to      = param('to');
  my $from    = param('from');
  my $subject = param('subject');
  my $message = param('message');
  my $method  = param('method');
  verifyToAddress($to) or exit;
  $result = send_email($to, $from, $subject, $message);
}

# --- print the web page ----------------------------------------
print                                   
  header,
  start_html( -title => 'Send some Email'),
  " <h2>Send some email</h2> \n",
  start_form,
  "To :     ", textfield( -name=>'to',      -size=>40, -maxlength=>60),   br
  "From :   ", textfield( -name=>'from',    -size=>40, -maxlength=>60),   br
  "Subject :", textfield( -name=>'subject', -size=>40, -maxlegnth=>60),   br
  "Message :", br, textarea(  -name=>'message', -columns=>50, =>rows=>4), br
  submit(-value=>'Send Email'),
  end_form,
  hr,
  $result,
  "<div align='right'>Jim Mahoney (mahoney\@marlboro.edu)</div>\n",
  end_html;

# === subroutines =================================================

sub send_email {
  my ($to, $from, $subject, $message) = @_;
  use Mail::Sendmail;
  my %mail = ( smtp    => $SMTPserver,
	       To      => $to,
	       From    => $from,
	       Subject => $subject,
	       Message => $message,
	     );
  sendmail(%mail) or die "$Mail::Sendmail::error";
  $to = CGI::escapeHTML($to);
  $subject = CGI::escapeHTML($subject);
  return "OK, Mail::Sendmail set a message to '$to' about '$subject'.";
}

# Check to see if the destination address is OK.
# If it is, return 1.
# If not, output an html error page and return 0.
sub verifyToAddress {
  my ($to) = @_;
  # As an example of checking the form of the user input,
  # in this case I'm going to make sure that the destination "To"
  # address has only (letters numbers @ . - _).  commas are not allowed,
  # which should (I think) limit us to one address and minimize spam.
  if ($to =~ /[^a-zA-Z0-9@.-_]/) {
    print
      header,
      start_html(-title=>'Oops'),
      "<h2>Error in destination address</h2>",
      "The 'To' address may contain only the following characters: ",
      "<font color='darkred'>a-z A-Z 0-9 . - _ @ </font>.\n",
      "The destination address you entered, <br>",
      "<table border=1><tr><td><pre>", 
        CGI::escapeHTML($to),
      "</pre></tr></td></table><br>",
      "is not of this form.",
      end_html;  
    return 0;
  }
  else {
    return 1;
  }

}
