Email Obfuscation – WordPress Shortcode

Recently I was working on a WordPress website and was into a situation where I wanted to protect the email address from spam bots but also didn’t want the legitimate users to go through the trouble of filling out captcha and click an extra link. WordPress do have a nice function called antispambot which does it alright. But not up to my satisfaction. This function converts the email address to special characters which is quite intelligent but let’s face it. Robots are going to take over the world soon. They are becoming more smart every day. It is quite possible that some bots (at least their coder) knows how WordPress does it and a simple decode will reveal the email address for them. Recaptcha also have a feature to protect emails from bots. But this is quite tedious. User have to leave the website just to see the email address. Also the Recaptcha’s popup window looks really awful on mobile devices.

So, I created a shortcode that will hide the email address by default and reveal it to users using JavaScript. At least bots are not smart enough to use JavaScript (yet!). As a very limited number of users will use browsers with JavaScript disable, they can do the extra work and get the email address through recaptcha validation. Let’s see the code.

function my_hide_email_shortcode( $atts , $content = null ) {
    $a = shortcode_atts( array(
        'email' => '',
    ), $atts );
    if ( ! is_email( $a['email']) ) {
        return;
    }
    $email_parts = explode('@', $a['email']);
    $email_head = $email_parts[0];
    $email_tail = $email_parts[1];
    $obfuscated_email_link = get_options('recaptcha_email_link');  //It's wise to set the link from admin side instead of hard coding.
    wp_register_script( 'email-obfusc', get_stylesheet_directory_uri() . '/library/js/email_obfusc.js', array( 'jquery' ), '', true );
    wp_localize_script( 'email-obfusc', 'email', array('content' => antispambot( $content )) );
    wp_enqueue_script( 'email-obfusc' );
    return '<span class="mail_hide" data-mail-h="'.strrev($email_head).'" data-mail-t="'.strrev($email_tail).'"><a class="obfocused-email" href="'.$obfuscated_email_link.'" target="_blank"> ' . (strlen($content) > 0 ? antispambot( $content ) : __('View email address', 'mytextdomain')) . '</a></span>';
}
add_shortcode( 'hide_email', 'my_hide_email_shortcode' );

If we use the shortcode like [hide_email email="[email protected]"]See the Email[/hide_email] the email address will first be broken into parts, reversed and stored as data variable of the wrapper. Later I’ve revealed the email address to users using JavaScript. If JavaScript is not available, user will be sent to recaptcha link to retrieve the email address. Here is the JavaScript code.

jQuery(document).ready(function(){
    var mail_head = jQuery('.mail_hide').first().attr('data-mail-h').split('').reverse().join('');
    var mail_tail = jQuery('.mail_hide').first().attr('data-mail-t').split('').reverse().join('');
    var oldhtml = '';
    var mail = mail_head+'@'+mail_tail;
    var mail_content = email.content;
    if(mail_content.length < 3) {
        mail_content = mail_head + '@' + mail_tail;
    }
    jQuery('.choobs_mail_hide').first().html('<a class="obfocused-email" href="mailto:'+mail+'">'+mail_content+'</a>');
    jQuery('.obfocused-email').on('mouseover', function(e){
        oldhtml = jQuery(this).html();
        jQuery(this).html(mail);
        jQuery(this).attr('href', 'mailto:'+mail);
    }).on('mouseleave', function(e) {
        jQuery(this).html(oldhtml);
    });
});

This script fetches the parts of email address, reverses them again and the joins to form the actual email address. I’ve added an effect to reveal the email address when user mouse over the content text. But if there was no content and shortcode was used only like [hide_email email="[email protected]"] the email will be revealed by default.

Go away spam bots!!