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 000000000..433945d70 Binary files /dev/null and b/static/pics/quarantine.png differ diff --git a/static/stylesheets/basic.css b/static/stylesheets/basic.css index 53403fb9e..8a1fe213d 100644 --- a/static/stylesheets/basic.css +++ b/static/stylesheets/basic.css @@ -59,7 +59,6 @@ body { float: left; width: 100%; margin: 15px 0; - /*height: 600px;*/ } #loginbox { @@ -129,11 +128,11 @@ body { #content { float: right; width: 750px; - height: 400px; background: white; border: 1px solid #333; padding: 5px; margin: 0 0 0 15px; + min-height: 400px; } #content2 { diff --git a/static/stylesheets/box.css b/static/stylesheets/box.css index 620a20e21..449531602 100644 --- a/static/stylesheets/box.css +++ b/static/stylesheets/box.css @@ -18,7 +18,7 @@ div.row label { padding: 3px 0; } -form input { +input { border: 1px solid #cccccc; color: inherit; /*background-color: #e9e9e9;*/ @@ -26,7 +26,7 @@ form input { padding: 2px; } -form input:hover { +input:hover { color: inherit; background-color: #ffffcc; } diff --git a/templates/layout.html b/templates/layout.html index 04ab3c7fb..2e4385674 100644 --- a/templates/layout.html +++ b/templates/layout.html @@ -1,4 +1,5 @@ {% load i18n %} +{% load main_extras %} @@ -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(