diff --git a/extensions/amavis_quarantine/main.py b/extensions/amavis_quarantine/main.py index 40683a875..f5b734a6b 100644 --- a/extensions/amavis_quarantine/main.py +++ b/extensions/amavis_quarantine/main.py @@ -2,27 +2,10 @@ """ """ -from datetime import datetime -import time -import email -import re -import os -from django.http import HttpResponseRedirect, HttpResponse -from django.template import Template, Context -from django.utils import simplejson from django.conf.urls.defaults import * from django.utils.translation import ugettext as _, ungettext from django.core.urlresolvers import reverse -from django.contrib.auth.decorators \ - import login_required from mailng.lib import events, parameters -from mailng.lib import _render, _ctx_ok, _ctx_ko, decode, getctx -from mailng.lib import db -from mailng.admin.models import Mailbox -from lib import AMrelease -from templatetags.amextras import * -from mailng.lib.email_listing import parse_search_parameters -from sql_listing import * def infos(): return { @@ -55,185 +38,14 @@ def urls(): include('mailng.extensions.amavis_quarantine.urls')) def menu(**kwargs): + import views + if kwargs["target"] == "user_menu_box": return [ {"name" : "quarantine", "label" : _("Quarantine"), - "url" : reverse(index), + "url" : reverse(views.index), "img" : "/static/pics/quarantine.png"} ] return [] -def __get_current_url(request): - res = "?page=%s" % request.session["page"] - for p in ["criteria", "pattern"]: - if p in request.session.keys(): - res += "&%s=%s" % (p, request.session[p]) - return res - -@login_required -def _listing(request, internal=False, filter=None): - #start = time.time() - if not request.user.is_superuser: - mb = Mailbox.objects.get(user=request.user.id) - if filter is None: - filter = ["&maddr.email='%s'" % mb.full_address] - else: - filter += ["&maddr.email='%s'" % mb.full_address] - - parse_search_parameters(request) - if request.session.has_key("pattern"): - tmp = "" - for c in request.session["criteria"].split(','): - if tmp != "": - tmp += " OR " - tmp += "msgs.%s LIKE '%%%s%%'" % (c, request.session["pattern"]) - tmp = "&(%s)" % tmp - if filter is None: - filter = [tmp] - else: - filter += [tmp] - - pageid = request.GET.has_key("page") and int(request.GET["page"]) or 1 - request.session["page"] = pageid # ?? nécessaire - lst = SQLlisting(filter, baseurl="listing/", empty=internal) - if internal: - return lst.render(request, pageid=int(pageid)) - page = lst.paginator.getpage(pageid) - if page: - content = lst.fetch(request, page.id_start, page.id_stop) - navbar = lst.render_navbar(page) - else: - content = _("Empty quarantine") - navbar = "" - ctx = getctx("ok", listing=content, navbar=navbar, - menu=quar_menu("", request.user.get_all_permissions())) - return HttpResponse(simplejson.dumps(ctx), mimetype="application/json") - -@login_required -def index(request, message=None): - return _listing(request, True) - -@login_required -def getmailcontent(request, mail_id): - from sql_listing import SQLemail - - 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) - links = request.GET.has_key("links") and request.GET["links"] or "0" - mode = request.GET.has_key("mode") and request.GET["mode"] or "plain" - mail = SQLemail(msg, mode, links) - return _render(request, "common/viewmail.html", { - "headers" : mail.render_headers(), - "mailbody" : mail.body, - "pre" : mail.pre - }) - -@login_required -def viewmail(request, mail_id): - args = "" - for kw in ["mode", "links"]: - if kw in request.GET.keys(): - args += args != "" and "&" or "?" - args += "%s=%s" % (kw, request.GET[kw]) - content = Template(""" - -""").render(Context({"url" : reverse(getmailcontent, args=[mail_id]) + args})) - menu = viewm_menu("", __get_current_url(request), mail_id, - request.user.get_all_permissions()) - ctx = getctx("ok", menu=menu, listing=content) - return HttpResponse(simplejson.dumps(ctx), mimetype="application/json") - -@login_required -def viewheaders(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) - return _render(request, 'amavis_quarantine/viewheader.html', { - "headers" : msg.items() - }) - -@login_required -def delete(request, mail_id, count=1): - conn = db.getconnection("amavis_quarantine") - if mail_id[0] != "'": - mail_id = "'%s'" % mail_id - status, error = db.execute(conn, - "DELETE FROM msgs WHERE mail_id IN (%s)" % mail_id) - if status: - message = ungettext("%(count)d message deleted successfully", - "%(count)d messages deleted successfully", - count) % {"count" : count} - else: - message = error - ctx = getctx("ok", url=__get_current_url(request), message=message) - return HttpResponse(simplejson.dumps(ctx), - mimetype="application/json") - -@login_required -def release(request, mail_id, count=1): - conn = db.getconnection("amavis_quarantine") - if mail_id[0] != "'": - mail_id = "'%s'" % mail_id - 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) -""" % (mail_id)) - emails = {} - amr = AMrelease() - 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 - error = None - for k, values in emails.iteritems(): - result = amr.sendreq(k, values["secret"], *values["rcpts"]) - if result: - count += 1 - else: - error = result - break - if not error: - message = ungettext("%(count)d message released successfully", - "%(count)d messages released successfully", - count) % {"count" : count} - else: - message = error - ctx = getctx("ok", url=__get_current_url(request), message=message) - return HttpResponse(simplejson.dumps(ctx), - mimetype="application/json") - -@login_required -def process(request): - ids = "" - count = len(request.POST["selection"].split(",")) - for id in request.POST["selection"].split(","): - if ids != "": - ids += "," - ids += "'%s'" % id - if ids == "": - return HttpResponseRedirect(reverse(index)) - - if request.POST["action"] == "release": - return release(request, ids, count) - - if request.POST["action"] == "delete": - return delete(request, ids, count) diff --git a/extensions/amavis_quarantine/templates/index.html b/extensions/amavis_quarantine/templates/index.html index 78f537496..2889f2236 100644 --- a/extensions/amavis_quarantine/templates/index.html +++ b/extensions/amavis_quarantine/templates/index.html @@ -71,6 +71,16 @@ tr.table-tr-selected { $$("a[name=selectmsgs]").addEvent("click", function(evt) { evt.stop(); var type = evt.target.get("href"); + if (!$chk(type)) { + $$("tr[class*=table-tr-selected]").each(function(item) { + item.removeClass("table-tr-selected"); + }); + if ($("toggleselect").checked) { + $("toggleselect").checked = false; + tbl.selectNone(); + } + return; + } $$("td[name=type]").each(function(item) { if (item.get("html").trim() == type) { item.getParent().addClass("table-tr-selected"); diff --git a/extensions/amavis_quarantine/templatetags/amextras.py b/extensions/amavis_quarantine/templatetags/amextras.py index b8aaccb08..d16e0c7bb 100644 --- a/extensions/amavis_quarantine/templatetags/amextras.py +++ b/extensions/amavis_quarantine/templatetags/amextras.py @@ -26,18 +26,18 @@ def viewm_menu(selection, backurl, mail_id, perms): "img" : "/static/pics/back.png", "label" : _("Back to list")}, {"name" : "headers", - "url" : reverse(amavis_quarantine.main.viewheaders, args=[mail_id]), + "url" : reverse(amavis_quarantine.views.viewheaders, args=[mail_id]), "img" : "/static/pics/add.png", "label" : _("View full headers"), "class" : "boxed", "rel" : "{handler:'iframe',size:{x:600,y:500}}"}, {"name" : "release", - "url" : reverse(amavis_quarantine.main.release, args=[mail_id]), + "url" : reverse(amavis_quarantine.views.release, args=[mail_id]), "img" : "/static/pics/release.png", "label" : _("Release"), "confirm" : _("Release this message?")}, {"name" : "delete", - "url" : reverse(amavis_quarantine.main.delete, args=[mail_id]), + "url" : reverse(amavis_quarantine.views.delete, args=[mail_id]), "img" : "/static/pics/remove.png", "label" : _("Delete"), "confirm" : _("Delete this message?")}, @@ -66,9 +66,12 @@ def quar_menu(selection, perms): {"name" : "select", "url" : "", "img" : "/static/pics/domains.png", - "label" : _("Select all"), + "label" : _("Select"), "class" : "menubardropdown", "menu" : [ + {"name" : "selectmsgs", + "url" : "", + "label" : _("Nothing")}, {"name" : "selectmsgs", "url" : "S", "label" : _("Spam")}, diff --git a/extensions/amavis_quarantine/urls.py b/extensions/amavis_quarantine/urls.py index 22dc36b70..2d33d8d6d 100644 --- a/extensions/amavis_quarantine/urls.py +++ b/extensions/amavis_quarantine/urls.py @@ -1,6 +1,6 @@ from django.conf.urls.defaults import * -urlpatterns = patterns('mailng.extensions.amavis_quarantine.main', +urlpatterns = patterns('mailng.extensions.amavis_quarantine.views', (r'^$', 'index'), (r'^listing/$', '_listing'), (r'^getmailcontent/(?P[\w\-\+]+)/$', 'getmailcontent'), diff --git a/extensions/amavis_quarantine/views.py b/extensions/amavis_quarantine/views.py new file mode 100644 index 000000000..d9a95ca04 --- /dev/null +++ b/extensions/amavis_quarantine/views.py @@ -0,0 +1,195 @@ +# -*- coding: utf-8 -*- + +from datetime import datetime +import time +import email +import re +import os +from django.http import HttpResponseRedirect, HttpResponse +from django.template import Template, Context +from django.utils import simplejson +from django.utils.translation import ugettext as _, ungettext +from django.core.urlresolvers import reverse +from django.contrib.auth.decorators \ + import login_required +from mailng.lib import _render, _ctx_ok, _ctx_ko, decode, getctx +from mailng.lib import db +from mailng.admin.models import Mailbox +from lib import AMrelease +from templatetags.amextras import * +from mailng.lib.email_listing import parse_search_parameters +from sql_listing import * + +def __get_current_url(request): + res = "?page=%s" % request.session["page"] + for p in ["criteria", "pattern"]: + if p in request.session.keys(): + res += "&%s=%s" % (p, request.session[p]) + return res + +@login_required +def _listing(request, internal=False, filter=None): + #start = time.time() + if not request.user.is_superuser: + mb = Mailbox.objects.get(user=request.user.id) + if filter is None: + filter = ["&maddr.email='%s'" % mb.full_address] + else: + filter += ["&maddr.email='%s'" % mb.full_address] + + parse_search_parameters(request) + if request.session.has_key("pattern"): + tmp = "" + for c in request.session["criteria"].split(','): + if tmp != "": + tmp += " OR " + tmp += "msgs.%s LIKE '%%%s%%'" % (c, request.session["pattern"]) + tmp = "&(%s)" % tmp + if filter is None: + filter = [tmp] + else: + filter += [tmp] + + pageid = request.GET.has_key("page") and int(request.GET["page"]) or 1 + request.session["page"] = pageid # ?? nécessaire + lst = SQLlisting(filter, baseurl="listing/", empty=internal) + if internal: + return lst.render(request, pageid=int(pageid)) + page = lst.paginator.getpage(pageid) + if page: + content = lst.fetch(request, page.id_start, page.id_stop) + navbar = lst.render_navbar(page) + else: + content = _("Empty quarantine") + navbar = "" + ctx = getctx("ok", listing=content, navbar=navbar, + menu=quar_menu("", request.user.get_all_permissions())) + return HttpResponse(simplejson.dumps(ctx), mimetype="application/json") + +@login_required +def index(request, message=None): + return _listing(request, True) + +@login_required +def getmailcontent(request, mail_id): + from sql_listing import SQLemail + + 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) + links = request.GET.has_key("links") and request.GET["links"] or "0" + mode = request.GET.has_key("mode") and request.GET["mode"] or "plain" + mail = SQLemail(msg, mode, links) + return _render(request, "common/viewmail.html", { + "headers" : mail.render_headers(), + "mailbody" : mail.body, + "pre" : mail.pre + }) + +@login_required +def viewmail(request, mail_id): + args = "" + for kw in ["mode", "links"]: + if kw in request.GET.keys(): + args += args != "" and "&" or "?" + args += "%s=%s" % (kw, request.GET[kw]) + content = Template(""" + +""").render(Context({"url" : reverse(getmailcontent, args=[mail_id]) + args})) + menu = viewm_menu("", __get_current_url(request), mail_id, + request.user.get_all_permissions()) + ctx = getctx("ok", menu=menu, listing=content) + return HttpResponse(simplejson.dumps(ctx), mimetype="application/json") + +@login_required +def viewheaders(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) + return _render(request, 'amavis_quarantine/viewheader.html', { + "headers" : msg.items() + }) + +@login_required +def delete(request, mail_id, count=1): + conn = db.getconnection("amavis_quarantine") + if mail_id[0] != "'": + mail_id = "'%s'" % mail_id + status, error = db.execute(conn, + "DELETE FROM msgs WHERE mail_id IN (%s)" % mail_id) + if status: + message = ungettext("%(count)d message deleted successfully", + "%(count)d messages deleted successfully", + count) % {"count" : count} + else: + message = error + ctx = getctx("ok", url=__get_current_url(request), message=message) + return HttpResponse(simplejson.dumps(ctx), + mimetype="application/json") + +@login_required +def release(request, mail_id, count=1): + conn = db.getconnection("amavis_quarantine") + if mail_id[0] != "'": + mail_id = "'%s'" % mail_id + 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) +""" % (mail_id)) + emails = {} + amr = AMrelease() + 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 + error = None + for k, values in emails.iteritems(): + result = amr.sendreq(k, values["secret"], *values["rcpts"]) + if result: + count += 1 + else: + error = result + break + if not error: + message = ungettext("%(count)d message released successfully", + "%(count)d messages released successfully", + count) % {"count" : count} + else: + message = error + ctx = getctx("ok", url=__get_current_url(request), message=message) + return HttpResponse(simplejson.dumps(ctx), + mimetype="application/json") + +@login_required +def process(request): + ids = "" + count = len(request.POST["selection"].split(",")) + for id in request.POST["selection"].split(","): + if ids != "": + ids += "," + ids += "'%s'" % id + if ids == "": + return HttpResponseRedirect(reverse(index)) + + if request.POST["action"] == "release": + return release(request, ids, count) + + if request.POST["action"] == "delete": + return delete(request, ids, count) diff --git a/extensions/postfix_autoreply/main.py b/extensions/postfix_autoreply/main.py index 894d05257..c386e04ef 100644 --- a/extensions/postfix_autoreply/main.py +++ b/extensions/postfix_autoreply/main.py @@ -7,15 +7,10 @@ This module provides a way to integrate MailNG auto-reply functionality into Postfix. """ -from django.http import HttpResponse -from django.utils import simplejson -from django.contrib.auth.decorators \ - import login_required from django.conf.urls.defaults import include from django.core.urlresolvers import reverse from django.utils.translation import ugettext as _ -from mailng.lib import _render, events, parameters, _ctx_ok, _ctx_ko -from forms import * +from mailng.lib import events, parameters from models import * def infos(): @@ -50,11 +45,13 @@ def urls(): include('mailng.extensions.postfix_autoreply.urls')) def menu(**kwargs): + import views + if kwargs["target"] != "user_menu_bar": return [] return [ {"name" : "autoreply", - "url" : reverse(autoreply), + "url" : reverse(views.autoreply), "img" : "/static/pics/auto-reply.png", "class" : "boxed", "rel" : "{handler:'iframe',size:{x:440,y:370}}", @@ -99,38 +96,3 @@ def onModifyMailbox(**kwargs): alias.autoreply_address = \ "%s@autoreply.%s" % (mbox.full_address, mbox.domain.name) alias.save() - -@login_required -def autoreply(request): - mb = Mailbox.objects.get(user=request.user.id) - try: - arm = ARmessage.objects.get(mbox=mb.id) - except ARmessage.DoesNotExist: - arm = None - if request.method == "POST": - if arm: - form = ARmessageForm(request.POST, instance=arm) - else: - form = ARmessageForm(request.POST) - error = None - if form.is_valid(): - from mailng import userprefs - - arm = form.save(commit=False) - arm.mbox = mb - arm.save() - request.user.message_set.create( - message=_("Auto reply message updated successfully.") - ) - ctx = _ctx_ok(reverse(userprefs.views.index)) - else: - ctx = _ctx_ko("postfix_autoreply/autoreply.html", { - "form" : form, "error" : error - }) - return HttpResponse(simplejson.dumps(ctx), - mimetype="application/json") - - form = ARmessageForm(instance=arm) - return _render(request, "postfix_autoreply/autoreply.html", { - "form" : form - }) diff --git a/extensions/postfix_autoreply/templates/autoreply.html b/extensions/postfix_autoreply/templates/autoreply.html index f282c21e8..6ce9e2e9e 100644 --- a/extensions/postfix_autoreply/templates/autoreply.html +++ b/extensions/postfix_autoreply/templates/autoreply.html @@ -26,7 +26,7 @@ window.addEvent("domready", function() { {% block content %}

{% trans "Auto-reply message" %}

-
{% include "common/genericform.html" %}
diff --git a/extensions/postfix_autoreply/urls.py b/extensions/postfix_autoreply/urls.py index e0bfc51f2..641969efb 100644 --- a/extensions/postfix_autoreply/urls.py +++ b/extensions/postfix_autoreply/urls.py @@ -1,5 +1,5 @@ from django.conf.urls.defaults import * -urlpatterns = patterns('mailng.extensions.postfix_autoreply.main', +urlpatterns = patterns('mailng.extensions.postfix_autoreply.views', url(r'^$', 'autoreply'), ) diff --git a/extensions/postfix_autoreply/views.py b/extensions/postfix_autoreply/views.py new file mode 100644 index 000000000..9d182bc1e --- /dev/null +++ b/extensions/postfix_autoreply/views.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- + +from django.http import HttpResponse +from django.utils import simplejson +from django.contrib.auth.decorators \ + import login_required +from django.core.urlresolvers import reverse +from django.utils.translation import ugettext as _ +from mailng.lib import _render, _ctx_ok, _ctx_ko +from forms import * +from models import * + +@login_required +def autoreply(request): + mb = Mailbox.objects.get(user=request.user.id) + try: + arm = ARmessage.objects.get(mbox=mb.id) + except ARmessage.DoesNotExist: + arm = None + if request.method == "POST": + if arm: + form = ARmessageForm(request.POST, instance=arm) + else: + form = ARmessageForm(request.POST) + error = None + if form.is_valid(): + from mailng import userprefs + + arm = form.save(commit=False) + arm.mbox = mb + arm.save() + request.user.message_set.create( + message=_("Auto reply message updated successfully.") + ) + ctx = _ctx_ok(reverse(userprefs.views.index)) + else: + ctx = _ctx_ko("postfix_autoreply/autoreply.html", { + "form" : form, "error" : error + }) + return HttpResponse(simplejson.dumps(ctx), + mimetype="application/json") + + form = ARmessageForm(instance=arm) + return _render(request, "postfix_autoreply/autoreply.html", { + "form" : form + }) diff --git a/extensions/stats/main.py b/extensions/stats/main.py index 74d985a34..232cc0142 100644 --- a/extensions/stats/main.py +++ b/extensions/stats/main.py @@ -7,23 +7,10 @@ This module provides support to retrieve statistics from postfix log : sent, received, bounced, rejected """ -import calendar from django.core.urlresolvers import reverse from django.utils.translation import ugettext as _ from django.conf.urls.defaults import * -from mailng.lib import events, parameters, _render -from mailng.admin.views import good_domain -from mailng.admin.models import Domain, Mailbox -from django.contrib.auth.decorators \ - import login_required, user_passes_test, permission_required -from extensions.stats.grapher import Grapher, tpl -from extensions.stats.logparser import str2Time - -graph_types = ['AVERAGE', 'MAX'] - -graph_list = [{"name" : "traffic", "label" : _("Average normal traffic")}, - {"name" : "badtraffic", "label" : _("Average bad traffic")}, - {"name" : "size", "label" : _("Average normal traffic size")}] +from mailng.lib import events, parameters def infos(): return { @@ -65,136 +52,3 @@ def menu(**kwargs): "img" : "/static/pics/graph.png"} ] return [] - -@login_required -def domain(request, dom_id): - domains = [] - errors = [] - return graph_display(request,dom_id,graph_types) - -@login_required -def graph_display(request,dom_id,graph_t=graph_types): - domains = [] - errors = [] - graph_type = None - domain=None - if type(graph_t) == type([]): - graph_type = graph_t - else : - graph_type = [graph_t] - - if dom_id: - domain = Domain.objects.get(pk=dom_id) - if domain: - domains.append(domain) - - if domains == []: - errors.append(_("No Domain defined")) - - - for d in domains: - P = parser(d.name) - if type(P) == type('err'): - errors.append(P) - else: - P.plot_rrd() - - return _render(request, 'stats/index.html', { - "page" : "Domain statistics", "graph" : graph_nature, - "domain": domain, "domains" : domains, "messages" : errors, - "types" : graph_type, "tmp_path" : tmp_path, - "img_rootdir" : parameters.get("stats", "IMG_ROOTDIR")}) - -@login_required -@user_passes_test(lambda u: u.is_superuser) -def adminindex(request): - CH = calendar.HTMLCalendar(calendar.MONDAY) - CH_print = CH.formatmonth(2009,11) - period = request.GET.has_key("period") and request.GET["period"] or "day" - domain = request.GET.has_key("domain") and request.GET["domain"] or "global" - if domain != "global": - domain = Domain.objects.get(pk=domain) - domain = domain.name - domains = Domain.objects.all() - G = Grapher() - for name, t in tpl.iteritems(): - G.make_defaults(domain, t) - - return _render(request, 'stats/adminindex.html', { - "domains" : domains, "domain" : domain, - "graphs" : graph_list, - "periods" : ["day", "week", "month", "year","Custom"], - "period" : period, "cal" : CH_print, - "img_rootdir" : parameters.get("stats", "IMG_ROOTDIR")}) - -@login_required -@user_passes_test(lambda u: u.is_superuser) -def custom_period(request): - start = None - end = None - start_ref = None - end_ref = None - domains = Domain.objects.all() - domain = request.GET.has_key("domain") and request.GET["domain"] or "global" - period = request.GET.has_key("period") and request.GET["period"] or "Custom" - - if domain != "global": - domain = Domain.objects.get(pk=domain) - domain = domain.name - try: - start_ref = str(request.POST.get('start')) - start = start_ref.split(', ')[1] - end_ref = str(request.POST.get('end')) - end = end_ref.split(', ')[1] - except: - pass - - if not end or not start: - return _render(request, 'stats/adminindex.html', { - "domains" : domains, "domain" : domain, - "graphs" : graph_list, - "period" : period, - "periods" : ["day", "week", "month", "year","Custom"], - "period_name":None, - "start" : start_ref, - "end" : end_ref, - "messages" : ["Custom period not selected"], - "img_rootdir" : parameters.get("stats", "IMG_ROOTDIR")}) - - period_name = "%s_%s" %(start.replace('/',''),end.replace('/','')) - G = Grapher() - for tpl_name in graph_list: - G.process(domain, - period_name, - str2Time(*start.split('/')), - str2Time(*end.split('/')), - tpl[tpl_name['name']]) - - print "[stats] ", period - return _render(request, 'stats/adminindex.html', { - "domains" : domains, "domain" : domain, - "graphs" : graph_list, - "period" : period, - "periods" : ["day", "week", "month", "year","Custom"], - "period_name": period_name, - "start" : start_ref, - "end" : end_ref, - "messages" : None, - "img_rootdir" : parameters.get("stats", "IMG_ROOTDIR")}) - - -@login_required -@good_domain -@permission_required("admin.view_mailboxes") -def index(request, dom_id=None): - domain = None - period = request.GET.has_key("period") and request.GET["period"] or "day" - if request.user.has_perm("admin.view_mailboxes"): - domain = Domain.objects.get(pk=dom_id) - - return _render(request, 'stats/index.html', { - "domain" : domain, - "graphs" : graph_list, - "periods" : ["day", "week", "month", "year","Custom"], - "period" : period, - "img_rootdir" : parameters.get("stats", "IMG_ROOTDIR")}) diff --git a/extensions/stats/urls.py b/extensions/stats/urls.py index b72709229..e22eaaa2f 100644 --- a/extensions/stats/urls.py +++ b/extensions/stats/urls.py @@ -1,6 +1,6 @@ from django.conf.urls.defaults import * -urlpatterns = patterns('mailng.extensions.stats.main', +urlpatterns = patterns('mailng.extensions.stats.views', url(r'^$', 'adminindex', name='fullindex'), url(r'^custom_period$', 'custom_period'), url(r'^(?P\d+)/$', 'index', name='domindex'), diff --git a/extensions/stats/views.py b/extensions/stats/views.py new file mode 100644 index 000000000..1b515dddf --- /dev/null +++ b/extensions/stats/views.py @@ -0,0 +1,150 @@ +# -*- coding: utf-8 -*- + +import calendar +from django.core.urlresolvers import reverse +from django.utils.translation import ugettext as _ +from mailng.lib import parameters, _render +from mailng.admin.views import good_domain +from mailng.admin.models import Domain, Mailbox +from django.contrib.auth.decorators \ + import login_required, user_passes_test, permission_required +from extensions.stats.grapher import Grapher, tpl +from extensions.stats.logparser import str2Time + +graph_types = ['AVERAGE', 'MAX'] +graph_list = [{"name" : "traffic", "label" : _("Average normal traffic")}, + {"name" : "badtraffic", "label" : _("Average bad traffic")}, + {"name" : "size", "label" : _("Average normal traffic size")}] + +@login_required +def domain(request, dom_id): + domains = [] + errors = [] + return graph_display(request,dom_id,graph_types) + +@login_required +def graph_display(request,dom_id,graph_t=graph_types): + domains = [] + errors = [] + graph_type = None + domain=None + if type(graph_t) == type([]): + graph_type = graph_t + else : + graph_type = [graph_t] + + if dom_id: + domain = Domain.objects.get(pk=dom_id) + if domain: + domains.append(domain) + + if domains == []: + errors.append(_("No Domain defined")) + + + for d in domains: + P = parser(d.name) + if type(P) == type('err'): + errors.append(P) + else: + P.plot_rrd() + + return _render(request, 'stats/index.html', { + "page" : "Domain statistics", "graph" : graph_nature, + "domain": domain, "domains" : domains, "messages" : errors, + "types" : graph_type, "tmp_path" : tmp_path, + "img_rootdir" : parameters.get("stats", "IMG_ROOTDIR")}) + +@login_required +@user_passes_test(lambda u: u.is_superuser) +def adminindex(request): + CH = calendar.HTMLCalendar(calendar.MONDAY) + CH_print = CH.formatmonth(2009,11) + period = request.GET.has_key("period") and request.GET["period"] or "day" + domain = request.GET.has_key("domain") and request.GET["domain"] or "global" + if domain != "global": + domain = Domain.objects.get(pk=domain) + domain = domain.name + domains = Domain.objects.all() + G = Grapher() + for name, t in tpl.iteritems(): + G.make_defaults(domain, t) + + return _render(request, 'stats/adminindex.html', { + "domains" : domains, "domain" : domain, + "graphs" : graph_list, + "periods" : ["day", "week", "month", "year","Custom"], + "period" : period, "cal" : CH_print, + "img_rootdir" : parameters.get("stats", "IMG_ROOTDIR")}) + +@login_required +@user_passes_test(lambda u: u.is_superuser) +def custom_period(request): + start = None + end = None + start_ref = None + end_ref = None + domains = Domain.objects.all() + domain = request.GET.has_key("domain") and request.GET["domain"] or "global" + period = request.GET.has_key("period") and request.GET["period"] or "Custom" + + if domain != "global": + domain = Domain.objects.get(pk=domain) + domain = domain.name + try: + start_ref = str(request.POST.get('start')) + start = start_ref.split(', ')[1] + end_ref = str(request.POST.get('end')) + end = end_ref.split(', ')[1] + except: + pass + + if not end or not start: + return _render(request, 'stats/adminindex.html', { + "domains" : domains, "domain" : domain, + "graphs" : graph_list, + "period" : period, + "periods" : ["day", "week", "month", "year","Custom"], + "period_name":None, + "start" : start_ref, + "end" : end_ref, + "messages" : ["Custom period not selected"], + "img_rootdir" : parameters.get("stats", "IMG_ROOTDIR")}) + + period_name = "%s_%s" %(start.replace('/',''),end.replace('/','')) + G = Grapher() + for tpl_name in graph_list: + G.process(domain, + period_name, + str2Time(*start.split('/')), + str2Time(*end.split('/')), + tpl[tpl_name['name']]) + + print "[stats] ", period + return _render(request, 'stats/adminindex.html', { + "domains" : domains, "domain" : domain, + "graphs" : graph_list, + "period" : period, + "periods" : ["day", "week", "month", "year","Custom"], + "period_name": period_name, + "start" : start_ref, + "end" : end_ref, + "messages" : None, + "img_rootdir" : parameters.get("stats", "IMG_ROOTDIR")}) + + +@login_required +@good_domain +@permission_required("admin.view_mailboxes") +def index(request, dom_id=None): + domain = None + period = request.GET.has_key("period") and request.GET["period"] or "day" + if request.user.has_perm("admin.view_mailboxes"): + domain = Domain.objects.get(pk=dom_id) + + return _render(request, 'stats/index.html', { + "domain" : domain, + "graphs" : graph_list, + "periods" : ["day", "week", "month", "year","Custom"], + "period" : period, + "img_rootdir" : parameters.get("stats", "IMG_ROOTDIR")}) diff --git a/extensions/webmail/main.py b/extensions/webmail/main.py index 3cad08f5b..c98835d9c 100644 --- a/extensions/webmail/main.py +++ b/extensions/webmail/main.py @@ -1,20 +1,8 @@ # -*- coding: utf-8 -*- -import time -import sys -from django.http import HttpResponse, Http404 -from django.template import Template, Context -from django.template.loader import render_to_string -from django.utils import simplejson from django.utils.translation import ugettext as _ 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, _render_error, getctx -from imap_listing import * -from forms import * -from templatetags.webextras import * -from lib.email_listing import parse_search_parameters +from mailng.lib import events, parameters def init(): events.register("UserMenuDisplay", menu) @@ -51,298 +39,16 @@ def urls(): include('mailng.extensions.webmail.urls')) def menu(**kwargs): + import views + if kwargs["target"] != "user_menu_box": return [] return [ {"name" : "webmail", "label" : _("Webmail"), - "url" : reverse(index), + "url" : reverse(views.index), "img" : "/static/pics/webmail.png"} ] -def __get_current_url(request): - res = "%s?page=%s" % (request.session["folder"], request.session["page"]) - for p in ["criteria", "pattern", "order"]: - if p in request.session.keys(): - res += "&%s=%s" % (p, request.session[p]) - return res - def userlogin(**kwargs): kwargs["request"].session["password"] = kwargs["password"] - -@login_required -def folder(request, name, updatenav=True): - if not name: - name = "INBOX" - order = request.GET.has_key("order") and request.GET["order"] or "-date" - if updatenav: - pageid = request.GET.has_key("page") and int(request.GET["page"]) or 1 - if not "navparams" in request.session.keys(): - request.session["navparams"] = {} - request.session["folder"] = name - request.session["page"] = pageid - if order: - request.session["navparams"]["order"] = order - parse_search_parameters(request) - else: - # Internal usage - order = request.session["navparams"]["order"] - - optparams = {} - if request.session.has_key("pattern"): - optparams["pattern"] = request.session["pattern"] - optparams["criteria"] = request.session["criteria"] - else: - optparams["reset"] = True - lst = ImapListing(request.user.username, request.session["password"], - baseurl=name, folder=name, order=order, **optparams) - - page = lst.paginator.getpage(request.session["page"]) - if page: - content = lst.fetch(request, page.id_start, page.id_stop) - navbar = lst.render_navbar(page) - else: - content = "Empty folder" - navbar = "" - folders = render_to_string("webmail/folders.html", { - "folders" : lst.getfolders() - }) - ctx = getctx("ok", folders=folders, listing=content, navbar=navbar, - menu=listing_menu("", name, request.user.get_all_permissions())) - return HttpResponse(simplejson.dumps(ctx), mimetype="application/json") - -@login_required -def index(request): - try: - navp = request.session.has_key("navparams") \ - and request.session["navparams"] or {} - lst = ImapListing(request.user.username, request.session["password"], - baseurl="INBOX", navparams=navp, folder="INBOX", - empty=True) - except Exception, exp: - return _render_error(request, {"error" : exp}) - return lst.render(request) - -def fetchmail(request, folder, mail_id, all=False): - res = IMAPconnector(request).fetch(start=mail_id, folder=folder, all=all) - if len(res): - return res[0] - return None - -@login_required -def viewmail(request, folder, mail_id=None): - from templatetags.webextras import viewm_menu - - content = Template(""" - -""").render(Context({"url" : reverse(getmailcontent, args=[folder, mail_id])})) - menu = viewm_menu("", __get_current_url(request), folder, mail_id, - request.user.get_all_permissions()) - ctx = getctx("ok", menu=menu, listing=content) - return HttpResponse(simplejson.dumps(ctx), mimetype="application/json") - -@login_required -def getmailcontent(request, folder, mail_id): - msg = fetchmail(request, folder, mail_id, True) - if "class" in msg.keys() and msg["class"] == "unseen": - IMAPconnector(request).msg_read(folder, mail_id) - email = ImapEmail(msg, mode="html", links="1") - try: - pageid = request.session["page"] - except KeyError: - pageid = "1" - return _render(request, "common/viewmail.html", { - "headers" : email.render_headers(folder=folder, mail_id=mail_id), - "folder" : folder, "imapid" : mail_id, "mailbody" : email.body, - "pre" : email.pre - }) - -@login_required -def getattachment(request, folder, mail_id): - msg = fetchmail(request, folder, mail_id, True) - for part in msg.walk(): - fname = part.get_filename() - if fname is None: - continue - decoded = decode_header(fname) - if decoded[0][1] is None: - fname = unicode(decoded[0][0]) - else: - fname = unicode(decoded[0][0], decoded[0][1]) - if fname == request.GET["fname"]: - resp = HttpResponse(part.get_payload(decode=1)) - for hdr in ["Content-Disposition", "Content-Type"]: - resp[hdr] = re.sub("\s", "", part[hdr]) - resp["Content-Length"] = len(resp.content) - return resp - raise Http404 - -@login_required -def move(request): - for arg in ["msgset", "to"]: - if not request.GET.has_key(arg): - return - mbc = IMAPconnector(request) - mbc.move(request.GET["msgset"], request.session["folder"], request.GET["to"]) - return folder(request, request.session["folder"], False) - -@login_required -def delete(request, fdname, mail_id): - mbc = IMAPconnector(request) - mbc.move(mail_id, fdname, "Trash") - return folder(request, fdname, False) - -@login_required -def mark(request, name): - if not request.GET.has_key("status") or not request.GET.has_key("ids"): - return - mbc = IMAPconnector(request) - try: - getattr(mbc, "msg_%s" % request.GET["status"])(name, request.GET["ids"]) - except AttributeError: - pass - return folder(request, name, False) - -@login_required -def empty(request, name): - if name == "Trash": - mbc = IMAPconnector(request) - mbc.empty(name) - return folder(request, name, False) - -@login_required -def compact(request, name): - mbc = IMAPconnector(request) - mbc.compact(name) - return folder(request, name, False) - -def render_compose(request, form, posturl, bodyheader=None, body=None): - menu = compose_menu("", __get_current_url(request), - request.user.get_all_permissions()) - content = render_to_string("webmail/compose.html", { - "form" : form, "bodyheader" : bodyheader, "body" : body, - "posturl" : posturl - }) - ctx = getctx("ok", level=2, menu=menu, listing=content) - return HttpResponse(simplejson.dumps(ctx), mimetype="application/json") - -def send_mail(request, withctx=False, origmsg=None): - form = ComposeMailForm(request.POST) - if form.is_valid(): - from email.mime.text import MIMEText - from email.utils import make_msgid, formatdate - import smtplib - - msg = MIMEText(request.POST["id_body"].encode("utf-8"), - _charset="utf-8") - msg["Subject"] = request.POST["subject"] - msg["From"] = request.POST["from_"] - msg["To"] = request.POST["to"] - msg["Message-ID"] = make_msgid() - msg["User-Agent"] = "MailNG" - msg["Date"] = formatdate(time.time(), True) - if origmsg and origmsg.has_key("Message-ID"): - msg["References"] = msg["In-Reply-To"] = origmsg["Message-ID"] - rcpts = msg['To'].split(',') - if "cc" in request.POST.keys(): - msg["Cc"] = request.POST["cc"] - rcpts += msg["Cc"].split(",") - try: - s = smtplib.SMTP(parameters.get("webmail", "SMTP_SERVER")) - if parameters.get("webmail", "SMTP_SECURED") == "yes": - s.starttls() - except (smtplib.SMTPException, ssl.SSLError), error: - print error - # Prévoir la remontée de cette erreur au niveau du client!! - - if parameters.get("webmail", "SMTP_AUTHENTICATION") == "yes": - s.login(request.user.username, request.session["password"]) - s.sendmail(msg['From'], rcpts, msg.as_string()) - s.quit() - IMAPconnector(request).push_mail("Sent", msg) - ctx = getctx("ok", url=__get_current_url(request)) - else: - ctx = getctx("ko", level=2, listing=render_to_string("webmail/compose.html", - {"form" : form})) - if not withctx: - return HttpResponse(simplejson.dumps(ctx), mimetype="application/json") - return ctx, HttpResponse(simplejson.dumps(ctx), mimetype="application/json") - -@login_required -def compose(request): - if request.method == "POST": - return send_mail(request) - - form = ComposeMailForm() - form.fields["from_"].initial = request.user.username - return render_compose(request, form, reverse(compose)) - -@login_required -def reply(request, folder, mail_id): - msg = fetchmail(request, folder, mail_id, True) - if request.method == "POST": - ctx, r = send_mail(request, True, origmsg=msg) - if ctx["status"] == "ok": - IMAPconnector(request).msg_answered(folder, mail_id) - return r - email = ImapEmail(msg, True) - lines = email.body.split('\n') - body = "" - for l in lines: - if body != "": - body += "\n" - body += ">%s" % l - form = ComposeMailForm() - form.fields["from_"].initial = request.user.username - if not "Reply-To" in msg.keys(): - form.fields["to"].initial = email.From - else: - form.fields["to"].initial = email.Reply_To - if request.GET.has_key("all"): - form.fields["cc"].initial = "" - toparse = msg["To"].split(",") - if "Cc" in msg.keys(): - toparse += msg["Cc"].split(",") - for addr in toparse: - tmp = EmailAddress(addr) - if tmp.address and tmp.address == request.user.username: - continue - if form.fields["cc"].initial != "": - form.fields["cc"].initial += ", " - form.fields["cc"].initial += tmp.fulladdress - m = re.match("re\s*:\s*.+", email.Subject.lower()) - if m: - form.fields["subject"].initial = email.Subject - else: - form.fields["subject"].initial = "Re: %s" % email.Subject - textheader = "%s %s" % (email.From, _("wrote:")) - return render_compose(request, form, reverse(reply, args=[folder, mail_id]), - textheader, body) - -@login_required -def forward(request, folder, mail_id): - if request.method == "POST": - ctx, response = send_mail(request, True) - if ctx["status"] == "ok": - IMAPconnector(request).msgforwarded(folder, mail_id) - return response - - msg = fetchmail(request, folder, mail_id, True) - email = ImapEmail(msg, True) - textheader = "----- %s -----" % _("Original message") - textheader += "\n%s: %s" % (_("Subject"), email.Subject) - textheader += "\n%s: %s" % (_("Date"), msg["Date"]) - for hdr in ["From", "To", "Reply-To"]: - try: - key = re.sub("-", "_", hdr) - value = getattr(email, key) - textheader += "\n%s: %s" % (_(hdr), value) - except: - pass - textheader += "\n" - - form = ComposeMailForm() - form.fields["from_"].initial = request.user.username - form.fields["subject"].initial = "Fwd: %s" % email.Subject - return render_compose(request, form, reverse(forward, args=[folder, mail_id]), - textheader, email.body) diff --git a/extensions/webmail/templatetags/webextras.py b/extensions/webmail/templatetags/webextras.py index cf8eb8b99..3d54acb4b 100644 --- a/extensions/webmail/templatetags/webextras.py +++ b/extensions/webmail/templatetags/webextras.py @@ -28,7 +28,7 @@ def viewm_menu(selection, backurl, folder, mail_id, perms): "label" : _("Forward")}, {"name" : "delete", "img" : "/static/pics/remove.png", - "url" : reverse(webmail.main.delete, args=[folder, mail_id]), + "url" : reverse(webmail.views.delete, args=[folder, mail_id]), "label" : _("Delete")}, ] @@ -56,7 +56,7 @@ def compose_menu(selection, backurl, perms): def listing_menu(selection, folder, perms): entries = [ {"name" : "compose", - "url" : reverse(webmail.main.compose), + "url" : reverse(webmail.views.compose), "img" : "/static/pics/edit.png", "label" : _("New message")}, {"name" : "mark", @@ -66,10 +66,10 @@ def listing_menu(selection, folder, perms): "menu" : [ {"name" : "mark-read", "label" : _("As read"), - "url" : reverse(webmail.main.mark, args=[folder]) + "?status=read"}, + "url" : reverse(webmail.views.mark, args=[folder]) + "?status=read"}, {"name" : "mark-unread", "label" : _("As unread"), - "url" : reverse(webmail.main.mark, args=[folder]) + "?status=unread"} + "url" : reverse(webmail.views.mark, args=[folder]) + "?status=unread"} ] }, {"name" : "actions", @@ -86,7 +86,7 @@ def listing_menu(selection, folder, perms): "label" : _("Empty folder"), "img" : "/static/pics/clear.png", "url" : folder == "Trash" \ - and reverse(webmail.main.empty, args=[folder]) or ""} + and reverse(webmail.views.empty, args=[folder]) or ""} ] } ] diff --git a/extensions/webmail/urls.py b/extensions/webmail/urls.py index 88d9a99a6..ae0fce429 100644 --- a/extensions/webmail/urls.py +++ b/extensions/webmail/urls.py @@ -1,6 +1,6 @@ from django.conf.urls.defaults import * -urlpatterns = patterns('mailng.extensions.webmail.main', +urlpatterns = patterns('mailng.extensions.webmail.views', (r'^$', "index"), (r'^compose/$', "compose"), (r'^move/$', "move"), diff --git a/extensions/webmail/views.py b/extensions/webmail/views.py new file mode 100644 index 000000000..e09c3fbce --- /dev/null +++ b/extensions/webmail/views.py @@ -0,0 +1,300 @@ +# -*- coding: utf-8 -*- +import time +import sys +from django.http import HttpResponse, Http404 +from django.template import Template, Context +from django.template.loader import render_to_string +from django.utils import simplejson +from django.utils.translation import ugettext as _ +from django.core.urlresolvers import reverse +from django.contrib.auth.decorators import login_required +from mailng.admin.models import Mailbox +from mailng.lib import parameters, _render, _render_error, getctx +from imap_listing import * +from forms import * +from templatetags.webextras import * +from lib.email_listing import parse_search_parameters + +def __get_current_url(request): + res = "%s?page=%s" % (request.session["folder"], request.session["page"]) + for p in ["criteria", "pattern", "order"]: + if p in request.session.keys(): + res += "&%s=%s" % (p, request.session[p]) + return res + +@login_required +def folder(request, name, updatenav=True): + if not name: + name = "INBOX" + order = request.GET.has_key("order") and request.GET["order"] or "-date" + if updatenav: + pageid = request.GET.has_key("page") and int(request.GET["page"]) or 1 + if not "navparams" in request.session.keys(): + request.session["navparams"] = {} + request.session["folder"] = name + request.session["page"] = pageid + if order: + request.session["navparams"]["order"] = order + parse_search_parameters(request) + else: + # Internal usage + order = request.session["navparams"]["order"] + + optparams = {} + if request.session.has_key("pattern"): + optparams["pattern"] = request.session["pattern"] + optparams["criteria"] = request.session["criteria"] + else: + optparams["reset"] = True + lst = ImapListing(request.user.username, request.session["password"], + baseurl=name, folder=name, order=order, **optparams) + + page = lst.paginator.getpage(request.session["page"]) + if page: + content = lst.fetch(request, page.id_start, page.id_stop) + navbar = lst.render_navbar(page) + else: + content = "Empty folder" + navbar = "" + folders = render_to_string("webmail/folders.html", { + "folders" : lst.getfolders() + }) + ctx = getctx("ok", folders=folders, listing=content, navbar=navbar, + menu=listing_menu("", name, request.user.get_all_permissions())) + return HttpResponse(simplejson.dumps(ctx), mimetype="application/json") + +@login_required +def index(request): + try: + navp = request.session.has_key("navparams") \ + and request.session["navparams"] or {} + lst = ImapListing(request.user.username, request.session["password"], + baseurl="INBOX", navparams=navp, folder="INBOX", + empty=True) + except Exception, exp: + return _render_error(request, {"error" : exp}) + return lst.render(request) + +def fetchmail(request, folder, mail_id, all=False): + res = IMAPconnector(request).fetch(start=mail_id, folder=folder, all=all) + if len(res): + return res[0] + return None + +@login_required +def viewmail(request, folder, mail_id=None): + from templatetags.webextras import viewm_menu + + content = Template(""" + +""").render(Context({"url" : reverse(getmailcontent, args=[folder, mail_id])})) + menu = viewm_menu("", __get_current_url(request), folder, mail_id, + request.user.get_all_permissions()) + ctx = getctx("ok", menu=menu, listing=content) + return HttpResponse(simplejson.dumps(ctx), mimetype="application/json") + +@login_required +def getmailcontent(request, folder, mail_id): + msg = fetchmail(request, folder, mail_id, True) + if "class" in msg.keys() and msg["class"] == "unseen": + IMAPconnector(request).msg_read(folder, mail_id) + email = ImapEmail(msg, mode="html", links="1") + try: + pageid = request.session["page"] + except KeyError: + pageid = "1" + return _render(request, "common/viewmail.html", { + "headers" : email.render_headers(folder=folder, mail_id=mail_id), + "folder" : folder, "imapid" : mail_id, "mailbody" : email.body, + "pre" : email.pre + }) + +@login_required +def getattachment(request, folder, mail_id): + msg = fetchmail(request, folder, mail_id, True) + for part in msg.walk(): + fname = part.get_filename() + if fname is None: + continue + decoded = decode_header(fname) + if decoded[0][1] is None: + fname = unicode(decoded[0][0]) + else: + fname = unicode(decoded[0][0], decoded[0][1]) + if fname == request.GET["fname"]: + resp = HttpResponse(part.get_payload(decode=1)) + for hdr in ["Content-Disposition", "Content-Type"]: + resp[hdr] = re.sub("\s", "", part[hdr]) + resp["Content-Length"] = len(resp.content) + return resp + raise Http404 + +@login_required +def move(request): + for arg in ["msgset", "to"]: + if not request.GET.has_key(arg): + return + mbc = IMAPconnector(request) + mbc.move(request.GET["msgset"], request.session["folder"], request.GET["to"]) + return folder(request, request.session["folder"], False) + +@login_required +def delete(request, fdname, mail_id): + mbc = IMAPconnector(request) + mbc.move(mail_id, fdname, "Trash") + return folder(request, fdname, False) + +@login_required +def mark(request, name): + if not request.GET.has_key("status") or not request.GET.has_key("ids"): + return + mbc = IMAPconnector(request) + try: + getattr(mbc, "msg_%s" % request.GET["status"])(name, request.GET["ids"]) + except AttributeError: + pass + return folder(request, name, False) + +@login_required +def empty(request, name): + if name == "Trash": + mbc = IMAPconnector(request) + mbc.empty(name) + return folder(request, name, False) + +@login_required +def compact(request, name): + mbc = IMAPconnector(request) + mbc.compact(name) + return folder(request, name, False) + +def render_compose(request, form, posturl, bodyheader=None, body=None): + menu = compose_menu("", __get_current_url(request), + request.user.get_all_permissions()) + content = render_to_string("webmail/compose.html", { + "form" : form, "bodyheader" : bodyheader, "body" : body, + "posturl" : posturl + }) + ctx = getctx("ok", level=2, menu=menu, listing=content) + return HttpResponse(simplejson.dumps(ctx), mimetype="application/json") + +def send_mail(request, withctx=False, origmsg=None): + form = ComposeMailForm(request.POST) + if form.is_valid(): + from email.mime.text import MIMEText + from email.utils import make_msgid, formatdate + import smtplib + + msg = MIMEText(request.POST["id_body"].encode("utf-8"), + _charset="utf-8") + msg["Subject"] = request.POST["subject"] + msg["From"] = request.POST["from_"] + msg["To"] = request.POST["to"] + msg["Message-ID"] = make_msgid() + msg["User-Agent"] = "MailNG" + msg["Date"] = formatdate(time.time(), True) + if origmsg and origmsg.has_key("Message-ID"): + msg["References"] = msg["In-Reply-To"] = origmsg["Message-ID"] + rcpts = msg['To'].split(',') + if "cc" in request.POST.keys(): + msg["Cc"] = request.POST["cc"] + rcpts += msg["Cc"].split(",") + try: + s = smtplib.SMTP(parameters.get("webmail", "SMTP_SERVER")) + if parameters.get("webmail", "SMTP_SECURED") == "yes": + s.starttls() + except (smtplib.SMTPException, ssl.SSLError), error: + print error + # Prévoir la remontée de cette erreur au niveau du client!! + + if parameters.get("webmail", "SMTP_AUTHENTICATION") == "yes": + s.login(request.user.username, request.session["password"]) + s.sendmail(msg['From'], rcpts, msg.as_string()) + s.quit() + IMAPconnector(request).push_mail("Sent", msg) + ctx = getctx("ok", url=__get_current_url(request)) + else: + ctx = getctx("ko", level=2, listing=render_to_string("webmail/compose.html", + {"form" : form})) + if not withctx: + return HttpResponse(simplejson.dumps(ctx), mimetype="application/json") + return ctx, HttpResponse(simplejson.dumps(ctx), mimetype="application/json") + +@login_required +def compose(request): + if request.method == "POST": + return send_mail(request) + + form = ComposeMailForm() + form.fields["from_"].initial = request.user.username + return render_compose(request, form, reverse(compose)) + +@login_required +def reply(request, folder, mail_id): + msg = fetchmail(request, folder, mail_id, True) + if request.method == "POST": + ctx, r = send_mail(request, True, origmsg=msg) + if ctx["status"] == "ok": + IMAPconnector(request).msg_answered(folder, mail_id) + return r + email = ImapEmail(msg, True) + lines = email.body.split('\n') + body = "" + for l in lines: + if body != "": + body += "\n" + body += ">%s" % l + form = ComposeMailForm() + form.fields["from_"].initial = request.user.username + if not "Reply-To" in msg.keys(): + form.fields["to"].initial = email.From + else: + form.fields["to"].initial = email.Reply_To + if request.GET.has_key("all"): + form.fields["cc"].initial = "" + toparse = msg["To"].split(",") + if "Cc" in msg.keys(): + toparse += msg["Cc"].split(",") + for addr in toparse: + tmp = EmailAddress(addr) + if tmp.address and tmp.address == request.user.username: + continue + if form.fields["cc"].initial != "": + form.fields["cc"].initial += ", " + form.fields["cc"].initial += tmp.fulladdress + m = re.match("re\s*:\s*.+", email.Subject.lower()) + if m: + form.fields["subject"].initial = email.Subject + else: + form.fields["subject"].initial = "Re: %s" % email.Subject + textheader = "%s %s" % (email.From, _("wrote:")) + return render_compose(request, form, reverse(reply, args=[folder, mail_id]), + textheader, body) + +@login_required +def forward(request, folder, mail_id): + if request.method == "POST": + ctx, response = send_mail(request, True) + if ctx["status"] == "ok": + IMAPconnector(request).msgforwarded(folder, mail_id) + return response + + msg = fetchmail(request, folder, mail_id, True) + email = ImapEmail(msg, True) + textheader = "----- %s -----" % _("Original message") + textheader += "\n%s: %s" % (_("Subject"), email.Subject) + textheader += "\n%s: %s" % (_("Date"), msg["Date"]) + for hdr in ["From", "To", "Reply-To"]: + try: + key = re.sub("-", "_", hdr) + value = getattr(email, key) + textheader += "\n%s: %s" % (_(hdr), value) + except: + pass + textheader += "\n" + + form = ComposeMailForm() + form.fields["from_"].initial = request.user.username + form.fields["subject"].initial = "Fwd: %s" % email.Subject + return render_compose(request, form, reverse(forward, args=[folder, mail_id]), + textheader, email.body)