ITT #15: Create a Simple Contact Form

Get mail right through your site

Reach Out to Visitors with a Simple Contact Form

NOTE: This entry has been improved upon by adding spam protection and sessions. It's strongly recommended that you use the newer version of the simple contact form.

Making yourself accessible is one of the most important aspects of a site that aims to connect with its audience online, and nothing makes a person more accessible than an easy-to-use contact form.

In this week's Instant Tip Tuesday, we'll build a simple (less than 200 lines of code, including comments) contact form that will allow users to contact us without needing to open their mail client or copy and paste our email address into their web mail service. Our finished contact form will do the following:

  • Accept the user's name, email, URL, and a message
  • Verify that required fields were filled out
  • Validate the supplied email address
  • Send the user's message to an email address of our choice
  • Send the user a confirmation that their message was sent

View the Demo | Download the Files

Step 1 — The Message Form

Our first step is to generate the form so that our user can create their message. As we decided above, we want to accept the user's name, email address, website URL, and a message.

Because we're all savvy with HTML, we won't cover the "why" for the following code. The following is valid XHTML 1.0 Strict:


<h1> Simple Contact Form </h1>
<form action="inc/contact.inc.php" method="post" id="cf">
	<fieldset>
		<legend>Send a Message</legend>
		<label for="cf_n">Name (required)</label>
		<input id="cf_n" name="cf_n" type="text" maxlength="75" />
		<label for="cf_e">Email (required)</label>
		<input id="cf_e" name="cf_e" type="text" maxlength="150" />
		<label for="cf_w">Website (optional)</label>
		<input id="cf_w" name="cf_w" type="text" maxlength="150" />
		<label for="cf_m">Enter Your Message Here</label>
		<textarea id="cf_m" name="cf_m" rows="14" cols="45"></textarea>
		<input type="submit" name="submit" class="submit" value="Send" />
		<input type="submit" name="submit" class="submit" value="Cancel" />
	</fieldset>
</form>

We won't go into details on the styling of the form so that we can focus on the processing, but feel free to take a look at the CSS in the demo for a starting point.

Step 2 — Processing the Form

When the user submits the form, it sends the information via the POST method to the file inc/contact.inc.php. Our next step is to write the script that will process the input and send the message.

Validate the Data

Before sending any messages, we need to make sure that the user actually filled out the form and entered valid information. To do this, we first verify that the POST method was used to access the script and that the "Send" button was pressed to submit the form.

After that, we simply check that each form is not empty (and also not equal to the value of the field's label), then store the information in a variable. The email address is special, which we'll talk about in a minute.


<?php

/*
 * If the form was submitted and the "Send" button pressed, 
 * continue processing the data
 */
if($_SERVER['REQUEST_METHOD']=='POST' && $_POST['submit']=='Send')
{
	$err = NULL;

	// If the name field was filled out, sanitize the input and store it
	if(!empty($_POST['cf_n']) && $_POST['cf_n']!='Name (required)')
	{
		$name = htmlentities($_POST['cf_n'], ENT_QUOTES);
	}
	else
	{
		// If the name wasn't entered, create an error message
		$err .= "Please enter your name!<br />";
	}

	// If the email is set, validate and store it
	if(!empty($_POST['cf_e']) && $_POST['cf_e']!='Email (required)')
	{
		// Define a regex pattern to validate the email address
		$pattern = "/^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,3})$/i";
			if (preg_match($pattern, $_POST['cf_e']))
			{
				$email = $_POST['cf_e'];
			}

			else
			{
				// If the email doesn't match the pattern, error
				$err .= "Please enter a valid email address!<br />";
			}
	}

	// If no email was entered, generate an error message
	else
	{
		$err .= "Please enter a valid email address!<br />";
	}

	// Check the website field
	if(!empty($_POST['cf_w']) && $_POST['cf_w']!='Website (optional)')
	{
		$site = htmlentities($_POST['cf_w'], ENT_QUOTES);
	}
	else
	{
		// Because the website is optional, no error if empty
		$site = "none";
	}

	// Ensure a message was entered, then sanitize it
	if(!empty($_POST['cf_m']) && $_POST['cf_m']!='Enter Your Message Here')
	{
		$message = strip_tags($_POST['cf_m']);
	}

	// If no message was entered, adds an error message
	else
	{
		$err .= "Please enter a message!<br />";
	}

	// Process the sanitized and validated data
}

else
{
	/*
	 * If the wrong request method was used or the "Send" button
	 * wasn't pressed (i.e. "Cancel" was pressed), return the user
	 * to the contact form with no message.
	 */
	header("Location: ../");
	exit;
}

?>

As noted in the comments above, each submitted field is checked, then sanitized and saved in a variable.

If any of our required fields aren't properly filled out, we store a message in the variable $err. Note that we are appending messages to the variable rather than overwriting the variable. This way, we're able to tell the user every error that occurred, rather than just the last one.

The email check is performed by using a regex pattern, then matching the user input against the pattern using preg_match(). If a match is found, this means the email is valid, so we save it in a variable.

Process the Data

Now that we have our data stored, we're ready to start sending messages. First, we need to ensure that no errors occurred. Since the $err variable is NULL by default, we can check if it's set to catch any errors.

If an error occurred, we simply display the stored error messages and provide a link to try again. (NOTE: In a production environment, it would probably be a good idea to store the input in a session to prevent the user from needing to re-enter their message. This was left out in the interest of keeping this tip short and to-the-point.)

If no errors occurred, we place the supplied information into an email message and fire it off to the designated email address. Then, if the first message sent successfully, we send the user a confirmation email.

All of that functionality is accomplished with this code:


<?php

	// Validate and sanitize the input (see above)

	/*
	 * With the data sanitized, we need to check for errors to ensure
	 * that the message is valid before sending it
	 */
	if(isset($err))
	{
		echo '<h1> Oops! </h1>', $err, '<br /><a href="../">Try again!</a>';
		exit;
	}

	/*
	 * If no errors occurred, send the message
	 */
	else
	{
		$to = "Ennui Design <answers@ennuidesign.com>";
		$subject = "[Ennui Design] Message from the Ennui Design contact form";
		$headers = <<<MESSAGE_HEADER
From: $name <$email>
Content-Type: text/plain
MESSAGE_HEADER;
		$msg = <<<MESSAGE_BODY
Name:  $name
Email: $email
URL:   $site

Message:

$message

--
This message was sent via the contact form on EnnuiDesign.com
MESSAGE_BODY;
		if(!mail($to, $subject, $msg, $headers))
		{
			header("Location: ../?send=error");
			exit;
		}

		// Now send a confirmation email to the user.
		$conf_to  = "$name <$email>";
		$conf_sub = "Thank You for Contacting Us!";
		$conf_headers = <<<MESSAGE_HEADER
From: Ennui Design <donotreply@ennuidesign.com>
Content-Type: text/plain
MESSAGE_HEADER;
		$conf_message = <<<MESSAGE_BODY
Thank you for contacting us! Your message
was sent successfully, and we will get back
to you as quickly as possible.

All the Best,
Ennui Design

answers@ennuidesign.com
www.EnnuiDesign.com
MESSAGE_BODY;
		if(!mail($conf_to, $conf_sub, $conf_message, $conf_headers))
		{
			header("Location: ../?send=error");
			exit;
		}

		// Send the user back to the main page
		header('Location: ../?send=successful');
		exit;
	}

	// Remainder of script (see above)

?>

To send an email with PHP in plain text, all we have to do is put together a "to" address, a subject, the message itself, and the message headers (such as the content type and "from" address). With the message assembled, we simply run the mail() function and check that it fired successfully. If either call fails, we send the user back to the contact form with an error code in the URL to allow for a message to be displayed.

Make It Pretty

To add some client-side form validation, we'll implement the beautiful-forms.js script featured on Ennui Design a few months back. This is done by adding the following to the form HTML:


<script type="text/javascript" src="js/beautiful-forms.js"></script>
<script type="text/javascript">
	var formId = "cf";
	var reqFields = new Array('cf_n','cf_e','cf_m');
	if ( document.getElementById(formId) ) {
		prettyForms("cf", reqFields);
	}
</script>

For an explanation of how and why this works, read about JavaScript form validation with beautiful-forms.js.

View the Demo | Download the Files

Summary

This contact form is quick and dirty, but it will easily get you up and running with a new point of contact for your users. What do you use to make yourself accessible to users? How would you improve the contact form above? Let me know in the comments!

Posted May 12, 2009 by Jason Lengstorf.
This entry is filed under instant tip tuesday, email, and php.

Want more content like this? Subscribe for FREE!

Comments for This Entry

GravatarAnthony08:44PM on May 12, 2009

Hi Jason,
Another great post. Thanks! How well will this hold up against spam? I know little to none when it comes to php, so I have been using a pre-made php script called natemail for dreamweaver for a few years now and it is horrible for getting spam.

Gravatarnikolai03:59AM on May 13, 2009

1) no anti spam
2) if u made a mistake and return to form - all filled fields are empty again
3) this is lame. nowadays is not very efficient to create such things.
look at the frameworks...

GravatarJason Lengstorf08:38PM on May 13, 2009

@Anthony:
This won't hold up against spam at all. Adding a really simple anti-spam field wouldn't be too complex, but like nikolai said, there are plenty of existing scripts that exist that will already handle anti-spam for you.

If you find a good one, let me know which one it is!

GravatarDaquan Wright09:06PM on May 27, 2009

http://www.visual-blade.com/websites/justcomputers/contactus.php

I'm utilizing this form no that website, truly a great form. I'll adapt it for my own needs and use it to boost my knowledge of PHP and JavaScript.

Post a Comment

Want to show your face? Get a gravatar!

ALLOWED TAGS: <tt><strong><em>