#!/usr/bin/perl ############################################################################## # FormMail Version 1.9.SM-d.pgp # # Copyright 1995-2001 Matt Wright mattw@worldwidemart.com # # Created 06/09/95 Last Modified 08/03/01 # # Matt's Script Archive, Inc.: http://www.worldwidemart.com/scripts/ # ############################################################################## # COPYRIGHT NOTICE # # Copyright 1995-2001 Matthew M. Wright All Rights Reserved. # # # # FormMail may be used and modified free of charge by anyone so long as this # # copyright notice and the comments above remain intact. By using this # # code you agree to indemnify Matthew M. Wright from any liability that # # might arise from its use. # # # # Selling the code for this program without prior written consent is # # expressly forbidden. In other words, please ask first before you try and # # make money off of my program. # # # # Obtain permission before redistributing this software over the Internet or # # in any other medium. In all cases copyright and header must remain intact # ############################################################################## # ACCESS CONTROL FIX: Peter D. Thompson Yezek # # http://www.securityfocus.com/archive/1/62033 # ############################################################################## # Version 1.9.SM-d.pgp differs from version 1.9.SM-b.pgp thus: # # - added a recip_list facility where the recip list can be held in a # # seperate list (or optionally in a config file [less secure]) so that # # email addresses don't have to appear in HTML but can instead be # # referred to as "addr1", "addr2" etc # # Config file lines consist of "addr1=fred@hotmail.com" (email address # # can be a comma seperated list if specifying more than one recipient). # # K D Tart, Skymarket, June 2003. http://www.skymarket.co.uk/ # ############################################################################## # Version 1.9.SM-b.pgp differs from version 1.9.SM-b thus: # # - if a "pgp" or "pgp_key" field is present, it calls # # /etc/support/pgpencrypt to encrypt the message before it is sent # # K D Tart, Skymarket, June 2003. http://www.skymarket.co.uk/ # ############################################################################## # Version 1.9.SM-b differs from version 1.9 thus: # # - CC and BCC capability # # Various security holes closed: # # - nasty characters stripped from certain fields (eg realname) to prevent # # spammers inserting extra recipient fields # # - < and > in returned HTML changed to < and > # # - @recipients checking changed from regular expression matching to # # exact domain / exact address string matching # # K D Tart, Skymarket, April 2002. http://www.skymarket.co.uk/ # ############################################################################## # Define Variables # # Detailed Information Found In README File. # # $mailprog defines the location of your sendmail program on your unix # # system. # $mailprog = '/usr/sbin/sendmail'; # @referers allows forms to be located only on servers which are defined # # in this field. This security fix from the last version which allowed # # anyone on any server to use your FormMail script on their web site. # @referers = ('www.safeserver.co.uk','www.your-domain.com'); # @recipients defines the e-mail addresses or domain names that e-mail can # # be sent to. This must be filled in correctly to prevent SPAM and allow # # valid addresses to receive e-mail. Read the documentation to find out how # # this variable works!!! It is EXTREMELY IMPORTANT. # @recipients = ('user@your-domain.com', 'another-domain.com'); # NEW (MORE SECURE) WAY OF DEFINING RECIPIENTS HERE: # # Spammers trawl HTML code for email addresses. Using this menthod, you can # # hide your email addresses from the spammer by inserting them in here or # # in a seperate config file. You can then specify your recipients as "addr1" # # in your HTML code; the correct address will be looked up in the # # recip_list array automatically. # # If you want to use a seperate config file, call it the same name as this # # FormMail.cgi script but replace the .cgi with .conf (eg FormMail.conf). It # # must be in the same directory as FormMail.cgi. # %recip_list = (); $recip_list{'addr1'} = 'info@your-domain.com'; $recip_list{'addr2'} = 'sales@your-domain.com'; # ACCESS CONTROL FIX: Peter D. Thompson Yezek # # @valid_ENV allows the sysadmin to define what environment variables can # # be reported via the env_report directive. This was implemented to fix # # the problem reported at http://www.securityfocus.com/bid/1187 # @valid_ENV = ('REMOTE_HOST','REMOTE_ADDR','REMOTE_USER','HTTP_USER_AGENT'); # Done # ############################################################################## $illegal_recip_str = ''; $recip_list_file = $0; $recip_list_file =~ s/^(.+\.)\w+$/\1conf/; if (-e $recip_list_file && open (RECIPLIST, $recip_list_file)) { while (defined($recipdef=)) { chomp ($recipdef); if ($recipdef =~ /^(.+)=(.+)$/) { $key = $1; $recips = $2; $key =~ s/(^\s+|\s+$)//g; $recip_list{$key} = $recips; } } close (RECIPLIST); } # Check Referring URL &check_url; # Retrieve Date &get_date; # Parse Form Contents &parse_form; # Check Required Fields &check_required; # Send E-Mail &send_mail; # Return HTML Page or Redirect User &return_html; sub check_url { # Localize the check_referer flag which determines if user is valid. # local($check_referer) = 0; # If a referring URL was specified, for each valid referer, make sure # # that a valid referring URL was passed to FormMail. # if ($ENV{'HTTP_REFERER'}) { foreach $referer (@referers) { if ($ENV{'HTTP_REFERER'} =~ m|https?://([^/]*)$referer|i) { $check_referer = 1; last; } } } else { $check_referer = 1; } # If the HTTP_REFERER was invalid, send back an error. # if ($check_referer != 1) { &error('bad_referer') } } sub get_date { # Define arrays for the day of the week and month of the year. # @days = ('Sunday','Monday','Tuesday','Wednesday', 'Thursday','Friday','Saturday'); @months = ('January','February','March','April','May','June','July', 'August','September','October','November','December'); # Get the current time and format the hour, minutes and seconds. Add # # 1900 to the year to get the full 4 digit year. # ($sec,$min,$hour,$mday,$mon,$year,$wday) = (localtime(time))[0,1,2,3,4,5,6]; $time = sprintf("%02d:%02d:%02d",$hour,$min,$sec); $year += 1900; # Format the date. # $date = "$days[$wday], $months[$mon] $mday, $year at $time"; } sub parse_form { # Define the configuration associative array. # %Config = ('recipient','', 'subject','', 'ccrecipient','', 'bccrecipient','', 'email','', 'realname','', 'redirect','', 'bgcolor','', 'background','', 'link_color','', 'vlink_color','', 'text_color','', 'alink_color','', 'title','', 'sort','', 'print_config','', 'required','', 'env_report','', 'return_link_title','', 'return_link_url','', 'print_blank_fields','', 'missing_fields_redirect','', 'pgp','', 'pgp_key', ''); # Determine the form's REQUEST_METHOD (GET or POST) and split the form # # fields up into their name-value pairs. If the REQUEST_METHOD was # # not GET or POST, send an error. # if ($ENV{'REQUEST_METHOD'} eq 'GET') { # Split the name-value pairs @pairs = split(/&/, $ENV{'QUERY_STRING'}); } elsif ($ENV{'REQUEST_METHOD'} eq 'POST') { # Get the input read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'}); # Split the name-value pairs @pairs = split(/&/, $buffer); } else { &error('request_method'); } # For each name-value pair: # foreach $pair (@pairs) { # Split the pair up into individual variables. # local($name, $value) = split(/=/, $pair); # Decode the form encoding on the name and value variables. # $name =~ tr/+/ /; $name =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; $value =~ tr/+/ /; $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; # If they try to include server side includes, erase them, so they # aren't a security risk if the html gets returned. Another # security hole plugged up. $value =~ s///g; # If the field name has been specified in the %Config array, it will # # return a 1 for defined($Config{$name}}) and we should associate # # this value with the appropriate configuration variable. If this # # is not a configuration form field, put it into the associative # # array %Form, appending the value with a ', ' if there is already a # # value present. We also save the order of the form fields in the # # @Field_Order array so we can use this order for the generic sort. # if (defined($Config{$name})) { $Config{$name} = $value; } else { if ($Form{$name} && $value) { $Form{$name} = "$Form{$name}, $value"; } elsif ($value) { push(@Field_Order,$name); $Form{$name} = $value; } } } # The next six lines remove any extra spaces or new lines from the # # configuration variables, which may have been caused if your editor # # wraps lines after a certain length or if you used spaces between field # # names or environment variables. # $Config{'required'} =~ s/(\s+|\n)?,(\s+|\n)?/,/g; $Config{'required'} =~ s/(\s+)?\n+(\s+)?//g; $Config{'env_report'} =~ s/(\s+|\n)?,(\s+|\n)?/,/g; $Config{'env_report'} =~ s/(\s+)?\n+(\s+)?//g; $Config{'print_config'} =~ s/(\s+|\n)?,(\s+|\n)?/,/g; $Config{'print_config'} =~ s/(\s+)?\n+(\s+)?//g; # Split the configuration variables into individual field names. # @Required = split(/,/,$Config{'required'}); @Env_Report = split(/,/,$Config{'env_report'}); @Print_Config = split(/,/,$Config{'print_config'}); # ACCESS CONTROL FIX: Only allow ENV variables in @valid_ENV in # # @Env_Report for security reasons. # foreach $env_item (@Env_Report) { foreach $valid_item (@valid_ENV) { if ( $env_item eq $valid_item ) { push(@temp_array, $env_item) } } } @Env_Report = @temp_array; } sub valid_email_syntax { my ($emailaddr) = @_; my $result = 0; if ($emailaddr =~ /^\w+(([-=]\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/) { $result = 1; } return $result; } sub recipients_allowed { my ($addrs) = @_; my ($addr, $user, $domain, $spec, $match); my $allowed = 1; foreach $addr (split(/[\,\;]/,$addrs)) { $addr =~ s/\s+//g; $match = 0; if (valid_email_syntax($addr)) { ($user,$domain) = split(/\@/,$addr); foreach $spec (@recipients) { $spec =~ s/^\^//g; # backward compatability with FormMail 1.9 recipient strings if ($spec =~ /\@/) { if ($spec eq $addr) { $match = 1; } } elsif ($spec eq $domain) { $match = 1; } } } if (!$match) { $allowed = 0; if ($illegal_recip_str) { $illegal_recip_str .= ", $addr"; } else { $illegal_recip_str = $addr; } } } return $allowed; } sub check_local_config { # checks through values in @recipients to make sure that domains that are spam # targets (eg aol.com) are not in the list of valid recipients as bare domains. # Recipients in these domains must be specified as complete Email addresses. # DO NOT DISABLE THIS CODE - FIX YOUR RECIPIENTS LIST INSTEAD. # Does not run if the 'bad list' file is newer than this copy of FormMail; this # is a safety feature - if extra domains are added to the bad list that are # listed in @recipents as just the domain it would stop this FormMail working. my $badlist = '/admin/formmail/bad_recipient_list'; my $result = ''; if ((stat($0))[9] > (stat($badlist))[9]) # compare file mod times { my $tempstr; if (open(BADLIST,$badlist)) { my %badlist=(); while (defined($tempstr=)) { $tempstr =~ s/\s+//g; $badlist{$tempstr} = 1; } close (BADLIST); foreach $tempstr (@recipients) { if ($badlist{$tempstr}) { $result .= $tempstr.'
'; } } close (BADLIST); } } return $result; } sub check_required { # Localize the variables used in this subroutine. # local($require, @error); my $localcheck = check_local_config; if ($localcheck =~ /\w/) { &error('bad_recipients',$localcheck); } if ($Config{'subject'} =~ /(\n|\r)/m || $Config{'recipient'} =~ /(\n|\r)/m) { &error('no_recipient'); } if (!$Config{'recipient'}) { if (!defined(%Form)) { &error('bad_referer') } else { &error('no_recipient') } } else { # This block of code requires that the recipient address end with # # a valid domain or e-mail address as defined in @recipients. # if ($recip_list{$Config{'recipient'}}) { $Config{'recipient'} = $recip_list{$Config{'recipient'}}; } elsif (!recipients_allowed($Config{'recipient'})) { &error('illegal_recipients') } elsif ($recip_list{$Config{'ccrecipient'}}) { $Config{'ccrecipient'} = $recip_list{$Config{'ccrecipient'}}; } elsif ($Config{'ccrecipient'} =~ /\w/ && !recipients_allowed($Config{'ccrecipient'})) { &error('illegal_recipients') } elsif ($recip_list{$Config{'bccrecipient'}}) { $Config{'bccrecipient'} = $recip_list{$Config{'bccrecipient'}}; } elsif ($Config{'bccrecipient'} =~ /\w/ && !recipients_allowed($Config{'bccrecipient'})) { &error('illegal_recipients') } } # For each require field defined in the form: # foreach $require (@Required) { # If the required field is the email field, the syntax of the email # # address if checked to make sure it passes a valid syntax. # if ($require eq 'email' && !&check_email($Config{$require})) { push(@error,$require); } # Otherwise, if the required field is a configuration field and it # # has no value or has been filled in with a space, send an error. # elsif (defined($Config{$require})) { if (!$Config{$require}) { push(@error,$require); } } # If it is a regular form field which has not been filled in or # # filled in with a space, flag it as an error field. # elsif (!$Form{$require}) { push(@error,$require); } } # If any error fields have been found, send error message to the user. # if (@error) { &error('missing_fields', @error) } } sub convert_chevrons { my ($str) = @_; $str =~ s/\/>/g; return $str; } sub return_html { # Local variables used in this subroutine initialized. # local($key,$sort_order,$sorted_field); # If redirect option is used, print the redirectional location header. # if ($Config{'redirect'}) { print "Location: $Config{'redirect'}\n\n"; } # Otherwise, begin printing the response page. # else { # Print HTTP header and opening HTML tags. # print "Content-type: text/html\n\n"; print "\n \n"; # Print out title of page # if ($Config{'title'}) { print " ".convert_chevrons($Config{'title'})."\n" } else { print " Thank You\n" } print " \n \n
\n"; # Print custom or generic title. # if ($Config{'title'}) { print "

".convert_chevrons($Config{'title'})."

\n" } else { print "

Thank You For Filling Out This Form

\n" } print "
\n"; print "Below is what you submitted to $Config{'recipient'} on "; print "$date


\n"; # Sort alphabetically if specified: # if ($Config{'sort'} eq 'alphabetic') { foreach $field (sort keys %Form) { # If the field has a value or the print blank fields option # # is turned on, print out the form field and value. # if ($Config{'print_blank_fields'} || $Form{$field}) { print "$field: ".convert_chevrons($Form{$field})."

\n"; } } } # If a sort order is specified, sort the form fields based on that. # elsif ($Config{'sort'} =~ /^order:.*,.*/) { # Set the temporary $sort_order variable to the sorting order, # # remove extraneous line breaks and spaces, remove the order: # # directive and split the sort fields into an array. # $sort_order = $Config{'sort'}; $sort_order =~ s/(\s+|\n)?,(\s+|\n)?/,/g; $sort_order =~ s/(\s+)?\n+(\s+)?//g; $sort_order =~ s/order://; @sorted_fields = split(/,/, $sort_order); # For each sorted field, if it has a value or the print blank # # fields option is turned on print the form field and value. # foreach $sorted_field (@sorted_fields) { if ($Config{'print_blank_fields'} || $Form{$sorted_field}) { print "$sorted_field: ".convert_chevrons($Form{$sorted_field})."

\n"; } } } # Otherwise, default to the order in which the fields were sent. # else { # For each form field, if it has a value or the print blank # # fields option is turned on print the form field and value. # foreach $field (@Field_Order) { if ($Config{'print_blank_fields'} || $Form{$field}) { print "$field: ".convert_chevrons($Form{$field})."

\n"; } } } print "


\n"; # Check for a Return Link and print one if found. # if ($Config{'return_link_url'} && $Config{'return_link_title'}) { print "

\n"; } # Print the page footer. # print <<"(END HTML FOOTER)";

(END HTML FOOTER) } } sub remove_newlines_and_other_nasties { my ($str) = @_; $str =~ s/[\(\)\<\>\015\012\014\177\000]//g; return $str; } sub send_mail { # Localize variables used in this subroutine. # local($print_config,$key,$sort_order,$sorted_field,$env_report); # Open The Mail Program if ($Config{'pgp'} =~ /\w/) { open (MAIL, "|/etc/support/pgpencrypt $Config{'pgp'}"); } elsif ($Config{'pgp_key'} =~ /\w/) { open (MAIL, "|/etc/support/pgpencrypt $Config{'pgp_key'}"); } else { open(MAIL,"|$mailprog -t"); } $Config{'subject'} = remove_newlines_and_other_nasties($Config{'subject'}); $Config{'realname'} = remove_newlines_and_other_nasties($Config{'realname'}); # addresses are now validated before they get this far #$Config{'email'} = validated_email_syntax($Config{'email'}); #$Config{'recipient'} = validated_email_syntax($Config{'recipient'}); #$Config{'ccrecipient'} = validated_email_syntax($Config{'ccrecipient'}); #$Config{'bccrecipient'} = validated_email_syntax($Config{'bccrecipient'}); print MAIL "To: $Config{'recipient'}\n"; if ($Config{'ccrecipient'}) { print MAIL "CC: $Config{'ccrecipient'}\n"; } if ($Config{'bccrecipient'}) { print MAIL "BCC: $Config{'bccrecipient'}\n"; } print MAIL "From: $Config{'email'} ($Config{'realname'})\n"; # Check for Message Subject if ($Config{'subject'}) { print MAIL "Subject: $Config{'subject'}\n\n" } else { print MAIL "Subject: WWW Form Submission\n\n" } print MAIL "Below is the result of your feedback form. It was submitted by\n"; print MAIL "$Config{'realname'} ($Config{'email'}) on $date\n"; print MAIL "-" x 75 . "\n\n"; if (@Print_Config) { foreach $print_config (@Print_Config) { if ($Config{$print_config}) { print MAIL "$print_config: $Config{$print_config}\n\n"; } } } # Sort alphabetically if specified: # if ($Config{'sort'} eq 'alphabetic') { foreach $field (sort keys %Form) { # If the field has a value or the print blank fields option # # is turned on, print out the form field and value. # if ($Config{'print_blank_fields'} || $Form{$field} || $Form{$field} eq '0') { print MAIL "$field: $Form{$field}\n\n"; } } } # If a sort order is specified, sort the form fields based on that. # elsif ($Config{'sort'} =~ /^order:.*,.*/) { # Remove extraneous line breaks and spaces, remove the order: # # directive and split the sort fields into an array. # $Config{'sort'} =~ s/(\s+|\n)?,(\s+|\n)?/,/g; $Config{'sort'} =~ s/(\s+)?\n+(\s+)?//g; $Config{'sort'} =~ s/order://; @sorted_fields = split(/,/, $Config{'sort'}); # For each sorted field, if it has a value or the print blank # # fields option is turned on print the form field and value. # foreach $sorted_field (@sorted_fields) { if ($Config{'print_blank_fields'} || $Form{$sorted_field} || $Form{$sorted_field} eq '0') { print MAIL "$sorted_field: $Form{$sorted_field}\n\n"; } } } # Otherwise, default to the order in which the fields were sent. # else { # For each form field, if it has a value or the print blank # # fields option is turned on print the form field and value. # foreach $field (@Field_Order) { if ($Config{'print_blank_fields'} || $Form{$field} || $Form{$field} eq '0') { print MAIL "$field: $Form{$field}\n\n"; } } } print MAIL "-" x 75 . "\n\n"; # Send any specified Environment Variables to recipient. # foreach $env_report (@Env_Report) { if ($ENV{$env_report}) { print MAIL "$env_report: $ENV{$env_report}\n"; } } close (MAIL); } sub check_email { # Initialize local email variable with input to subroutine. # $email = $_[0]; # If the e-mail address contains: # if ($email =~ /(@.*@)|(\.\.)|(@\.)|(\.@)|(^\.)/ || # the e-mail address contains an invalid syntax. Or, if the # # syntax does not match the following regular expression pattern # # it fails basic syntax verification. # $email !~ /^.+\@(\[?)[a-zA-Z0-9\-\.]+\.([a-zA-Z0-9]+)(\]?)$/) { # Basic syntax requires: one or more characters before the @ sign, # # followed by an optional '[', then any number of letters, numbers, # # dashes or periods (valid domain/IP characters) ending in a period # # and then 2 or 3 letters (for domain suffixes) or 1 to 3 numbers # # (for IP addresses). An ending bracket is also allowed as it is # # valid syntax to have an email address like: user@[255.255.255.0] # # Return a false value, since the e-mail address did not pass valid # # syntax. # return 0; } else { # Return a true value, e-mail verification passed. # return 1; } } sub convert_chevrons { my ($str) = @_; $str =~ s/\/>/g; return $str; } sub body_attributes { # Check for Background Color if ($Config{'bgcolor'}) { print " bgcolor=\"".convert_chevrons($Config{'bgcolor'})."\"" } # Check for Background Image if ($Config{'background'}) { print " background=\"".convert_chevrons($Config{'background'})."\"" } # Check for Link Color if ($Config{'link_color'}) { print " link=\"".convert_chevrons($Config{'link_color'})."\"" } # Check for Visited Link Color if ($Config{'vlink_color'}) { print " vlink=\"".convert_chevrons($Config{'vlink_color'})."\"" } # Check for Active Link Color if ($Config{'alink_color'}) { print " alink=\"".convert_chevrons($Config{'alink_color'})."\"" } # Check for Body Text Color if ($Config{'text_color'}) { print " text=\"".convert_chevrons($Config{'text_color'})."\"" } } sub error { # Localize variables and assign subroutine input. # local($error,@error_fields) = @_; local($host,$missing_field,$missing_field_list); if ($error eq 'bad_referer') { if ($ENV{'HTTP_REFERER'} =~ m|^https?://([\w\.]+)|i) { $host = $1; print <<"(END ERROR HTML)"; Content-type: text/html Bad Referrer - Access Denied

Bad Referrer - Access Denied
The form attempting to use FormMail resides at $ENV{'HTTP_REFERER'}, which is not allowed to access this cgi script.

If you are attempting to configure FormMail to run with this form, you need to add the following to \@referers, explained in detail in the README file.

Add '$host' to your \@referers array.


FormMail V1.9 © 1995 - 2001 Matt Wright
A Free Product of Matt's Script Archive, Inc.
(END ERROR HTML) } else { print <<"(END ERROR HTML)"; Content-type: text/html FormMail v1.9
FormMail
Copyright 1995 - 2001 Matt Wright
Version 1.9 - Released August 3, 2001
A Free Product of Matt's Script Archive, Inc.
(END ERROR HTML) } } elsif ($error eq 'request_method') { print <<"(END ERROR HTML)"; Content-type: text/html Error: Request Method
Error: Request Method
The Request Method of the Form you submitted did not match either GET or POST. Please check the form and make sure the method= statement is in upper case and matches GET or POST.

FormMail V1.9 © 1995 - 2001 Matt Wright
A Free Product of Matt's Script Archive, Inc.
(END ERROR HTML) } elsif ($error eq 'no_recipient') { print <<"(END ERROR HTML)"; Content-type: text/html Error: Bad/No Recipient
Error: Bad/No Recipient
There was no recipient or an invalid recipient specified in the data sent to FormMail. Please make sure you have filled in the recipient form field with an e-mail address that has been configured in \@recipients. More information on filling in recipient form fields and variables can be found in the README file.
FormMail V1.9 © 1995 - 2001 Matt Wright
A Free Product of Matt's Script Archive, Inc.
(END ERROR HTML) } elsif ($error eq 'missing_fields') { if ($Config{'missing_fields_redirect'}) { print "Location: $Config{'missing_fields_redirect'}\n\n"; } else { foreach $missing_field (@error_fields) { $missing_field_list .= "
  • $missing_field\n"; } print <<"(END ERROR HTML)"; Content-type: text/html Error: Blank Fields
    Error: Blank Fields
    The following fields were left blank in your submission form:

      $missing_field_list

    These fields must be filled in before you can successfully submit the form.

    Please use your browser's back button to return to the form and try again.


    FormMail V1.9 © 1995 - 2001 Matt Wright
    A Free Product of Matt's Script Archive, Inc.
    (END ERROR HTML) } } elsif ($error eq 'illegal_recipients') { if ($Config{'missing_fields_redirect'}) { print "Location: $Config{'missing_fields_redirect'}\n\n"; } else { foreach $missing_field (@error_fields) { $missing_field_list .= "
  • $missing_field\n"; } print <<"(END ERROR HTML)"; Content-type: text/html Error: Illegal Recipient Address(es)
    Error: Illegal Recipient Address(es)
    The following recipient address(es) are illegal:

      $illegal_recip_str

    Adjust your settings to correct the error.

    Please use your browser's back button to return to the form and try again.


    FormMail V1.9 © 1995 - 2001 Matt Wright
    A Free Product of Matt's Script Archive, Inc.
    (END ERROR HTML) } } elsif ($error eq 'bad_recipients') { print <<"(END ERROR HTML)"; Content-type: text/html Error: Bad \@recipients setting in FormMail
    Error: Bad \@recipients setting in FormMail
    The following entries are not allowed as domain-only entries in your \@recipients list:

      $error_fields[0]

    Entering these domains in the \@recipients list is a security risk. Please enter the complete Email address for recipients in these domains.


    Example:
    If you want to be able to send the results of your web form to user123\@aol.com, do not put 'aol.com' in your \@recipients list. Instead, put 'user123\@aol.com'.
    (END ERROR HTML) } exit; }