JavaScript library for protecting email addresses from spam bots

email-protector.js

This is a JavaScript library for protecting email addresses included on webpages from spam bots. It uses different obfuscation techniques to hide the real email address and mailto links, as well as methods for correct presentation of them to the user. The trick is to use simple ROT encoding function (i.e. Caesar cipher), to hide an email address and decode it whenever the user clicks on a link (any mouse button click is counted here, because of the usage of the mousedown event).

There are also some other obfuscation techniques used to protect email addresses as CSS reverse technique, hidden <span> addition, and HTML comments insertion. Look at the Resources section for more details about the subject, especially the first two articles.

Prerequisites

There are no prerequisites for the library to use other than JavaScript enabled in a browser. The library was compiled with Babel transcompiler with default parameters of @babel/preset-env preset, so it should run without issues on any modern web browser. It was tested on:

  • Mozilla Firefox v79
  • Google Chrome v80
  • Opera v67

The library was minified using Terser Plugin in webpack with default parameters. Source map was included in the production build (see build directory). You can find webpack configuration files attached to the repository root folder.

Installation

To use the library with your HTML documents include the email-protector.js file (build directory) using <script> tag. You can download it and include as a local file (this way future changes to the project will not break your webpage):

<script src="assets/js/email-protector.js"></script>

Or you can attach the library with the global link as well:

<script src="https://raw.githubusercontent.com/bearbyt3z/email-protector.js/master/build/email-protector.js"></script>

Preparing email address

It is important to stress that an email address provided as an argument to each output function (see Inserting Email Address into HTML document section) must be already encoded - we don’t want to share it with spam bots. You can encode your email address using online tools like rot13.com, or using function rot() build in the EmailProtector (calling it directly in a browser console or in a <script> tag).

Here is an example using default value of code parameter (which is 13):

console.log(EmailProtector.rot('user@domain.net'));

The expected output is:

hfre@qbznva.arg

Another example for ROT23 encoding (code 23):

console.log(EmailProtector.rot('user@domain.net', 23));

The output will be:

rpbo@aljxfk.kbq

See Configuration Parameters section explaining the usage of the code and the rest of configuration parameters.

Inserting email address into HTML document

There are two methods available to insert your email address link into HTML document.

Using append() method

The first one assumes creating a HTML element with an arbitrary ID and calling append() function with the ID and the encoded email address as parameters:

<body>
  <!-- script with append() function can be placed anywhere in a HTML document -->
  <script>
    EmailProtector.append('email-protector', 'hfre@qbznva.arg');
  </script>
  ...
  <p>
    Please contact me at <span id="email-protector"></span>
  </p>
</body>

Please keep in mind, that the mailto link will be added as the last child of the provided HTML element. This is similar behavior as in case of Node.appendChild() method, which is called by the append() method.

This function uses window.onload event to add the email link to the specified HTML element, so it can be executed anywhere in a HTML document.

The above code will generate the following result:

<p>
  Please contact me at
  <span id="email-protector">
    <a id="_k905fu05ixbj1tazna" href="znvygb:hfre@qbznva.arg">
      <!-- mailto:spdgsl@mkuhrekslo.euh -->
      ten
      <!-- pre . -->
      .
      <!-- post . -->
      niamod
      <span>spdgsl@mkuhrekslo.euh</span>
      <!-- pre @ -->
      @
      <!-- post @ -->
      resu
    </a>
  </span>
</p>

Notice: Please keep in mind that id attribute of every anchor tag is randomly generated, and should be unique across the entire webpage.

Using write() method

Second technique uses document.write() method to print the mailto link exactly after the <script> tag, where the EmailProtector.write() method was called:

<body>
  <p>
    Please contact me at
    <script>
      EmailProtector.write('hfre@qbznva.arg');
    </script>
  </p>
</body>

Notice that there is no parameter corresponding to the ID of a DOM element, because the email link is placed where the <script> tag occurs.

The above code will generate a very similar result to the previous method:

<p>
  Please contact me at
  <script>
    EmailProtector.write('hfre@qbznva.arg');
  </script>
  <a id="_k905fu05ixbj1tazna" href="znvygb:hfre@qbznva.arg">
    <!-- mailto:spdgsl@mkuhrekslo.euh -->
    ten
    <!-- pre . -->
    .
    <!-- post . -->
    niamod
    <span>spdgsl@mkuhrekslo.euh</span>
    <!-- pre @ -->
    @
    <!-- post @ -->
    resu
  </a>
</p>

Email parameters

You can specify mailto link parameters using first (in case of write()) or second (in case of aplly()) argument when calling each method. The argument must be a string representing encoded email address or an object with any supported link parameters:

  • email - an ROT encoded email address;
  • subject - the subject of an email message (should not be encoded);
  • body - the body of an email (not encoded);
  • cc - carbon copy of an email (also ROT encoded);
  • bcc - blind carbon copy (also ROT encoded).

Here is an example of all the above mentioned mailto link parameters passed to the write() function:

EmailProtector.write({
  email:   'hfre@qbznva.arg',
  subject: 'Message from www',
  body:    'Hi, I\'m contacting you',
  cc:      'hfre2@qbznva.arg',
  bcc:     'hfre3@qbznva.arg'
});

The cc and bcc parameters in the example correspond to user2@domain.net and user3@domain.net addresses respectively. As stated above they also have to be ROT encoded, because they will be subjected to the decoding process in the same way the main email address is (we don’t want to expose them to spam bots either).

Configuration parameters

The last parameter of the append() and write() functions specifies the EmailProtector configuration object. There are several config options to choose from that allow to adjust encoding and the display value of the generated mailto link.

code

Specifies the code value for email decoding i.e. Caesar cipher code. You have to pass the code value that will revert back the encoding, so this parameter is crucial for proper work of the EmailProtector.decode() function.

The code value can be computed as the difference between 26 and the code value used in encoding (modulo 26). For example if the code 11 was used to encode an email address, then the code 15 should be used for decoding. You can also use numbers greater than 26, but the rot() and decoding function will do modulo operation anyway.

The default value is 13 i.e. ROT13 encoding is assumed. Notice that when encoding by 13 the decoder code value will be the same.

linkLabel

Specifies the display value used as the mailto link label. If set the provided email address will not be printed inside the email link. Instead the value of this parameter will be used.

The default value is undefined i.e. the email address is used as the link label.

cssReverse

Use the CSS reverse obfuscation technique to hide the real email address displayed as the mailto link label. The email address is written in reverse order and the following CSS code is used to display it right to a user:

#some-unique-id {
  unicode-bidi: bidi-override;
  direction: rtl;
}

The default value is true.

This option is taken into account only when linkLabel is unset (undefined).

hiddenSpan

Inserts a <span> element in the middle of the mailto link label (before @ char). The span is hidden using CSS display: none property, so it is invisible for a user.

The default value is true.

This option is taken into account only when linkLabel is unset (undefined).

htmlComments

Adds another obfuscation technique using HTML comments. Dot (.) and at (@) signs are extended with comments in the following manner:

<!-- pre @ -->@<!-- post @ -->

Furthermore there is another comment inserted at the beginning of the mailto link label with some fake (generated) email address, e.g.:

<!-- mailto:spdgsl@mkuhrekslo.euh -->

The default value of this parameter is true.

This option is taken into account only when linkLabel is unset (undefined).

Using global parameters and configuration

Email message parameters for the library as well as configuration can be set as global using setGlobalParams() and setGlobalConfig() methods respectively.

<head>
  ...
  <script>
    EmailProtector.setGlobalParams({ email: 'dpnzyo.fdpc@ozxlty.ype', subject: 'Message from www' });
    EmailProtector.setGlobalConfig({ code: 15, hiddenSpan: false, htmlComments: false });
  </script>
</head>
<body>
  <p>
    Please contact me at
    <script>
      EmailProtector.write(); // calling without the email parameter
    </script>
  </p>
  ...
  <p>
    My email address:
    <script>
      EmailProtector.write();
    </script>
  </p>
  ...
</body>

To reset global parameters use resetParams() method and to reset global configuration use resetConfig() method:

EmailProtector.resetParams();
EmailProtector.resetConfig();

After resetting global parameters you cannot call write() method without specifying the value of the email address parameter:

EmailProtector.write(); // this will throw a TypeError: "EmailProtector: undefined is not a valid email address"

Code examples

Here are some examples of tuning the output result from the library. To keep it simple only the email address is passed as an email link parameter. Please look also at the build/examples.html file where you can find more explanatory examples of the library usage.

JavaScript input:

EmailProtector.write('hfre@qbznva.arg', {
  linkLabel: 'Click here to contact me'
});

HTML result:

<a id="_k905fu05ixbj1tazna" href="znvygb:hfre@qbznva.arg">
  Click here to contact me
</a>

JavaScript input:

EmailProtector.write('hfre@qbznva.arg', {
  cssReverse: false,
  hiddenSpan: false,
  htmlComments: false
});

HTML result:

<a id="_k905fu05ixbj1tazna" href="znvygb:hfre@qbznva.arg">
  user@domain.net
</a>

JavaScript input:

EmailProtector.write('hfre@qbznva.arg', {
  cssReverse: true,
  hiddenSpan: false,
  htmlComments: false
});

HTML Result (+ CSS style for text reversing):

<a id="_k905fu05ixbj1tazna" href="znvygb:hfre@qbznva.arg">
  ten.niamod@resu
</a>

JavaScript input:

EmailProtector.write('hfre@qbznva.arg', {
  cssReverse: false,
  hiddenSpan: true,
  htmlComments: false
});

HTML result (+ CSS style for hiding the <span> element):

<a id="_k905fu05ixbj1tazna" href="znvygb:hfre@qbznva.arg">
  user
  <span>spdgsl@mkuhrekslo.euh</span>
  @domain.net
</a>

JavaScript input:

EmailProtector.write('hfre@qbznva.arg', {
  cssReverse: false,
  hiddenSpan: false,
  htmlComments: true
});

HTML result:

<a id="_k905fu05ixbj1tazna" href="znvygb:hfre@qbznva.arg">
  <!-- mailto:spdgsl@mkuhrekslo.euh -->
  user
  <!-- pre @ -->
  @
  <!-- post @ -->
  domain
  <!-- pre . -->
  .
  <!-- post . -->
  net
</a>

JavaScript input:

EmailProtector.write('hfre@qbznva.arg', {
  cssReverse: false,
  hiddenSpan: false,
  htmlComments: true
});

or simply:

EmailProtector.write('hfre@qbznva.arg');

HTML result:

<a id="_k905fu05ixbj1tazna" href="znvygb:hfre@qbznva.arg">
  <!-- mailto:spdgsl@mkuhrekslo.euh -->
  ten
  <!-- pre . -->
  .
  <!-- post . -->
  niamod
  <span>spdgsl@mkuhrekslo.euh</span>
  <!-- pre @ -->
  @
  <!-- post @ -->
  resu
</a>

Resources

  1. Silvan Mühlemann’s Blog post: Nine ways to obfuscate e-mail addresses compared.
  2. Hervé Grall’s article: Anti-spam measure: Against bots harvesting email addresses.
  3. Stack Overflow discutions:

Download Details:

Author: bearbyt3z

Source Code: https://github.com/bearbyt3z/email-protector.js

#javascript

JavaScript library for protecting email addresses from spam bots
4.70 GEEK