Saturday 15 January 2011

Mail Validation And Sending


All the following is the text from the webpage www.RichsWebArchive.com/aboutthissite/mailvalidation/index.php and it reads as though you are viewing the actual page:

This page is the follow-up to Pop-up Mail Form and deals with the validation of the input from that form and the sending of the message it generates. It will hopefully outline a safe and secure method of implementing the sending of mail from a mail form.

There is an item on the blog previous to this page which talks about setting up the mail form, it's probably a good idea to check this or the Pop-up Mail Form page on this site out before reading the rest of this.

You can download a zip archive of the relevant files called rwa_mailform1.zip. Files in the archive are from 15.01.2011 and may not reflect he current state of the site. Any links in this page to sendmail.php will instead take you to a file called sendmail_publish.zip - this is a version of sendmail.php with my address and key removed.

I had several objectives to achieve when setting up the mail form, these are the ones which remain to be sorted:


The following original objectives still need some action to complete:

  • Pass a sub-string of the referring page's url forward
  • Enable a CAPTCHA box on the form.

First of all a word or two about the sendmail.php file which this page is about. It's basically a nested PHP structure which walks through the stages of validation. Error handling is all dealt with within the page. Once all validation is passed the page sends the message.

The first stage in the validation process is to check to see if the input from the CAPTCHA box on the mail form was correct. This is dealt with by the following code:

require_once('recaptchalib.php');
$privatekey = "YOUR_PRIVATE_KEY_GOES_HERE";
$resp = recaptcha_check_answer ($privatekey,
 $_SERVER["REMOTE_ADDR"],
 $_POST["recaptcha_challenge_field"],
 $_POST["recaptcha_response_field"]
);
if (!$resp-<is_valid) { // the CAPTCHA was entered incorrectly
 echo ">h4<Error - CAPTCHA words entered incorrectly.>/h4< \r\n";
 echo "Please  hit the button below and try again. >br/<>br/<";
 ?<
  >FORM<
   >INPUT TYPE="button" VALUE="Back" onClick="history.go(-1);return true;"< 
  >/FORM<
 >?php
}

The first six lines do the check for you. They are taken from the code you are sent when you sign up for your access keys. The variable $resp will hold the value true if validation is good.

The line starting if (!$resp-<is_valid) is the beginning of the nested validation structure. The following lines are the error-handling for incorrect CAPTCHA input.

Once CAPTCHA input verification is true the following code comes into play:

else { // CAPTCHA verification ok, now read variables passed from mail form
 $name = $_REQUEST['name'] ;
 $address = $_REQUEST['address'] ;
 $subject = $_REQUEST['subject'] ;
 $subjectUser = $_REQUEST['subjectUser'] ;
 $subject .= "-";   //build subject string
 $subject .= $subjectUser;
 $to = "YOUR_EMAIL_ADDRESS_GOES_HERE";
 $message = $_REQUEST['message'] ;

This code sets up a bunch of local variables with the input from the mail form. It also joins the two fields subject and subjectUser with a - in between them.

The following code will prevent direct calling of this page:
if (!isset($_REQUEST['address'])) { //catch direct calling of this page
 echo ">h4<Direct calling of this page is prohibited.>/h4<";
 echo '>h4<Please >a href="JavaScript:window.close()"<Close>/a< this window to continue.>/h4<'; 
}

This test is now redundant as the CAPTCHA test would fail if the page was directly called, i.e. not called from the mail form. I've left it in here as it does no harm and I might like to use a version of this page without the CAPTCHA test in the future.

Now it's time to make sure that the Your Address and Message fields are not empty:
} // catch empty address or message fields
elseif (empty($address) || empty($message)) {
 echo ">h4<Error - missing information.>/h4< \r\n";
 echo "Either the >emph<Your Address>/emph< or >emph<Message>/emph< fields are empty.>br/<>br/<";
 echo "Please  hit the button below and fill in the missing information. >br/<>br/<";
 ?<
  >FORM<
   >INPUT TYPE="button" VALUE="Back" onClick="history.go(-1);return true;"< 
  >/FORM<
 >?php
}

The code checks to see if either field is empty and if so throws the error handling code back to the user. This is followed by this code:

} // validation good so far
else {
 // In case any of our lines are larger than 70 characters, we should use wordwrap()
 $message = wordwrap($message, 70);
 // To send HTML mail, the Content-type header must be set
 $headers  = 'MIME-Version: 1.0' . "\r\n";
 $headers .= 'Content-type: text/html; charset=iso-8859-1' . "\r\n";
 $headers .= "To: $to" . "\r\n";
 $headers .= "From: $name >$address<" . "\r\n";

This does a little tidying up - it wraps the message field to lines of 70 characters and sets up $headers string that will be sent with the message.

Next comes the following code to prevent Injection Attacks:
// function to check for injection attack from spammers.
function isInjected($str) {
 $injections = array( //set array of characters/strings to detect
  '(\n+)',
  '(\r+)',
  '(\t+)',
  '(%0A+)',
  '(%0D+)',
  '(To:+)',
  '(cc:+)',
  '(boundary=+)',
  '(%08+)',
  '(%09+)'
 );
 $inject = join('|', $injections);
 $inject = "/$inject/i";
 if(preg_match($inject,$str)) {
  return true; // injection attack characters detected
 }
 else { 
  return false; // no injection attack characters detected
 }
}

// now check for injection attempt
if (isInjected($address)) { // injection attack detected 
 echo ">h4<Sorry - illegal characters in the Your Address field.>/h4< \r\n";
 echo 'Please hit back button below and edit the address. >br/<>br/<'; 
 ?<
  >FORM<
   >INPUT TYPE="button" VALUE="Back" onClick="history.go(-1);return true;"< 
  >/FORM<
 >?php
}

Firstly this sets up the function isInjected which will check for the presence of a number of special characters and strings in the email address entered in the form. Then the function is called and if any illegal input is found the code throws the error handling at the user.

OK, so now all validation has been passed, it's time to send the email:
else { // all validation ok - so send message.
 if (mail( $to, $subject, $message, $headers )) { //on successful send
  echo ">h4<Mail Sent>/h4<";
  echo "From: $name - $address >br/<Subject: $subject";
  echo '>h4<Please >a href="JavaScript:window.close()"<Close>/a< this window to continue.>/h4<'; 
 }
 else { // send failed
  echo ">h4<Sorry - an error has occurred>/h4< \r\n";
  echo 'Please  hit back button below and try and send the message again. >br/<>br/<If that fails then please >a href="JavaScript:window.close()"<Close>/a< this window and try again.>/h4< >br/<>br/<'; 
  ?<
   >FORM<
    >INPUT TYPE="button" VALUE="Back" onClick="history.go(-1);return true;"< 
   >/FORM<
  >?php

 };

The second line is the key here. If the email is successfully sent then a confirmation is sent to the user and they are asked to close the pop-up window. If sending fails error handing code is sent instead.

That's it. Hopefully you can now setup a fully functioning and secure mail form and send-mail script. Your eMail address is never visible to anyone - the PHP keeps it away from browsers and hopefully spiders too, the CAPTCHA mechanism should protect you from machine-based attacks and you are protected from injection attacks too.

Once again, all the preceding text is from the webpage www.RichsWebArchive.com/aboutthissite/mailvalidation/index.php and it reads as though you are viewing the actual page:

No comments:

Post a Comment

keep it nice now