forked from CGM_Public/pretix_original
Compare commits
1 Commits
scan-debug
...
new-placeh
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ece1b21298 |
@@ -2,12 +2,15 @@ import logging
|
||||
from smtplib import SMTPRecipientsRefused, SMTPSenderRefused
|
||||
|
||||
from django.core.mail.backends.smtp import EmailBackend
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from i18nfield.forms import I18nFormField, I18nTextarea
|
||||
|
||||
from pretix.base.validators import PlaceholderValidator
|
||||
|
||||
logger = logging.getLogger('pretix.base.email')
|
||||
|
||||
|
||||
class CustomSMTPBackend(EmailBackend):
|
||||
|
||||
def test(self, from_addr):
|
||||
try:
|
||||
self.open()
|
||||
@@ -24,3 +27,72 @@ class CustomSMTPBackend(EmailBackend):
|
||||
raise SMTPRecipientsRefused(senderrs)
|
||||
finally:
|
||||
self.close()
|
||||
|
||||
|
||||
class MailTemplateRenderer:
|
||||
def __init__(self, placeholders: list):
|
||||
self.placeholders = placeholders
|
||||
|
||||
def formfield(self, **kwargs):
|
||||
defaults = {
|
||||
'required': False,
|
||||
'widget': I18nTextarea,
|
||||
'validators': [],
|
||||
'help_text': ''
|
||||
}
|
||||
defaults.update(kwargs)
|
||||
if defaults['help_text']:
|
||||
defaults['help_text'] += ' '
|
||||
defaults['help_text'] += _('Available placeholders: {list}').format(
|
||||
list=', '.join(['{' + v + '}' for v in self.placeholders])
|
||||
)
|
||||
defaults['validators'].append(PlaceholderValidator(['{' + v + '}' for v in self.placeholders]))
|
||||
return I18nFormField(**defaults)
|
||||
|
||||
def preview(self, text, **kwargs):
|
||||
return text.format(**kwargs)
|
||||
|
||||
def render(self, text, values):
|
||||
set_placeholders = set(values.keys())
|
||||
expected_palceholders = set(self.placeholders)
|
||||
if set_placeholders != expected_palceholders:
|
||||
raise ValueError('Invalid placeholder set. Unknown placeholders: {}. Missing placeholders: {}'.format(
|
||||
set_placeholders - expected_palceholders, expected_palceholders - set_placeholders
|
||||
))
|
||||
|
||||
return text.format_map(values)
|
||||
|
||||
|
||||
mail_text_order_placed = MailTemplateRenderer(
|
||||
['event', 'total', 'currency', 'date', 'payment_info', 'url', 'invoice_name', 'invoice_company']
|
||||
)
|
||||
mail_text_order_paid = MailTemplateRenderer(
|
||||
['event', 'url', 'invoice_name', 'invoice_company', 'payment_info']
|
||||
)
|
||||
mail_text_order_free = MailTemplateRenderer(
|
||||
['event', 'url', 'invoice_name', 'invoice_company']
|
||||
)
|
||||
mail_text_order_changed = MailTemplateRenderer(
|
||||
['event', 'url', 'invoice_name', 'invoice_company']
|
||||
)
|
||||
mail_text_resend_link = MailTemplateRenderer(
|
||||
['event', 'url', 'invoice_name', 'invoice_company']
|
||||
)
|
||||
mail_text_resend_all_links = MailTemplateRenderer(
|
||||
['event', 'orders']
|
||||
)
|
||||
mail_text_order_expire_warning = MailTemplateRenderer(
|
||||
['event', 'url', 'expire_date', 'invoice_name', 'invoice_company']
|
||||
)
|
||||
mail_text_waiting_list = MailTemplateRenderer(
|
||||
['event', 'url', 'product', 'hours', 'code']
|
||||
)
|
||||
mail_text_order_canceled = MailTemplateRenderer(
|
||||
['event', 'url', 'code']
|
||||
)
|
||||
mail_text_order_custom_mail = MailTemplateRenderer(
|
||||
['expire_date', 'event', 'code', 'date', 'url', 'invoice_name', 'invoice_company']
|
||||
)
|
||||
mail_text_download_reminder = MailTemplateRenderer(
|
||||
['event', 'url']
|
||||
)
|
||||
|
||||
@@ -9,8 +9,6 @@ from hierarkey.forms import HierarkeyForm
|
||||
from pretix.base.models import Event
|
||||
from pretix.base.reldate import RelativeDateField, RelativeDateTimeField
|
||||
|
||||
from .validators import PlaceholderValidator # NOQA
|
||||
|
||||
logger = logging.getLogger('pretix.plugins.ticketoutputpdf')
|
||||
|
||||
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
import re
|
||||
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.core.validators import BaseValidator
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from i18nfield.strings import LazyI18nString
|
||||
|
||||
|
||||
class PlaceholderValidator(BaseValidator):
|
||||
"""
|
||||
Takes list of allowed placeholders,
|
||||
validates form field by checking for placeholders,
|
||||
which are not presented in taken list.
|
||||
"""
|
||||
|
||||
def __init__(self, limit_value):
|
||||
super().__init__(limit_value)
|
||||
self.limit_value = limit_value
|
||||
|
||||
def __call__(self, value):
|
||||
if isinstance(value, LazyI18nString):
|
||||
for l, v in value.data.items():
|
||||
self.__call__(v)
|
||||
return
|
||||
|
||||
data_placeholders = list(re.findall(r'({[\w\s]*})', value, re.X))
|
||||
invalid_placeholders = []
|
||||
for placeholder in data_placeholders:
|
||||
if placeholder not in self.limit_value:
|
||||
invalid_placeholders.append(placeholder)
|
||||
if invalid_placeholders:
|
||||
raise ValidationError(
|
||||
_('Invalid placeholder(s): %(value)s'),
|
||||
code='invalid',
|
||||
params={'value': ", ".join(invalid_placeholders,)})
|
||||
|
||||
def clean(self, x):
|
||||
return x
|
||||
@@ -1,6 +1,42 @@
|
||||
import re
|
||||
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.core.validators import BaseValidator
|
||||
from django.utils.deconstruct import deconstructible
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from i18nfield.strings import LazyI18nString
|
||||
|
||||
|
||||
class PlaceholderValidator(BaseValidator):
|
||||
"""
|
||||
Takes list of allowed placeholders,
|
||||
validates form field by checking for placeholders,
|
||||
which are not presented in taken list.
|
||||
"""
|
||||
|
||||
def __init__(self, limit_value):
|
||||
super().__init__(limit_value)
|
||||
self.limit_value = limit_value
|
||||
|
||||
def __call__(self, value):
|
||||
if isinstance(value, LazyI18nString):
|
||||
for l, v in value.data.items():
|
||||
self.__call__(v)
|
||||
return
|
||||
|
||||
data_placeholders = list(re.findall(r'({[\w\s]*})', value, re.X))
|
||||
invalid_placeholders = []
|
||||
for placeholder in data_placeholders:
|
||||
if placeholder not in self.limit_value:
|
||||
invalid_placeholders.append(placeholder)
|
||||
if invalid_placeholders:
|
||||
raise ValidationError(
|
||||
_('Invalid placeholder(s): %(value)s'),
|
||||
code='invalid',
|
||||
params={'value': ", ".join(invalid_placeholders,)})
|
||||
|
||||
def clean(self, x):
|
||||
return x
|
||||
|
||||
|
||||
class BlacklistValidator:
|
||||
|
||||
@@ -8,13 +8,15 @@ from django.utils.translation import ugettext_lazy as _
|
||||
from i18nfield.forms import I18nFormField, I18nTextarea
|
||||
from pytz import common_timezones, timezone
|
||||
|
||||
from pretix.base.forms import I18nModelForm, PlaceholderValidator, SettingsForm
|
||||
from pretix.base.forms import I18nModelForm, SettingsForm
|
||||
from pretix.base.models import Event, Organizer, TaxRule
|
||||
from pretix.base.models.event import EventMetaValue
|
||||
from pretix.base.reldate import RelativeDateField, RelativeDateTimeField
|
||||
from pretix.base.validators import PlaceholderValidator
|
||||
from pretix.control.forms import ExtFileField, SlugWidget
|
||||
from pretix.multidomain.urlreverse import build_absolute_uri
|
||||
from pretix.presale.style import get_fonts
|
||||
from pretix.base import email
|
||||
|
||||
|
||||
class EventWizardFoundationForm(forms.Form):
|
||||
@@ -580,7 +582,6 @@ class MailSettingsForm(SettingsForm):
|
||||
label=_("Sender address"),
|
||||
help_text=_("Sender address for outgoing emails")
|
||||
)
|
||||
|
||||
mail_text_signature = I18nFormField(
|
||||
label=_("Signature"),
|
||||
required=False,
|
||||
@@ -588,50 +589,29 @@ class MailSettingsForm(SettingsForm):
|
||||
help_text=_("This will be attached to every email. Available placeholders: {event}"),
|
||||
validators=[PlaceholderValidator(['{event}'])]
|
||||
)
|
||||
|
||||
mail_text_order_placed = I18nFormField(
|
||||
mail_text_order_placed = email.mail_text_order_placed.formfield(
|
||||
label=_("Text"),
|
||||
required=False,
|
||||
widget=I18nTextarea,
|
||||
help_text=_("Available placeholders: {event}, {total}, {currency}, {date}, {payment_info}, {url}, "
|
||||
"{invoice_name}, {invoice_company}"),
|
||||
validators=[PlaceholderValidator(['{event}', '{total}', '{currency}', '{date}', '{payment_info}',
|
||||
'{url}', '{invoice_name}', '{invoice_company}'])]
|
||||
)
|
||||
mail_text_order_paid = I18nFormField(
|
||||
mail_text_order_paid = email.mail_text_order_paid.formfield(
|
||||
label=_("Text"),
|
||||
required=False,
|
||||
widget=I18nTextarea,
|
||||
help_text=_("Available placeholders: {event}, {url}, {invoice_name}, {invoice_company}, {payment_info}"),
|
||||
validators=[PlaceholderValidator(['{event}', '{url}', '{invoice_name}', '{invoice_company}', '{payment_info}'])]
|
||||
)
|
||||
mail_text_order_free = I18nFormField(
|
||||
mail_text_order_free = email.mail_text_order_free.formfield(
|
||||
label=_("Text"),
|
||||
required=False,
|
||||
widget=I18nTextarea,
|
||||
help_text=_("Available placeholders: {event}, {url}, {invoice_name}, {invoice_company}"),
|
||||
validators=[PlaceholderValidator(['{event}', '{url}', '{invoice_name}', '{invoice_company}'])]
|
||||
)
|
||||
mail_text_order_changed = I18nFormField(
|
||||
mail_text_order_changed = email.mail_text_order_changed.formfield(
|
||||
label=_("Text"),
|
||||
required=False,
|
||||
widget=I18nTextarea,
|
||||
help_text=_("Available placeholders: {event}, {url}, {invoice_name}, {invoice_company}"),
|
||||
validators=[PlaceholderValidator(['{event}', '{url}', '{invoice_name}', '{invoice_company}'])]
|
||||
)
|
||||
mail_text_resend_link = I18nFormField(
|
||||
mail_text_resend_link = email.mail_text_resend_link.formfield(
|
||||
label=_("Text (sent by admin)"),
|
||||
required=False,
|
||||
widget=I18nTextarea,
|
||||
help_text=_("Available placeholders: {event}, {url}, {invoice_name}, {invoice_company}"),
|
||||
validators=[PlaceholderValidator(['{event}', '{url}', '{invoice_name}', '{invoice_company}'])]
|
||||
)
|
||||
mail_text_resend_all_links = I18nFormField(
|
||||
mail_text_resend_all_links = email.mail_text_resend_all_links.formfield(
|
||||
label=_("Text (requested by user)"),
|
||||
required=False,
|
||||
widget=I18nTextarea,
|
||||
help_text=_("Available placeholders: {event}, {orders}"),
|
||||
validators=[PlaceholderValidator(['{event}', '{orders}'])]
|
||||
)
|
||||
mail_days_order_expire_warning = forms.IntegerField(
|
||||
label=_("Number of days"),
|
||||
@@ -640,42 +620,25 @@ class MailSettingsForm(SettingsForm):
|
||||
help_text=_("This email will be sent out this many days before the order expires. If the "
|
||||
"value is 0, the mail will never be sent.")
|
||||
)
|
||||
mail_text_order_expire_warning = I18nFormField(
|
||||
mail_text_order_expire_warning = email.mail_text_order_expire_warning.formfield(
|
||||
label=_("Text"),
|
||||
required=False,
|
||||
widget=I18nTextarea,
|
||||
help_text=_("Available placeholders: {event}, {url}, {expire_date}, {invoice_name}, {invoice_company}"),
|
||||
validators=[PlaceholderValidator(['{event}', '{url}', '{expire_date}', '{invoice_name}', '{invoice_company}'])]
|
||||
)
|
||||
mail_text_waiting_list = I18nFormField(
|
||||
mail_text_waiting_list = email.mail_text_waiting_list.formfield(
|
||||
label=_("Text"),
|
||||
required=False,
|
||||
widget=I18nTextarea,
|
||||
help_text=_("Available placeholders: {event}, {url}, {product}, {hours}, {code}"),
|
||||
validators=[PlaceholderValidator(['{event}', '{url}', '{product}', '{hours}', '{code}'])]
|
||||
)
|
||||
mail_text_order_canceled = I18nFormField(
|
||||
mail_text_order_canceled = email.mail_text_order_canceled.formfield(
|
||||
label=_("Text"),
|
||||
required=False,
|
||||
widget=I18nTextarea,
|
||||
help_text=_("Available placeholders: {event}, {code}, {url}"),
|
||||
validators=[PlaceholderValidator(['{event}', '{code}', '{url}'])]
|
||||
)
|
||||
mail_text_order_custom_mail = I18nFormField(
|
||||
mail_text_order_custom_mail = email.mail_text_order_custom_mail.formfield(
|
||||
label=_("Text"),
|
||||
required=False,
|
||||
widget=I18nTextarea,
|
||||
help_text=_("Available placeholders: {expire_date}, {event}, {code}, {date}, {url}, "
|
||||
"{invoice_name}, {invoice_company}"),
|
||||
validators=[PlaceholderValidator(['{expire_date}', '{event}', '{code}', '{date}', '{url}',
|
||||
'{invoice_name}', '{invoice_company}'])]
|
||||
)
|
||||
mail_text_download_reminder = I18nFormField(
|
||||
mail_text_download_reminder = email.mail_text_download_reminder.formfield(
|
||||
label=_("Text"),
|
||||
required=False,
|
||||
widget=I18nTextarea,
|
||||
help_text=_("Available placeholders: {event}, {url}"),
|
||||
validators=[PlaceholderValidator(['{event}', '{url}'])]
|
||||
)
|
||||
mail_days_download_reminder = forms.IntegerField(
|
||||
label=_("Number of days"),
|
||||
|
||||
@@ -6,12 +6,14 @@ from django.utils.formats import localize
|
||||
from django.utils.timezone import now
|
||||
from django.utils.translation import pgettext_lazy, ugettext_lazy as _
|
||||
|
||||
from pretix.base.forms import I18nModelForm, PlaceholderValidator
|
||||
from pretix.base.email import mail_text_order_custom_mail
|
||||
from pretix.base.forms import I18nModelForm
|
||||
from pretix.base.models import (
|
||||
InvoiceAddress, Item, ItemAddOn, Order, OrderPosition,
|
||||
)
|
||||
from pretix.base.models.event import SubEvent
|
||||
from pretix.base.services.pricing import get_price
|
||||
from pretix.base.validators import PlaceholderValidator
|
||||
|
||||
|
||||
class ExtendForm(I18nModelForm):
|
||||
@@ -269,13 +271,9 @@ class OrderMailForm(forms.Form):
|
||||
initial=order.email
|
||||
)
|
||||
self.fields['sendto'].widget.attrs['readonly'] = 'readonly'
|
||||
self.fields['message'] = forms.CharField(
|
||||
self.fields['message'] = mail_text_order_custom_mail.formfield(
|
||||
label=_("Message"),
|
||||
required=True,
|
||||
widget=forms.Textarea,
|
||||
initial=order.event.settings.mail_text_order_custom_mail.localize(order.locale),
|
||||
help_text=_("Available placeholders: {expire_date}, {event}, {code}, {date}, {url}, "
|
||||
"{invoice_name}, {invoice_company}"),
|
||||
validators=[PlaceholderValidator(['{expire_date}', '{event}', '{code}', '{date}', '{url}',
|
||||
'{invoice_name}', '{invoice_company}'])]
|
||||
)
|
||||
|
||||
6
src/pretix/plugins/sendmail/email.py
Normal file
6
src/pretix/plugins/sendmail/email.py
Normal file
@@ -0,0 +1,6 @@
|
||||
from pretix.base.email import MailTemplateRenderer
|
||||
|
||||
mail_text_sendmail = MailTemplateRenderer(
|
||||
['expire_date', 'event', 'code', 'date', 'url', 'invoice_name', 'invoice_company']
|
||||
)
|
||||
|
||||
@@ -2,9 +2,9 @@ from django import forms
|
||||
from django.utils.translation import pgettext_lazy, ugettext_lazy as _
|
||||
from i18nfield.forms import I18nFormField, I18nTextarea, I18nTextInput
|
||||
|
||||
from pretix.base.forms import PlaceholderValidator
|
||||
from pretix.base.models import Order
|
||||
from pretix.base.models.event import SubEvent
|
||||
from pretix.plugins.sendmail.email import mail_text_sendmail
|
||||
|
||||
|
||||
class MailForm(forms.Form):
|
||||
@@ -25,13 +25,9 @@ class MailForm(forms.Form):
|
||||
widget=I18nTextInput, required=True,
|
||||
locales=event.settings.get('locales')
|
||||
)
|
||||
self.fields['message'] = I18nFormField(
|
||||
self.fields['message'] = mail_text_sendmail.formfield(
|
||||
widget=I18nTextarea, required=True,
|
||||
locales=event.settings.get('locales'),
|
||||
help_text=_("Available placeholders: {expire_date}, {event}, {code}, {date}, {url}, "
|
||||
"{invoice_name}, {invoice_company}"),
|
||||
validators=[PlaceholderValidator(['{expire_date}', '{event}', '{code}', '{date}', '{url}',
|
||||
'{invoice_name}', '{invoice_company}'])]
|
||||
)
|
||||
choices = list(Order.STATUS_CHOICE)
|
||||
if not event.settings.get('payment_term_expire_automatically', as_type=bool):
|
||||
|
||||
@@ -17,6 +17,7 @@ from pretix.base.models.event import SubEvent
|
||||
from pretix.base.services.mail import SendMailException, mail
|
||||
from pretix.control.permissions import EventPermissionRequiredMixin
|
||||
from pretix.multidomain.urlreverse import build_absolute_uri
|
||||
from pretix.plugins.sendmail.email import mail_text_sendmail
|
||||
|
||||
from . import forms
|
||||
|
||||
@@ -82,8 +83,8 @@ class SenderView(EventPermissionRequiredMixin, FormView):
|
||||
self.output[l] = []
|
||||
self.output[l].append(
|
||||
_('Subject: {subject}').format(subject=form.cleaned_data['subject'].localize(l)))
|
||||
message = form.cleaned_data['message'].localize(l)
|
||||
preview_text = message.format(
|
||||
preview_text = mail_text_sendmail.preview(
|
||||
text=form.cleaned_data['message'].localize(l),
|
||||
code='ORDER1234',
|
||||
event=self.request.event.name,
|
||||
date=date_format(now(), 'SHORT_DATE_FORMAT'),
|
||||
|
||||
Reference in New Issue
Block a user