Dealing With Forum & Mailing List Spam
Written by Ian Elliot   
Friday, 04 January 2013
Article Index
Dealing With Forum & Mailing List Spam
Stop Forum Spam API in PHP
Complete program

The API In PHP

The Stop Forum Spam API is a very simple Restful API. You ask for a web page using an appropriate query and it returns the result in XML or JSON.

For example:

//www.stopforumspam.com
           /api?email=g2fsehis5e@mail.ru

returns something like:

<response success="true">
    <type>ip</type>
    <appears>yes</appears>
    <lastseen>2007-09-18 05:48:53</lastseen>
    <frequency>2</frequency>
</response>

You can assemble a query that checks email address, IP address and user name. In most cases the simplest thing to do is check the email address because this is unique in most registration databases and usernames are far less specific.

To lookup an email address you simply need the query string:

email=email@email.com

and to get the result back as JSON, which is easy to work with in PHP or JavaScript, you also need to add

f=json

So putting together a simple PHP function to lookup an email address in the database is quite easy. We start off by building the URL and the query:

function checkSpam($email){ 
 $baseURL =
       'http://www.stopforumspam.com/api';
 
 $query["email"]=$email;
 
 $query["f"]="json";
 $url = $baseURL.'?'.
          http_build_query($query, '', '&');
 

The $url variable now contains the complete query and we can get the result using:

$json= file_get_contents( $url );

The easiest thing to do at this point is to use the json_decode function to return a PHP object with properties that correspond to the JavaScript object defined by the JSON.  Once we have the $result object we can check that the API call worked i.e. $result->sucess is true:


 $result = json_decode($json);
 $spammer=false;
 if($result->success)
 {
  $spammer=$result->email->appears;
 };
  return $spammer;
}


As long as the API call has worked we simply return the appears property which is true if the email address appears in the database.

You can use a more complex test if you want to be 100% sure that the address corresponds to a spammer but this seems to be sufficient in practice.

The entire function is:

function checkSpam($email){
 $baseURL =
          'http://www.stopforumspam.com/api';
 $query["email"]=$email;
 $query["f"]="json";
 $url = $baseURL.'?'.
         http_build_query($query, '', '&');
 $json= file_get_contents( $url );
 $result = json_decode($json);
 $spammer=false;
 if($result->success)
 {
  $spammer=$result->email->appears;
 };
  return $spammer;
}

 

Deleting From The Database

Assuming that you are using a table to store the user details and the database has a field called email which stores the unique email address and a field called id which gives the unique id of the user. It is also assumed that id is assigned sequentially and in accenting order so that the most recent sign ups have the highest id values.

Remember that you need to test your script on a backup site and backup your database before working with it in this sort of ad-hoc way.

We might as well create a simple PHP script that will check the most recent n sign-ups in the database and delete any that are in the spam database.  So supposing that the script is called spam.php you would use the URL

spam.php?n=20

to check the latest 20 sign-ups. You can add more parameters to control the process in the same way.

The script starts off by retrieving the query parameter, i.e. n, from the URL:

<?php
$number=$_GET["n"];

You can retrieve other parameters in the same way.

Next we need to open the database. The only problem is that PHP has more ways of accessing a database than it actually needs! The simplest and most future-proof is to make use of PDO, which is an object-oriented framework but still very easy to use.
To open the database, assuming you are using MySQL use:

try {
    $dbh = new PDO('mysql:host=localhost;
                   dbname='MyDATABASE',
                   'MyUSERNAME',
                   'MyPASSWORD');

where of course you change the "My" quantities into the database name, user name and password that works for your database. If you don't know these you need to discover what they are by looking in the configuration files of your website say.

Next we process the first n items in the user database, keeping a count of how many we delete:

$rows=$dbh->query('SELECT email from MyUSERS
 ORDER BY id DESC  LIMIT '.$number);

You also have to change the name of the table MyUsers to whatever your user's table is called.

Notice that this query returns the result as an associative array that we can now step through:

$count=0;
foreach($rows as $row) {

First we lookup the email address using the function we created ealier:

$email=$row[email];         
$result= checkSpam($email);

To keep the user informed we echo the email to the page, complete with an X if the address is in the spam database:

echo $email;
if($result) echo "X";
echo "<BR/>";

Now we can delete the entry using the email address if it is a spam address:

 

if($result){
   $count++;
   $dbh->query('DELETE FROM 
    MyUSERS WHERE email="'.$row[email].'"')
}

Finally we flush the page buffer so that the user can see how the process is progressing.

    myFlush();
 }

Without the buffer flush the page would be stored in the buffer until the entire process was completed. Flushing the buffer makes each email address appear on the page as soon as it has been processed.

Flushing the buffer is something that varies according to the server and client and a general flush routine is:


function myFlush() {
    echo(str_repeat(' ', 256));
    if (@ob_get_contents()) {
        @ob_end_flush();
    }
    flush();
}

 

When the loop ends we dispose of the database object and complete the try and add the catch just in case things went wrong:

 $dbh = null;
echo $count;
} catch (PDOException $e) {
   print "Error!: ".
           $e->getMessage()."<br/>";
    die();}



Last Updated ( Tuesday, 08 January 2013 )