Back to: CGI Scripts and Programs Contents and Introduction

mailform User guide

A generic Web form handler utility.
Introduction
How it works. and a simple example
Supported INPUT fields
Syntax of mailform commands
Special characters
Variables
Delivery Methods
Reply URL
CGI environment variables
Mingling with Javascript

Abstract.

The mailform script (1.0.0 release - 1st December 1997) is written in Perl 5.003 as an update to the older C-coded gform one. It supports almost all the older features and also intoduces some new ones. All the new will be explained in detail en route.

Introduction.

The problem with forms is that they all need their own program or script to handle the fields in the form and perform some sort of action. This can make the creation of simple questionaire type forms difficult for web information providers. Usually you want to collect submitted forms of this type in a file or send it via email to yourself or to someone else.

mailform is a program that enables you to easily create these type of forms by using commands that are embedded inside the form HTML file. It then uses simple variable substitution to deliver the results.

How it works.

The HTML specification says that comments in a HTML file should be enclosed by '<!--' and '-->'. Mailform takes advantage of that and will interpret the tag '<!--mailform ' as the start of a command. (The program will identify the older syntax '<!--gform ' as well - which was maintained for compatibility purposes). These tags are considered to be comments by the HTML browsers. These mailform 'comment' tags can appear anywhere within the form HTML file.

Take a simple form example:

<html>
<title>A Simple Form</title>
<body>
<form method=POST action="/cgi-bin/handler">
Enter your name:<INPUT type="text" name="yourname"><br>
<INPUT type="submit" value="submit">
</form>
</body>
</html>

To handle this form, you need a script or program to interpret the input value(s) for you. In this case this is specified as '/cgi-bin/handler'. If you add input fields to this form you typically will also need to modify '/cgi-bin/handler'. Having one script or program for each form is obviously very cumbersome to maintain. More often than not, the person who writes the form is not a programmer and may find it difficult to write form handlers.

Here is the same example with 'mailform' as the 'handler'

<html>
<title>A Simple Form</title>
<body>
<form method=POST action="/cgi-bin/mailform">
Enter your name:<INPUT type="text" name="yourname"><br>
<INPUT type="submit" value="submit">
</form>
</body>
<!--mailform "The persons name is: $(yourname)\n"-->
<!--mailform deliver=mail "nobody@swin.edu.au"-->
</html>

(The mailform commands will be explained later) 

When somebody submits this form and gave their name as "Joe Bloggs", then the following line is sent to:
"nobody@swin.edu.au"

The persons name is: Joe Bloggs
You can easily add more INPUT tags and mailform tags without having to change 'mailform' itself.

Supported INPUT fields.

All the INPUT type tags defined in HTML v2.0 can be used.

Syntax of mailform commands.

The mailform script uses the same syntax as the older gform one apart from the "file" facility which is not supported in this release. Also some extra feature have been added. More specifically:

The are 3 types of mailform commands. The first handles text and variables, the second defines a delivery method. and the third is an optional reply URL that is send to the user after they submit the form.

The syntax can be summarized as:

<!--<mailform|gform> <"text|$(var)">|<[reply="URL "]>|<deliver=mail "address_txt|$(var)" [subject= "subject_txt|$(var)"] [from="from_txt|$(var)"]>-->

Where;

Special Characters

Within mailform text strings there would be no way to handle certain characters because they either have special meaning to mailform or they simply can't be entered from the keyboard. To handle these characters we precede certain letters with a backslash character.

Here is the list of escaped characters with special meaning within mailform text.

\n - newline
\t - tab
\f - form feed
\r - return
\$ - Escape a dollar sign
\" - Escape a double quote
\\ - Escape a slash
The most useful one is the Newline character. For example take the next 2 lines;
<!--mailform "The quick brown fox"-->
<!--mailform "jumped over the lazy dogs"-->
This will be returned as: "The quick brown foxjumped over the lazy dogs"

But by inserting newline characters,

<!--mailform "The quick brown fox\n"-->
<!--mailform "jumped over the lazy dogs\n"-->
we get
"The quick brown fox
jumped over the lazy dogs"

Variables

Variables are identified by a '$" sign and must be enclosed with parentheses ( ). Note that NO space is allowed between the dollar sign and the first parentheses. A variable should match with the name given in the input specification. In this release no CGI Enviroment variables are supported.

For example a typical line in a form maybe:

Enter your name:<INPUT TYPE="text" name="myvar">
The Variable name is given by 'name' and is called 'myvar'.
The corresponding mailform line could look something like;
<!--mailform "The persons name is: $(myvar)\n"-->
$(myvar) is then replaced by what the form user entered and the result is delivered according to the given delivery method(s).

There are 2 special variables that are always defined. $(date) and $(time) that return the current date and time.

Delivery methods.

There is at the current time only one way you can get the information from a submitted form and this is by email. To get the results send to you via email you use
<!--mailform deliver=mail "address@some.site.edu"-->
The "<!--mailform " lines with the text and variables you have specified, will be send to "address@some.site.edu" via email. The variables of course will contain the entered values.

You can optionally also include a subject

<!--mailform deliver=mail "address@some.site.edu" subject="Form x submission"-->
and also a from: field is also supported
<!--mailform deliver=mail "address@some.site.edu" from="address@senders.site"-->
Instead of inserting the addresses and the subject title in text form you could also insert appropriate variables, defined in the form like:
<!--mailform deliver=mail "$(email_addr)" subject="$(subject_title)" from="$(from_addr)"-->
The double quotes in the <!--mailform lines are required.

Note that is no subject is defined then the script will return the URL of the HTML mailform document. Also note that in this release only ONE deliver line can exist. If more of them exist, the first encountered will be processed.

Reply URL

After the user has submitted the form, the form creator has the option of specifying a URL to send back. This is done by using the 'reply' command. By default a simple "Thank You" will be send.
For example:
<!--mailform reply="mythanks.html">
The URL field can contain a filename in the current directory (where the HTML mailform document resides), or a valid URL with the http:// prefix.

CGI environment variables.

In the current release there is no support for CGI enviroment variables. 

Mingling with JavaScript.

An interesting and rather usefull result can be produced by the mingling of the mailform with javascript. The most trivial but, the most usefull perhaps, use of javascript is for the form validation. In this way, which we are going to describe below, the javascript code is used as a pre-checker of all the form-fields to see if they contain anyhting at all or/and if what they contain is valid. Javascript functions can be created to validate that: Functions are provided to interactively check the above kinds of data and prompt the user if they have been entered incorrectly. Other utility functions are provided to: Note that there are much more of these functions and that these presented here were supposed to be only an example.

Complete example.

The example here demonstrates the various INPUT tags and how mailform can be used with these:

<HTML>
<HEAD>
<TITLE>mailform sampler</TITLE>
</HEAD>
<BODY>
<H2>mailform form sampler</H2>
<P>
This is the 1.0.0 release of the mailform generic handler. Released on 1 Dec 1997<BR>
<FORM method=POST action="/cgi-bin/mailform">
<HR>
<P>
Some regular text input fields
<P>
What is your name: <INPUT NAME="name" VALUE="" ><BR>
Your email address:<INPUT NAME="email" VALUE="" ><BR>
<HR>
<P>
Single choice select option:
<P>
What do you want to drink ? <SELECT NAME="drink" >
<OPTION>nothing
<OPTION>coffee
<OPTION>tea
<OPTION>juice</SELECT><HR>
<P>
Using multiple choice select options:
<P>
What do you want on your pizza ? <BR>
<SELECT MULTIPLE NAME="pizza">
<OPTION VALUE="ham">ham
<OPTION VALUE="cheese">cheese
<OPTION VALUE="tomato">tomato
<OPTION VALUE="capsicum">capsicum
<OPTION VALUE="chili peppers">chili peppers
<OPTION VALUE="mushrooms">mushrooms
<OPTION VALUE="olives">olives </SELECT>
<BR>
<INPUT TYPE="RADIO" NAME="size" VALUE="Small"> Small (6")<BR>
<INPUT TYPE="RADIO" NAME="size" VALUE="Medium">Medium (8")<BR>
<INPUT TYPE="RADIO" NAME="size" VALUE="Large">Large (10")<BR>
<BR>

Here are some checkboxes
<P>
<INPUT TYPE="CHECKBOX" NAME="salt" VALUE="yes"> salt<BR>
<INPUT TYPE="CHECKBOX" NAME="pepper" VALUE="yes"> pepper<BR>
<BR>
<HR>
<P>
Here are some radio buttons:<BR>
Please select your subscription length: <BR>
<HR>
<P>
A textarea
<P>
Please let us know what you think of our service by entering your
comments in the space provided<BR>
<TEXTAREA NAME="comments" ROWS=5 COLS=40>
</TEXTAREA>
<P>
<INPUT type="submit" value="send"> <INPUT TYPE="RESET"> <HR>
<P>
<!--mailform "Form submitted by: $(name)\n"-->
<!--mailform "The date is $(date) and the time is $(time)\n"-->
<!--mailform "Email address given as: $(email)\n"-->
<!--mailform "selected drink is: $(drink)\n"-->
<!--mailform "A $(size) pizza with: $(pizza)\n"-->
<!--mailform "salt: $(salt) pepper: $(pepper)\n"-->
<!--mailform "Here is a dollar sign \$ and a double quote \"\n"-->
<!--mailform "Comments:\n"-->
<!--mailform "$(comments)\n"-->
<!--mailform deliver=mail "somebody@dgxy.cec.be"subject="Form X submission"-->
<!-- Note that in this case the reply file will be found in the current directory-->
<!--mailform reply="thanks.htm"-->
</FORM>
</BODY>
</HTML>

Complete example with JavaScript added.

Note: if you are copying this page for real use, you might want to remove the comments to reduce the size of the resulting HTML page.

<HTML>
<HEAD>
<TITLE>mailform sampler</TITLE>
<!-- We define all Javascript's variables and functions in the <HEAD> section, to make sure
that the functions are loaded before the BODY of the document and its FORM which uses the
functions -->

<SCRIPT LANGUAGE="JavaScript1.1"> 

// VARIABLE DECLARATIONS 

var digits = "0123456789"; 
var lowercaseLetters = "abcdefghijklmnopqrstuvwxyz"; 
var uppercaseLetters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 

// whitespace characters 
var whitespace = " \t\n\r"; 
 

// CONSTANT STRING DECLARATIONS 
// (grouped for ease of translation and localization) 

// m is an abbreviation for "missing" 

var mPrefix = "You did not enter a value into the " var mSuffix = " field. This is a required field. Please enter it now." 

// s is an abbreviation for "string" 

var sLastName = "Last Name" 
var sFirstName = "First Name" 
var sEmail = "Email" 
 

// i is an abbreviation for "invalid" 

var iEmail = "This field must be a valid email address (like foo@bar.com). Please reenter it now." 
 

// p is an abbreviation for "prompt" 

var pEntryPrompt = "Please enter a " 
var pEmail = "valid email address (like foo@bar.com)." 
 

// Global variable defaultEmptyOK defines default return value 
// for many functions when they are passed the empty string. 
// By default, they will return defaultEmptyOK. 
// 
// defaultEmptyOK is false, which means that by default, 
// these functions will do "strict" validation. Function 
// isInteger, for example, will only return true if it is 
// passed a string containing an integer; if it is passed 
// the empty string, it will return false. 
// 
// You can change this default behavior globally (for all 
// functions which use defaultEmptyOK) by changing the value 
// of defaultEmptyOK. 
// 
// Most of these functions have an optional argument emptyOK 
// which allows you to override the default behavior for 
// the duration of a function call. 
// 
// This functionality is useful because it is possible to 
// say "if the user puts anything in this field, it must 
// be an integer (or a phone number, or a string, etc.), 
// but it's OK to leave the field empty too." 
// This is the case for fields which are optional but which 
// must have a certain kind of content if filled in. 

var defaultEmptyOK = false 

// Attempting to make this library run on Navigator 2.0, 
// so I'm supplying this array creation routine as per 
// JavaScript 1.0 documentation. If you're using 
// Navigator 3.0 or later, you don't need to do this; 
// you can use the Array constructor instead. 

function makeArray(n) { 
//*** BUG: If I put this line in, I get two error messages: 
//(1) Window.length can't be set by assignment 
//(2) daysInMonth has no property indexed by 4 
//If I leave it out, the code works fine. 
// this.length = n; 
for (var i = 1; i <= n; i++) { 
this[i] = 0 

return this 

// Check whether string s is empty. 
function isEmpty(s) 
{ return ((s == null) || (s.length == 0)) } 

// Returns true if string s is empty or // whitespace characters only. 
function isWhitespace (s) 
{ var i; 

// Is s empty? if (isEmpty(s)) return true; 

// Search through string's characters one by one 
// until we find a non-whitespace character. 
// When we do, return false; if we don't, return true. 

for (i = 0; i < s.length; i++) { 
// Check that current character isn't whitespace. 
var c = s.charAt(i); 

if (whitespace.indexOf(c) == -1) return false; 

// All characters are whitespace. 
return true; 

// Returns true if character c is an English letter 
// (A .. Z, a..z). 
// 
// NOTE: Need i18n version to support European characters. 
// This could be tricky due to different character 
// sets and orderings for various languages and platforms. 

function isLetter (c) 
{ return ( ((c >= "a") && (c <= "z")) || ((c >= "A") && (c <= "Z")) ) } 
 

// isAlphabetic (STRING s [, BOOLEAN emptyOK]) 
// 
// Returns true if string s is English letters 
// (A .. Z, a..z) only. 
// 
// For explanation of optional argument emptyOK, 
// see comments of function isInteger. 
// 
// NOTE: Need i18n version to support European characters. 
// This could be tricky due to different character 
// sets and orderings for various languages and platforms. 

function isAlphabetic (s) 

{ var i; 

if (isEmpty(s)) 
if (isAlphabetic.arguments.length == 1) return defaultEmptyOK; 
else return (isAlphabetic.arguments[1] == true); 

// Search through string's characters one by one 
// until we find a non-alphabetic character. 
// When we do, return false; if we don't, return true. 

for (i = 0; i < s.length; i++) 

// Check that current character is letter. 
var c = s.charAt(i); 

if (!isLetter(c)) return false; 

// All characters are letters. return true; 

// isEmail (STRING s [, BOOLEAN emptyOK]) 
// 
// Email address must be of form a@b.c -- in other words: 
// * there must be at least one character before the @ 
// * there must be at least one character before and after the . 
// * the characters @ and . are both required 
// 
// For explanation of optional argument emptyOK, 
// see comments of function isInteger. 

function isEmail (s) 
{ if (isEmpty(s)) 
if (isEmail.arguments.length == 1) return defaultEmptyOK; 
else return (isEmail.arguments[1] == true); 

// is s whitespace? 
if (isWhitespace(s)) return false; 

// there must be >= 1 character before @, so we 
// start looking at character position 1 
// (i.e. second character) 
var i = 1; 
var sLength = s.length; 

// look for @ 
while ((i < sLength) && (s.charAt(i) != "@")) 
{ i++ } 

if ((i >= sLength) || (s.charAt(i) != "@")) return false; 
else i += 2; 

// look for . 
while ((i < sLength) && (s.charAt(i) != ".")) 
{ i++ } 

// there must be at least one character after the . 
if ((i >= sLength - 1) || (s.charAt(i) != ".")) return false; 
else return true; 

/* FUNCTIONS TO NOTIFY USER OF INPUT REQUIREMENTS OR MISTAKES. */ 

// Display prompt string s in status bar. 
function prompt (s) 
{ window.status = s } 

// Display data entry prompt string s in status bar. 
function promptEntry (s) 
{ window.status = pEntryPrompt + s } 

// Notify user that required field theField is empty. 
// String s describes expected contents of theField.value. 
// Put focus in theField and return false. 

function warnEmpty (theField, s) 
{ theField.focus() 
alert(mPrefix + s + mSuffix) 
return false } 

// Notify user that contents of field theField are invalid. 
// String s describes expected contents of theField.value. 
// Put select theField, pu focus in it, and return false. 

function warnInvalid (theField, s) 
{ theField.focus() 
theField.select() 
alert(s) 
return false } 

/* FUNCTIONS TO INTERACTIVELY CHECK VARIOUS FIELDS. */ 

// checkString (TEXTFIELD theField, STRING s, [, BOOLEAN emptyOK==false]) 
// 
// Check that string theField.value is not all whitespace. 
// 
// For explanation of optional argument emptyOK, 
// see comments of function isInteger. 

function checkString (theField, s, emptyOK) { 
// Next line is needed on NN3 to avoid "undefined is not a number" error 
// in equality comparison below. 
if (checkString.arguments.length == 2) emptyOK = defaultEmptyOK; 
if ((emptyOK == true) && (isEmpty(theField.value))) return true; 
if (isWhitespace(theField.value)) return warnEmpty (theField, s); 
else return true; } 

// checkEmail (TEXTFIELD theField [, BOOLEAN emptyOK==false]) 
// 
// Check that string theField.value is a valid Email. 
// 
// For explanation of optional argument emptyOK, 
// see comments of function isInteger. 

function checkEmail (theField, emptyOK) 
{ if (checkEmail.arguments.length == 1) emptyOK = defaultEmptyOK; 
if ((emptyOK == true) && (isEmpty(theField.value))) return true; 
else if (!isEmail(theField.value, false)) 
return warnInvalid (theField, iEmail); 
else return true; } 

function validatePersonalInfo(form) 
{ return ( 
checkString(form.elements["LastName"],sLastName) && 
checkString(form.elements["FirstName"],sFirstName) && 
checkEmail(form.elements["Email"], true) 

</SCRIPT> 
 

</HEAD>
<BODY>
<CENTER>
<H2>mailform form sampler</H2>
<P>
This is the 1.0.0 release of the mailform generic handler. Released on 1 Dec 1997<BR>
<P><I>Fileds matked with an asterisk (*) must be entered.</I>
</CENTER>
<FORM method=POST action="/cgi-bin/mailform">
<HR>
<P>
Some regular text input fields
<P>
*What is your first name: <INPUT TYPE="text" NAME="LastName" VALUE="" onFocus="promptEntry(sFirstName)" onChange="checkString(this,sFirstName)"><BR>
*What is your last name: <INPUT TYPE="text" NAME="FirstName" VALUE="" onFocus="promptEntry(sLastName)" onChange="checkString(this,sLastName)">
*Your email address:<INPUT TYPE="text" NAME="Email" VALUE="" onFocus="promptEntry(pEmail)" onChange="checkEmail(this, true)"><BR>
<HR>
<P>
Single choice select option:
<P>
What do you want to drink ? <SELECT NAME="drink" >
<OPTION>nothing
<OPTION>coffee
<OPTION>tea
<OPTION>juice</SELECT><HR>
<P>
Using multiple choice select options:
<P>
What do you want on your pizza ? <BR>
<SELECT MULTIPLE NAME="pizza">
<OPTION VALUE="ham">ham
<OPTION VALUE="cheese">cheese
<OPTION VALUE="tomato">tomato
<OPTION VALUE="capsicum">capsicum
<OPTION VALUE="chili peppers">chili peppers
<OPTION VALUE="mushrooms">mushrooms
<OPTION VALUE="olives">olives </SELECT>
<BR>
<INPUT TYPE="RADIO" NAME="size" VALUE="Small"> Small (6")<BR>
<INPUT TYPE="RADIO" NAME="size" VALUE="Medium">Medium (8")<BR>
<INPUT TYPE="RADIO" NAME="size" VALUE="Large">Large (10")<BR>
<BR>

Here are some checkboxes
<P>
<INPUT TYPE="CHECKBOX" NAME="salt" VALUE="yes"> salt<BR>
<INPUT TYPE="CHECKBOX" NAME="pepper" VALUE="yes"> pepper<BR>
<BR>
<HR>
<P>
Here are some radio buttons:<BR>
Please select your subscription length: <BR>
<HR>
<P>
A textarea
<P>
Please let us know what you think of our service by entering your
comments in the space provided<BR>
<TEXTAREA NAME="comments" ROWS=5 COLS=40>
</TEXTAREA>
<P>
<INPUT type="submit" value="send" onClick="validatePersonalInfo(this.form)">
<INPUT TYPE="RESET"> <HR>
<P>
<!--mailform "Form submitted by: $(FirstName) $(LastName) \n"-->
<!--mailform "The date is $(date) and the time is $(time)\n"-->
<!--mailform "Email address given as: $(Email)\n"-->
<!--mailform "selected drink is: $(drink)\n"-->
<!--mailform "A $(size) pizza with: $(pizza)\n"-->
<!--mailform "salt: $(salt) pepper: $(pepper)\n"-->
<!--mailform "Here is a dollar sign \$ and a double quote \"\n"-->
<!--mailform "Comments:\n"-->
<!--mailform "$(comments)\n"-->
<!--mailform deliver=mail "somebody@dgxy.cec.be"subject="Form X submission"-->
<!-- Note that in this case the reply file will be found in the current directory-->
<!--mailform reply="thanks.htm"-->
</FORM>
</BODY>
</HTML>

Data Centre