From 5c443e2f93d35dcaadba0f194e16adb91bbddb6d Mon Sep 17 00:00:00 2001 From: Daniel Date: Thu, 27 Jul 2017 21:09:06 +0800 Subject: [PATCH] Ref #569 -- Include other email to history (#570) Log all other order-specified emails and include them into email history. --- src/pretix/base/models/orders.py | 31 ++- src/pretix/base/services/mail.py | 28 +-- src/pretix/base/services/orders.py | 182 ++++++++++-------- src/pretix/control/logdisplay.py | 14 +- .../pretixcontrol/order/mail_history.html | 3 - src/pretix/control/views/orders.py | 59 +++--- 6 files changed, 178 insertions(+), 139 deletions(-) diff --git a/src/pretix/base/models/orders.py b/src/pretix/base/models/orders.py index 742174681f..cae4f72508 100644 --- a/src/pretix/base/models/orders.py +++ b/src/pretix/base/models/orders.py @@ -4,7 +4,7 @@ import os import string from datetime import datetime, time from decimal import Decimal -from typing import List, Union +from typing import Any, Dict, List, Union import pytz from django.conf import settings @@ -20,7 +20,10 @@ from django.utils.safestring import mark_safe from django.utils.timezone import make_aware, now from django.utils.translation import pgettext_lazy, ugettext_lazy as _ from django_countries.fields import CountryField +from i18nfield.strings import LazyI18nString +from pretix.base.i18n import language +from pretix.base.models import User from pretix.base.reldate import RelativeDateWrapper from ..decimal import round_decimal @@ -388,6 +391,32 @@ class Order(LoggedModel): return str(e) return True + def send_mail(self, subject: str, template: Union[str, LazyI18nString], + context: Dict[str, Any]=None, log_entry_type: str='pretix.event.order.email.sent', + user: User=None, headers: dict=None, sender: str=None): + from pretix.base.services.mail import SendMailException, mail, render_mail + + recipient = self.email + email_content = render_mail(template, context)[0] + try: + with language(self.locale): + mail( + recipient, subject, template, context, + self.event, self.locale, self, headers, sender + ) + except SendMailException: + raise + else: + self.log_action( + log_entry_type, + user=user, + data={ + 'subject': subject, + 'message': email_content, + 'recipient': recipient + } + ) + def answerfile_name(instance, filename: str) -> str: secret = get_random_string(length=32, allowed_chars=string.ascii_letters + string.digits) diff --git a/src/pretix/base/services/mail.py b/src/pretix/base/services/mail.py index 1db77717b3..b4c9731e59 100644 --- a/src/pretix/base/services/mail.py +++ b/src/pretix/base/services/mail.py @@ -81,18 +81,7 @@ def mail(email: str, subject: str, template: Union[str, LazyI18nString], 'invoice_name': '', 'invoice_company': '' }) - if isinstance(template, LazyI18nString): - body = str(template) - if context: - body = body.format_map(TolerantDict(context)) - body_md = bleach.linkify(bleach.clean(markdown.markdown(body), tags=bleach.ALLOWED_TAGS + [ - 'p', - ])) - else: - tpl = get_template(template) - body = tpl.render(context) - body_md = bleach.linkify(markdown.markdown(body)) - + body, body_md = render_mail(template, context) sender = sender or (event.settings.get('mail_from') if event else settings.MAIL_FROM) subject = str(subject) @@ -170,3 +159,18 @@ def mail_send_task(to: List[str], subject: str, body: str, html: str, sender: st def mail_send(*args, **kwargs): mail_send_task.apply_async(args=args, kwargs=kwargs) + + +def render_mail(template, context): + if isinstance(template, LazyI18nString): + body = str(template) + if context: + body = body.format_map(TolerantDict(context)) + body_md = bleach.linkify(bleach.clean(markdown.markdown(body), tags=bleach.ALLOWED_TAGS + [ + 'p', + ])) + else: + tpl = get_template(template) + body = tpl.render(context) + body_md = bleach.linkify(markdown.markdown(body)) + return body, body_md diff --git a/src/pretix/base/services/orders.py b/src/pretix/base/services/orders.py index f92cd71876..bbdd555020 100644 --- a/src/pretix/base/services/orders.py +++ b/src/pretix/base/services/orders.py @@ -31,7 +31,7 @@ from pretix.base.services.invoices import ( generate_cancellation, generate_invoice, invoice_qualified, ) from pretix.base.services.locking import LockTimeoutException -from pretix.base.services.mail import SendMailException, mail +from pretix.base.services.mail import SendMailException from pretix.base.services.pricing import get_price from pretix.base.signals import order_paid, order_placed, periodic_task from pretix.celery_app import app @@ -129,22 +129,27 @@ def mark_order_paid(order: Order, provider: str=None, info: str=None, date: date except InvoiceAddress.DoesNotExist: invoice_name = "" invoice_company = "" - mail( - order.email, _('Payment received for your order: %(code)s') % {'code': order.code}, - order.event.settings.mail_text_order_paid, - { - 'event': order.event.name, - 'url': build_absolute_uri(order.event, 'presale:event.order', kwargs={ - 'order': order.code, - 'secret': order.secret - }), - 'downloads': order.event.settings.get('ticket_download', as_type=bool), - 'invoice_name': invoice_name, - 'invoice_company': invoice_company, - 'payment_info': mail_text - }, - order.event, locale=order.locale - ) + email_template = order.event.settings.mail_text_order_paid + email_context = { + 'event': order.event.name, + 'url': build_absolute_uri(order.event, 'presale:event.order', kwargs={ + 'order': order.code, + 'secret': order.secret + }), + 'downloads': order.event.settings.get('ticket_download', as_type=bool), + 'invoice_name': invoice_name, + 'invoice_company': invoice_company, + 'payment_info': mail_text + } + email_subject = _('Payment received for your order: %(code)s') % {'code': order.code} + try: + order.send_mail( + email_subject, email_template, email_context, + 'pretix.event.order.email.order_paid', user + ) + except SendMailException: + logger.exception('Order paid email could not be sent') + return order @@ -198,20 +203,25 @@ def _cancel_order(order, user=None, send_mail: bool=True): Voucher.objects.filter(pk=position.voucher.pk).update(redeemed=F('redeemed') - 1) if send_mail: + email_template = order.event.settings.mail_text_order_canceled + email_context = { + 'event': order.event.name, + 'code': order.code, + 'url': build_absolute_uri(order.event, 'presale:event.order', kwargs={ + 'order': order.code, + 'secret': order.secret + }) + } + email_subject = _('Order canceled: %(code)s') % {'code': order.code} with language(order.locale): - mail( - order.email, _('Order canceled: %(code)s') % {'code': order.code}, - order.event.settings.mail_text_order_canceled, - { - 'event': order.event.name, - 'code': order.code, - 'url': build_absolute_uri(order.event, 'presale:event.order', kwargs={ - 'order': order.code, - 'secret': order.secret - }) - }, - order.event, locale=order.locale - ) + try: + order.send_mail( + email_subject, email_template, email_context, + 'pretix.event.order.email.order_canceled', user + ) + except SendMailException: + logger.exception('Order canceled email could not be sent') + return order.pk @@ -423,9 +433,11 @@ def _perform_order(event: str, payment_provider: str, position_ids: List[str], generate_invoice(order) if order.total == Decimal('0.00'): - mailtext = event.settings.mail_text_order_free + email_template = event.settings.mail_text_order_free + log_entry = 'pretix.event.order.email.order_free' else: - mailtext = event.settings.mail_text_order_placed + email_template = event.settings.mail_text_order_placed + log_entry = 'pretix.event.order.email.order_placed' try: invoice_name = order.invoice_address.name @@ -433,25 +445,27 @@ def _perform_order(event: str, payment_provider: str, position_ids: List[str], except InvoiceAddress.DoesNotExist: invoice_name = "" invoice_company = "" - - mail( - order.email, _('Your order: %(code)s') % {'code': order.code}, - mailtext, - { - '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, - }, - event, locale=order.locale - ) + 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 + ) + except SendMailException: + logger.exception('Order received email could not be sent') return order.id @@ -493,27 +507,25 @@ def send_expiry_warnings(sender, **kwargs): except InvoiceAddress.DoesNotExist: invoice_name = "" invoice_company = "" + email_template = eventsettings.mail_text_order_expire_warning + email_context = { + 'event': o.event.name, + 'url': build_absolute_uri(o.event, 'presale:event.order', kwargs={ + 'order': o.code, + 'secret': o.secret + }), + 'expire_date': date_format(o.expires.astimezone(tz), 'SHORT_DATE_FORMAT'), + 'invoice_name': invoice_name, + 'invoice_company': invoice_company, + } + email_subject = _('Your order is about to expire: %(code)s') % {'code': o.code} try: - with language(o.locale): - mail( - o.email, _('Your order is about to expire: %(code)s') % {'code': o.code}, - eventsettings.mail_text_order_expire_warning, - { - 'event': o.event.name, - 'url': build_absolute_uri(o.event, 'presale:event.order', kwargs={ - 'order': o.code, - 'secret': o.secret - }), - 'expire_date': date_format(o.expires.astimezone(tz), 'SHORT_DATE_FORMAT'), - 'invoice_name': invoice_name, - 'invoice_company': invoice_company, - }, - o.event, locale=o.locale - ) + o.send_mail( + email_subject, email_template, email_context, + 'pretix.event.order.email.expire_warning_sent' + ) except SendMailException: logger.exception('Reminder email could not be sent') - else: - o.log_action('pretix.event.order.expire_warning_sent') class OrderChangeManager: @@ -764,20 +776,24 @@ class OrderChangeManager: except InvoiceAddress.DoesNotExist: invoice_name = "" invoice_company = "" - mail( - self.order.email, _('Your order has been changed: %(code)s') % {'code': self.order.code}, - self.order.event.settings.mail_text_order_changed, - { - 'event': self.order.event.name, - 'url': build_absolute_uri(self.order.event, 'presale:event.order', kwargs={ - 'order': self.order.code, - 'secret': self.order.secret - }), - 'invoice_name': invoice_name, - 'invoice_company': invoice_company, - }, - self.order.event, locale=self.order.locale - ) + email_template = self.order.event.settings.mail_text_order_changed + email_context = { + 'event': self.order.event.name, + 'url': build_absolute_uri(self.order.event, 'presale:event.order', kwargs={ + 'order': self.order.code, + 'secret': self.order.secret + }), + 'invoice_name': invoice_name, + 'invoice_company': invoice_company, + } + email_subject = _('Your order has been changed: %(code)s') % {'code': self.order.code} + try: + self.order.send_mail( + email_subject, email_template, email_context, + 'pretix.event.order.email.order_changed', self.user + ) + except SendMailException: + logger.exception('Order changed email could not be sent') def commit(self): if not self._operations: diff --git a/src/pretix/control/logdisplay.py b/src/pretix/control/logdisplay.py index 2a26107ed9..590a7d0496 100644 --- a/src/pretix/control/logdisplay.py +++ b/src/pretix/control/logdisplay.py @@ -90,7 +90,6 @@ def pretixcontrol_logentry_display(sender: Event, logentry: LogEntry, **kwargs): 'pretix.event.comment': _('The event\'s internal comment has been updated.'), 'pretix.event.order.modified': _('The order details have been modified.'), 'pretix.event.order.unpaid': _('The order has been marked as unpaid.'), - 'pretix.event.order.resend': _('The link to the order detail page has been resent to the user.'), 'pretix.event.order.secret.changed': _('The order\'s secret has been changed.'), 'pretix.event.order.expirychanged': _('The order\'s expiry date has been changed.'), 'pretix.event.order.expired': _('The order has been marked as expired.'), @@ -105,9 +104,16 @@ def pretixcontrol_logentry_display(sender: Event, logentry: LogEntry, **kwargs): 'pretix.event.order.invoice.reissued': _('The invoice has been reissued.'), 'pretix.event.order.comment': _('The order\'s internal comment has been updated.'), 'pretix.event.order.payment.changed': _('The payment method has been changed.'), - 'pretix.event.order.expire_warning_sent': _('An email has been sent with a warning that the order is about ' - 'to expire.'), - 'pretix.event.order.mail_sent': _('A custom email has been sent.'), + 'pretix.event.order.email.sent': _('An unindentified type email has been sent.'), + 'pretix.event.order.email.custom_sent': _('A custom email has been sent.'), + 'pretix.event.order.email.expire_warning_sent': _('An email has been sent with a warning that the order is about ' + 'to expire.'), + 'pretix.event.order.email.order_canceled': _('An email has been sent to notify user order has been canceled.'), + 'pretix.event.order.email.order_changed': _('An email has been sent to notify user order has been changed.'), + 'pretix.event.order.email.order_free': _('An email has been sent to notify user order has been received.'), + 'pretix.event.order.email.order_paid': _('An email has been sent to notify user payment has been received.'), + 'pretix.event.order.email.order_placed': _('An email has been sent to notify user order has been received and require payment.'), + 'pretix.event.order.email.resend': _('An email has been sent with link to the order detail page has been resent to the user.'), 'pretix.user.settings.2fa.enabled': _('Two-factor authentication has been enabled.'), 'pretix.user.settings.2fa.disabled': _('Two-factor authentication has been disabled.'), 'pretix.user.settings.2fa.regenemergency': _('Your two-factor emergency codes have been regenerated.'), diff --git a/src/pretix/control/templates/pretixcontrol/order/mail_history.html b/src/pretix/control/templates/pretixcontrol/order/mail_history.html index b81f97db86..98f302a260 100644 --- a/src/pretix/control/templates/pretixcontrol/order/mail_history.html +++ b/src/pretix/control/templates/pretixcontrol/order/mail_history.html @@ -12,9 +12,6 @@ {% endblocktrans %} -
- {% trans "Includes sent custom and mass emails history only." %} -