mirror of
https://github.com/pretix/pretix.git
synced 2025-12-21 16:42:26 +00:00
Compare commits
2 Commits
widget-dia
...
linkify-pl
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d93e2693e5 | ||
|
|
a471a98206 |
@@ -24,6 +24,7 @@ from itertools import groupby
|
|||||||
from smtplib import SMTPResponseException
|
from smtplib import SMTPResponseException
|
||||||
from typing import TypeVar
|
from typing import TypeVar
|
||||||
|
|
||||||
|
import bleach
|
||||||
import css_inline
|
import css_inline
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.core.mail.backends.smtp import EmailBackend
|
from django.core.mail.backends.smtp import EmailBackend
|
||||||
@@ -34,7 +35,10 @@ from django.utils.translation import get_language, gettext_lazy as _
|
|||||||
|
|
||||||
from pretix.base.models import Event
|
from pretix.base.models import Event
|
||||||
from pretix.base.signals import register_html_mail_renderers
|
from pretix.base.signals import register_html_mail_renderers
|
||||||
from pretix.base.templatetags.rich_text import markdown_compile_email
|
from pretix.base.templatetags.rich_text import (
|
||||||
|
DEFAULT_CALLBACKS, EMAIL_RE, URL_RE, abslink_callback,
|
||||||
|
markdown_compile_email, truelink_callback,
|
||||||
|
)
|
||||||
from pretix.helpers.format import SafeFormatter, format_map
|
from pretix.helpers.format import SafeFormatter, format_map
|
||||||
|
|
||||||
from pretix.base.services.placeholders import ( # noqa
|
from pretix.base.services.placeholders import ( # noqa
|
||||||
@@ -139,7 +143,18 @@ class TemplateBasedMailRenderer(BaseHTMLMailRenderer):
|
|||||||
def render(self, plain_body: str, plain_signature: str, subject: str, order, position, context) -> str:
|
def render(self, plain_body: str, plain_signature: str, subject: str, order, position, context) -> str:
|
||||||
body_md = self.compile_markdown(plain_body, context)
|
body_md = self.compile_markdown(plain_body, context)
|
||||||
if context:
|
if context:
|
||||||
body_md = format_map(body_md, context=context, mode=SafeFormatter.MODE_RICH_TO_HTML)
|
linker = bleach.Linker(
|
||||||
|
url_re=URL_RE,
|
||||||
|
email_re=EMAIL_RE,
|
||||||
|
callbacks=DEFAULT_CALLBACKS + [truelink_callback, abslink_callback],
|
||||||
|
parse_email=True
|
||||||
|
)
|
||||||
|
body_md = format_map(
|
||||||
|
body_md,
|
||||||
|
context=context,
|
||||||
|
mode=SafeFormatter.MODE_RICH_TO_HTML,
|
||||||
|
linkifier=linker
|
||||||
|
)
|
||||||
htmlctx = {
|
htmlctx = {
|
||||||
'site': settings.PRETIX_INSTANCE_NAME,
|
'site': settings.PRETIX_INSTANCE_NAME,
|
||||||
'site_url': settings.SITE_URL,
|
'site_url': settings.SITE_URL,
|
||||||
|
|||||||
@@ -45,10 +45,11 @@ class SafeFormatter(Formatter):
|
|||||||
MODE_RICH_TO_PLAIN = 1
|
MODE_RICH_TO_PLAIN = 1
|
||||||
MODE_RICH_TO_HTML = 2
|
MODE_RICH_TO_HTML = 2
|
||||||
|
|
||||||
def __init__(self, context, raise_on_missing=False, mode=MODE_RICH_TO_PLAIN):
|
def __init__(self, context, raise_on_missing=False, mode=MODE_RICH_TO_PLAIN, linkifier=None):
|
||||||
self.context = context
|
self.context = context
|
||||||
self.raise_on_missing = raise_on_missing
|
self.raise_on_missing = raise_on_missing
|
||||||
self.mode = mode
|
self.mode = mode
|
||||||
|
self.linkifier = linkifier
|
||||||
|
|
||||||
def get_field(self, field_name, args, kwargs):
|
def get_field(self, field_name, args, kwargs):
|
||||||
return self.get_value(field_name, args, kwargs), field_name
|
return self.get_value(field_name, args, kwargs), field_name
|
||||||
@@ -68,6 +69,8 @@ class SafeFormatter(Formatter):
|
|||||||
value = str(value)
|
value = str(value)
|
||||||
if self.mode == self.MODE_RICH_TO_HTML:
|
if self.mode == self.MODE_RICH_TO_HTML:
|
||||||
value = conditional_escape(value)
|
value = conditional_escape(value)
|
||||||
|
if self.linkifier:
|
||||||
|
value = self.linkifier.linkify(value)
|
||||||
return value
|
return value
|
||||||
|
|
||||||
def format_field(self, value, format_spec):
|
def format_field(self, value, format_spec):
|
||||||
@@ -75,7 +78,7 @@ class SafeFormatter(Formatter):
|
|||||||
return super().format_field(self._prepare_value(value), '')
|
return super().format_field(self._prepare_value(value), '')
|
||||||
|
|
||||||
|
|
||||||
def format_map(template, context, raise_on_missing=False, mode=SafeFormatter.MODE_RICH_TO_PLAIN):
|
def format_map(template, context, raise_on_missing=False, mode=SafeFormatter.MODE_RICH_TO_PLAIN, linkifier=None):
|
||||||
if not isinstance(template, str):
|
if not isinstance(template, str):
|
||||||
template = str(template)
|
template = str(template)
|
||||||
return SafeFormatter(context, raise_on_missing, mode=mode).format(template)
|
return SafeFormatter(context, raise_on_missing, mode=mode, linkifier=linkifier).format(template)
|
||||||
|
|||||||
@@ -225,16 +225,20 @@ def test_placeholder_html_rendering_from_string(env):
|
|||||||
template = LazyI18nString({
|
template = LazyI18nString({
|
||||||
"en": "Event name: {event}\n\nPayment info:\n{payment_info}\n\n**Meta**: {meta_Test}\n\n"
|
"en": "Event name: {event}\n\nPayment info:\n{payment_info}\n\n**Meta**: {meta_Test}\n\n"
|
||||||
"Event website: [{event}](https://example.org/{event_slug})\n\n"
|
"Event website: [{event}](https://example.org/{event_slug})\n\n"
|
||||||
"Other website: [{event}]({meta_Website})"
|
"Other website: [{event}]({meta_Website})\n\n"
|
||||||
|
"URL: {url}\n\n"
|
||||||
|
"URL with text: <a href=\"{url}\">Test</a>"
|
||||||
})
|
})
|
||||||
djmail.outbox = []
|
djmail.outbox = []
|
||||||
event, user, organizer = env
|
event, user, organizer = env
|
||||||
event.name = "<strong>event & co. kg</strong>"
|
event.name = "<strong>event & co. kg</strong>"
|
||||||
event.save()
|
event.save()
|
||||||
mail('dummy@dummy.dummy', '{event} Test subject', template, get_email_context(
|
ctx = get_email_context(
|
||||||
event=event,
|
event=event,
|
||||||
payment_info="**IBAN**: 123 \n**BIC**: 456",
|
payment_info="**IBAN**: 123 \n**BIC**: 456",
|
||||||
), event)
|
)
|
||||||
|
ctx["url"] = "https://google.com"
|
||||||
|
mail('dummy@dummy.dummy', '{event} Test subject', template, ctx, event)
|
||||||
|
|
||||||
assert len(djmail.outbox) == 1
|
assert len(djmail.outbox) == 1
|
||||||
assert djmail.outbox[0].to == [user.email]
|
assert djmail.outbox[0].to == [user.email]
|
||||||
@@ -243,6 +247,8 @@ def test_placeholder_html_rendering_from_string(env):
|
|||||||
assert 'Other website: [<strong>event & co. kg</strong>](https://example.com)' in djmail.outbox[0].body
|
assert 'Other website: [<strong>event & co. kg</strong>](https://example.com)' in djmail.outbox[0].body
|
||||||
assert '**IBAN**: 123 \n**BIC**: 456' in djmail.outbox[0].body
|
assert '**IBAN**: 123 \n**BIC**: 456' in djmail.outbox[0].body
|
||||||
assert '**Meta**: *Beep*' in djmail.outbox[0].body
|
assert '**Meta**: *Beep*' in djmail.outbox[0].body
|
||||||
|
assert 'URL: https://google.com' in djmail.outbox[0].body
|
||||||
|
assert 'URL with text: <a href="https://google.com">Test</a>' in djmail.outbox[0].body
|
||||||
assert '<' not in djmail.outbox[0].body
|
assert '<' not in djmail.outbox[0].body
|
||||||
assert '&' not in djmail.outbox[0].body
|
assert '&' not in djmail.outbox[0].body
|
||||||
html = _extract_html(djmail.outbox[0])
|
html = _extract_html(djmail.outbox[0])
|
||||||
@@ -258,3 +264,11 @@ def test_placeholder_html_rendering_from_string(env):
|
|||||||
r'Other website: <a href="https://example.com" rel="noopener" style="[^"]+" target="_blank"><strong>event & co. kg</strong></a>',
|
r'Other website: <a href="https://example.com" rel="noopener" style="[^"]+" target="_blank"><strong>event & co. kg</strong></a>',
|
||||||
html
|
html
|
||||||
)
|
)
|
||||||
|
assert re.search(
|
||||||
|
r'URL: <a href="https://google.com" rel="noopener" style="[^"]+" target="_blank">https://google.com</a>',
|
||||||
|
html
|
||||||
|
)
|
||||||
|
assert re.search(
|
||||||
|
r'URL with text: <a href="https://google.com" rel="noopener" style="[^"]+" target="_blank">Test</a>',
|
||||||
|
html
|
||||||
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user