Error

Cannot open mail form /images/Ad-Heartling-Card.png, No such file or directory

NAME

/cgi-bin/email - CGI Email Processor

DESCRIPTION

The email form processor is a new way of dealing with sending mail from HTML forms. Instead of having a separate HTML form file and a CGI program to interact with it, the form processor uses a single file which contains templates for the HTML form, the email to be sent, and the HTML response if the form is correctly filled out.

Overview

To use the CGI email system, you must connect this form to the program which processes it. To connect the template file to the CGI program, reference the form as:

        /cgi-bin/email/path-to-your/form.file

where the path is a virtual path (starting at document root). The trickiest part is getting the <A HREF="..."> set correctly. Start with the URL of your template file, then split it into two parts, e.g.

        http://www.ibp.com/pit/customer/your.form
        \                /\                     /
         `--- Part 1 ---'  ` ----- Part 2 -----'

Then you put the script name in the middle. Usually this is ``/cgi-bin/email'', but it depends on how your server is configured. On www.ibp.com it is ``/cgi-bin/email'', so our tags looks like:

        http://www.ibp.com/cgi-bin/email/pit/customer/your.form
        \                /\            /\                     /
         `--- Part 1 ---'   script name  ` ----- Part 2 -----'

For simplicity, you may (usually) leave out part 1.

Format file components

A format file consists of three (or more) parts:

  1. Fill-in form. The form portion of the format file is HTML which is to be filled in by the user. The filled in fields will be emailed to the form maintainer(s) in the 3rd and subsequent parts of the format file. If any required fields are not filled in, the fill-in form is redisplayed with the correctly filled in parts displayed, and the missing parts in a warning message.

  2. Response page. The response page is HTML which is displayed if the form is coirrectly filled in by the user.

  3. Email. The email component(s) are sendmail templates which are passed to sendmail if the form is correctly filled in by the user. Multiple email templates can be sent to multiple (different) addresses.

Dividers

The three (or more) parts of the format file are separated by textual dividers. If a divider is not specified, it defaults be a string of 10 or more +'s. The divider is defined to be the first non-blank line of the file that is not a comment. If the first non-blank, non-comment line starts with "<html>", then the email package assumes that no divider has been specified (and uses the default divider of 10 or more +'s). For readability, I like to use a divider like:

        ===== DIVIDER =====

NOTE: Blank lines surrounding a divider are automatically deleted, so you can use extra blank lines for readability's sake.

Comments

Comments (which don't nest) are everything in between [# and a closing #].

        [# This is a [# sample comment #]

Embedded Commands

Everything is passed as it is seen to the browser in parts 1 and 2, and as to sendmail in parts 3 and later, but anything in between [square brackets] is considered a command to the system. Naturally, if you want a [ in your form, simply put a \ in front of it, and it will be preserved, as:

        \[ <= really a bracket.

There are 3 types of embedded commands (each with a different prefix character, similar to perl).

  1. Commands to the email system itself

  2. Environment variable interpolation (can only be used in parts 2, 3, etc.)

  3. Form variable interpolation (plain or with printf style formatting, can only be used in parts 2, 3, etc.)

Commands to the email system itself

Anything that starts with a "-" is a special command to the system (e.g., [-error-map], [-ERROR], etc.) Special commands are case insensitive. The following commands are recognized:

[-error]

The special tag [-ERROR] is used to pass error messages back to the user or maintainer of the email system. This tag has two different behaviors depending on where it is used.

  1. When used in part 1 (the fill-in form), the [-error] command will be replaced with a message that asks for missing fields which have been declared to be required (required fields are described later in this document).

  2. When used in part 2 (confirmation) and parts 3 or later (email), the [-error] command will be replaced with a message that reports consistancy errors (that is, fields which are present in the first part of the format file but absent in others (or vice versa) - which helps you find typos and omissions).

The division of behavior of the [-error] command is such because you want to tell the user what they forgot to type, but you typically want to tell the maintainer (via email) of consistency errors.

[-error-map]

When a required field is not filled in by the user, an error message is substituted wherever the [-error] command appears in the first part. The names of the fields that are printed are identical to the names of the format fields. The [-error-map] command can be used to override this default, either partially or completely.

The entries in the error map are the strings to print if one of the required entries is missing. If there is nothing in the error-map, the name of the field itself is printed. The left side of the "=>" is the field name, the right side is the string to print (no quotes are expected - if they are present, they will be part of the substitution). An example of this command is:

        [-error-map 
            First =>    First Name,
            Last =>     Last Name,
            Zip =>      Zip Code
            ]

The [-error-map] command only has meaning in part 1 of the format file (the other parts are only shown when there are no missing fields!)

[-include filename]

The [-include filename] command is used to insert the contents of the specified filename at the location of the command. This tag may be used in any part of the format file. Depending on the security level of the script which has been enabled, the file may be restricted as to location or type. The security level of the script is configured with the $security variable.

The [-include] directive is not recursive - you can't [-include] a file from within an [-include]ed file. However, the [-include] directive is performed before any variable interpolation or consistency checking. You may defined variables or interpolate them in an [-include]ed file.

[-no-autorelative]

In parts 1 and 2 of the format file, you can use URLs of the "usual" three kinds: Absolute (i.e., http://dir/file.html), Virtual (i.e., relative to the root directory of the server, as /dir/file.html), or Relative (i.e., relative to the current directory, as file.html). The problem with relative URLs is that the "current" directory is the directory that the CGI script is in!

Unless you disable this behaviour with the special directive [-no-autorelative], the script will automatically change all relative URLs to be relative to the directory that the format file is in (which is what you would expect in normal behaviour). The [-no-autorelative] directive must be applied independently to parts 1 and 2 of the form (it has no meaning on parts 3 and later, which are for email).

CAUTION: If you use the default autorelative feature, be advised that it inserts a <BASE> tag in the HTML header. If you don't use one yourself, don't worry. If you do use one, it will be overridden!

Environment variable interpolation

The values of environment variables can be interpolated into parts 2, 3, and later in the format file by using the [$ENVARIABLE] notation. Which variables are allowed to be interpolated (or whether any at all are allowed) is determined by the security level configured in the script. The security level of the script is configured with the $security variable. As a general rule, for security's sake, although all variables are allowed, you should only use the following variables in your email/response form:

        GATEWAY_INTERFACE       HTTP_ACCEPT             HTTP_USER_AGENT
        HTTP_REFERER            QUERY_STRING            REMOTE_ADDR
        REMOTE_HOST             REQUEST_METHOD          SERVER_ADMIN
        SERVER_NAME             SERVER_PORT             SERVER_PROTOCOL

Also generally available (and generally deprecated) are:

        DOCUMENT_ROOT           PATH_TRANSLATED         SERVER SOFTWARE

NOTE: Environment variables are case sensitive, and are generally in all upper case.

Form variable interpolation

The values of form variables can be interpolated into parts 2, 3, and later in the format file by using the [variable], [~variable], or [%fmt variable] notation. Which variables are defined is determined by part 1 (the form) of the format file.

The email system automatically tracks all variables introduced in part 1 of the format file. These are specified in the <INPUT>, <TEXTAREA>, and <SELECT> tags, and are named using the NAME attribute in these tags. Form variable names are case sensitive, and must be capitalized the same in part 1 as in the other parts of the format file.

The email system performs consistency checking, and will warn you (through the [-error] command), if any variables appear in part 1 of the format file and are missing later (or vice versa).

The values of the form variables may be interpolated in two ways:

  1. Plain interpolation - by simply specifying the name of the variable in brackets, the value of the variable will be substituted exactly as the user typed it. For example:

            [Address]

    would interpolate the value of the variable named Address.

  2. Printf-style interpolation - by specifying a printf-style format code followed by the name of the variable, the variable will be interpolated using that printf format. For example:

            [%05d Zip]

    will print a field called Zip as a 5-digit numeric field with leading zeros, while:

            [%-.20s Address]

    will print the first 20 characters of the field called Address left justified.

    NOTE: Perl is the underlying support engine, so strings and numbers will be interconverted as appropriate for the format (so printing the string "hello" with the format field "%d" will print 0).

Fill-in form

The HTML that is used in the fill-in form part of the format file is no different from ordinary HTML, with two exceptions:

  1. The <FORM> tag requires no action or method. These two attributes will automatically be filled in to match the current invocation of the email script.

  2. The <INPUT> and <TEXTAREA> accept another attribute REQUIRED. The REQUIRED attribute tells the email system that this attribute must be filled in before the form is considered complete.

    NOTE: The HTML in part 1 of the format file is output to the user's browser largely as-is. However, since the REQUIRED tag is not part of the DTD, it is stripped out before being sent to the browser. It does, however, still take effect even though you do not see it in the outputted HTML.

Email

The email parts of the format file are text that is sent to sendmail. As such, it must observe a few simple rules.

  1. There must be a To: header.

  2. The header items must have a blank line between them at the body of the email.

  3. It is recommended (not required) that the destination email address be constant (and not be filled in by the browser).

EXAMPLE

The following is a complete (if somewhat simple) example of a format file. The three components are the HTML form to fill in (with one required field), the HTML confirmation screen, and the email to send when the form is satisfactorily completed.

 [# We specify a divider here to override the default #]
 ===== DIVIDER =====

 <HTML>
 <head>
 <title>Food Survey</title>
 </head>
 <body bgcolor="#ffffff">
 <h1>Email test form<br clear=all></h1>

 [#
  # Specify an error map to use when we have errors, and a place
  # to put the error message itself
  #]
 [-error-map 
     First =>   First Name,
     Last =>    Last Name,
     Zip =>     Zip Code
     ]

 [-ERROR]

 <form> [# You don't need to specify METHOD or ACTION attributes #]
 <table border=10 cellpadding=6 cellspacing=6 width=100%>
 <tr><td align=center colspan=4><h3>Please complete the following
 information to register for any of the <i>free food</i>
 listed below. </h3>

 <table>
 <tr><td>First Name:</td><td colspan=3>
 [#
  # The input field First contains the attribute "required".  This
  # indicates that the field must be filled in on the form.
  #]
 <input type=text required name="First" size=35 maxlength=256><br></td></tr>
 <tr><td>Last Name:</td><td colspan=3>

 [#
  # The input field Last is optional (because there is no "required"
  # attribute - the user doesn't need to fill it in
  #]
 <input type=text name="Last" size=35 maxlength=256><br></td></tr>
 <tr><td>E-mail:</td><td colspan=3>
 <input type=text name="Email" size=35 maxlength=256><br></td></tr>
 </table>
 </td></tr>
 </table>

 <p><br></p>
 <hr size=5 width=90%>
 <p align=center>Please input the foodstuff
 which you would like to receive.<br>
 </p>

 <textarea name="TextQ1" rows=5 cols=45>Type your food here...</textarea>

 <hr size=5 width=90%>
 <p><center>To complete your request please select the
 &quot;Feed Me&quot; button now.<br>
 <input type=submit value="Feed Me">
 <br>Or you may clear your choices by selecting the
 &quot;I'm Not Hungry&quot; button.<br>
 <input type=reset value="I'm Not Hungry">
 </center>
 </form>

 <HR>
 <h5> Copyright &#169; 1996-2005 Daniel V. Klein</h5>
 </body>
 </HTML>

 ===== DIVIDER =====

 [#
  # If the form was filled out successfully, the second element in
  # the # form is sent back to the browser.  Variable substitution
  # is supported in the second and following parts.  It may occur in
  # one of three forms:
  #
  #     [foo]           Insert the value of the variable foo with newlines
  #                     suppressed
  #     [~foo]          Insert the value of the variable foo with newlines
  #                     allowed (this may be dangerous, cf. email addresses!)
  #     [%fmt foo]      Using the "printf" style format code, insert
  #                     the value of the variable foo.
  #]
 <HTML>
 <head>
 <title>Food Survey Received</title>
 </head>
 <body bgcolor="#ffffff">
 <h1>Mail sent!<br clear=all></h1>

 [-ERROR][# Won't be used here, but I want you to see it work #]

 <h3>Thank you for your interest in food. We will be
 contacting you about the information you requested shortly.</h3>

 <p>As near as I can tell, your used [$HTTP_USER_AGENT] from
 <tt>[$REMOTE_HOST] ([$REMOTE_ADDR])</tt> to submit your form.
 Also, your document root is <tt>[$DOCUMENT_ROOT]</tt> (shhh!)

 <HR>
 <h5> Copyright &#169; 1996-2005 Daniel V. Klein</h5>
 </body>
 </HTML>

 ===== DIVIDER =====

 [#
  # If the form was filled out successfully (that is, if no required
  # elements were missing), this third part is sent through
  # sendmail -oi -t.  All fields in square brackets are replaced with
  # the variables from the form.
  #]
 To:    dan@klein.com
 From:  "[First] [Last]" <[Email]> 
 Subject:Food Order

 The following requested a meal
 ===========================================================
 Name:          [First] [Last]
 Email:         [Email]

 Hungry for:    [~TextQ1]

 [#
  # If the -error tag is used in the 2nd or 3rd part, it will only list
  # fields which don't appear in the opposite half (fields which the
  # user has failed to fill in will only show up in the first part of
  # the form, of course)
  #][-ERROR]
 [#
  # Although it is not shown in this example, there can be additional
  # dividers after this point.  If there are, they will be separate
  # email messages.  The idea here is that you can only have one
  # response HTML, but you *might* want to send multiple different
  # email messages to different people.  Don't use this method to
  # send identical copies of email to different people - use a comma
  # separated To: or Cc: list instead.
  #]

AUTHOR

Daniel V. Klein, dan@klein.com, Copyright 1996-2005, all rights reserved