summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Sulfrian <alexander@sulfrian.net>2016-02-02 03:07:44 +0100
committerAlexander Sulfrian <alexander@sulfrian.net>2016-02-02 04:44:07 +0100
commit9a196839970e7d98a2bd9375bbd470846ccb3a27 (patch)
tree1c52403114bb5da11db863da72d67f2b6d75ac98
parent34b571a7335ba3d2b71409068b93df603b0271b9 (diff)
downloadweb-9a196839970e7d98a2bd9375bbd470846ccb3a27.tar.gz
web-9a196839970e7d98a2bd9375bbd470846ccb3a27.tar.bz2
web-9a196839970e7d98a2bd9375bbd470846ccb3a27.zip
templates/mail: Get all parts from the template
Also render sender and subject with the mail template, so the mails can be created with only a template name, a recipient and the template args. The required confirmation links are also generated in the templates.
-rw-r--r--accounts/__init__.py5
-rw-r--r--accounts/backend/mail/__init__.py13
-rw-r--r--accounts/backend/mail/dummy.py12
-rw-r--r--accounts/backend/mail/sendmail.py13
-rw-r--r--accounts/templates/mail/_base.txt15
-rw-r--r--accounts/templates/mail/change_mail.txt12
-rw-r--r--accounts/templates/mail/disable_notify.txt12
-rw-r--r--accounts/templates/mail/lost_password.txt10
-rw-r--r--accounts/templates/mail/register.txt12
-rw-r--r--accounts/templates/mail/register_notify.txt13
-rw-r--r--accounts/utils/__init__.py12
-rw-r--r--accounts/views/admin/__init__.py16
-rw-r--r--accounts/views/default/__init__.py34
13 files changed, 113 insertions, 66 deletions
diff --git a/accounts/__init__.py b/accounts/__init__.py
index e650586..01e5774 100644
--- a/accounts/__init__.py
+++ b/accounts/__init__.py
@@ -3,6 +3,7 @@ from flask import Flask, g, session
from models import Service
from utils import get_backend
+from utils.confirmation import Confirmation
from utils.sessions import EncryptedSessionInterface
from utils.login import create_login_manager
from views import default, login, admin
@@ -34,4 +35,8 @@ def create_app():
login_manager = create_login_manager()
login_manager.init_app(app)
+ def confirm(realm, *args):
+ return Confirmation(realm).dumps(tuple(args))
+ app.jinja_env.globals.update(confirm=confirm)
+
return app
diff --git a/accounts/backend/mail/__init__.py b/accounts/backend/mail/__init__.py
index c22b037..ecd0d45 100644
--- a/accounts/backend/mail/__init__.py
+++ b/accounts/backend/mail/__init__.py
@@ -5,5 +5,16 @@ class Backend(object):
def __init__(self, app):
self.app = app
- def send(self, recipient, subject, body, sender=None):
+ def _send(self, recipient, content):
raise NotImplementedError()
+
+ def send(self, recipient, template, **kwargs):
+ if recipient is None:
+ return
+
+ tmpl = self.app.jinja_env.get_or_select_template(template)
+
+ kwargs['recipient'] = recipient
+ module = tmpl.make_module(kwargs)
+
+ self._send(recipient, module)
diff --git a/accounts/backend/mail/dummy.py b/accounts/backend/mail/dummy.py
index d62a66b..ad38d42 100644
--- a/accounts/backend/mail/dummy.py
+++ b/accounts/backend/mail/dummy.py
@@ -36,13 +36,13 @@ class DummyBackend(Backend):
else:
self.format = format
- def send(self, recipient, subject, body, sender=None):
- if sender is None:
- sender = self.app.config['MAIL_DEFAULT_SENDER']
-
+ def _send(self, recipient, content):
+ body = content.body()
if not self.plain:
body = "\n| ".join(body.split("\n"))
print(self.format.format(
- subject=ensure_utf8(subject), to=ensure_utf8(recipient),
- sender=ensure_utf8(sender), body=ensure_utf8(body)))
+ subject=ensure_utf8(content.subject()),
+ sender=ensure_utf8(content.sender()),
+ to=ensure_utf8(recipient),
+ body=ensure_utf8(body)))
diff --git a/accounts/backend/mail/sendmail.py b/accounts/backend/mail/sendmail.py
index 92b354e..9a39b03 100644
--- a/accounts/backend/mail/sendmail.py
+++ b/accounts/backend/mail/sendmail.py
@@ -10,19 +10,16 @@ from . import Backend
class SendmailBackend(Backend):
- def send(self, recipient, subject, body, sender=None):
- if sender is None:
- sender = self.app.config['MAIL_DEFAULT_SENDER']
-
+ def _send(self, recipient, content):
safe = lambda s: s.split('\n', 1)[0]
- msg = MIMEText(body, _charset='utf-8')
- msg['Subject'] = safe(subject)
+ msg = MIMEText(content.body(), _charset='utf-8')
+ msg['Subject'] = safe(content.subject())
msg['To'] = safe(recipient)
- msg['From'] = safe(sender)
+ msg['From'] = safe(content.sender())
envelope = []
- _, address = parseaddr(safe(sender))
+ _, address = parseaddr(safe(content.sender()))
if address != '':
envelope = ['-f', address]
diff --git a/accounts/templates/mail/_base.txt b/accounts/templates/mail/_base.txt
new file mode 100644
index 0000000..b5941da
--- /dev/null
+++ b/accounts/templates/mail/_base.txt
@@ -0,0 +1,15 @@
+{% macro subject() -%}
+ {% block subject %}{% endblock %}
+{%- endmacro %}
+
+{% macro sender() -%}
+ {% if self.sender() -%}
+ {% block sender %}{% endblock %}
+ {%- else -%}
+ {{ config['MAIL_DEFAULT_SENDER'] }}
+ {%- endif %}
+{%- endmacro %}
+
+{% macro body() -%}
+ {% block body %}{% endblock %}
+{%- endmacro %}
diff --git a/accounts/templates/mail/change_mail.txt b/accounts/templates/mail/change_mail.txt
index 64cda14..54b6ca5 100644
--- a/accounts/templates/mail/change_mail.txt
+++ b/accounts/templates/mail/change_mail.txt
@@ -1,12 +1,19 @@
+{% extends 'mail/_base.txt' %}
+
+{% block subject %}E-Mail-Adresse bestätigen{% endblock %}
+{% block sender %}{{ config['MAIL_CONFIRM_SENDER'] }}{% endblock %}
+
+{% block body -%}
Hallo,
Jemand, vermutlich du, möchte auf spline accounts [1] die
E-Mail-Adresse des Accounts {{ username }} auf diese Adresse
- {{ mail }}
+ {{ recipient }}
ändern.
Um diese Änderung zu bestätigen, benutze bitte folgenden Link:
- <{{ link }}>
+ <{{ url_for('default.change_mail', _external=True,
+ token=confirm('change_mail', username, recipient)) }}>
Wenn du dies nicht möchtest, brauchst du nichts weiter zu tun.
@@ -14,3 +21,4 @@ Ohne deine Bestätigung wird die Adresse nicht geändert.
[1] {{ url_for('default.index', _external=True) }}
+{%- endblock %}
diff --git a/accounts/templates/mail/disable_notify.txt b/accounts/templates/mail/disable_notify.txt
new file mode 100644
index 0000000..a9662b6
--- /dev/null
+++ b/accounts/templates/mail/disable_notify.txt
@@ -0,0 +1,12 @@
+{% extends 'mail/_base.txt' %}
+
+{% block subject -%}
+ [accounts] Benutzer {{ username }} deaktiviert
+{%- endblock %}
+
+{% block body -%}
+Benutzername: {{ username }}
+E-Mail war: {{ mail }}
+
+durch: {{ admin }}
+{%- endblock %}
diff --git a/accounts/templates/mail/lost_password.txt b/accounts/templates/mail/lost_password.txt
index 5eaa654..6d38f15 100644
--- a/accounts/templates/mail/lost_password.txt
+++ b/accounts/templates/mail/lost_password.txt
@@ -1,11 +1,19 @@
+{% extends 'mail/_base.txt' %}
+
+{% block subject %}Passwort vergessen{% endblock %}
+{% block sender %}{{ config['MAIL_CONFIRM_SENDER'] }}{% endblock %}
+
+{% block body -%}
Hallo {{ username }},
Jemand, vermutlich du, hat auf spline accounts einen Link zum Ändern
deines Passworts angefordert.
Hier kannst du dein Passwort ändern:
- <{{ link }}>
+ <{{ url_for('default.lost_password_complete', _external=True,
+ token=confirm('lost_password', username)) }}>
Wenn du diese Mail nicht angefordert hast, brauchst du nichts
weiter zu tun. Dein altes Passwort bleibt dann weiter gültig.
+{% endblock %}
diff --git a/accounts/templates/mail/register.txt b/accounts/templates/mail/register.txt
index c5af422..0dc7cd1 100644
--- a/accounts/templates/mail/register.txt
+++ b/accounts/templates/mail/register.txt
@@ -1,15 +1,22 @@
+{% extends 'mail/_base.txt' %}
+
+{% block subject %}E-Mail-Adresse bestätigen{% endblock %}
+{% block sender %}{{ config['MAIL_CONFIRM_SENDER'] }}{% endblock %}
+
+{% block body -%}
Hallo,
Jemand, vermutlich du, möchte auf spline accounts [1] einen Account
mit folgenden Daten anlegen:
Benutzername: {{ username }}
- E-Mail-Adresse: {{ mail }}
+ E-Mail-Adresse: {{ recipient }}
Wenn du diesen Account anlegen möchtest, bestätige mit folgendem Link
deine E-Mail-Adresse:
- <{{ link }}>
+ <{{ url_for('default.register_complete', _external=True,
+ token=confirm('register', username, recipient)) }}>
Wenn du diesen Account nicht anlegen möchtest, brauchst du nichts
@@ -17,3 +24,4 @@ weiter zu tun. Ohne deine Bestätigung wird der Account nicht erstellt.
[1] {{ url_for('default.index', _external=True) }}
+{%- endblock %}
diff --git a/accounts/templates/mail/register_notify.txt b/accounts/templates/mail/register_notify.txt
new file mode 100644
index 0000000..7a649f4
--- /dev/null
+++ b/accounts/templates/mail/register_notify.txt
@@ -0,0 +1,13 @@
+{% extends 'mail/_base.txt' %}
+
+{% block subject -%}
+ [accounts] Neuer Benutzer {{ username }} erstellt
+{%- endblock %}
+
+{% block body -%}
+Benutzername: {{ username }}
+E-Mail: {{ mail }}
+
+Spammer? Deaktivieren: {{ url_for('admin.disable_account', uid=username,
+ _external=True) }}
+{%- endblock %}
diff --git a/accounts/utils/__init__.py b/accounts/utils/__init__.py
index 0a3fa10..0759fd1 100644
--- a/accounts/utils/__init__.py
+++ b/accounts/utils/__init__.py
@@ -35,18 +35,6 @@ def ensure_utf8(s):
return s
-def send_register_confirmation_mail(username, mail):
- confirm_token = Confirmation('register').dumps((username, mail))
- confirm_link = url_for('default.register_complete', token=confirm_token, _external=True)
-
- body = render_template('mail/register.txt', username=username,
- mail=mail, link=confirm_link)
-
- current_app.mail_backend.send(
- mail, u'E-Mail-Adresse bestätigen', body,
- sender=current_app.config.get('MAIL_CONFIRM_SENDER'))
-
-
class NotRegexp(Regexp):
"""
Like wtforms.validators.Regexp, but rejects data that DOES match the regex.
diff --git a/accounts/views/admin/__init__.py b/accounts/views/admin/__init__.py
index f6ac51a..d008d98 100644
--- a/accounts/views/admin/__init__.py
+++ b/accounts/views/admin/__init__.py
@@ -7,7 +7,7 @@ from flask.ext.login import current_user
from uuid import uuid4
from werkzeug.exceptions import Forbidden
-from accounts.utils import templated, send_register_confirmation_mail
+from accounts.utils import templated
from accounts.forms import AdminCreateAccountForm, AdminDisableAccountForm
@@ -33,7 +33,8 @@ def index():
def create_account():
form = AdminCreateAccountForm()
if request.method == 'POST' and form.validate():
- send_register_confirmation_mail(form.username.data, form.mail.data)
+ current_app.mail_backend.send(form.mail.data, 'mail/register.txt',
+ username=form.username.data)
flash(u'Mail versandt.', 'success')
return redirect(url_for('admin.index'))
@@ -78,13 +79,10 @@ def disable_account():
flash(u'Passwort auf ein zufälliges und Mailadresse auf %s '
u'gesetzt.' % mail, 'success')
- if current_app.config.get('MAIL_REGISTER_NOTIFY'):
- current_app.mail_backend.send(
- current_app.config['MAIL_REGISTER_NOTIFY'],
- u'[accounts] Benutzer %s deaktiviert' % form.user.uid,
- 'Benutzername: %s\nE-Mail war: %s\n\ndurch: %s\n' % \
- (form.user.uid, oldmail, session['username'])
- )
+ current_app.mail_backend.send(
+ current_app.config['MAIL_REGISTER_NOTIFY'],
+ 'mail/disable_notify.txt',
+ username=form.user.uid, mail=oldmail, admin=current_user.uid)
return redirect(url_for('admin.index'))
diff --git a/accounts/views/default/__init__.py b/accounts/views/default/__init__.py
index 0a7e65d..eec173e 100644
--- a/accounts/views/default/__init__.py
+++ b/accounts/views/default/__init__.py
@@ -23,7 +23,8 @@ bp = Blueprint('default', __name__)
def register():
form = RegisterForm(request.form)
if form.validate_on_submit():
- send_register_confirmation_mail(form.username.data, form.mail.data)
+ current_app.mail_backend.send(form.mail.data, 'mail/register.txt',
+ username=form.username.data)
flash(u'Es wurde eine E-Mail an die angegebene Adresse geschickt, '
u'um diese zu überprüfen. Bitte folge den Anweisungen in der '
@@ -58,14 +59,10 @@ def register_complete(token):
current_app.user_backend.register(user)
login_user(user)
- if current_app.config.get('MAIL_REGISTER_NOTIFY'):
- current_app.mail_backend.send(
- current_app.config['MAIL_REGISTER_NOTIFY'],
- u'[accounts] Neuer Benutzer %s erstellt' % username,
- u'Benutzername: %s\nE-Mail: %s\n\nSpammer? Deaktivieren: '
- u'%s\n' % (username, mail,
- url_for('admin.disable_account', uid=username, _external=True))
- )
+ current_app.mail_backend.send(
+ current_app.config['MAIL_REGISTER_NOTIFY'],
+ 'mail/register_notify.txt',
+ username=username, mail=mail)
flash(u'Benutzer erfolgreich angelegt.', 'success')
return redirect(url_for('.index'))
@@ -86,15 +83,8 @@ def lost_password():
if form.validate_on_submit():
#TODO: make the link only usable once (e.g include a hash of the old pw)
# atm the only thing we do is make the link valid for only little time
- confirm_token = Confirmation('lost_password').dumps(form.user.uid)
- confirm_link = url_for('.lost_password_complete', token=confirm_token, _external=True)
-
- body = render_template('mail/lost_password.txt', username=form.user.uid,
- link=confirm_link)
-
current_app.mail_backend.send(
- form.user.attributes['mail'], u'Passwort vergessen', body,
- sender=current_app.config.get('MAIL_CONFIRM_SENDER'))
+ form.user.mail, 'mail/lost_password.txt', username=form.user.uid)
flash(u'Wir haben dir eine E-Mail mit einem Link zum Passwort ändern '
u'geschickt. Bitte folge den Anweisungen in der E-Mail.', 'success')
@@ -144,15 +134,9 @@ def index():
elif request.form.get('submit_main'):
if form.mail.data and form.mail.data != current_user.mail:
- confirm_token = Confirmation('change_mail').dumps((current_user.uid, form.mail.data))
- confirm_link = url_for('.change_mail', token=confirm_token, _external=True)
-
- body = render_template('mail/change_mail.txt', username=current_user.uid,
- mail=form.mail.data, link=confirm_link)
-
current_app.mail_backend.send(
- form.mail.data, u'E-Mail-Adresse bestätigen', body,
- sender=current_app.config.get('MAIL_CONFIRM_SENDER'))
+ form.mail.data, 'mail/change_mail.txt',
+ username=current_user.uid)
flash(u'Es wurde eine E-Mail an die angegebene Adresse geschickt, '
u'um diese zu überprüfen. Bitte folge den Anweisungen in der '