Stories
Slash Boxes
Comments
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

use Perl Log In

Log In

[ Create a new account ]

jozef (8299)

jozef
  (email not shown publicly)
http://jozef.kutej.net/
Jabber: jozef@kutej.net

Journal of jozef (8299)

Saturday November 01, 2008
05:41 PM

CGI for sending emails

[ #37782 ]
Today I've created a CGI (below) to send feedback emails from submitted form.

I would like to use (that's why I've created it of course) but also to give it as an example.

Now I'm wondering 1. is it a good example and 2. if it's "secure" enough.

Any suggestions?

---cut---

#!/usr/bin/perl -T

=head1 NAME

send-feedback.cgi - CGI that sends email from posted feedback form

=head1 SYNOPSIS

in html:

    <form action="/cgi-bin/send-feedback.cgi" id="feedback_form" method="post">
        <fieldset>
            <span class="text label">
                <label for="name">Your name</label>
                <input name="name" type="text" id="name" size="25" />
            </span>
            <span class="text label">
                <label for="email">Tour email</label>
                <input name="email" type="text" id="email" size="25" />
            </span>
            <span class="text label">
                <label for="subject">Subject</label>
                <input name="subject" type="text" id="subject" size="25" />
            </span>
            <span class="textarea label">
                <label for="message">Message</label>
                <textarea name="message" cols="40" id="message" rows="5"></textarea>
            </span>
            <span class="submit">
                <input name="submit" type="submit" value="Submit" />
            </span>
        </fieldset>
    </form>

in Apache virtualhost:

    AddHandler cgi-script .cgi
    <Location "/cgi-bin/send-feedback.cgi">
        Options +ExecCGI
    </Location>

test from commandline:

    send-feedback.cgi message=test name=jozef subject=subj email=devnull@ba.pm.org

=head1 DESCRIPTION

=cut

use strict;
use warnings;

use CGI;
use MIME::Lite;
use Email::Address;

my $EMAIL_TO        = 'feedback@bratislava.pm.org';
my $REDIRECT_OK     = '/cgi/email-ok.html';
my $REDIRECT_FAILED = '/cgi/email-fail.html';

my $EMAIL_ADDRESS_RE = $Email::Address::mailbox;

exit main();

sub main {
    my $q = CGI->new();

    # default redirection is to _FAILED
    my $REDIRECT = $REDIRECT_FAILED;

    # get parameters
    my $name    = $q->param('name')    || '';
    my $from    = $q->param('email')    || 'devnull@ba.pm.org';
    my $subject = $q->param('subject') || '';
    my $message = $q->param('message');

    $from = "$name <$from>"
        if ($name);

    # input check
    my $input_ok = 1;
    $input_ok = 0
        if ($from =~ m/\r|\n/m);
    $input_ok = 0
        if ($subject =~ m/\r|\n/m);
    $input_ok = 0
        if ($from !~ m/^$EMAIL_ADDRESS_RE$/xms);

    # only message paramter is mandatory
    if ($message and $input_ok) {
        # create message
        my $msg = MIME::Lite->new(
            From     => $from,
            To       => $EMAIL_TO,
            Subject  => $subject,
            Type     => 'text/plain; charset=UTF-8',
            Encoding => '8bit',
            Data     => $message,
        );

        # send email and redirect to _OK if sucessfull
        $REDIRECT = $REDIRECT_OK
            if eval { $msg->send('smtp', 'localhost'); };
    }

    # redirect
    print $q->redirect(
        -uri    => 'http://'.$q->virtual_host.$REDIRECT,
        -status => 302
    );

    return 0;
}
The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.
 Full
 Abbreviated
 Hidden
More | Login | Reply
Loading... please wait.
  • At first glance, it seems secure. The biggest issue with a script that sends mail from web input is if you allow the "To" address to be controlled by the form submission. Obviously, allowing that is a recipe for spam.

    You're generating the email using a module, rather than by hand, so that should help rule out other vulnerabilities that could come if you built the email by hand.

    There might be an issue with the message body, because you're not restricting it to 7-bit ASCII. I'm not sure if MIME::Lite will do

    • the "To:" is fixed to one address, the purpose is just to collect feedback, so that people can leave notes for us.

      the encoding was a good point. The page is in utf-8, so I changed:

              my $msg = MIME::Lite->new(
                  From     => $from,
                  To       => $EMAIL_TO,
                  Subject  => $subject,
               
  • Other people have already commented on the Perl, so I'll mention the HTML.

    If it is trying to be HTML, then its invalid. If it is trying to be XHTML, then it is probably flawed in ways you don't want. I'm going to assume the latter.

    It's "post" not "POST"

    You have no block level container between the form element and its inline content. This means you can't be using valid XHTML 1.0 Strict (or anything based on it). Strict is the modern approach, it is generally wise to avoid Transitional.

    You don't have elemen

    • You are right! The SYNOPSIS is bad :-(

          <form action="/cgi-bin/send-feedback.cgi" method="POST">
              Your Name:  <input type="text" name="name" size="20" /><br/>
              Your Email: <input type="text" name="from" size="20" /><br/>
              Subject: <input type="text" name="subject" size="20" /><br/>
              Message: <textarea name="message" cols="80" rows="20" />
      • It's still weird: placing textarea inside span element is not an option you should use :-)