aboutsummaryrefslogtreecommitdiff
blob: 36bdd0aa0aa8ff19a0c7772f7c40c5aa1e715ab6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# -*- coding: utf-8 -*-
"""
    grumpy.utils
    ~~~~~~~~~~~~

    Miscellaneous utils for authentication, mailing and pagination.

    :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()