How to

install & configure

the free contact form

The following areas are covered in this guide:


Free Contact form installation overview

Our contact form is simple to set up. It's designed to work out of the box as much as possible with minimum effort. You only need to provide a few settings first.

The form needs PHP 8.2 or newer on your hosting. See the requirements guide if you're not sure which version you have.

This page covers most of the settings you should be aware of. Most of them you will never need to set or change, they're included for completeness.

The package has two folders. fcf-config is yours: your settings, field rules, email templates and colours. fcf-assets is the form's own code, which you leave alone. This makes upgrading easy, as you'll see at the end of this guide.


Quick set up guide

This is the quick set up guide which should work for you in most cases. However, you may need some of the other settings below if it doesn't work on your environment.

Step 1: Download and extract the free contact form package.

Step 2: In your hosting control panel, create an email account just for the form, for example [email protected]. In cPanel this is under Email Accounts. The form logs in to this account to send its messages, which is the most reliable way to get them delivered.

Using an email service such as SendGrid or Mailjet instead? Skip this step and see "Configuration - Email Transport" below.

Step 3: Open the file fcf-config/fcf.config.php in a code or plain text editor.

Step 4: Add your email address to the line below. This is the email address which the form submissions will be sent to.

define('EMAIL_TO', '');

If your email address is "[email protected]", then it should now look like this:

define('EMAIL_TO', '[email protected]');

Step 5: Add the details of the email account from step 2 to these three lines:

define('SMTP_HOST', '');
define('SMTP_USER', '');
define('SMTP_PASS', '');

The other email settings are already set for the usual case (port 465 with SMTPS), and the form sends from the email account you've entered.

Step 6: Copy the HTML code from fcf.form.htm to your contact page. You can clean-up some code first.

At the very top - remove

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

Keep the Style Sheets links (for example: <link href="fcf-assets/css/fcf.default.css" rel="stylesheet">).

Also remove.

<title>your title</title>
</head>

<body>

At the very bottom - remove

</body>
</html>

You can also move the JS and CSS code references to where you're other JS and CSS code references are. It's often best-practice to put the CSS references at the top of your page and the JS at the end.

Leave the small "spam trap" block in the form exactly as it is, and keep the "Contact Form by" link visible on the same page as the form, as set out in the licence.

Step 7: Upload all files (including the fcf-assets and fcf-config folders) to your website.

Congratulations, your form is now ready to use!

Please now test your form to make sure it's been configured correctly and is sending emails.

If you experience any problems, please double check all your settings. More settings are shown below.

If you continue to have issues, take a look at the section below, or the contact form troubleshooting page for help.


Messages not arriving?

Work through this short list:

  1. Check your spam folder at the address you set in EMAIL_TO.
  2. Check the server name. A message like "Connection timed out" almost always means SMTP_HOST is not the name of the server your site runs on. In cPanel, use the Server Name shown on the main page, not your domain name.
  3. Turn on SMTP_DEBUG. Set SMTP_DEBUG to 'YES' and send a test. The form then shows the whole conversation with the mail server, which usually shows the problem. Set it back to 'NO' afterwards.
  4. Use the self-test page. It checks your PHP version, your settings and your mail connection, and can send a test email. Turn it on by putting a random string of at least 16 characters in SELFTEST_TOKEN, then visit fcf-assets/fcf.selftest.php on your website. Clear the token again (or delete that file) when you've finished.
  5. Using Cloudflare or another CDN? After replacing files, clear its cache, or visitors can keep getting the old copies.
  6. Still stuck? The docs/DELIVERABILITY.md file in the download explains how to make sure your messages reach the inbox.

Many hosts also limit how many emails you can send per hour. The form has a setting to keep you under that limit, shown in the spam protection section below.


Getting to know the files

Contact Form file types

Here's a quick list of some of the important files which make up the contact form package.

In most cases, you only need to consider the configuration file. But more details are included if you are interested in learning more.

  1. fcf.form.htm - This is the free contact form.
  2. fcf-config/fcf.config.php - Configuration file (your settings)
  3. fcf-config/fcf.rules.js - Form validation rules (client-side)
  4. fcf-config/css/fcf.custom.css - Your colours
  5. fcf-config/email-templates/fcf.email-in.htm - Email templates
  6. fcf-assets/ - The form's own code and style sheet. You don't need to change anything in here
  7. fcf-assets/fcf.selftest.php - The self-test page (switched off until you set a token)

The contact forms HTML file

fcf.form.htm

The form code is made up of the four main sections:

  1. Reference to the style sheets
  2. The form
  3. The thank you message (hidden before the form is submitted)
  4. References to the JavaScript files
    <!-- 1: REFERENCE TO STYLE SHEETS -->
    <link href="fcf-assets/css/fcf.default.css" rel="stylesheet">
    <link href="fcf-config/css/fcf.custom.css" rel="stylesheet">
    ...
    <!-- 2: THE FORM -->
    <div id="fcf-form">
    ...
    <!-- 3: THANK YOU MESSAGE -->
    <div id="fcf-thank-you">
    ...
    <!-- 4: REFERENCES TO JAVASCRIPT FILES -->
    <script src="fcf-assets/js/lang/fcf.en.js"></script>
    <script src="fcf-assets/js/fcf.just-validate.min.js"></script>
    <script src="fcf-config/fcf.rules.js"></script>
    <script src="fcf-assets/js/fcf.form.js"></script>

Top Tip!

You may be interested in changing the message which is shown to your visitor after they submit the contact form.

This is the default code:

    <div id="fcf-thank-you" role="status" style="display:none">
    <!-- Thank you message goes below -->
    <p>Thanks for contacting us, we will get back in touch with you soon.</p>
    <!-- Thank you message goes above -->
    </div>

You can also have the form redirect to another page after submission. See the next section for details.

 


The contact forms configuration file

fcf-config/fcf.config.php

This is the most important part of setting up and running your form, so please read carefully.

As you can see from the file extension, this is a PHP file. This is used by your Server when processing the form submissions.

The file is split into the following sections:

  1. Form field validation
  2. Language
  3. Thank you page
  4. Email templates - incoming
  5. Email message
  6. Email transport
  7. DKIM signing (optional)
  8. Spam protection
  9. Logging
  10. Self-test

Let's go through each part.

Configuration - Form Field Validation

// *********************
// FORM FIELD VALIDATION
// *********************
$rules = array(
  "Name" => array(
    "required" => true,
    "label" => "Your name",
    "maxLength" => 60
  ),
  "Email" => array(
    "required" => true,
    "label" => "Your email address",
    "maxLength" => 100,
    "email" => true
  ),
  "Phone" => array(
    "required" => false,
    "label" => "Your phone number (optional)",
    "maxLength" => 30
  ),
  "Message" => array(
    "required" => true,
    "label" => "Your message",
    "maxLength" => 3000
  )
);

The purpose of the form field validation section is to set which fields on the form should be validated. This is pre-set, so you probably don't need to change it, unless you add or change fields (see adding or changing form fields).

It's also good to know that the form validation is already carried out in the browser prior to this. This is only a back-up in case your visitor has a browser issue that prevents the validation from functioning client-side.

Important: any field the form sends that is not listed here is ignored. It will not appear in your email.

Configuration - Language

// ********
// LANGUAGE
// ********
define('LANG', 'en');

This is the language of the messages shown to your visitor, such as "This field is required". English is included. If you add a translation file to fcf-assets/js/lang/ (named like fcf.fr.js), set the language here and change the matching <script src="fcf-assets/js/lang/fcf.en.js"> line in your form page. Anything missing from a translation falls back to English.

Configuration - Thank you page

// ******************
// THANK YOU PAGE
// ******************
define('THANK_YOU_PAGE','');

This is optional, the default behaviour of the form is to show a message on the same page as the form.

By adding a page here (for example define('THANK_YOU_PAGE','thankyou.htm');), you will enable this feature and your visitor is sent to that page after submitting.

Leaving this empty, as above, keeps the default behaviour.

Configuration - Email Templates Incoming

// **************************
// EMAIL TEMPLATES - INCOMING
// **************************
define('EMAIL_TEMPLATE_IN_HTML', 'fcf.email-in.htm');
define('EMAIL_TEMPLATE_IN_TEXT', 'fcf.email-in.txt');

Email Templates Incoming is referencing template files that are used to create the email sent to you after someone uses your form. You do not need to change anything directly here, however, if you want to change the format of your email, then take a look at the template .htm and .txt files in fcf-config/email-templates/.

Emails are sent as multipart HTML with a Text alternative. So, if you can't receive HTML emails for whatever reason, then the text version will be shown.

Because we're looking at the configuration file, We'll not explain how the email template works here. You can find out more about that later.

Configuration - Email Message

// *************
// EMAIL MESSAGE
// *************
define('EMAIL_TO', '');
define('EMAIL_TO_NAME', '');

define('EMAIL_TO_CC', '');
define('EMAIL_TO_CC_NAME', '');

define('EMAIL_TO_BCC', '');
define('EMAIL_TO_BCC_NAME', '');

define('EMAIL_FROM', '');
define('EMAIL_FROM_NAME', '');

define('EMAIL_REPLY_TO', 'FIELD:Email');
define('EMAIL_REPLY_TO_NAME', 'FIELD:Name');

define('EMAIL_SUBJECT_BEFORE', '');
define('EMAIL_SUBJECT', 'New Contact Form Message');
define('EMAIL_SUBJECT_AFTER', '');

Here's a grid with details of each field:

Setting Description
EMAIL_TO
Required
Email address where the form will be sent to. Several addresses can be separated by commas.
EMAIL_TO_NAME
Optional
Name part of the email.
EMAIL_TO_CC
Optional
Email CC address where the form will be sent to.
EMAIL_TO_CC_NAME
Optional
Name CC part of the email.
EMAIL_TO_BCC
Optional
Email BCC address where the form will be sent to.
EMAIL_TO_BCC_NAME
Optional
Name BCC part of the email.
EMAIL_FROM
Optional with SMTP
The address the message is sent from. This must be a real address on your own domain (or one verified with your email service). If you send through SMTP and leave this empty, the email account you log in with (SMTP_USER) is used, which is what most mail servers expect. It cannot be taken from the form: mail that claims to come from your visitor is rejected or sent to spam by Gmail, Outlook and others. Don't worry, the visitor's address is used as the Reply-To (below), so pressing "Reply" still goes to them.
EMAIL_FROM_NAME
Optional
Name part of the email, for example your website's name.
EMAIL_REPLY_TO
Optional
The address that is used when you reply to the message. The default, "FIELD:Email", uses the address entered into the form's Email field. Leave it empty if you don't want a Reply-To.
EMAIL_REPLY_TO_NAME
Optional
Name part of the email. The default, "FIELD:Name", uses the name entered into the form's Name field.
EMAIL_SUBJECT_BEFORE
Optional
Prepended to the subject line.
EMAIL_SUBJECT
The subject line from your email, for example: "Contact form message". You can also use a form field, for example 'FIELD:Subject' to show what your visitor chose in a "Subject" dropdown.
EMAIL_SUBJECT_AFTER
Optional
Appended to the subject line.

Configuration - Email Transport

// ***************
// EMAIL TRANSPORT
// ***************
define('USE_SMTP', 'YES');       // YES or NO
define('SMTP_HOST', '');         // server hostname (cPanel "Server Name"), not your domain
define('SMTP_PORT', '465');      // 465 with SMTPS, or 587 with STARTTLS
define('SMTP_SECURE', 'SMTPS');  // SMTPS, STARTTLS or empty
define('SMTP_AUTH', 'YES');      // YES if the server needs a username/password (almost always)
define('SMTP_USER', '');         // the full mailbox address
define('SMTP_PASS', '');
define('SMTP_TIMEOUT', 20);      // seconds to wait for the mail server
define('SMTP_DEBUG', 'NO');      // YES or NO

This is how the form sends your messages. For most people only the host, user and password need filling in (see the quick set up guide above), the rest is already set.

SMTP_AUTH should usually be set to YES. But if your SMTP server has authentication switched-off, then change this to NO.

The two settings SMTP_SECURE and SMTP_PORT work together. The most common settings are:

SMTPS with port 465, or STARTTLS with port 587.

Sometimes you may need to try different combinations to find the correct values for your environment.

If you're having issues getting your form to send emails, then set SMTP_DEBUG value to YES. This will show the whole conversation with the mail server in the form, which can help identify the issue. The most common issues are the host name, or the user, password and port number having the wrong values. Remember to set this back to NO before the form goes live.

Using an email service such as SendGrid or Mailjet? The form works with any SMTP service. Enter the server name, port, username and password your provider shows in its SMTP settings, and set EMAIL_FROM to a sender address you have verified with them. You need to set EMAIL_FROM yourself here because many providers use an API key as the username, not an email address.

Can't use SMTP at all? Set USE_SMTP to NO and PHP's built-in mail function is used instead. EMAIL_FROM must then be an address on a domain hosted with your hosting account. This works on some hosts, but it's less reliable: if the message is rejected later, the form still says it was sent. We recommend SMTP wherever you can.

Configuration - DKIM Signing (optional)

// *************************
// DKIM SIGNING (OPTIONAL)
// *************************
define('DKIM_PRIVATE_KEY_FILE', '');
define('DKIM_SELECTOR', '');
define('DKIM_DOMAIN', '');
define('DKIM_PASSPHRASE', '');

You can ignore this section. DKIM is a way of signing your email to prove it came from your domain. Your hosting account or email service normally does this for you. It's only here for the few people who send through a server which doesn't. The docs/DELIVERABILITY.md file in the download explains how it works. Leaving DKIM_PRIVATE_KEY_FILE empty keeps it switched off.

Configuration - Spam Protection

// ***************
// SPAM PROTECTION
// ***************
define('SPAM_MIN_SECONDS', 2);
define('RATE_LIMIT_MAX', 10);
define('RATE_LIMIT_WINDOW', 600);
define('SITE_LIMIT_MAX', 30);
define('SITE_LIMIT_WINDOW', 3600);

The form protects itself from spam bots without needing an account or any third-party service, using four things:

  1. A hidden field that bots fill in and people never see (the "spam trap" in the form, which you should leave as it is).
  2. A minimum time between the page loading and the form being sent (SPAM_MIN_SECONDS). Bots are usually faster than people.
  3. A limit on messages per visitor (RATE_LIMIT_MAX messages within RATE_LIMIT_WINDOW seconds).
  4. A limit for the whole website (SITE_LIMIT_MAX messages within SITE_LIMIT_WINDOW seconds). Many hosts limit how many emails you can send per hour (sometimes as low as 50) and switch your script off if you go over. Set this a little below your host's limit so a flood of spam can't use up your allowance.

Setting any of the maximum values to 0 switches that limit off.

If you use a CDN or proxy such as Cloudflare, every visitor can appear to have the same address. If real visitors see "Too many messages", set RATE_LIMIT_MAX to 0 and rely on the whole-website limit.

These settings stop the typical bots, but they're deliberately simple. They won't stop a determined person. There is no CAPTCHA to put your visitors through.

Configuration - Logging

// *******
// LOGGING
// *******
define('LOG_FILE', '');

If a message can't be sent, or there's a problem with your settings, a line is written to a log so you find out about it. No names, email addresses, messages or IP addresses are ever logged, only the time and the error.

Put a full server path to a file outside your website's public folder here, for example '/home/youruser/logs/contact-form.log'. Leaving it empty uses PHP's own error log instead.

Configuration - Self-test

// **********
// SELF-TEST
// **********
define('SELFTEST_TOKEN', '');

This switches on the self-test page, which checks your server and settings and can send a test email. It's off until you put a random string of at least 16 characters here. Then visit fcf-assets/fcf.selftest.php on your website and enter the same string. Clear it again (or delete fcf.selftest.php) when you've finished.


Adding or changing form fields

The form has Name, Email, Phone and Message by default. You can add your own fields, for example a "Website" field. A field must be listed in four places for everything to work. Miss one and it won't work properly.

  1. The form (fcf.form.htm or your page). Copy one of the existing field blocks and change the name, id and label. Keep the data-validate-field attribute and make it match the name.
  2. The server rules ($rules in fcf-config/fcf.config.php). Without an entry here, the field is ignored and never reaches your email.
  3. The browser rules (fcf-config/fcf.rules.js), so your visitor gets instant feedback. Keep it matching the server rules.
  4. The email templates (both the .htm and .txt files in fcf-config/email-templates/). Add {Website} where you want the value to appear.

For example, an optional "Website" field in the server rules:

  "Website" => array(
    "required" => false,
    "label" => "Your website link (optional)",
    "maxLength" => 200
  ),

A dropdown works the same way, and you can use its value in the subject line with 'FIELD:Subject' (see the email message table above). The server checks that a dropdown has a value and isn't too long, but it doesn't check the value is one of your options.


The contact forms rules file

fcf-config/fcf.rules.js

This is the part which sets the form validation done in the visitor's browser, before the form is submitted.

As mentioned above in the configuration section, the server checks again, so nobody can get around these rules. This file just gives the visitor instant feedback. Keep it in step with $rules in the configuration file.

var fcfRules = {
    "Name": {
        "required": true,
        "maxLength": 60
    },
    "Email": {
        "required": true,
        "maxLength": 100,
        "email": true
    },
    "Phone": {
        "required": false,
        "maxLength": 30
    },
    "Message": {
        "required": true,
        "maxLength": 3000
    }
};

In the above example, 4 fields have been included: Name, Email, Phone, and Message. Some of the fields are required and all have a maximum acceptable length set. The email field also states the validation type is 'email'. You can use the rules required, maxLength, minLength and email.

You never need to edit the other JavaScript files.


The contact forms CSS file

fcf-assets/css/fcf.default.css

The required styles for the form are included in this file. You don't need to change it.

fcf-config/css/fcf.custom.css

The core color settings are available in this file. If you want to edit the color theme of your form, this is the best place to do that. It's in your fcf-config folder, so it's kept when you upgrade.


The contact forms email templates

fcf-config/email-templates/fcf.email-in.htm

This file (along with the .txt version) is used to generate the email which is sent to you after each form submission.

Element like this one: {Name} will be replaced with the form field submitted value. {IP} is replaced with the visitor's IP address.

The form no longer sends an automatic reply to your visitor. This removes a common way for spammers to misuse contact forms.


Upgrading to a newer version

Your settings live in the fcf-config folder, and the form's own code lives in fcf-assets. To upgrade, replace the fcf-assets folder with the new one (delete the old one first so no stale files remain) and keep your fcf-config folder. Then check the change log in the download in case anything affects your form page.

If a new version needs a change to your settings file, the form will stop with a message that says so, rather than quietly behaving differently.