The SpamSpan module obfuscates email addresses to help prevent spambots from collecting them. It will produce clickable links if JavaScript is enabled, and will show the email address as example [at] example [dot] com if the browser does not support JavaScript.

To configure the module, select "configure" next to the input format you\'d like to use. Enable "Hide Email Addresses using the SpamSpan technique" and submit the form. Then select the "configure" tab to choose relevant options.

'); } } /** * Implements hook_filter_info(). */ function spamspan_filter_info() { $filters['spamspan'] = array( 'title' => t('SpamSpan email address encoding filter'), 'description' => t('Attempt to hide email addresses from spam-bots.'), 'process callback' => '_spamspan_filter_process', 'settings callback' => '_spamspan_filter_settings', 'tips callback' => '_spamspan_filter_tips', 'default settings' => array( 'spamspan_at' => ' [at] ', 'spamspan_use_graphic' => 0, ), ); return $filters; } /** * Spamspan filter process callback * * Scan text and replace email addresses with span tags * * We are aiming to replace emails with code like this: * * user * [at] * example [dot] com * * */ function _spamspan_filter_process($text, $filter) { // Top and tail the email regexp it so that it is case insensitive and // ignores whitespace. $emailpattern = "!" . SPAMSPAN_EMAIL . "!ix"; // Next set up a regex for mailto: URLs. // - see http://www.faqs.org/rfcs/rfc2368.html // This captures the whole mailto: URL into the second group, // the name into the third group and the domain into // the fourth. The tag contents go into the fifth. $mailtopattern = "! # end of the first tag (.*?) # tag contents. NB this # will not work properly # if there is a nested # , but this is not # valid xhtml anyway. # closing tag !ix"; // The preg_repalce_callback functions below cannot take any additional // arguments, so we have to use a global variable to pass the relevant // settings. $GLOBALS['spamspan_settings'] = $filter->settings; // Now we can convert all mailto URLs $text = preg_replace_callback($mailtopattern, '_spamspan_callback_mailto', $text); // and finally, all bare email addresses return preg_replace_callback($emailpattern, '_spamspan_callback_email', $text); unset($GLOBALS['spamspan_settings']); } /** * Settings callback for spamspan filter * * */ function _spamspan_filter_settings($form, $form_state, $filter, $format, $defaults, $filters) { $filter->settings += $defaults; // spamspan '@' replacement $settings['spamspan_at'] = array( '#type' => 'textfield', '#title' => t('Replacement for "@"'), '#default_value' => $filter->settings['spamspan_at'], '#required' => TRUE, '#description' => t('Replace "@" with this text when javascript is disabled.'), ); $settings['spamspan_use_graphic'] = array( '#type' => 'checkbox', '#title' => t('Use a graphical replacement for "@"'), '#default_value' => $filter->settings['spamspan_use_graphic'], '#description' => t('Replace "@" with a graphical representation when javascript is disabled (and ignore the setting "Replacement for @" above).'), ); return $settings; } /** * Filter tips callback */ function _spamspan_filter_tips($filter, $format, $long = FALSE) { return t('Each email address will be obfuscated in a human readable fashion or (if JavaScript is enabled) replaced with a spamproof clickable link.'); } /** * The callback functions for preg_replace_callback * * Replace an email addresses which has been found with the appropriate * tags * * @param $matches * An array containing parts of an email address or mailto: URL. * @return * The span with which to replace the email address */ function _spamspan_callback_mailto($matches) { // take the mailto: URL in $matches[2] and split the query string // into its component parts, putting them in $headers as // [0]=>"header=contents" etc. We cannot use parse_str because // the query string might contain dots. $headers = preg_split('/[&;]/', parse_url($matches[2], PHP_URL_QUERY)); // if no matches, $headers[0] will be set to '' so $headers must be reset if ($headers[0] == '') { $headers = array(); } return _spamspan_output($matches[3], $matches[4], $matches[5], $headers); } function _spamspan_callback_email($matches) { return _spamspan_output($matches[1], $matches[2], '', ''); } /** * A helper function for the callbacks * * Replace an email addresses which has been found with the appropriate * tags * * @param $name * The user name * @param $domain * The email domain * @param $contents * The contents of any tag * @param $headers * The email headers extracted from a mailto: URL * @return * The span with which to replace the email address */ function _spamspan_output($name, $domain, $contents, $headers) { $settings = $GLOBALS['spamspan_settings']; // Replace .'s in the address with [dot] $user_name = str_replace(".", " [dot] ", $name); $domain = str_replace(".", " [dot] ", $domain); $at = $settings['spamspan_use_graphic'] ? 'at' : $settings['spamspan_at']; $output = '' . $user_name . '' . $at . '' . $domain . ''; // if there are headers, include them as eg (subject: xxx, cc: zzz) if (isset($headers) and $headers) { foreach ($headers as $value) { //replace the = in the headers arrays by ": " to look nicer $temp_headers[] = str_replace("=", ": ", $value); } $output .= ' (' . check_plain(implode(', ', $temp_headers)) . ') '; } // if there are tag contents, include them, between round brackets, unless // the contents are an email address. In that case, we can ignore them. This // is also a good idea because otherise the tag contents are themselves // converted into a spamspan, with undesirable consequences - see bug #305464. // NB problems may still be caused by edge cases, eg if the tag contents are // "blah blah email@example.com ..." if (isset($contents) and $contents and !(preg_match("!^" . SPAMSPAN_EMAIL . "$!ix", $contents))) { $output .= ' (' . $contents . ')'; } $output .= ""; // remove anything except certain inline elements, just in case. NB nested // elements are illegal. needs to be here to allow for graphic // @ $output = filter_xss($output, $allowed_tags = array('em', 'strong', 'cite', 'b', 'i', 'code', 'span', 'img')); return $output; } /** * A simple utility function wrapping the main processing callback. * This function may be called by other modules and themes. * * @param $text * Text, maybe containing email addresses. * @param $settings * An associative array of settings to be applied. * @return * The input text with emails replaced by spans */ function spamspan($text, $settings = array()) { //apply default settings $defaults = array( 'spamspan_at' => ' [at] ', 'spamspan_use_graphic' => 0, ); $defaults += $settings; //create a dummy filter object so we can apply the settings $filter = new stdClass(); $filter->settings = $defaults; return _spamspan_filter_process($text, $filter); }