Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical

Battling form spam

by rickaltman (Initiate)
on Nov 17, 2010 at 06:19 UTC ( #871935=perlquestion: print w/replies, xml ) Need Help??
rickaltman has asked for the wisdom of the Perl Monks concerning the following question:

At our website,, we take book orders and host an annual conference. Our modest submission-form needs are met with your basic garden-variety form.cgi script ( Meanwhile, we average about four to six form spam intrusions per day, so this is not an emergency, just an annoyance. In my hope to find a solution that uses our existing plumbing, I came up with the following scheme:

1. Spam bots indiscriminately fill out every field in a form and send it off.

2. If a field is not visible to a human, he or she would most likely not enter data into it.

3. I added a CSS rule into our external .css file called hiddenrow.

4. I applied this rule to the row of the table that holds the field in question.

(I also included a simple "do not enter data in this field" comment next to the field, in case someone is using an old browser or for whatever reason the CSS rule is not working.)

5. It should be a simple matter to include a test at the beginning of the send_mail subroutine that checks for contents in the hidden field. If it finds content, the subroutine aborts; if it does not find content, it continues.

I suspect that this would eliminate 95% of the form spam we now receive. The only problem is that I don't know how to code it! I tried the following:

sub send_email { <br> if ($Form{'hiddenfield'} eq '') { <br> [continue with send_email subroutine] <br> } <br> } <br>
but it did not work properly. I would be most grateful if some of the expters here could a) test my theory and my logic; and b) if they are sound, help me figure out the proper syntax for this seemingly-simple task.

Many thanks.
Rick A.

Replies are listed 'Best First'.
Re: Battling form spam
by pKai (Priest) on Nov 17, 2010 at 11:02 UTC

    A few random observations after having a cursory view on the download of your script (Form.cgi from which does "not work properly":

    The original script is not your own, but you tried to adapt some form script "flying around" in the internet. (Which is not a bad thing as is, but just to mention because it was not obvious from your post.)

    I didn't bother to long for the original of the script, but try to deduce your changes from what you wrote here.

    You introduced the lines 631,632 (at beginning of sub send_email):

    # Only send email if spam trapping field is empty # if ($Form{'hiddenfield'} eq '') {

    and line 907,908:

    # closing bracket for spam if statement # }

    Now coming from here:

    There is no such variable as %Form declared or filled anywhere, so it will be empty (referencing that stray variable is no error, since use strict; is not used in the script.)

    The closing bracket for spam if statement is not placed at the end of the original sub send_email but a good while further below enclosing some additional subs.

    The last 2 mentioned observations are errors IMHO. To correct that, I propose the following:

    $Form{'hiddenfield'} should read $query->param('hiddenfield').

    Move the closing bracket for spam if statement to approx. line 830, where the original sub send_email ended. (more precisely: place it in front of the } which precedes sub add_error.)

    This is all untested guesswork, but I hope it may lead you closer to what you wanted.

      pKai, thank you very much for the reply. In trying to implement your suggested changes, I botched something up. The beginning of the sub send_email routine now looks like this:


      sub send_email {



      $FullName = $query->param("FullName");



      My tests now return this:

      syntax error at form.cgi line 632, near ")


      syntax error at form.cgi line 832, near "}"

      Execution of form.cgi aborted due to compilation errors.

      As you can plainly see, I'm pretty lame with all of this so any hand-holding that you can provide would be appreciated. A copy of the script is available at if you need to see it.

Re: Battling form spam
by Corion (Pope) on Nov 17, 2010 at 08:26 UTC

    In what way does it fail to work?

    Please reduce one of your scripts to a small, self-contained script that exhibits the problem.

    How do you fill %Form?

    I would double check that the name of the hidden field ("hiddenfield") is actually the same between the HTML page submitting to the script and the script.

    Assuming a standard CGI setup, the following could work, if your scripts use (and if they don't, you should start rewriting them to use CGI).

    #!perl -w use strict; use CGI; my $q = CGI->new(); print $q->header(); if ($q->param('hiddenfield') eq '') { print "<h1>Hidden field was not set</h1>"; } else { print "<h1>Hidden field was sent</h1>"; };
Re: Battling form spam
by sundialsvc4 (Abbot) on Nov 17, 2010 at 14:46 UTC

    I find that almost no spam-bots are the slightest bit “clever.”   The malcontents that run them usually get a scoop of URLs, say from Google, and start slamming random data (“prescription drugs without a prescription, anyone?”) into them.   They really aren’t out to trash your website out of the hundreds or thousands of URLs that might be on their trash-list.

    So... put almost anything on the site which may require any sort of specific human input.   (Put the instructions somewhere besides a “label” that is adjacent to the field in question.)   The bots will consistently fail that test, and the bot-owners (who are busy burning in hell...) will never actually bother to find out why.

Re: Battling form spam
by Anonymous Monk on Nov 17, 2010 at 21:52 UTC
    Do you think this approach will help against spammers that create forum accounts and promote their products/events on the first line of their first post even though that information is irrelevant?
      A three-pronged attack is usually necessary for that.

      First, force them to validate the login by supplying an email to which you'll send a validation URL. That will kill a lot of them, as spammers tend to sign up with mail addresses that are either totally bogus or someone else's.

      Second, if you have a captcha on the confirmation page - or some other humanity test (i.e., which of these pictures is cute? with several randomly-named junk pictures and a kitten and checkboxes) - that will kill a lot of others.

      Last, moderate them for the first few posts. As you say, almost all spammers are hit-and-run, and work off volume. If you make it hard for them, they'll just not bother.

      The last and really sneaky alternative is to have a "spammer" flag. They can post, and the site reports to them that they have successfully posted, but you throw it away. They will waste time trying to post to your site, but will get nothing for it, and they'll get no hint that you are dropping their posts.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://871935]
Approved by lidden
and not a whimper to be heard...

How do I use this? | Other CB clients
Other Users?
Others studying the Monastery: (3)
As of 2018-05-25 09:25 GMT
Find Nodes?
    Voting Booth?