From 111104c8e3e9487965eac9e916200a12d43bf2be Mon Sep 17 00:00:00 2001 From: Jan Szejko Date: Wed, 14 Sep 2016 12:26:43 +0200 Subject: [PATCH] newsletter --- src/ajaxable/templatetags/ajaxable_tags.py | 9 ++- src/newsletter/admin.py | 4 +- src/newsletter/forms.py | 53 +++++++++++++--- src/newsletter/models.py | 8 ++- .../newsletter/confirm_subscription.html | 7 +++ .../templates/newsletter/subscribe_email.html | 14 +++++ .../templates/newsletter/subscribe_form.html | 18 ++++++ .../templates/newsletter/subscribed.html | 9 +++ .../newsletter/unsubscribe_email.html | 6 ++ .../newsletter/unsubscribe_form.html | 16 +++++ .../templates/newsletter/unsubscribed.html | 7 +++ src/newsletter/urls.py | 7 ++- src/newsletter/views.py | 61 ++++++++++++++++++- src/suggest/forms.py | 18 +++--- src/wolnelektury/templates/main_page.html | 1 + src/wolnelektury/utils.py | 9 +++ 16 files changed, 224 insertions(+), 23 deletions(-) create mode 100644 src/newsletter/templates/newsletter/confirm_subscription.html create mode 100644 src/newsletter/templates/newsletter/subscribe_email.html create mode 100644 src/newsletter/templates/newsletter/subscribe_form.html create mode 100644 src/newsletter/templates/newsletter/subscribed.html create mode 100644 src/newsletter/templates/newsletter/unsubscribe_email.html create mode 100644 src/newsletter/templates/newsletter/unsubscribe_form.html create mode 100644 src/newsletter/templates/newsletter/unsubscribed.html diff --git a/src/ajaxable/templatetags/ajaxable_tags.py b/src/ajaxable/templatetags/ajaxable_tags.py index c262a92c3..72b9baad4 100644 --- a/src/ajaxable/templatetags/ajaxable_tags.py +++ b/src/ajaxable/templatetags/ajaxable_tags.py @@ -26,8 +26,14 @@ def pretty_field(field, template=None):
  • %(errors)s + %(helptext)s
  • ''' - return mark_safe(template % {'errors': field.errors, 'input': field, 'label': field.label}) + return mark_safe(template % { + 'errors': field.errors, + 'input': field, + 'label': field.label, + 'helptext': field.help_text, + }) @register.filter @@ -36,4 +42,5 @@ def pretty_checkbox(field):
  • %(errors)s + %(helptext)s
  • ''') diff --git a/src/newsletter/admin.py b/src/newsletter/admin.py index bcb789761..21ab43403 100644 --- a/src/newsletter/admin.py +++ b/src/newsletter/admin.py @@ -15,7 +15,9 @@ class SubscriptionAdmin(admin.ModelAdmin): return my_urls + urls def extract_subscribers(self, request): - return HttpResponse(',\n'.join(Subscription.objects.values_list('email', flat=True)), content_type='text/plain') + active_subscriptions = Subscription.objects.filter(active=True) + return HttpResponse(',\n'.join(active_subscriptions.values_list('email', flat=True)), + content_type='text/plain') admin.site.register(Subscription, SubscriptionAdmin) diff --git a/src/newsletter/forms.py b/src/newsletter/forms.py index d9f931b3d..5eb71e898 100644 --- a/src/newsletter/forms.py +++ b/src/newsletter/forms.py @@ -2,15 +2,23 @@ from django.core.exceptions import ValidationError from django.core.validators import validate_email from django.forms import Form, BooleanField -from django.utils.translation import ugettext_lazy as _ +from django.forms.fields import EmailField +from django.template.loader import render_to_string +from django.utils.translation import ugettext_lazy as _, ugettext from newsletter.models import Subscription +from wolnelektury.utils import send_noreply_mail class NewsletterForm(Form): email_field = 'email' agree_newsletter = BooleanField( - required=False, initial=True, label=_(u'I want to receive Wolne Lektury\'s newsletter.')) + required=False, initial=True, label=_(u'I want to receive Wolne Lektury\'s newsletter.'), help_text='''\ +Oświadczam, że wyrażam zgodę na przetwarzanie moich danych osobowych zawartych \ +w niniejszym formularzu zgłoszeniowym przez Fundację Nowoczesna Polska (administratora danych) z siedzibą \ +w Warszawie (00-514) przy ul. Marszałkowskiej 84/92 lok. 125 w celu otrzymywania newslettera Wolnych Lektur. \ +Jednocześnie oświadczam, że zostałam/em poinformowana/y o tym, że mam prawo wglądu w treść swoich danych i \ +możliwość ich poprawiania oraz że ich podanie jest dobrowolne, ale niezbędne do dokonania zgłoszenia.''') def save(self): try: @@ -26,8 +34,39 @@ class NewsletterForm(Form): except ValidationError: pass else: - subscription, created = Subscription.objects.get_or_create(email=email) - if not created and not subscription.active: - subscription.active = True - subscription.save() - # Send some test email? + subscription, created = Subscription.objects.get_or_create(email=email, defaults={'active': False}) + send_noreply_mail( + ugettext(u'Confirm your subscription to Wolne Lektury newsletter'), + render_to_string('newsletter/subscribe_email.html', {'subscription': subscription}), [email]) + + +class SubscribeForm(NewsletterForm): + email = EmailField(label=_('email address')) + + def __init__(self, *args, **kwargs): + super(SubscribeForm, self).__init__(*args, **kwargs) + self.fields['agree_newsletter'].required = True + + +class UnsubscribeForm(Form): + email = EmailField(label=_('email address')) + + def clean(self): + email = self.cleaned_data.get('email') + try: + subscription = Subscription.objects.get(email=email) + except Subscription.DoesNotExist: + raise ValidationError(ugettext(u'Email address not found.')) + self.cleaned_data['subscription'] = subscription + + def save(self): + subscription = self.cleaned_data['subscription'] + subscription.active = False + subscription.save() + + context = {'subscription': subscription} + # refactor to send_noreply_mail + send_noreply_mail( + ugettext(u'Unsubscribe from Wolne Lektury\'s newsletter.'), + render_to_string('newsletter/unsubscribe_email.html', context), + [subscription.email], fail_silently=True) diff --git a/src/newsletter/models.py b/src/newsletter/models.py index 6d100a380..65fc43502 100644 --- a/src/newsletter/models.py +++ b/src/newsletter/models.py @@ -1,6 +1,9 @@ # -*- coding: utf-8 -*- +import hashlib + from django.db.models import Model, EmailField, DateTimeField, BooleanField from django.utils.translation import ugettext_lazy as _ +from django.conf import settings class Subscription(Model): @@ -14,4 +17,7 @@ class Subscription(Model): verbose_name_plural = _('subscriptions') def __unicode__(self): - return self.email \ No newline at end of file + return self.email + + def hashcode(self): + return hashlib.sha224(self.email + settings.SECRET_KEY).hexdigest()[:30] diff --git a/src/newsletter/templates/newsletter/confirm_subscription.html b/src/newsletter/templates/newsletter/confirm_subscription.html new file mode 100644 index 000000000..401789e05 --- /dev/null +++ b/src/newsletter/templates/newsletter/confirm_subscription.html @@ -0,0 +1,7 @@ +{% extends "base/base.html" %} +{% load i18n %} + +{% block body %} +

    {{ page_title }}

    +

    {% trans "Your subscription to Wolne Lektury newsletter is confirmed. Thank you!" %}

    +{% endblock %} \ No newline at end of file diff --git a/src/newsletter/templates/newsletter/subscribe_email.html b/src/newsletter/templates/newsletter/subscribe_email.html new file mode 100644 index 000000000..2670a48eb --- /dev/null +++ b/src/newsletter/templates/newsletter/subscribe_email.html @@ -0,0 +1,14 @@ +Dziękujemy za zapisanie się na newsletter Wolnych Lektur! + +W celu dokończenia rejestracji kliknij w poniższy link: + +https://wolnelektury.pl{% url 'confirm_subscription' subscription_id=subscription.id hashcode=subscription.hashcode %} + +lub skopiuj go do swojej przeglądarki. + +Dopóki tego nie zrobisz, nie będziesz otrzymywał od nas newsletterów. + +Jeżeli jednak otrzymałaś/eś tę wiadomość przez przypadek i nie chcesz otrzymywać newslettera Wolnych Lektur, zignoruj ją. + +Pozdrawiamy, +zespół Wolnych Lektur \ No newline at end of file diff --git a/src/newsletter/templates/newsletter/subscribe_form.html b/src/newsletter/templates/newsletter/subscribe_form.html new file mode 100644 index 000000000..67a39ce28 --- /dev/null +++ b/src/newsletter/templates/newsletter/subscribe_form.html @@ -0,0 +1,18 @@ +{% extends "base/base.html" %} +{% load i18n %} +{% load ssify %} +{% load honeypot %} +{% load ajaxable_tags %} + +{% block body %} +

    {{ page_title }}

    +
    + {% ssi_csrf_token %} + {% render_honeypot_field %} +
      +
    1. {{ form.email|pretty_field }}
    2. +
    3. {{ form.agree_newsletter|pretty_checkbox }}
    4. +
    5. +
    +
    +{% endblock %} \ No newline at end of file diff --git a/src/newsletter/templates/newsletter/subscribed.html b/src/newsletter/templates/newsletter/subscribed.html new file mode 100644 index 000000000..a703092e0 --- /dev/null +++ b/src/newsletter/templates/newsletter/subscribed.html @@ -0,0 +1,9 @@ +{% extends "base/base.html" %} +{% load i18n %} + +{% block body %} +

    {{ page_title }}

    +

    + {% trans "You have requested subscription to Wolne Lektury newsletter. You'll receive a confirmation link by email." %} +

    +{% endblock %} \ No newline at end of file diff --git a/src/newsletter/templates/newsletter/unsubscribe_email.html b/src/newsletter/templates/newsletter/unsubscribe_email.html new file mode 100644 index 000000000..e8e34f6bf --- /dev/null +++ b/src/newsletter/templates/newsletter/unsubscribe_email.html @@ -0,0 +1,6 @@ +Dziękujemy za dotychczasowe korzystanie z newslettera Wolnych Lektur. +Jeśli w przyszłości zdecydujesz ponownie się na niego zapisać, wypełnij formularz +https://wolnelektury.pl/{% url "subscribe" %}, a będziemy Cię na bieżąco informować o naszych działaniach. + +Pozdrawiamy, +zespół Wolnych Lektur \ No newline at end of file diff --git a/src/newsletter/templates/newsletter/unsubscribe_form.html b/src/newsletter/templates/newsletter/unsubscribe_form.html new file mode 100644 index 000000000..3372d2f4c --- /dev/null +++ b/src/newsletter/templates/newsletter/unsubscribe_form.html @@ -0,0 +1,16 @@ +{% extends "base/base.html" %} +{% load i18n %} +{% load ssify %} +{% load honeypot %} + +{% block body %} +

    {{ page_title }}

    +
    + {% ssi_csrf_token %} + {% render_honeypot_field %} +
      + {{ form.as_ul }} +
    1. +
    +
    +{% endblock %} \ No newline at end of file diff --git a/src/newsletter/templates/newsletter/unsubscribed.html b/src/newsletter/templates/newsletter/unsubscribed.html new file mode 100644 index 000000000..f96c6134d --- /dev/null +++ b/src/newsletter/templates/newsletter/unsubscribed.html @@ -0,0 +1,7 @@ +{% extends "base/base.html" %} +{% load i18n %} + +{% block body %} +

    {{ page_title }}

    +

    {% trans "You have unsubscribed from Wolne Lektury newsletter. You'll receive a confirmation by email." %}

    +{% endblock %} \ No newline at end of file diff --git a/src/newsletter/urls.py b/src/newsletter/urls.py index 566f777f4..a34d98c41 100644 --- a/src/newsletter/urls.py +++ b/src/newsletter/urls.py @@ -3,5 +3,10 @@ from django.conf.urls import url from . import views urlpatterns = [ - url(r'^wypisz-sie/$', views.unsubscribe, name='unsubscribe'), + url(r'^zapisz-sie/$', views.subscribe_form, name='subscribe'), + url(r'^zapis/$', views.subscribed, name='subscribed'), + url(r'^potwierdzenie/(?P[0-9]+)/(?P[0-9a-f]+)/$', + views.confirm_subscription, name='confirm_subscription'), + url(r'^wypisz-sie/$', views.unsubscribe_form, name='unsubscribe'), + url(r'^wypisano/$', views.unsubscribed, name='unsubscribed'), ] diff --git a/src/newsletter/views.py b/src/newsletter/views.py index 847530e16..c1e4fbb19 100644 --- a/src/newsletter/views.py +++ b/src/newsletter/views.py @@ -1,9 +1,64 @@ # -*- coding: utf-8 -*- -from django.shortcuts import render +from django.core.urlresolvers import reverse +from django.http import Http404 +from django.http.response import HttpResponseRedirect +from django.shortcuts import render, get_object_or_404 from django.utils.translation import ugettext_lazy as _ +from newsletter.forms import UnsubscribeForm, SubscribeForm +from newsletter.models import Subscription -def unsubscribe(request): - return render(request, 'newsletter/unsubscribe.html', { + +def subscribe_form(request): + if request.POST: + form = SubscribeForm(request.POST) + if form.is_valid(): + form.save() + return HttpResponseRedirect(reverse('subscribed')) + else: + form = SubscribeForm() + return render(request, 'newsletter/subscribe_form.html', { + 'page_title': _(u'Subscribe'), + 'form': form, + }) + + +def subscribed(request): + return render(request, 'newsletter/subscribed.html', { + 'page_title': _(u'Subscribed'), + }) + + +def check_subscription(subscription, hashcode): + if hashcode != subscription.hashcode(): + raise Http404 + + +def confirm_subscription(request, subscription_id, hashcode): + subscription = get_object_or_404(Subscription, id=subscription_id) + check_subscription(subscription, hashcode) + subscription.active = True + subscription.save() + return render(request, 'newsletter/confirm_subscription.html', { + 'page_title': _(u'Subscription confirmed') + }) + + +def unsubscribe_form(request): + if request.POST: + form = UnsubscribeForm(request.POST) + if form.is_valid(): + form.save() + return HttpResponseRedirect(reverse('unsubscribed')) + else: + form = UnsubscribeForm() + return render(request, 'newsletter/unsubscribe_form.html', { 'page_title': _(u'Unsubscribe'), + 'form': form, + }) + + +def unsubscribed(request): + return render(request, 'newsletter/unsubscribed.html', { + 'page_title': _(u'Unsubscribed'), }) \ No newline at end of file diff --git a/src/suggest/forms.py b/src/suggest/forms.py index 452180559..717cbc733 100644 --- a/src/suggest/forms.py +++ b/src/suggest/forms.py @@ -13,6 +13,7 @@ from django.utils.translation import ugettext from newsletter.forms import NewsletterForm from suggest.models import PublishingSuggestion, Suggestion +from wolnelektury.utils import send_noreply_mail class SuggestForm(NewsletterForm): @@ -50,12 +51,12 @@ Kontakt: %(contact)s except ValidationError: pass else: - send_mail(u'[WolneLektury] ' + ugettext(u'Thank you for your suggestion.'), - ugettext(u"""\ + send_noreply_mail( + ugettext(u'Thank you for your suggestion.'), + ugettext(u"""\ Thank you for your comment on WolneLektury.pl. -The suggestion has been referred to the project coordinator.""") + - u'\n\n-- \n' + ugettext(u'''Message sent automatically. Please do not reply.'''), - 'no-reply@wolnelektury.pl', [contact], fail_silently=True) +The suggestion has been referred to the project coordinator."""), + [contact], fail_silently=True) class PublishingSuggestForm(NewsletterForm): @@ -113,9 +114,8 @@ class PublishingSuggestForm(NewsletterForm): pass else: send_mail( - u'[WolneLektury] ' + ugettext(u'Thank you for your suggestion.'), + ugettext(u'Thank you for your suggestion.'), ugettext(u"""\ Thank you for your comment on WolneLektury.pl. -The suggestion has been referred to the project coordinator.""") + - u"\n\n-- \n" + ugettext(u'''Message sent automatically. Please do not reply.'''), - 'no-reply@wolnelektury.pl', [contact], fail_silently=True) +The suggestion has been referred to the project coordinator."""), + [contact], fail_silently=True) diff --git a/src/wolnelektury/templates/main_page.html b/src/wolnelektury/templates/main_page.html index d2b7556c8..d46e19218 100755 --- a/src/wolnelektury/templates/main_page.html +++ b/src/wolnelektury/templates/main_page.html @@ -129,6 +129,7 @@
  • OAI-PMH
  • Leśmianator
  • Materiały do nauki j. polskiego
  • +
  • {% trans "Newsletter" %}
  • diff --git a/src/wolnelektury/utils.py b/src/wolnelektury/utils.py index 2ce231b1a..72bc7d0c7 100644 --- a/src/wolnelektury/utils.py +++ b/src/wolnelektury/utils.py @@ -9,11 +9,13 @@ from functools import wraps import pytz from inspect import getargspec +from django.core.mail import send_mail from django.http import HttpResponse from django.template import RequestContext from django.template.loader import render_to_string from django.utils import timezone from django.conf import settings +from django.utils.translation import ugettext tz = pytz.timezone(settings.TIME_ZONE) @@ -106,3 +108,10 @@ def ajax(login_required=False, method=None, template=None, permission_required=N return ajax_view return decorator + + +def send_noreply_mail(subject, message, recipient_list, **kwargs): + send_mail( + u'[WolneLektury] ' + subject, + message + u"\n\n-- \n" + ugettext(u'Message sent automatically. Please do not reply.'), + 'no-reply@wolnelektury.pl', recipient_list, **kwargs) -- 2.20.1