Jump to content

Email Obfuscator Module


Recommended Posts

First post and you are uploading a module! Nice. :)

A couple things I noted and wanted to ask about:

Correct me if I'm wrong, but I think this would break mailto links like this:

<a href='mailto:mike@yep.com'>email me</a>

Would become this?

<a href='mailto:mike<span style="display:none;">1234567</span>@yep.com'>email me</a>

It looks like it would replace all instances of the "@" character, whether they were email addresses or not? So that this:

Meet me @ the total experience

Becomes this (though not that big of a deal here):

Meet me <span style="display:none;">7654321</span>@ the total experience

So if you use this obfuscation method, I'm thinking it might be better to use a regular expression so that you know you are matching email addresses, i.e.

if(strpos($event->return, '@')) {
    $event->return = preg_replace('/\b([^\s\r\n]+)@([-.a-z0-9]{2,}\.[a-z]{2,4})\b/i', '$1' . $rand . '$2', $event->return);

Written in the browser and not tested, but I think that would work (let me know if it doesn't, as it sometimes takes me a couple tries making these regexps). Granted, preg_replaces aren't nearly as fast as str_replaces, but they are much more accurate with something like this. And technically, this may be even better as a Textformatter module rather than a page render module, but I can see value in either.

But we're still left with the problem of mailto links. We could easily make the regexp exclude emails that start with "mailto:", but then it would hardly be obfuscated. My experience has been that the only way to get effective obfuscation with something like this is a combined PHP and JS based solution that has the email encrypted in the markup, and then some JS comes in and decrypts it. something relatively simple like a rot13 encryption/decryption, or even just reversing all the characters in the email address is likely to be adequate to keep the bots out. Ultimately it's not the most accessible solution (requiring javascript) but a worthwhile tradeoff in many instances.

Link to comment
Share on other sites


I agree, there are definitely some issues with the current approach (like the mailto links). I'll upload a new version later, but this is my "standard" test for a cms- if I can do something like this easily, I'll continue, if not, I'll drop it. Very easy in processwire, looking forward to helping out.


okay, just figured out how to add js to modules so I'm back with an improved version. Leave feedback if you find any bugs.

Adam: Please no double posts, thank you.

Link to comment
Share on other sites

Nice work 12345J :)

You've gone from something very simple to something that I don't understand–a good thing when it comes to obfuscation. And it looks good! If you don't mind me asking, how does this work? I'm learning something new here, as I'd not seen create_function() before, but I'm intrigued by this. I'm sure I could figure it out by going through the code in more detail, but figure it might be good to include a brief summary of what it's doing in your module readme file for when we add to the directory (if you'd like me to). 

Also, how are you including the JS? I don't see any calls to include the JS. I'm guessing that one would include it manually from their template, but want to confirm? That's certainly a fine way to go. But in case you are interested, here are a couple ways to make it get included automatically:

Add it to $config->scripts, like this:

$class = $this->className; 
$config->scripts->add($config->urls->$class . "$class.js"); 

When building sites, I recommend that developers include scripts (and styles) in this $config item in your own header include (or main template) so that modules can add scripts. So this is what developers would add to their sites, rather than individual links to specific scripts or stylesheets:

foreach($config->styles as $url) echo "<link rel='stylesheet' type='text/css' href='$url' />";
foreach($config->scripts as $url) echo "<script type='text/javascript' src='$url'></script>";

This is the method I use in my own sites, and this is also the method the PW admin uses. I think it's pretty handy because if I need a specific script or css file for a given template, I can just add it to those $config vars before including my header. For example, lets say I had a rotating feature on my homepage and wanted to include the jQuery cycle plugin to do it. Here's what the template might look like:


$config->scripts->add($config->urls->templates . "scripts/jquery.cycle.lite.js"); 
$config->styles->add($config->urls->templates . "styles/home.css"); 
// output homepage specific content and markup

As handy as that is, it's ultimately up to the developer to decide whether they take that approach in their own templates. But I'm thinking we'll encourage people to do something like the above more and more in the future. That would make it easier for module developers to have a standard way of adding stylesheets and JS to site templates.

Another method you can use that is not quite as pretty, but doesn't require the developer to do anything, is to add it to just do another string replace in your obfuscate() function. Add your script right before the closing </head> or </body> tag. i.e.

$class = $this->className; 
$url = $config->urls->$class . "$class.js";
$event->return = str_ireplace("</head>", "<script src='$url'></script>\n</head>", $event->return); 

This is probably the best way to go for simplest possible installation of a script into a unknown HTML output.

Link to comment
Share on other sites

Hey, I think I was loading js the wrong way, I'll fix that and it should be good to go. Basically what it's doing is if it's a mail to link it adds GOSPAM infront of the link, and removes it with js. If it's text, it just reverses the text and reverses it back with CSS. Create function was new for me too as of yesterday- it just makes a termporary function for use by the file it's made by.

Okay, now it should be good to go- including js via the last method, simplest for others to use.

Link to comment
Share on other sites

  • 5 months later...

Hey 12345j, are you still here? I just tried this out and fixed a bug with "$config" should be $this->config in modules.

Mind if I put this on my github account?

Edit: I just added a configuration setting, for defining the html tag the js script will get prepended to. Right now it will be prepended to the </head>, which might not where one wants to have it. So I added a text field where you can for example use "</body>" instead.

Edit: Ok I just went and created a git repo with the updated version of this module. I also renamed the module to EmailObfuscator: https://github.com/s...EmailObfuscator

  • Like 3
Link to comment
Share on other sites

  • 1 month later...

@12345j and @Ryan and the superDuper @Soma! :D Thanks SO much. I just searched "obfuscation" in the forum and < 5 mins later here I am with auto-obfuscation happening. Brilliant!

  • Like 2
Link to comment
Share on other sites

  • 2 months later...

Just a small notice. I spotted when including the .js file the script gots included as:

<script src='/site/modules/EmailObfuscator/EmailObfuscator.js'></script>

When validating the site in in the w3c validator I'm getting an error message:

The attribute given above is required for an element that you've used, but you have omitted it. For instance, in most HTML and XHTML document types the "type" attribute is required on the "script" element and the "alt" attribute is required for the "img" element.

Typical values for type are type="text/css" for <style> and type="text/javascript" for <script>.

Nothing real important, but if you have the time could you fix it? I've done it myself, but I don't know how to use github or git (yet). Thanks!

Link to comment
Share on other sites

  • 1 year later...
  • 4 weeks later...

I have installed Page Edit Soft Lock as well as the Email Obfuscator Module. I find both very useful. :)

There is a small isssue though in using both of them:

When I log in as another user (at the same time as joe), the javascript popup message sometimes says the page is being edited by

"joe (<span style="unicode-bidi:bidi-override; direction: rtl;"class="email-obfuscator-unreverse">ten.lmtf@liameoj</span>)"

I believe it didn´t happen all the time, currently it does, haven´t investigated further yet... It only happens when the user has an E-Mail address registered, well, that´s clear to see why... => But it does not happen all the time, now the e-mail address shows correctly again, but I have not changed anything. It might be hard to find, it certainly doesn´t appear to be a major thing.

(I have posted this in the Page Edit Soft Lock forum as well.)

Edited by Joe
Link to comment
Share on other sites

  • 3 weeks later...
  • 6 months later...
  • 8 months later...
  • 3 weeks later...

Lovely little module! It works perfectly in my 2.5 installation, except for one thing: Links containing "mailto:" seem to get mixed up and are stuck in the obfuscated, reversed order.


<a href="mailto:mail@example.com">mail@example.com</a>

turns into

<span style="unicode-bidi:bidi-override; direction: rtl;" class="email-obfuscator-unreverse">moc.elpmaxe@liam</span><br />
<a href="GOSPAM:moc.elpmaxe@liam"><span style="unicode-bidi:bidi-override; direction: rtl;" class="email-obfuscator-unreverse">moc.elpmaxe@liam</span></a>

(the output on the page is mail@example.com for both lines, but the link is broken and still reversed: gospam:moc.elpmaxe@liam)

Any ideas what went wrong? The JavaScript file is included before the </head> tag.

Link to comment
Share on other sites

  • 3 months later...

Just noticed a small issue.

If you use: $some_other_page->render(), any emails in the rendered code don't get de-obfuscated

Is there a workaround for this behaviour?

I like this module and have used it on serveral websites. But now that I'm using the PageTable-field to render my content, this module doesn't obfuscate e-mail-adresses anymore.

If someone has an idea to fix this, would make me really happy. ;)

Link to comment
Share on other sites

My loop looks like this:

  foreach($child->content as $element) {
    echo $element->render();

I don't quite understand your code, because you are not using the page object. Could you please explain why? I have never seen such variables in the context of ProcessWire.

But I don't think that has anything to do with the module, so let's just wait, if the authors respond. ;)

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Create New...