I've created a script that allows people to send messages to members of a team or band. To send a message is accessed by calling
membermailer.cgi?member_name
The script looks through a data file for the member's name, and send the message to that member if their name is in the database. If their name is not in the database, it sends the message to a designated email to be printed and given as a hard copy to the member. The data file has each on it's own line in the form of
member_name,email@host.com
I've tried to make the script as secure as possible, but I'm new enough to CGI that I don't know all the security holes, so I'd like someone to look over the script and tell me of any seen.
Also, I'd like to make so that the member_name portion is case insensitive, but have been unsuccessful. Any ideas?
In testing the script has worked well. Some of the older versions of mailx don't support the ~R, but I haven't worried too much about that because most machines have sendmail, but I created the script to accept mailx because that is all that is available on the server this was created for.
The code:
#!/usr/bin/perl
# ---- USER DEFINED AREA ----
# email to send to when member has no email address
$master_email = "rythem\@iname.com";
# address book
$email_file = "/memberemail.txt";
$document_root = "/home/users/public";
$full_path = $document_root . $email_file;
# Set this to 1 if using sendmail, 0 for mailx or mail
$exists_sendmail = 0;
# Mail Program Path
$emailer = "/usr/bin/mailx";
# Cascading Style Sheet (leave empty for no style sheet)
$css_file = "Lords.css";
# Document Title
$page_title = "Dream Team Mailer";
# Link to another page (leave text empty for no link)
$link_text = "Return to the Dream Team";
$link_file = "team.html";
# ---- END OF USER EDITABLE ----
if ($ENV{'REQUEST_METHOD'} eq "GET" {
$going_to = $ENV{'QUERY_STRING'};
print <<End_Of_Head;
Content-type: text/html
<html>
<head>
<title>$page_title</title>
End_Of_Head
if ($css_file ne "" {
print "<link rel=\"stylesheet\" type=\"text/css\" href=\"$css_file\"></link>";
}
print <<End_Of_Form;
</head>
<body>
<h1>$page_title</h1>
Welcome to our member mailer. Fill in the form below to send your message
to $going_to. Please read the privacy warning below before submitting.
<p>
<FORM ACTION="membermailer.cgi" METHOD="POST">
<table>
<tr><td>To:</td><td>$going_to</td></tr>
<tr><td>From:</td><td><INPUT TYPE="text" NAME="name" SIZE=40></td></tr>
<tr><td>Email Address:</td><td><INPUT TYPE="text" NAME="from" SIZE=40></td></tr>
<tr><td>Subject:</td><td><INPUT TYPE="text" NAME="subject" SIZE=40></td></tr>
</table>
Enter the message you have for our member:<br>
<TEXTAREA ROWS=6 COLS=60 NAME="message"></TEXTAREA><br>
<INPUT TYPE="hidden" NAME="sendto" VALUE="$going_to">
<INPUT TYPE="submit" VALUE="Send Message">
<INPUT TYPE="reset" VALUE="Clear Form">
</FORM>
<p><a href="$link_file">$link_text</a>
<p><b>Privacy Warning:</b> Some members may not have an email address in our
database. The members without addresses will have their messages sent to another
member designated to deliver your message.
<p><font size='1'>©Bullet Web Design Plus, All Rights Reserved 2002</font>
</body>
</html>
End_Of_Form
} elsif ($ENV{'REQUEST_METHOD'} eq "POST" {
read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
@pairs = split(/&/, $buffer);
foreach $pair (@pairs) {
($name, $value) = split(/=/, $pair);
$value =~ tr/+/ /;
$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
if (!$exists_sendmail){
$value =~ tr/\n\~/\n\~\~/;
}
$FORM{$name} = $value;
}
if ( open(READFILE,$full_path) ){
flock(READFILE,2);
while (<READFILE>) {
($name, $value) = split(/,/, $_);
$EMAILS{$name} = $value;
}
flock(READFILE,8);
close(READFILE);
} else {
&error_out(500,"Unable to open data file"
}
if ( exists $EMAILS{$FORM{'sendto'}} ) {
$email_out = $EMAILS{$FORM{'sendto'}};
} else {
$email_out = $master_email;
}
if ($exists_sendmail){
if (open(MAILPROG,"| $emailer -t"){
print MAILPROG <<mail_head;
To: $email_out
Reply-To: $FORM{'from'}
Subject: Mail for $FORM{'sendto'}; $FORM{'subject'}
mail_head
} else {
&error_out(500,"Unable to open sendmail"
}
} else {
if (open(MAILPROG,"| $emailer -s 'mailer' $email_out"){
print MAILPROG <<mail2_head;
~s Mail for $FORM{'sendto'}; $FORM{'subject'}
~R $FORM{'from'}
mail2_head
} else {
&error_out(500,"Unable to open mailx"
}
}
print MAILPROG <<mail_body;
------------------------------------------------------
To: $FORM{'sendto'}
From: $FORM{'name'} <$FORM{'from'}>
Subject: $FORM{'subject'}
------------------------------------------------------
Message: $FORM{'message'}
------------------------------------------------------
Sent using $page_title
mail_body
close(MAILPROG);
print <<End_Of_Head2;
Content-type: text/html
<html>
<head>
<title>$page_title</title>
End_Of_Head2
if ($css_file ne "" {
print "<link rel=\"stylesheet\" type=\"text/css\" href=\"$css_file\"></link>";
}
print <<End_Of_Form2;
</head>
<body>
<h1>$page_title</h1>
Thank you for using our team mailer. The following has been sent to $FORM{'sendto'}.
<p>
Name: $FORM{'name'}<br>
email: $FORM{'from'}<br>
subject: $FORM{'subject'}<br>
Message: $FORM{'message'}
<p>
<p><a href="$link_file">$link_text</a>
<p><font size='1'>©Bullet Web Design Plus, All Rights Reserved 2002</font>
</body>
</html>
End_Of_Form2
} else {
&error_out(500,"Invalid Request Method"
}
exit(0);
sub error_out
{
local ($status, $keyword) = @_;
print "Content-type: text/html", "\n";
print "Status: ", $status, " ", $keyword, "\n\n";
print <<End_of_Error;
<HTML>
<HEAD>
<TITLE>CGI Program - Unexpected Error</TITLE>
</HEAD>
<BODY>
<H1>$keyword</H1>
<HR>
Please contact the webmaster for more information.<br>
</BODY>
</HTML>
End_of_Error
exit(1);
}
membermailer.cgi?member_name
The script looks through a data file for the member's name, and send the message to that member if their name is in the database. If their name is not in the database, it sends the message to a designated email to be printed and given as a hard copy to the member. The data file has each on it's own line in the form of
member_name,email@host.com
I've tried to make the script as secure as possible, but I'm new enough to CGI that I don't know all the security holes, so I'd like someone to look over the script and tell me of any seen.
Also, I'd like to make so that the member_name portion is case insensitive, but have been unsuccessful. Any ideas?
In testing the script has worked well. Some of the older versions of mailx don't support the ~R, but I haven't worried too much about that because most machines have sendmail, but I created the script to accept mailx because that is all that is available on the server this was created for.
The code:
#!/usr/bin/perl
# ---- USER DEFINED AREA ----
# email to send to when member has no email address
$master_email = "rythem\@iname.com";
# address book
$email_file = "/memberemail.txt";
$document_root = "/home/users/public";
$full_path = $document_root . $email_file;
# Set this to 1 if using sendmail, 0 for mailx or mail
$exists_sendmail = 0;
# Mail Program Path
$emailer = "/usr/bin/mailx";
# Cascading Style Sheet (leave empty for no style sheet)
$css_file = "Lords.css";
# Document Title
$page_title = "Dream Team Mailer";
# Link to another page (leave text empty for no link)
$link_text = "Return to the Dream Team";
$link_file = "team.html";
# ---- END OF USER EDITABLE ----
if ($ENV{'REQUEST_METHOD'} eq "GET" {
$going_to = $ENV{'QUERY_STRING'};
print <<End_Of_Head;
Content-type: text/html
<html>
<head>
<title>$page_title</title>
End_Of_Head
if ($css_file ne "" {
print "<link rel=\"stylesheet\" type=\"text/css\" href=\"$css_file\"></link>";
}
print <<End_Of_Form;
</head>
<body>
<h1>$page_title</h1>
Welcome to our member mailer. Fill in the form below to send your message
to $going_to. Please read the privacy warning below before submitting.
<p>
<FORM ACTION="membermailer.cgi" METHOD="POST">
<table>
<tr><td>To:</td><td>$going_to</td></tr>
<tr><td>From:</td><td><INPUT TYPE="text" NAME="name" SIZE=40></td></tr>
<tr><td>Email Address:</td><td><INPUT TYPE="text" NAME="from" SIZE=40></td></tr>
<tr><td>Subject:</td><td><INPUT TYPE="text" NAME="subject" SIZE=40></td></tr>
</table>
Enter the message you have for our member:<br>
<TEXTAREA ROWS=6 COLS=60 NAME="message"></TEXTAREA><br>
<INPUT TYPE="hidden" NAME="sendto" VALUE="$going_to">
<INPUT TYPE="submit" VALUE="Send Message">
<INPUT TYPE="reset" VALUE="Clear Form">
</FORM>
<p><a href="$link_file">$link_text</a>
<p><b>Privacy Warning:</b> Some members may not have an email address in our
database. The members without addresses will have their messages sent to another
member designated to deliver your message.
<p><font size='1'>©Bullet Web Design Plus, All Rights Reserved 2002</font>
</body>
</html>
End_Of_Form
} elsif ($ENV{'REQUEST_METHOD'} eq "POST" {
read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
@pairs = split(/&/, $buffer);
foreach $pair (@pairs) {
($name, $value) = split(/=/, $pair);
$value =~ tr/+/ /;
$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
if (!$exists_sendmail){
$value =~ tr/\n\~/\n\~\~/;
}
$FORM{$name} = $value;
}
if ( open(READFILE,$full_path) ){
flock(READFILE,2);
while (<READFILE>) {
($name, $value) = split(/,/, $_);
$EMAILS{$name} = $value;
}
flock(READFILE,8);
close(READFILE);
} else {
&error_out(500,"Unable to open data file"
}
if ( exists $EMAILS{$FORM{'sendto'}} ) {
$email_out = $EMAILS{$FORM{'sendto'}};
} else {
$email_out = $master_email;
}
if ($exists_sendmail){
if (open(MAILPROG,"| $emailer -t"){
print MAILPROG <<mail_head;
To: $email_out
Reply-To: $FORM{'from'}
Subject: Mail for $FORM{'sendto'}; $FORM{'subject'}
mail_head
} else {
&error_out(500,"Unable to open sendmail"
}
} else {
if (open(MAILPROG,"| $emailer -s 'mailer' $email_out"){
print MAILPROG <<mail2_head;
~s Mail for $FORM{'sendto'}; $FORM{'subject'}
~R $FORM{'from'}
mail2_head
} else {
&error_out(500,"Unable to open mailx"
}
}
print MAILPROG <<mail_body;
------------------------------------------------------
To: $FORM{'sendto'}
From: $FORM{'name'} <$FORM{'from'}>
Subject: $FORM{'subject'}
------------------------------------------------------
Message: $FORM{'message'}
------------------------------------------------------
Sent using $page_title
mail_body
close(MAILPROG);
print <<End_Of_Head2;
Content-type: text/html
<html>
<head>
<title>$page_title</title>
End_Of_Head2
if ($css_file ne "" {
print "<link rel=\"stylesheet\" type=\"text/css\" href=\"$css_file\"></link>";
}
print <<End_Of_Form2;
</head>
<body>
<h1>$page_title</h1>
Thank you for using our team mailer. The following has been sent to $FORM{'sendto'}.
<p>
Name: $FORM{'name'}<br>
email: $FORM{'from'}<br>
subject: $FORM{'subject'}<br>
Message: $FORM{'message'}
<p>
<p><a href="$link_file">$link_text</a>
<p><font size='1'>©Bullet Web Design Plus, All Rights Reserved 2002</font>
</body>
</html>
End_Of_Form2
} else {
&error_out(500,"Invalid Request Method"
}
exit(0);
sub error_out
{
local ($status, $keyword) = @_;
print "Content-type: text/html", "\n";
print "Status: ", $status, " ", $keyword, "\n\n";
print <<End_of_Error;
<HTML>
<HEAD>
<TITLE>CGI Program - Unexpected Error</TITLE>
</HEAD>
<BODY>
<H1>$keyword</H1>
<HR>
Please contact the webmaster for more information.<br>
</BODY>
</HTML>
End_of_Error
exit(1);
}