diff --git a/src/pretix/plugins/sendmail/__init__.py b/src/pretix/plugins/sendmail/__init__.py index 4ece00263b..4854858aef 100644 --- a/src/pretix/plugins/sendmail/__init__.py +++ b/src/pretix/plugins/sendmail/__init__.py @@ -17,6 +17,7 @@ class SendMailApp(AppConfig): def ready(self): from . import signals # NOQA + from . import tasks # NOQA default_app_config = 'pretix.plugins.sendmail.SendMailApp' diff --git a/src/pretix/plugins/sendmail/tasks.py b/src/pretix/plugins/sendmail/tasks.py new file mode 100644 index 0000000000..099669b730 --- /dev/null +++ b/src/pretix/plugins/sendmail/tasks.py @@ -0,0 +1,63 @@ +import pytz +from django.utils.formats import date_format +from i18nfield.strings import LazyI18nString + +from pretix.base.i18n import language +from pretix.base.models import Event, InvoiceAddress, Order, User +from pretix.base.services.async import ProfiledTask +from pretix.base.services.mail import SendMailException, mail +from pretix.celery_app import app +from pretix.multidomain.urlreverse import build_absolute_uri + + +@app.task(base=ProfiledTask) +def send_mails(event: int, user: int, subject: dict, message: dict, orders: list) -> None: + failures = [] + event = Event.objects.get(pk=event) + user = User.objects.get(pk=user) if user else None + orders = Order.objects.filter(pk__in=orders) + subject = LazyI18nString(subject) + message = LazyI18nString(message) + tz = pytz.timezone(event.settings.timezone) + + for o in orders: + try: + invoice_name = o.invoice_address.name + invoice_company = o.invoice_address.company + except InvoiceAddress.DoesNotExist: + invoice_name = "" + invoice_company = "" + try: + with language(o.locale): + email_context = { + 'event': o.event, + 'code': o.code, + 'date': date_format(o.datetime.astimezone(tz), 'SHORT_DATETIME_FORMAT'), + 'expire_date': date_format(o.expires, 'SHORT_DATE_FORMAT'), + 'url': build_absolute_uri(event, 'presale:event.order', kwargs={ + 'order': o.code, + 'secret': o.secret + }), + 'invoice_name': invoice_name, + 'invoice_company': invoice_company, + } + mail( + o.email, + subject, + message, + email_context, + event, + locale=o.locale, + order=o + ) + o.log_action( + 'pretix.plugins.sendmail.order.email.sent', + user=user, + data={ + 'subject': subject.localize(o.locale), + 'message': message.localize(o.locale).format_map(email_context), + 'recipient': o.email + } + ) + except SendMailException: + failures.append(o.email) diff --git a/src/pretix/plugins/sendmail/views.py b/src/pretix/plugins/sendmail/views.py index 5069030561..586d38f1d2 100644 --- a/src/pretix/plugins/sendmail/views.py +++ b/src/pretix/plugins/sendmail/views.py @@ -1,7 +1,6 @@ import logging from datetime import timedelta -import pytz from django.contrib import messages from django.db.models import Q from django.http import Http404 @@ -12,11 +11,11 @@ from django.utils.translation import ugettext_lazy as _ from django.views.generic import FormView, ListView from pretix.base.i18n import LazyI18nString, language -from pretix.base.models import InvoiceAddress, LogEntry, Order +from pretix.base.models import LogEntry, Order 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.tasks import send_mails from . import forms @@ -71,9 +70,6 @@ class SenderView(EventPermissionRequiredMixin, FormView): orders = orders.filter(positions__subevent__in=(form.cleaned_data.get('subevent'),)) orders = orders.distinct() - tz = pytz.timezone(self.request.event.settings.timezone) - - failures = [] self.output = {} if not orders: messages.error(self.request, _('There are no orders matching this selection.')) @@ -110,50 +106,19 @@ class SenderView(EventPermissionRequiredMixin, FormView): return self.get(self.request, *self.args, **self.kwargs) - for o in orders: - try: - invoice_name = o.invoice_address.name - invoice_company = o.invoice_address.company - except InvoiceAddress.DoesNotExist: - invoice_name = "" - invoice_company = "" - try: - with language(o.locale): - email_context = { - 'event': o.event, - 'code': o.code, - 'date': date_format(o.datetime.astimezone(tz), 'SHORT_DATETIME_FORMAT'), - 'expire_date': date_format(o.expires, 'SHORT_DATE_FORMAT'), - 'url': build_absolute_uri(o.event, 'presale:event.order', kwargs={ - 'order': o.code, - 'secret': o.secret - }), - 'invoice_name': invoice_name, - 'invoice_company': invoice_company, - } - mail( - o.email, form.cleaned_data['subject'], form.cleaned_data['message'], - email_context, - self.request.event, locale=o.locale, order=o) - o.log_action( - 'pretix.plugins.sendmail.order.email.sent', - user=self.request.user, - data={ - 'subject': form.cleaned_data['subject'].localize(o.locale), - 'message': form.cleaned_data['message'].localize(o.locale).format_map(email_context), - 'recipient': o.email - } - ) - except SendMailException: - failures.append(o.email) + send_mails.apply_async( + kwargs={ + 'event': self.request.event.pk, + 'user': self.request.user.pk, + 'subject': form.cleaned_data['subject'].data, + 'message': form.cleaned_data['message'].data, + 'orders': [o.pk for o in orders], + } + ) self.request.event.log_action('pretix.plugins.sendmail.sent', user=self.request.user, data=dict(form.cleaned_data)) - if failures: - messages.error(self.request, - _('Failed to send mails to the following users: {}'.format(' '.join(failures)))) - else: - messages.success(self.request, _('Your message has been queued and will be sent to the selected users.')) + messages.success(self.request, _('Your message has been queued and will be sent to %d users in the next minutes.') % len(orders)) return redirect( 'plugins:sendmail:send',