From 20664710869d1414bff47e7bce89c42564d016e4 Mon Sep 17 00:00:00 2001 From: Ananya <84459091+ananyatimalsina@users.noreply.github.com> Date: Fri, 27 Feb 2026 08:50:33 +0100 Subject: [PATCH] =?UTF-8?q?Fix=20#1907=20=E2=80=93=20Obfuscate=20contact?= =?UTF-8?q?=20email=20addresses=20in=20public=20HTML=20(#5477)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Include nix development enviornment * Obfuscate contact email addresses in shop HTML and deanonymize via JavaScript This change addresses #1907: "hide contact e-mail address in source code of a shop". - Contact email addresses rendered in public-facing templates are now obfuscated in the HTML source (e.g., replacing "@" with "[at]" and "." with "[dot]"). - A new JavaScript file is included in the relevant templates to automatically rewrite and restore the email address for users after the page loads. - This approach helps protect email addresses from basic harvesting bots and reduces spam, while keeping them accessible and user-friendly for human visitors. - The obfuscation and deanonymization logic is only applied to web templates, not to emails sent via pretix. This implementation follows the recommendations discussed in #1907, using a standardized, maintainable approach that’s compatible with pretix's asset pipeline and template structure. * Undo nix development environment for merge into main * convert complete mailto-link to HTML entities * remove gitignore noise * Update .gitignore * fix gitignore noise * Update .gitignore --------- Co-authored-by: Richard Schreiber --- src/pretix/base/templatetags/anonymize_email.py | 13 +++++++++++++ .../presale/templates/pretixpresale/event/base.html | 3 ++- .../templates/pretixpresale/fragment_js.html | 1 + .../templates/pretixpresale/organizers/base.html | 3 ++- .../static/pretixbase/js/deanonymize_email.js | 7 +++++++ 5 files changed, 25 insertions(+), 2 deletions(-) create mode 100644 src/pretix/base/templatetags/anonymize_email.py create mode 100644 src/pretix/static/pretixbase/js/deanonymize_email.js diff --git a/src/pretix/base/templatetags/anonymize_email.py b/src/pretix/base/templatetags/anonymize_email.py new file mode 100644 index 000000000..b1e75b100 --- /dev/null +++ b/src/pretix/base/templatetags/anonymize_email.py @@ -0,0 +1,13 @@ +from django import template +from django.utils.html import mark_safe + +register = template.Library() + + +@register.filter("anon_email") +def anon_email(value): + """Replaces @ with [at] and . with [dot] for anonymization.""" + if not isinstance(value, str): + return value + value = value.replace("@", "[at]").replace(".", "[dot]") + return mark_safe(''.join(['&#{0};'.format(ord(char)) for char in value])) diff --git a/src/pretix/presale/templates/pretixpresale/event/base.html b/src/pretix/presale/templates/pretixpresale/event/base.html index 99422e54c..984410d3b 100644 --- a/src/pretix/presale/templates/pretixpresale/event/base.html +++ b/src/pretix/presale/templates/pretixpresale/event/base.html @@ -6,6 +6,7 @@ {% load eventurl %} {% load safelink %} {% load rich_text %} +{% load anonymize_email %} {% block thetitle %} {% if messages %} {{ messages|join:" " }} :: @@ -219,7 +220,7 @@ {% endblock %} {% block footernav %} {% if request.event.settings.contact_mail %} -
  • {% trans "Contact" %}
  • +
  • {% trans "Contact" %}
  • {% endif %} {% if request.event.settings.privacy_url %}
  • {% trans "Privacy policy" %}
  • diff --git a/src/pretix/presale/templates/pretixpresale/fragment_js.html b/src/pretix/presale/templates/pretixpresale/fragment_js.html index 09350e862..37ca39ed1 100644 --- a/src/pretix/presale/templates/pretixpresale/fragment_js.html +++ b/src/pretix/presale/templates/pretixpresale/fragment_js.html @@ -21,4 +21,5 @@ + {% endcompress %} diff --git a/src/pretix/presale/templates/pretixpresale/organizers/base.html b/src/pretix/presale/templates/pretixpresale/organizers/base.html index 1783b758f..da77df7cd 100644 --- a/src/pretix/presale/templates/pretixpresale/organizers/base.html +++ b/src/pretix/presale/templates/pretixpresale/organizers/base.html @@ -5,6 +5,7 @@ {% load thumb %} {% load eventurl %} {% load safelink %} +{% load anonymize_email %} {% block thetitle %} {% block title %}{% endblock %}{% if url_name != "organizer.index" %} :: {% endif %}{{ organizer.name }} {% endblock %} @@ -97,7 +98,7 @@ {% endblock %} {% block footernav %} {% if not request.event and request.organizer.settings.contact_mail %} -
  • {% trans "Contact" %}
  • +
  • {% trans "Contact" %}
  • {% endif %} {% if not request.event and request.organizer.settings.privacy_url %}
  • {% trans "Privacy policy" %}
  • diff --git a/src/pretix/static/pretixbase/js/deanonymize_email.js b/src/pretix/static/pretixbase/js/deanonymize_email.js new file mode 100644 index 000000000..d01035ee6 --- /dev/null +++ b/src/pretix/static/pretixbase/js/deanonymize_email.js @@ -0,0 +1,7 @@ +document.addEventListener('DOMContentLoaded', function() { + document.querySelectorAll('a[href^="mailto:"]').forEach(function(link) { + // Replace [at] with @ and the [dot] with . in both the href and the displayed text (if needed) + link.href = link.href.replace('[at]', '@').replace('[dot]', '.'); + link.textContent = link.textContent.replace('[at]', '@').replace('[dot]', '.'); + }); +});