Name
RC4 email

Version
Drupal 7.x. Will be considering D8 version once the module enters maintenance phrase.

Description
This module provides graceful email obfuscation to protect email addresses from harvesting bots on mailto links generated by the Drupal l() function by obfuscating email addresses found in mailto links and its link text. A RC4 ciphertext of the original email address are saved and is later decrypted and reinserted back to HTML by Javascript, providing a transparent experience to sites where a majority of users are using a Javascript-enabled browser, at the same time prevents non-Javascript capable bots (which at the time of writing, are the majority of the bots out there) from harvesting email addresses.

Example
Original link from l():

<a href="mailto:example.one@example.org">Send email to example.one@example.com</a>

For bots:

<a href="mailto:example ! one () example ! org" data-emailurl="H5NkTqSWw54048Y34paoxxdCTz5/yAKUavP6XcL7ZeB24tB4" data-textenc="MYBsVbaWi5lm1dQz4IW/nQVV" class="rc4_email">Send email to example ! one () example ! org</a>

For users:

<a href="mailto:example.one@example.org">Send email to example.one@example.com</a>

Project page
https://drupal.org/sandbox/sunnz/2110029

Git repository
git clone --branch 7.x-1.x http://git.drupal.org/sandbox/sunnz/2110029.git rc4_email

Similar projects
Other email obfuscating modules like Invisimail and SpamSpan filter provides a filter for a text format and does not guard against email generated through l() functions. We’ve developed this module for our clients where they have a Drupal web site with no email address provided through a filtered text, but elsewhere generated by the l() function, such as a site wide contact address on the bottom of the web pages.

Of course, using a combination of this module and a filter module are also a good and recommended way to protect emails in both templates and filtered text.

Other differences are:

  • This module actually encrypts the originals with a per page key instead of encoding.
  • This module makes extensive use of jQuery and Drupal API whenever it is applicable.

Comments

PA robot’s picture

We are currently quite busy with all the project applications and we prefer projects with a review bonus. Please help reviewing and put yourself on the high priority list, then we will take a look at your project right away :-)

Also, you should get your friends, colleagues or other community members involved to review this application. Let them go through the review checklist and post a comment that sets this issue to "needs work" (they found some problems with the project) or "reviewed & tested by the community" (they found no major flaws).

I'm a robot and this is an automated message from Project Applications Scraper.

saitanay’s picture

Status: Needs review » Needs work

Hi Sunnz,

Tried this on an email mailto link generated with l() in a custom block.

The markup generated was
<a href="mailto:jim () hotmail ! com" data-emailurl="krtxYcCOIkjELHFTnFXhVG+onY4H/Q==" data-textenc="srtxYZSMfQ==" rel="nofollow" class="rc4_email">Mail me</a> which appears to the user as expected.

Coding Standards

As for the module code, running it through coder module, shows some markup issues.
List @ http://pastebin.com/hwUt3J8t

You could also run the code through http://pareview.sh/ . It is a great tool.

README.md

Also there is a README.md file. You might want to rename that through README.txt

Does not seem to work with JS aggregation or Page compression

The email display text is weird and looks something like "âo¼nOË(" for various combinations of "Cache pages for anonymous users","Compress cached pages" and "Aggregate JavaScript files" settings on the performance page. The results are different for various combination.

One of the combinations that does not work:
Cache pages for anonymous users = NO
Cache Blocks = Yes (My implementation shows the email link in a custom block from custom module)
Compress cached pages = NO
Aggregate JavaScript files = YES

Javascript Fallback

Without JS, the rendering of the email address seems to err out. The mail to, as appearing to the frontend user is pointing to the mail address
jim () hotmail! com

When javascript is disabled, it would be great to have a fallback like the way Flags Module does.
But again, revealing the email address without encryption when there is no JS defies the purpose of the module. As the spammer would simply have to turn off JS on his crawler agent to harvest the email addresses. I am not sure of what would be the technically feasible solution here, but something to prevent rendering the broken email address in non-js clients should help.

Similar Modules

Could not find any apart from the ones mentioned in the main post. Should be a helpful module with the above issues fixed.

Overall the code looks good. No flags except for a use of hook_init(). But it looks like that it can not be avoided in this case.

Best
Tanay

Anonymous’s picture

Hi Tanay,

Thank you for your review!

I am too testing this module with links generated with l() in a custom block on a vanilla install of Drupal. I have attempted to address the issues found.

Coding standards

Should be all good now.

Note that coder will always complain about missing @file docblock in Javascript files for now because of this issue: #1834598: Coder_Review does not recognize @file docblock in .js files.

README.md

Renamed to README.txt.

Does not seem to work with JS aggregation or Page compression

Unable reproduce problem at the moment, I have tried the combination listed, as well as other combination of JS aggregation, compression, and cache on:

  • Standard Drupal installation with devel, coder and rc4_email.
  • Production sites of my clients.
  • Site running standard Drupal 7.23 platform in Aegir.

Would you be able to provide more information about your testing stack? Are you running multi-site, other modules do you have turned on, etc...

Javascript fallback

Your are correct, that purpose of the module is to give a obscure enough copy of the email address to prevent non-JS bots, while still unobscure enough that a noscript human can make out the email address. Currently I am using the same format used at marc.info: http://marc.info/?l=openbsd-misc&m=138240419110086&w=2, it is in the plans though to add more flexibility to that, such as redirecting to Drupal's contact form, see "Road map" on the project home, and we'll certainly welcome other fallbacks in the future and look at how flag module does it.

Thanks again!
sunnz

Anonymous’s picture

Status: Needs work » Needs review
a_thakur’s picture

Documentation of hook_init() says *Perform setup tasks for non-cached page requests*

So in case cached is enabled, so the code inside the rc4_email_init() won't run, eventually the key won't be available to JS files.

Also please review other projects to get review bonus.

shubhangibb’s picture

Hi,
I found below errors in pareview.sh reviews
FILE: /var/www/drupal-7-pareview/pareview_temp/README.txt
--------------------------------------------------------------------------------
FOUND 0 ERROR(S) AND 2 WARNING(S) AFFECTING 2 LINE(S)
--------------------------------------------------------------------------------
16 | WARNING | Line exceeds 80 characters; contains 86 characters
20 | WARNING | Line exceeds 80 characters; contains 223 characters

Otherwise code looks perfect's, comments are proper.
Good work guys.! :-)

Anonymous’s picture

Hi a_thakur, shubhangibb,

Thank you for your comments!

Yes I can see how it might not work when the keys are set in hook_init(), but we can't call drupal_add_js in hook_boot().

The solutions I am thinking that might work with caching:

  • In theme_link(), call a helper function that calls drupal_add_js if it is setting up the key for the first time.
  • Always use the same key stored in variables table.

Line 16 and 20 in the README file are snippet of sample code outputs. (In markdown code block.) So I think it would be suitable to provide those as-is in this case.

Cheers!
sunnz

perignon’s picture

Are you planning on making any changes from this input? If not then this should be updated to reviewed and tested (RTBC).

Anonymous’s picture

Yes, I am experimenting with the solutions regarding to hook_init() above, so, should I change this back to needs work for now? Or can we proceed to reviewed and tested and work on the hook_init() code in the issue queue in the project's page?

perignon’s picture

I would say if it something you can really add to the code that's a lot of value. Being it's dealing with cacheing I would probably put that as a yes. You can't really run Drupal sites without cacheing under most production scenarios.

Anonymous’s picture

Assigned: Unassigned »
Issue summary: View changes
Status: Needs review » Needs work

Good point. Updating status to needs work while I am experimenting with solution (1), and if anyone suggest any other alternatives I am happy to try it out as well, as we can always fallback to solution (2).

Thanks!

Anonymous’s picture

Status: Needs work » Needs review

Ok I have moved the key generation and drupal_add_js to a helper function _rc4_email_key() in the latest commit:

http://drupalcode.org/sandbox/sunnz/2110029.git/commitdiff/1f3ecd7?hp=c0...

This helper function is called in hook_preprocess_html() and hook_preprocess_link(). It generates the key in the first run and keeps it in its static variable and adds it to Drupal.settings. Then it simply returns it on subsequent calls.

During my testing with caching turned on, cached pages simply keeps the same encrypted email sources and encryption key, whereas authenticated user gets a different key on each page load as they don't get cached pages.

So I am now asserting that this module should work with caching turned on.

Hope that problem is solved for real and we can proceed to the next step. :-)

perignon’s picture

Status: Needs review » Reviewed & tested by the community

Awesome. Thank you for taking the time to make the module better and being realistic about the use of the module.

kscheirer’s picture

Status: Reviewed & tested by the community » Fixed
  • You have a couple of typos, occurances should be occurrences.
  • It looks like you only use _rc4_email_rc4() in a single function - rc4_email_preprocess_link(). It would be better to load the include file just for that function instead of in the global scope, which will be used in all Drupal page requests.
  • Do you need to generate a unique key for every page? It seems like it would be easier to only generate one when there's an email on the page. Or use 1 key and keep it in a variable.

None of those re blocking issues though.

Thanks for your contribution, sunnz!

I updated your account to let you promote this to a full project and also create new projects as either a sandbox or a "full" project.

Here are some recommended readings to help with excellent maintainership:

You can find lots more contributors chatting on IRC in #drupal-contribute. So, come hang out and get involved!

Thanks, also, for your patience with the review process. Anyone is welcome to participate in the review process. Please consider reviewing other projects that are pending review. I encourage you to learn more about that process and join the group of reviewers.

Thanks to the dedicated reviewer(s) as well.

----
Top Shelf Modules - Crafted, Curated, Contributed.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.