advertisement -- please support sponsors

forms, networking:
submitting forms via email

How can I submit a form via email, without using CGI?

Forms are great tools for collecting information from web surfers passing through a site. Unfortunately, because most forms require CGI programs for processing, people with little or no programming experience are often unable to implement them. Additionally, some users who actually do understand CGI may not be authorized to run CGI programs on their web sites.

For these people, the mailto form submission protocol, which enables clients to submit completed forms via email, is an invaluable substitute. When used by itself, however, this protocol generates extremely difficult-to-process email -- so difficult, in fact, that it is really not fit for human consumption. In this article, I will describe a technique in which the mailto protocol is combined with JavaScript to produce forms that are submitted via human-readable email.

using the mailto protocol

When the sole purpose of a form is just to send data to the form's owner -- and no immediate response is required -- a CGI program is not really necessary. Instead, why not just let the client's browser mail the form directly to the form's owner?

In new browsers, this can be done by specifying the recipient's email address in the "action" field of the <form> tag, as shown in the following example:


<form method="post" action="mailto:sharky@sharky.com">
     .
     .
     .
(form elements)
     .
     .
     .
</form>
Note that when an email address is given as a URL, it must be prefixed with the mailto: protocol identifier. In the example above, the form data will emailed to sharky@sharky.com.

You may also wish to send the email with a particular subject. This is done by appending a subject specifier to the end of the mailto URL:

action="mailto:sharky@sharky.com?subject=your web site"
A subject specifier consists of the keyword "subject," followed by an equals sign, and then by the actual subject text. As shown, the email address and the subject field must be separated by a question mark. Except for the actual subject text, a properly formed mailto URL should not have any spaces in it.

sending un-encoded data

Submitted form data is usually composed one or more "identifier=value" pairs. When posted to a CGI program, these pairs are URL-encoded, concatenated together, and separated by question marks. For example, the pairs
name    = "Sharky"
comment = "It's hard to read!"
would be transmitted to a CGI program as
name=Sharky?comment=It%27s%20hard%20to%20read%21
We certainly don't want our email to look like this! To send the form data in a human-readable format, we must set the <form> tag's enctype field (i.e., the form's encoding type) to "multipart/form-data." This option instructs the browser to send the data as a plain text, multiple-attachments email message. In this format, the first data item in the form becomes the body of the message, and each additional item is included as an attachment. In both the main message body and in the attachments, identifiers are stripped from the data, leaving only the values.

formatting the data

Suppose you had the following form...
   Name: 
Comment: 
...and that you want it to produce the following email message:
Greetings.

I have a comment for you.  It is:

	I like it.

Sincerely,
Sharky
Because the multipart/form-data encoding type will send each item of the form as a separate email attachment, formatting the data so that it all appears in the main message body -- and in an intelligent, human-readable format -- is not a trivial task. If you're thinking, "This is a job for JavaScript!," you are right.

The basic idea is to use two forms: an input form and a proxy form. The input form contains the actual form elements through which the user inputs data -- text fields, radio buttons, check-boxes, etc. -- everything, that is, except for the actual submit button. The submit button is part of the second form, or the proxy form. When pushed, it activates a JavaScript routine that transforms input data from the first form into human-readable email. Let's discuss the procedure in greater detail.

step 1: build the input form

The first step is to generate a regular input form, but without the "submit" button, as shown below:
<form name="form_data">
<pre>
   Name: <input name="username" type="text">
Comment: <input name="comment"  type="text">
</pre>
</form>
Don't forget to name each element of the form, including the form itself, so that JavaScript can be used to access them later. In this example, the form's name is "form_data," and the two input fields are called "username" and "comment."

It is not necessary, nor is it useful, to specify the input form's action, method, or enctype, since the input form itself will never be submitted.

step 2: build a proxy form

The form created in step (1) is used only the gather data. The formatted email message will actually be sent as part of a second, proxy form. As described earlier, a form that is submitted via email should have its method set to "post," its enctype set to "multipart/form-data," and its action set to a valid mailto URL:
<form name    ="proxy_form"
      method  ="post"
      enctype ="multipart/form-data"
      action  ="mailto:sharky@sharky.com?subject=your web site"
      onSubmit="return update_message_body ();">
Take special note that the <form> tag has an onSubmit event handler that calls a function named "update_message_body." The purpose of this event handler will be explained in step (3).

In order send the data as a normal email message, without attachments, the proxy form should have only one named field. Furthermore, this field should be a "hidden" field so that the user cannot interact with it.

<input type="hidden" name="message_body">
As mentioned earlier, the submit button is also included in the proxy form:
<input type="submit" value="send mail">
It should appear to the user as if the submit button will send the input form created in step (1). (When pushed, however, it will actually send the proxy form.)

step 3: format the message

Now here's the big trick: When the user pushes the proxy form's submit button, the proxy form's onSubmit event handler will be executed. Since the form cannot be mailed until after the event handler has completed, the event handler can be used to generate the email message just before it is sent!

Here is a function that generates a formatted message from data entered in the original form:

<script>
function update_message_body ()
{
	var username = document . input_form . username . value;
	var comment  = document . input_form . comment  . value;

	document . proxy_form . message_body . value =
		"Greetings.\n"
	+	"\n"
	+	"I have a comment for you.  It is:\n"
	+	"\n"
	+	"\t" + comment + "\n"
	+	"\n"
	+	"Sincerely,\n"
	+	username + "\n";

	return true;
}
</script>
This function, called by the onSubmit event handler, reads fields from the main form to build a single message string, which is then copied into the proxy form's hidden element.

Whenever false is returned by an onSubmit event handler, the submit process is aborted. Since the value returned by update_message_body is also returned by the event handler, update_message_body should return true only if it is OK to send the form. This is your chance to validate the information entered into the form before sending it.

By the way, you should use great care when programming the onSubmit event handler. If the JavaScript interpreter encounters an error while processing the event handler, the entire event handler will be aborted, and the form will be submitted anyway -- even if the proxy form's message_body element has not been properly initialized.

step 4: put it all together

The results of our labors is the following HTML/JavaScript document:
<form name="input_form"><pre>
   Name: <input name="username" type="text">
Comment: <input name="comment"  type="text">
</pre></form>

<script>
function update_message_body ()
{
	var username = document . input_form . username . value;
	var comment  = document . input_form . comment  . value;

	document . proxy_form . message_body . value =
		"Greetings.\n"
	+	"\n"
	+	"I have a comment for you.  It is:\n"
	+	"\n"
	+	"\t" + comment + "\n"
	+	"\n"
	+	"Sincerely,\n"
	+	username + "\n";

	return true;
}
</script>
<form name    ="proxy_form"
      method  ="post"
      enctype ="multipart/form-data"
      action  ="mailto:sharky@sharky.com?subject=your web site"
      onSubmit="return update_message_body ();">
<input type=hidden name="message_body">
<input type=submit value="send mail">
</form>
The user enters information into the input form but pushes the proxy form's submit button. The event handler of the proxy form processes the input form's data to generate a single, large string containing the email message to be sent. This string is copied into the proxy form's hidden input field, and then the proxy form is mailed.

special considerations

Email-submitted forms have a few "peculiarities" which are worth mentioning.

changing the action field

Odds are good that you will only want your form mailed to one place and that you will always want it to have the same subject. This is why the email recipient's address (sharky@sharky.com) was hard-coded in the preceding example. However, because JavaScript also allows you to modify a form's action field on the fly, there is no reason why you can't change the email message's subject or destination address within the event handler. All you need to do is generate a new action string and copy it into the proxy form's action property:
new_action = "mailto:" + new_destination_address + "?subject=" + new_subject;
document . proxy_form . action = new_action;
When the form is submitted (mailed), the new action string will be used instead.

responding to a submission

When forms are submitted to servers via CGI, the server is obligated to respond with a web page containing feedback about the form. In simple cases, this is limited to a brief "thank you" message, but for more complex applications, the feedback may contain either an additional form to fill out (i.e., requesting missing information) or a specific response to information just received (i.e., results of a query). Because of this, users have learned to expect a response page after submitting a form. If the browser just "sits there," some users will believe that something is wrong.

Form's submitted via email, unfortunately, are not automatically followed by a response page. When a user pushes the submit button, the mail will indeed be sent, but the browser window will just "sit there" and not show a response (except in the status bar, which provides information about the progress of the email being sent). Confused, some users will push the submit button over and over again, desperately hoping for a response, and send multiple copies of the same form before finally giving up!

This means that you should provide the user with instructions about what to do after mailing the form. (I.e., "Click here after you have submitted the form.") It would be nice if JavaScript provided methods for detecting when the browser has finsihed sending email. If these were available, then JavaScript could be used to automatically load a response page after sending the mail. At the time of this writing, however, there is no way for JavaScript to detect when the browser has finished sending email.

One possible work-around is to activate a window timer that loads the response page some arbitrary time after the submit button has been pressed. This solution, however, cannot work for everyone because the amount of time required to send mail is different from browser to browser and user to user, and cannot be predicted accurately.

If you find a good solution to this problem, I would like to hear about it.

Charlton Rose
March 25, 1997