diff options
author | Priit Laes <plaes@plaes.org> | 2010-07-18 17:28:56 +0300 |
---|---|---|
committer | Priit Laes <plaes@plaes.org> | 2010-07-18 17:28:56 +0300 |
commit | 2cef376ac68af60b64b91bce93fb88ebf54206c4 (patch) | |
tree | 073621fe1b475053f1a8039c26335698ff06ca7a /grumpy | |
parent | Added Flask-OpenID to dependencies (diff) | |
download | gsoc2010-grumpy-2cef376ac68af60b64b91bce93fb88ebf54206c4.tar.gz gsoc2010-grumpy-2cef376ac68af60b64b91bce93fb88ebf54206c4.tar.bz2 gsoc2010-grumpy-2cef376ac68af60b64b91bce93fb88ebf54206c4.zip |
Implement registration token generation and email sending
Diffstat (limited to 'grumpy')
-rw-r--r-- | grumpy/models.py | 15 | ||||
-rw-r--r-- | grumpy/templates/email/registration.txt | 7 | ||||
-rw-r--r-- | grumpy/utils.py | 62 | ||||
-rw-r--r-- | grumpy/webapp.py | 9 |
4 files changed, 86 insertions, 7 deletions
diff --git a/grumpy/models.py b/grumpy/models.py index 55019f0..d5fd6de 100644 --- a/grumpy/models.py +++ b/grumpy/models.py @@ -14,7 +14,7 @@ from datetime import datetime from flaskext.sqlalchemy import SQLAlchemy from sqlalchemy.sql import func -import json +import json, random, string db = SQLAlchemy(app) @@ -193,11 +193,20 @@ class User(db.Model): __tablename__ = 'users' id = db.Column('id', db.Integer, primary_key=True) - regtoken = db.Column('token', db.String) openid = db.Column('openid', db.String) email = db.Column('user', db.String, unique=True) + apitoken = db.Column('apitoken', db.String) + regtoken = db.Column('regtoken', db.String) + created_on = db.Column('created_on', db.DateTime, default=func.now()) def __init__(self, email, openid): self.email = email self.openid = openid - # TODO, generate token + # API token + self.apitoken = None + # Registration token + self.regtoken = self.generate_token(8) + + def generate_token(self, length): + return ''.join([random.choice(string.ascii_letters + \ + string.digits) for x in xrange(length)]) diff --git a/grumpy/templates/email/registration.txt b/grumpy/templates/email/registration.txt new file mode 100644 index 0000000..1d6efab --- /dev/null +++ b/grumpy/templates/email/registration.txt @@ -0,0 +1,7 @@ +Hey! + +You have signed up on `TODO: site address` but your account is not yet activated. +You have to follow the following link to finish the registration and +activate your account: + +`TODO: Figure out url:` {{ user.regtoken }} diff --git a/grumpy/utils.py b/grumpy/utils.py index a70fd95..3fe7506 100644 --- a/grumpy/utils.py +++ b/grumpy/utils.py @@ -3,12 +3,14 @@ grumpy.utils ~~~~~~~~~~~~ - Miscellaneous utils for authentication and pagination. + Miscellaneous utils for authentication, mailing and pagination. :copyright: (c) 2010 Priit Laes """ +from email.mime.text import MIMEText from flask import request, Response from functools import wraps +from smtplib import SMTP, SMTPException from . import app @@ -31,3 +33,61 @@ def requires_auth_basic(f): return authenticate() return f(*args, **kwargs) return decorated + +def send_email(recipients, subject, text): + """Send mail using EMail class.""" + return EMail(recipients, subject, text).send() + +class EMail(object): + + def __init__(self, recipients=None, subject=None, text=''): + # FIXME: Use app.config for from address + self.from_addr = 'noreply-grumpy@example.com' + self.subject = u' '.join(subject.splitlines()) + self.to_addr = [] + if isinstance(recipients, basestring): + self.to_addr.append(recipients) + else: + for addr in recipients: + self.to_addr.append(addr) + self.text = text + + def as_message(self): + """Return the email as MIMEText object.""" + if not self.subject or not self.text or not self.to_addr: + raise RuntimeError("Not all mailing parameters filled in") + + msg = MIMEText(self.text.encode('utf-8')) + + # We set these ourself + del msg['Content-Transfer-Encoding'] + del msg['Content-Type'] + + msg['From'] = self.from_addr.encode('utf-8') + msg['To'] = ', '.join(x.encode('utf-8') for x in self.to_addr) + msg['Subject'] = self.subject.encode('utf-8') + msg['Content-Transfer-Encoding'] = '8bit' + msg['Content-Type'] = 'text/plain; charset=utf-8' + return msg + + def format(self, sep='\r\n'): + """Convert the message into long string""" + return sep.join(self.as_message().as_string().splitlines()) + + def send(self): + try: + # TODO: Make configurable? + smtp = SMTP('localhost') + except SMTPException, e: + raise RuntimeError(str(e)) + + # TODO: Handle authentication and/or TLS + + try: + try: + return smtp.sendmail(self.from_addr, self.to_addr, self.format()) + except SMTPException, e: + raise RuntimeError(str(e)) + finally: + # Close SMTP connection + smtp.quit() diff --git a/grumpy/webapp.py b/grumpy/webapp.py index b426cc8..81e5e58 100644 --- a/grumpy/webapp.py +++ b/grumpy/webapp.py @@ -10,7 +10,7 @@ """ from . import app from .models import db, Category, Package, User -from .utils import requires_auth_basic +from .utils import requires_auth_basic, send_email from flask import (flash, g, jsonify, redirect, render_template, request, \ session, url_for) @@ -94,9 +94,12 @@ def create_profile(): flash(u'You need to be a valid Gentoo developer to sign up') else: flash(u'Profile successfully created') - db.session.add(User(email, session['openid'])) - # TODO: send confirmation token with email + user = User(email, session['openid']) + db.session.add(user) db.session.commit() + send_email(email, u'Gentoo Grumpy registration confirmation', \ + render_template('email/registration.txt', user=user)) + return redirect(oid.get_next_url()) return render_template('create_profile.html', next=oid.get_next_url()) @app.route('/_api/1.0/tinderbox/') |