« February 06, 2004 | Main | February 08, 2004 »

In an effort to curb the effects of receiving spam from I've devised a few scripts that will automatically create random email address every-so-often that will redirect to my read email account. The idea is that if a spammer harvests this email address, it (spammers are not worthy of human pronouns) will have a window of X days to spam me before that email alias is gone forever and my web hosts blackholes the message. It won't stop the spam problem, but at least I don't have to see it. Of course, I could make a email form, but that's not too interesting.

The code I have below is what I've created for myself. It'll probably require some tweaking if you want to use it since I didn't spend the extra time to make it thoroughly generic, but hopefully it'll give you an idea.

There are three components to this, a Perl script that runs on the server, a cron job that calls the Perl script, and a PHP script in the web page so that for every request, it'll get the latest email rather than having to wait for the next re-building of the page.

Some prerequisites: even though all my pages end with .html, they're all sent through a PHP processor before being displayed. This is done with an Apache directive ForceType. Your web server also has to have a ".redirect" file available. For my host, I have a web page control panel to create email aliases, but that's just a front end to modifying the ".redirect" file. This script will access the file directly.

The Perl script (I call it "genalias.pl"):
#!/usr/bin/perl

# Needed, download from http://www.cpan.org (do a search)
use Tie::File;

### Constants
# The redirect file for email aliases
my $redirectFile = "/home/jupiterstar/.redirect";

# This keeps track of the previously used email addresses
# so the cronjob knows what to delete from .redirect
my $recordFile = "/home/jupiterstar/.oldaliases";

# Number of old emails that are valid after they've
# been replaced by a new one (even though the page will
# show the new address only, the previous X number of email
# address will still be valid, where X is this variable)
# Increasing this number means that old email address
# will be valid much longer 
my $staggeredNum = 1;

# This is the email addresses to forward to
my $permanentAddress = "xxx@xxx.com";

### Begin Code

# The new email address is a random string of length 12
# domain for this address is whatever your host is
my $newAddress = generate_random_string(12);
my $newAddressTime = time();

# push new address and time into the $recordfile and
# remove the old address
tie(@recordArray, 'Tie::File', $recordFile) or die "Error tying $recordFile";

unshift(@recordArray, $newAddress . " " . $newAddressTime);

my $oldAddressRecord = "";

if(scalar(@recordArray) - 1 > $staggeredNum) {
     $oldAddressRecord = pop(@recordArray);
}
untie(@recordArray);

# open up redirect file and add new address, deleting old if needed
tie(@redirectArray, 'Tie::File', $redirectFile) or die "Error tying $redirectFile";

if($oldAddressRecord) {
     $oldAddressRecord =~ /^([^\ ]+).*/; # find first item (the address, not time)
     my $oldAddress = $1;
 
     for(my $i = 0; $i < scalar(@redirectArray); $i++) {
          if($redirectArray[$i] =~ /$oldAddress/) {
               splice(@redirectArray, $i, 1); 
               last;
           }
      }
}

push(@redirectArray, $newAddress . " " . $permanentAddress);
untie(@redirectArray);

# Generate Random String
# (lifted from: http://www.codeproject.com/useritems/perl_randomstring.asp)
sub generate_random_string
{
     my $stringsize = shift;
     my @chars = ('a'..'z', 'A'..'Z', 0..9);
     my $randstring = join '', map{$chars[rand@chars]}@chars[0 .. $stringsize];
     return $randstring;
}
The PHP script (I have this stored as a MoveableType Template named "Get Random Email Link"):
<?
    // The location of the record file (to get latest email)
    $recordFile = "/home/jupiterstar/.oldaliases";
    
    // This is the domain for your email address
    $domain = "@jupiterstar.com";
    
    // The delay before showing new email address
    // the redirect file doesn't update immediately, so
    // you might want to delay the showing of newly generated
    // addresses (in seconds)
    $delay = 1*60;
    
    $recordArray = file($recordFile);
    $showAddress = "";
    if($recordArray) {
         for($i = 0; $i < count($recordArray); $i++) {
              // first elt is the address, second is the time
              $thisRecord = explode(" ", $recordArray[$i]);
              if(empty($showAddress)) { # set new one regardless of time
                   $showAddress = $thisRecord[0];
               }
              if($thisRecord[1] + $delay < time()) { # if it's longer
                   $showAddress = $thisRecord[0];
                   break;
               }
          }
     }
    echo $showAddress . $domain;
?>
The Cron Job (updates the 1st and 15th of every month):
0 0 1,15 * * /home/jupiterstar/genalias.pl

After all is said and done, I put the tag <$MTInclude module="Get Random Email Link"$> in my index template and it'll give me the current email address.

Lunar Scribbles