Simon & Matt's new Photoshop book is out now!

Photoshop CS3 Layers Bible book cover

Sharpen your Photoshop skills today!

PageKits.com Featured PageKits

Naturespace PageKit
Naturespace ($44.99)


Splash PageKit
Splash ($39.99)


See more! > >

 

How-To: Writing a simple form mailer

Level: Intermediate. Published on 11 March 2003 in Perl and CGI scripting

This tutorial will show you how to build a simple form mailer script, so that visitors can send you emails from your site. Along the way we explain some new Perl concepts, including the CGI library module.

In this tutorial we'll show you how to create a simple form mailer CGI script in Perl. A form mailer script allows you to add feedback forms to your site. Visitors fill in the forms, and the information they fill in is emailed to you.

CGI form handling can be quite an involved process. Luckily the Perl CGI module, CGI.pm, can do most of the tricky stuff for you! We'll use CGI.pm in this tutorial to build a nice simple form mailer.

Creating the form

The first thing to do is to build the HTML form that your visitors can fill in. We're going to create a very simple form that just has fields for the user's email address and their comments; however, once you've mastered the technique, you can easily add as many fields as you need to the form.

If you're not familiar with creating HTML forms, you may like to read our Building Forms tutorial first.

Here is the HTML for our simple form:


<html>
<head></head>
<body>

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

<p>Your Email Address:<br>
<input type="text" name="email_address" size="40"></p>
<p>Your Comments:<br>
<textarea name="comments" cols="50" rows="10"></textarea>

<p><input type="submit" name="send" value="Send Email"></p>

</form>

</body>
</html>

Note that our form will send two parameters to our script: one called email_address and one called comments.

Call this page something like mailform.html, and upload it to your site somewhere.

Now let's build the CGI script itself!

Sponsor message

Unlimited Autoresponders & Newsletters. 99.34% email delivered. Free support. Click Here for more info!

Using CGI.pm

CGI.pm is a Perl library module. It does a lot of the CGI "nitty-gritty" for you, which makes writing CGI scripts in Perl a lot easier!

Most Web servers these days tend to come with the CGI.pm module already installed. However, if you need to install it yourself, you can grab it here.

To use the CGI module in your scripts, you first tell Perl that you want to use it. This is done as follows:


use CGI;

Easy! :)

The next step is to create a CGI object. The CGI library is object-oriented, which means that all the functions and data to do with CGI are accessed through an object.

You can create the CGI object like this:


my $query = new CGI;

This creates a new CGI object and assigns a variable, $query, to point to it.

Note that this Perl variable name has a dollar sign ($) before it. This tells Perl that it is a scalar variable. Scalar variables can be used to store things like object pointers, numbers, and strings of text. (For more info see this tutorial.)

Note also that we are declaring the variable to be a private variable using the my operator. This ensures that the variable will only exist within this CGI script. This is a good practice to get into, and will help you to avoid problems when developing more complex Perl scripts in the future!

Printing out the HTTP header

You may remember from the Your first CGI script tutorial that CGI scripts need to output a Content-type HTTP header before anything else. It would be a good idea to print this out from our script now.

Luckily, the CGI object provides a handy way to output the Content-type header:


print $query->header ( );

(You can specify the content type between the ( ) if required, e.g. $query->header(-type=>'text/plain'); however, if you leave the brackets empty then it defaults to a content type of text/html, which is usually what you want.)

Getting the form information

Now we have our CGI object, $query, we can use it to retrieve the information that the user filled in. The information is passed to CGI scripts as parameters. To access a parameter using the CGI object, we use the following syntax:


$variable_name = $query->param("parameter_name");

So, if we want to retrieve the values of our two form parameters and store them in Perl variables, we can use something like this:


my $email_address = $query->param("email_address");
my $comments = $query->param("comments");

This code takes the values from our two form parameters, email_address and comments, and stores them in two Perl variables, $email_address and $comments.

Filtering the input

Whenever accepting data from an "untrusted" source, such as the our form, we should filter the data to ensure it doesn't contain anything malicious. For example, without filtering the data in the $email_address and $comments variables, it would be quite easy for a hacker to use our form mailer script to send out spam to thousands of people!

When writing real-world Web applications and scripts, always filter any data that the script receives from an untrusted source. This includes any data from form posts, GET variables in query strings, uploaded files and anything else that might have been created by someone, or something, you don't control.

To filter our data, let's write a couple of simple filter functions:


sub filter_field
{
  my $field = shift;
  $field =~ s/From://gi;
  $field =~ s/To://gi;
  $field =~ s/BCC://gi;
  $field =~ s/CC://gi;
  $field =~ s/Subject://gi;
  $field =~ s/Content-Type://gi;
  return $field;
}

sub filter_header_field
{
  my $field = shift;
  $field =~ s/From://gi;
  $field =~ s/To://gi;
  $field =~ s/BCC://gi;
  $field =~ s/CC://gi;
  $field =~ s/Subject://gi;
  $field =~ s/Content-Type://gi;
  $field =~ s/[\0\n\r\|\!\/\<\>\^\$\%\*\&]+/ /g;
  return $field;
}

These functions strip out anything in the data that could be used to trick our script into sending spam. filter_field is good for general data (such as our $comments variable), while filter_header_field is a bit more thorough and is suited to header data, such as the "from:" and "to:" email addresses (which are the most vulnerable to hacking).

We'll place these functions at the end of our script, and call them as follows:


$email_address = filter_header_field ( $email_address );
$comments = filter_field ( $comments );

Our input values have now been filtered against hacking attempts.

Emailing the results

Now that we have the values of our two form fields, and we know that those values won't contain any malicious text, it's time to email them to the webmaster (i.e. you!).

Most UNIX and Linux Web servers include a handy program called sendmail that you can use to send emails from your CGI scripts. (If you have a Windows server or hosting account, you'll need to ask your Web hosting company how to send emails from your CGI scripts, as the technique varies from server to server.)

To send the email, we open a pipe to the sendmail program, then output our email (including header information such as the sender, recipient and email subject) to the pipe:


open ( MAIL, "| /usr/lib/sendmail -t" );
print MAIL "From: $email_address\n";
print MAIL "To: webmaster\@yourdomain.com\n";
print MAIL "Subject: Form Submission\n\n";
print MAIL "$comments\n";
print MAIL "\n.\n";
close ( MAIL );

You'll need to change 2 things in this block of code:

  1. Change /usr/lib/sendmail to your actual path to sendmail. (Often /usr/lib/sendmail will work fine, but if it doesn't, check with your Web hosting company to find the correct path for your server.)

  2. Change webmaster\@yourdomain.com to your actual email address (the address you'd like the form results to be sent to). Note that the \ before the @ symbol is required - more about this in a later tutorial!

By the way, the line:


print MAIL "\n.\n";

prints a dot (.) on a line on its own at the end of the email. This tells sendmail that we've finished outputting the email message. sendmail will then send the email.

Thanking the visitor

Finally, let's display a short page to the visitor, thanking them for filling in the form:


print <<END_HTML;
<html>
<head></head>
<body>Thanks for filling in our form!</body>
</html>
END_HTML

The finished script

That's all there is to it! Let's put it all together so you can see the whole script. We've added comments in the code (the lines beginning with #) to help you work out which bit does what:


#!/usr/bin/perl

use CGI;

# Create the CGI object
my $query = new CGI;

# Output the HTTP header
print $query->header ( );

# Capture the form results
my $email_address = $query->param("email_address");
my $comments = $query->param("comments");

# Filter the form results
$email_address = filter_header_field ( $email_address );
$comments = filter_field ( $comments );

# Email the form results
open ( MAIL, "| /usr/lib/sendmail -t" );
print MAIL "From: $email_address\n";
print MAIL "To: webmaster\@yourdomain.com\n";
print MAIL "Subject: Form Submission\n\n";
print MAIL "$comments\n";
print MAIL "\n.\n";
close ( MAIL );

# Thank the user
print <<END_HTML;
<html>
<head></head>
<body>Thanks for filling in our form!</body>
</html>
END_HTML

# Functions for filtering user input

sub filter_field
{
  my $field = shift;
  $field =~ s/From://gi;
  $field =~ s/To://gi;
  $field =~ s/BCC://gi;
  $field =~ s/CC://gi;
  $field =~ s/Subject://gi;
  $field =~ s/Content-Type://gi;
  return $field;
}

sub filter_header_field
{
  my $field = shift;
  $field =~ s/From://gi;
  $field =~ s/To://gi;
  $field =~ s/BCC://gi;
  $field =~ s/CC://gi;
  $field =~ s/Subject://gi;
  $field =~ s/Content-Type://gi;
  $field =~ s/[\0\n\r\|\!\/\<\>\^\$\%\*\&]+/ /g;
  return $field;
}

Call this file form_mailer.cgi and upload it to your CGI scripts folder (usually cgi-bin) on your server. Don't forget to upload in ASCII mode, and to set execute permission on the file after you've uploaded it! (For more info on these points, read the Your first CGI script tutorial.)

Check your HTML form to make sure that the URL of your CGI script in the <form> tag is correct.

Finally you're ready to test your form mailer! Enter the URL of your form in your browser's address bar, then fill in your email address and some comments, and press the Send Email button. If all goes well, you should shortly receive your comments in an email!

Troubleshooting the script

If you get the dreaded Internal Server Error message, don't panic! It's probably a simple problem. Make sure your paths to Perl and sendmail are correct, and that you uploaded your file in ASCII format and set the correct permissions. If you still have problems, check that your script doesn't have any typos in, and that it looks like the version in our "The finished script" section above.

It's also a good idea to work through our Troubleshooting CGI scripts tutorial.

If your script still doesn't work, there may be some configuration problem with your server - ask your web hosting company's technical support staff for help.

The end

That's the end of this article. We hope you found it useful. If you're still stuck and would like further help, check out our online Help Forums, where you can get assistance from members of Elated and other webmasters.

Also, don't forget the free ELATED Extra Newsletter, where you can get more great Web-building articles and tips sent straight to your inbox!

If you would like to offer us feedback on this or any of our articles, please contact us. Have fun!

Top of Page

Get our free newsletter!

  • Improve your Web skills
  • Exclusive tips and tricks
  • Free bonus Web template

Sign up now!

We won't give or sell your email address to anyone, and you can unsubscribe at any time. Privacy statement