mirror of
https://github.com/jwinterm/modoboa.git
synced 2026-10-17 05:41:25 +02:00
Ticket #32 + minor CSS modifications.
This commit is contained in:
@@ -90,19 +90,30 @@ def loadadminextmenu(perms):
|
||||
|
||||
@register.simple_tag
|
||||
def param(app, definition):
|
||||
print definition
|
||||
result = """<div class='row'>
|
||||
<label>%s</label>""" % definition["name"]
|
||||
name = "%s.%s" % (app, definition["name"])
|
||||
if definition["type"] in ["string", "int"]:
|
||||
value = definition.has_key("value") \
|
||||
and definition["value"] or definition["default"]
|
||||
name = "%s.%s" % (app, definition["name"])
|
||||
result += """
|
||||
<input type='text' name='%s' id='%s' value='%s' />""" % (name, name, value)
|
||||
if definition["type"] in ["list"]:
|
||||
if definition["type"] in ["list", "list_yesno"]:
|
||||
result += """
|
||||
<select name='' id=''>"""
|
||||
|
||||
<select name='%s' id='%s'>""" % (name, name)
|
||||
values = []
|
||||
if definition["type"] == "list_yesno":
|
||||
values = [("yes", _("Yes")), ("no", _("No"))]
|
||||
else:
|
||||
if definition.has_key("values"):
|
||||
values = definition["values"]
|
||||
value = definition.has_key("value") \
|
||||
and definition["value"] or definition["default"]
|
||||
for v in values:
|
||||
selected = ""
|
||||
if value == v[0]:
|
||||
selected = " selected='selected'"
|
||||
result += "<option value='%s'%s>%s</option>\n" % (v[0], selected, v[1])
|
||||
result += """
|
||||
</select>
|
||||
"""
|
||||
|
||||
+3
-1
@@ -413,8 +413,10 @@ def viewparameters(request):
|
||||
for app in apps:
|
||||
tmp = {"name" : app, "params" : []}
|
||||
for p in sorted(parameters._params[app]):
|
||||
tmp["params"] += [{"name" : p, "value" : parameters.get(app, p),
|
||||
tmp["params"] += [{"name" : p,
|
||||
"value" : parameters.get(app, p),
|
||||
"help" : parameters._params[app][p]["help"],
|
||||
"default" : parameters._params[app][p]["default"],
|
||||
"type" : parameters._params[app][p]["type"]}]
|
||||
gparams += [tmp]
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import re
|
||||
import time
|
||||
import imaplib
|
||||
import ssl
|
||||
from datetime import datetime, timedelta
|
||||
from email.header import decode_header
|
||||
import email.utils
|
||||
@@ -69,7 +70,10 @@ class IMAPheader(object):
|
||||
|
||||
@staticmethod
|
||||
def parse_date(value):
|
||||
ndate = datetime(*(email.utils.parsedate_tz(value))[:7])
|
||||
tmp = email.utils.parsedate_tz(value)
|
||||
if not tmp:
|
||||
return value
|
||||
ndate = datetime(*(tmp)[:7])
|
||||
now = datetime.now()
|
||||
if now - ndate > timedelta(7):
|
||||
return ndate.strftime("%d.%m.%Y %H:%M")
|
||||
@@ -90,22 +94,30 @@ class IMAPconnector(object):
|
||||
|
||||
def __init__(self, request=None, user=None, password=None):
|
||||
self.address = parameters.get("webmail", "IMAP_SERVER")
|
||||
self.port = int(parameters.get("webmail", "IMAP_PORT"))
|
||||
if request:
|
||||
status, msg = self.login(request.user.username,
|
||||
request.session["password"])
|
||||
else:
|
||||
status, msg = self.login(user, password)
|
||||
if not status:
|
||||
# Gestion d'erreur
|
||||
pass
|
||||
raise Exception(msg)
|
||||
|
||||
def login(self, user, passwd):
|
||||
import imaplib
|
||||
try:
|
||||
self.m = imaplib.IMAP4_SSL(self.address)
|
||||
secured = parameters.get("webmail", "IMAP_SECURED")
|
||||
if secured == "yes":
|
||||
self.m = imaplib.IMAP4_SSL(self.address, self.port)
|
||||
else:
|
||||
self.m = imaplib.IMAP4(self.address, self.port)
|
||||
except (imaplib.IMAP4.error, ssl.SSLError), error:
|
||||
return False, _("Connection to IMAP server failed, check your configuration")
|
||||
try:
|
||||
self.m.login(user, passwd)
|
||||
except imaplib.IMAP4.error, test:
|
||||
return False, test
|
||||
except (imaplib.IMAP4.error, ssl.SSLError), error:
|
||||
return False, _("Authentication failed, check your configuration")
|
||||
|
||||
return True, None
|
||||
|
||||
def _encodefolder(self, folder):
|
||||
@@ -113,9 +125,18 @@ class IMAPconnector(object):
|
||||
return "INBOX"
|
||||
return folder.encode("imap4-utf-7")
|
||||
|
||||
def messages_count(self, folder=None):
|
||||
def messages_count(self, folder=None, order=None):
|
||||
if order:
|
||||
sign = order[:1]
|
||||
criterion = order[1:].upper()
|
||||
if sign == '-':
|
||||
criterion = "REVERSE %s" % criterion
|
||||
else:
|
||||
criterion = "REVERSE DATE"
|
||||
print criterion
|
||||
|
||||
(status, data) = self.m.select(self._encodefolder(folder))
|
||||
(status, data) = self.m.sort("(REVERSE DATE)", "UTF-8", "(NOT DELETED)")
|
||||
(status, data) = self.m.sort("(%s)" % criterion, "UTF-8", "(NOT DELETED)")
|
||||
self.messages = data[0].split()
|
||||
return len(self.messages)
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ from django.core.urlresolvers import reverse
|
||||
from django.conf.urls.defaults import include
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from mailng.admin.models import Mailbox
|
||||
from mailng.lib import events, parameters, _render
|
||||
from mailng.lib import events, parameters, _render, _render_error
|
||||
from mailng.lib.email_listing import Email
|
||||
from imap_listing import *
|
||||
from forms import *
|
||||
@@ -20,7 +20,7 @@ def init():
|
||||
events.register("UserLogin", userlogin)
|
||||
parameters.register("webmail", "IMAP_SERVER", "string", "127.0.0.1",
|
||||
help=_("Address of your IMAP server"))
|
||||
parameters.register("webmail", "IMAP_SECURED", "list", "No",
|
||||
parameters.register("webmail", "IMAP_SECURED", "list_yesno", "no",
|
||||
help=_("Use a secure connexion to access IMAP server"))
|
||||
parameters.register("webmail", "IMAP_PORT", "int", "143",
|
||||
help=_("Listening port of your IMAP server"))
|
||||
@@ -60,8 +60,9 @@ def folder(request, name, updatenav=True):
|
||||
pageid = request.GET.has_key("page") and int(request.GET["page"]) or 1
|
||||
request.session["folder"] = name
|
||||
request.session["page"] = pageid
|
||||
order = request.GET.has_key("order") and request.GET["order"] or None
|
||||
lst = ImapListing(request.user.username, request.session["password"],
|
||||
name, folder=name)
|
||||
name, folder=name, order=order)
|
||||
page = lst.paginator.getpage(request.session["page"])
|
||||
if page:
|
||||
content = lst.fetch(request, page.id_start, page.id_stop)
|
||||
@@ -75,8 +76,11 @@ def folder(request, name, updatenav=True):
|
||||
|
||||
@login_required
|
||||
def index(request):
|
||||
lst = ImapListing(request.user.username, request.session["password"],
|
||||
"INBOX", folder="INBOX")
|
||||
try:
|
||||
lst = ImapListing(request.user.username, request.session["password"],
|
||||
"INBOX", folder="INBOX")
|
||||
except Exception as exp:
|
||||
return _render_error(request, {"error" : exp})
|
||||
return lst.render(request, empty=True)
|
||||
|
||||
def fetchmail(request, folder, mail_id, all=False):
|
||||
|
||||
@@ -207,6 +207,32 @@ tr {
|
||||
});
|
||||
});
|
||||
$$("tr").addEvent("dblclick", viewmail);
|
||||
var sortOrder = "";
|
||||
$$("th[class=sortable]").addEvent("click", function(evt) {
|
||||
var tmp = "?";
|
||||
|
||||
if (sortOrder == "") {
|
||||
test = /order=([\+\-]\w+$|&)/.exec(location.hash);
|
||||
if (test) {
|
||||
sortOrder = test[1];
|
||||
}
|
||||
}
|
||||
if (sortOrder.substring(1) == evt.target.id) {
|
||||
var sign = (sortOrder.charAt(0) == '+') ? '-' : '+';
|
||||
sortOrder = sign + evt.target.id;
|
||||
} else {
|
||||
sortOrder = "-" + evt.target.id;
|
||||
}
|
||||
if (location.hash.indexOf("?") != -1) {
|
||||
if (location.hash.indexOf("order") != -1) {
|
||||
location.hash = location.hash.replace(/order=[\+\-]\w+$|&/,
|
||||
"order=" + sortOrder);
|
||||
return;
|
||||
}
|
||||
tmp = "&";
|
||||
}
|
||||
location.hash += tmp + "order=" + sortOrder;
|
||||
});
|
||||
});
|
||||
|
||||
navbarcallback = function(event) {
|
||||
@@ -224,10 +250,6 @@ tr {
|
||||
$$("a[name=compose]").addEvent("click", loadCompose);
|
||||
{% endblock %}
|
||||
{% block middletitle %}{% trans "Webmail" %}{% endblock %}
|
||||
{% block menu %}
|
||||
{% load webextras %}
|
||||
{% listing_menu "" "INBOX" perms %}
|
||||
{% endblock %}
|
||||
{% block leftcol %}
|
||||
<div id="leftcol" class="box">
|
||||
<h3>{% trans "Folders" %}</h3>
|
||||
|
||||
@@ -50,6 +50,10 @@ def _render(request, tpl, user_context):
|
||||
return render_to_response(tpl, user_context,
|
||||
context_instance=RequestContext(request))
|
||||
|
||||
def _render_error(request, user_context):
|
||||
return render_to_response("common/error.html", user_context,
|
||||
context_instance=RequestContext(request))
|
||||
|
||||
def exec_as_vuser(cmd):
|
||||
code, output = exec_pipe("sudo -u %s %s" % (settings.VIRTUAL_UID, cmd))
|
||||
if code:
|
||||
|
||||
@@ -80,7 +80,8 @@ class EmailListing:
|
||||
def __init__(self, folder=None, elems_per_page=40, **kwargs):
|
||||
self.folder = folder
|
||||
self.elems_per_page = elems_per_page
|
||||
self.paginator = Paginator(self.mbc.messages_count(self.folder),
|
||||
order = "order" in kwargs.keys() and kwargs["order"] or None
|
||||
self.paginator = Paginator(self.mbc.messages_count(self.folder, order),
|
||||
elems_per_page)
|
||||
|
||||
def render_navbar(self, page):
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@ class NotDefined(Exception):
|
||||
return "Application '%s' and/or parameter '%s' not defined" % (self.app,
|
||||
self.name)
|
||||
|
||||
def register(app, name, type="string", deflt=None, help=None):
|
||||
def register(app, name, type="string", deflt=None, help=None, **kwargs):
|
||||
"""Register a new parameter.
|
||||
|
||||
app corresponds to a core component (admin, main) or an extension.
|
||||
|
||||
+1
-1
@@ -23,7 +23,7 @@ check_anchor = function() {
|
||||
query = "INBOX/"; // Default location
|
||||
} else {
|
||||
var splits = current_anchor.substring(1).split('?');
|
||||
var section = splits[0];
|
||||
var section = (splits[0] != "") ? splits[0] : "INBOX";
|
||||
delete splits[0];
|
||||
var params = splits.join('&');
|
||||
if (section[section.length - 1] != '/') {
|
||||
|
||||
@@ -66,6 +66,7 @@ window.addEvent('domready', function() {
|
||||
}
|
||||
}
|
||||
});
|
||||
setDivHeight("content", 20, 0);
|
||||
});
|
||||
|
||||
newdom = function() {
|
||||
|
||||
@@ -3,6 +3,7 @@ window.addEvent('domready', function() {
|
||||
parse: 'rel',
|
||||
|
||||
});
|
||||
setDivHeight("content", 20, 0);
|
||||
|
||||
if ($$("a[name=deletePerm]"))
|
||||
$$("a[name=deletePerm]").addEvent('click', function(event) {
|
||||
|
||||
@@ -262,16 +262,13 @@ table.hr {
|
||||
}
|
||||
|
||||
.toggler {
|
||||
color: #222;
|
||||
margin: 0;
|
||||
margin: 5px auto;
|
||||
padding: 2px 5px;
|
||||
background: #eee;
|
||||
border-bottom: 1px solid #ddd;
|
||||
border-right: 1px solid #ddd;
|
||||
border-top: 1px solid #f5f5f5;
|
||||
border-left: 1px solid #f5f5f5;
|
||||
font-size: small;
|
||||
font-weight: normal;
|
||||
background: #CEDBEC;
|
||||
-moz-border-radius: 5px;
|
||||
-webkit-border-radius: 5px;
|
||||
/*border: 1px solid #CCC;*/
|
||||
font-size: 1.1em;
|
||||
}
|
||||
|
||||
.element {
|
||||
@@ -287,3 +284,14 @@ div.row label {
|
||||
width: 200px;
|
||||
padding: 3px 0;
|
||||
}
|
||||
|
||||
.error {
|
||||
margin: 0 auto;
|
||||
padding: 5px;
|
||||
background: red;
|
||||
width: 500px;
|
||||
text-align: center;
|
||||
background-color: #F9D2D2;
|
||||
border: 3px solid #FF2A2A;
|
||||
color: #FF2A00;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{% extends "nlayout.html" %}
|
||||
{% load i18n %}
|
||||
{% block middletitle %}{% trans "Error" %}{% endblock %}
|
||||
{% block content %}
|
||||
<div class="error"><p>{{ error }}</p></div>
|
||||
{% endblock %}
|
||||
@@ -2,7 +2,7 @@
|
||||
<thead>
|
||||
<tr>
|
||||
{% for c in table.columns %}
|
||||
<th width="{{ c.width }}">{{ c|safe }}</th>
|
||||
<th id="{{ c.name }}" class="sortable" width="{{ c.width }}">{{ c|safe }}</th>
|
||||
{% endfor %}
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
Reference in New Issue
Block a user