diff --git a/src/pretix/base/exporters/mail.py b/src/pretix/base/exporters/mail.py index 31ec4fd243..2fd6ab8f71 100644 --- a/src/pretix/base/exporters/mail.py +++ b/src/pretix/base/exporters/mail.py @@ -21,7 +21,7 @@ class MailExporter(BaseExporter): pos = OrderPosition.objects.filter( order__event=self.event, order__status__in=form_data['status'] ).values('attendee_email') - data = "\r\n".join(set(a['email'] for a in addrs) + data = "\r\n".join(set(a['email'] for a in addrs if a['email']) | set(a['attendee_email'] for a in pos if a['attendee_email'])) return '{}_pretixemails.txt'.format(self.event.slug), 'text/plain', data.encode("utf-8") diff --git a/src/pretix/base/models/orders.py b/src/pretix/base/models/orders.py index 9ca28d97a2..d2af4c885c 100644 --- a/src/pretix/base/models/orders.py +++ b/src/pretix/base/models/orders.py @@ -395,6 +395,9 @@ class Order(LoggedModel): """ from pretix.base.services.mail import SendMailException, mail, render_mail + if not self.email: + return + with language(self.locale): recipient = self.email try: diff --git a/src/pretix/base/services/orders.py b/src/pretix/base/services/orders.py index e9b7f69106..b2f64a3282 100644 --- a/src/pretix/base/services/orders.py +++ b/src/pretix/base/services/orders.py @@ -521,6 +521,9 @@ def _perform_order(event: str, payment_provider: str, position_ids: List[str], if not pprov: raise OrderError(error_messages['internal']) + if email == settings.PRETIX_EMAIL_NONE_VALUE: + email = None + addr = None if address is not None: try: @@ -542,44 +545,48 @@ def _perform_order(event: str, payment_provider: str, position_ids: List[str], invoice = order.invoices.last() # Might be generated by plugin already if event.settings.get('invoice_generate') == 'True' and invoice_qualified(order): if not invoice: - invoice = generate_invoice(order, trigger_pdf=not event.settings.invoice_email_attachment) + invoice = generate_invoice( + order, + trigger_pdf=not event.settings.invoice_email_attachment or not order.email + ) # send_mail will trigger PDF generation later - if order.payment_provider == 'free': - email_template = event.settings.mail_text_order_free - log_entry = 'pretix.event.order.email.order_free' - else: - email_template = event.settings.mail_text_order_placed - log_entry = 'pretix.event.order.email.order_placed' + if order.email: + if order.payment_provider == 'free': + email_template = event.settings.mail_text_order_free + log_entry = 'pretix.event.order.email.order_free' + else: + email_template = event.settings.mail_text_order_placed + log_entry = 'pretix.event.order.email.order_placed' - try: - invoice_name = order.invoice_address.name - invoice_company = order.invoice_address.company - except InvoiceAddress.DoesNotExist: - invoice_name = "" - invoice_company = "" - email_context = { - 'total': LazyNumber(order.total), - 'currency': event.currency, - 'date': LazyDate(order.expires), - 'event': event.name, - 'url': build_absolute_uri(event, 'presale:event.order', kwargs={ - 'order': order.code, - 'secret': order.secret - }), - 'payment_info': str(pprov.order_pending_mail_render(order)), - 'invoice_name': invoice_name, - 'invoice_company': invoice_company, - } - email_subject = _('Your order: %(code)s') % {'code': order.code} - try: - order.send_mail( - email_subject, email_template, email_context, - log_entry, - invoices=[invoice] if invoice and event.settings.invoice_email_attachment else [] - ) - except SendMailException: - logger.exception('Order received email could not be sent') + try: + invoice_name = order.invoice_address.name + invoice_company = order.invoice_address.company + except InvoiceAddress.DoesNotExist: + invoice_name = "" + invoice_company = "" + email_context = { + 'total': LazyNumber(order.total), + 'currency': event.currency, + 'date': LazyDate(order.expires), + 'event': event.name, + 'url': build_absolute_uri(event, 'presale:event.order', kwargs={ + 'order': order.code, + 'secret': order.secret + }), + 'payment_info': str(pprov.order_pending_mail_render(order)), + 'invoice_name': invoice_name, + 'invoice_company': invoice_company, + } + email_subject = _('Your order: %(code)s') % {'code': order.code} + try: + order.send_mail( + email_subject, email_template, email_context, + log_entry, + invoices=[invoice] if invoice and event.settings.invoice_email_attachment else [] + ) + except SendMailException: + logger.exception('Order received email could not be sent') return order.id diff --git a/src/pretix/base/validators.py b/src/pretix/base/validators.py index 0b7d8db3d3..dd492fe4a3 100644 --- a/src/pretix/base/validators.py +++ b/src/pretix/base/validators.py @@ -1,3 +1,4 @@ +from django.conf import settings from django.core.exceptions import ValidationError from django.utils.deconstruct import deconstructible from django.utils.translation import ugettext_lazy as _ @@ -11,7 +12,7 @@ class BlacklistValidator: # Validation logic if value in self.blacklist: raise ValidationError( - _('This slug has an invalid value: %(value)s.'), + _('This field has an invalid value: %(value)s.'), code='invalid', params={'value': value}, ) @@ -56,3 +57,11 @@ class OrganizerSlugBlacklistValidator(BlacklistValidator): 'csp_report', 'widget', ] + + +@deconstructible +class EmailBlacklistValidator(BlacklistValidator): + + blacklist = [ + settings.PRETIX_EMAIL_NONE_VALUE, + ] diff --git a/src/pretix/control/templates/pretixcontrol/order/index.html b/src/pretix/control/templates/pretixcontrol/order/index.html index 4344700173..fbe6274b68 100644 --- a/src/pretix/control/templates/pretixcontrol/order/index.html +++ b/src/pretix/control/templates/pretixcontrol/order/index.html @@ -93,21 +93,23 @@ {% endif %}
{% trans "User" %}
- {{ order.email }}   + {{ order.email|default_if_none:"" }}   - - - - {% if order.status != "c" %} -
- {% csrf_token %} - -
+ {% if order.email %} + + + + {% if order.status != "c" %} +
+ {% csrf_token %} + +
+ {% endif %} {% endif %}
{% if invoices %} diff --git a/src/pretix/control/templates/pretixcontrol/orders/index.html b/src/pretix/control/templates/pretixcontrol/orders/index.html index e67706edbc..6a91e784e1 100644 --- a/src/pretix/control/templates/pretixcontrol/orders/index.html +++ b/src/pretix/control/templates/pretixcontrol/orders/index.html @@ -108,7 +108,7 @@ - {{ o.email }} + {{ o.email|default_if_none:"" }} {% if o.invoice_address.name %}
{{ o.invoice_address.name }} {% endif %} diff --git a/src/pretix/control/templates/pretixcontrol/search/orders.html b/src/pretix/control/templates/pretixcontrol/search/orders.html index 808cc36c9a..64db07e2dc 100644 --- a/src/pretix/control/templates/pretixcontrol/search/orders.html +++ b/src/pretix/control/templates/pretixcontrol/search/orders.html @@ -64,7 +64,7 @@ {{ o.event.name }} - {{ o.email }} + {{ o.email|default_if_none:"" }} {% if o.invoice_address.name %}
{{ o.invoice_address.name }} {% endif %} diff --git a/src/pretix/plugins/sendmail/views.py b/src/pretix/plugins/sendmail/views.py index dcfbbe9371..5069030561 100644 --- a/src/pretix/plugins/sendmail/views.py +++ b/src/pretix/plugins/sendmail/views.py @@ -60,7 +60,7 @@ class SenderView(EventPermissionRequiredMixin, FormView): return super().form_invalid(form) def form_valid(self, form): - qs = Order.objects.filter(event=self.request.event) + qs = Order.objects.filter(event=self.request.event, email__isnull=False) statusq = Q(status__in=form.cleaned_data['sendto']) if 'overdue' in form.cleaned_data['sendto']: statusq |= Q(status=Order.STATUS_PENDING, expires__lt=now()) diff --git a/src/pretix/presale/checkoutflow.py b/src/pretix/presale/checkoutflow.py index 18c9deb969..474a765110 100644 --- a/src/pretix/presale/checkoutflow.py +++ b/src/pretix/presale/checkoutflow.py @@ -522,6 +522,7 @@ class ConfirmStep(CartMixin, AsyncAction, TemplateFlowStep): for r, response in sorted(responses, key=lambda r: str(r[0])): for key, value in response.items(): v = self.cart_session.get('contact_form_data', {}).get(key) + v = value.bound_data(v, initial='') if v is True: v = _('Yes') elif v is False: diff --git a/src/pretix/presale/forms/checkout.py b/src/pretix/presale/forms/checkout.py index e55cb5cdf1..672cdc63e1 100644 --- a/src/pretix/presale/forms/checkout.py +++ b/src/pretix/presale/forms/checkout.py @@ -14,6 +14,7 @@ from pretix.base.forms.questions import ( from pretix.base.models import ItemVariation from pretix.base.models.tax import TAXED_ZERO from pretix.base.templatetags.rich_text import rich_text +from pretix.base.validators import EmailBlacklistValidator from pretix.presale.signals import contact_form_fields @@ -23,6 +24,7 @@ class ContactForm(forms.Form): help_text=_('Make sure to enter a valid email address. We will send you an order ' 'confirmation including a link that you need in case you want to make ' 'modifications to your order or download your ticket later.'), + validators=[EmailBlacklistValidator()], widget=forms.EmailInput(attrs={'autofocus': 'autofocus'})) def __init__(self, *args, **kwargs): diff --git a/src/pretix/presale/templates/pretixpresale/event/checkout_confirm.html b/src/pretix/presale/templates/pretixpresale/event/checkout_confirm.html index 19d337ac24..50d027a9ca 100644 --- a/src/pretix/presale/templates/pretixpresale/event/checkout_confirm.html +++ b/src/pretix/presale/templates/pretixpresale/event/checkout_confirm.html @@ -120,10 +120,12 @@
-
-
{% trans "E-mail address" %}
-
{{ cart_session.email }}
-
+ {% if "email" not in contact_info.keys %} +
+
{% trans "E-mail address" %}
+
{{ cart_session.email }}
+
+ {% endif %} {% for l, v in contact_info %}
{{ l }}
diff --git a/src/pretix/settings.py b/src/pretix/settings.py index d731ab0ecf..464730be8c 100644 --- a/src/pretix/settings.py +++ b/src/pretix/settings.py @@ -187,6 +187,7 @@ ENTROPY = { } # Internal settings +PRETIX_EMAIL_NONE_VALUE = 'none@well-known.pretix.eu' STATIC_ROOT = os.path.join(os.path.dirname(__file__), 'static.dist')