-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathemail_gateway.py
executable file
·119 lines (91 loc) · 3.53 KB
/
email_gateway.py
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
109
110
111
112
113
114
115
116
117
118
119
#!/usr/bin/env python2.6
import logging
import os
import re
import urlparse
from cStringIO import StringIO
from email.mime.text import MIMEText
from ConfigParser import NoSectionError, NoOptionError
from spambayes.storage import PickledClassifier
from get_config import config
log = logging.getLogger("email_gateway")
default_log_filename = "/var/log/webapps/email_gateway.log"
log_filename = config.get("global", "log") or default_log_filename
handler = logging.FileHandler(log_filename)
log.addHandler(handler)
log.setLevel(logging.DEBUG)
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):
log.info("Checking message for spam...")
log.debug(message)
pickle_filename = config.get(section, 'spam.pickle_file')
min_spam_prob = config.getfloat(section, 'spam.min_spam_prob') or 0.90
log.debug("Loading pickle from %s", pickle_filename)
bayes = PickledClassifier(pickle_filename)
spamprob = bayes.chi2_spamprob(message)
if spamprob >= min_spam_prob:
log.debug("spamprob %s >= %s, probably spam", spamprob, min_spam_prob)
return True
log.debug("spamprob %s <= %s, probably not spam", spamprob, min_spam_prob)
return False
def email_app(environ, start_response):
ignored_fields = []
useful_fields = []
form_key = None
message_buffer = StringIO()
context = {}
to_check = []
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:
to_check.append(value)
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(" ".join(to_check), 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()