# -*- coding: utf-8 -*- """ grumpy.utils ~~~~~~~~~~~~ Miscellaneous utils for authentication and mailing. :copyright: (c) 2010 Priit Laes """ from flask import flash, g, redirect, request, url_for, Response from functools import wraps from smtplib import SMTP, SMTPException from email.mime.text import MIMEText from pkgcore.ebuild.cpv import native_ver_cmp from . import app def compare_version(ver1, ver2): """Compares two version strings.""" return native_ver_cmp(ver1, '', ver2, '') def authenticate(): """Sends a 401 response that enables basic HTTP auth""" return Response('Could not verify your access level for that URL.\n' 'You have to login with proper credentials', 401, {'WWW-Authenticate': 'Basic realm="Login required"'}) def check_auth(username, password): """Checks username password against ones stored in configuration.""" return username == app.config['TINDERBOX_USER'] and \ password == app.config['TINDERBOX_PASS'] def requires_auth(f): @wraps(f) def decorated(*args, **kwargs): if not g.user: flash(u'This view requires valid user') return redirect(url_for('index')) return f(*args, **kwargs) return decorated def requires_auth_basic(f): @wraps(f) def decorated(*args, **kwargs): auth = request.authorization if not auth or not check_auth(auth.username, auth.password): 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()