diff --git a/extensions/amavis_quarantine/__init__.py b/extensions/amavis_quarantine/__init__.py
index f5358ce9d..396232842 100644
--- a/extensions/amavis_quarantine/__init__.py
+++ b/extensions/amavis_quarantine/__init__.py
@@ -43,6 +43,8 @@ def load():
help=_("Path to the PDP server socket (if unix mode)"))
parameters.register_admin("USER_CAN_RELEASE", type="list_yesno", deflt="no",
help=_("Allow users to directly release their messages"))
+ parameters.register_admin("SELF_SERVICE", type="list_yesno", deflt="no",
+ help=_("Activate the 'self-service' mode"))
parameters.register_user(
"MESSAGES_PER_PAGE", type="int", deflt=40,
@@ -67,3 +69,12 @@ def menu(target, user):
]
return []
+@events.observe("CreateMailbox")
+def create_user_record(user, mailbox):
+ from models import Users
+
+ u = Users()
+ u.email = mailbox.full_address
+ u.fullname = mailbox.user.fullname
+ u.local = "1"
+ u.save()
diff --git a/extensions/amavis_quarantine/lib.py b/extensions/amavis_quarantine/lib.py
index afc5e29d5..650ee3816 100644
--- a/extensions/amavis_quarantine/lib.py
+++ b/extensions/amavis_quarantine/lib.py
@@ -2,8 +2,32 @@ import socket
import re
import struct
import string
+from functools import wraps
from modoboa.lib import parameters
+def selfservice(ssfunc=None):
+ """Decorator used to expose views to the 'self-service' feature
+
+ The 'self-service' feature allows users to act on quarantined
+ messages without beeing authenticated.
+
+ This decorator only acts as a 'router'.
+
+ :param ssfunc: the function to call if the 'self-service'
+ pre-requisites are satisfied
+ """
+ def decorator(f):
+ @wraps(f)
+ def wrapped_f(request, *args, **kwargs):
+ if request.user.is_authenticated():
+ return f(request, *args, **kwargs)
+ if parameters.get_admin("SELF_SERVICE") == "no":
+ from django.contrib.auth.views import redirect_to_login
+ return redirect_to_login(reverse(f, args=args))
+ return ssfunc(request, *args, **kwargs)
+ return wrapped_f
+ return decorator
+
class AMrelease(object):
def __init__(self):
mode = parameters.get_admin("AM_PDP_MODE")
diff --git a/extensions/amavis_quarantine/static/css/selfservice.css b/extensions/amavis_quarantine/static/css/selfservice.css
new file mode 100644
index 000000000..bfab53b9a
--- /dev/null
+++ b/extensions/amavis_quarantine/static/css/selfservice.css
@@ -0,0 +1,20 @@
+#menubar {
+ padding-left: 15px;
+}
+
+#listing {
+ position: absolute;
+ padding: 0px;
+ right: 0;
+ left: 0;
+ bottom: 0;
+ overflow: hidden;
+}
+
+#mailcontent {
+ border: 0;
+ margin: 0;
+ padding: 0;
+ width: 100%;
+ height: 100%;
+}
\ No newline at end of file
diff --git a/extensions/amavis_quarantine/static/js/selfservice.js b/extensions/amavis_quarantine/static/js/selfservice.js
new file mode 100644
index 000000000..8aecf6d04
--- /dev/null
+++ b/extensions/amavis_quarantine/static/js/selfservice.js
@@ -0,0 +1,35 @@
+function send_action(e, message) {
+ var $link = $(e.target);
+
+ e.preventDefault();
+ if (!confirm(message)) {
+ return;
+ }
+ $.ajax({
+ url: $link.attr("href"),
+ dataType: 'json',
+ success: function(data) {
+ if (data.status == "ok") {
+ $("body").notify("success", data.respmsg, 2000);
+ } else {
+ $("body").notify("error", data.respmsg);
+ }
+ }
+ });
+}
+
+function release(e) {
+ send_action(e, gettext("Release this message?"));
+}
+
+function remove(e) {
+ send_action(e, gettext("Delete this message?"));
+}
+
+$(document).ready(function() {
+ $("#listing").css({
+ top: $("#menubar").outerHeight() + 10
+ });
+ $(document).on("click", "a[name=release]", release);
+ $(document).on("click", "a[name=delete]", remove);
+});
\ No newline at end of file
diff --git a/extensions/amavis_quarantine/templates/amavis_quarantine/viewmail_selfservice.html b/extensions/amavis_quarantine/templates/amavis_quarantine/viewmail_selfservice.html
new file mode 100644
index 000000000..8dbcacc86
--- /dev/null
+++ b/extensions/amavis_quarantine/templates/amavis_quarantine/viewmail_selfservice.html
@@ -0,0 +1,30 @@
+
+{% load i18n libextras amextras %}
+
+
+
+ Modoboa
+
+
+
+
+
+
+
+
+
+
+ {% url django.views.i18n.javascript_catalog as catalog_url %}
+
+
+
+
+
+
+
+
diff --git a/extensions/amavis_quarantine/templatetags/amextras.py b/extensions/amavis_quarantine/templatetags/amextras.py
index 1a2ce3342..8ab4ba15f 100644
--- a/extensions/amavis_quarantine/templatetags/amextras.py
+++ b/extensions/amavis_quarantine/templatetags/amextras.py
@@ -52,6 +52,26 @@ def viewm_menu(user, mail_id, rcpt):
return render_to_string('common/buttons_list.html',
{"entries" : entries})
+@register.simple_tag
+def viewm_menu_simple(user, mail_id, rcpt, secret_id=""):
+ entries = [
+ {"name" : "release",
+ "img" : "icon-ok",
+ "url" : reverse(amavis_quarantine.views.release, args=[mail_id]) \
+ + ("?rcpt=%s" % rcpt \
+ + (("&secret_id=%s" % secret_id) if secret_id != "" else "")),
+ "label" : _("Release")},
+ {"name" : "delete",
+ "img" : "icon-remove",
+ "url" : reverse(amavis_quarantine.views.delete, args=[mail_id]) \
+ + "?rcpt=%s" % rcpt \
+ + ("&secret_id=%s" % secret_id if secret_id != "" else ""),
+ "label" : _("Delete")},
+ ]
+
+ return render_to_string('common/buttons_list.html',
+ {"entries" : entries})
+
@register.simple_tag
def quar_menu(user, nbrequests):
entries = [
@@ -94,7 +114,7 @@ def quar_menu(user, nbrequests):
"extraopts" : extraopts
})
- if nbrequests != -1:
+ if nbrequests > 0:
tpl = Template('')
extracontent += tpl.render(Context(dict(
label=_("%d pending requests" % nbrequests)
diff --git a/extensions/amavis_quarantine/urls.py b/extensions/amavis_quarantine/urls.py
index 9633389cc..80ef0138c 100644
--- a/extensions/amavis_quarantine/urls.py
+++ b/extensions/amavis_quarantine/urls.py
@@ -5,9 +5,9 @@ urlpatterns = patterns(
(r'^$', 'index'),
(r'^listing/$', '_listing'),
(r'^getmailcontent/(?P[\w\-\+]+)/$', 'getmailcontent'),
- (r'^(?P[\w\-\+]+)/headers/$', 'viewheaders'),
(r'^process/$', 'process'),
(r'^delete/(?P[\w\-\+]+)/$', 'delete'),
(r'^release/(?P[\w\-\+]+)/$', 'release'),
(r'^(?P[\w\-\+]+)/$', 'viewmail'),
+ (r'^(?P[\w\-\+]+)/headers/$', 'viewheaders'),
)
diff --git a/extensions/amavis_quarantine/views.py b/extensions/amavis_quarantine/views.py
index 621d07442..d0ff5ef41 100644
--- a/extensions/amavis_quarantine/views.py
+++ b/extensions/amavis_quarantine/views.py
@@ -1,6 +1,6 @@
# coding: utf-8
import email
-from django.http import HttpResponseRedirect, HttpResponse
+from django.http import HttpResponseRedirect, HttpResponse, Http404
from django.template import Template, Context
from django.utils import simplejson
from django.utils.translation import ugettext as _, ungettext
@@ -9,9 +9,10 @@ from django.contrib.auth.decorators \
import login_required
from django.db.models import Q
from modoboa.lib import parameters
-from modoboa.lib.webutils import _render, getctx, ajax_response
+from modoboa.lib.exceptions import ModoboaException
+from modoboa.lib.webutils import _render, getctx, ajax_response, ajax_simple_response
from modoboa.admin.models import Mailbox
-from lib import AMrelease
+from lib import AMrelease, selfservice
from templatetags.amextras import *
from modoboa.lib.email_listing import parse_search_parameters
from sql_listing import *
@@ -116,7 +117,21 @@ def index(request):
deflocation="listing/", defcallback="listing_cb", selection="quarantine"
))
-@login_required
+def getmailcontent_selfservice(request, mail_id):
+ from sql_listing import SQLemail
+
+ qmails = Quarantine.objects.filter(mail=mail_id)
+ content = ""
+ for qm in qmails:
+ content += qm.mail_text
+ msg = email.message_from_string(content)
+ mail = SQLemail(msg, mformat="plain", links="0")
+ return _render(request, "common/viewmail.html", {
+ "headers" : mail.render_headers(),
+ "mailbody" : mail.body
+ })
+
+@selfservice(getmailcontent_selfservice)
def getmailcontent(request, mail_id):
from sql_listing import SQLemail
@@ -133,7 +148,21 @@ def getmailcontent(request, mail_id):
"mailbody" : mail.body
})
-@login_required
+def viewmail_selfservice(request, mail_id,
+ tplname="amavis_quarantine/viewmail_selfservice.html"):
+ rcpt = request.GET.get("rcpt", None)
+ secret_id = request.GET.get("secret_id", "")
+ if rcpt is None:
+ raise Http404
+ content = Template("""
+
+""").render(Context(dict(mail_id=mail_id)))
+
+ return _render(request, tplname, dict(
+ mail_id=mail_id, rcpt=rcpt, secret_id=secret_id, content=content
+ ))
+
+@selfservice(viewmail_selfservice)
def viewmail(request, mail_id):
if request.user.group != 'SimpleUsers':
rcpt = request.GET["rcpt"]
@@ -175,7 +204,19 @@ def check_mail_id(request, mail_id):
mail_id = [mail_id]
return mail_id
-@login_required
+def delete_selfservice(request, mail_id):
+ rcpt = request.GET.get("rcpt", None)
+ if rcpt is None:
+ raise ModoboaException(_("Invalid request"))
+ try:
+ msgrcpt = Msgrcpt.objects.get(mail=mail_id, rid__email=rcpt)
+ msgrcpt.rs = 'D'
+ msgrcpt.save()
+ except Msgrcpt.DoesNotExist:
+ raise ModoboaException(_("Invalid request"))
+ return ajax_simple_response(dict(status="ok", respmsg=_("Message deleted")))
+
+@selfservice(delete_selfservice)
def delete(request, mail_id):
mail_id = check_mail_id(request, mail_id)
if request.user.group == 'SimpleUsers':
@@ -195,15 +236,38 @@ def delete(request, mail_id):
return ajax_response(request, respmsg=message,
url=__get_current_url(request))
-@login_required
+def release_selfservice(request, mail_id):
+ rcpt = request.GET.get("rcpt", None)
+ secret_id = request.GET.get("secret_id", None)
+ if rcpt is None or secret_id is None:
+ raise ModoboaException(_("Invalid request"))
+ try:
+ msgrcpt = Msgrcpt.objects.get(mail=mail_id, rid__email=rcpt)
+ except Msgrcpt.DoesNotExist:
+ raise ModoboaException(_("Invalid request"))
+ if secret_id != msgrcpt.mail.secret_id:
+ raise ModoboaException(_("Invalid request"))
+ if parameters.get_admin("USER_CAN_RELEASE") == "no":
+ msgrcpt.rs = 'p'
+ msg = _("Request sent")
+ else:
+ amr = AMrelease()
+ result = amr.sendreq(mail_id, secret_id, rcpt)
+ if result:
+ rcpt.rs = 'R'
+ msg = _("Message released")
+ else:
+ raise ModoboaException(result)
+ msgrcpt.save()
+ return ajax_simple_response(dict(status="ok", respmsg=msg))
+
+@selfservice(release_selfservice)
def release(request, mail_id):
mail_id = check_mail_id(request, mail_id)
if request.user.group == 'SimpleUsers':
mb = Mailbox.objects.get(user=request.user)
- print mail_id
msgrcpts = Msgrcpt.objects.filter(mail__in=mail_id, rid__email=mb.full_address)
if parameters.get_admin("USER_CAN_RELEASE") == "no":
- print msgrcpts
msgrcpts.update(rs='p')
message = ungettext("%(count)d request sent",
"%(count)d requests sent",
diff --git a/templates/common/viewmail.html b/templates/common/viewmail.html
index a73ff8a9d..19c00dd9e 100644
--- a/templates/common/viewmail.html
+++ b/templates/common/viewmail.html
@@ -1,6 +1,5 @@
-{% load i18n %}