mirror of
https://github.com/jwinterm/modoboa.git
synced 2026-10-18 05:51:26 +02:00
Extension structure has been simplified. All extensions have been ported to the new version.
see #197
This commit is contained in:
+10
-12
@@ -10,8 +10,9 @@ from modoboa.lib import parameters, events
|
||||
from modoboa.lib.exceptions import PermDeniedException
|
||||
from modoboa.lib.sysutils import exec_cmd, exec_as_vuser
|
||||
from modoboa.lib.emailutils import split_mailbox
|
||||
from modoboa.extensions import get_ext_module
|
||||
from exceptions import *
|
||||
import os
|
||||
import os, sys
|
||||
import pwd
|
||||
import re
|
||||
import crypt, hashlib, string, base64
|
||||
@@ -653,22 +654,19 @@ class Extension(models.Model):
|
||||
help_text=ugettext_noop("Check to enable this extension")
|
||||
)
|
||||
|
||||
def __getmodule(self):
|
||||
extname = "modoboa.extensions.%s" % self.name
|
||||
return __import__(extname, globals(), locals(), ['main'])
|
||||
|
||||
def init(self):
|
||||
module = self.__getmodule()
|
||||
if hasattr(module.main, "init"):
|
||||
module.main.init()
|
||||
module = get_ext_module(self.name)
|
||||
if hasattr(module, "init"):
|
||||
module.init()
|
||||
|
||||
def load(self):
|
||||
module = self.__getmodule()
|
||||
if hasattr(module.main, "load"):
|
||||
module.main.load()
|
||||
module = get_ext_module(self.name)
|
||||
if hasattr(module, "load"):
|
||||
module.load()
|
||||
|
||||
def unload(self):
|
||||
self.__getmodule().main.destroy()
|
||||
module = get_ext_module(self.name)
|
||||
module.destroy()
|
||||
|
||||
def on(self):
|
||||
self.load()
|
||||
|
||||
+18
-21
@@ -1,14 +1,20 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import os
|
||||
# coding: utf-8
|
||||
import os, sys
|
||||
import re
|
||||
from django.conf import settings
|
||||
from django.conf.urls.defaults import include
|
||||
|
||||
def isinstalled(ext):
|
||||
return "modoboa.extensions.%s" % ext in settings.INSTALLED_APPS
|
||||
|
||||
def get_ext_module(extname):
|
||||
modname = "modoboa.extensions.%s" % extname
|
||||
if not sys.modules.has_key(modname):
|
||||
__import__(modname)
|
||||
return sys.modules[modname]
|
||||
|
||||
def get_extension_infos(name):
|
||||
ext = __import__(name, globals(), locals(), ["main"])
|
||||
return ext.main.infos()
|
||||
return get_ext_module(name).infos()
|
||||
|
||||
def loadextensions(prefix):
|
||||
# To avoid a circular import...
|
||||
@@ -21,17 +27,17 @@ def loadextensions(prefix):
|
||||
continue
|
||||
if not isinstalled(f):
|
||||
continue
|
||||
module = __import__(f, globals(), locals(), ['main'])
|
||||
try:
|
||||
ext = Extension.objects.get(name=f)
|
||||
if ext.enabled:
|
||||
ext.load()
|
||||
except Extension.DoesNotExist:
|
||||
pass
|
||||
u = module.main.urls(prefix)
|
||||
if u == ():
|
||||
continue
|
||||
result += [u]
|
||||
module = get_ext_module(f)
|
||||
baseurl = module.baseurl if hasattr(module, "baseurl") \
|
||||
else f
|
||||
result += [(r'%s%s/' % (prefix, baseurl),
|
||||
include("modoboa.extensions.%s.urls" % f))]
|
||||
return result
|
||||
|
||||
def list_extensions():
|
||||
@@ -43,14 +49,14 @@ def list_extensions():
|
||||
if not isinstalled(d):
|
||||
continue
|
||||
isvalid = True
|
||||
for f in ['urls.py', 'main.py', '__init__.py', 'views.py']:
|
||||
for f in ['urls.py', '__init__.py', 'views.py']:
|
||||
if not os.path.exists("%s/%s/%s" % (basedir, d, f)):
|
||||
isvalid = False
|
||||
break
|
||||
if isvalid:
|
||||
module = __import__(d, globals(), locals(), ['main'])
|
||||
module = __import__(d, globals(), locals())
|
||||
try:
|
||||
infos = module.main.infos()
|
||||
infos = module.infos()
|
||||
infos["id"] = d
|
||||
if os.path.isdir("%s/%s/templates" % (basedir, d)):
|
||||
infos["templates"] = True
|
||||
@@ -60,12 +66,3 @@ def list_extensions():
|
||||
except AttributeError:
|
||||
pass
|
||||
return result
|
||||
|
||||
def loadmenus():
|
||||
result = []
|
||||
for name, mod in extensions.iteritems():
|
||||
u = mod.main.urls()
|
||||
if u == ():
|
||||
continue
|
||||
result += (u,)
|
||||
return result
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
# coding: utf-8
|
||||
"""
|
||||
Amavis quarantine manager (SQL based)
|
||||
|
||||
|
||||
"""
|
||||
from django.utils.translation import ugettext_noop as _, ugettext
|
||||
from django.core.urlresolvers import reverse
|
||||
from modoboa.lib import events, parameters
|
||||
|
||||
baseurl = "quarantine"
|
||||
|
||||
def infos():
|
||||
return {
|
||||
"name" : "Amavis quarantine",
|
||||
"version" : "1.0",
|
||||
"description" : ugettext("Simple amavis quarantine management tool"),
|
||||
"url" : "quarantine"
|
||||
}
|
||||
|
||||
def load():
|
||||
parameters.register_admin(
|
||||
"MAX_MESSAGES_AGE", type="int",
|
||||
deflt=14,
|
||||
help=_("Quarantine messages maximum age (in days) before deletion")
|
||||
)
|
||||
parameters.register_admin(
|
||||
"RELEASED_MSGS_CLEANUP", type="list_yesno", deflt="no",
|
||||
help=_("Remove messages marked as released while cleaning up the database")
|
||||
)
|
||||
parameters.register_admin("AM_PDP_MODE", type="list",
|
||||
deflt="unix",
|
||||
values=[("inet", "inet"), ("unix", "unix")],
|
||||
help=_("Mode used to access the PDP server"))
|
||||
parameters.register_admin("AM_PDP_HOST", type="string",
|
||||
deflt="localhost",
|
||||
help=_("PDP server address (if inet mode)"))
|
||||
parameters.register_admin("AM_PDP_PORT", type="int",
|
||||
deflt=9998,
|
||||
help=_("PDP server port (if inet mode)"))
|
||||
parameters.register_admin("AM_PDP_SOCKET", type="string",
|
||||
deflt=_("/var/amavis/amavisd.sock"),
|
||||
help=_("Path to the PDP server socket (if unix mode)"))
|
||||
|
||||
parameters.register_user(
|
||||
"MESSAGES_PER_PAGE", type="int", deflt=40,
|
||||
label="Number of displayed emails per page",
|
||||
help=_("Sets the maximum number of messages displayed in a page")
|
||||
)
|
||||
|
||||
def destroy():
|
||||
events.unregister("UserMenuDisplay", menu)
|
||||
parameters.unregister_app("amavis_quarantine")
|
||||
|
||||
@events.observe("UserMenuDisplay")
|
||||
def menu(target, user):
|
||||
from modoboa.lib.webutils import static_url
|
||||
|
||||
if target == "top_menu":
|
||||
return [
|
||||
{"name" : "quarantine",
|
||||
"label" : _("Quarantine"),
|
||||
"url" : reverse('modoboa.extensions.amavis_quarantine.views.index'),
|
||||
"img" : static_url("pics/quarantine.png")}
|
||||
]
|
||||
return []
|
||||
|
||||
|
||||
@@ -1,69 +0,0 @@
|
||||
# coding: utf-8
|
||||
|
||||
"""
|
||||
"""
|
||||
from django.conf.urls.defaults import *
|
||||
from django.utils.translation import ugettext_noop as _, ugettext
|
||||
from django.core.urlresolvers import reverse
|
||||
from modoboa.lib import events, parameters
|
||||
from modoboa.lib.webutils import static_url
|
||||
|
||||
def infos():
|
||||
return {
|
||||
"name" : "Amavis quarantine",
|
||||
"version" : "1.0",
|
||||
"description" : ugettext("Simple amavis quarantine management tool"),
|
||||
"url" : "quarantine"
|
||||
}
|
||||
|
||||
def load():
|
||||
parameters.register_admin(
|
||||
"MAX_MESSAGES_AGE", type="int",
|
||||
deflt=14,
|
||||
help=_("Quarantine messages maximum age (in days) before deletion")
|
||||
)
|
||||
parameters.register_admin(
|
||||
"RELEASED_MSGS_CLEANUP", type="list_yesno", deflt="no",
|
||||
help=_("Remove messages marked as released while cleaning up the database")
|
||||
)
|
||||
parameters.register_admin("AM_PDP_MODE", type="list",
|
||||
deflt="unix",
|
||||
values=[("inet", "inet"), ("unix", "unix")],
|
||||
help=_("Mode used to access the PDP server"))
|
||||
parameters.register_admin("AM_PDP_HOST", type="string",
|
||||
deflt="localhost",
|
||||
help=_("PDP server address (if inet mode)"))
|
||||
parameters.register_admin("AM_PDP_PORT", type="int",
|
||||
deflt=9998,
|
||||
help=_("PDP server port (if inet mode)"))
|
||||
parameters.register_admin("AM_PDP_SOCKET", type="string",
|
||||
deflt=_("/var/amavis/amavisd.sock"),
|
||||
help=_("Path to the PDP server socket (if unix mode)"))
|
||||
|
||||
parameters.register_user(
|
||||
"MESSAGES_PER_PAGE", type="int", deflt=40,
|
||||
label="Number of displayed emails per page",
|
||||
help=_("Sets the maximum number of messages displayed in a page")
|
||||
)
|
||||
|
||||
def destroy():
|
||||
events.unregister("UserMenuDisplay", menu)
|
||||
parameters.unregister_app("amavis_quarantine")
|
||||
|
||||
def urls(prefix):
|
||||
return (r'^%squarantine/' % prefix,
|
||||
include('modoboa.extensions.amavis_quarantine.urls'))
|
||||
|
||||
@events.observe("UserMenuDisplay")
|
||||
def menu(target, menu):
|
||||
import views
|
||||
|
||||
if target == "top_menu":
|
||||
return [
|
||||
{"name" : "quarantine",
|
||||
"label" : _("Quarantine"),
|
||||
"url" : reverse(views.index),
|
||||
"img" : static_url("pics/quarantine.png")}
|
||||
]
|
||||
return []
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
new Element('input', {
|
||||
'type' : 'hidden', 'name' : "action", style: "display:none", 'value' : name
|
||||
}).inject($("listingform"), "top");
|
||||
{% url extensions.amavis_quarantine.views.process as actionurl %}
|
||||
{% url modoboa.extensions.amavis_quarantine.views.process as actionurl %}
|
||||
$("listingform").set("action", "{{ actionurl }}");
|
||||
$("listingform").set("send", {
|
||||
onSuccess : function(res) {
|
||||
|
||||
@@ -1,16 +1,13 @@
|
||||
from django.conf.urls.defaults import *
|
||||
|
||||
extpatterns = [
|
||||
(r'^$', 'index'),
|
||||
(r'^listing/$', '_listing'),
|
||||
(r'^getmailcontent/(?P<mail_id>[\w\-\+]+)/$', 'getmailcontent'),
|
||||
(r'^(?P<mail_id>[\w\-\+]+)/headers/$', 'viewheaders'),
|
||||
(r'^process/$', 'process'),
|
||||
(r'^delete/(?P<mail_id>[\w\-\+]+)/$', 'delete'),
|
||||
(r'^release/(?P<mail_id>[\w\-\+]+)/$', 'release'),
|
||||
(r'^(?P<mail_id>[\w\-\+]+)/$', 'viewmail')
|
||||
]
|
||||
|
||||
urlpatterns = patterns('modoboa.extensions.amavis_quarantine.views',
|
||||
*extpatterns
|
||||
)
|
||||
urlpatterns = patterns(
|
||||
'modoboa.extensions.amavis_quarantine.views',
|
||||
(r'^$', 'index'),
|
||||
(r'^listing/$', '_listing'),
|
||||
(r'^getmailcontent/(?P<mail_id>[\w\-\+]+)/$', 'getmailcontent'),
|
||||
(r'^(?P<mail_id>[\w\-\+]+)/headers/$', 'viewheaders'),
|
||||
(r'^process/$', 'process'),
|
||||
(r'^delete/(?P<mail_id>[\w\-\+]+)/$', 'delete'),
|
||||
(r'^release/(?P<mail_id>[\w\-\+]+)/$', 'release'),
|
||||
(r'^(?P<mail_id>[\w\-\+]+)/$', 'viewmail'),
|
||||
)
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
# coding: utf-8
|
||||
|
||||
"""
|
||||
The *limits* extension
|
||||
----------------------
|
||||
"""
|
||||
from django.contrib.auth.models import Permission, Group
|
||||
from django.db import IntegrityError
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.utils.translation import ugettext_noop as _, ugettext
|
||||
from django.core.urlresolvers import reverse
|
||||
from modoboa.lib import events, parameters
|
||||
from modoboa.lib.webutils import static_url
|
||||
from modoboa.admin.models import User
|
||||
from models import *
|
||||
import permissions
|
||||
import controls
|
||||
import views
|
||||
|
||||
baseurl = "limits"
|
||||
|
||||
def init():
|
||||
ct = ContentType.objects.get(app_label="admin", model="domain")
|
||||
grp = Group.objects.get(name="DomainAdmins")
|
||||
for pname in ["view_domains", "add_domain", "change_domain", "delete_domain"]:
|
||||
perm = Permission.objects.get(content_type=ct, codename=pname)
|
||||
grp.permissions.add(perm)
|
||||
grp.save()
|
||||
|
||||
for user in User.objects.filter(groups__name='DomainAdmins'):
|
||||
try:
|
||||
controls.create_pool(user)
|
||||
except IntegrityError:
|
||||
pass
|
||||
|
||||
def destroy():
|
||||
ct = ContentType.objects.get(app_label="admin", model="domain")
|
||||
grp = Group.objects.get(name="DomainAdmins")
|
||||
for pname in ["view_domains", "add_domain", "change_domain", "delete_domain"]:
|
||||
perm = Permission.objects.get(content_type=ct, codename=pname)
|
||||
grp.permissions.remove(perm)
|
||||
grp.save()
|
||||
|
||||
def infos():
|
||||
return {
|
||||
"name" : "Limits",
|
||||
"version" : "1.0",
|
||||
"description" : ugettext("Limits for objects creation"),
|
||||
"url" : baseurl
|
||||
}
|
||||
|
||||
@events.observe('AdminFooterDisplay')
|
||||
def display_pool_usage(user, objtype):
|
||||
if user.id == 1:
|
||||
return []
|
||||
if objtype == "domaliases":
|
||||
objtype = "domain_aliases"
|
||||
elif objtype == "mbaliases":
|
||||
objtype = "mailbox_aliases"
|
||||
try:
|
||||
l = user.limitspool.get_limit('%s_limit' % objtype)
|
||||
except LimitsPool.DoesNotExist:
|
||||
return []
|
||||
if l.maxvalue == -2:
|
||||
label = _("undefined")
|
||||
elif l.maxvalue == -1:
|
||||
label = _("unlimited")
|
||||
else:
|
||||
label = str(l.maxvalue)
|
||||
return [_("Pool usage: %s / %s") % (l.curvalue, label)]
|
||||
|
||||
@events.observe("DomainAdminActions")
|
||||
def get_da_actions(user):
|
||||
return [
|
||||
{"name" : "editpool",
|
||||
"url" : reverse(views.edit_limits_pool, args=[user.id]),
|
||||
"img" : static_url("pics/settings.png"),
|
||||
"title" : _("Edit limits allocated to this domain admin"),
|
||||
"class" : "boxed",
|
||||
"rel" : "{handler:'iframe',size:{x:330,y:280}}"},
|
||||
]
|
||||
|
||||
@@ -1,87 +0,0 @@
|
||||
# coding: utf-8
|
||||
|
||||
"""
|
||||
The *limits* extension
|
||||
----------------------
|
||||
|
||||
|
||||
"""
|
||||
from django.contrib.auth.models import Permission, User, Group
|
||||
from django.db import IntegrityError
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.utils.translation import ugettext_noop as _, ugettext
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.conf.urls.defaults import include
|
||||
from modoboa.lib import events, parameters
|
||||
from modoboa.lib.webutils import static_url
|
||||
from models import *
|
||||
import permissions
|
||||
import controls
|
||||
import views
|
||||
|
||||
baseurl = "limits"
|
||||
|
||||
def init():
|
||||
ct = ContentType.objects.get(app_label="admin", model="domain")
|
||||
grp = Group.objects.get(name="DomainAdmins")
|
||||
for pname in ["view_domains", "add_domain", "change_domain", "delete_domain"]:
|
||||
perm = Permission.objects.get(content_type=ct, codename=pname)
|
||||
grp.permissions.add(perm)
|
||||
grp.save()
|
||||
|
||||
for user in User.objects.filter(groups__name='DomainAdmins'):
|
||||
try:
|
||||
controls.create_pool(user)
|
||||
except IntegrityError:
|
||||
pass
|
||||
|
||||
def destroy():
|
||||
ct = ContentType.objects.get(app_label="admin", model="domain")
|
||||
grp = Group.objects.get(name="DomainAdmins")
|
||||
for pname in ["view_domains", "add_domain", "change_domain", "delete_domain"]:
|
||||
perm = Permission.objects.get(content_type=ct, codename=pname)
|
||||
grp.permissions.remove(perm)
|
||||
grp.save()
|
||||
|
||||
def infos():
|
||||
return {
|
||||
"name" : "Limits",
|
||||
"version" : "1.0",
|
||||
"description" : ugettext("Limits for objects creation"),
|
||||
"url" : baseurl
|
||||
}
|
||||
|
||||
def urls(prefix):
|
||||
return (r'^%s%s/' % (prefix, baseurl),
|
||||
include('modoboa.extensions.limits.urls'))
|
||||
|
||||
@events.observe('AdminFooterDisplay')
|
||||
def display_pool_usage(user, objtype):
|
||||
if user.id == 1:
|
||||
return []
|
||||
if objtype == "domaliases":
|
||||
objtype = "domain_aliases"
|
||||
elif objtype == "mbaliases":
|
||||
objtype = "mailbox_aliases"
|
||||
try:
|
||||
l = user.limitspool.get_limit('%s_limit' % objtype)
|
||||
except LimitsPool.DoesNotExist:
|
||||
return []
|
||||
if l.maxvalue == -2:
|
||||
label = _("undefined")
|
||||
elif l.maxvalue == -1:
|
||||
label = _("unlimited")
|
||||
else:
|
||||
label = str(l.maxvalue)
|
||||
return [_("Pool usage: %s / %s") % (l.curvalue, label)]
|
||||
|
||||
@events.observe("DomainAdminActions")
|
||||
def get_da_actions(user):
|
||||
return [
|
||||
{"name" : "editpool",
|
||||
"url" : reverse(views.edit_limits_pool, args=[user.id]),
|
||||
"img" : static_url("pics/settings.png"),
|
||||
"title" : _("Edit limits allocated to this domain admin"),
|
||||
"class" : "boxed",
|
||||
"rel" : "{handler:'iframe',size:{x:330,y:280}}"},
|
||||
]
|
||||
@@ -11,7 +11,7 @@ window.addEvent("domready", function() {
|
||||
{% block content %}
|
||||
<div class="title"><h1>{% trans "Limits pool for" %} {{ reseller.username }}</h1></div>
|
||||
<div class="error">{% if error %}{{ error }}{% endif %}</div>
|
||||
<form action="{% url extensions.limits.views.edit_limits_pool reseller.id %}"
|
||||
<form action="{% url modoboa.extensions.limits.views.edit_limits_pool reseller.id %}"
|
||||
method="POST" id="limits_pool_form" name="limits_pool_form">
|
||||
{% include "common/genericform.html" %}
|
||||
<div class="spacer"></div>
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
# coding: utf-8
|
||||
"""
|
||||
Postfix auto-replies plugin.
|
||||
|
||||
This module provides a way to integrate Modoboa auto-reply
|
||||
functionality into Postfix.
|
||||
|
||||
"""
|
||||
from django.conf.urls.defaults import include
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.utils.translation import ugettext_noop as _, ugettext
|
||||
from modoboa.lib import events, parameters
|
||||
from modoboa.lib.webutils import static_url
|
||||
from models import *
|
||||
|
||||
def infos():
|
||||
return {
|
||||
"name" : "Postfix autoreply",
|
||||
"version" : "1.0",
|
||||
"description" : ugettext("Auto-reply (vacation) functionality using Postfix"),
|
||||
"url" : "postfix_autoreply"
|
||||
}
|
||||
|
||||
def load():
|
||||
parameters.register_admin(
|
||||
"AUTOREPLIES_TIMEOUT",
|
||||
type="int", deflt=86400,
|
||||
help=_("Timeout in seconds between two auto-replies to the same recipient")
|
||||
)
|
||||
|
||||
def destroy():
|
||||
events.unregister("CreateDomain", onCreateDomain)
|
||||
events.unregister("DeleteDomain", onDeleteDomain)
|
||||
events.unregister("CreateMailbox", onCreateMailbox)
|
||||
events.unregister("DeleteMailbox", onDeleteMailbox)
|
||||
events.unregister("ModifyMailbox", onModifyMailbox)
|
||||
events.unregister("UserMenuDisplay", menu)
|
||||
parameters.unregister_app("postfix_autoreply")
|
||||
|
||||
@events.observe("UserMenuDisplay")
|
||||
def menu(target, user):
|
||||
import views
|
||||
|
||||
if target != "uprefs_menu":
|
||||
return []
|
||||
if not user.has_mailbox:
|
||||
return []
|
||||
return [
|
||||
{"name" : "autoreply",
|
||||
"url" : reverse(views.autoreply),
|
||||
"img" : static_url("pics/auto-reply.png"),
|
||||
"class" : "boxed",
|
||||
"rel" : "{handler:'iframe',size:{x:440,y:400}}",
|
||||
"label" : ugettext("Auto-reply message")}
|
||||
]
|
||||
|
||||
@events.observe("CreateDomain")
|
||||
def onCreateDomain(user, domain):
|
||||
transport = Transport()
|
||||
transport.domain = "autoreply.%s" % domain.name
|
||||
transport.method = "autoreply:"
|
||||
transport.save()
|
||||
|
||||
@events.observe("DeleteDomain")
|
||||
def onDeleteDomain(domain):
|
||||
trans = Transport.objects.get(domain="autoreply.%s" % domain.name)
|
||||
trans.delete()
|
||||
|
||||
@events.observe("CreateMailbox")
|
||||
def onCreateMailbox(user, mailbox):
|
||||
alias = Alias()
|
||||
alias.full_address = mailbox.full_address
|
||||
alias.autoreply_address = \
|
||||
"%s@autoreply.%s" % (mailbox.full_address, mailbox.domain.name)
|
||||
alias.save()
|
||||
|
||||
@events.observe("DeleteMailbox")
|
||||
def onDeleteMailbox(mailbox):
|
||||
try:
|
||||
alias = Alias.objects.get(full_address=mailbox.full_address)
|
||||
alias.delete()
|
||||
except Alias.DoesNotExist:
|
||||
pass
|
||||
|
||||
@events.observe("ModifyMailbox")
|
||||
def onModifyMailbox(mailbox, oldmailbox):
|
||||
if oldmailbox.full_address == mailbox.full_address:
|
||||
return
|
||||
alias = Alias.objects.get(full_address=oldmailbox.full_address)
|
||||
alias.full_address = mailbox.full_address
|
||||
alias.autoreply_address = \
|
||||
"%s@autoreply.%s" % (mailbox.full_address, mailbox.domain.name)
|
||||
alias.save()
|
||||
|
||||
@@ -1,98 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
Postfix auto-replies plugin.
|
||||
|
||||
This module provides a way to integrate Modoboa auto-reply
|
||||
functionality into Postfix.
|
||||
|
||||
"""
|
||||
from django.conf.urls.defaults import include
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.utils.translation import ugettext_noop as _, ugettext
|
||||
from modoboa.lib import events, parameters
|
||||
from modoboa.lib.webutils import static_url
|
||||
from models import *
|
||||
|
||||
def infos():
|
||||
return {
|
||||
"name" : "Postfix autoreply",
|
||||
"version" : "1.0",
|
||||
"description" : ugettext("Auto-reply (vacation) functionality using Postfix"),
|
||||
"url" : "postfix_autoreply"
|
||||
}
|
||||
|
||||
def load():
|
||||
parameters.register_admin(
|
||||
"AUTOREPLIES_TIMEOUT",
|
||||
type="int", deflt=86400,
|
||||
help=_("Timeout in seconds between two auto-replies to the same recipient")
|
||||
)
|
||||
|
||||
def destroy():
|
||||
events.unregister("CreateDomain", onCreateDomain)
|
||||
events.unregister("DeleteDomain", onDeleteDomain)
|
||||
events.unregister("CreateMailbox", onCreateMailbox)
|
||||
events.unregister("DeleteMailbox", onDeleteMailbox)
|
||||
events.unregister("ModifyMailbox", onModifyMailbox)
|
||||
events.unregister("UserMenuDisplay", menu)
|
||||
parameters.unregister_app("postfix_autoreply")
|
||||
|
||||
def urls(prefix):
|
||||
return (r'^%spostfix_autoreply/' % prefix,
|
||||
include('modoboa.extensions.postfix_autoreply.urls'))
|
||||
|
||||
@events.observe("UserMenuDisplay")
|
||||
def menu(target, user):
|
||||
import views
|
||||
|
||||
if target != "uprefs_menu":
|
||||
return []
|
||||
if not user.has_mailbox:
|
||||
return []
|
||||
return [
|
||||
{"name" : "autoreply",
|
||||
"url" : reverse(views.autoreply),
|
||||
"img" : static_url("pics/auto-reply.png"),
|
||||
"class" : "boxed",
|
||||
"rel" : "{handler:'iframe',size:{x:440,y:400}}",
|
||||
"label" : ugettext("Auto-reply message")}
|
||||
]
|
||||
|
||||
@events.observe("CreateDomain")
|
||||
def onCreateDomain(user, domain):
|
||||
transport = Transport()
|
||||
transport.domain = "autoreply.%s" % domain.name
|
||||
transport.method = "autoreply:"
|
||||
transport.save()
|
||||
|
||||
@events.observe("DeleteDomain")
|
||||
def onDeleteDomain(domain):
|
||||
trans = Transport.objects.get(domain="autoreply.%s" % domain.name)
|
||||
trans.delete()
|
||||
|
||||
@events.observe("CreateMailbox")
|
||||
def onCreateMailbox(user, mailbox):
|
||||
alias = Alias()
|
||||
alias.full_address = mailbox.full_address
|
||||
alias.autoreply_address = \
|
||||
"%s@autoreply.%s" % (mailbox.full_address, mailbox.domain.name)
|
||||
alias.save()
|
||||
|
||||
@events.observe("DeleteMailbox")
|
||||
def onDeleteMailbox(mailbox):
|
||||
try:
|
||||
alias = Alias.objects.get(full_address=mailbox.full_address)
|
||||
alias.delete()
|
||||
except Alias.DoesNotExist:
|
||||
pass
|
||||
|
||||
@events.observe("ModifyMailbox")
|
||||
def onModifyMailbox(mailbox, oldmailbox):
|
||||
if oldmailbox.full_address == mailbox.full_address:
|
||||
return
|
||||
alias = Alias.objects.get(full_address=oldmailbox.full_address)
|
||||
alias.full_address = mailbox.full_address
|
||||
alias.autoreply_address = \
|
||||
"%s@autoreply.%s" % (mailbox.full_address, mailbox.domain.name)
|
||||
alias.save()
|
||||
@@ -29,7 +29,7 @@ window.addEvent("domready", function() {
|
||||
{% block content %}
|
||||
<div class="title"><h1>{% trans "Auto-reply message" %}</h1></div>
|
||||
|
||||
<form action="{% url extensions.postfix_autoreply.views.autoreply %}"
|
||||
<form action="{% url modoboa.extensions.postfix_autoreply.views.autoreply %}"
|
||||
method="POST" id="armform" name="armform" class="simple">
|
||||
{% include "common/genericform.html" %}
|
||||
<div class="spacer"></div>
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from django.utils.translation import ugettext_noop as _, ugettext
|
||||
from django.core.urlresolvers import reverse
|
||||
from modoboa.lib import events, parameters
|
||||
from modoboa.lib.webutils import static_url
|
||||
from sievelib.managesieve import SUPPORTED_AUTH_MECHS
|
||||
|
||||
baseurl = "sfilters"
|
||||
|
||||
def load():
|
||||
parameters.register_admin("SERVER", type="string",
|
||||
deflt="127.0.0.1",
|
||||
help=_("Address of your MANAGESIEVE server"))
|
||||
parameters.register_admin("PORT", type="int", deflt="2000",
|
||||
help=_("Listening port of your MANAGESIEVE server"))
|
||||
parameters.register_admin("STARTTLS", type="list_yesno", deflt="no",
|
||||
help=_("Use the STARTTLS extension"))
|
||||
|
||||
values = [('AUTO', 'auto')]
|
||||
for m in SUPPORTED_AUTH_MECHS:
|
||||
values += [(m, m.lower())]
|
||||
parameters.register_admin("AUTHENTICATION_MECH", type="list", deflt="auto",
|
||||
values=values,
|
||||
help=_("Prefered authentication mechanism"))
|
||||
|
||||
# User parameters
|
||||
parameters.register_user("EDITOR_MODE", type="list", deflt="raw",
|
||||
label=_("Editor mode"),
|
||||
values=[("raw", "raw"), ("gui", "simplified")],
|
||||
help=_("Select the mode you want the editor to work in"))
|
||||
|
||||
def destroy():
|
||||
events.unregister("UserMenuDisplay", menu)
|
||||
parameters.unregister_app("sievefilters")
|
||||
|
||||
def infos():
|
||||
return {
|
||||
"name" : "Sieve filters",
|
||||
"version" : "1.0",
|
||||
"description" : ugettext("Plugin to easily create server-side filters"),
|
||||
"url" : "sfilters"
|
||||
}
|
||||
|
||||
@events.observe("UserMenuDisplay")
|
||||
def menu(target, user):
|
||||
import views
|
||||
|
||||
if target != "options_menu":
|
||||
return []
|
||||
if not user.has_mailbox:
|
||||
return []
|
||||
return [
|
||||
{"name" : "sievefilters",
|
||||
"label" : ugettext("Message filters"),
|
||||
"url" : reverse(views.index),
|
||||
"img" : static_url("pics/filters.png")}
|
||||
]
|
||||
|
||||
@events.observe("Userlogout")
|
||||
def userlogout(request):
|
||||
from lib import SieveClient
|
||||
|
||||
if not request.user.has_mailbox:
|
||||
return
|
||||
try:
|
||||
sc = SieveClient(user=request.user.username,
|
||||
password=request.session["password"])
|
||||
except Exception, e:
|
||||
pass
|
||||
else:
|
||||
sc.logout()
|
||||
|
||||
@@ -1,74 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from django.utils.translation import ugettext_noop as _, ugettext
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.conf.urls.defaults import include
|
||||
from modoboa.lib import events, parameters
|
||||
from modoboa.lib.webutils import static_url
|
||||
from sievelib.managesieve import SUPPORTED_AUTH_MECHS
|
||||
|
||||
def load():
|
||||
parameters.register_admin("SERVER", type="string",
|
||||
deflt="127.0.0.1",
|
||||
help=_("Address of your MANAGESIEVE server"))
|
||||
parameters.register_admin("PORT", type="int", deflt="2000",
|
||||
help=_("Listening port of your MANAGESIEVE server"))
|
||||
parameters.register_admin("STARTTLS", type="list_yesno", deflt="no",
|
||||
help=_("Use the STARTTLS extension"))
|
||||
|
||||
values = [('AUTO', 'auto')]
|
||||
for m in SUPPORTED_AUTH_MECHS:
|
||||
values += [(m, m.lower())]
|
||||
parameters.register_admin("AUTHENTICATION_MECH", type="list", deflt="auto",
|
||||
values=values,
|
||||
help=_("Prefered authentication mechanism"))
|
||||
|
||||
# User parameters
|
||||
parameters.register_user("EDITOR_MODE", type="list", deflt="raw",
|
||||
label=_("Editor mode"),
|
||||
values=[("raw", "raw"), ("gui", "simplified")],
|
||||
help=_("Select the mode you want the editor to work in"))
|
||||
|
||||
def destroy():
|
||||
events.unregister("UserMenuDisplay", menu)
|
||||
parameters.unregister_app("sievefilters")
|
||||
|
||||
def infos():
|
||||
return {
|
||||
"name" : "Sieve filters",
|
||||
"version" : "1.0",
|
||||
"description" : ugettext("Plugin to easily create server-side filters"),
|
||||
"url" : "sfilters"
|
||||
}
|
||||
|
||||
def urls(prefix):
|
||||
return (r'^%ssfilters/' % prefix,
|
||||
include('modoboa.extensions.sievefilters.urls'))
|
||||
|
||||
@events.observe("UserMenuDisplay")
|
||||
def menu(target, user):
|
||||
import views
|
||||
|
||||
if target != "options_menu":
|
||||
return []
|
||||
if not user.has_mailbox:
|
||||
return []
|
||||
return [
|
||||
{"name" : "sievefilters",
|
||||
"label" : ugettext("Message filters"),
|
||||
"url" : reverse(views.index),
|
||||
"img" : static_url("pics/filters.png")}
|
||||
]
|
||||
|
||||
@events.observe("Userlogout")
|
||||
def userlogout(request):
|
||||
from lib import SieveClient
|
||||
|
||||
if not request.user.has_mailbox:
|
||||
return
|
||||
try:
|
||||
sc = SieveClient(user=request.user.username,
|
||||
password=request.session["password"])
|
||||
except Exception, e:
|
||||
pass
|
||||
else:
|
||||
sc.logout()
|
||||
@@ -32,7 +32,7 @@ function initform() {
|
||||
});
|
||||
da = new DynamicAction(alist, {
|
||||
templates: action_templates,
|
||||
ufolders_url: "{% url extensions.sievefilters.views.get_user_folders %}"
|
||||
ufolders_url: "{% url modoboa.extensions.sievefilters.views.get_user_folders %}"
|
||||
});
|
||||
|
||||
clist.addEvent("change", dc.onTargetChange.bind(dc));
|
||||
@@ -43,13 +43,13 @@ function initform() {
|
||||
|
||||
$(document).addEvent("domready", function() {
|
||||
new Request.JSON({
|
||||
url: "{% url extensions.sievefilters.views.get_templates 'condition' %}",
|
||||
url: "{% url modoboa.extensions.sievefilters.views.get_templates 'condition' %}",
|
||||
onSuccess: function(response) {
|
||||
cond_templates = response;
|
||||
}
|
||||
}).get();
|
||||
new Request.JSON({
|
||||
url: "{% url extensions.sievefilters.views.get_templates 'action' %}",
|
||||
url: "{% url modoboa.extensions.sievefilters.views.get_templates 'action' %}",
|
||||
onSuccess: function(response) {
|
||||
action_templates = response;
|
||||
initform();
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
<td>
|
||||
<a name="togglestate"
|
||||
class={% if filter.enabled %}"green"{% else %}"red"{% endif %}
|
||||
href="{% url extensions.sievefilters.views.toggle_filter_state fs.name filter.name %}">
|
||||
href="{% url modoboa.extensions.sievefilters.views.toggle_filter_state fs.name filter.name %}">
|
||||
{{ filter.enabled|yesno }}
|
||||
</a>
|
||||
</td>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<h1>{% trans "Actions" %}</h1>
|
||||
{% fset_menu "raw" name %}
|
||||
</div>
|
||||
<form action="{% url extensions.sievefilters.views.savefs name %}"
|
||||
<form action="{% url modoboa.extensions.sievefilters.views.savefs name %}"
|
||||
method="POST" id="feditor" name="feditor">
|
||||
<textarea id="scriptcontent" name="scriptcontent">{{ scriptcontent }}</textarea>
|
||||
</form>
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
# coding: utf-8
|
||||
|
||||
"""
|
||||
Graphical statistics about emails traffic using RRDtool
|
||||
|
||||
This module provides support to retrieve statistics from postfix log :
|
||||
sent, received, bounced, rejected
|
||||
|
||||
"""
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.utils.translation import ugettext_noop as _, ugettext
|
||||
from django.conf.urls.defaults import *
|
||||
from modoboa.lib import events, parameters
|
||||
from modoboa.lib.webutils import static_url
|
||||
|
||||
def infos():
|
||||
return {
|
||||
"name" : "Statistics",
|
||||
"version" : "1.0",
|
||||
"description" : ugettext("Graphical statistics about emails traffic using RRDtool"),
|
||||
"url" : "stats"
|
||||
}
|
||||
|
||||
def load():
|
||||
parameters.register_admin("LOGFILE", type="string",
|
||||
deflt="/var/log/mail.log",
|
||||
help=_("Path to log file used to collect statistics"))
|
||||
parameters.register_admin("RRD_ROOTDIR", type="string",
|
||||
deflt="/tmp/modoboa",
|
||||
help=_("Path to directory where RRD files are stored"))
|
||||
parameters.register_admin("IMG_ROOTDIR", type="string",
|
||||
deflt="/tmp/modoboa",
|
||||
help=_("Path to directory where PNG files are stored"))
|
||||
|
||||
def destroy():
|
||||
events.unregister("AdminMenuDisplay", menu)
|
||||
|
||||
@events.observe("AdminMenuDisplay")
|
||||
def menu(target, user):
|
||||
if target == "admin_menu_box":
|
||||
return [
|
||||
{"name" : "stats",
|
||||
"label" : ugettext("Statistics"),
|
||||
"url" : reverse('fullindex'),
|
||||
"img" : static_url("pics/graph.png")}
|
||||
]
|
||||
return []
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
Graphical statistics about emails traffic using RRDtool
|
||||
|
||||
This module provides support to retrieve statistics from postfix log :
|
||||
sent, received, bounced, rejected
|
||||
|
||||
"""
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.utils.translation import ugettext_noop as _, ugettext
|
||||
from django.conf.urls.defaults import *
|
||||
from modoboa.lib import events, parameters
|
||||
from modoboa.lib.webutils import static_url
|
||||
|
||||
def infos():
|
||||
return {
|
||||
"name" : "Statistics",
|
||||
"version" : "1.0",
|
||||
"description" : ugettext("Graphical statistics about emails traffic using RRDtool"),
|
||||
"url" : "stats"
|
||||
}
|
||||
|
||||
def load():
|
||||
parameters.register_admin("LOGFILE", type="string",
|
||||
deflt="/var/log/mail.log",
|
||||
help=_("Path to log file used to collect statistics"))
|
||||
parameters.register_admin("RRD_ROOTDIR", type="string",
|
||||
deflt="/tmp/modoboa",
|
||||
help=_("Path to directory where RRD files are stored"))
|
||||
parameters.register_admin("IMG_ROOTDIR", type="string",
|
||||
deflt="/tmp/modoboa",
|
||||
help=_("Path to directory where PNG files are stored"))
|
||||
|
||||
def destroy():
|
||||
events.unregister("AdminMenuDisplay", menu)
|
||||
|
||||
def urls(prefix):
|
||||
return (r'^%sstats/' % prefix,
|
||||
include('modoboa.extensions.stats.urls'))
|
||||
|
||||
@events.observe("AdminMenuDisplay")
|
||||
def menu(target, user):
|
||||
if target == "admin_menu_box":
|
||||
return [
|
||||
{"name" : "stats",
|
||||
"label" : ugettext("Statistics"),
|
||||
"url" : reverse('fullindex'),
|
||||
"img" : static_url("pics/graph.png")}
|
||||
]
|
||||
return []
|
||||
@@ -0,0 +1,103 @@
|
||||
# coding: utf-8
|
||||
from django.utils.translation import ugettext_noop as _, ugettext
|
||||
from django.core.urlresolvers import reverse
|
||||
from modoboa.lib import events, parameters
|
||||
from modoboa.lib.webutils import static_url
|
||||
|
||||
def load():
|
||||
parameters.register_admin("IMAP_SERVER", type="string",
|
||||
deflt="127.0.0.1",
|
||||
help=_("Address of your IMAP server"))
|
||||
parameters.register_admin("IMAP_SECURED", type="list_yesno",
|
||||
deflt="no",
|
||||
help=_("Use a secured connection to access IMAP server"))
|
||||
parameters.register_admin("IMAP_PORT", type="int", deflt="143",
|
||||
help=_("Listening port of your IMAP server"))
|
||||
parameters.register_admin("SMTP_SERVER", type="string",
|
||||
deflt="127.0.0.1",
|
||||
help=_("Address of your SMTP server"))
|
||||
parameters.register_admin("SMTP_SECURED_MODE", type="list",
|
||||
values=[("none", _("None")),
|
||||
("starttls", "STARTTLS"),
|
||||
("ssl", "SSL/TLS")],
|
||||
deflt="none",
|
||||
help=_("Use a secured connection to access SMTP server"))
|
||||
parameters.register_admin("SMTP_PORT", type="int", deflt="25",
|
||||
help=_("Listening port of your SMTP server"))
|
||||
parameters.register_admin("SMTP_AUTHENTICATION", type="list_yesno",
|
||||
deflt="no",
|
||||
help=_("Server needs authentication"))
|
||||
parameters.register_admin("MAX_ATTACHMENT_SIZE", type="int", deflt=2048,
|
||||
help=_("Maximum attachment size in bytes (or KB, MB, GB if specified)"))
|
||||
|
||||
|
||||
parameters.register_user("MESSAGES_PER_PAGE", type="int", deflt=40,
|
||||
label=_("Number of displayed emails per page"),
|
||||
help=_("Sets the maximum number of messages displayed in a page"))
|
||||
parameters.register_user("REFRESH_INTERVAL", type="int", deflt=300,
|
||||
label=_("Listing refresh rate"),
|
||||
help=_("Automatic folder refresh rate (in seconds)"))
|
||||
parameters.register_user("TRASH_FOLDER", type="string", deflt="Trash",
|
||||
label=_("Trash folder"),
|
||||
help=_("Folder where deleted messages go"))
|
||||
parameters.register_user("SENT_FOLDER", type="string", deflt="Sent",
|
||||
label=_("Sent folder"),
|
||||
help=_("Folder where copies of sent messages go"))
|
||||
parameters.register_user("DRAFTS_FOLDER", type="string", deflt="Drafts",
|
||||
label=_("Drafts folder"),
|
||||
help=_("Folder where drafts go"))
|
||||
parameters.register_user("SIGNATURE", type="text", deflt="",
|
||||
label=_("Signature text"),
|
||||
help=_("User defined email signature"))
|
||||
parameters.register_user("EDITOR", type="list", deflt="plain",
|
||||
label=_("Default editor"),
|
||||
values=[("html", "html"), ("plain", "text")],
|
||||
help=_("The default editor to use when composing a message"))
|
||||
parameters.register_user("DISPLAYMODE", type="list", deflt="plain",
|
||||
label=_("Default message display mode"),
|
||||
values=[("html", "html"), ("plain", "text")],
|
||||
help=_("The default mode used when displaying a message"))
|
||||
parameters.register_user("ENABLE_LINKS", type="list_yesno", deflt="no",
|
||||
label=_("Enable HTML links display"),
|
||||
help=_("Enable/Disable HTML links display"))
|
||||
|
||||
def destroy():
|
||||
events.unregister("UserMenuDisplay", menu)
|
||||
parameters.unregister_app("webmail")
|
||||
|
||||
def infos():
|
||||
return {
|
||||
"name" : "Webmail",
|
||||
"version" : "1.0",
|
||||
"description" : ugettext("Simple IMAP webmail"),
|
||||
"url" : "webmail"
|
||||
}
|
||||
|
||||
@events.observe("UserMenuDisplay")
|
||||
def menu(target, user):
|
||||
import views
|
||||
|
||||
if target != "top_menu":
|
||||
return []
|
||||
if not user.has_mailbox:
|
||||
return []
|
||||
return [
|
||||
{"name" : "webmail",
|
||||
"label" : _("Webmail"),
|
||||
"url" : reverse(views.index),
|
||||
"img" : static_url("pics/webmail.png")}
|
||||
]
|
||||
|
||||
@events.observe("Userlogout")
|
||||
def userlogout(request):
|
||||
from lib import IMAPconnector
|
||||
|
||||
if not request.user.has_mailbox:
|
||||
return
|
||||
try:
|
||||
m = IMAPconnector(user=request.user.username,
|
||||
password=request.session["password"])
|
||||
except Exception, e:
|
||||
pass
|
||||
else:
|
||||
m.logout()
|
||||
|
||||
@@ -1,108 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from django.utils.translation import ugettext_noop as _, ugettext
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.conf.urls.defaults import include
|
||||
from modoboa.lib import events, parameters
|
||||
from modoboa.lib.webutils import static_url
|
||||
|
||||
def load():
|
||||
parameters.register_admin("IMAP_SERVER", type="string",
|
||||
deflt="127.0.0.1",
|
||||
help=_("Address of your IMAP server"))
|
||||
parameters.register_admin("IMAP_SECURED", type="list_yesno",
|
||||
deflt="no",
|
||||
help=_("Use a secured connection to access IMAP server"))
|
||||
parameters.register_admin("IMAP_PORT", type="int", deflt="143",
|
||||
help=_("Listening port of your IMAP server"))
|
||||
parameters.register_admin("SMTP_SERVER", type="string",
|
||||
deflt="127.0.0.1",
|
||||
help=_("Address of your SMTP server"))
|
||||
parameters.register_admin("SMTP_SECURED_MODE", type="list",
|
||||
values=[("none", _("None")),
|
||||
("starttls", "STARTTLS"),
|
||||
("ssl", "SSL/TLS")],
|
||||
deflt="none",
|
||||
help=_("Use a secured connection to access SMTP server"))
|
||||
parameters.register_admin("SMTP_PORT", type="int", deflt="25",
|
||||
help=_("Listening port of your SMTP server"))
|
||||
parameters.register_admin("SMTP_AUTHENTICATION", type="list_yesno",
|
||||
deflt="no",
|
||||
help=_("Server needs authentication"))
|
||||
parameters.register_admin("MAX_ATTACHMENT_SIZE", type="int", deflt=2048,
|
||||
help=_("Maximum attachment size in bytes (or KB, MB, GB if specified)"))
|
||||
|
||||
|
||||
parameters.register_user("MESSAGES_PER_PAGE", type="int", deflt=40,
|
||||
label=_("Number of displayed emails per page"),
|
||||
help=_("Sets the maximum number of messages displayed in a page"))
|
||||
parameters.register_user("REFRESH_INTERVAL", type="int", deflt=300,
|
||||
label=_("Listing refresh rate"),
|
||||
help=_("Automatic folder refresh rate (in seconds)"))
|
||||
parameters.register_user("TRASH_FOLDER", type="string", deflt="Trash",
|
||||
label=_("Trash folder"),
|
||||
help=_("Folder where deleted messages go"))
|
||||
parameters.register_user("SENT_FOLDER", type="string", deflt="Sent",
|
||||
label=_("Sent folder"),
|
||||
help=_("Folder where copies of sent messages go"))
|
||||
parameters.register_user("DRAFTS_FOLDER", type="string", deflt="Drafts",
|
||||
label=_("Drafts folder"),
|
||||
help=_("Folder where drafts go"))
|
||||
parameters.register_user("SIGNATURE", type="text", deflt="",
|
||||
label=_("Signature text"),
|
||||
help=_("User defined email signature"))
|
||||
parameters.register_user("EDITOR", type="list", deflt="plain",
|
||||
label=_("Default editor"),
|
||||
values=[("html", "html"), ("plain", "text")],
|
||||
help=_("The default editor to use when composing a message"))
|
||||
parameters.register_user("DISPLAYMODE", type="list", deflt="plain",
|
||||
label=_("Default message display mode"),
|
||||
values=[("html", "html"), ("plain", "text")],
|
||||
help=_("The default mode used when displaying a message"))
|
||||
parameters.register_user("ENABLE_LINKS", type="list_yesno", deflt="no",
|
||||
label=_("Enable HTML links display"),
|
||||
help=_("Enable/Disable HTML links display"))
|
||||
|
||||
def destroy():
|
||||
events.unregister("UserMenuDisplay", menu)
|
||||
parameters.unregister_app("webmail")
|
||||
|
||||
def infos():
|
||||
return {
|
||||
"name" : "Webmail",
|
||||
"version" : "1.0",
|
||||
"description" : ugettext("Simple IMAP webmail"),
|
||||
"url" : "webmail"
|
||||
}
|
||||
|
||||
def urls(prefix):
|
||||
return (r'^%swebmail/' % prefix,
|
||||
include('modoboa.extensions.webmail.urls'))
|
||||
|
||||
@events.observe("UserMenuDisplay")
|
||||
def menu(target, user):
|
||||
import views
|
||||
|
||||
if target != "top_menu":
|
||||
return []
|
||||
if not user.has_mailbox:
|
||||
return []
|
||||
return [
|
||||
{"name" : "webmail",
|
||||
"label" : _("Webmail"),
|
||||
"url" : reverse(views.index),
|
||||
"img" : static_url("pics/webmail.png")}
|
||||
]
|
||||
|
||||
@events.observe("Userlogout")
|
||||
def userlogout(request):
|
||||
from lib import IMAPconnector
|
||||
|
||||
if not request.user.has_mailbox:
|
||||
return
|
||||
try:
|
||||
m = IMAPconnector(user=request.user.username,
|
||||
password=request.session["password"])
|
||||
except Exception, e:
|
||||
pass
|
||||
else:
|
||||
m.logout()
|
||||
@@ -22,7 +22,7 @@ function upload_cb(fname, tmpname) {
|
||||
var ndiv = new Element("div");
|
||||
var delbtn = new Element("a")
|
||||
.set("name", "delattachment")
|
||||
.set("href", "{% url extensions.webmail.views.delattachment %}?name=" + tmpname)
|
||||
.set("href", "{% url modoboa.extensions.webmail.views.delattachment %}?name=" + tmpname)
|
||||
.set("html", "<img src='{{MEDIA_URL}}pics/remove.png' />")
|
||||
.inject(ndiv);
|
||||
var label = new Element("label").set("html", fname).inject(ndiv);
|
||||
@@ -87,7 +87,7 @@ window.addEvent("domready", function() {
|
||||
<div id="error" class="error">{{ error }}</div>
|
||||
<form enctype="multipart/form-data" method="post" name="uploadfile" id="uploadfile"
|
||||
target="upload_target"
|
||||
action="{% url extensions.webmail.views.attachments %}">
|
||||
action="{% url modoboa.extensions.webmail.views.attachments %}">
|
||||
{% include "common/genericform.html" %}
|
||||
<div class="row">
|
||||
<input type="submit" id="submit" name="submit" value="{% trans 'Attach' %}" />
|
||||
@@ -101,7 +101,7 @@ window.addEvent("domready", function() {
|
||||
<div id="attachment_list">
|
||||
{% for att in attachments %}
|
||||
<div>
|
||||
<a href="{% url extensions.webmail.views.delattachment %}?name={{ att.tmpname }}"
|
||||
<a href="{% url modoboa.extensions.webmail.views.delattachment %}?name={{ att.tmpname }}"
|
||||
name="delattachment">
|
||||
<img src="{{ MEDIA_URL }}pics/remove.png" />
|
||||
</a>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<div id="compose-container">
|
||||
<div id="mailheader">
|
||||
{% include "common/genericform.html" %}
|
||||
<div id="attachments" name="{% url extensions.webmail.views.attachments %}">
|
||||
<div id="attachments" name="{% url modoboa.extensions.webmail.views.attachments %}">
|
||||
<div>
|
||||
<img src="{{ MEDIA_URL }}pics/attachment.png" />
|
||||
{% trans "Attachments" %}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
{% load webextras %}
|
||||
{% if titlebar %}
|
||||
<div class="boxtitle">
|
||||
<a href="{% url extensions.webmail.views.newfolder %}" class="boxed"
|
||||
<a href="{% url modoboa.extensions.webmail.views.newfolder %}" class="boxed"
|
||||
rel="{handler: 'iframe', size: {x: 350, y: 400}, closeBtn: true}">
|
||||
<img src="{{MEDIA_URL}}pics/add.png"
|
||||
alt="{% trans 'Add a new folder' %}"/>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<tr>
|
||||
<th>{% trans "Attachments" %}</th>
|
||||
<td>
|
||||
{% url extensions.webmail.views.getattachment folder mail_id as test %}
|
||||
{% url modoboa.extensions.webmail.views.getattachment folder mail_id as test %}
|
||||
{% for key, fname in attachments.items %}
|
||||
<a href="{{ test }}?fname={{ fname }}&partnumber={{ key }}">{{ fname }}</a>
|
||||
{% endfor %}
|
||||
|
||||
@@ -20,8 +20,8 @@ function wm_updatelisting(resp) {
|
||||
|
||||
var fdbuttons = $$("img[class*=footer]");
|
||||
var fdmenu = new FdMenu({
|
||||
modify_url: "{% url extensions.webmail.views.editfolder %}",
|
||||
delete_url: "{% url extensions.webmail.views.delfolder %}"
|
||||
modify_url: "{% url modoboa.extensions.webmail.views.editfolder %}",
|
||||
delete_url: "{% url modoboa.extensions.webmail.views.delfolder %}"
|
||||
});
|
||||
|
||||
fdbuttons.addEvents({
|
||||
@@ -154,7 +154,7 @@ function wm_updatelisting(resp) {
|
||||
emails_table._selectedRows.each(function(item, index) {
|
||||
msgset.include(item.get("id"));
|
||||
});
|
||||
{% url extensions.webmail.views.move as moveurl %}
|
||||
{% url modoboa.extensions.webmail.views.move as moveurl %}
|
||||
simple_request("{{ moveurl }}", {msgset : msgset.join(), to : dest});
|
||||
};
|
||||
|
||||
|
||||
+9
-7
@@ -69,9 +69,10 @@ def register(event, callback):
|
||||
if not event in events:
|
||||
return 0
|
||||
if not event in callbacks.keys():
|
||||
callbacks[event] = []
|
||||
if not callback in callbacks[event]:
|
||||
callbacks[event].append(callback)
|
||||
callbacks[event] = {}
|
||||
fullname = "%s.%s" % (callback.__module__, callback.__name__)
|
||||
if not callbacks[event].has_key(fullname):
|
||||
callbacks[event][fullname] = callback
|
||||
return 1
|
||||
|
||||
class observe(object):
|
||||
@@ -127,9 +128,10 @@ def unregister(event, callback):
|
||||
return False
|
||||
if not callbacks.has_key(event):
|
||||
return False
|
||||
fullname = "%s.%s" % (callback.__module__, callback.__name__)
|
||||
try:
|
||||
callbacks[event].remove(callback)
|
||||
except ValueError:
|
||||
del callbacks[event][fullname]
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
def raiseEvent(event, *args):
|
||||
@@ -142,7 +144,7 @@ def raiseEvent(event, *args):
|
||||
"""
|
||||
if not event in events or not event in callbacks.keys():
|
||||
return 0
|
||||
for callback in callbacks[event]:
|
||||
for name, callback in callbacks[event].iteritems():
|
||||
callback(*args)
|
||||
return 1
|
||||
|
||||
@@ -157,6 +159,6 @@ def raiseQueryEvent(event, *args):
|
||||
result = []
|
||||
if not event in events or not event in callbacks.keys():
|
||||
return result
|
||||
for callback in callbacks[event]:
|
||||
for name, callback in callbacks[event].iteritems():
|
||||
result += callback(*args)
|
||||
return result
|
||||
|
||||
Reference in New Issue
Block a user