Secure & Accessible PHP Contact Form

Notice: There is now a more powerful stand-alone version 3 available. You might want to get it instead of this version. It’s better offering the same as this form and a lot more. Check it out.

This is the official page for my Secure and Accessible PHP Contact Form v.2.0. This easy-to-install form has many accessibility, usability, and security features over my old form that used to be offered on this page. The line between accessibility and security is a fine one. Hopefully I drew it well. (Want a copy of this for WordPress?) On this page you will find the following information:

Accessibility & Usability

I went to great lengths to make sure this form is as accessible and usable as possible. If you have suggestions to make it better, please let me know. As far as I know, though, for legitimate users, it just can’t get much better than this.

  1. Semantic mark-up, proper form elements, and proper alt- and label-input associations are all provided. From a standards-compliant and web accessibility point of view, this form is spot-on.
  2. Written to XHTML 1.0 Strict, but the form admin can change it to HTML 4.01 Strict by simply making one change in the configuration file.
  3. Features a #results fragment identifier on form submit, all error headings, and the success results heading. When the form is submitted it brings the user directly to the result itself, instead of bringing him or her to the top of the applicable results page. To visual browser users this is inconsequential, but for text browser and screen-reader users, or anyone using a keyboard to get around, this is a huge benefit.
  4. Logical groupings within fieldsets are provided. Additionally, all fieldsets are within a wrapper fieldset to better identify the form as a single working unit.
  5. Tabindexing is built in and can be modified by the form administrator. All values are set to zero by default which means they are already useful to Opera browser users. These values are added not only to the input fields, and also on specific form-related links.
  6. Form field focus is added by way of the basic CSS which is supplied with the form. Moreover, this focus is made available to IE users by way of some JavaScript functionality — since that browser lacks support by default. To counter styling difficulties, all inputs are classed and a couple of overriding inline styles are provided. This is the only use of JavaScript. The form itself relies completely on PHP so anybody can use it.
  7. Names and form instructions are meant to clear and simple to understand.
  8. Screen Reader Tested: Listen to the form demo page using the Jaws 8 screen reader. Hear it in Forms Mode or Virtual Cursor Mode. Recordings courtesy of Nick Fitzsimons.

| Menu |

Security Features

I went off the deep end on matters of security. While one feature, regardless of how good it may be, may suffice, two features are better, and have employed fourteen features to prevent abuse. Only one really requires the form user to do anything. Most anti-spam controls are passive and only targeted to stop remote machine posting and spam ‘bot abuse.

  1. Form submit email is hidden by PHP to keep it from being harvested by email harvesting ‘bots.
  2. Required fields are supplied to prevent meaningless submissions by abusive human users.
  3. Email structure is validated and sanitized. Full email validation isn’t provided to ensure fast processing.
  4. Pulldown menu (select) is required to make abusive repetitive form-use less convenient for human users. Legitimate users won’t be bothered by this.
  5. Markup and code is removed from all inputs by PHP using built in PHP functionality.
  6. All variables are sanitized or “scrubbed” and trimmed to prevent any form of malicious injection, blind carbon copies (bcc), script, etc.
  7. Inputs have the maxlength attribute, and this is also strictly enforced by PHP to mitigate circumvention by spam ‘bots.
  8. A simple anti-spam question must be answered correctly. Form admin can change this and examples are provided. For the admin and the user, the answer-data entered is case-insensitive for simplicity’s sake as is other match-require variable data. If the question can’t be answered by a legitimate user, a convenient option is provided so that user can still communicate.
  9. To prevent exploit distribution (if one is found), each form features a unique ID and will not submit if it doesn’t match the code submitted. This form ID code is unique for each form and each form user.
  10. The form features a type-hidden spam-trap field. Again, to prevent exploit distribution, it features an IDs unique to each form and each form user. The details of this trap will not be discussed here, but it’s specifically designed to passively mitigate spam ‘bot use.
  11. The form features a CSS-hidden spam-trap field, with available notation. The details of this trap will not be discussed here, but it’s specifically designed to passively mitigate spam ‘bot use.
  12. To prevent usage by spam ‘bots and yet again to prevent exploit distribution, the submit ID must be matched and has a value unique to each form and each form user. If problematic to a legitimate user (it shouldn’t be), a convenient option is provided so that user can still communicate.
  13. Pulldown (select) choices must be present in the array used to populate this value so one of the existing choices must be used. If not, an error is returned. This is yet another anti-spam ‘bot tool.
  14. The referrer must match and not be blocked to submit form. If it is blocked by a legitimate user, a convenient option is provided so that user can still communicate.
  15. Complete educated header and input injection exploit detector and killer ensures the form, if exploited, can’t be used for evil purposes or pose a threat to others.
  16. And if worst comes to worst and you have a human visitor that simply wants to make your life difficult, this form features an IP Blacklist function. This is a last resort option, but it is available.

| Menu |

The Form Files

The following files are provided with the download:

  1. gbcf_readme.txt - The installation and configuration instructions.
  2. gbcf_config.php - The form admin’s form configuration file.
  3. gbcf_form.php - The form body and script file — it should not need any editing.
  4. gbcf_focus.js - The form-focus script file for IE users.
  5. gbcf_styles.css - The form’s basic Cascading Style Sheet.

| Menu |

Form Installation

This form is simple to install and can be done in a matter of minutes. The following must be done:

  1. Unpack the *.zip file and extract the individual files.
  2. Using a text editor like Notepad, open the file named gbcf_config.php and complete at least section one of the configuration steps.
  3. Upload the files gbcf_config.php, gbcf_form.php, and gbcf_focus.js in a single “form-files-directory” on your server. Name the directory however you want.
  4. You can also place the gbcf_styles.css in the same directory, but you will likely just want to add the file’s contents to your own CSS file. It’s your call.
  5. Using the PHP include function, include the file gbcf_form.php in any *.php page file where you want it to be. It must be below the <body> tag and preferably below the main heading. I recommend placing it in the main content area. See Example 1, below.
  6. Place a JavaScript link within the <head></head> of the page. See Example 2, below. Place it in a conditional comment since it’s only needed for IE. You won’t need this unless your are providing form field focus (recommended).
  7. That’s it. Your done. At this point you will want to link to the style sheet if you’re not adding the elements, selectors, classes, and IDs to your own style sheet, modify the configuration file further if wanted, and of course test your new form. To link to the style sheet, please see Example 3, below.

 Example 1
  <?php include("form-files-directory/gbcf_form.php"); ?> 

 Example 2
  <!--[if IE]><script type="text/javascript" src="form-files-directory/gbcf_focus.js"></script><![endif]--> 
 Example 3
  <link rel="stylesheet" type="text/css" href="form-files-directory/gbcf_styles.css" media="screen" />
  Note: XHTML method shown, for HTML drop the slash at the end and close the gap. 

| Menu |

Form Configuration

This form’s admin configuration is broken down into eight sections to help clarify and simplify. Only one section is required, and default values are provided, but you might want to modify the other sections to suit your individual needs. The sections and variables are as follows:

  1. General form configuration:
    1. “Enter your email address” (what the form submits to).
    2. “Enter your name or company” (for the email greeting).
    3. “Set site/form possession” (this changes wording from “me” to “us,” my” to “our,” etc. This is for the main heading, error messages, etc.).
    4. “Enter website name” (or page name, company name, whatever).
    5. “Enter time offset if needed” (if server time varies from local) from "0"; for no change (default) to "+1"; plus one hour, "-1"; minus one hour, +/-2, plus/minus two hours, +/-3, plus/minus three hours, +/-4, plus/minus four hours, or whatever you need.
  2. “Contact Reason” menu: Use this to enter options for the pulldown (select) menu. Enter as many options you want, the form will adapt. Some common ones are provided.
  3. “Anti-Spam” q/a options: Use this to enter a simple question and answer. Suggestions are provided.
  4. Heading options:
    1. “Set heading size” (enter a numeric value, 1-6).
    2. “Enter your error heading” (what your errors say, set color to .error class in CSS).
    3. “Enter your success heading” (what your success result says, set color to .success class in CSS).
  5. Other config options menu:
    1. “Choose XHTML or HTML” (enter the form markup type needed for your site).
    2. “Enter your button text” (enter optional text for your “Submit Form” button).
    3. “Enter credit link option” (a simple yes or no determines if you want the link back to me to show… I hope you keep it as “yes” but it’s your call).
    4. “Enter privacy link option” (a simple yes or no… “yes” if you have a privacy policy. “no” if you don’t).
    5. “Enter privacy link url” (if you answered “yes” to above option, enter the absolute URL or relative path to that policy).
  6. Custom tabindex assignments: If you want to set tabindex values, use this section to do so. All are set to zero by default.
  7. IP Blacklist: If you have a need to block a certain IP address, you can enter it in this array. The array is structured for you but left blank by default. Use this only as a last resort and know that this is not effective against anyone who doesn’t have a static IP address. When you get emails sent to you, the user’s IP address is part of the data you will receive.
  8. Form location specification: This is done for you by way of a PHP code snippet, but if you have a problem with the form giving referrer mismatch errors during testing, it may be due to its location or in instances where you have custom URLs resulting from apache_mod_rewrite rules being in effect. If so, enter your absolute URL or relative path to the form page (shown in the nav bar on your browser) in place of the snippet used in the form_location variable.

| Menu |

Get Form Support

Use the Form Demo Page to request support or if you have any special customization requirements. Basic support is free as a courtesy to you — I will answer simple questions but it is requested that you first refer to the installation and configuration instructions to try and answer the question yourself. Advanced support requests and all customization work are for-hire services. Donations are always accepted if you find this form useful to you; use the Form Demo Page to get in touch. While comments remain open, you can also ask questions or give feedback in the dedicated announcement post.

| Menu |

Form Disclaimer

9 out 10 gurus will agree, but I’ll beat them to it and say it first: I’m not a PHP guru. Thus, while I have made this form to the best of my current abilities — which is a whole heck of a lot better than my version 1 — it is not perfect and may very well have some flaws so using it is at your own risk. I make no warranties, direct or implied. Do know, however, that it’ll be upgraded now and then, and will improve further over time. If you’re using it, you may want to check back here now and then to view the Change Log - Updates to see if version 2.0 improvements are available. I promise to try and make any changes in such a way that all you have to do as a user is drag-and-drop the form script file gbcf_form.php (which I recommend not editing yourself for this reason) to overwrite the existing file and implement the changes.

| Menu |

Change Log & Updates

If any errors are found or changes made, they will be logged here and summarized in brief. (From oldest to most recent.)

  1. 2006.10.04: Typo found and fixed on Line 28 of the gbcf_config.php file. Line should end with comma, not semi-colon. Affects first 7 downloads. Recommendation: Correct this yourself in the affected file by replacing character.
  2. 2006.10.04: Demo header and footer included in gbcf_form.php file. Oops. Header and footer removed. Affects downloads 8-15. Recommendation: Re-download *.zip and simply replace the affected file.
  3. 2006.10.04: Anti-Spam Trap 2 modified in gbcf_form.php file. Attribute type changed to text, but hidden by CSS. A notation was added to explain it those users not supporting or using CSS. Affects first 15 downloads. Recommendation: Re-download *.zip and simply replace the affected file.
  4. 2006.10.06: Exploit detector/killer added, functions clean-up performed, AOL-user modification made, and email validation improved/modified in gbcf_form.php file, and two styles sheet edits made in gbcf_styles.php file: div#gb_form_dv was changed to div#gb_form_div, and the main heading class was changed from .formhead to .main_formhead (.formhead still remains for error headings) for more user flexibility. Affects first 49 downloads. Recommendation: Re-download *.zip and simply replace the gbcf_form.php and make manual edits to those two CSS classes (if needed).
  5. 2006.10.16: Time offset variable added in gbcf_config.php file, in Section 1 of 8, and function added in gbcf_form.php file (and the gbcf_readme.txt was updated). This was updated to allow the ability to alter the date/time for those users whose server is not in their time zone. If you’re not concerned about this or your server is in your time zone, you have no need to worry about this, (but you may want to anyway just in case there are future upgrades available). Affects first 127 downloads. Recommendation: Read more about your four options.
  6. 2006.10.23: I updated the gbcf_focus.js file. There was a comment in the file that was preventing the script from running thus offering no form field focus in IE6. I replaced the file. Affects first 171 downloads. Recommendation: Replace the file if you offer form field focus and care that it works in IE6. Otherwise, do nothing.
  7. 2006.10.23: I updated the gbcf_styles.css file. I added hacks just for IE6 to keep button stable. I replaced the file. Affects first 174 downloads. Recommendation: Add the hacks in the new file to your file and modify them if you offer form field focus and care that it works in IE6. Otherwise, do nothing.
  8. 2006.10.26: I updated the gbcf_form.php file. The problem was referrer mis-matching if the form admin set the URL manually with/without a WWW and the form user accessed the form page in an opposite manner. If you’re using the default $form_location code snippet don’t worry about this, but if you set it manually and users can access your form with/without the WWW in the URL you’ll want/need to address this. Affects first 222 downloads. Recommendation: If applicable to you, as described, swap out the gbcf_form.php and the problem is solved.
  9. 2006.11.01: I updated the gbcf_form.php and gbcf_config.php files. The basic changes I made to the form file now allows admins to now enable or disable the Carbon Copy function, the carbon copy email sent to users was modified extensively and is a separate mail, an identified auto-fill user bug was fixed (Spam Trap 2 was being populated), and the referrer match-up was changed significantly as that was giving people problems. The config file was changed to add the carbon copy selection (line in config section 1), and I also added an include security function (line at very top of file). Affects first 343 downloads. Recommendation: Swap out the two files mentioned and reconfigure OR swap out the form file and add the two added lines to the config file. That’s it.
  10. 2006.11.05: Minor tweaks made to the gbcf_form.php file to make it look nicer in the source. Also made one tweak to mitigate the possibility of an “open relay attack” being carried out. Affects first 417 downloads. Recommendation: Swap out the gbcf_form.php file.
  11. 2006.11.25: Success message typo corrected in the gbcf_form.php file. Affects first 779 downloads. Recommendation: Swap out the gbcf_form.php file.
  12. 2007.01.20: Minor tweaks made to the gbcf_form.php to negotiate IP addresses differently, changed character set to UTF-8 to allow more characters in emails, fixed a typo, and changed the “from” to the sender to allow use with host that require SMTP authentication. Affects first 1728 downloads. Recommendation: Swap out the gbcf_form.php file.
  13. 2007.02.03: Minor tweaks made to the gbcf_form.php to plug a possible header injection exploit hole, general tweaks and mods. Ordering of gbcf_config.php file made. Affects first 1999 downloads. Recommendation: Swap out the gbcf_form.php file only.
  14. 2007.02.13: A modification was made to the gbcf_form.php file to update the header injection exploit error message. Affects first 2211 downloads. Recommendation: Swap out the gbcf_form.php file.
  15. 2007.03.03: The ordering of the negotiations was modified in the gbcf_form.php file for even greater email security. Affects first 2680 downloads. Recommendation: Swap out the gbcf_form.php.
  16. 2007.03.29: In the gbcf_form.php file the blockquote’s cite attribute in the success result was changed, the “Referrer Mismatch” error was modified, the random exploit distribution codes were changed, and mail function detection was added to help users determine if they can use the form. The readme file was also updated. Affects first 3413 downloads. Recommendation: Swap out the gbcf_form.php file.
  17. 2007.04.03: In the gbcf_form.php there was a really stupid validation error — I should have checked. I didn’t properly close the main form heading. Affects downloads 3413 through 3509. Recommendation: Swap out the gbcf_form.php file. Sorry.
  18. 2007.04.07: I made several changes in the gbcf_form.php mostly to further enhance security, small tweaks. Affects the first 3641 downloads. Recommendation: Swap out the gbcf_form.php file.
  19. 2007.04.14: Due to threats from a disgruntled user I have removed all link-backs in the gbcf_form.php file if Showcredit “No” is selected in the config. Affects first 3863 downloads. Recommendation: Swap out the gbcf_form.php file. This was never meant to dupe or spam anyone. It was used purely for software promotion and innocuous tracking.
  20. 2008.02.07: I moved the labels, reduced their length, spanned the legends, added 3D to make a working Whois query input. Most changes were for greater accessibility. Affects first 13652 downloads. Recommendation: Swap out the gbcf_form.php file.
  21. 2008.07.31: I shortened the variable lengths due to some server issues some people encountered. I also remove the negative top margin from the hidden input (better for tabbing to use left only). Affects first 17284 downloads. Recommendation: Swap out the gbcf_form.php file.
  22. 2008.11.18: I added the -f parameter to help those with requiring email providers such as AOL. Affects first 19476 downloads. Recommendation: Swap out the gbcf_form.php file.

| Menu |

Form Customizations

Fee-based form customizations are available. This service might include the addition or removal of user inputs, etc. To learn more or to ask for quote request, please contact me.

| Menu |

Download the Form

Terms of Use: You are free to download and use this form but you may not redistribute it without written permission. Donations are gratefully accepted but no payment is required to use this script. If you do use this form whether on your site or a client’s site, it is requested that you keep the built in link-back in place but it is no longer required by these terms.

To date, this “Secure and Accessible PHP Contact Form v.2.0″ has been downloaded 35111 times since its release on: Oct. 3rd, 2006.

| Menu |

Credits & Thanks

The following people or groups helped me with this form in some way, whether it be giving me a simple but brilliant idea, lending a little scripting support, providing answers by way of documentation, testing the completed form, or in some cases just trying to help. I offer them my gratitude whether their ideas were put to use or not: Joe Dolson, Jonathan Fenocchi, Stephan Segraves, Tommy Olsson, Harmen Janssen, Mel Pedley, Jemma Turner, Adam Messinger, andrabr, Jon Gibbins, Pierre Far, Karen Mardahl, some of the folks at Site Point (most notably “clamcrusher”), and, of course,

| Content Top |

Note: This is the end of the usable page. The image(s) below are preloaded for performance only.