From fcab20b6087c01b538048667706846bf8971de51 Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Fri, 26 Jun 2009 17:13:35 +0200 Subject: [PATCH] Important update of the plugin engine. New plugin that allows the handling of an Amavisd-new SQL quarantine. NB: a DB connections manager has been added inside the lib because Django does not support multiple connections at the same time. The main consequence is that we don't use an ORM and that we have to rewrite a small wrapper that supports several DB (mysql, postgresql, etc.). Adding a dependancy to an existing ORM module (like SQLalchemy) is heavy, we don't want that for now. --- admin/forms.py | 3 +- admin/models.py | 2 +- extensions/__init__.py | 9 +++ extensions/amavis_quarantine/__init__.py | 0 extensions/amavis_quarantine/main.py | 64 ++++++++++++++++ .../amavis_quarantine/templates/index.html | 71 ++++++++++++++++++ extensions/amavis_quarantine/urls.py | 5 ++ extensions/postfix_autoreply/main.py | 3 + lib/db.py | 22 ++++++ lib/events.py | 12 ++- main/templatetags/main_extras.py | 25 +++++- static/pics/quarantine.png | Bin 0 -> 564 bytes static/stylesheets/basic.css | 3 +- static/stylesheets/box.css | 4 +- templates/layout.html | 2 + templates/main/menu.html | 18 ++--- urls.py | 3 +- 17 files changed, 227 insertions(+), 19 deletions(-) create mode 100644 extensions/amavis_quarantine/__init__.py create mode 100644 extensions/amavis_quarantine/main.py create mode 100644 extensions/amavis_quarantine/templates/index.html create mode 100644 extensions/amavis_quarantine/urls.py create mode 100644 lib/db.py create mode 100644 static/pics/quarantine.png diff --git a/admin/forms.py b/admin/forms.py index 3b67a4333..446bfab63 100644 --- a/admin/forms.py +++ b/admin/forms.py @@ -16,7 +16,8 @@ class MailboxForm(forms.ModelForm): quota = forms.IntegerField(label=_("Quota"), required=False) password1 = forms.CharField(label=_("Password"), widget=forms.PasswordInput) password2 = forms.CharField(label=_("Confirmation"), widget=forms.PasswordInput) - enabled = forms.BooleanField(label=gender("Enabled", "f"), required=False) + enabled = forms.BooleanField(label=gender("Enabled", "f"), required=False, + initial=True) class Meta: model = Mailbox diff --git a/admin/models.py b/admin/models.py index 83ef556d6..2f2d7c1c8 100644 --- a/admin/models.py +++ b/admin/models.py @@ -18,7 +18,7 @@ class Domain(models.Model): def create_dir(self): path = "%s/%s" % (settings.STORAGE_PATH, self.name) - return exec_as_vuser("mkdir %s" % path) + return exec_as_vuser("mkdir -p %s" % path) def rename_dir(self, newname): code, output = exec_pipe("sudo -u %s mv %s/%s %s/%s" \ diff --git a/extensions/__init__.py b/extensions/__init__.py index 2b9599676..b2526b98f 100644 --- a/extensions/__init__.py +++ b/extensions/__init__.py @@ -2,6 +2,8 @@ import os import re +extensions = [] + def loadextensions(): from django.conf import settings @@ -12,3 +14,10 @@ def loadextensions(): continue module = __import__(m.group(1), globals(), locals(), ['main']) module.main.init() + globals()['extensions'] += [module] + +def loadmenus(): + result = () + for mod in extensions: + result += mod.main.urls() + return result diff --git a/extensions/amavis_quarantine/__init__.py b/extensions/amavis_quarantine/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/extensions/amavis_quarantine/main.py b/extensions/amavis_quarantine/main.py new file mode 100644 index 000000000..e4cba1b54 --- /dev/null +++ b/extensions/amavis_quarantine/main.py @@ -0,0 +1,64 @@ +# -*- coding: utf-8 -*- + +""" +""" +from django.shortcuts import get_object_or_404, render_to_response +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 mailng.lib import events +from mailng.lib import _render, _ctx_ok, _ctx_ko +from mailng.lib import db +from mailng.admin.models import Mailbox + +def init(): + events.register("UserMenuDisplay", menu) + +def urls(): + return (r'^mailng/quarantine/', + include('mailng.extensions.amavis_quarantine.urls')) + +def menu(**kwargs): + return [ + {"name" : _("Quarantine"), + "url" : reverse(index), + "img" : "/static/pics/quarantine.png"} + ] + +def index(request): + 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 +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 +""" % 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]}) + +# 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')) + except ValueError: + pagenum = 1 + page = paginator.page(pagenum) + return _render(request, 'amavis_quarantine/index.html', { + "count" : len(rows), "emails" : page + }) diff --git a/extensions/amavis_quarantine/templates/index.html b/extensions/amavis_quarantine/templates/index.html new file mode 100644 index 000000000..8c56b5e41 --- /dev/null +++ b/extensions/amavis_quarantine/templates/index.html @@ -0,0 +1,71 @@ +{% extends "layout.html" %} +{% load i18n %} +{% block html_head %} + +{% endblock %} +{% block content %} + + +
+

{% trans "Quarantine" %}

+ {% if messages %} +
+ {% for m in messages %} + {{ m }} + {% endfor %} +
+ {% endif %} +
+ +
+ Il y a {{ count }} messages dans la quarantaine. + +
+
+ + + +
+ +
+ + + + + + + + {% for m in emails.object_list %} + + + + {% endfor %} +
{% trans "From" %}{% trans "To" %}{% trans "Subject" %}
{{ m.from }}{{ m.to }}{{ m.subject }}
+
+{% endblock %} \ No newline at end of file diff --git a/extensions/amavis_quarantine/urls.py b/extensions/amavis_quarantine/urls.py new file mode 100644 index 000000000..2a9a46789 --- /dev/null +++ b/extensions/amavis_quarantine/urls.py @@ -0,0 +1,5 @@ +from django.conf.urls.defaults import * + +urlpatterns = patterns('mailng.extensions.amavis_quarantine.main', + (r'^$', 'index'), + ) diff --git a/extensions/postfix_autoreply/main.py b/extensions/postfix_autoreply/main.py index 80ec2a156..023555293 100644 --- a/extensions/postfix_autoreply/main.py +++ b/extensions/postfix_autoreply/main.py @@ -16,6 +16,9 @@ def init(): events.register("CreateMailbox", onCreateMailbox) events.register("DeleteMailbox", onDeleteMailbox) +def urls(): + return () + def onCreateDomain(**kwargs): dom = kwargs["dom"] transport = Transport() diff --git a/lib/db.py b/lib/db.py new file mode 100644 index 000000000..57e3c6e4f --- /dev/null +++ b/lib/db.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- + +""" + +""" +connections = {} + +def mysql_newconnection(host, dbname, login, password): + import MySQLdb + return MySQLdb.connect(host=host, db=dbname, user=login, passwd=password) + +def getconnection(name): + if not name in connections.keys(): + from django.conf import settings + + cfg = settings.DB_CONNECTIONS[name] + if cfg["driver"] == "mysql": + conn = mysql_newconnection(cfg["host"], cfg["dbname"], cfg["login"], + cfg["password"]) + connections[name] = conn + return connections[name] + diff --git a/lib/events.py b/lib/events.py index da77f6c94..893aac740 100644 --- a/lib/events.py +++ b/lib/events.py @@ -9,7 +9,9 @@ core application and additional components. events = ["CreateDomain", "DeleteDomain", "CreateMailbox", - "DeleteMailbox"] + "DeleteMailbox", + + "UserMenuDisplay"] callbacks = {} @@ -27,3 +29,11 @@ def raiseEvent(event, **kwargs): for callback in callbacks[event]: callback(**kwargs) return 1 + +def raiseQueryEvent(event, **kwargs): + result = [] + if not event in events or not event in callbacks.keys(): + return result + for callback in callbacks[event]: + result += callback(**kwargs) + return result diff --git a/main/templatetags/main_extras.py b/main/templatetags/main_extras.py index 2c75830e1..2dce791aa 100644 --- a/main/templatetags/main_extras.py +++ b/main/templatetags/main_extras.py @@ -1,10 +1,33 @@ from django import template from django.template.loader import render_to_string from django.utils.translation import ugettext as _ +from django.core.urlresolvers import reverse +from mailng import main +from mailng.lib import events register = template.Library() @register.simple_tag def menu(selection, perms): + entries = [ + {"name" : "autoreply", + "url" : reverse(main.views.autoreply), + "img" : "/static/pics/auto-reply.png", + "label" : _("Auto-reply message")}, + {"name" : "changepwd", + "url" : reverse(main.views.changepassword), + "img" : "/static/pics/edit.png", + "label" : _("Change password"), + "class" : "boxed", + "rel" : "{handler:'iframe',size:{x:350,y:220}}"} + ] + return render_to_string('main/menu.html', - {"selection" : selection, "perms" : perms}) + {"selection" : selection, "entries" : entries, + "perms" : perms}) + +@register.simple_tag +def loadextmenu(perms): + menu = events.raiseQueryEvent("UserMenuDisplay") + return render_to_string('main/menulist.html', + {"menu" : menu, "perms" : perms}) diff --git a/static/pics/quarantine.png b/static/pics/quarantine.png new file mode 100644 index 0000000000000000000000000000000000000000..433945d700d4e22f7793a51c2a1e481155df890f GIT binary patch literal 564 zcmV-40?Yl0P)aJ$MuJ z;6I2U2!aRygcs}4LlLAsx~Qec_S8eD|G`r!wr9hp5GWXY9S_mf+9WC+c!zoO&CK_` zk4LJC^8}x(`)>o@F}F5FUX8=hC?5w_LK6(p;e`3!t z$cXNH#w=Y=5(6RtKpe-o9LH9epO2N05s4V{W~te{K)(NrrL|aWHp>8>W<)b12QbmI zi$QQHsn?;t4?Q@5?(ajbMJWt1m!_U4^7{9l!p4lKYK%F&ySyAs1i_$MsQ@BCuLl5d zCnwlyw~xQ}`wv>G?Nbay-YlXtG9DGl|y5IiU! @@ -47,6 +48,7 @@ {% trans "Preferences" %} {% endif %} + {% loadextmenu perms %}
  • {% url django.contrib.auth.views.logout_then_login as logout_url %} diff --git a/templates/main/menu.html b/templates/main/menu.html index 5e5c5c050..775b07501 100644 --- a/templates/main/menu.html +++ b/templates/main/menu.html @@ -1,15 +1,13 @@ {% load i18n %} \ No newline at end of file diff --git a/urls.py b/urls.py index eb6b08d79..80e19781e 100644 --- a/urls.py +++ b/urls.py @@ -5,7 +5,7 @@ from django.conf import settings # from django.contrib import admin # admin.autodiscover() -from mailng.extensions import loadextensions +from mailng.extensions import loadextensions, loadmenus loadextensions() urlpatterns = patterns('', @@ -26,6 +26,7 @@ urlpatterns = patterns('', (r'^jsi18n/$', 'django.views.i18n.javascript_catalog', {'packages': ('mailng',),}) ) +urlpatterns += patterns('', loadmenus()) if settings.DEBUG: urlpatterns += patterns(