Some work about quarantine management.

This commit is contained in:
tonio
2009-07-02 18:05:56 +02:00
parent fcab20b608
commit 1d1c23f63e
8 changed files with 271 additions and 18 deletions
+110 -10
View File
@@ -2,15 +2,24 @@
"""
"""
from django.http import HttpResponseRedirect
from django.shortcuts import get_object_or_404, render_to_response
from django.template.loader import render_to_string
from django.template import Template
from django.conf.urls.defaults import *
from django.utils.translation import ugettext as _
from django.core.urlresolvers import reverse
from django.core.paginator import Paginator
from django.contrib.auth.decorators \
import login_required
from mailng.lib import events
from mailng.lib import _render, _ctx_ok, _ctx_ko
from mailng.lib import _render, _ctx_ok, _ctx_ko, decode
from mailng.lib import db
from mailng.admin.models import Mailbox
from datetime import datetime
import email
import re
import os
def init():
events.register("UserMenuDisplay", menu)
@@ -26,33 +35,33 @@ def menu(**kwargs):
"img" : "/static/pics/quarantine.png"}
]
def index(request):
@login_required
def index(request, message=None):
if not request.user.is_superuser:
mb = Mailbox.objects.get(user=request.user.id)
filter = "AND maddr.email='%s'" % mb.full_address
else:
filter = ""
cursor = db.getconnection("amavis_quarantine").cursor()
cursor.execute("""
SELECT msgs.from_addr, maddr.email, msgs.subject, msgs.content, quarantine.mail_id
conn = db.getconnection("amavis_quarantine")
status, cursor = db.execute(conn, """
SELECT msgs.from_addr, maddr.email, msgs.subject, msgs.content, quarantine.mail_id,
msgs.time_num, msgs.content
FROM quarantine, maddr, msgrcpt, msgs
WHERE quarantine.mail_id=msgrcpt.mail_id
AND msgrcpt.rid=maddr.id
AND msgrcpt.mail_id=msgs.mail_id
AND quarantine.chunk_ind=1
%s
ORDER BY msgs.time_num DESC
""" % filter)
emails = []
rows = cursor.fetchall()
for row in rows:
emails.append({"from" : row[0], "to" : row[1],
"subject" : row[2], "content" : row[3],
"mailid" : row[4]})
"mailid" : row[4], "time" : datetime.fromtimestamp(row[5]),
"type" : row[6]})
# cursor.execute("SELECT count(*) AS cnt FROM quarantine")
# row = cursor.fetchone()
# cnt = row[0]
paginator = Paginator(emails, 10)
try:
pagenum = int(request.GET.get('page', '1'))
@@ -62,3 +71,94 @@ AND quarantine.chunk_ind=1
return _render(request, 'amavis_quarantine/index.html', {
"count" : len(rows), "emails" : page
})
@login_required
def viewmail(request, mail_id):
conn = db.getconnection("amavis_quarantine")
status, cursor = db.execute(conn, """
SELECT mail_text
FROM quarantine
WHERE quarantine.mail_id='%s'
""" % mail_id)
content = ""
for part in cursor.fetchall():
content += part[0]
msg = email.message_from_string(content)
html_body = ""
text_body = ""
for part in msg.walk():
print part.get_content_type()
if part.get_content_maintype() == 'multipart':
continue
if part.get_content_type() in ("text/html"):
html_body += part.get_payload()
if part.get_content_type() in ("text/plain"):
text_body += part.get_payload(decode=True)
pre = None
if html_body != "":
html_body = email.utils.quote(html_body)
html_body = re.sub('(\n|\r|\r\n)', '\\\\n', html_body)
body = Template(decode(html_body)).render({})
else:
text_body = email.utils.quote(text_body)
text_body = re.sub('(\n|\r|\r\n)', '\\\\n', text_body)
body = decode(text_body)
pre = True
return _render(request, 'amavis_quarantine/viewmail.html', {
"headers" : msg.items(),
"body" : body,
"pre" : pre
})
@login_required
def process(request):
if request.POST.has_key("deleteall"):
return
ids = ""
count = len(request.POST.getlist("selection"))
for id in request.POST.getlist("selection"):
if ids != "":
ids += ","
ids += "'%s'" % id
if ids == "":
return
conn = db.getconnection("amavis_quarantine")
if request.POST.has_key("release"):
status, cursor = db.execute(conn, """
SELECT msgs.mail_id,secret_id,quar_type,maddr.email FROM msgs, maddr, msgrcpt
WHERE msgrcpt.mail_id=msgs.mail_id AND msgrcpt.rid=maddr.id AND msgs.mail_id IN (%s)
""" % (ids))
emails = {}
for row in cursor.fetchall():
if not emails.has_key(row[0]):
emails[row[0]] = {}
emails[row[0]]["rcpts"] = []
emails[row[0]]["secret"] = row[1]
emails[row[0]]["rcpts"] += [row[3]]
count = 0
for k, values in emails.iteritems():
cmd = "/tmp/amavisd-release "
cmd += "%s %s" % (k, values["secret"])
for rcpt in values["rcpts"]:
cmd += " %s" % rcpt
cmd += "\n"
result = os.system(cmd)
# if re.search("250 [^\s]+ Ok", result):
if not result:
count += 1
message = _("%d message%s released successfully" \
% (count, count > 1 and "s" or ""))
if request.POST.has_key("delete"):
status, error = db.execute(conn,
"DELETE FROM msgs WHERE mail_id IN (%s)" % ids)
if status:
message = _("%d message%s deleted successfully" \
% (count, count > 1 and "s" or ""))
else:
message = error
request.user.message_set.create(message=message)
return HttpResponseRedirect(reverse(index))
+63
View File
@@ -0,0 +1,63 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import socket
import sys
import re
import struct
from optparse import OptionParser
def getsocket(options):
if options.mode == "net":
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((options.host, options.port))
return s
def from_stdin():
res = []
for line in sys.stdin:
res += [line]
return res
def decodevalue(val):
def pack(match):
return struct.pack('B', match.group(0))
res = re.sub("%([0-9a-fA-F]{2})", pack, val)
if __name__ == "__main__":
parser = OptionParser()
parser.add_option("-o", "--host", default="127.0.0.1",
help="")
parser.add_option("-p", "--port", default=9998,
help="")
parser.add_option("-s", "--socket", default="",
help="")
parser.add_option("-m", "--mode", default="unix",
help="")
(options, args) = parser.parse_args()
if not len(args):
print "Nothing to do, exiting."
sys.exit(1)
s = getsocket(options)
# if args[0] == '-':
# worklist = from_stdin()
# else:
# worklist = [args[0]]
# for message in worklist:
# params = message.split()
params = ["k1URJIk76bKa", "k1URJIk76bKa", "antoine.nguyen@streamcore.com"]
cmd = """request=release
mail_id=%s
secret_id=%s
quar_type=Q
recipient=%s
""" % (params[0], params[1], params[2])
s.send(cmd)
answer = s.recv(1024)
print answer
s.close()
@@ -19,6 +19,11 @@
float: left;
}
#listing {
margin: 0 auto;
width: 98%;
}
td {
font-size: smaller;
height: 40px;
@@ -36,17 +41,19 @@ td {
{% endif %}
</div>
<div id="subcontent">
{% url extensions.amavis_quarantine.main.process as actionurl %}
<form method="POST" action="{{ actionurl }}">
<div id="listing">
<b> Il y a {{ count }} messages dans la quarantaine.</b>
<div id="quarmenu">
<div id="actionbar">
<input type="button" name="release" value="{% trans "Release" %}" />
<input type="button" name="delete" value="{% trans "Delete" %}" />
<input type="button" name="deleteall" value="{% trans "Delete all" %}" />
<input type="submit" name="release" value="{% trans "Release" %}" />
<input type="submit" name="delete" value="{% trans "Delete" %}" />
<input type="submit" name="deleteall" value="{% trans "Delete all" %}" />
</div>
<div id="navbar">
{% if emails.has_previous %}
<a href="?page=1">{% trans "First" %}</a>
<a href="?page={{ emails.previous_page_number }}">{% trans "Previous" %}</a>
{% endif %}
{% if emails.has_next %}
@@ -57,15 +64,23 @@ td {
<table>
<tr>
<th></th>
<th>{% trans "Type" %}</th>
<th width="150px">{% trans "From" %}</th>
<th width="150px">{% trans "To" %}</th>
<th>{% trans "Subject" %}</th>
<th width="100px">{% trans "Date" %}</th>
</tr>
{% for m in emails.object_list %}
<tr class="{% cycle 'odd' 'even' %}">
<td><input type="checkbox" name="selection" id="selection" /></td>
<td>{{ m.from }}</td><td>{{ m.to }}</td><td>{{ m.subject }}</td></tr>
<td><input type="checkbox" name="selection" id="selection"
value="{{ m.mailid }}" /></td>
<td>{{ m.type }}</td>
{% if user.is_superuser %}<td>{{ m.to }}</td>{% endif %}
{% url extensions.amavis_quarantine.main.viewmail m.mailid as view_url %}
<td><a href="{{ view_url }}">{{ m.subject }}</a></td>
<td>{{ m.time }}</td>
</tr>
{% endfor %}
</table>
</div>
</form>
{% endblock %}
@@ -0,0 +1,47 @@
{% extends "layout.html" %}
{% load i18n %}
{% block html_head %}
<script type="text/javascript">
window.addEvent("domready", function() {
doc = $("mailcontent").contentWindow.document;
doc.open();
{% if pre %}
doc.write("<pre>{{ body }}</pre>");
{% else %}
doc.write("{{ body }}");
{% endif %}
doc.close();
});
</script>
<link rel="stylesheet" type="text/css" href="/static/stylesheets/box.css" />
<style type="text/css">
td {
font-size: smaller;
height: 20px;
}
td.left {
background: #F7F9Fb;
}
#mailcontent {
width: 100%;
height: 400px;
border: 0;
}
</style>
{% endblock %}
{% block content %}
<iframe id="mailcontent"></iframe>
<table border="0">
<tr><th colspan="2">{% trans "Message headers" %}</th></tr>
{% for k, v in headers %}
<tr>
<td class="left">{{ k }}</td><td>{{ v }}</td>
</tr>
{% endfor %}
</table>
{% endblock %}
+2
View File
@@ -2,4 +2,6 @@ from django.conf.urls.defaults import *
urlpatterns = patterns('mailng.extensions.amavis_quarantine.main',
(r'^$', 'index'),
(r'^view/(?P<mail_id>[\w\-\+]+)/$', 'viewmail'),
(r'^process/$', 'process')
)
+8
View File
@@ -62,3 +62,11 @@ def _ctx_ok(url):
def _ctx_ko(tpl, ctx):
return {"status" : "ko", "content" : render_to_string(tpl, ctx)}
def decode(s, encodings=('ascii', 'utf8', 'latin1')):
for encoding in encodings:
try:
return s.decode(encoding)
except UnicodeDecodeError:
pass
return s.decode('ascii', 'ignore')
+13
View File
@@ -3,6 +3,9 @@
"""
"""
import re
import MySQLdb
connections = {}
def mysql_newconnection(host, dbname, login, password):
@@ -20,3 +23,13 @@ def getconnection(name):
connections[name] = conn
return connections[name]
def execute(conn, query):
try:
cursor = conn.cursor()
cursor.execute(query)
if re.search("INSERT|DELETE|UPDATE", query):
conn.commit()
return (True, None)
return (True, cursor)
except MySQLdb.Error, e:
return (False, "Error %d: %s" % (e.args[0], e.args[1]))
+5
View File
@@ -0,0 +1,5 @@
{% for entry in menu %}
<li><a href="{{ entry.url }}"><img src="{{ entry.img }}" border="0" />
{{ entry.name }}
</a></li>
{% endfor %}