Marat BN — Marat Borisovich Nepomnyashy's home page

SP@in (SP64in) website component for CAPTCHA-protecting email addresses from email address harvesting web crawlers

  • Download Release 0.2.1 tar.gz

    Download Release 0.2.1 zip

    View Release Notes

    View / Report Issues / Bugs

    Browse Source

  • Overview:

    • Hides published email addresses from conventional web crawlers.

    • Supports organization directories with multiple email addresses.

    • Each unique visitor can privately see the published email addresses only by solving a CAPTCHA challenge.

    • Published email addresses are revealed in clickable links compatible with the browser-configured default email client.

    • The process of entering the CAPTCHA challenge does not involve page navigation or switching browser windows.

    • CAPTCHA re-entry not always necessary on subsequent page re-visits.

    • Works on IE7 and better browsers.

    • BSD licensed, with BSD / MIT / OFL licensed components.

    Note: Currently requires the PHP server-side framework with GD support for CAPTCHA generation.

  • Demo:

    • What the user sees:

      Contact Us:

      Sales: Send Email
      Support: Send Email
      Public Relations: Send Email
      Webmaster: Send Email

    • What a SPAM crawler sees:

          ...                    ...                       ...                    ...                     ...
      
        ...   <a href='mailto:dbb53b147f32177758034bfcbc4e327d2188caa2_sp@in'>Send Email</a>   ...
      
          ...                     ...                     ...                     ...                     ...
      
        ...   <a href='mailto:cae07669d3019a57b75cc59de780d64964b9acf6_sp@in'>Send Email</a>   ...
      
          ...                      ...                     ...                     ...                    ...
      
        ...   <a href='mailto:79e0b4a15fbf1d71c27da2e78f0b68fee32e4dae_sp@in'>Send Email</a>   ...
      
          ...                     ...                     ...                     ...                     ...
      
        ...   <a href='mailto:9885f32b5a63aa5ea5f6633235bc003b45d48022_sp@in'>Send Email</a>   ...
      
           ...                    ...                      ...                    ...                     ...
              
  • SP@in leverages the following open-source projects:

    • PHP
      Must be pre-installed on deployment server.

    • PHP GD (Graphics Draw) Library
      PHP must be installed/configured with GD.

    • PhpCaptcha Library
      Distributed with SP@in under BSD license.

    • Pecita font
      Distributed with SP@in under OFL license.

    • jQuery
      Distributed with SP@in under MIT license. Must be deployed on website for SP@in to work. Version 1.8.3 bundled with SP@in, but other versions will likely work as well. Version 1.5 or newer recommended.

    • jQuery Cookie plugin
      Internally embedded into SP@in source code under MIT license. Will not interfere with another version of this plugin loaded into the jQuery namespace.

    • qTip2
      Distributed with SP@in under MIT license.

    • Animated loading GIF
      Generated GIFs are totally free for use.

  • Instructions for deploying SP@in on the PHP platform:

    1. Download the latest release of SP@in.

    2. Unpack the release tarball, and copy its contents to the directory <web_root>/components/sp@in/ of your web server.

      This directory would be /var/www/components/sp@in/ on a typical LAMP stack.

      At the end of this step, the destination directory should look like this:

      user@LAMP-stack:~/tmp/maratbn-SP-in-9999999$ ls /var/www/components/sp@in/
      
      common.php   graphics  php-captcha  RELEASE_NOTES   sp@in.js   sp@in-v0.2.1-min.js  validator.php
      example.php  LICENSE   README       sp@in.conf.php  sp@in.php  toolkits
      
      
      user@LAMP-stack:~/tmp/maratbn-SP-in-9999999$ find /var/www/components/sp@in/
      
      /var/www/components/sp@in/
      /var/www/components/sp@in/LICENSE
      /var/www/components/sp@in/example.php
      /var/www/components/sp@in/validator.php
      /var/www/components/sp@in/graphics
      /var/www/components/sp@in/graphics/sp@in-loading-1.gif
      /var/www/components/sp@in/sp@in.js
      /var/www/components/sp@in/common.php
      /var/www/components/sp@in/sp@in-v0.2.1-min.js
      /var/www/components/sp@in/sp@in.php
      /var/www/components/sp@in/php-captcha
      /var/www/components/sp@in/php-captcha/captcha_img.php
      /var/www/components/sp@in/php-captcha/Pecita.otf
      /var/www/components/sp@in/php-captcha/php-captcha.inc.php
      /var/www/components/sp@in/RELEASE_NOTES
      /var/www/components/sp@in/sp@in.conf.php
      /var/www/components/sp@in/toolkits
      /var/www/components/sp@in/toolkits/jquery
      /var/www/components/sp@in/toolkits/jquery/jquery-1.8.3.min.js
      /var/www/components/sp@in/toolkits/jquery/jquery.qtip-nightly.custom
      /var/www/components/sp@in/toolkits/jquery/jquery.qtip-nightly.custom/nightly-365741
      /var/www/components/sp@in/toolkits/jquery/jquery.qtip-nightly.custom/nightly-365741/jquery.qtip.js
      /var/www/components/sp@in/toolkits/jquery/jquery.qtip-nightly.custom/nightly-365741/jquery.qtip.min.js
      /var/www/components/sp@in/toolkits/jquery/jquery.qtip-nightly.custom/nightly-365741/jquery.qtip.css
      /var/www/components/sp@in/toolkits/jquery/jquery.qtip-nightly.custom/nightly-365741/jquery.qtip.min.css
      /var/www/components/sp@in/toolkits/jquery/jquery-1.8.3.js
      /var/www/components/sp@in/README
      
      
      user@LAMP-stack:~/tmp/maratbn-SP-in-9999999$
                
    3. Make sure jQuery is already deployed on the web page on which you want to deploy SP@in.

      If jQuery has never been deployed on the target website before, then the jQuery version 1.8.3 that comes bundled with SP@in can be used like this (lines 9 and 10):

      <html>
        <head>
          <title>Your Page Title</title>
        </head>
        <body>
      
          ... Your page content ...
      
          <script type='text/javascript' src='/components/sp@in/toolkits/jquery/jquery-1.8.3.min.js'>
          </script>
        </body>
      </html>
                

      The above assumes that SP@in was installed to the server-side directory <web_root>/components/sp@in/, which translates to /var/www/components/sp@in/ on a typical LAMP stack.

      It is not necessary to use the version of jQuery bundled with SP@in. If another version of jQuery is already deployed on the target website, then it will likely work as well. Version 1.5 or newer is recommended. Typical jQuery deployment (lines 9 and 10):

      <html>
        <head>
          <title>Your Page Title</title>
        </head>
        <body>
      
          ... Your page content ...
      
          <script type='text/javascript' src='/toolkits/jquery/jquery-1.8.3.min.js'>
          </script>
        </body>
      </html>
                

      The above assumes that the jQuery minified JavaScript file jquery-1.8.3.min.js is placed into the server-side directory <web_root>/toolkits/jquery/.

    4. Deploy the CSS and JavaScript resources for the qTip2 version distributed with SP@in on your web page.

      The qTip2 version that is distributed with SP@in is recommended for deployment, as it has been tested to work well with the SP@in website widget. However, if your web page is already using a recent version of qTip2, then that version might also work well.

      The SP@in website widget is not compatible with the original qTip(1) plugin.

      To deploy qTip2 resources:

      1. Insert a new <link> tag into the <head> of your web page to link to the qTip2 CSS file.

        • If SP@in was installed to the server-side directory:
          <web_root>/components/sp@in/

        • Then the CSS file server-side location should be:
          <web_root>/components/sp@in/toolkits/jquery/jquery.qtip-nightly.custom/nightly-365741/jquery.qtip.min.css

        • And the CSS file should be accessible from the web page via the path:
          /components/sp@in/toolkits/jquery/jquery.qtip-nightly.custom/nightly-365741/jquery.qtip.min.css

      2. Insert a new <script> tag into the <head> or <body> of your web page to link to the qTip2 JavaScript file.

        Having <script> tags in the <head> of the page will delay the complete rendering of the page content until all the said <script> tags have loaded. Having the <script> tags down at the bottom of the page <body> will render the page content without waiting for the <script> tags to load.

        The appropriate insertion location for the <script> tag for qTip2 will depend on the earlier insertion location of the <script> tag for jQuery. The <script> tag for qTip2 must be below the <script> tag for jQuery.

        • If SP@in was installed to the server-side directory:
          <web_root>/components/sp@in/

        • Then the JavaScript file server-side location should be:
          <web_root>/components/sp@in/toolkits/jquery/jquery.qtip-nightly.custom/nightly-365741/jquery.qtip.min.js

        • And the JavaScript file should be accessible from the web page via the path:
          /components/sp@in/toolkits/jquery/jquery.qtip-nightly.custom/nightly-365741/jquery.qtip.min.js

      Typical qTip2 deployment (lines 4, 5, and 13 – 15):

      <html>
        <head>
          <title>Your Page Title</title>
          <link rel='stylesheet'
              href='/components/sp@in/./toolkits/jquery/jquery.qtip-nightly.custom/nightly-365741/jquery.qtip.min.css'>
        </head>
        <body>
      
          ... Your page content ...
      
          <script type='text/javascript' src='/toolkits/jquery/jquery-1.8.3.min.js'>
          </script>
          <script type='text/javascript'
              src='/components/sp@in/toolkits/jquery/jquery.qtip-nightly.custom/nightly-365741/jquery.qtip.min.js'>
          </script>
        </body>
      </html>
                
    5. Test out if the SP@in website component can function properly on your web server, and make server configuration changes if necessary.

      The SP@in website component requires the PHP GD module which is not enabled by default on most web servers. To test if this module is enabled and available for use by SP@in, point a web browser to your local SP@in examples page, which should be at:
      http://your-web-server/components/sp@in/example.php

      The examples page will check for server-side PHP GD installation, and will display a notice if PHP GD is not available.

      The PHP project web page http://php.net/manual/en/image.installation.php contains information on how to install/configure the PHP GD module.

    6. Link to the SP@in website widget JavaScript resource.

      Once properly loaded as a JavaScript resource, the SP@in website widget will:

      1. automatically initialize when your web page loads,

      2. and scan your web page for the appropriate SP@in email address links,

      3. and add a dynamic functionality to each link to enable the user to enter the CAPTCHA challenge.

      The <script> tag for the SP@in website widget JavaScript file must be inserted below the <script> tag for the qTip2 jQuery plugin.

      • If SP@in was installed to the server-side directory:
        <web_root>/components/sp@in/

      • Then the SP@in website widget JavaScript file server-side location should be:
        <web_root>/components/sp@in/sp@in-v0.2.1-min.js

      • And the SP@in website widget JavaScript file should be accessible from the web page via the path:
        /components/sp@in/sp@in-v0.2.1-min.js

      Typical SP@in website widget JavaScript deployment (lines 16 and 17):

      <html>
        <head>
          <title>Your Page Title</title>
          <link rel='stylesheet'
              href='/components/sp@in/toolkits/jquery/jquery.qtip-nightly.custom/nightly-365741/jquery.qtip.min.css'>
        </head>
        <body>
      
          ... Your page content ...
      
          <script type='text/javascript' src='/toolkits/jquery/jquery-1.8.3.min.js'>
          </script>
          <script type='text/javascript'
              src='/components/sp@in/toolkits/jquery/jquery.qtip-nightly.custom/nightly-365741/jquery.qtip.min.js'>
          </script>
          <script type='text/javascript' src='/components/sp@in/sp@in-v0.2.1-min.js'>
          </script>
        </body>
      </html>
                
    7. Configure SP@in server-side settings.

      The emails published and protected by SP@in can be pre-configured in the server-side configuration file sp@in.conf.php. A sample configuration is distributed with the SP@in release:

      <?php
      //  -----------------------------------------------------------------------------
      //  This configuration file is intended for SP@in (SP64in) version 0.2.1
      //  -----------------------------------------------------------------------------
      
      
      if (!class_exists('SP64inCfg')) {class SP64inCfg {
      //  SP@in configuration starts here:
      
          public $email_default = "webmaster@example.com";
      
          public $emails_keyed = array(
                  'webmaster'     => 'joe_the_webmaster@example.com',
                  'admin'         => 'tom_the_admin@example.com',
                  'president'     => 'roy@example.com',
                  'vpresident'    => 'franklin@example.com',
                  'ceo'           => 'art@example.com',
                  'treasurer'     => 'max@example.com',
                  'pubrelations'  => 'roz@example.com',
                  'sales'         => 'rudy@example.com',
                  'support'       => 'ellen@example.com',
                  'product'       => 'violet@example.com',
                  'marketing'     => 'clark@example.com',
                  'engineering'   => 'brad@example.com'
              );
      
          public $urls_keyed = array(
                  'sp64in'        => 'http://maratbn.com/projects/sp64in',
                  'sp64in_github' => array(
                      'caption'   => 'Visit SP@in (SP64in) GitHub page',
                      'url'       => 'https://github.com/maratbn/sp64in')
              );
      
          //  This is the default CSS class for the parent .
          public $class_parent_span = 'sp64in_parent';
      
      
      // The default configuration below should not be modified in most cases
      
          //  If this flag is set to 'True' then rendered SP@in tags will have
          //  'mailto:' 'href's:
          public $flagUseMailto = True;
      
          //  If this flag is set to 'True', then all the email keys will always be
          //  rendered to the client encrypted rather than in cleartext.
          //
          //  Disabling this setting may sometimes be useful for debuging, but
          //  otherwise NOT RECOMMENDED.
          public $flagAlwaysEncryptKeys = True;
      
          //  If this flag is set to 'True', then all the email keys will always be
          //  encrypted with an additional random salt for each session.  This means
          //  that the same keys will never be encrypted the same across separate
          //  sessions, preventing correctly guessing the encrypted key tokens just
          //  by knowing how they look like encrypted.
          //
          //  Disabling this setting may sometimes be useful for debuging, but
          //  otherwise NOT RECOMMENDED.
          public $flagAlwaysEncryptWithSalt = True;
      
      
      // SP@in configuration ends here.
      }
      global $sp64in_cfg; $sp64in_cfg = new SP64inCfg();}?>
                

      The SP@in configuration file must adhere to the PHP syntax.

      The PHP public class field $email_default is useful for publishing a single email address. This can be the email address of the site owner.

      The PHP public class field $emails_keyed is an associative array that can hold a directory of multiple email addresses, as shown in the Demo section above. Each email address is mapped by a key token. They key tokens are used to distinguish the multiple email addresses in the associative array, and to indicate to SP@in which email address to publish where on the site. The SP@in website widget looks at the key token to determine which email address to update the anchor tag with after the user solves the CAPTCHA challenge.

      Make a backup copy of the sample configuration file, and edit the email address strings in the file to reflect the email addresses you want to publish on your site. The default email address is the easiest one to publish, as it is not associated with any key. Multiple email addresses will have to be specified in the associative array, and then referred to by their keys.

    8. Insert SP@in email address anchor tags into your web page to publish your email addresses.

      The procedure slightly varies depending on if the objective is to publish just the pre-configured default email address, one or more of the pre-configured keyed email addresses, or a non-preconfigured email address.

      • Publishing just the default email address:

        The procedure for inserting the SP@in email address anchor tag for the default email address is the simplest. All it involves is inserting the following link into either a static HTML or a PHP file:

           ...       ...       ...       ...       your site content       ...       ...       ...       ...
        
            ...   Contact Webmaster:  <a href='mailto:sp@in' style='visibility:hidden'>Send Email</a>   ...
        
           ...       ...       ...       ...       your site content       ...       ...       ...       ...
                      

        The inline CSS style visibility:hidden specified above will initially hide the anchor tag just as the page loads. This CSS style will then be cleared out by the SP@in website widget as soon as it initializes some time after the page loads.

        The purpose of this mechanism is to prevent the user from clicking on the email address link before the SP@in website widget can initialize and present the user with the proper UI for the CAPTCHA challenge entry. Otherwise, the user’s default email client would open up to send email to the original invalid email address embedded in the tag that’s intended for the SPAM crawler.

        The chore of explicitly specifying the visibility:hidden inline CSS style for publishing email addresses with SP@in can be avoided by using the SP@in server-side PHP utility. This obviously works only with a PHP file, rather than a static HTML file. It involves importing / requiring sp@in.php, and then calling the convenience function sp64inInjectTag() within the page where it is desired to insert a SP@in anchor tag.

        PHP-only example for publishing the default email address:

           ...       ...       ...       ...       your site content       ...       ...       ...       ...
        
         ...   Contact Webmaster:  <?php require_once('components/sp@in/sp@in.php');sp64inInjectTag(); ?>   ...
        
           ...       ...       ...       ...       your site content       ...       ...       ...       ...
                      

        The above assumes that sp@in.php is in the directory <web_root>/components/sp@in/ of your web server, while the page with the injected tag is in the <web_root>/ directory. This also applies to all the examples below.

        The PHP convenience function sp64inInjectTag() also inserts a graphic loading indicator just before the email address anchor tag. This graphic is dynamically hidden by the SP@in website widget after it finishes loading and initializes.

      • Publishing one or more keyed email addresses:

        The procedure for publishing the pre-configured non-default keyed email addresses involves passing the associated key token to the sp64inInjectTag() convenience function. The key token is fed to the function in a separate PHP associative array of options.

        PHP-only example of publishing a non-default email address with the pre-configured key admin:

               ...       ...       ...       ...       ...       your site content       ...       ...       ...       ...       ...
        
         ...   Contact Administrator:  <?php require_once('components/sp@in/sp@in.php');sp64inInjectTag(array('key' => 'admin')); ?>   ...
        
               ...       ...       ...       ...       ...       your site content       ...       ...       ...       ...       ...
                      

        The key token is rendered on the page encrypted to prevent an attacker from using the name and format of a single key token to guess the names of other key tokens. The encryption process is handled internally by the SP@in server-side PHP logic.

        The sp64inInjectTag() convenience function can be called multiple times for multiple email key tokens.

        PHP-only example of publishing multiple non-default email addresses with pre-configured keys president, vpresident, and ceo:

           ...       ...       ...       ...       your site content       ...       ...       ...       ...
        
            ...   <?php require_once('components/sp@in/sp@in.php'); ?>   ...
        
             ...   Contact President:    ...    <?php sp64inInjectTag(array('key' => 'president')); ?>   ...
        
            ...    Contact Vice President:  ... <?php sp64inInjectTag(array('key' => 'vpresident')); ?>    ...
        
             ...   Contact CEO:       ...       <?php sp64inInjectTag(array('key' => 'ceo')); ?>        ...
        
           ...       ...       ...       ...       your site content       ...       ...       ...       ...
                      
      • Publishing a non-pre-configured email address:

        It is not necessary that an email address be pre-configured in the configuration file sp@in.conf.php in order to publish it. The SP@in server-side logic can take any dynamic email address, and publish it on the fly using an internally-generated temporary email key token.

        Inserting an email anchor tag with a non-pre-configured email address is accomplished by calling the SP@in PHP convenience function sp64inInjectTagForNonConfigEmail(...) with the said email address as the first parameter.

        PHP-only example of publishing a non-pre-configured email address:

           ...       ...       ...       ...       your site content       ...       ...       ...       ...
        
            ...   <?php require_once('components/sp@in/sp@in.php'); ?>   ...
        
             ...   Contact User XYZ:  ...       <?php sp64inInjectTagForNonConfigEmail('user_xyz@example.com'); ?>    ...
        
           ...       ...       ...       ...       your site content       ...       ...       ...       ...
        
                        
    9. Add CSS styling to the injected email anchor tags if needed.

      SP@in can render email anchor tags with arbitrary values for the class and style HTML attributes. This is accomplished by passing the desired values for these attributes via the PHP associative array class and style option parameters to the SP@in PHP convenience functions sp64inInjectTag(...) and sp64inInjectTagForNonConfigEmail(...).

      PHP-only example of passing CSS class and style values:

         ...       ...       ...       ...       your site content       ...       ...       ...       ...
      
          ...   <?php require_once('sp@in.php'); ?>   ...
      
          ...    Contact Webmaster:    ...   <?php sp64inInjectTag(array(
                                                              'class' => 'classA classB classC',
                                                              'style' => 'text-color:#123456;font-weight:bold'
                                                          )) ?>   ...
      
           ...   Contact President:   ...    <?php sp64inInjectTag(array(
                                                              'class' => 'classB classC classD',
                                                              'style' => 'text-color:#654321;font-style:italic',
                                                              'key'   => 'president'
                                                          )) ?>   ...
      
           ...   Contact User XYZ:     ...   <?php sp64inInjectTagForNonConfigEmail(
                                                          'user_xyz@example.com', array(
                                                              'class' => 'classC classD classE',
                                                              'style' => 'text-color:#abcdef;font-size:+1em'
                                                          )) ?>   ...
      
         ...       ...       ...       ...       your site content       ...       ...       ...       ...
                
  • Troubleshooting / bug reporting:

    Please post issues / bugs to https://github.com/maratbn/SP64in/issues.

Creative Commons License

Copyright (c) 2010-2018 Marat Nepomnyashy

Except where otherwise noted, this webpage is licensed under a Creative Commons Attribution 3.0 Unported License.

Background wallpaper by Patrick Hoesly, used under Creative Commons Attribution 2.0 Generic License.