I've had my biz email address for... let's just say, quite a long time. Back in the early days I would just toss it up on my website with a basic "mailto:" link, like so:
<a href="mailto:matt@matts-fake-domain.com">matt@matts-fake-domain.com</a>
So, for awhile there I was pretty much just giving it away to the spam-bots, and I'm paying for it today with huge amounts of spam (which, thankfully, SpamAssassin does an excellent job of catching).
There are numerous ways to clone your email address, the most robust being to use contact forms, which make it so that you don't ever need to show your email address on your website. But sometimes a contact form won't do.
When this happens, it's up to the designer/developer to take the time to encode the email so that it makes it harder for the spam-bots to harvest. There are various javascript encoders, and text editors like TextMate can use ASCII numbers to HTML encode any email address.
(You can do that in TextMate by copying the email address to the clipboard, selecting what you'd like to be the link text, and then hitting ctrl+shift+L. Just make sure that if the link text is an email address itself, you also encode that.)
When you're hand-editing your HTML pages, these methods work great.
But what about if you use some sort of Content Management System, or you have clients that do? Do you really want to explain ASCII to them?
PHP to the Rescue
In the CMSs that I design, I place the following 2 functions into my functions file:
function safeEmail($email) { $email = eregi_replace('#','', $email); $length = strlen($email); for ($i = 0; $i < $length; $i++) $obfuscatedEmail .= "&#" . ord($email[$i]); // creates ASCII HTML entity $return = '<a href="mailto:' . $obfuscatedEmail . '">'.$obfuscatedEmail.'</a>'; return $return; } function check4email($string){ $pattern = "#[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,3})#"; preg_match_all($pattern, $string, $split); foreach ($split[0] as $value) { $email_to_find = '#' . $value . '#'; $string = eregi_replace($email_to_find,safeEmail($value),$string); } return $string; }
The safeEmail function makes use of the PHP ord function to turn an email address into its ASCII equivalent, which should be enough to shrug off the average spambot. The check4email function take a string and searches it for an email pattern that's surrounded in hash symbols, like so: #joe@user.com#
If it finds a match, it gets passed to the safeEmail function, which then encodes the email address. (I only use the hash marks because I like having the ability to turn this function on and off, and it also helps ensure a match.) When I tell my clients how to make an email link in the CMS, I just say to write out the email address and surround it in number signs. That's it. They're keeping email addresses on their website safe in a simple, intuitive manner. The function even creates the link.
When a text-blurb gets pulled out of the database on the live site, the blurb-fetching-function might look like this:
function getBlurb($id) { $db =& DB::connect(DSN); $sql = 'SELECT blurb FROM blurbs WHERE blurb_id='.$id; $row = $db->getRow($sql); $return = check4email($return); return $return; }
So, These Functions Get Used on Every Page View?
Yes, but that's just because the WYSIWYG editors that get used on textboxes (like TinyMCE) take the ASCII text and turn it back into plain text. So, if you use such editors, it chucks your carefully encoded email address out the window and serves it up as spam-bot food. In fact, that's why I couldn't show any ASCII examples here, as WordPress just turned them into their text equivalent, even wo/ using the WYSIWYG editor.
However, I've used these email functions on some well trafficked sites with no performance hit. However, when you need it, you can always cache a page on the server.
Cheers.

By Derek July 31, 2010 - 3:10 pm
With John’s fix, it’s perfect for my CMS, thanks!
By John Fulton May 6, 2010 - 2:20 pm
Made a slight adjustment to safeEmail(), the first time your loop goes it concatenates onto $obfuscatedEmail, but it doesn’t exist the first time and you get a warning:
PHP Notice: Undefined variable: obfuscatedEmail
I simply set $obfuscatedEmail = “”; above the loop.
By Bogdan February 16, 2009 - 1:34 am
Thanks for sharing this scripts, it is just was I was looking for!
By cochon December 15, 2008 - 2:33 pm
christ. it took forever to find this simple function. it amazes me, the amount of people who would charge an arm and a leg for something so simple. this rocks! thank you!!!!