Hiding email addresses

There’s a link on the del.icio.us popular page to a post by Sarven Capadisli on ways to obscure email addresses from harvesting spambots. For what it’s worth, here’s what I’ve done (I left comments on Sarven’s site, but butchered the HTML so badly I thought it should be redone here):

Put a link on the page that looks something like this:

<a href="/cgi-bin/email.cgi">email me</a>

Create a CGI script called “email.cgi” that looks like this:

!/usr/bin/perl
print v76.111.99.97.116.105.111.110.58.32;
print v109.97.105.108.116.111.58;
print v110.97.109.101.64;
print v112.108.97.99.101.46.99.111.109.10.10

and put it in the cgi-bin directory for your site. (The link assumes that cgi-bin is at the root level of your site’s directory structure. You may need to change that if your site is laid out differently.)

This gives a link that the user can click on to bring up his email client, but keeps the address itself off the page. For belt-and-suspenders insurance, I’ve also obscured the address in the source of the CGI script using Perl’s v-string notation. The script prints out

Location: mailto:name@place.com

with two newlines at the end. The first print does the “Location : ” part; the second does the “mailto:”; the third does the address through the “@”; and the fourth does the domain and the two trailing newlines. Each number is the ASCII value of the corresponding character. I suspect this encoding is unnecessary, but it was fun to write.

I can’t remember where I learned to use v-strings to obscure source code, but it was probably in some obfuscated Perl contest. Or maybe one of Randal Schwartz’s JAPHs. V-strings have been deprecated in recent versions of Perl, but still work. I suppose I’ll have to rewrite the script someday, bloating the code with a bunch of chr()s.

By the way, if you want to do something like this and you don’t want to figure out the ASCII codes by hand, you can do this in Ruby:

str="lucy@desi.com"
(0...str.length).each do |i|
  print str[i], '.'
end

It puts an extra period at the end, but is otherwise just what you need to paste into the CGI script. (Why Ruby? I’m trying to learn it by using it whenever I have some small thing to do.)

Update
Since v-strings are apparently going to be taken out of Perl after the version 5.8 series, I decided I’d better figure out how to write an equivalent CGI without v-strings. Here’s what I came up with:

#!/usr/bin/perl

print chr(76).chr(111).chr(99).chr(97).chr(116).chr(105);
print chr(111).chr(110).chr(58).chr(32).chr(109).chr(97);
print chr(105).chr(108).chr(116).chr(111).chr(58).chr(110);
print chr(97).chr(109).chr(101).chr(64).chr(112).chr(108);
print chr(97).chr(99).chr(101).chr(46).chr(99).chr(111);
print chr(109).chr(10).chr(10);

which is, of course, a lot more clunky. I’ve been getting disappointed in Perl recently, mainly because there seems to be so much effort going into taking the fun out of it. “Always use strict.” “Always use warnings.” If I wanted to do that, I wouldn’t be using Perl, would I?

Anyway, to generate those nasty print statements, I ran the following Ruby code in irb:

str = "Location: mailto:name@place.com\n\n"
a = []
str.each_byte do |i|
  a += ["chr(#{i})"]
end
a.join('.')

and then cut and pasted the output into the Perl program in line-sized chunks.

Update 2
Sarven has graciously edited my post to his blog to get rid of my HTML errors.