Generating Valid HTML Email Contact Form Using PHP and JavaScript

By Jeffrey McArthur

One of the most popular PHP scripts is an email contact form. There are many different PHP scripts available. One of the easier to use is the script from www.stargeek.com. The script is simple to install and understand. The URL for the original script from www.stargeek.com is located here: http://www.stargeek.com/php_scripts.php?script=12

However, there is a problem with almost all the PHP scripts for an email contact form. None of the scripts generated valid HTML by the standards of the W3C. JSM Software is committed to total quality management, or TQM. This commitment includes the small details of creating a PHP script for an email contact form that produces valid HTML.

There is also a subtle issue with the code from www.stargeek.com. The code uses a table to format the layout of the input form. This is valid HTML. However, if the main HTML page (or template) uses a table then the input form implementation would require a nested table. This works with most browsers, but is more complicated than needed.

This white paper discusses how to implement a PHP script for an email contact form that generates valid HTML code without using tables. JSM Software's website uses the strict version of HTML 4.01. JSM Software validated the pages using the service provided by the W3C at: http://validator.w3.org. One common problem with many PHP scripts is they leave out the required DOCTYPE declaration. The strict HTML 4.01 DOCTYPE declaration looks like this:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
            "http://www.w3.org/TR/html4/strict.dtd"> 

The first line of the HTML file must be the DOCTYPE declaration. PHP passes the DOCTYPE declaration through unchanged. Therefore, as part of the best practices, the DOCTYPE declaration should be the first line of all PHP pages.

Another requirement of the W3C is that all HTML files specify the character encoding. The <meta> tag included in the head of the HTML page specifies the character encoding. One standard encoding is iso-8859-1. This encoding matches the Latin-1 encoding common to most PC's in the United States. Below is the HTML to specify iso-8859-1 character encoding:

<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">

The first step in using the script is to determine the path to the email program. For most RedHat Linux installations, the code to initialize a variable pointing to the email path looks like this:

$mail_path = "/usr/sbin/sendmail -i -t";

An email message has several parts: the address of the sender of the email, the address of the recipient of the email, the subject of the email, and the body of the email message. The script uses variables to store each piece of the email. The script uses a variable to store the address of the recipient of the email. The code to set the local variable is below:

//The email address to be receiving emails from this form
$mail_to = "info@jsm-software.com";

The next variable is the subject of the email.

//the subject of the email sent by the form
$mail_subject = "Contact Form"; 

JSM Software uses special formatting for all references to the company name. The HTML <span> tag provides the style to implement this. The code below sets the name of the business used in the contact form. Notice that embedded HTML tags can be included:

//the name of the buisness or website that the form contacts
$buisness_name = '<span class="jsmsoft">JSM Software</span>';

The most significant deviation from the code provided by www.stargeek.com is the coding of the actual HTML form. The input form is implemented using <div> and <span> instead of a table. This provides freedom for the web site designer to use tables to layout the form. Below is the code:

$form_html = '$html = "
<h1>To Contact $buisness_name:</h1>
<form name=\"contactForm\" action=\"$PHP_SELF\" method=\"POST\">
    <div>
        <div style=\"width: 20ex; float: left\">Your Name:</div>
        $name
    </div>
    <div>
        <div style=\"width: 20ex; float: left\">Your Email Address:</div>
        $reply
    </div>
    <div style=\"text-align: center\">
        <span>Your Message</span>
    </div>
    <div>
        <span>$message </span>
    </div>
    <div style=\"text-align: center\">
        <span>$send </span>
    </div>
</form>
";';

The PHP function ini_set allows programs to set the value of a configuration option. The use of the mail function requires setting the path to the mail program and the sender of the email. The code below uses ini_set to set the required path parameters using the variable that was set above:

ini_set("sendmail_path", $mail_path);

PHP provides a variable that is automatically global in any context: $_POST. The $_POST variable is an associative array of variables passed to the current script via the HTTP POST method. Testing the value of the $_POST variable provides a mechanism for the code to know if the user has submitted the form. The code from www.stargeek.com used a simple test:

if ($_POST)
. Although the code works, it makes assumptions about the type conversions in PHP. A slightly more wordy, but easier to understand test is:
if (!empty($_POST))
. The program executes code for both the empty and non-empty situation. One obvious optimization is to remove the not operator "!", and rearrange the code so that the test can be just:

if (empty($_POST)). 
When $_POST is empty, the code sets the variables for $message, $name, $reply, and $send used in the input form. Below is the code fragment of the first part of the statement:

if (empty($_POST))
{
    $message = '<textarea name="userMessage" rows="20" cols="70"></textarea>';
    $name = '<input onBlur="CheckName(document.contactForm.userName.value)" type="text" name="userName" size="30">';
    $reply = '<input onBlur="CheckEmail(document.contactForm.userEmail.value)" type="text" name="userEmail" size="30">';
    $send = '<input onClick="return ValidateAll()" type="submit" name="submit" value="Send">';

    eval($form_html);
}

Rearranging the order of the testing allows simplification of the control logic. The code rearrangement removes one layer of nested if statements by using an elseif. The situation where $_POST is empty is handled by the first clause. The second clause checks to see if the user email address is set. The code sets two local variables constructing the values from the data provided. Then the code calls the mail function with the local variables as parameters. Below is the second clause:

elseif(isset($_POST['userEmail']))
{
    $mail_message = "\t From: "
        . $_POST['userName']
        . "\n \t Email: "
        . $_POST['userEmail']
        . "\n\n"
        . stripslashes($_POST['userMessage'])
        . "\r\n"
        . "From: $_POST[userEmail]\r\n"
        . "Reply-To: $_POST[userEmail]\r\n";

    $mail_headers = "From: "
        . $_POST[userEmail]
        . "\r\n"
        . "Reply-To: "
        . $_POST[userEmail]
        . "\r\n";

    if(mail($mail_to, $mail_subject, $mail_message, $mail_headers))
    {
        $html  = '<p>Thank you for contacting '
                 . $buisness_name
                 . ', '
                 . $_POST['userName']
                 . '. </p>';
    }
    else
    {
        $html = '<p>There was an error</p>';
    }
}

JavaScript provides client side validation of data prior to submitting the data. The website http://willmaster.com provides a set of validation tools to simplify the task. The only problem is using the tools as provided produces a web page that will not validate. The problem is the <script> wrapper around the JavaScript functions. The W3C deprecated the script language attribute and it is not part of the strict DTD. The proper way to specify the language is to use the type attribute. Below is the modified code.

<script type="text/javascript">
<!-- 
function ValidateAll()
{
    if(CheckName(document.contactForm.userName.value) == false) return false;
    if(CheckEmail(document.contactForm.userEmail.value) == false) return false;
    return true;
}

function StripSpacesFromEnds(s)
{
    // developed by willmaster.com
    while((s.indexOf(' ',0) == 0) && (s.length > 1))
    {
        s = s.substring(1,s.length);
    }
    while((s.lastIndexOf(' ') == (s.length - 1) && (s.length > 1)))
    {
        s = s.substring(0,(s.length - 1));
    }
    if((s.indexOf(' ',0) == 0) && (s.length == 1)) s = '';
    return s;
}

function IsItPresent(s,explanation)
{
    // developed by willmaster.com
    s = StripSpacesFromEnds(s);
    if(s.length) return s;
    alert('Please enter ' + explanation + '.');
    return '';
}

function CheckName(s_name)
{
    // developed by willmaster.com
    s_name = IsItPresent(s_name,'your name');
    if(! s_name) return false;
    var i = s_name.indexOf('  ',0);
    while(i > -1)
    {
        s_name = s_name.substring(0,(i + 1)) + 
            s_name.substring((i + 2),s_name.length);
        i = s_name.indexOf('  ',0);
    }
    s_name = s_name.toLowerCase();
    var s = new String(s_name.substring(0,1));
    s = s.toUpperCase();
    s_name = s + s_name.substring(1,s_name.length);
    i = s_name.indexOf(' ',0);
    if(i == (s_name.length - 1)) i = -1;
    var ts = new String("");
    var j = 0;
    while(i > -1)
    {
        i++;
        j = i + 1;
        s = s_name.substring(i,j);
        s = s.toUpperCase();
        ts = '';
        if(i > 0) ts = s_name.substring(0,i);
        s_name = ts + s + s_name.substring(j,s_name.length);
        i = s_name.indexOf(' ',j);
        if(i == (s_name.length - 1)) i = -1;
    }
    document.contactForm.name.value = s_name;
    return true;
}

function CheckEmail(s_email)
{
    // developed by willmaster.com
    s_email = IsItPresent(s_email,'your email address');
    if(! s_email) return false;
    var i = s_email.indexOf(' ',0);
    while(i > -1)
    {
        s_email = s_email.substring(0,i) + 
            s_email.substring((i + 1),s_email.length);
        i = s_email.indexOf(' ',0);
    }
    document.contactForm.email.value = s_email;
    if((s_email.length < 6) ||
       (s_email.indexOf('@',0) < 1) ||
       (s_email.lastIndexOf('@') != s_email.indexOf('@',0)) ||
       (s_email.lastIndexOf('@') > (s_email.length - 5)) ||
       (s_email.lastIndexOf('.') > (s_email.length - 3)) ||
       (s_email.lastIndexOf('.') < (s_email.length - 4)) ||
       (s_email.indexOf('..',0) > -1) ||
       (s_email.indexOf('@.',0) > -1) ||
       (s_email.indexOf('.@',0) > -1) ||
       (s_email.indexOf(',',0) > -1))
    {
        alert('The email address "' + s_email + '" is not valid.');
        return false;
    }
    return true;
}
// -->
</script>

In conclusion, it is possible to generate valid html web pages using PHP that use JavaScript. The process requires careful consideration and research to ensure that the resulting page is valid.

The author, Jeffrey McArthur, is President of JSM Software, a company focused on affordable business intelligence solution using Microsoft SQL Server. You can reach Jeffrey at jeffmcarthur@jsm-software.com. For more information on JSM Software, please see http://www.jsm-software.com or contact the sales department at 1-410-290-6958.

White Papers Calculating Deciles Valid PHP Email Form Database Frequency Time Management Using Excel Y2K Problems Still Haunt Us
Windows Mobile 6.5