This is a good starting point for some kind of obfuscation technique, but on its own it may no longer be effective because of the evolving techniques used by spam harvesters.

This snippet will replace all email addresses in a href="mailto:" by its hexadecimal representation. Thus making email harvesting for spammers harder to do while still retaining the functionality for the user to click on the link and send an email through an email-client.

It is just an implementation of hook_filter, see the filter_example.module to turn this snippet into a valid module.

function obfuscate_email_filter($op, $delta = 0, $format = -1, $text = '') { 
  if ($op == 'list') { 
    return array( 
      0 => t('Obfuscate email addresses'));
  } 

  switch ($delta) { 
    case 0: 
      switch ($op) { 
        case 'description': 
          return t('Obfuscates mailto: email-addresses.'); 

        case 'prepare': 
          return $text; 

        case 'process':
          $pos = 0;
          $oldpos = 0;
          $pat = "/[a-zA-Z]+[a-zA-Z0-9]*[\.|\-|_]?[a-zA-Z0-9]+@([a-zA-Z]+[a-zA-Z0-9]*[\.|\-|_]?[a-zA-Z]+[a-zA-Z0-9]*[a-zA-Z0-9]+){1,4}\.[a-zA-Z]{2,4}/";
            #
            # to improve performance, match 'href=mailto:' with static string matching
            #
            while($pos = strpos($text, 'href="mailto:', $pos+1)) {
              $matches = array();
              #
              # a few characters after $pos, the email address begins
              # preg_match stops after the first match, so this should be fast enough
              #
              preg_match($pat, $text, $matches, PREG_OFFSET_CAPTURE, $pos);
              $len = strlen($matches[0][0]);
              $pos = $matches[0][1];
              $temp .= substr($text, $oldpos, $pos-$oldpos);
              #
              # replace the email address by its hex values
              #
              for ($i = 0; $i < $len; $i++) {
                $temp .= "&#" . ord($matches[0][0][$i]);
              }
              $oldpos = $pos+$len;
            }
            $temp .= substr($text, $oldpos, strlen($text)-$oldpos);
            $text = $temp;
          }
          return $text;
      } 
      break; 
  } 
}

Feel free to criticise and improve the code. The regular expression in $pat is a modified version of a comment from http://php.net/preg_match. There are still some cases where only parts of the email address are obfuscated.

One might want to obfuscate all occuring email addresses in $text, but this is good enough for me and I am hesitant to use preg_match_all or iterate with preg_match due to performance considerations. Though I have to admit that I did not run any benchmarks.