Nick not found

E-mail Address Obfuscation

Dec 12 2008

If you’ve ever put your e-mail address on your site, you know how quickly spambots find it and start sending you great offers you can’t refuse.  I had this problem and needed to come up with a good solution before beginning to develop client sites.

There are some libraries out there that provide e-mail address obfuscation, but the ones I found were not accessible in that there was no chance that a human would be able to read the e-mail address until after it had been decoded using JavaScript.  Maybe a savant could decode it, but I don’t think that makes the site 503 compliant.

Instead, I needed something that would output a human-readable e-mail address that most spambots wouldn’t find.  In this case, accessibility is most important, and obfuscation comes second.  Because most spambots are lazy and only look for mailto: links or for e-mail addresses that match a regular expression, breaking the address apart would be enough.  (I have no stats to back up the “most” qualifier in the previous sentence, but in practice I’ve found this to be true.)

A simple format that fits my two requirements is this:

address [at] domain [dot] com

This is sufficiently human readable, and most spambots won’t notice it.  For users with JavaScript enabled, it would be best to show a clickable link for

<a href="mailto:address@domain.com">
  address@domain.com
</a>

To make the e-mail addresses easy for our code to find, each should be wrapped in a span tag marked with a special CSS class.  For sake of example, I used “email”, but you can use something else if you want to be more discreet.  So, an e-mail address should appear in the code as:

<span class="email">
  address [at] domain [dot] com
</span>

As a bonus, I also wanted it to handle addresses with a name. For instance:

"Clark Kent" <clark [at] dailyplanet [dot] com>

should become:

<a href="mailto:clark@dailyplanet.com">
  Clark Kent
</a>

To use a name as the link text, just add it in quotes before the address, and surround the address in &lt; and &gt; (properly escaped), such as:

<span class="email">
  "Clark Kent" &lt;clark [at] dailyplanet [dot] com&gt;
</span>

In order to make the transformation, here’s what I did. (This code intentionally does not use any JavaScript libraries because I often use it on temporary pages that are posted while I’m building a site, so it’s pointless to require users to download all that extra code just so I can save myself a few lines).

function initEmailLinks() {
  var spans = document.getElementsByTagName('span');
  for (var i = 0; i < spans.length; i++) {
    var span = spans[i];
    if (span.className.indexOf('email') != -1) {
      var name = null;
      var matches = span.innerHTML.match('"(.*?)"');
      if (matches != null && matches.length == 2) {
        name = matches[1];
      }
      var address =
        span.innerHTML // split to multiple lines for readability
            .replace(/.*&lt;(.*)&gt;\s*/, '$1') // remove '<' & '>'
            .replace(/\s*\[at\]\s*/, '@') // ' [at] ' to '@'
            .replace(/\s*\[dot\]\s*/, '.'); // ' [dot] ' to '.'
      if (name == null || name == '') {
        name = address;
      }
      if (span.style.className.match('no-link')) {
        span.update(address); // render address as plain text
      } else {
        // render the address as a mailto: link
        span.innerHTML =
          '<a href="mailto:' + address + '">' +
          name + '</a>';
      }
    }
  }
}

Then once the page loads, just call initEmailLinks() and all the address [at] domain [dot] com links change to <a href="mailto:address@domain.com">address@domain.com</a>.  Since it’s sometimes useful to show an e-mail address without making it a link, adding the CSS class “no-link” to the span surrounding the e-mail address has this effect.

The code is much simpler when jQuery or Prototype are available, since we can use the libraries’ CSS selectors to get the elements we’re interested in.  Since I’m switching things over to jQuery, I’ll post that version here:

$(function(){
  $('span.email').each(function(){
    var span = $(this);
    var name = null;
    var matches = span.html().match('"(.*?)"');
    if (matches && matches.length == 2) {
      name = matches[1];
    }
    var address =
      span.html() // split to multiple lines for readability
          .replace(/.*<(.*)>\s*/, '$1') // remove '<' & '>'
          .replace(/\s*\[at\]\s*/, '@') // ' [at] ' to '@'
          .replace(/\s*\[dot\]\s*/, '.'); // ' [dot] ' to '.'
    if (name == null || name == '') {
      name = address;
    }
    if (span.hasClass('no-link')) {
      span.html(address);
    } else {
      span.html('<a href="mailto:' + address + '">' +
                name + '</a>');
    }
  });
}

If you’re using jQuery and you don’t care about support for using custom link text (such as a person’s name) and rendering e-mail addresses as plain text, then the code can be simplified to this:

$(function(){
  $('span.email').each(function(){
    var span = $(this);
    var address = span.html()
                      .replace(/\s*\[at\]\s*/, '@')
                      .replace(/\s*\[dot\]\s*/, '.');
    span.html('<a href="mailto:' + address + '">' +
              address + '</a>');
  });
}

For convenience, your server-side code should to be able to properly obfuscate e-mail addresses for you on-the-fly. I use Rails for most of my projects, so here’s a simplified version of a helper method I use:

def email(address, name=nil)
  [ '<span class="email">',
    (name ? %{"#{name}" &lt;} : ''),
    address.gsub('@', ' [at] ').gsub('.', ' [dot] '),
    (name ? '&gt;' : ''),
    '</span>'
  ].join
end

I highly recommend using something like this, especially when you’re putting a client’s e-mail address on their website. It’s fairly quick and easy to implement on both the server and client, and it will keep the address harvesting to a minimum while still being accessible to users without JavaScript.

One Article Comment

Obfuscating Email Addresses In Ruby on Rails | Truespire

May 30 '09 at 10:42 pm

[…] Obscuring e-mail addresses via javascript: This approach is a bit more complex. It involves using e-mail links that are essentially broken in your html (i.e. “Clark Kent” ) and then using javascript to parse that address back to a usable form. This approach works well but seems overkill to me. I won’t post the code to this solution because you can find it here: http://nicknotfound.com/2008/12/12/e-mail-address-obfuscation/ […]


Leave a Comment * indicates a required field


(Do not fill out this field, or your comment will be ignored. This field is here to help us protect against automated comments.

Your name, URL, and comment will appear on this page after I have reviewed it. (I do this to prevent spam). Some Markdown is allowed. I may make formatting adjustments to your comment. Your email address will not be published.

RSS

« Back to all articles

More articles about:


Lightrail Online Platform

Lightrail – a solid, secure platform for insurance websites.

Find out what makes Lightrail awesome »


A little bit about me

© 2022 nicknotfound.com