Ref #569 -- Include other email to history (#570)

Log all other order-specified emails and include them into
email history.
This commit is contained in:
Daniel
2017-07-27 21:09:06 +08:00
committed by Raphael Michel
parent 54f01f63f7
commit 5c443e2f93
6 changed files with 178 additions and 139 deletions

View File

@@ -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)

View File

@@ -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

View File

@@ -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:

View File

@@ -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.'),

View File

@@ -12,9 +12,6 @@
{% endblocktrans %}
</a>
</h1>
<div class="alert alert-info">
{% trans "Includes sent custom and mass emails history only." %}
</div>
<div>
<ul class="list-group">
{% for log in logs %}

View File

@@ -4,7 +4,7 @@ import pytz
from django.conf import settings
from django.contrib import messages
from django.core.urlresolvers import reverse
from django.db.models import Count, Q
from django.db.models import Count
from django.http import FileResponse, Http404, HttpResponseNotAllowed
from django.shortcuts import redirect, render
from django.utils.formats import date_format
@@ -28,7 +28,7 @@ from pretix.base.services.invoices import (
regenerate_invoice,
)
from pretix.base.services.locking import LockTimeoutException
from pretix.base.services.mail import SendMailException, mail
from pretix.base.services.mail import SendMailException, render_mail
from pretix.base.services.orders import (
OrderChangeManager, OrderError, cancel_order, mark_order_paid,
)
@@ -332,26 +332,26 @@ class OrderResendLink(OrderView):
except InvoiceAddress.DoesNotExist:
invoice_name = ""
invoice_company = ""
mail(
self.order.email, _('Your order: %(code)s') % {'code': self.order.code},
self.order.event.settings.mail_text_resend_link,
{
'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_resend_link
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: %(code)s') % {'code': self.order.code}
self.order.send_mail(
email_subject, email_template, email_context,
'pretix.event.order.email.resend', user=self.request.user
)
except SendMailException:
messages.error(self.request, _('There was an error sending the mail. Please try again later.'))
return redirect(self.get_order_url())
messages.success(self.request, _('The email has been queued to be sent.'))
self.order.log_action('pretix.event.order.resend', user=self.request.user)
return redirect(self.get_order_url())
def get(self, *args, **kwargs):
@@ -684,8 +684,8 @@ class OrderSendMail(EventPermissionRequiredMixin, OrderViewMixin, FormView):
'invoice_name': invoice_name,
'invoice_company': invoice_company,
}
email_content = form.cleaned_data['message'].format_map(email_context)
email_template = LazyI18nString(form.cleaned_data['message'])
email_content = render_mail(email_template, email_context)[0]
if self.request.POST.get('action') == 'preview':
self.preview_output = []
self.preview_output.append(
@@ -694,22 +694,10 @@ class OrderSendMail(EventPermissionRequiredMixin, OrderViewMixin, FormView):
return self.get(self.request, *self.args, **self.kwargs)
else:
try:
with language(order.locale):
email_template = LazyI18nString(form.cleaned_data['message'])
mail(
order.email, form.cleaned_data['subject'],
email_template, email_context,
self.request.event, locale=order.locale,
order=order
)
order.log_action(
'pretix.event.order.mail_sent',
user=self.request.user,
data={
'subject': form.cleaned_data['subject'],
'message': email_content,
'recipient': form.cleaned_data['sendto'],
}
order.send_mail(
form.cleaned_data['subject'], email_template,
email_context, 'pretix.event.order.email.custom_sent',
self.request.user
)
messages.success(self.request, _('Your message has been queued and will be sent to {}.'.format(order.email)))
except SendMailException:
@@ -746,8 +734,7 @@ class OrderEmailHistory(EventPermissionRequiredMixin, OrderViewMixin, ListView):
).first()
qs = order.all_logentries()
qs = qs.filter(
Q(action_type="pretix.plugins.sendmail.order.email.sent")
| Q(action_type="pretix.event.order.mail_sent")
action_type__contains="order.email"
)
return qs