summaryrefslogtreecommitdiff
path: root/email_gateway.py
blob: fe58fadad2b87485754fcbf9b9c4aab77df61878 (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
#!/usr/bin/env python2.6

import os
import smtplib
import re
import urlparse
from cStringIO import StringIO
from email.mime.text import MIMEText
from ConfigParser import SafeConfigParser as ConfigParser, \
        NoSectionError, NoOptionError
from spambayes.storage import PickledClassifier


config = ConfigParser()
with open("/etc/email_gateway.cfg") as fp:
    config.readfp(fp)


def send_message(text, subject, to, from_email):
    msg = MIMEText(text.getvalue(), "plain")

    msg['Subject'] = subject
    msg['From'] = from_email
    msg['To'] = to

    p = os.popen("/usr/sbin/sendmail -t", "w")
    p.write(msg.as_string())
    p.close()


def looks_like_spam(message, config, section):
    pickle_filename = config.get(section, 'spam.pickle_file')
    min_spam_prob = config.getfloat(section, 'spam.min_spam_prob')

    bayes = PickledClassifier(pickle_filename)

    if bayes.chi2_spamprob(message) >= min_spam_prob:
        return True

    return False


def email_app(environ, start_response):
    ignored_fields = []
    useful_fields = []
    form_key = None
    message_buffer = StringIO()

    context = {}

    fields = urlparse.parse_qsl(environ["wsgi.input"].read())
    for key, value in fields:
        if key == "mailer.form-key":
            form_key = value
        elif key == "mailer.redirect":
            context["redirect"] = value
        elif key == "mailer.subject":
            context["subject"] = value
        elif key == "mailer.message":
            context["message"] = value
        elif key == "mailer.fields.ignore":
            ignored_fields = value.split(",")
        else:
            useful_fields.append((key, value))

    try:
        my_config = dict(config.items(form_key))
        site_matcher = re.compile(my_config["site"])
    except NoSectionError:
        start_response('403 Forbidden', [('Content-Type', 'text/plain')])
        return "Invalid form key!"

    if not site_matcher.match(environ["HTTP_REFERER"]):
        start_response('403 Forbidden', [('Content-Type', 'text/plain')])
        return "Invalid send!"

    try:
        if config.getboolean(form_key, 'spam.check') \
                and looks_like_spam(context["message"], config, form_key):
            start_response('403 Forbidden', [('Content-Type', 'text/plain')])
            return "I don't like SPAM!"
    except NoOptionError:
        pass

    useful_fields = ["{0}: {1}".format(*f)
                     for f in useful_fields
                     if f[0] not in ignored_fields]

    message_buffer.write(context.get("message", my_config["message"]))
    message_buffer.write("\n\n")
    message_buffer.write("\n".join(useful_fields))

    send_message(message_buffer,
        context.get("subject", my_config["subject"]),
        my_config["to"],
        my_config["from"])

    redirect_location = context.get("redirect", my_config["redirect"])
    start_response('302 Found', [('Location', redirect_location)])

    return ""


if __name__ == "__main__":
    from flup.server.fcgi_fork import WSGIServer
    WSGIServer(email_app, maxSpare=1).run()