Ive knocked together a bit of php to prevent our website email form from sending us spam. We dont have a huge problem with receiving spam but were getting a few regular ones which this bit of code has prevented.

It uses the mail() but the users entries must first pass some validation checks (not shown here) followed by the spam mail checks shown below before it executes the mail().

We cant use a default spam filter as the email facility on our site allows our patients to request repeat prescriptions and will ligitamately contains phrases like Viagra and other commonly spam associated phrases.

This method is working absolutely fine at the moment but as i continue to add more and more phrases to block it will become rather messy with an endless list of elseif string interogations. What would be a better way to execute this, some sort of array perhaps (containing the blcoked phrases)?

<html>

<body leftmargin="0" topmargin="0">
<?php

/* BLOCKED MAIL SENDER NAMES */

if(strstr($_POST['visitor'],"add a name to catch here") ){
$isspamfree = false;
}


/* BLOCKED EMAIL ADDRESSES */

if (strstr($_POST['visitormail'],"uk-car-ads") || strstr($_POST['visitormail'],"anotheremailtoblockhere")) {

$isspamfree = false;
}


/* MESSAGE CONTENT SPAM FILTER */

elseif(strstr($_POST['notes'],"gaur eskimoic") || strstr($_POST['notes'],"Central Contracts") || strstr($_POST['notes'],"click on") || strstr($_POST['notes'],"nsubscribe") || strstr($_POST['notes'],"[url=http") || strstr($_POST['notes'],"<a href") )  {
$isspamfree = false;
}

if($isspamfree == false) {

echo '

<!-- DISPLAY THE FOLLOWING ONLY IF SPAM IS DETECTED -->



<table width="780" height="100%" border="0" align="center" cellpadding="0" cellspacing="0">
  <tr>
    <td height="144" valign="top" background="RBtopslogan.jpg">
    <table width="99%" border="0" cellspacing="0" cellpadding="0">
      <tr>
        <td>
        <div align="right">
          <font color="#666666" size="1" face="Arial, Helvetica, sans-serif">&gt;&gt;
          www.winyatesHC.co.uk</font></div>
        </td>
      </tr>
    </table>
    </td>
  </tr>
  <tr>
    <td height="23" background="topunder.jpg">
    <table width="75%" border="0" align="right" cellpadding="0" cellspacing="0">
      <tr>
        <td><font face="Arial, Helvetica, sans-serif" color="#ffffff" size="1">
        &gt;&gt; SPAM DETECTED!</font></td>
      </tr>
    </table>
    </td>
  </tr>
  <tr>
    <td valign="top">
    <table width="780" height="100%" border="0" cellpadding="0" cellspacing="0">
      <tr valign="top">
        <td width="174" background="leftback.jpg">

    </td>
    <td width="606" background="back.jpg">
    <table width="98%" height="100%" border="0" align="center" cellpadding="0" cellspacing="5">
      <tr>
        <td valign="top">
        <p align="justify"><strong><span lang="en-gb">
        <font face="Arial, Helvetica, sans-serif" size="2" color="#993333">Prescription
        request - not sent.</font></span></strong></p>
        <p align="justify"><strong><span lang="en-gb">
        <font face="Arial, Helvetica, sans-serif" size="2" color="#993333">
    THE EMAIL YOU ARE ATTEMPTING TO SEND APPEARS TO BE SPAM:<br/><br/>


    </font></span></strong></p>
        <p align="center">&nbsp;</p>

        <p align="center">
			<font face="Arial, Helvetica, sans-serif" size="2" color="#993333">
			<b>Summary</b><br/><br/>
			</font><br />
		</p>

		<p align="center"><b>If you believe this request is not a spam email</b></p>
		<p align="center"><b/>please contact the surgery in person or by phone.</b></p>
		<br /><br/>


        <p class="MsoNormal">&nbsp;</p>
        <p class="MsoNormal">&nbsp;</p>
        <p class="MsoNormal">&nbsp;</p>
        <p class="MsoNormal">&nbsp;</p>
        <p class="MsoNormal">&nbsp;</p>
        <p class="MsoNormal">&nbsp;</p>
        <p class="MsoNormal">&nbsp;</p>
        <p class="MsoNormal" align="center" style="text-align: left">&nbsp;</p>
        <p></font></td>
      </tr>
      <tr>
        <td align="center">
        <!--RiteCounter-->
		<script type="text/javascript" src="http://www.ritecounter.com/c/10/9702.js"></script>
		<noscript>
        <a href="http://www.ritecounter.com"><img src="http://www.ritecounter.com/scripts/htmlc.php?id=9702" alt="javascript hit counter" border=0></a></noscript>
		<!--END RiteCounter-->
		</td>
	  </tr>

  	</table>
  	</td>
   </tr>
</table>
</td>
  </tr>
  <tr>
    <td height="29" background="down.jpg">
    <table width="78%" border="0" align="right" cellpadding="0" cellspacing="0">
      <tr>
        <td>
        <div align="center">
&nbsp;</div>
        </td>
      </tr>
    </table>
    </td>
  </tr>
</table>';



   }
?>
</body>

</html>

this page is displayed informing them their email has not been sent and to contact the surgery in person. I have deliberately NOT given specifics as to an email is flagged as spam to prevent it being easily by-passed in future.

    You could look for phrases all day and at some point, spam will get through. For now, the most effective method (although, slightly annoying for the end user) is a CAPTCHA test. I'm sure you have submitted these when signing up new accounts etc. Currently, I really like the reCAPTCHA project at Carnegie Mellon University. Why? Well, they offer a widely-used, and handicap accessible CAPTCHA field for your website. It's very easy to setup and implement (see the link above.) And, it helps them digitize old books that OCR cannot read. A good case for mutually beneficial.

      yes and thanks.
      I did look in to that but its not suitable considering our potential end user (sight impaired, dyslexic etc). I get extremely annoyed when im made to use similar methods on for example ebay, as they are often completely unreadable.

        They do have audio CAPTCHA integrated (albeit a bit annoying also.) Yes, they stink, I hate filling them out myself, BUT they work!

        Some other tricks you can try before I answer your question:

        1. Seems like most form spam these days are link spammers. ie: Use a regular expression to look for URLs in fields that should not be URLs.

        2. Another trick that sometimes works (most of the time actually) is to use css (preferably a class and style sheet) to hide a table row from the end user. The end user will not see it and not fill that field out. Because spam bots just read the html content (no human eyes to notice the field is hidden from view) they will submit that field. If that field is submitted, you can be marginally assured the the submission is spam.

        Now, for your question...

        Yes, in the long run you will benefit from using an array. Since your if statements differ I suggest using regular expressions instead.

        For example...

        <?php
        $isspamfree = true;
        $patterns = array();
        $patterns['Viagra'] = '/\bviagra\b/i';
        $patterns['Cialis'] = '/\cialis\b/i';
        
        foreach ( $_POST as $key => $value )
        {
        	foreach ($patterns as $pattern) {
        		if ( preg_match($pattern, $value) ) {
        			$isspamfree = false;
        			break 2;
        		}			
        	}
        }
        ?>

        Of course your regular expression patterns can be as complex or simple as you need. Also, you can add an infinite number of patterns. This may not be the exact implementation that you use but it should give you some ideas. However, even this type of implementation can get very large and complex, which is why I prefer a CAPTCHA test.

        Good luck!

          Don't let me confuse you with the associative array. For example, in the code I submitted:

          $patterns['Viagra'] = '/\bviagra\b/i';

          'Viagra' is an associative key not used in my example. I have a habit of doing things that way in case I want to log which pattern I used, for example:

          <?php
          $isspamfree = true;
          $patterns = array();
          $patterns['Viagra'] = '/\bviagra\b/i';
          $patterns['Cialis'] = '/\cialis\b/i';
          
          foreach ( $_POST as $key => $value )
          {
              foreach ($patterns as $rule => $pattern) {
                  if ( preg_match($pattern, $value) ) {
                      $isspamfree = false;
                      log('post variable: $key failed rule: $rule');
                      break 2;
                  }            
          } } ?>

            You might want to take a look at what I'm currently using on my personal site as a sort of experiment. So far, I've only gotten a very small amount of spam (like not more than an average of 1 or 2 a week).

            My Contact Form code

            It's basic spam protection consists of a hidden form field with a random token as a value which is also saved in a session variable, plus another text input field which is hidden via CSS means, and must be empty when received, hopefully therefore deceiving any spam-bots. (This will have no effect on most manually entered spam, which is what I suspect most, if not all, of the little bit of spam I have received has been.)

              11 days later

              tnx for the tips.. the hidden field is a good idea yes.
              I seem to have eliminated all spam via the website now..

              unfortunately it seems a few spam bots have managed to harvest the email address (even though it was tucked away in a hidden 'include').

              we're only getting a couple of bits of spam per week now but its direct and not generated from our website. I thought hiding the 'sendemail' action which includes our email address away in an 'include' would prevent this as the source isnt visable to end users?

                If the email address is a dictionary word with your domain, spam will find it. Spammers employ dictionary attacks (sending to all variations of user@yourdomain.com.) If you need proof, just setup a catchall email address and see how many weird combinations of email you get over time. If you have something like hg2kljh53k2345@yourdomain.com and you are getting spam even though you never reply with that address and it's never posted anywhere, then it'd be a mystery I suppose 🙂

                  Write a Reply...