Browse Source

feat(emails): envoi de la confirmation de vote

pull/1/head
François Poulain 2 years ago committed by François Poulain
parent
commit
b3da5a897b
  1. 2
      config.env.example
  2. 39
      gvot/base/emails.py
  3. 22
      gvot/base/models.py
  4. 4
      gvot/settings/gvot.py
  5. 38
      gvot/templates/emails/notify_vote.html
  6. 1
      gvot/templates/emails/notify_vote.subject
  7. 20
      gvot/templates/emails/notify_vote.txt

2
config.env.example

@ -103,3 +103,5 @@ @@ -103,3 +103,5 @@
# Note that it's always disabled in production.
#DJANGO_DEBUG=off
#DJANGO_DEBUG_TOOLBAR=on
#
#ASSISTANCE=tech@cliss21.org

39
gvot/base/emails.py

@ -0,0 +1,39 @@ @@ -0,0 +1,39 @@
from django.conf import settings
from django.contrib.sites.shortcuts import get_current_site
from django.core.mail.message import EmailMultiAlternatives
from django.template.exceptions import TemplateDoesNotExist
from django.template.loader import render_to_string
def send_templated(request, base_tpl, context, sender, recipients, **kwargs):
def render_subject():
template = "emails/{}.subject".format(base_tpl)
subject = render_to_string(template, context, request=request)
# Email subject *must not* contain newlines
return ''.join(subject.splitlines())
def render_message(html=False):
if not html:
template = "emails/{}.txt".format(base_tpl)
else:
template = "emails/{}.html".format(base_tpl)
return render_to_string(template, context, request=request)
context.update({
'site': get_current_site(request),
'settings': {'assistance': settings.ASSISTANCE},
})
subject = render_subject()
message = render_message()
email_message = EmailMultiAlternatives(
subject, message, sender, recipients, **kwargs
)
try:
html_message = render_message(html=True)
email_message.attach_alternative(html_message, 'text/html')
except TemplateDoesNotExist:
pass
email_message.send()

22
gvot/base/models.py

@ -30,7 +30,7 @@ from wagtail.core.fields import RichTextField, StreamField @@ -30,7 +30,7 @@ from wagtail.core.fields import RichTextField, StreamField
from wagtail.core.models import Page
from wagtail.search import index
from . import blocks
from . import blocks, emails
class SitePage(Page):
@ -118,7 +118,6 @@ class ClosedScrutin(Exception): @@ -118,7 +118,6 @@ class ClosedScrutin(Exception):
# TODO: email d'annonce
# TODO: email de rappel
# TODO: email de confirmation
# TODO: afficher ouverture du scrutin dans la liste des scrutins
class Scrutin(RoutablePageMixin, AbstractEmailForm):
"""
@ -220,6 +219,7 @@ class Scrutin(RoutablePageMixin, AbstractEmailForm): @@ -220,6 +219,7 @@ class Scrutin(RoutablePageMixin, AbstractEmailForm):
return super().serve(request, *args, **kwargs)
raise Http404
# FIXME: c'est contreproductif de mettre l'uuid sous le path
@route(r'(?P<uuid>' + UUIDConverter.regex + ')')
def uuid_way(self, request, uuid, *args, **kwargs):
pouvoir = get_object_or_404(Pouvoir, uuid=uuid)
@ -236,7 +236,9 @@ class Scrutin(RoutablePageMixin, AbstractEmailForm): @@ -236,7 +236,9 @@ class Scrutin(RoutablePageMixin, AbstractEmailForm):
if form.is_valid():
try:
submission = self.process_form_submission(form, pouvoir)
submission = self.process_form_submission(
request, form, pouvoir
)
return self.render_landing_page(
request, submission, *args, **kwargs
)
@ -265,7 +267,7 @@ class Scrutin(RoutablePageMixin, AbstractEmailForm): @@ -265,7 +267,7 @@ class Scrutin(RoutablePageMixin, AbstractEmailForm):
return form_class(*args, initial=initial, **kwargs)
return form_class(*args, **kwargs)
def process_form_submission(self, form, pouvoir):
def process_form_submission(self, request, form, pouvoir):
# FIXME: documentation :
# compte tenu que les types des questions/réponses ne sont pas
# nécessairement multipliables, la seule façon de les comptabiliser
@ -291,6 +293,8 @@ class Scrutin(RoutablePageMixin, AbstractEmailForm): @@ -291,6 +293,8 @@ class Scrutin(RoutablePageMixin, AbstractEmailForm):
else:
# Mise à jour
votes.update(form_data=form_data, submit_time=timezone.now())
pouvoir.notify_vote(request)
elif not self.vote_set.exists():
# Personne n'a oncore voté ; donc on est en test
pass
@ -298,13 +302,13 @@ class Scrutin(RoutablePageMixin, AbstractEmailForm): @@ -298,13 +302,13 @@ class Scrutin(RoutablePageMixin, AbstractEmailForm):
# Quelqu'un rejoue un POST alors que l'interface ne le propose pas
raise ClosedScrutin
# TODO: notification au participant
def get_submission_class(self):
return Vote
class Pouvoir(models.Model):
# FIXME: le pouvoir devrait fournir lui même son url d'accès
# pour limiter le contexte accessible via le backend
uuid = models.UUIDField(
primary_key=True, default=uuid.uuid4, editable=False
)
@ -335,3 +339,9 @@ class Pouvoir(models.Model): @@ -335,3 +339,9 @@ class Pouvoir(models.Model):
def __str__(self):
return "{} {} ({})".format(self.prenom, self.nom, self.uuid)
def notify_vote(self, request):
context = {'pouvoir': self}
emails.send_templated(
request, 'notify_vote', context, None, [self.courriel]
)

4
gvot/settings/gvot.py

@ -1,3 +1,5 @@ @@ -1,3 +1,5 @@
from . import env
"""
Django specific settings for GvoT project.
"""
@ -15,3 +17,5 @@ WAGTAILEMBEDS_FINDERS = [ @@ -15,3 +17,5 @@ WAGTAILEMBEDS_FINDERS = [
{'class': 'wagtail.embeds.finders.oembed'},
{'class': 'wagtailembedpeertube.finders'},
]
ASSISTANCE = env('ASSISTANCE', default='assistance@localhost')

38
gvot/templates/emails/notify_vote.html

@ -0,0 +1,38 @@ @@ -0,0 +1,38 @@
<!doctype html>
<html lang="fr">
<head>
<title>
Confirmation de votre participation au scrutin « {{ pouvoir.scrutin.title }} »
</title>
</head>
<body>
<p>
Bonjour {{ pouvoir.prenom }} {{ pouvoir.nom }},
</p>
<p>
Nous avons bien enregistré votre vote pour le scrutin
« {{ pouvoir.scrutin.title }} ».
</p>
<p>
Vous pouvez à tout moment jusque la fin du scrutin retrouver votre contribution
et éventuellement la corriger à cette adresse :<br>
<a rel="noreferrer"href="{{ request.scheme }}://{{ request.get_host }}{{ pouvoir.scrutin.url_path }}{{ pouvoir.uuid }}">
{{ request.scheme }}://{{ request.get_host }}{{ pouvoir.scrutin.url_path }}{{ pouvoir.uuid }}
</a>
</p>
<p>
Merci pour votre participation.
</p>
<hr>
<p>
Ce courriel a été envoyé automatiquement ; merci de ne pas y répondre.<br>
Pour plus d'informations :
<a rel="noreferrer"href="{{ request.scheme }}://{{ request.get_host }}">
{{ request.scheme }}://{{ request.get_host }}
</a>
</p>
<p>
En cas de difficultés : <a href="mailto:{{ settings.assistance }}">contactez l'assistance</a>.
</p>
</body>
</html>

1
gvot/templates/emails/notify_vote.subject

@ -0,0 +1 @@ @@ -0,0 +1 @@
Confirmation de votre participation au scrutin « {{ pouvoir.scrutin.title | safe }} »

20
gvot/templates/emails/notify_vote.txt

@ -0,0 +1,20 @@ @@ -0,0 +1,20 @@
{% autoescape off %}
Bonjour {{ pouvoir.prenom }} {{ pouvoir.nom }},
Nous avons bien enregistré votre vote pour le scrutin
« {{ pouvoir.scrutin.title }} ».
Vous pouvez à tout moment jusque la fin du scrutin retrouver votre contribution
et éventuellement la corriger à cette adresse :
{{ request.scheme }}://{{ request.get_host }}{{ pouvoir.scrutin.url_path }}{{ pouvoir.uuid }}
Merci pour votre participation.
L'équipe organisatrice
---
Ce courriel a été envoyé automatiquement ; merci de ne pas y répondre.
Pour plus d'informations : {{ request.scheme }}://{{ request.get_host }}
En cas de difficultés : {{ settings.assistance }}
{% endautoescape %}
Loading…
Cancel
Save
Map all the world