mirror of
https://github.com/jwinterm/modoboa.git
synced 2026-10-18 05:51:26 +02:00
Ticket #41
Some code refactoring, extensions look more like Django applications now.
This commit is contained in:
@@ -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("""
|
||||
<iframe width="100%" frameBorder="0" src="{{ url }}" id="mailcontent"></iframe>
|
||||
""").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)
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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")},
|
||||
|
||||
@@ -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<mail_id>[\w\-\+]+)/$', 'getmailcontent'),
|
||||
|
||||
@@ -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("""
|
||||
<iframe width="100%" frameBorder="0" src="{{ url }}" id="mailcontent"></iframe>
|
||||
""").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)
|
||||
@@ -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
|
||||
})
|
||||
|
||||
@@ -26,7 +26,7 @@ window.addEvent("domready", function() {
|
||||
{% block content %}
|
||||
<div class="title"><h1>{% trans "Auto-reply message" %}</h1></div>
|
||||
|
||||
<form action="{% url extensions.postfix_autoreply.main.autoreply %}"
|
||||
<form action="{% url extensions.postfix_autoreply.views.autoreply %}"
|
||||
method="POST" id="armform" name="armform" class="simple">
|
||||
{% include "common/genericform.html" %}
|
||||
<div class="spacer"></div>
|
||||
|
||||
@@ -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'),
|
||||
)
|
||||
|
||||
@@ -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
|
||||
})
|
||||
+1
-147
@@ -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")})
|
||||
|
||||
@@ -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<dom_id>\d+)/$', 'index', name='domindex'),
|
||||
|
||||
@@ -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")})
|
||||
+4
-298
@@ -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("""
|
||||
<iframe width="100%" frameBorder="0" src="{{ url }}" id="mailcontent"></iframe>
|
||||
""").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)
|
||||
|
||||
@@ -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 ""}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
@@ -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"),
|
||||
|
||||
@@ -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("""
|
||||
<iframe width="100%" frameBorder="0" src="{{ url }}" id="mailcontent"></iframe>
|
||||
""").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)
|
||||
Reference in New Issue
Block a user