Send e-mails on order completion (#27)

This commit is contained in:
Raphael Michel
2015-04-01 10:30:07 +02:00
parent 8a81d4859d
commit 16244bd69c
9 changed files with 105 additions and 2 deletions

View File

@@ -77,6 +77,8 @@ The provider class
.. automethod:: checkout_perform .. automethod:: checkout_perform
.. automethod:: order_pending_mail_render
.. automethod:: order_pending_render .. automethod:: order_pending_render
This is an abstract method, you **must** override this! This is an abstract method, you **must** override this!

51
src/pretix/base/mail.py Normal file
View File

@@ -0,0 +1,51 @@
import logging
from django.conf import settings
from django.core.mail import EmailMessage
from django.template.loader import get_template
from django.utils import translation
from pretix.base.models import User, Event
logger = logging.getLogger('pretix.base.mail')
def mail(user: User, subject: str, template: str, context: dict, event: Event=None):
"""
Sends out an email to a user.
:param user: The user this should be sent to.
:param subject: The e-mail subject. Should be localized.
:param template: The filename of a template to be used. It will
be rendered with the recipient's locale.
:param context: The context for rendering the template.
:param event: The event, used for determining the sender of the e-mail
:return: ``False`` on obvious failures, like the user having to e-mail
address, ``True`` otherwise. ``True`` does not necessarily mean that
the email has been sent, just that it has been queued by the e-mail
backend.
"""
if not user.email:
return False
_lng = translation.get_language()
translation.activate(user.locale or settings.LANGUAGE_CODE)
tpl = get_template(template)
body = tpl.render(context)
sender = event.settings.get('mail_from') if event else settings.MAIL_FROM
email = EmailMessage(
subject, body, sender,
to=[user.email]
)
try:
email.send(fail_silently=False)
return True
except Exception:
logger.exception('Error sending e-mail')
return False
finally:
translation.activate(_lng)

View File

@@ -248,6 +248,16 @@ class BasePaymentProvider:
""" """
return None return None
def order_pending_mail_render(self, order: Order) -> str:
"""
After the user submitted his order, he or she will receive a confirmation
e-mail. You can return a string from this method if you want to add additional
information to this e-mail.
:param order: The order object
"""
return ""
def order_pending_render(self, request: HttpRequest, order: Order) -> str: def order_pending_render(self, request: HttpRequest, order: Order) -> str:
""" """
If the user visits a detail page of an order which has not yet been paid but If the user visits a detail page of an order which has not yet been paid but

View File

@@ -4,6 +4,7 @@ import decimal
import dateutil.parser import dateutil.parser
from django.db.models import Model from django.db.models import Model
from django.conf import settings
from versions.models import Versionable from versions.models import Versionable
@@ -14,6 +15,7 @@ DEFAULTS = {
'attendee_names_required': 'False', 'attendee_names_required': 'False',
'reservation_time': '30', 'reservation_time': '30',
'last_order_modification_date': None, 'last_order_modification_date': None,
'mail_from': settings.MAIL_FROM,
} }

View File

@@ -41,6 +41,11 @@ class BankTransfer(BasePaymentProvider):
ctx = {'request': request, 'form': form, 'settings': self.settings} ctx = {'request': request, 'form': form, 'settings': self.settings}
return template.render(ctx) return template.render(ctx)
def order_pending_mail_render(self, order) -> str:
template = get_template('pretixplugins/banktransfer/email/order_pending.txt')
ctx = {'event': self.event, 'order': order, 'settings': self.settings}
return template.render(ctx)
def order_pending_render(self, request, order) -> str: def order_pending_render(self, request, order) -> str:
template = get_template('pretixplugins/banktransfer/pending.html') template = get_template('pretixplugins/banktransfer/pending.html')
ctx = {'request': request, 'order': order, 'settings': self.settings} ctx = {'request': request, 'order': order, 'settings': self.settings}

View File

@@ -0,0 +1,5 @@
{% load i18n %}{% blocktrans with bank=settings.bank_details code=order.full_code %}
Please transfer the full amount to the following bank account.
Reference: {{ code }}
{{ bank }}{% endblocktrans %}

View File

@@ -0,0 +1,13 @@
{% load i18n %}{% blocktrans with event=event.name total=order.total|floatformat:2 currency=event.currency paymentinfo=payment date=order.expires|date url=url %}Hello,
we successfully received your order for {{ event }} with a total value
of {{ total }} {{ currency }}. Please complete your payment before {{ date }}.
{{ paymentinfo }}
You can view the status of your order at
{{ url }}
Best regards,
Your {{ event }} team
{% endblocktrans %}

View File

@@ -4,11 +4,13 @@ from django.core.urlresolvers import reverse
from django.db import transaction from django.db import transaction
from django.db.models import Q, Sum from django.db.models import Q, Sum
from django import forms from django import forms
from django.http import HttpRequest
from django.shortcuts import redirect from django.shortcuts import redirect
from django.utils.functional import cached_property from django.utils.functional import cached_property
from django.utils.timezone import now from django.utils.timezone import now
from django.views.generic import TemplateView from django.views.generic import TemplateView
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from pretix.base.mail import mail
from pretix.base.models import CartPosition, Question, QuestionAnswer, Quota, Order, OrderPosition from pretix.base.models import CartPosition, Question, QuestionAnswer, Quota, Order, OrderPosition
from pretix.base.signals import register_payment_providers from pretix.base.signals import register_payment_providers
@@ -319,7 +321,7 @@ class OrderConfirm(EventViewMixin, CartDisplayMixin, EventLoginRequiredMixin, Ch
self.request = request self.request = request
return self.check_process(request) or self.perform_order(request) return self.check_process(request) or self.perform_order(request)
def perform_order(self, request): def perform_order(self, request: HttpRequest):
dt = now() dt = now()
quotas_locked = set() quotas_locked = set()
@@ -362,6 +364,17 @@ class OrderConfirm(EventViewMixin, CartDisplayMixin, EventLoginRequiredMixin, Ch
if not self.msg_some_unavailable: # Everything went well if not self.msg_some_unavailable: # Everything went well
order = self._place_order(cartpos, dt) order = self._place_order(cartpos, dt)
messages.success(request, _('Your order has been placed.')) messages.success(request, _('Your order has been placed.'))
mail(
request.user, _('Your order: %(code)s') % {'code': order.code},
'pretixpresale/email/order_placed.txt',
{
'user': request.user, 'order': order,
'event': request.event,
'url': request.build_absolute_uri(self.get_order_url(order)),
'payment': self.payment_provider.order_pending_mail_render(order)
},
request.event
)
resp = self.payment_provider.checkout_perform(request, order) resp = self.payment_provider.checkout_perform(request, order)
return redirect(resp or self.get_order_url(order)) return redirect(resp or self.get_order_url(order))

View File

@@ -193,7 +193,9 @@ LOGGING = {
}, },
} }
MAIL_FROM = 'pretix@localhost'
try: try:
from local_settings import * # NOQA from .local_settings import * # NOQA
except ImportError: except ImportError:
pass pass