Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people, just like you, are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
Solved

Simple Secure Contact Us Form Page Script

Posted on 2008-10-21
4
667 Views
Last Modified: 2013-11-19
Nearly everyone has a 'Contact Us' page on their site, right? Why is it so difficult to find a script that is simple, secure and unobtrusive (if using AJAX/JS) on the net?

I am looking for a ready to use script that displays a html form on the front end with the following inputs;

Name
Email
Subject
Message

User types in their stuff, some server side validation takes place and if it passes, an email is sent to me and a success message is displayed to the user.

Bonus if there is use of unobtrusive ajax, i.e. form validation error messages, message is sent and success statement displayed without page reload etc.

Please show me examples you know about that are simple, secure and work across browsers.  Thanks.

(site is hosted on windows server with php available)
0
Comment
Question by:thyros
4 Comments
 
LVL 8

Accepted Solution

by:
MatthiasVance earned 250 total points
ID: 22772134
I hope this helps you, I attached two files with some example code.

Kind regards,

Matthias Vance
<!-- This file is named form.php -->
<script language="JavaScript">
	var request;
	
	// This function is copied from http://cass-hacks.com/articles/code/js_url_encode_decode/
	function URLEncode(clearString) {
	  var output = '';
	  var x = 0;
	  clearString = clearString.toString();
	  var regex = /(^[a-zA-Z0-9_.]*)/;
	  while (x < clearString.length) {
		var match = regex.exec(clearString.substr(x));
		if (match != null && match.length > 1 && match[1] != '') {
			output += match[1];
		  x += match[1].length;
		} else {
		  if (clearString[x] == ' ')
			output += '+';
		  else {
			var charCode = clearString.charCodeAt(x);
			var hexVal = charCode.toString(16);
			output += '%' + ( hexVal.length < 2 ? '0' : '' ) + hexVal.toUpperCase();
		  }
		  x++;
		}
	  }
	  return output;
	}
 
	function checkForm() {
		// Prepare URL
		var url = "check_form.php?";
		url += "name=" + URLEncode(document.getElementById("name").value) + "&";
		url += "mail=" + URLEncode(document.getElementById("mail").value) + "&";
		url += "subject=" + URLEncode(document.getElementById("subject").value) + "&";
		url += "message=" + URLEncode(document.getElementById("message").value);
		alert(url);
		
		// Perform XmlHttpRequest
		request = null;
		if(window.XMLHttpRequest) {
			request = new XMLHttpRequest();
		} else if(window.ActiveXObject) {
			request = new ActiveXObject("Microsoft.XMLHTTP");
		}
		if(request != null) {
			request.onreadystatechange = function() {
				if(request.readyState == 4 && request.status == 200) {
					if(request.responseText == "OK") {
						alert("Your message has been sent!"); // Inform the user
						window.location = "http://localhost/test/form/"; // Redirect
					} else {
						document.getElementById("error").innerHTML = request.responseText;
					}
				} else {
					// There was a problem retrieving the data
				}
			}
			request.open("GET", url, true);
			request.send(null);
		} else {
			// This browser doesn't support the use of XmlHttpRequest
		}
	}
</script>
<form id="form" onsubmit="return false;">
	Name:<br /><input type="text" id="name" name="name" /><br />
	E-mail:<br /><input type="text" id="mail" ame="mail" /><br />
	Subject:<br /><input type="text" id="subject" name="subject" /><br />
	Message:<br /><textarea id="message" name="message"></textarea><br />
	<input type="submit" value="Send message" onClick="checkForm()"/>
</form>
<div id="error"></div>
 
<!-- This file is named check_form.php -->
<?php
	$error = "";
	$count = 0;
 
	$name = $_GET['name'];
	if(strlen($name) > 0) {
		$count++;
	} else {
		$error .= "You must supply a name.<br>";
	}
 
	$mail = $_GET['mail'];
	if(strpos($mail, "@")) {
		$count++;
	} else {
		$error .= "You must supply a valid mail address.<br>";
	}
 
	$subject = $_GET['subject'];
	if(strlen($subject) > 0) {
		$count++;
	} else {
		$error .= "You must supply a subject.<br>";
	}
 
	$message = $_GET['message'];
	if(strlen($message) > 0) {
		if(strlen($message) < 1024) {
			$count++;
		} else {
			$error .= "Your message must not exceed 1024 characters.<br>";
		}
	} else {
		$error .= "You must supply a message.<br>";
	}
 
	if($count == 4) {
		ini_set("sendmail_from", "WebMail"); // This may be needed
		mail("yourmail@yourdomain.com", $subject, $mail . "\n\r\n\r" . $message);
		echo "OK";
	} else {
		echo $error;
	}
?>

Open in new window

0
 
LVL 7

Assisted Solution

by:tg_wilk
tg_wilk earned 250 total points
ID: 22772699
Something based on similar principles. The main differences:
- object oriented (php)
- xml http request using post rather then get method - the advantage is that some browsers (IE for example) limit the length of a get request. This doesn't happen with post data.
- more thorough check of an email address

Description:
- contact.us.class.php - main engine
- contact.us.js - client part
- load.gif - animation
- index.php and contactus_backend.php show the example implementation.
Create a folder, copy all the files and start playing around. You'd want to change the e-mail address in contactus_backend.php for starters.
<-- index.php -->
 
 <html>
 	<head>
 		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
 		<script type="text/javascript" src="contact.us.js"></script>
 	</head>
 	<body>
 		<p>This is the simple contact us form. The page loaded on <?php echo date('Y-m-d H:i:s') ?> and
 		haven't reloaded since.</p>
 		<p>
 			<?php
 				include('contact.us.class.php');
 				$CU = new ContactUs('contactus_backend.php');
 				echo $CU->ContactForm();
 			?>
 		</p>
 	</body>
 </html>
 
 
 
 
<-- contactus_backend.php -->
 
<?php
include('contact.us.class.php');
 
$CU = new ContactUs("","UTF-8","email@to.send.to.com");
$CU->Process();
?>
 
 
 
<-- contact.us.class.php -->
 
<?php
class ContactUs {
	private $BackEnd;
	private $Charset;
	private $SendTo;
 
	public function __construct($BackEnd="",$Charset="UTF-8",$SendTo="your_email@yourdomain.com")
	{
		$this->BackEnd = $BackEnd;
		$this->Charset = $Charset;
		$this->SendTo = $SendTo;
	}
 
	public function ContactForm($BackEnd="")
	{
		if ($BackEnd != "") $this->BackEnd = $BackEnd;
		$result = '<div id="CUstatus"></div>
			<div id="CUdiv">
			<form name="CUform" method="POST">
			Name: <input type="text" name="CUname" value="" /><br />
			E-mail: <input type="text" name="CUemail" value="" /><br />
			Subject: <input type="text" name="CUsubject" value="" /><br />
			Message: <br /><textarea name="CUmessage"></textarea><br />
			<input type="button" name="CUsubmit" value="Submit" onclick="CUSubmit(\''.$this->BackEnd.'\');" />
		</form></div>';
		return $result;
	}
 
	public function Process()
	{
		if ($this->Validate())
		{
			header('Content-type: text/xml; charset='.$this->Charset);
			if ($this->SendContactInfo())
			{
				echo "<response>
					<status>ok</status>
				</response>";
			}
			else
			{
				echo "<response>
					<status>error</status>
					<error>There was an error while trying to send contact info. Please try again later.</error>
				</response>";
			}
		}
	}
 
	private function SendContactInfo()
	{
		$name = $_POST['name'];
		$email = $_POST['email'];
		$subject = str_replace("\n"," ",$_POST['subject']);
		$message = $_POST['message'];
 
		$charset=$this->Charset;
		$encoded_subject="=?$charset?B?".base64_encode($subject)."?=\n";
		$body = "Name: $name\nE-mail: $email\nSubject: $subject\nMessage:\n$message";
		$headers="From: ".$this->SendTo."\n"
		. "Content-Type: text/plain; charset=$charset; format=flowed\n"
		. "MIME-Version: 1.0\n"
		. "Content-Transfer-Encoding: 8bit\n"
		. "X-Mailer: PHP\n";
		//echo "here";flush();
		return mail($this->SendTo,$encoded_subject, $body,$headers);
	}
 
	private function Validate()
	{
		$name = isset($_POST['name'])?$_POST['name']:'';
		$email = isset($_POST['email'])?$_POST['email']:'';
		$subject = isset($_POST['subject'])?str_replace("\n"," ",$_POST['subject']):'';
		$message = isset($_POST['message'])?$_POST['message']:'';
 
		$error = '';
		if (strlen($name)<3) $error .= 'Name has to be at least 3 characters long. ';
		if (strlen($name)>256) $error .= 'Name has to be less then 256 characters long. ';
		if (!$this->ValidateEmail($email)) $error.= "Email $email is not valid. ";
		if (strlen($subject)<3) $error .= 'Subject has to be at least 3 characters long. ';
		if (strlen($subject)>256) $error .= 'Subject has to less then 256 characters long. ';
		if (strlen($message)<3) $error .= 'Message has to be at least 3 characters long. ';
		if (strlen($message)>2000) $error .= 'Message has to be less then 2000 characters long. ';
 
		if (!empty($error))
		{
			header('Content-type: text/xml; charset='.$this->Charset);
			echo "<response>
			<status>error</status>
			<error>$error</error>
			</response>";
			return false;
		}
		else return true;
	}
 
	private function ValidateEmail($email) {
		// First, we check that there's one @ symbol,
		// and that the lengths are right.
		if (!ereg("^[^@]{1,64}@[^@]{1,255}$", $email)) {
			// Email invalid because wrong number of characters
			// in one section or wrong number of @ symbols.
			return false;
		}
		// Split it into sections to make life easier
		$email_array = explode("@", $email);
		$local_array = explode(".", $email_array[0]);
		for ($i = 0; $i < sizeof($local_array); $i++) {
			if
			(!ereg("^(([A-Za-z0-9!#$%&'*+/=?^_`{|}~-][A-Za-z0-9!#$%&'*+/=?^_`{|}~\.-]{0,63})|(\"[^(\\|\")]{0,62}\"))$",
			$local_array[$i])) {
				return false;
			}
		}
		// Check if domain is IP. If not,
		// it should be valid domain name
		if (!ereg("^\[?[0-9\.]+\]?$", $email_array[1])) {
			$domain_array = explode(".", $email_array[1]);
			if (sizeof($domain_array) < 2) {
				return false; // Not enough parts to domain
			}
			for ($i = 0; $i < sizeof($domain_array); $i++) {
				if
				(!ereg("^(([A-Za-z0-9][A-Za-z0-9-]{0,61}[A-Za-z0-9])|([A-Za-z0-9]+))$",
				$domain_array[$i])) {
					return false;
				}
			}
		}
		return true;
	}
 
 
}
?>
 
 
 
 
<-- contact.us.js -->
 
var http;
 
//this function gets XMLHTTPRequest object independently from the browser 
function getXMLHTTPRequest() {
try {
	req = new XMLHttpRequest();
	} 
catch(err1) {
    try {
    	req = new ActiveXObject("Msxml2.XMLHTTP");
    	} 
    catch (err2) {
        try {
        	req = new ActiveXObject("Microsoft.XMLHTTP");
        	} 
        catch (err3) {
            req = false;
        	}
    	}
	}
return req;
} 
 
function urlencode(str) {
	return escape(str).replace('+', '%2B').replace('%20', '+').replace('*', '%2A').replace('/', '%2F').replace('@', '%40');
}
 
function CUHideForm()
{
	document.getElementById('CUdiv').style.display='none';
}
 
function CUSubmit(url)
{
	document.getElementById('CUstatus').innerHTML = '<img src="load.gif" /> Sending...';
	params = 'name='+urlencode(document.forms['CUform'].CUname.value);
	params += '&email='+urlencode(document.forms['CUform'].CUemail.value);
	params += '&subject='+urlencode(document.forms['CUform'].CUsubject.value);
	params += '&message='+urlencode(document.forms['CUform'].CUmessage.value);
	http = getXMLHTTPRequest();
	http.open("POST",url,true);
	http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
	http.setRequestHeader("Content-length", params.length);
	http.setRequestHeader("Connection", "close");
	http.onreadystatechange = CUStateChange;
	http.send(params);	
}
 
function CUStateChange()
{
	try
			{
	
			if (http.readyState == 4){
				if (http.status == 200)
				{
					if (http.responseXML)
					{
						var s = http.responseXML.getElementsByTagName('status');
						var status = s[0].firstChild.data;
            			if (status == 'error')
            			{
            				var e = http.responseXML.getElementsByTagName('error');
            				var err = e[0].firstChild.data;
            				document.getElementById('CUstatus').innerHTML = err;
            			}
            			else if (status == 'ok')
            			{
        					document.getElementById('CUstatus').innerHTML = 'Your contact info was succesfully sent.';
        					CUHideForm();
            			}
					}
				}
				else
				{
					document.getElementById('CUstatus').innerHTML = 'There was a http error: '+http.status;
				}
				
			}
			}
			catch (err)
			{
				document.getElementById('CUstatus').innerHTML = 'Unknown error occured.';
				
			}
}

Open in new window

load.gif
0
 

Author Comment

by:thyros
ID: 22775474
Thanks for your posts.  I will try to test these out and let you know how I get on.

I'd also like to mention that we are using the JQuery library on our site, in case that makes any difference.
0

Featured Post

Announcing the Most Valuable Experts of 2016

MVEs are more concerned with the satisfaction of those they help than with the considerable points they can earn. They are the types of people you feel privileged to call colleagues. Join us in honoring this amazing group of Experts.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

What is Node.js? Node.js is a server side scripting language much like PHP or ASP but is used to implement the complete package of HTTP webserver and application framework. The difference is that Node.js’s execution engine is asynchronous and event…
Nothing in an HTTP request can be trusted, including HTTP headers and form data.  A form token is a tool that can be used to guard against request forgeries (CSRF).  This article shows an improved approach to form tokens, making it more difficult to…
This tutorial will teach you the core code needed to finalize the addition of a watermark to your image. The viewer will use a small PHP class to learn and create a watermark.
Learn how to create flexible layouts using relative units in CSS.  New relative units added in CSS3 include vw(viewports width), vh(viewports height), vmin(minimum of viewports height and width), and vmax (maximum of viewports height and width).

791 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question