From 825e58a9f99ec05f3bd45119e2ba0786541b9022 Mon Sep 17 00:00:00 2001 From: HacKan Date: Fri, 6 Apr 2018 01:24:59 -0300 Subject: [PATCH] Send HTML emails Closes #253. --- eventol/manager/models.py | 10 ++++- eventol/manager/utils/email.py | 55 +++++++++++++++++-------- eventol/manager/views.py | 75 ++++++++++++++++++++++++---------- 3 files changed, 99 insertions(+), 41 deletions(-) diff --git a/eventol/manager/models.py b/eventol/manager/models.py index c92906b8..bdfe24c6 100644 --- a/eventol/manager/models.py +++ b/eventol/manager/models.py @@ -113,7 +113,15 @@ class ContactMessage(models.Model): blank=True, null=True) def __str__(self): - return '{} - {} ({})'.format(self.event, self.name, self.email) + return _( + 'Message received from: {name}\n' + 'User email: {email}\n\n' + '{message}' + ).format( + name=self.name, + email=self.email, + message=self.message + ) class Meta(object): verbose_name = _('Contact Message') diff --git a/eventol/manager/utils/email.py b/eventol/manager/utils/email.py index 11553d6b..5cd703af 100644 --- a/eventol/manager/utils/email.py +++ b/eventol/manager/utils/email.py @@ -1,27 +1,46 @@ import cairosvg -from django.core.mail import EmailMessage, EmailMultiAlternatives +from django.core.mail import EmailMultiAlternatives from django.utils.translation import ugettext_lazy as _ def get_ticket_subject(event_name): - return _('Ticket for {} event').format(event_name) + return _('Ticket for {event_name} event').format(event_name=event_name) def get_ticket_body(first_name, last_name, event_name): - lines = [ - 'Hello {0} {1},'.format(first_name, last_name), - 'Here is your ticket for {} event.'.format(event_name), - 'Please remember to print it and bring it with ' + - 'you the day of the event.', - 'Regards, FLISoL {} team.'.format(event_name) - ] - return '\n'.join(lines) + body_txt = _( + 'Hello {first_name} {last_name},\n' + 'Here is your ticket for {event_name} event.\n' + 'Please remember to print it and bring it with you the day(s) of the event.\n' + 'Regards,\n' + '{event_name} and eventoL team' + ).format( + first_name=first_name, + last_name=last_name, + event_name=event_name + ) + body_html = _( + '

Hello {first_name} {last_name},
\n' + 'Here is your ticket for {event_name} event.

\n' + '

Please remember to print it and bring it with you the day(s) of the event.

\n' + '

Regards,\n' + '{event_name} and eventoL team

' + ).format( + first_name=first_name, + last_name=last_name, + event_name=event_name + ) + return (body_txt, body_html) def get_installation_subject(first_name, last_name, event_name): - return _('{0} {1}, thank you for participating in FLISoL {2}'.format( - first_name, last_name, event_name)) + # ToDo: has FLISoL string + return _( + '{first_name} {last_name}, thank you for participating in FLISoL {event_name}' + ).format( + first_name=first_name, last_name=last_name, event_name=event_name + ) def send_ticket_email(ticket_data, ticket_svg): @@ -29,14 +48,14 @@ def send_ticket_email(ticket_data, ticket_svg): first_name = ticket_data['first_name'] last_name = ticket_data['last_name'] email_to = ticket_data['email'] - ticket_id = ticket_data['ticket'].id - email = EmailMessage() + ticket_code = ticket_data['ticket'].code + email = EmailMultiAlternatives() email.subject = get_ticket_subject(event_name) - email.body = get_ticket_body( - first_name, last_name, event_name) + body_txt, body_html = get_ticket_body(first_name, last_name, event_name) + email.body = body_txt + email.attach_alternative(body_html, "text/html") email.to = [email_to] - ticket_id = str(ticket_id).zfill(12) - email.attach('Ticket-{}.pdf'.format(ticket_id), + email.attach('Ticket-{}.pdf'.format(ticket_code), cairosvg.svg2pdf(bytestring=ticket_svg), 'application/pdf') email.send(fail_silently=False) diff --git a/eventol/manager/views.py b/eventol/manager/views.py index 76e28906..95a65385 100644 --- a/eventol/manager/views.py +++ b/eventol/manager/views.py @@ -16,14 +16,14 @@ from django.contrib.auth.decorators import login_required, permission_required from django.contrib.auth.models import Permission from django.contrib.contenttypes.models import ContentType -from django.core.mail import EmailMessage, EmailMultiAlternatives +from django.core.mail import EmailMultiAlternatives from django.core.urlresolvers import reverse from django.forms import modelformset_factory from django.http import HttpResponse from django.shortcuts import get_object_or_404, render, render_to_response, redirect from django.utils import timezone from django.utils.translation import ugettext_lazy as _, ugettext -from django.utils.formats import localize +from django.utils.formats import localize, date_format from django.core.validators import validate_email from django.core.exceptions import ValidationError from lxml import etree @@ -42,7 +42,7 @@ add_attendance_permission, is_collaborator, \ add_organizer_permissions, is_collaborator_or_installer -from .utils import email +from .utils import email as utils_email logger = logging.getLogger('eventol') @@ -139,7 +139,7 @@ def send_event_ticket(user): ticket_svg = generate_ticket(user) ticket_data = user.get_ticket_data() try: - email.send_ticket_email(ticket_data, ticket_svg) + utils_email.send_ticket_email(ticket_data, ticket_svg) ticket_data['ticket'].sent = True ticket_data['ticket'].save() except Exception as error: @@ -243,7 +243,7 @@ def installation(request, event_slug, event_uid): .filter(event=event).first() if postinstall_email: try: - email.send_installation_email( + utils_email.send_installation_email( event.name, postinstall_email, install.attendee) except Exception: # Don't raise email exception to form exception @@ -819,18 +819,13 @@ def contact(request, event_slug, event_uid): event = Event.objects.filter(uid=event_uid).get() if not event: return handler404(request) - contact_message = ContactMessage() - form = ContactMessageForm(request.POST or None, instance=contact_message) + form = ContactMessageForm(request.POST or None) if request.POST: if form.is_valid(): contact_message = form.save() - info = _("Message received from ") + contact_message.name + "\n" - info += _("User email: ") + contact_message.email + "\n" - contact_message.message = info + contact_message.message - - email = EmailMessage() - email.subject = _("eventoL Contact Message from " + contact_message.name) - email.body = contact_message.message + email = EmailMultiAlternatives() + email.subject = _("[eventoL] Contact message from {name}").format(name=contact_message.name) + email.body = str(contact_message) email.from_email = contact_message.email email.to = [event.email] email.extra_headers = {'Reply-To': contact_message.email} @@ -1063,14 +1058,50 @@ def attendee_registration(request, event_slug, event_uid): if request.user.is_authenticated(): return redirect(confirm_url) - body = _("Hi! You're receiving this message because you've registered to attend to " + - "FLISoL %(event_name)s.\n\nPlease follow this link to confirm your email address and we'll " + - "send you your ticket.\n\n%(confirm_url)s") % {'event_name': event.name, - 'confirm_url': confirm_url} - - email = EmailMessage() - email.subject = _("[FLISoL] Please confirm your email") - email.body = body + # ToDo: it has a FLISoL hardcoded string + body_text = _( + 'Hi! You are receiving this message because you have registered to attend to FLISoL ' + '{event_name}, being held on {event_dates}.\n\n' + 'Please follow this link to confirm your email address and we will send you your ' + 'ticket:\n' + '{confirm_url}\n\n' + 'If you encounter any issue, please contact the event organizer in ' + '{event_contact_url}.\n\n' + 'Happily yours,\n' + '{event_name} and eventoL team' + ).format( + event_name=event.name, + event_dates=', '.join([ + date_format(eventdate.date, format='SHORT_DATE_FORMAT', use_l10n=True) + for eventdate in EventDate.objects.filter(event=event) + ]), + event_contact_url=reverse('contact', args=[event_slug, event_uid]), + confirm_url=confirm_url + ) + body_html = _( + '

Hi! You are receiving this message because you have registered to attend to FLISoL ' + '{event_name}, being held on {event_dates}.

\n' + '

Please follow this link to confirm your email address and we will send you your ' + 'ticket:
\n' + '{confirm_url}

\n' + '

If you encounter any issue, please contact the event organizer in ' + '{event_contact_url}.

\n' + '

Happily yours,
\n' + '{event_name} and eventoL team

' + ).format( + event_name=event.name, + event_dates=', '.join([ + date_format(eventdate.date, format='SHORT_DATE_FORMAT', use_l10n=True) + for eventdate in EventDate.objects.filter(event=event) + ]), + event_contact_url=reverse('contact', args=[event_slug, event_uid]), + confirm_url=confirm_url + ) + + email = EmailMultiAlternatives() + email.subject = _("[eventoL] Please confirm your email") + email.body = body_text + email.attach_alternative(body_html, "text/html") email.from_email = settings.EMAIL_FROM email.to = [attendee.email] email.extra_headers = {'Reply-To': settings.EMAIL_FROM}