http://www.dagondesign.com/articles/secure-php-form-mailer-script/
Installation
While this script is highly configurable, some of you may just want to
get up and running quickly with a simple (and secure) contact form. If so,
these are the minimum options you need to configure within the file:
Language Setting
$language - The relative path to the language
file you want to use.
Recipient Data
$recipients - If you are just
sending email to a single address, enter it here. For more advanced usage such
as multiple recipients, CC, BCC, etc.. more information is below
The other settings are optional, and are explained below.
This is a listing of the other configurable options in the script. These
are optional, but allow for much greater customization
Form Structure - This is where you
define the fields that will be used on this form. There are a lot of options
available for this, and they will be explained further down as well
Manual Form Code - This is a very
advanced option that has its own section on this page.
Wrap messages - This option wraps
message lines to 70 characters to comply with RFC specifications
Save attachments - If enabled, attached
files will be saved to a directory on the server instead of attached to the
email.
Save attachment path - Where files will be
saved, if attach_save is enabled. This is the full
path on the server, with a trailing slash. Directory must have write
permissions. Example: /home/user/public_html/uploads/
Show required - If enabled, required
fields will be marked with an asterisk
Show URL - If enabled, the URL the script is
running from will be added to the message
Show IP and Hostname - If enabled, the
visitor’s IP and hostname are added to the message
Special Fields - Sender name, Sender email, and Email subject - These options help generate the email headers. If you enter a field
name, it will be replaced by user input from that field. For example, if you
have a form field called fm_name and you use that as
the Sender name option, the visitor’s name will be used as the From field in
the email. You can also combine them. If you have a field called fm_firstname and fm_lastname you
could enter ‘fm_lastname, fm_firstname’
- For the Sender email option, just use your email field
Max upload size - This allows you to
set the maximum file size (in bytes) for attachment uploads. This option only
applies if the setting is lower than the value already set in your php.ini file
Message Structure - This feature is
optional. If left blank, the script will generate the email message itself,
which will include all the data the visitor submits. If you choose to use this
option, it will act as the message template. Simply enter your custom text,
including your field names. When the message is generated, the field names will
be replaced by the user input from those fields. Note: Since the script will
just do a search and replace for field names, be sure they are unique enough.
Example: A check for fm_message2 would also get triggered by fm_message when the script adds in the input.
Success Message - This is the text that
is shown after the email has been sent. You can also use field names in this,
and the user input from those fields will be used to generate the message.
Auto Reply - This is an optional
feature that allows you to automatically send a pre-defined message back to
those who contact you. More information on this is below
Image Verification Method - There are
three choices for image verification. It can be disabled, you can use the
script’s built-in system (a simple captcha - requires
GD support on the server), or you can use the ReCaptcha
system (requires signing up for a free account at recaptcha.net)
Basic Method Options - If using the basic
image verification method, you can choose the text and background color for the image (3 or 6 digit hex codes). By default,
the script will try and choose the best file format for the verification image,
but if it gives you any problems, you can manually specify the format to see
what works best for your server.
ReCaptcha
Method Options - If using the ReCaptcha
image verification method, you must enter the public and private keys given to
you at the ReCaptcha website. These are used to
generate the verification form, and the keys are specific to the website under
your account (meaning if you use this script on multiple sites, you need a set
of keys for each).
Save Data to File - When enabled, the
form input will be saved to a delimited file.
Still Send Email - When using the
delimited file feature, this option determines whether or not the script still
sends the email.
Data Path - The path to the file the data
will be written to - relative to the script’s directory. Be sure to give this
file write access.
Delimiter - Fields will be separated by this
character. If this character is found in the actual data, it will be removed
for simplicity.
Newlines - Newlines in input, such as text
areas, will be replaced by this, to keep the data on a single line in the file.
Timestamp - Adds the
date/time to the beginning of each line in your data file. This uses the PHP
date format. Leave blank to
disable.
With the exception of the text defined in the options, all text visible
to the visitor is contained within the language file.
Visual changes to the form can be made in the included CSS file. The
class names used in the examples below already exist within the CSS.
If you are using the standalone option, all you have to do is open the
URL to the script file in your browser.
If you are not using the standalone option, you can include the script
in your existing PHP file with the following code:
<?php include('dd-formmailer.php'); ?>
Be sure to use the relative path to the script file.
As mentioned above, if you want to send the messages to a single
recipient, just enter the email address in the recipients
option. To send to multiple recipients, separate the addresses with a |
(pipe) character, and use one of the following prefixes for each: to= cc=
bcc=
Examples:
to=user1@domain.com|to=user2@domain.com
to=user1@domain.com|cc=user2@domain.com
to=user1@domain.com|cc=user2@domain.com|bcc=user3@domain.com
You can have as many of each type (to, cc, bcc) as you like, and they
can be in any order, although the first one in the list is the always the
primary recipient, and must use to=
For those of you who want to let the vistor
choose the recipient from a drop-down box, first you must enter selrecip in the recipients
field. Then you must add a new line in the form structure box. Example:
type=selrecip|class=fmselect|label=Recipient|data=(select),
User1,user1@domain.com,User2,user2@domain.com
The type must be selrecip, but you can
use whatever you like as the CSS class, and label. The first item in the data
parameter is the default (unselected) option. After that are the names and
email addresses. You can add in as many as you like - just keep them in the
proper order (name,email,name,email,etc..).
Only the names are visible within the HTML for privacy reasons.
The ‘(select)’ item is the default selection, which the user must change
to submit the form. You can change the ‘(select)’ text if you choose.
This script uses a dynamic form generation system, which means that by
simply adding a new line to the form structure, you will have a new field in
your form. You can have as many fields as you like, and in any order. The only
field type that you must absolutely have is the verify field if you are
using the image verification option. All of the fields are explained below,
with examples. Separate each field type with a single newline in the form
structure option. (Some of the examples below are bit long, so they are wrapped
to the next line - be sure that the only newlines are after each field type
when adding them to your form structure.)
These are the different parameters that apply to most of the field types
(Special exceptions and parameters unique to a particular field are listed
under each field type):
TEXT
This is a standard text input field.
type=text|class=|label=|fieldname=|max=|[req=true]|[ver=]|[default=]
The text field type has a special parameter - ver
- which can be used to verify the input. You can choose email (which
checks that the input is a proper email address) or url (which checks that the input is not only a
proper URL, but that it actually exists). If you do not want to use either
validation option, do not add this parameter.
Examples:
type=text|class=fmtext|label=Name|fieldname=fm_name|max=100|req=true
type=text|class=fmtext|label=Age|fieldname=fm_age|max=100|
default=Enter your age!
type=text|class=fmtext|label=Email|fieldname=fm_email|max=100|req=true|
ver=email
type=text|class=fmtext|label=URL|fieldname=fm_url|max=100|ver=url
DATE
This is a javascript pop-up date chooser.
type=date|class=|label=|fieldname=|[req=true]
This field type generates a text box with a calendar icon next to it.
The user can enter a date manually, or click on the icon to see a small
calendar that they can choose a date from.
To change this image, just replace calendar.gif
in the script directory. Either give your file the
same name, or search and replace the name in the script file.
Example:
type=date|class=fmdate|label=Event Date|fieldname=fm_date|req=true
HTML
This field type lets you insert html, or other code, anywhere in your
form.
type=html|text=
Example:
type=html|text=<p>Hello!</p>
PASSWORD
This is a standard password field. It is exactly like a text field,
except it shows asterisks when the user types.
type=password|class=|label=|fieldname=|max=|[req=true]|[confirm=true]
The password field type also has a special parameter - confirm -
which if set to true, it duplicates the password field, so that the visitor has
to confirm their input. If you do not want to use this, do not add the confirm
parameter.
Examples:
type=password|class=fmtext|label=Password|fieldname=fm_pass|max=100|
req=true|confirm=true
type=password|class=fmtext|label=Secret Word|fieldname=fm_secret|max=100
TEXTAREA
This is a standard text area, for multiple lines of text.
type=textarea|class=|label=|fieldname=|max=|rows=|[req=true]|[default=]
The textarea field type has a special
parameter - rows which defines the number of
rows in the field (required for valid html).
Examples:
type=textarea|class=fmtextarea|label=Message|fieldname=fm_message|
max=1000|rows=6
type=textarea|class=fmtextarea|label=Message|fieldname=fm_message|max=1000|
rows=4|req=true
type=textarea|class=fmtextarea|label=Message|fieldname=fm_message|max=1000|
rows=10|req=true|default=Type here!
WIDETEXTAREA
This is exactly the same as the standard textarea,
except that it’s wider, and the label is above it instead of to the side.
type=widetextarea|class=|label=|fieldname=|max=|rows=|[req=true]|[default=]
Example:
type=widetextarea|class=fmtextwide|label=Message|fieldname=fm_message|
max=1000|rows=10|req=true
* Note that the normal textarea, and wide textarea fields use a different CSS class for formatting.
VERIFY
This field is required if you are using the basic verification
method. It does not apply if you are using the ReCaptcha
method. It is used for placement of the verification image (and associated text
box) in the form.
type=verify|class=|label=
Example:
type=verify|class=fmverify|label=Verify
FULLBLOCK and HALFBLOCK
These are not standard form fields, but simply a way you can add text to
your form. The full block is as wide as a wide textarea,
while the half block is aligned with other standard fields. You can use basic
HTML in your text if you like.
type=fullblock|class=|text=
type=halfblock|class=|text=
Examples:
type=fullblock|class=fmfullblock|text=This could be some sort of
introduction message.
type=halfblock|class=fmhalfblock|text=This could be used to
explain a field
in
greater depth.
OPENFIELDSET and CLOSEFIELDSET
These do just what the name implies - they open and close a fieldset in your form so you can help group fields
together. It also allows you to specify a legend for the fieldset
(required for valid HTML).
type=openfieldset|legend=
type=closefieldset
Examples:
type=openfieldset|legend=Your Information
(other field would go between
these)
type=closefieldset
CHECKBOX
The checkbox field can be used to generate a single checkbox, or a group
of them. The usage is a bit different than the other fields.
type=checkbox|class=|label=|data=
(fieldname),(text),(checked),(REQUIRED),
(fieldname),(text),(CHECKED),(REQUIRED)...
As you can see, the checkbox data is a comma separated list of four
items per checkbox:
*NOTE* Because
this field type uses commas to separate data, if you would like a comma to be
displayed in your data, simply use two. It will be replaced later in the code.
Examples
type=checkbox|class=fmcheck|label=I Agree|data=fm_agree,I agree to the
terms,false,true
type=checkbox|class=fmcheck|label=Interests|data=fm_i1,Computers,false,
false,fm_i2,Art,false,false,fm_i3,Music,false,false
RADIO
This field generates a group of radio buttons. Radio buttons are similar
to checkboxes, except that they are treated as a group, and only one option may
be selected.
type=radio|class=|label=|fieldname=|[req=true]|[default=]|data=(text),(text),
(text)...
The req and default items are
optional. req, if set
to true, makes the field required. default can
be set to the option number you want to be selected by default (starting at 1).
*NOTE* Because
this field type uses commas to separate data, if you would like a comma to be
displayed in your data, simply use two. It will be replaced later in the code.
Examples:
type=radio|class=fmradio|label=Gender|fieldname=fm_gender|data=Male,Female
type=radio|class=fmradio|label=Color|fieldname=fm_color|req=true|default=1|
data=Unspecified,Red,Green,Blue
SELECT
The select field generates either a standard drop-down box, or a
multi-select box, depending on the multi option. Option groups are
supported as well.
type=select|class=|label=|fieldname=|[multi=true]|[req=true]|data=(#group),
(text),(text),(#group),(text)...
The multi and req options are
optional.
If the field is required, the first option you have in the data paramater will be the default, which tells the user they
need to select one of the options. If they do not change the default option,
and it is required, they will receive an error.
The data field is just a list of the options, separated by a comma. To
define the start of an option group, just prefix the group name with a # as shown below.
*NOTE* Because
this field type uses commas to separate data, if you would like a comma to be
displayed in your data, simply use two. It will be replaced later in the code.
Examples:
type=select|class=fmselect|label=Age|fieldname=fm_age|req=true|
data=(select),0-30,31-60,61-90,91-120
type=select|class=fmselect|label=Colors|fieldname=fm_colors|
multi=true|req=true|data=(select),Red,Green,Blue
type=select|class=fmselect|label=Choose|fieldname=fm_choose|
data=#Category1,item1,item2,#Category2,item3,item4
FILE
The file field generates a file upload box. As with all other fields,
you can add as many of these as you like, as this script supports not only
attachments, but multiple attachments. The only thing to keep in mind is that
you may need to find out the limit your server has set for file upload sizes.
type=file|class=|label=|fieldname=|[req=true]|[allowed=1,2,3]
The allowed field is optional, and lets you define a (comma
separated) list of file extensions that are allowed to be uploaded. Otherwise,
all file types will be allowed.
Examples:
type=file|class=fmfile|label=Upload|fieldname=fm_upload
type=file|class=fmfile|label=Upload|fieldname=fm_upload|req=true|
allowed=jpg,jpeg,gif,png
This feature allows you to manually specify the code used to generate
your form. By default, this script uses the form structure information to dynamically
generate the form. While this makes it easier for most people, since they do
not have to write any code, it can limit those who need a bit more flexibility
in their form structure.
Important Notice: Because this method
means you will be writing the form code yourself, and it will not be generated
by the script, there is no way for it to automatically insert the PHP code
needed to put the user’s input back into the form when there is a validation
error. It is just not possible for this to be done automatically due to the
nature of the option. The only way this can be accomplished is if you know
enough about PHP to insert the code manually yourself. In other words, this is
a very advanced option - only for those who are very familiar with HTML forms
and PHP.
·
<!-- START of Dagon
Design Formmailer output -->
<!-- END of Dagon Design Formmailer output -->
You can also adjust the included CSS file to better fit your needs, or
completely clear it out and manually create an entire new CSS structure for
your task. Keep in mind that if you change any field items (or any options
which affect the form code generation), you will have
to repeat this process.
To disable the manual form code feature, just clear out the option for
it.
The options page for each instance includes fields to define an auto
reply message. This is a pre-defined message that is sent back to the visitor.
To use this option, simply enter the name, email address, subject line,
and message for your auto response. To disable this feature, just leave the
message field blank.
You can also use field names in the auto reply message, and the user
input from those fields will be used to generate the message.
This option allows you to save the form input in a delimited file.
Please see above for a full explanation of the options.
With the PHP version of this script, the path to the data file is
relative to the location of the script. Be sure to give this file write
access.
Redirect after form submission -
Method 1
It is possible to use Javascript to redirect
the user after the form has been filled out. While this method is not 100%
valid (Javascript redirection should go in the HEAD
section of the page), it works. To add this feature, first find the following
line in the script:
$o .= $sent_message;
And replace it with this:
$o .= '<script><!--
window.location= "http://www.mysite.com/"
//--></script>';
(where mysite.com is the URL you want to
redirect to)
Redirect after form submission -
Method 2
This is another method you can use to redirect the user after the form
has been submitted. First, find this line:
$o .= $sent_message;
And after it, add this:
$o .= '<
Where ‘4′ is the number of seconds to wait before refresh, and the
‘http://www.mysite.com/’ is the URL you want to
redirect to.
Passing values to the form
To allow values to be passed directly to the form, all you have to do is
change all references of $_POST to $_REQUEST (The REQUEST superglobal
contains the values of both POST and GET items)
Prevent form data from being
resubmitted upon refresh
This feature is included in the WordPress plugin version, but not in the PHP version, because of how
it has to be used. To enable the feature when using the script in standalone
mode, add the following code after the PHP declaration at the top of the
script:
if (count($_POST) >
0) {
$lastpost = isset($_COOKIE['lastpost']) ? $_COOKIE['lastpost'] : '';
if ($lastpost != md5(serialize($_POST))) {
setcookie('lastpost', md5(serialize($_POST)));
$_POST['_REPEATED']
= 0;
} else {
$_POST['_REPEATED']
= 1;
}
}
If you are not using the standalone option, you must add that
code at the very top of the PHP file you are calling the script from. Add PHP
tags around it if needed. Just make sure there is no extra whitespace around
the PHP tags.
Modifying the script to use HII for
image verification
Miro has posted
instructions for users wanting to use HII: Read the comment. Notice: Modifications listed in the comments may not apply for
new versions of the script.
Using SELRECIP and BCC together
The easiest way to do this, is to find the
following line in the script:
$send_status = mail($send_to, $email_subject, $msg, $headers);
If you are using SELRECIP, the message will be sent to whoever the
visitor chooses. If you would also like the message to go to someone else, no
matter who is chosen, just duplicate that line like so, adding in the address
of the secondary recipient:
$send_status = mail("user2@domain.com",
$email_subject, $msg,
$headers);
Fields not working properly/Form is
not displaying properly
As stated above, each field item needs to be on a single line in your
form structure. Many of the examples above are long, so they do not show up on
a single line. Be sure to remove any linebreaks when
adding them to your form. One form field statement per
line.
Verification image not showing up
The first thing to do is check to make sure your paths are set correctly
in the options.
This script automatically chooses the best file type to generate the
verification image. If your verification image is not displaying, the problem
could be that your server will not properly generate that type of file. You can
manually set this using the ‘Force image type’ option in the script. It allows
you to manually specify jpeg, gif, or png.
Try all the options to see which works best for you.
Problems sending email
The most common question I receive is ‘Why am I not receiving email from
the script?’
There are many reasons this can happen. The first thing to do is make
sure you have access to the PHP mail function on your web server, and that
there are no restrictions in place that might prevent certain features of this
script from working. If you are not sure, please ask your host for information.
Unfortunately, I am not able to spend the time troubleshooting general server
issues for everyone.
Also try having the script send the messages to another email address
(on another domain), just to be sure the problem is not with your email
account.
If you believe you can use the PHP mail function and have already tried
a different email address, create a small PHP file with the following contents
(be sure to use your own email address):
<?php
mail('you@domain.com', 'test subject', 'test message'); ?>
Open the file in your browser and then check your mail. If you did not
receive the message, something is not set properly on your server, and the
trouble is not with this script. Even if other mail scripts work for you, that
does not mean this one will, as there are several methods to send mail in PHP.
If you do receive the message, it most likely means that your
server is configured to not allow the use of the fourth parameter (extra
headers) in the mail() function. To work around this,
replace this line:
$send_status = mail($send_to, $email_subject, $msg, $headers);
With this:
$send_status = mail($send_to, $email_subject, $msg);
The only downside is that certain features (such as some header information, and the ability to send to multiple recipients)
will be disabled. You may be able to contact your host and have them change
this though. Many hosts add in this restriction for security reasons, to
protect against unsafe scripts.
Lastly, some servers require an extra parameter for the mail function
that specifies who the message is from. In many cases, this must be an email
address on the server itself. Example:
$send_status = mail($send_to, $email_subject, $msg, $headers", "-f user@domain.com");
‘Headers already sent’ error
Another common question is the ‘headers already sent’ error message.
Without getting into the details, this generally happens when something is
output to the browser before a call to set_cookie,
header, or a number of other PHP functions. Be sure there is no extra
whitespace at the top of your file.
Mail headers showing up in message
body / attachments not working
This issue can be caused if your server does not like the return/newline
character set being used to end lines of the email headers. If you are
experiencing this problem, try changing this line:
if (!defined('PHP_EOL')) define ('PHP_EOL', strtoupper(substr(PHP_OS,0,3) ==
'WIN') ? "\r\n" : "\n");
To this:
if (!defined('PHP_EOL')) define ('PHP_EOL', strtoupper(substr(PHP_OS,0,3) ==
'WIN') ? "\n" : "\n");
If you require special SMTP settings
for mail to be sent
If you have to manually specify the SMTP settings, you can do so with
the following code. This is only recommended for advanced users.
ini_set("SMTP","mail.MYDOMAIN.com");
ini_set("smtp_port","587");
ini_set("username","MYUSERNAME@MYDOMAIN.com");
ini_set("password","MYPASSWORD");
ini_set('sendmail_from',
$sender_email);
$send_status = mail($send_to, $email_subject, $msg, $headers);
ini_restore('sendmail_from');
(Just search for the reference to the mail()
function to see where to add it)
Conclusion
Please be sure to read the entire article before asking a question. I
spend a lot of time on the scripts and plugins
available on this site, and it can be hard to keep up with all the requests. If
you need modifications or a custom version, please contact me. Thanks for reading!