Soupermail - a generic CGI WWW form handler written in Perl


<form method="post" action="/cgi-bin/">


Soupermail is a generic HTML form handling script designed to provide a high degree of control over a form's behaviour and output. It provides the following features:

Soupermail can be used to handle single standalone forms, or generate and control complex multipart forms.


Soupermail assumes some form fields have special meanings. These field names ARE CASE SENSITIVE. The following is a list of such fields:

Assumed to be the email address of the form's sender. Needed if the email is to be copied to the sender, or you are using a sendertemplate. When Soupermail sends and email back, it will use the value of this field as the email's From: address.
This is a path to the configuration file that controls soupermail. The path can either be relative to the location of the form, or an absolute path from the webserver's root. If you are using soupermail to generate multipart forms, it is recommended that you use absolute paths.


Soupermail is controlled on a per form basis by using configuration files. Each form handled by soupermail must have an associated configuration file.

The location of the file is passed to soupermail through the PATH_INFO CGI variable, or by using 'SoupermailConf' as a form parameter. The PATH_INFO is set by providing a path after the call to soupermail in the <form> element of the HTML page.

If a form has a configuration file in /forms/config.txt, the form should call soupermail with

<form method="post" action="/cgi-bin/">

or as a form variable with:

<input type="hidden" name="SoupermailConf" value="/forms/config.txt">

The second method of supplying the config file is recommended. People running under a cgiwrapped environment will have problems with the first method, and even worse, the IIS webserver defaults to not supporting the PATH_INFO method.

The path to the configuration file must be relative to the web server's root directory. Do not use URLs or absolute paths to the configuration file.

The format for a configuration file is a series of configuration statements of the form:

name : value


if : condition then name : value


unless : condition then name : value

If a badly phrased or incorrect configuration file is passed to soupermail, it will complain, so always check your soupermail configurations carefully.

Valid names for the configuration file are:

This can be set to yes or no. If its yes, then email is sent out encoded as quoted printable characters (i.e. 7bit safe). By default though, email is sent out as 8bit, and its assumed the mailservers in the transmission route will handle the 8bit conversions. You should only need to alter this if you are experiencing character corruption in your emails.
Set to yes or no. When email is sent without a mailtemplate, the form fields are displayed in the email in alphabetical order. Setting this value to no does not sort the fields, and returns them in the same order that the browser sent them.
Files can be attached to email sent with sendertemplate and htmlsendertemplate. X is a number identifying the attachment.

See also listattachmentX

attachment1 : /forms/download/myfile.pdf
attachment3 : file2.doc
Since Soupermail doesn't know about MIME types, you may want to set a specific MIME type for an attachment so receiving mail clients know how to deal with them. By default, Soupermail sends text attachments as text/plain and binary attachments as application/octet-stream.

See also listattachmentXmime

attachment2 : /wordfile.doc
attachment2mime : application/x-msword
attachment5 : /forms/download/myfile.pdf
attachment5mime : application/pdf
This is a comma separated list of email addresses to blind carbon copy on the email sent to the mailto addresses. See also senderbcc.
A template file to return to the user if they submitted a blank form.
blank : /forms/config/blank.tpl
The MIME type that's returned to the browser for the blank template. Also see successmime, expiresmime and failuremime.
Set to yes or no. If you are running Soupermail in a CGI wrappers type environment, where Soupermail's running with its owner's permissions rather than the webserver's permissions, setting cgiwrappers to yes will make the filereadable config command actually work.
This specifies the domain name that the cookie will be sent to. By default, no domain is specified for a cookie. See the section on COOKIES for more information.
cookie1domain :

Will only send cookie1 to pages on the webserver. See the section on COOKIES for more information.

A date or time format indicating when one of the nine available cookies expires. Allowable formats can be relative. eg. +1h means one hour from now, -2d means 2 days ago. The time periods allowable are s = second, m = minute, h = hour, d = day, M = month, y = year.

Absolute dates and times can also be specified.

See the section on COOKIES for more information.

cookie1expires : 1-4-1999 12:00:00

will expire the first cookie at midday on 1 April 1999.

cookie2expires : +1M

will expire the second cookie one month from when the form was submitted

By default, cookies expire 24 hours from when they were set.

This sets the name of one of the nine available cookies to a value. See the section on COOKIES for more information.
cookie1name: zippy

sets the first cookie's name to 'zippy'

This specifies which pathnames a cookie will be sent to. By default, this will be to the location where soupermail is stored. See the section on COOKIES for more information.
cookie3path : /products

Would only send cookie 3 to pages below the /products directory of a website.

This is a yes or no value that specifies whether a cookie will be sent over all connections, or just secure SSL connections. See the section on COOKIES for more information.
This sets the value of one of the nine available cookies. See the section on COOKIES for more information.
If set to yes, this will send cookies when a blank form is detected.
When set to yes, this will send cookies when a submission past an expires date is sent.
When this is set to yes, cookies will be sent out even if the form has been considered a failure.
When set to yes, cookies are sent out when the form is considered a success. This is the default behaviour.
Each counter is stored on the webserver in a single file. The file simply contains a number and should be specified in a directory that's writable by the webserver. When a counterfile line is read into the config file, the counter's value is made available for later use in the config file. See COUNTERS for more information.
If set to yes, this specifies that counter X will be incremented if a blank form is submitted.
If set to yes this specifies that counter X will be incremented if the form is submitted after its expiry date.
If set to yes this specifies that counter X will be incremented if the form is missing required fields.
If set to yes this specifies that counter X will be incremented if the form is submitted successfully. The default is to increase the counter by is 1.
This is a positive integer value that specifies how much counter X should be increased by.
By default, the Subject line of emails is assumed to be 7bit ASCII. However, if you are sending non-ASCII characters, and have set the mailcharset option, then Subject lines are encoded as described in RFC 2047.
This is an error message that you can generate and that becomes available to use in the config file and templates as http_config_error. If an error is set, SQL commands will not run, and Soupermail will run in a failure mode.
A date of the format dd-mm-yyyy after which the form cannot be submitted
expires : 24-12-1998

This means the form would not be submittable after the 24st of December 1998

The MIME type to return to the browser when expirestemplate is sent out. See also successmime, blankmime and failuremime.
A template file to use if the form has been submitted after its expires date. See the section on TEMPLATES for more information.
A template to return to the user if they have not completed all the required fields of a form. See the section on TEMPLATES for more information.
failure : /forms/config/bad.tpl
The MIME type to return to the browser when the failure template is sent out. See also successmime, blankmime and expiresmime.
When writing the contents of a form to a file, new data is usually placed at the end of the file. By setting fileattop, new data can be written at the start of the file (although after any specified header).
fileattop : yes
This specifies a filename for backup files to be written into if a soupermail generated file will grow over a filemaxbytes limit.

The value for this can include formatting codes as listed in the FORMATS section of this document. This lets you generate a number of backups with a very fine level of detail.

The value specified in filereadable will affect any backup files generated.

filebackupformat: /files/backup.txt

would always backup the file to /files/backup.txt

filebackupformat: /files/%yyyy%%mmm%%dd%backup.txt

would backup to /files/19980801backup.txt on 1 August 1998.

This specifies the maximum size a soupermail generated file can grow to in bytes. If a new addition would cause the generated file to grow over filemaxbytes, then the file will be cleared of all other entries.

If you would like to save backup copies of the file, rather than simply deleting it, specify a filebackupformat as described above.

To force a deletion after each entry, set the filemaxbytes to 1. Note that setting it to 0 (zero), effectively resets filemaxbytes, and so has no effect.

filemaxbytes: 10000
If you want to store the data from a form encrypted, you can use filepgpuserid to securely store data.

Will store data encrypted for

When writing form data to a file, the file is usually kept unreadable by the webserver. By setting filereadable, the file can be made readable by the webserver.

Note that this only affects people reading the file from a web browser, it does not secure the file from other types of access (eg. from FTP or through the filesystem). So, don't go storing credit card numbers in a file unless you're damn sure that your machine's secure.

filereadable : yes
A template file which determines how a set of form data should be written to the file specified by fileto. See the section on TEMPLATES for more information.
The filename that the contents of a form should be written to. The path is either relative to the location of the configuration file or an absolute path from the web server's root.
fileto : output/out.txt

If no filetemplate is given, the output form a form is written as a series of lines matching:

name = value[,value ...]

Where a form field has multiple values, these are listed separated by commas.

This is a plain text file that can be placed at the end of files specified by fileto.
A URL for a page to redirect the user to if their form entry was blank. Unlike the blank field, the file is not a template, and so should not contain <output> elements. CGI variable replacement can be used in the value of gotoblank to achieve PIPELINING.
gotoblank : http://myserver/errors/blank.htm
A URL for a page to redirect to if the form has past its expires date. CGI variable replacement can be used in the value of gotoexpires to achieve PIPELINING.
A URL for a page to redirect the user to if their form entry did not contain all the required fields. Unlike the failure entry, this is not a template and should not contain <output> elements. CGI variable replacement can be used in the value of gotofailure to achieve PIPELINING.
gotofailure : http://myserver/errors/failed.htm
A URL for a page to redirect the user to if their form entry was successfully completed. Unlike the success field, this is not a template and should not contain <output> elements. CGI variable replacement can be used in the value of gotosuccess to achieve PIPELINING.
gotosuccess : http://myserver/forms/success.htm
It is possible to use the GNU Privacy Guard program rather than PGP. If you do use it, then set gnupg to yes in your configuration. If you do not, then Soupermail will assume encryption is using PGP. This command is now deprecated in favour of pgpversion.
This is a plain text file that can be placed at the start of files specified by fileto.
The HTML email template to use for the MAILING LISTS function. This and/or a listtemplate must be used for mailing lists to work.
This option allows you to send mail formatted in HTML. Only the HTML is sent, images are not encoded or sent. All relative links from the HTML will be from the location of the config file on the server. Probably the best thing to do with HTML templates is use absolute URLs for images and suchlike.

If you specify both htmlmailtemplate and mailtemplate a mixed text and HTML message is generated. This will allow people who don't have HTML capable mail clients to read your mail.

In the same way as htmlmailtemplate is sent to the mailto address, this template is used when sending mail to the submitter of the form. It behaves in the same way as htmlmailtemplate when it comes to link handling.
If your HTML forms contain hidden fields, you can ignore them so that you can check for situations where the user doesn't complete any fields. Only one form field can be specified on an ignore line. Use multiple ignore lines if you wish to ignore more than one field. The soupermail special form variable SoupermailConf is ignored automatically.
ignore : hidden1
ignore : hidden2

This would ignore the values of fields 'hidden1' and 'hidden2' when determining if a form was left blank.

A conditional statement used to set configuration values based on the user's form input. See the section on CONDITIONAL STATEMENTS for more information.
if : (division eq 'Accounts') then mailto :

This would set mailto to if the form contained a field called 'division' and its value was 'Accounts'.

This is used to validate a form field to see if its a credit card number. The check performed is a basic Luhn checksum, and doesn't check card ranges.
If you have a field called 'creditc' in your form, and want to validate it, use:

iscreditcard: creditc

If the validation fails, the failure template is activated. Validation will not fail if the field is left blank.

This is used to validate a form field is an email address. If the validation fails, the failure template is activated.
This is used to validate a form field is an integer. If the validation fails, the failure template is activated.
Behaves in the same way as the isinteger option, and validates a form field as a number.
Used to check is a form field is NOT a credit card number.
Used to check is a form field is NOT an email address.
Used to check is a form field is NOT an integer.
Used to check is a form field is NOT a number.
This defines an attachment that is sent from the server to each mail sent to the mailing list. Its syntax is the same as that of attachmentX.
This is the MIME type for an attachment sent to the mailing list. See attachmentXmime for the syntax.
When HTML email is sent to a mailing list, Soupermail inserts a Content-Location email header based on the submitting form's URL. Use this option to modify it for your own needs. Similar to senderbase and mailbase.
The email address to use in the From: field for emails sent out using Soupermail's MAILING LISTS function.
Sometimes, you may want to send emails to a mailing list sent to the form through a form field. This config command says which form field contains this data.
When email is sent out with Soupermail's MAILING LISTS function, the Precedence mail header is set to prevent mail loops. It can take one of three possible values; list, junk and bulk. By default, the Precedence value is list.
The email address to use in the Reply-To: field for emails sent out using Soupermail's MAILING LISTS function.
The data for a mailing list can be pulled from a SQL database as long as the sqlname, sqluser, sqlpassword and appropriate sqlbind values have been set. listsql is an SQL command in the same format as sqlrunX commands.

The data returned from the SQL statement must have the user's email address as the first column.

The Subject: line to be used for emails sent out using the MAILING LISTS function.
The plain text message template to use for the MAILING LISTS function. This and/or a htmllisttemplate must be specified for a mailing list to work.
When HTML email is sent to the mailto address, Soupermail inserts a Content-Location email header based on the submitting form's URL. Use this option to modify it for your own needs. Similar to senderbase and listbase.
mailbase :
This defines the character set to send email as. It defaults to iso-8859-1.
This option is the location for a MAILING LISTS file.
maillist : /forms/config/mynames.csv
A template file to use when formatting the outgoing email. See the section on TEMPLATES for more information.
mailtemplate : /forms/config/mail.tpl
A comma separated list of email addresses to send the results of the email to.
mailto :,,
When set, Soupermail will allow file uploads from web browsers using RFC1867 and will attach the uploaded files as MIME attachments on resulting emails.
mimeon : yes

This would allow MIME attachments to be sent.

When saving results to a file, it is sometimes useful to remove newline characters from the results. Setting nofilecr will do this.
nofilecr : yes

This would remove newline characters from fields written to a file.

Do not display the hostname and IP address details at the foot of each outgoing email.
nomailfooter : yes
This is a lout template file that will be processed into a PDF and returned to the browser. If you want to use this option, don't specify a success template in your config file. See the MAKING PDFs section for more details.
This is a lout template file that will be processed into a PDF and returned to the mailto email recipient as an email attachment. It can be used in conjunction with mailtemplate and htmlmailtemplate.
This is a lout template file that will be processed into a PDF and returned to the email address given in the Email form field. It can be used in conjunction with sendertemplate and htmlsendertemplate.
By default, Soupermail will send PGP messages as a multipart/encrypted MIME message (as per RFC 2015). However, not all PGP mail plugins recognise this format (eg, the Pegasus mail PGP plugin). Setting pgpmime to no will not encapsulate the PGP message in MIME headers.
If set to 'no', then PDF's generated with Soupermail are NOT encrypted when sent. Instead, they are attached to the encrypted content of the email. The default behaviour is to encrypt PDFs.
This is the port number of a HTTP PGP 5 keyserver. The default port is 11371. The hostname for the server is specified with pgpserver below. See the section on USING PGP for more information.
This is the hostname of a HTTP PGP 5 keyserver to get PGP keys from. See the section on USING PGP for more information.
pgpserver :
If set to 'no', then uploaded files are NOT encrypted when sent. Instead, they are attached to the encrypted content of the email. The default behaviour is to encrypt uploaded files.
A user in the public keyring which outgoing email should be encrypted for. See the section on USING PGP for more information.
pgpuserid :
From version 1.0.8, this is the prefered mechanism for selecting the type of encryption to use. Values for this can currently be 'gpg', 'pgp2' and 'pgp5'. By using this field, future versions of PGP and GNUPG can be supported.
A format for a reference number to be generated and used as the http_ref CGI variable. See the sections on CGI VARIABLES and FORMATS for more information.
ref : REF%yy%%mmm%%dd%%rrrr%

This may generate a reference like: REF9704016364 on April 1 1997

An email address that will be used in the Reply-To: mail header.
replyto :
A boolean expression which determines which form fields must be completed. The entry is composed of field names separated by && (AND) and || (OR) operators. See the section on Boolean Expressions for more details.
required : ((name && address) || telephone)

The above expression requires either the fields name and address to be completed, or the field telephone to be completed.

This will CC the sender of the form a copy of the email message sent as a result of the form. This requires the form to have a field called Email (case sensitive), which is assumed to be the sender's email address.
returntosender : yes
When HTML email is sent to the submitter of a form, Soupermail inserts a Content-Location email header based on the submitting form's URL. Use this option to modify it for your own needs. Similar to listbase and mailbase.
This is a comma separated list of email addresses to blind carbon copy on the email sent to the form's sender when a sendertemplate is specified. See also bcc.
When using a sendertemplate, the email address used in the email back to the form's sender is set to this. The preferred order email addresses are chosen for the sender's From field is:

This field is useful if you need an auto-reply function from your form, but don't want to obviously expose the mailto address directly to the sender of a form.

An email address that will be used in the Reply-To: mail header for mails sent with the sendertemplate config option.
Used in conjunction with sendertemplate, this is a subject line only to be used in email messages send directly back to the form's submitter. If its not set, the subject line set with the subject config line is used.
This is a template file for an email to be sent back to whoever submitted the form. It takes the email address to send this to from the Email form variable. The From field of the email is set to either the mailto or replyto configuration values. See the section on TEMPLATES for more information.
This sets the value of a counter prior to any templates being filled based on the counter's onsuccess, onfailure, onblank and onexpires config values.
Using the sqlbind command allows you to specify a variable that will be used in the next SQL statement specified by a sqlrunX command.
sqlbind2: "$form_second_field"
sqlrun1: SELECT * FROM TABLE WHERE field1 = ? AND field2 = ?

In this example, the value of the form field "second_field" is used to replace the second question-mark value in the SQL statement.

Binding does all the character escaping needed by the SQL, so there is no need to enclose strings in single quotes.

This is the DBI name for the next database connection you will use. You can use multiple connections during the course of a config file. The format for the name is the normal DBI format.
sqlname: dbi:mysql:database=test;
This is the connection password that will be used for the next SQL command run in the config file. Usually used with sqluser.
sqlpassword: my_random_password
Multiple SQL statements can be executed in a config file, and each statement is defined by a sqlrunX command. Statements are executed in the order they are seen in the config file, working from top to bottom.

The number at the end of the sqlrunX name is used to identify the results of the command for later use in the config file and in templates.

Variables that you want to use in your SQL command that come from form, cookie or counter data must be passed in by binding the values. Binding involves using a question-mark character to represent a variable, and setting a sqlbind command to indicate something to use.

sqlbind1: "$form_name"
sqlrun1: SELECT id FROM users WHERE name LIKE ?

The bind command attaches the value of the form field to the first question-mark in the next SQL statement. In this case, if the value of the form field 'name' was 'fred', then the SQL command would become:

SELECT id FROM users WHERE name LIKE 'fred'

For security reasons SQL commands will not run if there are required, or invalid field types.

This is the username to use when connecting for the next SQL statement. Usually used with sqlpassword.
sqluser: root
A subject line to use on resulting emails.
subject : This is a feedback email
A template file to return through the web browser if the form was correctly submitted. See the section on TEMPLATES for more information.
success : /forms/config/success.tpl
This allows you to specify a specific MIME type for the data returned back to the browser by the success template. Values given here should be of the form word/word. Its related to the failuremime, blankmime and expiresmime config commands.
successmime : text/xml; charset=utf8
This has an identical format to the if command, but performs the opposite of what the if tests do. Using this, you can check for when values are not set. See the section on CONDITIONAL STATEMENTS for more information.
The number of characters to wrap the soupermail emails to.
wrap : 60

Sometimes it is useful to concatenate some of the configuration values, for instance where you need to specify more that one mailto recipient based on the user's input. In order to do this, you can use the following variables in you configuration files:

This is the current value of mailto in the configuration. This will be expanded to the value when the configuration is parsed.
mailto :
mailto : "$mailto,"

This example initially sets mailto to Then it sets mailto to, Notice that the expansion occurs only if the value is enclosed in double quotes (").

This is used to get the current value of subject
subject : Feedback of type - 
if (feedtype eq 'comment') then subject : "$subject Comment"
if (feedtype eq 'problem') then subject : "$subject Problem"

This example changes the subject based on a field in the original form called 'feedtype'.

This is used to get the current value of the replyto field.
replyto :
if : (interested has 'rod') then replyto : "$replyto,"
if : (interested has 'jane') then replyto : "$replyto,"
if : (interested has 'freddy') then replyto : "$replyto,"

If the form contained a set of checkboxes all called 'interested' with the values of 'rod', 'jane' and 'freddy', this configuration will add the email addresses of rod, jane and freddy depending upon which checkboxes were set by the user.

CGI variables
It is possible to use all of the CGI VARIABLES listed below by placing a '$' character before their name.

will return the web browser name.

Form Variables
It is possible to use any value from a form by placing '$form_' before the form variable's name.
If a form has a field called 'TheirName', then the following could be used in the configuration file:

Subject: "Form response from $form_TheirName"

Cookie Variables
In the same way as its possible to use form variables, cookie variables can be inserted by putting '$cookie_' before the cookie's name. See the section on COOKIES for more information.
Subject: "The cookie named Bungle has value $cookie_Bungle"

Replacements can only be used when setting the subject, mailto, replyto, reference number and cookie value fields.

Replacement value will only be used when they are enclosed in double-quotes. So, the following will NOT work:

Subject: This is a non-working mail to $mailto

However, this will work:

Subject: "This is a working mail to $mailto"


Conditional statements in configuration files allow you to control the configuration of a form based on the user's form input, values from a users cookies or any of the http_ variables. A conditional statement is made up of a boolean expression followed by a configuration statement.

if : boolean_expression then configuration_statement


unless : boolean_expression then configuration_statement

The only configuration statement disallowed in a conditional statement is another if or unless.

Conditional statements are executed in the same order that they appear in the configuration file.

Boolean Expressions

A boolean expression is something that can either be true or false. If it's true, then the configuration statement is set, otherwise it isn't.

The simplest boolean expression is just the name of a form field. If the form field was completed by the user, then the boolean is true.

If you have a form that contains and input field called 'name' and you want to set the subject line based on this name being set, you could use the following configuration statements:
subject : They haven't set their name
if : name then subject : They have set their name!

Initially, subject is set to 'They haven't set their name'. However, if the 'name' field is completed on the form, the conditional statement is activated and the subject is reset to 'They have set their name!'.

If you want to check on cookies, prefix the cookie's name with $cookie_. So, if you wanted to test if the user had sent a cookie called "MyName", use a condition like this:

if: $cookie_MyName then Subject: "Cookie MyName was set to $cookie_MyName"

Boolean expressions in soupermail use three basic operators, AND (&&), OR (||) and NOT (!). An expression with an AND in will be true if BOTH of the things around the AND are true. An expression with an OR in will be true if one or more of the things around the OR is true. An expression preceded by a NOT will be true if the thing following it is false.

x && y will be true if x is true and y is true

x || y will be true if x is true or y is true

x && y || z will be true if x and y are both true, or x is true.

!x will be true if x is false.

Boolean expressions can contain any number of smaller boolean expressions. To make life easy, you can group these with brackets "(" and ")".

You have a form containing the fields 'name', 'address', 'telephone', 'fax' and 'Email'. You want to know that name has been filled in and that they have supplied an address or telephone or email. The following boolean expression could be used:

name && (address || telephone || Email)

Notice the use of brackets, to enclose the ORs. If the brackets were missed out, the expression would have meant the user must complete their name and address, or their telephone, or their email; or as a boolean expression:

(name && address) || telephone || Email

This is because AND is considered to be more important than OR.

If you have form fields that contain spaces, you can still use them in boolean expressions, but you must enclose them in double quotes (").

You have a form containing:

<input type="text" name="First Name">

Any boolean expression using this field name must use it quoted:

"First Name"

Other operators available in boolean expressions are:

Numerical equality
if : age == 45 then subject : You are 45
Numerical inequality
if : age != 50 then subject : You are NOT 50
Numerically less than or equal to
if : age <= 50 then subject : You are younger than 51
Numerically greater than or equal to
if : age >= 50 then subject : You are older than 49
Numerically less than
if : age < 50 then subject : You are younger than 50
Numerically greater than
if : age > 50 then subject : You are older than 50
String equality
if : name eq 'Humphry' then subject : You are called Humphry
String inequality
if : name ne 'Humphry' then subject : You are NOT called Humphry
String less than or equal to
String greater than or equal to
String less than
String greater than
A string value is equal to something in a multivalue field
A string value is not equal to something in a multivalue field
A string value exists inside, or is equal to another value. It is case-insensitive.
if : name contains 'on' then subject: Your name contains the letters on

The above example would match names such as "Ron" or "Donna".

Returns true if the value to the left is made of more characters than the value to the right.
if : name longerthan 5 then subject: Your name has more than 5 characters
Returns true if the value to the left is made of less characters than the value to the right.
if : name shorterthan 5 then subject: Your name has less than 5 characters


Soupermail uses a series of templates specified by the configuration file to control the output, either to the screen, a file or to email. All the template locations should be specified relative to the location of the configuration file, as absolute paths (things starting with a '/' character) from the web server's root, or as private paths (things starting with a '~' character). The basis for a template are the HTML-like elements called <output>, <only> and <loop>.

Templates can be used for emails, files and pages returned to the browser. Templates returned to the browser can be given different MIME types, meaning you can return things like WML for WAP sites.

When sending HTML email templates, you can set the base for images embedded in the email with the listbase, mailbase and senderbase commands.

The <only> element defines a block in a template to use if its if attribute is matched. The if attribute should contain a boolean expression. See Boolean Expressions for more information about what the if attribute can contain.

<only if="month == 12">

Its December, so here's December's calendar:

<!--#include virtual="dec.txt"-->


<only> elements cannot be nested, but they can contain any number of <output> elements and includes.

<loop> elements allow one part of a template to be repeated multiple times. Using loops, you can repeat a section of template a fixed number of times, or loop through the values of form field.

Loops can take five attributes:

If you need to control when a loop starts, the start attribute sets the initial value of the loop. This can be any number.
This is the final value of the loop. It can be any number. If the value of end is greater than the value of start, the loop counts forward in steps of one. If the value of end is less than the value of start, the loop counts backward in steps of minus one.
Each time Soupermail goes through a loop, you can take the current value of the loop, and use it in the template. To get the value, you need to refer to it by the loop's name.

To get the value out, surround the loop's name by @ characters inside the loop block.

<loop name="loopvalue" start="1" end="5">

This loop will return '1 2 3 4 5'.

The default step in loops between the start and end values is one. With the step attribute, you can change this value. Step can take any number as a value.
<loop name="loopvalue" start="1" end="5" step="2">

This loop will return '1 3 5'.

When you need to use a loop to run through the multiple values of a form field the field attribute is used to specify which field to loop with.
If you have a SELECT element in your form like this:
<select multiple="multiple" name="multiselect">
<option>value one
<option>another value
<option>yet another value

you can use the following loop to get the values:

<loop name="selectfield" field="multiselect">
One of the values is @selectfield@

The <output> element can be considered as analogous to the HTML <input> element.

Where an <output> element appears in a template, Soupermail replaces it with some appropriate text. The value of the replacement text depends upon the attributes specified in the <output> element.

Attributes for output

The following is a list of attributes that can be placed in template <output> elements.

This field is alternative text to replace the <output> element with, if the field name wasn't filled in on the original form.
Usually, the value of the name attribute is replaced in the <output> element. However, using altvar, another variable can be used if name hasn't a value.
Supposing you have a field called 'month' that you want to default to the current month if it's not filled in in the form. The following could be used:

<output name="month" altvar="http_date" format="%mmm%">

This can take the values of upper or lower and will upcase or downcase the thing returned by the output element.
Sometimes, you need to change one character in a string to another; for instance, escaping quote marks when saving a CSV file. The charmap attribute allows a character to be changed to a string (or removed). The format for the charmap attribute should be the character to change, followed by a comma, followed by the string to change it to.
To double up quote marks for a CSV file, use something like:

<output name="fieldname" charmap='",""'>

To remove all occurrences of the letter 'a':

<output name="fieldname" charmap="a,">

To turn underscores into hyphens:

<output name="fieldname" charmap="_,-">

This is used to check the type of data in the form field. The data attribute can have the following values: number, notnumber, integer, notinteger, email, notemail, creditcard, notcreditcard

If the check fails, then the output element will return its alt value.

Here are some examples for a form field, 'foo', with a value of 6.5:

<output name="foo" data="number" alt="fail" sub="pass"> = pass

<output name="foo" data="integer" alt="fail" sub="pass"> = fail

<output name="foo" data="notnumber" alt="fail" sub="pass"> = fail

<output name="foo" data="notinteger" alt="fail" sub="pass"> = pass

<output name="foo" data="email" alt="fail" sub="pass"> = fail

The credit card check is a simple LUHN checksum that makes sure the number given looks like a credit card number. It does not mean the number is a real card number, or that there's any money in the account.

A text string to display between items in a text list.
A format to specify how certain variables are formatted when displayed. Only applies to http_time, http_date and http_ref.
This is a string to indent the substituted text with. Its mainly useful for email templates, where you may want to indent the contents of an HTML textarea element.
When an <output> element is replaced by a multivalued form field, Soupermail's default behavior is to output a HTML <ul> list, or text list. By setting the list attribute to ul|ol|menu|dir|text, a specific type of HTML list can be achieved. The text value will return a non-HTML text list. The format of this text list can be controlled by the delim attribute.
You can use simple maths expressions using this attribute. You can use form, cookie and http values in the math expression, and they will be replaced before the expression is evaluated. Values that are undefined or non-numeric are replaced by zero. If the name attribute is multi-valued, the math expression is evalued for each value.

The following are the maths operators available:

summation of a multiple valued field
count of a multiple valued field

To add two fields together:

<output name="field1" math="field1 + field2">

To calculate an average of a number of fields:

<output name="field1" math="(field1 + field2 + field3) / 3">

This should correspond to a field name from the HTML form, a CGI Variable available from Soupermail a cookie name, a counter value, a mailing list value or a SQL value. CGI variables start with 'http_', counter values start wit 'counter_', cookie values start with 'cookie_', mailing list values start with 'mailist_' and SQL values start 'sql_'. This field is case-sensitive.
This allows newlines to be represented as either HTML or removed from the value. If newline has the value html, then newline characters are converted to <br> tags. If it has the value of none, then newline characters are replaced by spaces. If it has a value of unchanged then newlines are left as is. The value of paragraphs replaces breaks of more than 2 newlines with only 2 newlines - useful for formatting plain text entries.
This is text to be post-pended to the value of the field name if the field was set in the original form. It isn't used with the alt or sub attributes. For multivalue entries, the post section is placed after each list item.
This is text to be pre-pended to the value of the field name if the field name was set in the original form. It isn't used with the alt or sub attributes. For multivalue entries, the pre section is placed before each list item.
Used in conjunction with the math attribute, this value is the number of decimal places to display numbers to.
This is text to replace the output field with if the field is set in the original form.
This is similar to the altvar attribute, but comes into play when the variable set be the name attribute has a value.
This is used for providing a time offset when outputting http_time and http_date values. Values should be of the form:


Where, the initial plus and minus indicate the direction of the offset, num represents how much to offset by, and s indicates an offset in seconds, m an offset in minutes, h an offset in hours, d an offset in days, M an offset in months and y an offset in years.

If type is set, it can be one of escaped, unescaped, html or unescapedhtml. Escaping output tags is useful if you want to pass form values between forms in hidden form fields. Escaped output tags are URL encoded, so characters such as < and " don't appear. When you want to get the user's original values, use the unescaped or unescapedhtml types in an output tag. The html type is useful for displaying values in HTML templates where a user may have typed in HTML characters such as < or >.
If you have a field like this:

<input type="text" name="val">

and this in a template:

<input type=hidden name=val value="<output name="val">">

and the user's typed something like this into the field:

The "sum" is > than the "parts"

If you don't escape the output tag, you get broken HTML like this:

<input type=hidden name=val value="The "sum" is > than the "parts"">

However, if you used <output name="val" type="html">, you'd get:

<input type=hidden name=val value="The &amp;#34;sum&amp;#34; is &#62; than the &amp;#34;parts&amp;#34;">

which is HTML safe.

Usually, if the thing set by name has a value, it is returned by the <output> element. However, if value is set, it is only returned if its value equals that of value. The alt attribute will become active if the values do not match and the sub attribute will become active if they do match. This may sound pretty daft, but its useful for regenerating drop down lists in multipart forms. See the Multipart form example that comes with Soupermail.
Similar to the value attribute, but affects the use of altvar and subvar replacement.
An integer specifying how many characters to wrap the output value to. Wrapping occurs after any maths, charmap or HTML conversions have been applied to the value, but before the PRE and POST attributes take effect. This attribute is useful for formatting HTML textarea elements.

SSI Like Includes

Server Side Includes (SSI) are a means of dropping one file into another before sending a page onto the user's browser. Soupermail can provide a basic inclusion mechanism using the same syntax as normal SSI directives. Soupermail will only handle <!--#include virtual="..."--> type includes, #exec is too much of a processing burden. The path can either be an absolute path from the server's root, or a path relative to the location of the config file.

If you are putting the include into a HTML page, and don't want characters like < to be specially treated by the browser, then you should put the type="html" attribute in the include call: <!--#include virtual="..." type="html"-->. ALWAYS do this if you do not trust the source of the include.


CGI variables are set by the web server, and in some specific cases, Soupermail. These names should not be used as field names in your HTML forms.

The value of the counter named X
The time at the web server.
The date at the web server.
The URL of the calling form.
The hostname of the person sending the form.
The IP address of the person sending the form.
The name of the webserver.
The port number the webserver is listening on.
The type of browser used to send the form.
A soupermail generated reference number.
The username if the form was password protected.
Not sure, but some browsers set it.
The server name the browser thinks its at.
A browser specific variable
The last error message set in the config file with the error config command.
The path from the web server's root to the configuration file that was used to generate the page. This can be very useful when generating multipart forms, where you want to keep your directory structure portable by using relative links.
This is a value from the current mailist line of data. X is the column number of the data to use. Columns start at one (the email address). See MAILING LISTS for more information.


Formats allow the http_time, http_date and http_ref variables to be controlled. A format is a one line string containing the following substrings. When the <output> element is expanded, the substrings are expanded into the following:

A 4 digit year (eg. 1997)
A two digit year (eg. 97)
A three letter month code (eg. Jan)
A two digit month code
A three letter day code (eg. Mon)
A two digit day code (eg. 28)
A 2 digit 24 hour (eg. 13)
A 2 digit hour (eg. 03)
A 2 digit minute (eg. 23)
A 2 digit second (eg. 06)
Either 'am' or 'pm' depending on what the time is.
Return the epoch time for your system. On UNIX, this is the number of seconds since 00:00:00, 01/01/1970.
A random number. The length of the random number is determined by the number of r's in the format. The maximum number of r's is 12. eg. %rrr% returns a value between 0 and 999.
This is a formatting command used to break a number into a series of space delimited blocks. The number of c characters given determines how many characters to use before a space.
eg., to format a credit card number
use format="%cccc%" which would give you something like:

1234 5678 9876 5432

format="%ccc%" would give you:

123 456 789 876 543 2

Non-numeric characters are removed from the value.

This is the value of a config file specified counter. The value used is calculated after any increments or sets are performed on the counter, so it will be the same value that appears in templates. The value of X is the counter number needed. eg. %counter_3%


Counters are a way of storing and reading the number of times Soupermail has done something. They are specified in the configuration file, and you can have any number of them in use. In their simplest guise, you can use them to count how many people have submitted a form. More complex uses include setting the maximum number of times a form's submitted, online voting systems and renaming the filenames form information is saved to.

The behaviour of counters can be slightly odd for the unwary. Firstly, they are always defined in the config file, but simply declaring a counter file does not mean it gets updated, its value just becomes available for the config file and for templates. To update a counter, an onsuccess, onfailure, onblank or onexpires setting for the counter must be set.

Secondly, the value returned by a counter in the config file is the value stored in the counter file BEFORE any increments have been performed on the counter, however, the value returned in templates and the http_ref value are set AFTER increments have been applied to the counter.

counter1file: counters/count1.txt
counter1onsuccess: yes
if : ("$counter_1" == 10) then setcounter1 : 1
if : ("$counter_1" == 10) then mailto :

The above example would result in counter1 being set to 1 and the mailto address set to whenever the counter reached 10. Note that even though the setcounter1 is set in the config file, it does not have an immediate effect, and does not prevent the second if statement being used.


Cookies were introduced in Netscape Navigator 2.0. They are a means of storing information on the user's browser even after they've turned off their computer. Soupermail allows up to nine cookies to be set, each cookie holding at most 516 characters worth of data, and with a cookie name less than 50 characters long. The restriction on the cookie size and number of cookies is mainly out of politeness, because its not considered nice to flood users with cookies.

More information on cookies can be found at


PGP is a means of encrypting text through a public key and decrypting through a private key. Using PGP, Soupermail can send secure encrypted email over an insecure Internet.

To use PGP, you will need to place a public keyring (pubring.pkr for PGP 5, pubring.pgp for PGP 2.6.3 or pubring.gpg for GPG) in the directory where your form's configuration file is located. In your configuration file, set pgpuserid to be a user in the pubring keyring. When soupermail generates an email, it will encrypt the message using the public key of the given user. By default, this version of Soupermail assumes that GPG is being used.

As of Soupermail 1.0.3, GNU Privacy Guard (GPG) is supported as an alternative to using PGP. Using GPG rather than PGP differs only in that the public keyring file is called pubring.gpg. The pgpversion config option must be set to choose between the different encryption methods. See the GPG documentation for more information.

If you have problems using PGP or GPG, make sure your webserver has the ability to run the scripts - some server installations may not give the nobody user rights for this. Generating a debug file is the best diagnostic option.

Versions of Soupermail greater than 1.0.8 have support for PGP 5.0i and 2.6.3i (I've only tested the international versions so people using US versions may have different results).

You can also specify a PGP keyserver in the configuration file. If specified, the PGP encryption will look on the key server for encryption keys. THE PGP KEYSERVER CODE IS EXPERIMENTAL AND HASN'T BEEN TESTED! USE AT YOUR OWN RISK!

For more information on PGP, please look at

For more information on GPG, please look at


From version 1.0.7, Soupermail can generate Adobe PDF files by hooking up to lout and ghostscript.

Lout is a nifty document formatting language, which is used to generate postscript files. Ghostscript is a postscript processor which can generate PDF files (amongst other things).

To use this feature, you're going to have to look into how lout templates work. Its a powerful language, so spend some time delving though the documentation that comes with lout. Basically, Soupermail hooks into lout by allowing you to use <output> elements in lout templates. Soupermail reads the lout templates you specify with the pdftemplate config options, fills in the <output> elements, then passes this on to lout and ghostscript to handle. The results can be emailed out, or returned to the browser depending on the config options you have used.

One of the nice things about using lout and ghostscript together is the ability to include EPS images in your generated PDFs. To do this, place your EPS files in the same directory as your lout templates and use lout's include image command in your templates. Soupermail assumes that EPS files end in a .eps file extension.

The Soupermail example files contain an example of using Soupermail's PDF commands.

To use the PDF commands, you'll need to install GhostScript from and Lout from


Version 1.0.7 of Soupermail brings along mailing lists, which are ways of sending Soupermail generated email to a set of people defined in a file. To do this, you should specify a maillist file in your form's configuration. The maillist file should be a set of lines, each one starting with and email address, and with other optional columns following, separated by commas.

eg.,Mr Foo,nothing special,"Bloggs, Fred",geezer,XYZ Man,unable to think of a better name,other stuff

As you should see from the example, there can be any number of extra columns of data in the file. When Soupermail is given a mailing list file, it generates an email for each address in the file based on the listtemplate and htmllisttemplate config options. However, these templates can also take data from extra columns in the maillist file and use them in <output> elements.

From our previous example, if the listtemplate contains the following:

Hi <output name="maillist_2">, Email: <output name="maillist_1">

Then the email sent out to would contain:

Hi Mr Foo, Email:

the email sent out to would contain:

Hi Bloggs, Fred, Email:

and the email sent out to would contain

Hi XYZ Man, Email:

Email addresses and other column data is not shared between the email addresses in the list. However, if your list is private, you should ensure it isn't browsable from the internet.

Sometimes, you don't have your mailing list data in a file - to handle this, there are two other sources of list information. It is possible to pull list information from a form field using the listformfield config command to provide the list data. The format of the list data provided by the form field should be the same format as for the data file - ie. email as the first field, with other fields separated by commas.

Even more useful, it is possible to pull mailing list information from a SQL database by using the listsql command. This specifies a SQL statement which returns a table, the first field of which should be an email address.

It is possible to attach files to emails sent out with a mailing list using the listattachmentX and listattachmentXmime commands.

Other list config commands are: listsubject, listfrom and listreplyto.


Pipelining Soupermail allows you to use Soupermail to process a form and then send on the original information to another URL for processing. This is useful if you want to use Soupermail as a logger, or as a quick email function to another web application.

To use pipelining, you need to use the gotosuccess, gotoblank, gotofailure and gotoexpires config commands. These commands usually specify a URL to go to once Soupermail has finished, but they can also be used dynamically by using variable replacement of CGI VARIABLES.

Once Soupermail's finished, I want to send the form onto a page with the field foo set to the word bar. I can do this with the following:


Now though, suppose I want to send whatever the user typed into one of my form fields (eg. myfoofield). I can use the following:

success: "${form_myfoofield}"

Some things to notice; The value of the config command has been wrapped in double quotes - this allows CGI value replacement to happen. The CGI value replacement is wrapped in { } braces - this makes it easier to distinguish the value.

What about sending multiple values? Well, you can have things like:


Here, foo is set to whatever value myfoofield was in the original form, and baz is set to whatever value the cookie myBazCookie has. The ampersand (&) character is used to separate the values.

For those of you who may be doing advanced pipelining, you should know that URI escaping is only done to replaced values. So, this is wrong:

foo=my value&baz=${form_baz}

The space is illegal in URLs. It should be:



As from version 1.0.8, Soupermail has included support for database access. It can be used to query, insert, amend and delete records in a database. The commands used for this are:






One important feature of Soupermail is the ability to use the values returned by SQL SELECT statements in your config files and in templates. All sqlrunX commands have an identifying number. All SQL commands that return a table populate a two dimensional array of values. Used in conjunction with the command number, it is possible to get any return value from a SQL command.

Lets say we have a table called 'test' containing these values:

Then, we have the following in our config:

sqlrun1: SELECT * FROM test

We can get values back from this by using the variable sql_[command_number]_[row_number]_[col_number]. In config files, this value should be prefixed with a $ sign.

In a config file:

if: "$sql_1_3_1" then subject: The test table has at least 3 rows

In a template:

The third field on the second row of the table test is:

<output name="sql_1_2_3"> = dash

To make use of database support with Soupermail, you'll need perl's DBI module installed, and an appropriate DBD driver for your database. This driver must support placeholders and bind values. Consult your DBD driver's manual for more information on this.


From version 1.0.8, it is possible to store configuration files, attachment files, templates and writable locations outside your webserver's document tree. This is to allow you to store information without it being viewable with a browser.

Not all ISP's will provide you with a directory outside your document tree, so you may need to ask their support staff for an appropriate location.

To call a config file in a private root, prefix the filename with a '~' character when setting SoupermailConf.

<input type="hidden" name="SoupermailConf" value="~/subscribe/sub.con">

Looks for a config file $privateRoot/subscribe/sub.con

One security restriction on private roots is that config files outside the private root cannot read data from inside the config root. ie. You can not have a config file outside the private root calling a template inside the private root. The aim of this is to save you if someone manages to write a config file on your server. See the section on SECURITY for more information about making Soupermail paranoid.


With the introduction of database support, Soupermail has become a bit of a security headache for the consciencious webmaster. Here are some tips about using Soupermail in a secure manner.

Firstly, NEVER put a database password and username in an unsecured config file. If the config file can be read by a user with a web browser, and the file contains database connection information, then you are in trouble. Use the $privateRoot Soupermail has to put your config files outside the webserver tree.

NEVER use a database user with high privileges (eg. sa, system, sys, root) to access your database via Soupermail, unless you are in a very trusted environment and you know exactly what will be going into your SQL statements.

ALWAYS ensure you are using a good random password for your database access - people's names and stuff are trivial to brute-force.

If you have a database with a network daemon, ALWAYS consider ways you can restrict access to only known hosts.

ALWAYS use requires, length checking and type checking in config files to make sure the data you pass to your SQL commands is valid.

NEVER make web writable directories in your CGI area.

ALWAYS consider how you will protect files written by Soupermail on your webserver. Protecting the files usually involves ensuring that they are safe from being read from a browser, the area being written to cannot contain executables, that there is no means of anonymously FTPing to the area and that other users on the system cannot exploit the area.

ALWAYS remove backup files and temporary files from your live sites.

NEVER transmit credit card details by un-encrypted email.

NEVER store credit card numbers un-encrypted on your webspace.

Get to know the admin staff of your server space, or, at least find your way around your service provider's support web pages. If they don't have support web pages, then worry.

If your job is to maintain your website, make sure you've read Website security is easily compromised by misconfiguration of software - if you didn't read up about it, its your fault.

Where possible, use secure communications to your webspace, rather than insecure access (eg. SCP rather than FTP, SSH rather than Telnet, encrypted pcAnywhere, etc). IMHO, this is simple common sense, but it never hurts to say it again.

When you have Soupermail installed, you should be extra careful about people being able to write config files to your system. If you are using something like a message board, it may be possible for someone to write a config file with it, and then use that config file to read sensitive pages off your website. Beware!

To help counter this, from version 1.0.8, Soupermail will not read any files from a directory containing a file called "soupermail.deny" (all lower case). This file doesn't have to contain anything, just exist. Place a soupermail.deny file in any directory that contains untrusted content. Also place a soupermail.deny in any directory that contains sensitive information (eg. ASP or PHP code containing database logon details).

For even more security, you can set the $paranoid variable in Soupermail. In this mode, Soupermail won't read any files from a directory, unless the directory contains a file called "soupermail.allow". This is the recommended approach for security conscious webmasters.


Soupermail requires perl 5.004 or better. See for where to get perl from, or if you need the Windows NT version of Perl.

To handle the CGI input, Soupermail needs Lincoln D. Stein's excellent CGI module, available from

To do anything, Soupermail needs the MIME::Lite module installed on your server. This module can be downloaded from CPAN.

To send email, Soupermail either needs a working Net::SMTP perl module installed on the server, or, if you are on a UNIX server, a working sendmail. Net::SMTP is distributed as part of the Libnet set of packages available from CPAN. For users on Windows NT, libnet is available with Activestate's Perl Package Manager.

On UNIX boxes, PGP requires PGP 2.6.3 or 5.0, available internationally from

Under NT, you can use the DOS version of PGP 5, again, available from Unfortunately, I haven't got version 6.x to work yet, so its the 16bit only.

GNU Privacy Guard is available from


Some examples are distributed with Soupermail in If anyone has any good sites with examples, please let me know.


Vittal Aithal <>


I'd would be wrong to say I wrote this all on my own, other people made my life difficult on the way, so I'd better credit them (only joking guys :) A round of applause for everyone at


Soupermail started life in late 1995 as a fairly lightweight CGI to handle emails. However, as the years went by, it began to suffer heavily from creeping featuritis, and has now grown into a monster. It started life at Unipalm PIPEX, and various copies/versions are used by a number of companies. UUNET UK ( ) maintain a copy for their WorldWeb service users, this copy escaped and worked at Ionica. However, things went a bit pear-shaped, so now it teleworks from my house or from Revolution ( ).


Success with PGP/GPG is highly variable upon platform its run on :( GPG often depends on the Entropy Gathering Daemon to generate random numbers and this may not work in a webserver user context.

CGIWrapped environments can prevent the config file location being passed in with the PATH_INFO option, and will result in a config file error unless the config location is passed in with the SoupermailConf form field.

Soupermail suffers from major bloat, but I just haven't worked up the will to cull it down. The template code really needs to be modularised out.

Empty config files return a Thank you message, although nothing has happened. Its debatable if this is correct.