Kaye and Geoff's web page documentation 

Perl script to handle formatted email

An email CGI can be simple and customised for one type of form, or generalised to handle almost any form, as is this example.

The CGI is written in Perl and is assumed to be invoked from a web server running under Unix, since Unix system calls are used. The code splits the input into fields, using the ampersand (&) to determine where each new field starts. The hidden fields from the form are used to provide a subject line for the email, set the email address and the URL of a page to display after the form is submitted. To send the email, the script opens up an email process and writes directly to it.

#! /usr/bin/perl # require 'Re_sub.pm'; # # receives a request from www passing any number of fields for emailing to anyone # the names of required fields are prefixed with req_ # # get the form information # split the imput stream into separate fields # use resub from the Re_sub.pm package to translate escaped characters # pick out the non-message fields and push the other fields into lists # $missing = ''; $message = 'Information mailed<p>No return URL provided'; $incoming = <STDIN>; foreach $item (split (/&/, $incoming)) { ($name, $value) = split (/=/,$item); $value = &resub ($value); if ($name eq "subject_fm") { $subject = $value; } elsif ($name eq "emailto_fm") { $email = $value; } elsif ($name eq "returnURL_fm") { $url = $value; } else { if ($name =~ /^req_/ && !($value =~ /[\S]/)) { $missing = substr ($name, 4); } $item = &resub ($item); push (@itemlist, "$item\n"); } } # # ensure that the email address is correct # email address validation should be included here # also that required fields are present # $email =~ s/AT/@/; unless ($email =~ /\@/) { $message = "Invalid email address: $email<p>Information not mailed"; $email = ''; } if ($missing) { $email = ''; $message = "$missing field is required<p>Information not mailed"; $url = ''; } # # mail the contents of the list # use process as a filehandle and write the array to it # unless ($subject) { $subject = 'from WWW page'; } if ($email) { open (MAILPROC, "|/bin/mail -s \"$subject\" $emailto"); print MAILPROC "Source=$ENV{REMOTE_HOST}\n\n"; print MAILPROC @itemlist; close (MAILPROC); } # # display the specified www page to return control to the user # if none then mock one up # if ($url) { print "Location: $url\n\n"; } else { print "Content-type: text/html \n\n"; print "<html> <body>"; print "<center>$message</center>"; print "</body> </html>"; } exit;

Using this CGI has a number of advantages over a simple "mailto:" hardcoded in the HTML of the form:

  • it allows the email "subject" to be set
  • it ensures consistent behaviour with all browsers on all platforms
  • it allows some fields to be declared as required and asks for the form to be redone if they are blank
  • it allows for the email address to be hidden from spammer's harvesters
  • it performs some simple formatting of the information
  • it can display a page confirming the action taken
  • it carries out simple validation checks but also tries to carry on if input is missing or incorrect

This CGI could be modified to perform any number of additional tasks; it might:

  • email different people depending on the contents
  • scan the contents for offensive words
  • record the message and information about it in a database
  • keep a count of the number of messages received
  • record information about the sender (what browser, etc.)

Only minimal checking of the input is carried out in the code above. A working version of the program should validate all the input fields, especially the email address. This could include rejecting addresses with invalid characters, making sure that the format is correct (that there is one and only one '@', and no more than one '.' in a row, etc.) and checking to see if the domain is valid, and has associated MX records.