Safer Mailto Links

25 May 2006 | Tutorials | 18 Comments

From the creator of "15 Days of jQuery" (me):

Rule number one when it comes to preventing spam: Don’t put a your email address in a mailto: link.

To fight the evil Legion of Spammers, web designers and programmers have come up with some creative solutions. Let’s take a quick look at the more common workarounds and the drawbacks (minor as they may be).

name [at-no-spam] website.com

Problem: a link would be more convenient than typing in the address and some
will mistype.

Contact forms

Problem: you run the risk of having a spammer use your account to send their
mass emails (unless you use a really secure formmail script) and it’s overkill for situations
where you want visitors to just send a simple message.

Javascript encryption

Problem: your email is still sitting out in the open even if you use sophisticated
encryption
to mask it. And who wants to run off to a third party website and run a dozen email addresses through an encryption algorithm one at a time? Not me.

Hiding behind a simple form

(For an example, see Simon Willison’s site and the button that reads ‘Reveal my Address’ near the top of the page.)

Problem: None that I can think of… but let’s see if we can improve on the
concept.

A Possible Solution: AJAX

The solution I propose will have a few advantages over some of the workarounds that we webdesigners currently use:

By the last point I suggest that email encryption devices rely on obfuscation to hide the email address and assume that spammers aren’t smart enough or determined enough to reverse engineer the code and then go about collecting any emails they find on the web that are encrypted using the same method. In practice, I think that email encryption is relatively safe but the fact remains that the email is sitting in the html source code.

The Concept

  1. Use jQuery to grab html content from a file on the server
  2. The file containing the email addresses is mostly html (mailto links) with a simple protection mechanism thrown in for good measure

The Demos

I’m going to start with an example that shows the email addresses when the visitor clicks a button or link and move towards an example where the email addresses appear on the page almost instantaneously.

On button click - instant

On link click - fade in

On page load - fade in

On page load - instant

(*Note: by instant, I mean to say “no fancy effects… show the email addresses as fast as possible.)

The Code

This is released under a non-commercial creative commons license. Contact me if you want to use the code in a commercial product. I’m currently using it in a new CMS for web designers that I’m launching soon.

Get the code here (link to be added later)

Why Is This Safer Than A Regular Mailto Link?

The real problem with mailto links is that spammers can use automated software that searches the web to find them in the source code of your html. They most likely find you the same way Google does: by following links.

They’re lazy just like the rest of us. Therefore it’s unlikely that they’re surfing the web with a legal pad next to their keyboard, scribbling down lists of email addresses to spam.

View the source code of any of the demos and you will see that the email addresses are not in the html.

Is this a rock solid way to absolutely guarantee that you will never get spam and only receive pleasant emails from friendly web visitors… no.

But removing the email address from the source code, changing the secret phrase in the jQuery code, and changing the filename of the target file will probably give you a fair compromise between convenience for your visitors and security for your email address.

One Final Note

Take a close look at the code for the first three examples and you’ll see that I use the AJAX callback function to trigger the slideDown() and show() effects.

In other words, I don’t want jQuery starting the slideDown() effect until the information (html) has been received from the AJAX call. Posting the secret phrase to our simple server side script and then receiving the information back takes time.

Right way:

$(document).ready(function(){
$.post('mailtoInfo.php',{
  pass: "secret"
},function(txt){
  $('div.email').html(txt);
  $('div.email').slideDown("slow");
});
});

Wrong way:

$(document).ready(function(){
$.post('mailtoInfo.php',{
  pass: "secret"
},function(txt){
  $('div.email').html(txt);
});
 $('div.email').slideDown("slow");
});

Technorati Tags: , , ,

Share and Enjoy:These icons link to social bookmarking sites where readers can share and discover new web pages.

Subscribe

Email Updates:
Email:
RSS Feed:

RSS information | Email Policy | RSS to Email by Aweber

18 Comments

  1. Andrea said on 27 May 2006 at 5:03 am:

    Samples 3 and 4 are not always working on Fx. Firebug tells me that the post is not fired at all. Since I’ve never seen JQuery’s ready ‘event’ fail to fire, I’m left wondering whether the post shouldn’t wait for the load event instead: not that I would know why, but maybe you can’t post before the page is loaded? Just wondering.
    Also, and maybe slightly beside the point of a JQuery tutorial like this, I wonder how long it will take for email harvesters to read the ‘generated’ rather than the loaded source.
    In fact, I’d be surprised if they don’t already, since this kind of techniques have been around for a while now.
    This said, nice work, it’s great to see a short tutorials site for JQuery.

  2. Joel Birch said on 27 May 2006 at 5:44 am:

    This is a great solution. I’m sick of using inline code to do generate the mailto address, because those solutions seem hacky and use document.write which only causes more problems for me.

    Having not yet got my Ajax feet wet however, could you please post an example of what the php file contains? That would help me greatly. Thanks a lot.

  3. Joel Birch said on 27 May 2006 at 10:07 am:

    Ok, I got it working anyway - that wasn’t so hard after all. Cheers :)

  4. Jack said on 27 May 2006 at 10:49 am:

    @Andrea
    I assume by Fx you mean Firefox… which I use too and it appears to be working fine. If someone else sees the same problem, please let me know.
    I can’t say for certain if harvesting programs can read generated code but I would think that it would be much more difficult. And if you’re asking the visitor to click a link or press a form button then I’d imagine that the bar would be raised that much further for email harvesting software.

    As I mentioned in the tutorial:

    Is this a rock solid way to absolutely guarantee that you will never get spam and only receive pleasant emails from friendly web visitors… no.

    @Joel
    I’ll post a link to the code shortly, even though you got it working. Glad you liked the tutorial.

  5. Andrea said on 29 May 2006 at 5:04 am:

    Hi again. I’m having the same problem again on another PC at work, again with Firefox 1.5.0.3 (I know that sounds a bit überGeeky, but Fx is the ‘official’ preferred abbreviation for Fx). In particular, it happens if you come back to the page after a first visit. I need to refresh to see the effect. I’m not at all sure why this happens. One would think that it has something to do with the cache, like if jQuery’s ajax plugin wasn’t calling back your function when data is retrieved from the cache, but I doubt it. I’d probably try to run the code in a $(”document”).load rather than $(”document”).ready and see if that changes anything. Unless of course I’m really the only Fx user on earth who’s having this problem, but that sounds unlikely.
    On the other point, I’m afraid reading the generated source is not that hard (a Firefox extension wouldn’t be too hard to develop - in fact I use a few who do already), but I agree that it is still more work, in particular if you also ask for an additional action from the user.
    In fact, in spite of my worries, I’m seriously thinking about using your solution…
    Cheers.

  6. Jeff said on 29 May 2006 at 4:25 pm:

    I’m really enjoying this jquery series. Thank you!

    I have a problem reading these posts through rss (specifically: with bloglines) because the links to your examples use relative addressing.

  7. Jack said on 29 May 2006 at 5:47 pm:

    @Jeff,
    Great catch. I’m going to fix that tonight. I’m currently trying to catch up from taking Memorial Day weekend off.

    Thanks for the heads up. Didn’t even consider it, so you helped out a ton with that comment.

  8. Jack said on 29 May 2006 at 6:32 pm:

    @Andrea,
    I too use 1.5.03 and I don’t see any problems. Demo 3 doesn’t do the fade in when you visit another page and then hit the back button, but the mailto links are there. If that’s the issue, then I think you’d need to send some specifically designed headers via server side code to prevent the browser from caching the content.

  9. Antonio said on 30 May 2006 at 7:29 am:

    I had this “e-mail protection” problem recently, and I was worried also by the generated code, but I didn’t know about jQuery. In the end I did this:
    http://bcds.udg.es/red-mpls/participantes.php

    Now I have to do a jQuery version :)

  10. Andrea said on 8 Jun 2006 at 1:05 pm:

    @Jack,
    I have no idea of what was happening, but it’s working without any problem now on my home PC (only thing that changed is that I just updated to 1.5.0.4, but I’m sure that has nothing to do with it). I’ll also try again from work, but in the meanwhile apologies for the false alarm.

    @Antonio,
    Great solution! Thanks for sharing.

  11. Steve said on 9 Jun 2006 at 9:08 am:

    Would you mind commenting on this Javascript technique? It seems to work, so far. Are there any drawbacks with it?
    http://www.badboy.ro/articles/2005-01-25/

  12. Jack said on 9 Jun 2006 at 10:35 am:

    @Steve,
    The page you’ve linked to gives some code that is short, but I don’t think is quite as good as what I’ve presented for two reasons:

    1- The email address is sitting in the source of the html as you(at)isp.com which could make it very easy for a spam harvester to come along and grab. IMO easier to grab this kind of text and transpose the (at) with a true @ sign than what I’ve done here, which is to put the email addresses in a separate file.

    2- Pulling off multiple email addresses on one page looks tedious with the code you linked to.

    That said, if it works for you - who am I to tell you not to use it?

  13. Curious George said on 16 Jan 2007 at 7:47 pm:

    Interesting idea. But the generated source will still show the email address(es). What is preventing an intelligent spammer to scraping through the generated source code using some simple scripts?

  14. Jack said on 16 Jan 2007 at 9:32 pm:

    George,
    The code I’m familiar with for grabbing remote files is the PHP Snoopy class. To my knowledge, this is not capable of grabbing “generated” source html since a javascript enabled browser, or some similar mechanism, would be required to run the javascript code… but I also have to assume that you have a few scripts in mind that would do the trick.

    That said, I would answer it this way:

    1) It’s not as secure as a good contact form and server side processor, and I never intended to give that impression.

    2) Spammers are lazy, and there are plenty of easier ways to harvest email addresses

    3) It’s up to the webmaster/coder to decide what tradeoff they want to strike between easy of use and security. I’m pretty clear in my article that on one end of the spectrum you have a contact form, on the other you have a naked mailto link, and in between somewhere you have this technique.

    4) I’ve been reading articles about some spammers going so far as to hire people to type in captchas. So the “unbreakable” CAPTCHA that is frustrating for good guys to use, isn’t even a foolproof solution against spam.

  15. anonymous said on 14 Feb 2007 at 12:07 am:

    How about just:
    $(’a.emaillink’).each(function(){
    var to_replace = ‘ [at-no-spam] ‘;
    $(this).html(
    $(this).html().replace(to_replace, ‘@’)
    ).attr(’href’,
    $(this).attr(’href’).replace(to_replace, ‘@’)
    );
    });

    and:
    test [at-no-spam] gmail.com

  16. Jack said on 14 Feb 2007 at 12:11 am:

    anon,
    Actually, I have a plugin that does just that coming soon.

  17. sunfish said on 23 Apr 2007 at 9:17 am:

    Uuups, my first post has vanished and the second is not complete. I do not know how to post code. But you can have a look at the mentioned homepage.

  18. Srini said on 14 Sep 2007 at 1:28 am:

    Nice tutorial..
    I tried this and it just didnt work.
    Should I delay the slideDown somehow??

    Slide down

    $(document).load( function() {
    $(”div.slideMe”).slideDown(”slow”);
    });

    Google
    jQuery really does it..

Leave a Reply

You can follow the discussion through the Comments feed. You can also pingback or trackback from your own site.