A Bot-Safe Email Link

The quest for bot-safe email is one of the many holy grails of web development. There are many different ways to achieve this, each with their own merits and shortcomings.

Some people suggest using ascii character codes, like this:

<a href="&#109&#97&#105&#108&#116&#111&#58&#97&#98&#99&#64&#97&#98&#99&#46&#99&#111&#109> &#109&#97&#105&#108&#116&#111&#58&#97&#98&#99 &#64&#97&#98&#99&#46&#99&#111&#109</a>

Which, when rendered in the browser gives the address ‘mailto:abc@abc.com’. The obvious shortcoming of this approach is that browsers have built in tools for decoding such strings and browser supported scripting languages, such as JavaScript, have simple methods that will make the string intelligible. Take for example, the same string run through a simple call to the unescape(str) JavaScript method:

<a href="
 javascript:alert(
    unescape(
    '&#109&#97&#105&#108&#116&#111&#58&#97&#98&#99&#64&#97&#98&#99&#46&#99&#111&#109'
    ));">Click me to show 'mailto:abc@abc.com</a>

Others use images to make it harder for bots to read the addresses. We’ve all seen this – you see an email address and go to copy it only to find that it will neither copy into a text form nor will it allow you to click on it. The end result is that the site makes the user type the email address in manually, while looking at the web site. This may work fine for bill@microsoft.com however it is hardly suitable for mukesh.radadeshish@iborrcat.state.us.gov. If you are like me you would readily send Bill email, but Mukesh would often be left in the dark – its just too much work to transcribe all that.

The method I have been using lately simply uses a series of obfuscated methods to place the ‘mailto:abc@abc.com’ in the window’s location bar, causing the browser to pop open the default client with the email address already implanted. For example, the abc@abc.com address would be represented by this:

function emailMe() { window.location = Y4312t7g1o6010685() + fl8CyEyI2jg() + D97ts() + P55j7BkgWM0O34281i2w() + Oo7j() + jRt208Km3G2aYM29GtMf() + BSCL2kW(); }
function nG7DOf6h448mG() {return "m";}
function JFb402B0GN33Ybie4() {return eval("if (true) 'ai';")}
function Y4312t7g1o6010685() { return nG7DOf6h448mG() + JFb402B0GN33Ybie4();}
function nk0t4313DtfU28b8K16U2() {return "lt";}
function Qi() {return "o:";}
function fl8CyEyI2jg() { return nk0t4313DtfU28b8K16U2() + Qi();}
function zdPUN0S37vx9x2() {return unescape("ab");}
function I6OD5jYkoOZF8fVLy8mELQ() {return unescape("");}
function D97ts() { return zdPUN0S37vx9x2() + I6OD5jYkoOZF8fVLy8mELQ();}
function r5KyhM() {return unescape("c@");}
function d53nO3EgQr2N() {return "a";}
function P55j7BkgWM0O34281i2w() { return r5KyhM() + d53nO3EgQr2N();}
function UR5() {return eval("if (true) '';")}
function i542HIf4g2q164245i() {return "bc";}
function Oo7j() { return UR5() + i542HIf4g2q164245i();}
function jRt208Km3G2aYM29GtMf() {return eval("if (true) '.';")}
function BSCL2kW() {return unescape("com");}

A call to the emailMe() method would then pop the mail client with abc@abc.com in the TO address field. I use a script to generate and test this for any email address. I’ll have another post in the future that outlines how I went about writing this generator.

The obvious benefit of this method is that it takes a lot more work to determine the results than it would to simply decode the ascii string or to implement a pre-packaged image reader to extract the address from within an image. To automate the reading of this technique it would require that the script load up all the javascript on the page then execute it. This complexity is then compounded by the fact that the bot has no way of knowing what the outcome of calling a particular function would be, meaning that it could have unintended side effects on the bot itself.