mirror of
https://github.com/jwinterm/modoboa.git
synced 2026-10-18 05:51:26 +02:00
Merge from bitbucket
This commit is contained in:
@@ -7,3 +7,6 @@ modoboa.egg-info
|
||||
doc/.build
|
||||
doc/.static
|
||||
doc/.templates
|
||||
DEV
|
||||
.idea
|
||||
modoboa.iml
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
# coding: utf-8
|
||||
from django import forms
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
class LoginForm(forms.Form):
|
||||
username = forms.CharField(
|
||||
label=_("Username"),
|
||||
widget=forms.TextInput(attrs={"class" : "span3"})
|
||||
)
|
||||
widget=forms.TextInput(attrs={"class": "span3"})
|
||||
)
|
||||
password = forms.CharField(
|
||||
label=_("Password"),
|
||||
widget=forms.PasswordInput(attrs={"class" : "span3"})
|
||||
)
|
||||
widget=forms.PasswordInput(attrs={"class": "span3"})
|
||||
)
|
||||
rememberme = forms.BooleanField(
|
||||
initial=False,
|
||||
required=False
|
||||
)
|
||||
)
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
# coding: utf-8
|
||||
|
||||
import crypt, hashlib
|
||||
import string
|
||||
from random import Random
|
||||
from Crypto.Cipher import AES
|
||||
import base64
|
||||
from modoboa.lib import parameters
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# coding: utf-8
|
||||
"""
|
||||
This file demonstrates two different styles of tests (one doctest and one
|
||||
unittest). These will both pass when you run "manage.py test".
|
||||
@@ -20,4 +21,3 @@ Another way to test that 1 + 1 is equal to 2.
|
||||
>>> 1 + 1 == 2
|
||||
True
|
||||
"""}
|
||||
|
||||
|
||||
@@ -4,31 +4,31 @@ from django.contrib.auth import authenticate, login, logout
|
||||
from django.http import HttpResponse, HttpResponseRedirect
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.utils.translation import ugettext as _
|
||||
from modoboa.lib import events
|
||||
from modoboa.lib import events, parameters
|
||||
from modoboa.lib.webutils import _render_to_string
|
||||
from modoboa.lib.sysutils import log_warning
|
||||
from modoboa.admin import views as admviews
|
||||
from forms import LoginForm
|
||||
from modoboa.auth.lib import *
|
||||
from modoboa.auth.lib import encrypt
|
||||
|
||||
def dologin(request):
|
||||
error = None
|
||||
if request.method == "POST":
|
||||
form = LoginForm(request.POST)
|
||||
if form.is_valid():
|
||||
user = authenticate(username=form.cleaned_data["username"],
|
||||
user = authenticate(username=form.cleaned_data["username"],
|
||||
password=form.cleaned_data["password"])
|
||||
if user and user.is_active:
|
||||
if not form.cleaned_data["rememberme"]:
|
||||
request.session.set_expiry(0)
|
||||
login(request, user)
|
||||
login(request, user)
|
||||
if request.user.id != 1:
|
||||
request.session["password"] = encrypt(request.POST["password"])
|
||||
|
||||
request.session["django_language"] = \
|
||||
parameters.get_user(request.user, "LANG", app="general")
|
||||
|
||||
events.raiseEvent("UserLogin", request,
|
||||
events.raiseEvent("UserLogin", request,
|
||||
form.cleaned_data["username"],
|
||||
form.cleaned_data["password"])
|
||||
|
||||
@@ -38,7 +38,7 @@ def dologin(request):
|
||||
return HttpResponseRedirect(next)
|
||||
error = _("Your username and password didn't match. Please try again.")
|
||||
log_warning("Failed connection attempt from %(addr)s as user %(user)s" \
|
||||
% {"addr" : request.META["REMOTE_ADDR"],
|
||||
% {"addr" : request.META["REMOTE_ADDR"],
|
||||
"user" : form.cleaned_data["username"]})
|
||||
|
||||
next = request.POST.get("next", None)
|
||||
@@ -49,7 +49,7 @@ def dologin(request):
|
||||
httpcode = 200
|
||||
|
||||
return HttpResponse(_render_to_string(request, "registration/login.html", {
|
||||
"form" : form, "error" : error, "next" : next,
|
||||
"form" : form, "error" : error, "next" : next,
|
||||
"annoucements" : events.raiseQueryEvent("GetAnnouncement", "loginpage")
|
||||
}), status=httpcode)
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# coding: utf-8
|
||||
import sys
|
||||
import os
|
||||
import shutil
|
||||
@@ -53,7 +54,7 @@ class DeployCommand(Command):
|
||||
output = None
|
||||
if p.returncode:
|
||||
if output:
|
||||
print >>sys.stderr, "\n".join(filter(lambda l: l != None, output))
|
||||
print >>sys.stderr, "\n".join(filter(lambda l: l is not None, output))
|
||||
print >>sys.stderr, "%s failed, check your configuration" % cmd
|
||||
|
||||
def ask_db_info(self, name='default'):
|
||||
@@ -65,8 +66,7 @@ class DeployCommand(Command):
|
||||
:param name: the connection name
|
||||
"""
|
||||
print "Configuring database connection: %s" % name
|
||||
info = {'conn_name' : name}
|
||||
info['dbtype'] = raw_input('Database type (mysql or postgres): ')
|
||||
info = {'conn_name': name, 'dbtype': raw_input('Database type (mysql or postgres): ')}
|
||||
if info['dbtype'] not in ['mysql', 'postgres']:
|
||||
info['dbtype'] = 'mysql'
|
||||
if info['dbtype'] == 'postgres':
|
||||
@@ -78,7 +78,7 @@ class DeployCommand(Command):
|
||||
info['username'] = raw_input('Username: ')
|
||||
info['password'] = getpass.getpass('Password: ')
|
||||
return info
|
||||
|
||||
|
||||
def handle(self, parsed_args):
|
||||
management.call_command('startproject', parsed_args.name, verbosity=False)
|
||||
if os.path.exists("%(name)s/%(name)s" % {'name' : parsed_args.name}):
|
||||
@@ -90,7 +90,7 @@ class DeployCommand(Command):
|
||||
path = parsed_args.name
|
||||
sys.path.append(".")
|
||||
django14 = False
|
||||
|
||||
|
||||
t = Template(dbconn_tpl)
|
||||
default_conn = t.render(Context(self.ask_db_info()))
|
||||
amavis_conn = t.render(Context(self.ask_db_info('amavis'))) if parsed_args.with_amavis \
|
||||
@@ -107,10 +107,10 @@ class DeployCommand(Command):
|
||||
fp.close()
|
||||
shutil.copyfile("%s/urls.py" % self._templates_dir, "%s/urls.py" % path)
|
||||
os.mkdir("%s/media" % path)
|
||||
|
||||
|
||||
if parsed_args.syncdb:
|
||||
self._exec_django_command("syncdb", parsed_args.name, '--migrate', '--noinput')
|
||||
self._exec_django_command("loaddata", parsed_args.name, 'initial_users.json')
|
||||
|
||||
|
||||
if parsed_args.collectstatic:
|
||||
self._exec_django_command("collectstatic", parsed_args.name, '--noinput')
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# coding: utf-8
|
||||
import sys
|
||||
from modoboa.core.management import Command
|
||||
|
||||
@@ -8,7 +9,7 @@ class HelpCommand(Command):
|
||||
super(HelpCommand, self).__init__(*args, **kwargs)
|
||||
self._parser.add_argument('name', type=str,
|
||||
help='A command name')
|
||||
|
||||
|
||||
def handle(self, parsed_args):
|
||||
if not self._commands.has_key(parsed_args.name):
|
||||
print >>sys.stderr, "Unknown command: %s" % parsed_args.name
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# coding: utf-8
|
||||
import getpass
|
||||
import inspect
|
||||
import os
|
||||
@@ -84,14 +85,14 @@ class PostfixMapsCommand(Command):
|
||||
help='Used database type')
|
||||
self._parser.add_argument('--dbhost', type=str, default='127.0.0.1',
|
||||
help='Database host address')
|
||||
self._parser.add_argument('--categories', type=str, nargs='*', default=['std'],
|
||||
self._parser.add_argument('--categories', type=str, nargs='*', default=['std'],
|
||||
help='Map file categories to generate (choices: std, autoreply)')
|
||||
|
||||
|
||||
def handle(self, parsed_args):
|
||||
dbname = raw_input('Database name: ')
|
||||
dbuser = raw_input('Username: ')
|
||||
dbpass = getpass.getpass('Password: ')
|
||||
|
||||
|
||||
try:
|
||||
os.mkdir(parsed_args.destdir)
|
||||
except OSError:
|
||||
@@ -102,6 +103,6 @@ class PostfixMapsCommand(Command):
|
||||
continue
|
||||
if not v.category in parsed_args.categories:
|
||||
continue
|
||||
v().render(parsed_args.destdir, parsed_args.dbtype,
|
||||
dbname=dbname, dbuser=dbuser, dbpassword=dbpass,
|
||||
v().render(parsed_args.destdir, parsed_args.dbtype,
|
||||
dbname=dbname, dbuser=dbuser, dbpassword=dbpass,
|
||||
dbhost=parsed_args.dbhost)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
from django.conf.urls.defaults import *
|
||||
# coding: utf-8
|
||||
from django.conf.urls.defaults import patterns
|
||||
|
||||
urlpatterns = patterns('modoboa.demo.views',
|
||||
(r'^sendvirus/$', 'send_virus'),
|
||||
(r'^sendspam/$', 'send_spam'),
|
||||
)
|
||||
(r'^sendvirus/$', 'send_virus'),
|
||||
(r'^sendspam/$', 'send_spam'),
|
||||
)
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
from django.utils.translation import ugettext as _, ugettext_lazy
|
||||
from django.core.urlresolvers import reverse
|
||||
from modoboa.lib import events, parameters
|
||||
from modoboa.lib.webutils import static_url
|
||||
from modoboa.extensions import ModoExtension, exts_pool
|
||||
|
||||
class Webmail(ModoExtension):
|
||||
@@ -11,23 +10,23 @@ class Webmail(ModoExtension):
|
||||
version = "1.0"
|
||||
description = ugettext_lazy("Simple IMAP webmail")
|
||||
needs_media = True
|
||||
|
||||
|
||||
def load(self):
|
||||
parameters.register_app(uparams_opts=dict(needs_mailbox=True))
|
||||
|
||||
parameters.register_admin("IMAP_SERVER", type="string",
|
||||
|
||||
parameters.register_admin("IMAP_SERVER", type="string",
|
||||
deflt="127.0.0.1",
|
||||
help=ugettext_lazy("Address of your IMAP server"))
|
||||
parameters.register_admin("IMAP_SECURED", type="list_yesno",
|
||||
parameters.register_admin("IMAP_SECURED", type="list_yesno",
|
||||
deflt="no",
|
||||
help=ugettext_lazy("Use a secured connection to access IMAP server"))
|
||||
parameters.register_admin("IMAP_PORT", type="int", deflt="143",
|
||||
help=ugettext_lazy("Listening port of your IMAP server"))
|
||||
parameters.register_admin("SMTP_SERVER", type="string",
|
||||
parameters.register_admin("SMTP_SERVER", type="string",
|
||||
deflt="127.0.0.1",
|
||||
help=ugettext_lazy("Address of your SMTP server"))
|
||||
parameters.register_admin("SMTP_SECURED_MODE", type="list",
|
||||
values=[("none", ugettext_lazy("None")),
|
||||
parameters.register_admin("SMTP_SECURED_MODE", type="list",
|
||||
values=[("none", ugettext_lazy("None")),
|
||||
("starttls", "STARTTLS"),
|
||||
("ssl", "SSL/TLS")],
|
||||
deflt="none",
|
||||
@@ -39,7 +38,7 @@ class Webmail(ModoExtension):
|
||||
help=ugettext_lazy("Server needs authentication"))
|
||||
parameters.register_admin("MAX_ATTACHMENT_SIZE", type="int", deflt=2048,
|
||||
help=ugettext_lazy("Maximum attachment size in bytes (or KB, MB, GB if specified)"))
|
||||
|
||||
|
||||
parameters.register_user("MESSAGES_PER_PAGE", type="int", deflt=40,
|
||||
label=ugettext_lazy("Number of displayed emails per page"),
|
||||
help=ugettext_lazy("Sets the maximum number of messages displayed in a page"))
|
||||
@@ -99,9 +98,10 @@ def userlogout(request):
|
||||
try:
|
||||
m = IMAPconnector(user=request.user.username,
|
||||
password=request.session["password"])
|
||||
except Exception, e:
|
||||
except Exception:
|
||||
# TODO silent exception are bad : we should at least log it
|
||||
return
|
||||
|
||||
|
||||
# The following statement may fail under Python 2.6...
|
||||
try:
|
||||
m.logout()
|
||||
|
||||
@@ -12,11 +12,11 @@ class WebmailError(ModoboaException):
|
||||
errorexpr = re.compile("\[([^\]]+)\]\s*([^\.]+)")
|
||||
|
||||
def __init__(self, reason, ajax=False):
|
||||
m = WebmailError.errorexpr.match(reason)
|
||||
if m is None:
|
||||
match = WebmailError.errorexpr.match(reason)
|
||||
if not match:
|
||||
self.reason = reason
|
||||
else:
|
||||
self.reason = "%s: %s" % (_("Server response"), m.group(2))
|
||||
self.reason = "%s: %s" % (_("Server response"), match.group(2))
|
||||
self.ajax = ajax
|
||||
|
||||
def __str__(self):
|
||||
|
||||
@@ -61,8 +61,7 @@ def parse_bodystructure(buf, depth=0, prefix=""):
|
||||
if nb_bodystruct == 0:
|
||||
ret.append(subret)
|
||||
elif nb_bodystruct == 1:
|
||||
newret = [ret.pop(-1)]
|
||||
newret.append(subret)
|
||||
newret = [ret.pop(-1), subret]
|
||||
ret.append(newret)
|
||||
else:
|
||||
ret[-1].append(subret)
|
||||
@@ -97,7 +96,7 @@ def parse_fetch_response(data):
|
||||
|
||||
We extract the message number, the UID and its value and consider
|
||||
what remains as the response data.
|
||||
|
||||
|
||||
:param data: the data returned by the ``imaplib`` command
|
||||
:return: a dictionnary
|
||||
"""
|
||||
@@ -182,7 +181,7 @@ def dump_bodystructure(bs, depth=0):
|
||||
dump_bodystructure(part, depth + 1)
|
||||
else:
|
||||
print "%s/%s" % (struct[0], struct[1])
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# resp = [('855 (UID 46931 BODYSTRUCTURE ((("text" "plain" ("charset" "iso-8859-1") NIL NIL "quoted-printable" 886 32 NIL NIL NIL NIL)("text" "html" ("charset" "us-ascii") NIL NIL "quoted-printable" 1208 16 NIL NIL NIL NIL) "alternative" ("boundary" "----=_NextPart_001_0003_01CCC564.B2F64FF0") NIL NIL NIL)("application" "octet-stream" ("name" "Carte Verte_2.pdf") NIL NIL "base64" 285610 NIL ("attachment" ("filename" "Carte Verte_2.pdf")) NIL NIL) "mixed" ("boundary" "----=_NextPart_000_0002_01CCC564.B2F64FF0") NIL NIL NIL) BODY[HEADER.FIELDS (DATE FROM TO CC SUBJECT)] {153}', 'From: <Service.client10@maaf.fr>\r\nTo: <TONIO@NGYN.ORG>\r\nCc: \r\nSubject: Notre contact du 28/12/2011 - 192175092\r\nDate: Wed, 28 Dec 2011 13:29:17 +0100\r\n\r\n'), ')']
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# coding: utf-8
|
||||
from django import forms
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
@@ -9,7 +10,7 @@ class ComposeMailForm(forms.Form):
|
||||
subject = forms.CharField(label=_("Subject"), max_length=255, required=False)
|
||||
|
||||
origmsgid = forms.CharField(label="", widget=forms.HiddenInput(), required=False)
|
||||
|
||||
|
||||
class FolderForm(forms.Form):
|
||||
oldname = forms.CharField(label="", widget=forms.HiddenInput(), required=False)
|
||||
name = forms.CharField()
|
||||
|
||||
@@ -9,10 +9,10 @@ import time
|
||||
from functools import wraps
|
||||
from django.utils.translation import ugettext as _
|
||||
from modoboa.lib import parameters
|
||||
from modoboa.lib.connections import *
|
||||
from modoboa.lib.connections import ConnectionsManager
|
||||
from modoboa.lib.webutils import static_url
|
||||
from exceptions import ImapError, WebmailError
|
||||
from fetch_parser import *
|
||||
from fetch_parser import parse_fetch_response
|
||||
|
||||
#imaplib.Debug = 4
|
||||
|
||||
@@ -75,12 +75,12 @@ class BodyStructure(object):
|
||||
* Any other MIME type is considered as an attachment (for now)
|
||||
|
||||
:param definition: a part definition (list)
|
||||
:param prefix: the part's number
|
||||
:param pnum: the part's number
|
||||
:param multisubtype: the multipart subtype
|
||||
"""
|
||||
pnum = "1" if pnum is None else pnum
|
||||
params = dict(pnum=pnum, params=definition[2], cid=definition[3],
|
||||
description=definition[4], encoding=definition[5],
|
||||
description=definition[4], encoding=definition[5],
|
||||
size=definition[6])
|
||||
mtype = definition[0].lower()
|
||||
subtype = definition[1].lower()
|
||||
@@ -122,7 +122,7 @@ class BodyStructure(object):
|
||||
for part in struct[0]:
|
||||
self.load_from_definition(part, struct[1])
|
||||
return
|
||||
|
||||
|
||||
self.__store_part(struct, pnum, multisubtype)
|
||||
|
||||
def has_attachments(self):
|
||||
@@ -214,7 +214,7 @@ class IMAPconnector(object):
|
||||
cpt += 1
|
||||
else:
|
||||
if bodystruct[0].lower() == mtype and bodystruct[1].lower() == stype:
|
||||
return ("1" if not len(prefix) else prefix,
|
||||
return ("1" if not len(prefix) else prefix,
|
||||
bodystruct[5], int(bodystruct[6]))
|
||||
return (None, None, 0)
|
||||
|
||||
@@ -230,12 +230,12 @@ class IMAPconnector(object):
|
||||
if hasattr(self, "current_mailbox"):
|
||||
del self.current_mailbox
|
||||
else:
|
||||
return
|
||||
return
|
||||
self.login(user, password)
|
||||
|
||||
def login(self, user, passwd):
|
||||
"""Custom login method
|
||||
|
||||
|
||||
We connect to the server, issue a LOGIN command. If
|
||||
successfull, we try to record a eventuel CAPABILITY untagged
|
||||
response. Otherwise, we issue the command.
|
||||
@@ -305,9 +305,9 @@ class IMAPconnector(object):
|
||||
"""Issue a SELECT/EXAMINE command to the server
|
||||
|
||||
The given name is first 'imap-utf7' encoded.
|
||||
|
||||
|
||||
:param name: mailbox's name
|
||||
:param readonly:
|
||||
:param readonly:
|
||||
"""
|
||||
if hasattr(self, "current_mailbox"):
|
||||
if self.current_mailbox == name and not force:
|
||||
@@ -348,35 +348,35 @@ class IMAPconnector(object):
|
||||
break
|
||||
if sdescr is None:
|
||||
sdescr = {"name" : parts[0], "path" : path, "sub" : []}
|
||||
descr += [sdescr]
|
||||
descr += [sdescr]
|
||||
if self._parse_mailbox_name(sdescr["sub"], path, delimiter, parts[1:]):
|
||||
sdescr["class"] = "subfolders"
|
||||
return True
|
||||
|
||||
def _listmboxes_simple(self, topmailbox='INBOX', mailboxes=[], **kwargs):
|
||||
def _listmboxes_simple(self, topmailbox='INBOX', mailboxes=None, **kwargs):
|
||||
#data = self._cmd("LIST", "", "*")
|
||||
if not mailboxes: mailboxes = []
|
||||
(status, data) = self.m.list()
|
||||
result = []
|
||||
newmboxes = []
|
||||
for mb in data:
|
||||
flags, delimiter, name = self.list_response_pattern.match(mb).groups()
|
||||
name = name.strip('"').decode("imap4-utf-7")
|
||||
pos = -1
|
||||
mdm_found = False
|
||||
for idx, mdm in enumerate(mailboxes):
|
||||
if mdm["name"] == name:
|
||||
pos = idx
|
||||
mdm_found = True
|
||||
descr = mailboxes[idx]
|
||||
break
|
||||
if pos == -1:
|
||||
if not mdm_found:
|
||||
descr = dict(name=name)
|
||||
newmboxes += [descr]
|
||||
else:
|
||||
descr = mailboxes[idx]
|
||||
|
||||
if re.search("\%s" % delimiter, name):
|
||||
parts = name.split(".")
|
||||
if not descr.has_key("path"):
|
||||
descr["path"] = parts[0]
|
||||
descr["sub"] = []
|
||||
if self._parse_mailbox_name(descr["sub"], parts[0], delimiter,
|
||||
if self._parse_mailbox_name(descr["sub"], parts[0], delimiter,
|
||||
parts[1:]):
|
||||
descr["class"] = "subfolders"
|
||||
continue
|
||||
@@ -385,7 +385,8 @@ class IMAPconnector(object):
|
||||
mailboxes += sorted(newmboxes, key=itemgetter("name"))
|
||||
|
||||
@capability('LIST-EXTENDED', '_listmboxes_simple')
|
||||
def _listmboxes(self, topmailbox='', mailboxes=[], until_mailbox=None):
|
||||
def _listmboxes(self, topmailbox='', mailboxes=None, until_mailbox=None):
|
||||
if not mailboxes: mailboxes = []
|
||||
pattern = ("%s.%%" % topmailbox.encode("imap4-utf-7")) if len(topmailbox) else "%"
|
||||
resp = self._cmd("LIST", "", pattern, "RETURN", "(CHILDREN)")
|
||||
newmboxes = []
|
||||
@@ -394,17 +395,16 @@ class IMAPconnector(object):
|
||||
self.listextended_response_pattern.match(mb).groups()
|
||||
flags = flags.split(' ')
|
||||
name = name.decode("imap4-utf-7")
|
||||
pos = -1
|
||||
mdm_found = False
|
||||
for idx, mdm in enumerate(mailboxes):
|
||||
if mdm["name"] == name:
|
||||
pos = idx
|
||||
mdm_found = True
|
||||
descr = mailboxes[idx]
|
||||
break
|
||||
if pos == -1:
|
||||
if not mdm_found:
|
||||
descr = dict(name=name)
|
||||
newmboxes += [descr]
|
||||
else:
|
||||
descr = mailboxes[idx]
|
||||
|
||||
|
||||
if r'\Marked' in flags or not r'\UnMarked' in flags:
|
||||
descr["send_status"] = True
|
||||
if r'\HasChildren' in flags:
|
||||
@@ -433,7 +433,7 @@ class IMAPconnector(object):
|
||||
md_mailboxes = []
|
||||
else:
|
||||
md_mailboxes = [{"name" : "INBOX", "class" : "icon-inbox"},
|
||||
{"name" : parameters.get_user(user, "DRAFTS_FOLDER"),
|
||||
{"name" : parameters.get_user(user, "DRAFTS_FOLDER"),
|
||||
"class" : "icon-file"},
|
||||
{"name" : 'Junk', "class" : "icon-fire"},
|
||||
{"name" : parameters.get_user(user, "SENT_FOLDER"),
|
||||
@@ -515,7 +515,7 @@ class IMAPconnector(object):
|
||||
"""Compact a specific mailbox
|
||||
|
||||
Issue an EXPUNGE command for the specified mailbox.
|
||||
|
||||
|
||||
:param mbox: the mailbox's name
|
||||
"""
|
||||
self.select_mailbox(mbox, False)
|
||||
@@ -547,12 +547,12 @@ class IMAPconnector(object):
|
||||
self.quota_limit = self.quota_actual = None
|
||||
return
|
||||
|
||||
data = self._cmd("GETQUOTAROOT", self._encode_mbox_name(mailbox),
|
||||
data = self._cmd("GETQUOTAROOT", self._encode_mbox_name(mailbox),
|
||||
responses=["QUOTAROOT", "QUOTA"])
|
||||
if data is None:
|
||||
self.quota_limit = self.quota_actual = None
|
||||
return
|
||||
|
||||
|
||||
quotadef = data[1][0]
|
||||
m = re.match("[^\s]+ \(STORAGE (\d+) (\d+)\)", quotadef)
|
||||
if not m:
|
||||
@@ -628,14 +628,14 @@ class IMAPconnector(object):
|
||||
:param mbox: the mailbox containing the message
|
||||
:param mailid: the message's unique id
|
||||
:param readonly:
|
||||
:param extraheaders:
|
||||
:param headers:
|
||||
"""
|
||||
self.select_mailbox(mbox, readonly)
|
||||
if headers is None:
|
||||
headers = ['DATE', 'FROM', 'TO', 'CC', 'SUBJECT']
|
||||
bcmd = "BODY.PEEK" if readonly else "BODY"
|
||||
data = self._cmd(
|
||||
"FETCH", mailid,
|
||||
"FETCH", mailid,
|
||||
"(BODYSTRUCTURE %s[HEADER.FIELDS (%s)])" % (bcmd, " ".join(headers))
|
||||
)
|
||||
return data[int(mailid)]
|
||||
@@ -658,7 +658,7 @@ def get_imapconnector(request):
|
||||
|
||||
:param request: a ``Request`` object
|
||||
"""
|
||||
imapc = IMAPconnector(user=request.user.username,
|
||||
imapc = IMAPconnector(user=request.user.username,
|
||||
password=request.session["password"])
|
||||
return imapc
|
||||
|
||||
|
||||
@@ -1,31 +1,30 @@
|
||||
# coding: utf-8
|
||||
|
||||
import sys, os
|
||||
import re
|
||||
import time
|
||||
from datetime import datetime, timedelta
|
||||
import email
|
||||
import lxml
|
||||
import chardet
|
||||
from django.core.files.uploadhandler import FileUploadHandler, StopUpload, SkipFile
|
||||
from django.http import HttpResponse
|
||||
|
||||
from django.core.files.uploadhandler import FileUploadHandler, SkipFile
|
||||
from django.utils.translation import ugettext as _, ugettext_lazy
|
||||
from django.conf import settings
|
||||
from modoboa.lib import u2u_decode, tables, imap_utf7, parameters
|
||||
from modoboa.lib.webutils import static_url, size2integer
|
||||
from modoboa.lib.connections import ConnectionsManager
|
||||
from modoboa.lib.email_listing import MBconnector, EmailListing
|
||||
from modoboa.lib.emailutils import *
|
||||
|
||||
from imaputils import *
|
||||
from exceptions import *
|
||||
import os
|
||||
import re
|
||||
from modoboa.lib import u2u_decode, tables, parameters
|
||||
from modoboa.lib.webutils import size2integer
|
||||
from modoboa.lib.email_listing import EmailListing
|
||||
from modoboa.extensions.webmail.exceptions import WebmailError
|
||||
from modoboa.extensions.webmail.imaputils import IMAPconnector, get_imapconnector, BodyStructure
|
||||
from modoboa.lib.emailutils import EmailAddress, Email
|
||||
|
||||
|
||||
class WMtable(tables.Table):
|
||||
tableid = "emails"
|
||||
styles = "table-condensed"
|
||||
idkey = "imapid"
|
||||
select = tables.ImgColumn(
|
||||
"select", cssclass="draggable left", width="2%",
|
||||
"select", cssclass="draggable left", width="2%",
|
||||
defvalue="%spics/grippy.png" % settings.STATIC_URL,
|
||||
header="<input type='checkbox' name='toggleselect' id='toggleselect' />"
|
||||
)
|
||||
@@ -112,7 +111,7 @@ class ImapListing(EmailListing):
|
||||
deflocation = "INBOX/"
|
||||
defcallback = "wm_updatelisting"
|
||||
reset_wm_url = False
|
||||
|
||||
|
||||
def __init__(self, user, password, **kwargs):
|
||||
self.user = user
|
||||
self.mbc = IMAPconnector(user=user.username, password=password)
|
||||
@@ -165,7 +164,7 @@ class ImapEmail(Email):
|
||||
('Subject', True),
|
||||
]
|
||||
|
||||
def __init__(self, mbox, mailid, request, dformat="DISPLAYMODE", addrfull=False,
|
||||
def __init__(self, mbox, mailid, request, dformat="DISPLAYMODE", addrfull=False,
|
||||
links=0):
|
||||
mformat = parameters.get_user(request.user, "DISPLAYMODE")
|
||||
self.dformat = parameters.get_user(request.user, dformat)
|
||||
@@ -179,7 +178,7 @@ class ImapEmail(Email):
|
||||
self.mailid = mailid
|
||||
headers = msg['BODY[HEADER.FIELDS (%s)]' % self.headers_as_text]
|
||||
fallback_fmt = "html" if self.dformat == "plain" else "plain"
|
||||
|
||||
|
||||
self.bs = BodyStructure(msg['BODYSTRUCTURE'])
|
||||
data = None
|
||||
|
||||
@@ -206,7 +205,7 @@ class ImapEmail(Email):
|
||||
getattr(self, "viewmail_%s" % mformat)(bodyc, links=links)
|
||||
else:
|
||||
self.body = None
|
||||
|
||||
|
||||
self._find_attachments()
|
||||
|
||||
msg = email.message_from_string(headers)
|
||||
@@ -257,7 +256,7 @@ class ImapEmail(Email):
|
||||
att.has_key("disposition") and len(att["disposition"]) > 1:
|
||||
params = att["disposition"][1]
|
||||
key = "filename"
|
||||
|
||||
|
||||
if key and params:
|
||||
for pos, value in enumerate(params):
|
||||
if value == key:
|
||||
@@ -311,7 +310,7 @@ class Modifier(ImapEmail):
|
||||
def _modify_html(self):
|
||||
pass
|
||||
|
||||
|
||||
|
||||
class ReplyModifier(Modifier):
|
||||
headernames = ImapEmail.headernames + \
|
||||
[("Reply-To", True),
|
||||
@@ -358,13 +357,13 @@ class ReplyModifier(Modifier):
|
||||
body += "\n"
|
||||
body += ">%s" % l
|
||||
self.body = body
|
||||
|
||||
|
||||
class ForwardModifier(Modifier):
|
||||
def __init__(self, mbox, mailid, request, form, **kwargs):
|
||||
super(ForwardModifier, self).__init__(
|
||||
mbox, mailid, request, dformat="EDITOR", **kwargs
|
||||
)
|
||||
|
||||
|
||||
self._header()
|
||||
form.fields["from_"].initial = request.user.username
|
||||
form.fields["subject"].initial = "Fwd: %s" % self.Subject
|
||||
@@ -488,7 +487,7 @@ def find_images_in_body(body):
|
||||
% (ct, os.path.basename(fname)))
|
||||
p["Content-Disposition"] = "inline"
|
||||
parts.append(p)
|
||||
|
||||
|
||||
return lxml.html.tostring(html), parts
|
||||
|
||||
def set_compose_session(request):
|
||||
@@ -557,7 +556,7 @@ def html2plaintext(content):
|
||||
if p is None:
|
||||
continue
|
||||
plaintext += p + "\n"
|
||||
|
||||
|
||||
return plaintext
|
||||
|
||||
def get_current_url(request):
|
||||
@@ -603,7 +602,7 @@ def send_mail(request, posturl=None):
|
||||
"""
|
||||
from email.mime.multipart import MIMEMultipart
|
||||
from forms import ComposeMailForm
|
||||
from modoboa.lib.webutils import getctx, ajax_simple_response, _render_to_string
|
||||
from modoboa.lib.webutils import _render_to_string
|
||||
from modoboa.auth.lib import get_password
|
||||
|
||||
form = ComposeMailForm(request.POST)
|
||||
@@ -623,13 +622,13 @@ def send_mail(request, posturl=None):
|
||||
submsg.attach(MIMEText(textbody.encode(charset),
|
||||
_subtype="plain", _charset=charset))
|
||||
body, images = find_images_in_body(body)
|
||||
submsg.attach(MIMEText(body.encode(charset), _subtype=editormode,
|
||||
submsg.attach(MIMEText(body.encode(charset), _subtype=editormode,
|
||||
_charset=charset))
|
||||
msg.attach(submsg)
|
||||
for img in images:
|
||||
msg.attach(img)
|
||||
else:
|
||||
text = MIMEText(body.encode(charset),
|
||||
text = MIMEText(body.encode(charset),
|
||||
_subtype=editormode, _charset=charset)
|
||||
if len(request.session["compose_mail"]["attachments"]):
|
||||
msg = MIMEMultipart()
|
||||
@@ -686,7 +685,7 @@ def send_mail(request, posturl=None):
|
||||
del request.session["compose_mail"]
|
||||
return True, dict(url=get_current_url(request))
|
||||
|
||||
listing = _render_to_string(request, "webmail/compose.html",
|
||||
listing = _render_to_string(request, "webmail/compose.html",
|
||||
{"form" : form, "noerrors" : True,
|
||||
"body" : request.POST["id_body"].strip(),
|
||||
"posturl" : posturl})
|
||||
@@ -698,19 +697,19 @@ class AttachmentUploadHandler(FileUploadHandler):
|
||||
Simple upload handler to limit the size of the attachments users
|
||||
can upload.
|
||||
"""
|
||||
|
||||
|
||||
def __init__(self, request=None):
|
||||
super(AttachmentUploadHandler, self).__init__(request)
|
||||
self.total_upload = 0
|
||||
self.toobig = False
|
||||
self.maxsize = size2integer(parameters.get_admin("MAX_ATTACHMENT_SIZE"))
|
||||
|
||||
|
||||
def receive_data_chunk(self, raw_data, start):
|
||||
self.total_upload += len(raw_data)
|
||||
if self.total_upload >= self.maxsize:
|
||||
self.toobig = True
|
||||
raise SkipFile()
|
||||
return raw_data
|
||||
|
||||
|
||||
def file_complete(self, file_size):
|
||||
return None
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
# coding: utf-8
|
||||
|
||||
from modoboa.lib.webutils import ajax_response, _render_error
|
||||
from modoboa.extensions.webmail.exceptions import *
|
||||
from modoboa.extensions.webmail.exceptions import WebmailError, ImapError
|
||||
|
||||
class WebmailErrorMiddleware(object):
|
||||
def process_exception(self, request, exception):
|
||||
@@ -10,6 +9,6 @@ class WebmailErrorMiddleware(object):
|
||||
json = request.GET.get("json", False) if request.method == "GET" \
|
||||
else request.POST.get("json", False)
|
||||
if json:
|
||||
return ajax_response(request, status="ko",
|
||||
return ajax_response(request, status="ko",
|
||||
respmsg=str(exception), norefresh=True)
|
||||
return _render_error(request, user_context=dict(error=str(exception)))
|
||||
|
||||
@@ -47,68 +47,42 @@ Webmail.prototype = {
|
||||
},
|
||||
|
||||
register_navcallbacks: function() {
|
||||
this.navobject.register_callback("listmailbox",
|
||||
$.proxy(this.listmailbox_callback, this));
|
||||
this.navobject.register_callback("compose",
|
||||
$.proxy(this.compose_callback, this));
|
||||
this.navobject.register_callback("viewmail",
|
||||
$.proxy(this.viewmail_callback, this));
|
||||
this.navobject.register_callback("listmailbox", $.proxy(this.listmailbox_callback, this));
|
||||
this.navobject.register_callback("compose", $.proxy(this.compose_callback, this));
|
||||
this.navobject.register_callback("viewmail", $.proxy(this.viewmail_callback, this));
|
||||
|
||||
this.navobject.register_callback("reply",
|
||||
$.proxy(this.compose_callback, this));
|
||||
this.navobject.register_callback("replyall",
|
||||
$.proxy(this.compose_callback, this));
|
||||
this.navobject.register_callback("forward",
|
||||
$.proxy(this.compose_callback, this));
|
||||
this.navobject.register_callback("delete",
|
||||
$.proxy(this.delete_callback, this));
|
||||
this.navobject.register_callback("reply", $.proxy(this.compose_callback, this));
|
||||
this.navobject.register_callback("replyall", $.proxy(this.compose_callback, this));
|
||||
this.navobject.register_callback("forward", $.proxy(this.compose_callback, this));
|
||||
this.navobject.register_callback("delete", $.proxy(this.delete_callback, this));
|
||||
},
|
||||
|
||||
listen: function() {
|
||||
$(window).resize(this.resize);
|
||||
|
||||
$(document).on("click", "a[name=compose]",
|
||||
$.proxy(this.compose_loader, this));
|
||||
$(document).on("click", "a[name*=mark-]",
|
||||
$.proxy(this.send_mark_request, this));
|
||||
$(document).on("click", "a[name=compress]",
|
||||
$.proxy(this.compress, this));
|
||||
$(document).on("click", "a[name=empty]",
|
||||
$.proxy(this.empty, this));
|
||||
$(document).on("click", "#bottom-bar a",
|
||||
$.proxy(this.getpage_loader, this));
|
||||
$(document).on("click", "a[name=compose]", $.proxy(this.compose_loader, this));
|
||||
$(document).on("click", "a[name*=mark-]", $.proxy(this.send_mark_request, this));
|
||||
$(document).on("click", "a[name=compress]", $.proxy(this.compress, this));
|
||||
$(document).on("click", "a[name=empty]", $.proxy(this.empty, this));
|
||||
$(document).on("click", "#bottom-bar a", $.proxy(this.getpage_loader, this));
|
||||
|
||||
$(document).on("click", "a[name=loadfolder]",
|
||||
$.proxy(this.listmailbox_loader, this));
|
||||
$(document).on("click", "a[name=selectfolder]",
|
||||
this.select_parent_mailbox),
|
||||
$(document).on("click", "div[class*=clickbox]",
|
||||
$.proxy(this.mbox_state_callback, this));
|
||||
$(document).on("click", "a[name=newmbox]",
|
||||
$.proxy(this.new_mailbox, this));
|
||||
$(document).on("click", "a[name=editmbox]",
|
||||
$.proxy(this.edit_mbox, this));
|
||||
$(document).on("click", "a[name=removembox]",
|
||||
$.proxy(this.remove_mbox, this));
|
||||
$(document).on("click", "a[name=loadfolder]", $.proxy(this.listmailbox_loader, this));
|
||||
$(document).on("click", "a[name=selectfolder]", this.select_parent_mailbox);
|
||||
$(document).on("click", "div[class*=clickbox]", $.proxy(this.mbox_state_callback, this));
|
||||
$(document).on("click", "a[name=newmbox]", $.proxy(this.new_mailbox, this));
|
||||
$(document).on("click", "a[name=editmbox]", $.proxy(this.edit_mbox, this));
|
||||
$(document).on("click", "a[name=removembox]", $.proxy(this.remove_mbox, this));
|
||||
|
||||
$(document).on("dblclick", "tbody>tr",
|
||||
$.proxy(this.viewmail_loader, this));
|
||||
$(document).on("click", "tbody>tr", $.proxy(this.viewmail_loader, this));
|
||||
|
||||
$(document).on("click", "a[name=reply]",
|
||||
$.proxy(this.reply_loader, this));
|
||||
$(document).on("click", "a[name=replyall]",
|
||||
$.proxy(this.reply_loader, this));
|
||||
$(document).on("click", "a[name=forward]",
|
||||
$.proxy(this.reply_loader, this));
|
||||
$(document).on("click", "a[name=delete]",
|
||||
$.proxy(this.delete_message, this));
|
||||
$(document).on("click", "a[name=activate_links]",
|
||||
$.proxy(function(e) { this.display_mode(e, "1"); }, this));
|
||||
$(document).on("click", "a[name=disable_links]",
|
||||
$.proxy(function(e) { this.disable_mode(e, "0"); }, this));
|
||||
$(document).on("click", "a[name=reply]", $.proxy(this.reply_loader, this));
|
||||
$(document).on("click", "a[name=replyall]", $.proxy(this.reply_loader, this));
|
||||
$(document).on("click", "a[name=forward]", $.proxy(this.reply_loader, this));
|
||||
$(document).on("click", "a[name=delete]", $.proxy(this.delete_message, this));
|
||||
$(document).on("click", "a[name=activate_links]", $.proxy(function(e) { this.display_mode(e, "1"); }, this));
|
||||
$(document).on("click", "a[name=disable_links]", $.proxy(function(e) { this.disable_mode(e, "0"); }, this));
|
||||
|
||||
$(document).on("click", "a[name=sendmail]",
|
||||
$.proxy(this.sendmail, this));
|
||||
$(document).on("click", "a[name=sendmail]", $.proxy(this.sendmail, this));
|
||||
|
||||
$(document).on("click", "#attachments", $.proxy(function(e) {
|
||||
modalbox(e, undefined, $("#attachments").attr("name"),
|
||||
|
||||
@@ -5,15 +5,13 @@ from django.utils.translation import ugettext as _
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.conf import settings
|
||||
from modoboa.extensions import webmail
|
||||
from modoboa.extensions.webmail.lib import IMAPheader
|
||||
from modoboa.extensions.webmail.imaputils import separate_mailbox
|
||||
from modoboa.lib import parameters
|
||||
from modoboa.lib.webutils import static_url
|
||||
|
||||
register = template.Library()
|
||||
|
||||
@register.simple_tag
|
||||
def viewmail_menu(selection, folder, user, mail_id=None):
|
||||
def viewmail_menu(selection, folder, user, mail_id=None):
|
||||
entries = [
|
||||
{"name" : "reply",
|
||||
"url" : "action=reply&mbox=%s&mailid=%s" % (folder, mail_id),
|
||||
@@ -34,21 +32,21 @@ def viewmail_menu(selection, folder, user, mail_id=None):
|
||||
{"name" : "display_options",
|
||||
"label" : _("Display options"),
|
||||
"menu" : [
|
||||
{"name" : "activate_links",
|
||||
{"name" : "activate_links",
|
||||
"label" : _("Activate links")},
|
||||
{"name" : "disable_links",
|
||||
{"name" : "disable_links",
|
||||
"label" : _("Disable links")}
|
||||
]
|
||||
}
|
||||
]
|
||||
menu = render_to_string('common/buttons_list.html',
|
||||
{"selection" : selection, "entries" : entries,
|
||||
menu = render_to_string('common/buttons_list.html',
|
||||
{"selection" : selection, "entries" : entries,
|
||||
"user" : user, "extraclasses" : "pull-left"})
|
||||
|
||||
entries = [{"name" : "close",
|
||||
"title" : _("Close this message"),
|
||||
"img" : "icon-remove"}]
|
||||
menu += render_to_string('common/buttons_list.html',
|
||||
menu += render_to_string('common/buttons_list.html',
|
||||
{"entries" : entries, "extraclasses" : "pull-right"})
|
||||
|
||||
return menu
|
||||
@@ -65,8 +63,8 @@ def compose_menu(selection, backurl, user):
|
||||
"img" : "icon-envelope",
|
||||
"label" : _("Send")},
|
||||
]
|
||||
return render_to_string('common/buttons_list.html',
|
||||
{"selection" : selection, "entries" : entries,
|
||||
return render_to_string('common/buttons_list.html',
|
||||
{"selection" : selection, "entries" : entries,
|
||||
"user" : user})
|
||||
|
||||
@register.simple_tag
|
||||
@@ -136,7 +134,7 @@ def print_mailboxes(tree, selected=None, withunseen=False, selectonly=False):
|
||||
ul_state = "hidden"
|
||||
div_state = "collapsed"
|
||||
result += "<div class='clickbox %s'></div>" % div_state
|
||||
|
||||
|
||||
cssclass = "block"
|
||||
extra_attrs = ""
|
||||
if withunseen and mbox.has_key("unseen"):
|
||||
@@ -148,7 +146,7 @@ def print_mailboxes(tree, selected=None, withunseen=False, selectonly=False):
|
||||
<i class="%s"></i>
|
||||
%s
|
||||
</a>
|
||||
""" % (mbox.has_key("path") and mbox["path"] or mbox["name"], cssclass,
|
||||
""" % (mbox.has_key("path") and mbox["path"] or mbox["name"], cssclass,
|
||||
'selectfolder' if selectonly else 'loadfolder', extra_attrs, iclass, label)
|
||||
if mbox.has_key("sub") and len(mbox["sub"]):
|
||||
result += "<ul name='%s' class='nav nav-list %s'>" % (mbox["path"], ul_state) \
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
from django.conf.urls.defaults import *
|
||||
# coding: utf-8
|
||||
from django.conf.urls.defaults import patterns
|
||||
|
||||
urlpatterns = patterns(
|
||||
'modoboa.extensions.webmail.views',
|
||||
@@ -6,7 +7,7 @@ urlpatterns = patterns(
|
||||
(r'^submailboxes', "submailboxes"),
|
||||
(r'^getmailcontent', 'getmailcontent'),
|
||||
(r'^unseenmsgs', 'check_unseen_messages'),
|
||||
|
||||
|
||||
(r'^delete/$', 'delete'),
|
||||
(r'^move/$', "move"),
|
||||
(r'^mark/(?P<name>.+)/$', "mark"),
|
||||
@@ -15,8 +16,8 @@ urlpatterns = patterns(
|
||||
(r'^newfolder/$', "newfolder"),
|
||||
(r'^editfolder/$', 'editfolder'),
|
||||
(r'^delfolder/$', 'delfolder'),
|
||||
|
||||
|
||||
(r'^attachments/$', 'attachments'),
|
||||
(r'^delattachment/$', 'delattachment'),
|
||||
(r'^getattachment/$', 'getattachment'),
|
||||
)
|
||||
)
|
||||
|
||||
@@ -1,36 +1,36 @@
|
||||
# coding: utf-8
|
||||
from django.http import HttpResponse, Http404
|
||||
from django.conf import settings
|
||||
import os
|
||||
from django.http import HttpResponse
|
||||
from django.template import Template, Context
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from modoboa.lib import parameters
|
||||
from modoboa.lib.webutils import _render, _render_error, \
|
||||
getctx, _render_to_string, ajax_response, ajax_simple_response
|
||||
from modoboa.lib.email_listing import parse_search_parameters
|
||||
from modoboa.lib.webutils import _render, _render_to_string, ajax_response, ajax_simple_response
|
||||
from modoboa.lib.decorators import needs_mailbox
|
||||
from modoboa.auth.lib import *
|
||||
from lib import *
|
||||
from forms import *
|
||||
from exceptions import WebmailError
|
||||
from forms import FolderForm, AttachmentForm, ComposeMailForm
|
||||
from imaputils import get_imapconnector, IMAPconnector, separate_mailbox
|
||||
from lib import decode_payload, AttachmentUploadHandler, save_attachment, ImapListing, EmailSignature, clean_attachments, set_compose_session, send_mail, ImapEmail
|
||||
from templatetags import webextras
|
||||
|
||||
@login_required
|
||||
@needs_mailbox()
|
||||
def getattachment(request):
|
||||
"""Fetch a message attachment
|
||||
|
||||
|
||||
FIXME: par manque de caching, le bodystructure du message est
|
||||
redemandé pour accéder aux headers de cette pièce jointe.
|
||||
|
||||
:param request: a ``Request`` object
|
||||
:param folder
|
||||
"""
|
||||
mbox = request.GET.get("mbox", None)
|
||||
mailid = request.GET.get("mailid", None)
|
||||
pnum = request.GET.get("partnumber", None)
|
||||
if not mbox or not mailid or not pnum:
|
||||
raise WebmailError(_("Invalid request"))
|
||||
|
||||
|
||||
headers = {"Content-Type" : "text/plain",
|
||||
"Content-Transfer-Encoding" : None}
|
||||
imapc = get_imapconnector(request)
|
||||
@@ -51,7 +51,7 @@ def getattachment(request):
|
||||
resp["Content-Disposition"] = cd
|
||||
resp["Content-Length"] = partdef["size"]
|
||||
return resp
|
||||
|
||||
|
||||
@login_required
|
||||
@needs_mailbox()
|
||||
def move(request):
|
||||
@@ -115,17 +115,17 @@ def compact(request, name):
|
||||
@login_required
|
||||
@needs_mailbox()
|
||||
def newfolder(request, tplname="webmail/folder.html"):
|
||||
mbc = IMAPconnector(user=request.user.username,
|
||||
mbc = IMAPconnector(user=request.user.username,
|
||||
password=request.session["password"])
|
||||
ctx = {"title" : _("Create a new mailbox"),
|
||||
"formid" : "mboxform",
|
||||
"action" : reverse(newfolder),
|
||||
"action_label" : _("Create"),
|
||||
"action_classes" : "submit",
|
||||
"withunseen" : False,
|
||||
"selectonly" : True}
|
||||
ctx = {"title": _("Create a new mailbox"),
|
||||
"formid": "mboxform",
|
||||
"action": reverse(newfolder),
|
||||
"action_label": _("Create"),
|
||||
"action_classes": "submit",
|
||||
"withunseen": False,
|
||||
"selectonly": True,
|
||||
"mboxes": mbc.getmboxes(request.user)}
|
||||
|
||||
ctx["mboxes"] = mbc.getmboxes(request.user)
|
||||
if request.method == "POST":
|
||||
form = FolderForm(request.POST)
|
||||
if form.is_valid():
|
||||
@@ -134,11 +134,11 @@ def newfolder(request, tplname="webmail/folder.html"):
|
||||
return ajax_simple_response(dict(
|
||||
status="ok", respmsg=_("Mailbox created"), newmb=form.cleaned_data["name"], parent=pf
|
||||
))
|
||||
|
||||
|
||||
ctx["form"] = form
|
||||
ctx["selected"] = None
|
||||
return ajax_response(request, status="ko", template=tplname, **ctx)
|
||||
|
||||
|
||||
ctx["form"] = FolderForm()
|
||||
ctx["selected"] = None
|
||||
return _render(request, tplname, ctx)
|
||||
@@ -146,7 +146,7 @@ def newfolder(request, tplname="webmail/folder.html"):
|
||||
@login_required
|
||||
@needs_mailbox()
|
||||
def editfolder(request, tplname="webmail/folder.html"):
|
||||
mbc = IMAPconnector(user=request.user.username,
|
||||
mbc = IMAPconnector(user=request.user.username,
|
||||
password=request.session["password"])
|
||||
ctx = {"title" : _("Edit mailbox"),
|
||||
"formid" : "mboxform",
|
||||
@@ -197,7 +197,7 @@ def delfolder(request):
|
||||
name = request.GET.get("name", None)
|
||||
if name is None:
|
||||
raise WebmailError(_("Bad request"))
|
||||
mbc = IMAPconnector(user=request.user.username,
|
||||
mbc = IMAPconnector(user=request.user.username,
|
||||
password=request.session["password"])
|
||||
mbc.delete_folder(name)
|
||||
if request.session.has_key("mbox"):
|
||||
@@ -217,7 +217,7 @@ def attachments(request, tplname="webmail/attachments.html"):
|
||||
fobj = request.FILES["attachment"]
|
||||
tmpname = save_attachment(fobj)
|
||||
request.session["compose_mail"]["attachments"] \
|
||||
+= [{"fname" : str(fobj),
|
||||
+= [{"fname" : str(fobj),
|
||||
"content-type" : fobj.content_type,
|
||||
"size" : fobj.size,
|
||||
"tmpname" : os.path.basename(tmpname)}]
|
||||
@@ -225,7 +225,7 @@ def attachments(request, tplname="webmail/attachments.html"):
|
||||
return _render(request, "webmail/upload_done.html", {
|
||||
"status" : "ok", "fname" : request.FILES["attachment"],
|
||||
"tmpname" : os.path.basename(tmpname)
|
||||
});
|
||||
})
|
||||
except WebmailError, inst:
|
||||
error = _("Failed to save attachment: ") + str(inst)
|
||||
|
||||
@@ -234,7 +234,7 @@ def attachments(request, tplname="webmail/attachments.html"):
|
||||
% parameters.get_admin("MAX_ATTACHMENT_SIZE"))
|
||||
return _render(request, "webmail/upload_done.html", {
|
||||
"status" : "ko", "error" : error
|
||||
});
|
||||
})
|
||||
ctx = {
|
||||
"title" : _("Attachments"),
|
||||
"formid" : "uploadfile",
|
||||
@@ -274,7 +274,7 @@ def render_mboxes_list(request, imapc):
|
||||
"""Return the HTML representation of a mailboxes list
|
||||
|
||||
:param request: a ``Request`` object
|
||||
:param imap: an ``IMAPconnector` object
|
||||
:param imapc: an ``IMAPconnector` object
|
||||
:return: a string
|
||||
"""
|
||||
curmbox = request.session.get("mbox", "INBOX")
|
||||
@@ -287,7 +287,7 @@ def render_mboxes_list(request, imapc):
|
||||
def set_nav_params(request):
|
||||
if not request.session.has_key("navparams"):
|
||||
request.session["navparams"] = {}
|
||||
|
||||
|
||||
request.session["pageid"] = \
|
||||
int(request.GET.get("page", 1))
|
||||
if not request.GET.get("order", False):
|
||||
@@ -320,7 +320,7 @@ def listmailbox(request, defmailbox="INBOX", update_session=True):
|
||||
|
||||
lst = ImapListing(request.user, request.session["password"],
|
||||
baseurl="?action=listmailbox&mbox=%s&" % mbox,
|
||||
folder=mbox,
|
||||
folder=mbox,
|
||||
elems_per_page=int(parameters.get_user(request.user, "MESSAGES_PER_PAGE")),
|
||||
**request.session["navparams"])
|
||||
return lst.render(request, request.session["pageid"])
|
||||
@@ -348,7 +348,7 @@ def render_compose(request, form, posturl, email=None, insert_signature=False):
|
||||
attachments = request.session["compose_mail"]["attachments"]
|
||||
if len(attachments):
|
||||
short_att_list = "(%s)" \
|
||||
% ", ".join(map(lambda att: att["fname"],
|
||||
% ", ".join(map(lambda att: att["fname"],
|
||||
attachments[:2] + [{"fname" : "..."}] \
|
||||
if len(attachments) > 2 else attachments))
|
||||
else:
|
||||
@@ -412,7 +412,7 @@ def getmailcontent(request):
|
||||
raise WebmailError(_("Invalid request"))
|
||||
email = ImapEmail(mbox, mailid, request, links=int(request.GET["links"]))
|
||||
return _render(request, "common/viewmail.html", {
|
||||
"headers" : email.render_headers(folder=mbox, mail_id=mailid),
|
||||
"headers" : email.render_headers(folder=mbox, mail_id=mailid),
|
||||
"folder" : mbox, "imapid" : mailid, "mailbody" : email.body if email.body else ""
|
||||
})
|
||||
|
||||
@@ -484,7 +484,7 @@ def index(request):
|
||||
if action is not None:
|
||||
if not globals().has_key(action):
|
||||
raise WebmailError(_("Undefined action"))
|
||||
response = globals()[action](request)
|
||||
response = globals()[action](request)
|
||||
else:
|
||||
if request.is_ajax():
|
||||
raise WebmailError(_("Bad request"))
|
||||
@@ -499,11 +499,11 @@ def index(request):
|
||||
response["refreshrate"] = \
|
||||
int(parameters.get_user(request.user, "REFRESH_INTERVAL"))
|
||||
response["quota"] = ImapListing.computequota(imapc)
|
||||
response["ro_mboxes"] = ["INBOX", "Junk",
|
||||
response["ro_mboxes"] = ["INBOX", "Junk",
|
||||
parameters.get_user(request.user, "SENT_FOLDER"),
|
||||
parameters.get_user(request.user, "TRASH_FOLDER"),
|
||||
parameters.get_user(request.user, "DRAFTS_FOLDER")]
|
||||
|
||||
|
||||
return _render(request, "webmail/index.html", response)
|
||||
|
||||
if action in ["reply", "forward"]:
|
||||
|
||||
@@ -1 +1,290 @@
|
||||
[{"pk": 1, "model": "lib.parameter", "fields": {"name": "admin.STORAGE_PATH", "value": "/srv/vmail"}}, {"pk": 2, "model": "lib.parameter", "fields": {"name": "admin.PASSWORD_SCHEME", "value": "crypt"}}, {"pk": 3, "model": "lib.parameter", "fields": {"name": "admin.ITEMS_PER_PAGE", "value": "30"}}, {"pk": 4, "model": "lib.parameter", "fields": {"name": "general.DEFAULT_TOP_REDIRECTION", "value": "userprefs"}}, {"pk": 5, "model": "lib.parameter", "fields": {"name": "admin.CREATE_DIRECTORIES", "value": "yes"}}, {"pk": 6, "model": "lib.parameter", "fields": {"name": "auth.SECRET_KEY", "value": "abcdefghijklmnop"}}, {"pk": 7, "model": "lib.parameter", "fields": {"name": "admin.MAILBOX_TYPE", "value": "maildir"}}, {"pk": 8, "model": "lib.parameter", "fields": {"name": "admin.AUTHENTICATION_TYPE", "value": "local"}}, {"pk": 9, "model": "lib.parameter", "fields": {"name": "admin.VIRTUAL_UID", "value": "vmail"}}, {"pk": 10, "model": "lib.parameter", "fields": {"name": "admin.MAILDIR_ROOT", "value": ".maildir"}}, {"pk": 11, "model": "lib.parameter", "fields": {"name": "admin.VIRTUAL_GID", "value": "vmail"}}, {"pk": 12, "model": "lib.parameter", "fields": {"name": "stats.IMG_ROOTDIR", "value": "/srv/www/modoboa/media/stats"}}, {"pk": 13, "model": "lib.parameter", "fields": {"name": "amavis_quarantine.USER_CAN_RELEASE", "value": "no"}}, {"pk": 14, "model": "lib.parameter", "fields": {"name": "amavis_quarantine.CHECK_REQUESTS_INTERVAL", "value": "30"}}, {"pk": 15, "model": "lib.parameter", "fields": {"name": "amavis_quarantine.AM_PDP_PORT", "value": "9998"}}, {"pk": 16, "model": "lib.parameter", "fields": {"name": "webmail.IMAP_SECURED", "value": "no"}}, {"pk": 17, "model": "lib.parameter", "fields": {"name": "postfix_autoreply.AUTOREPLIES_TIMEOUT", "value": "86400"}}, {"pk": 18, "model": "lib.parameter", "fields": {"name": "sievefilters.AUTHENTICATION_MECH", "value": "PLAIN"}}, {"pk": 19, "model": "lib.parameter", "fields": {"name": "amavis_quarantine.AM_PDP_SOCKET", "value": "/var/amavis/amavisd.sock"}}, {"pk": 20, "model": "lib.parameter", "fields": {"name": "amavis_quarantine.AM_PDP_MODE", "value": "inet"}}, {"pk": 21, "model": "lib.parameter", "fields": {"name": "amavis_quarantine.SELF_SERVICE", "value": "no"}}, {"pk": 22, "model": "lib.parameter", "fields": {"name": "webmail.IMAP_PORT", "value": "143"}}, {"pk": 23, "model": "lib.parameter", "fields": {"name": "webmail.SMTP_SECURED_MODE", "value": "none"}}, {"pk": 24, "model": "lib.parameter", "fields": {"name": "sievefilters.SERVER", "value": "127.0.0.1"}}, {"pk": 25, "model": "lib.parameter", "fields": {"name": "webmail.SMTP_SERVER", "value": "127.0.0.1"}}, {"pk": 26, "model": "lib.parameter", "fields": {"name": "webmail.SMTP_AUTHENTICATION", "value": "no"}}, {"pk": 27, "model": "lib.parameter", "fields": {"name": "webmail.MAX_ATTACHMENT_SIZE", "value": "512K"}}, {"pk": 28, "model": "lib.parameter", "fields": {"name": "stats.RRD_ROOTDIR", "value": "/srv/www/modoboa/tmp"}}, {"pk": 29, "model": "lib.parameter", "fields": {"name": "amavis_quarantine.RELEASED_MSGS_CLEANUP", "value": "no"}}, {"pk": 30, "model": "lib.parameter", "fields": {"name": "amavis_quarantine.MAX_MESSAGES_AGE", "value": "14"}}, {"pk": 31, "model": "lib.parameter", "fields": {"name": "webmail.SMTP_PORT", "value": "25"}}, {"pk": 33, "model": "lib.parameter", "fields": {"name": "webmail.IMAP_SERVER", "value": "127.0.0.1"}}, {"pk": 34, "model": "lib.parameter", "fields": {"name": "sievefilters.STARTTLS", "value": "yes"}}, {"pk": 35, "model": "lib.parameter", "fields": {"name": "sievefilters.PORT", "value": "2000"}}, {"pk": 36, "model": "lib.parameter", "fields": {"name": "amavis_quarantine.AM_PDP_HOST", "value": "localhost"}}, {"pk": 37, "model": "lib.parameter", "fields": {"name": "stats.LOGFILE", "value": "/var/log/mail.log"}}]
|
||||
[
|
||||
{
|
||||
"pk": 1,
|
||||
"model": "lib.parameter",
|
||||
"fields": {
|
||||
"name": "admin.STORAGE_PATH",
|
||||
"value": "/srv/vmail"
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": 2,
|
||||
"model": "lib.parameter",
|
||||
"fields": {
|
||||
"name": "admin.PASSWORD_SCHEME",
|
||||
"value": "crypt"
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": 3,
|
||||
"model": "lib.parameter",
|
||||
"fields": {
|
||||
"name": "admin.ITEMS_PER_PAGE",
|
||||
"value": "30"
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": 4,
|
||||
"model": "lib.parameter",
|
||||
"fields": {
|
||||
"name": "general.DEFAULT_TOP_REDIRECTION",
|
||||
"value": "userprefs"
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": 5,
|
||||
"model": "lib.parameter",
|
||||
"fields": {
|
||||
"name": "admin.CREATE_DIRECTORIES",
|
||||
"value": "yes"
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": 6,
|
||||
"model": "lib.parameter",
|
||||
"fields": {
|
||||
"name": "auth.SECRET_KEY",
|
||||
"value": "abcdefghijklmnop"
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": 7,
|
||||
"model": "lib.parameter",
|
||||
"fields": {
|
||||
"name": "admin.MAILBOX_TYPE",
|
||||
"value": "maildir"
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": 8,
|
||||
"model": "lib.parameter",
|
||||
"fields": {
|
||||
"name": "admin.AUTHENTICATION_TYPE",
|
||||
"value": "local"
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": 9,
|
||||
"model": "lib.parameter",
|
||||
"fields": {
|
||||
"name": "admin.VIRTUAL_UID",
|
||||
"value": "vmail"
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": 10,
|
||||
"model": "lib.parameter",
|
||||
"fields": {
|
||||
"name": "admin.MAILDIR_ROOT",
|
||||
"value": ".maildir"
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": 11,
|
||||
"model": "lib.parameter",
|
||||
"fields": {
|
||||
"name": "admin.VIRTUAL_GID",
|
||||
"value": "vmail"
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": 12,
|
||||
"model": "lib.parameter",
|
||||
"fields": {
|
||||
"name": "stats.IMG_ROOTDIR",
|
||||
"value": "/srv/www/modoboa/media/stats"
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": 13,
|
||||
"model": "lib.parameter",
|
||||
"fields": {
|
||||
"name": "amavis_quarantine.USER_CAN_RELEASE",
|
||||
"value": "no"
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": 14,
|
||||
"model": "lib.parameter",
|
||||
"fields": {
|
||||
"name": "amavis_quarantine.CHECK_REQUESTS_INTERVAL",
|
||||
"value": "30"
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": 15,
|
||||
"model": "lib.parameter",
|
||||
"fields": {
|
||||
"name": "amavis_quarantine.AM_PDP_PORT",
|
||||
"value": "9998"
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": 16,
|
||||
"model": "lib.parameter",
|
||||
"fields": {
|
||||
"name": "webmail.IMAP_SECURED",
|
||||
"value": "no"
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": 17,
|
||||
"model": "lib.parameter",
|
||||
"fields": {
|
||||
"name": "postfix_autoreply.AUTOREPLIES_TIMEOUT",
|
||||
"value": "86400"
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": 18,
|
||||
"model": "lib.parameter",
|
||||
"fields": {
|
||||
"name": "sievefilters.AUTHENTICATION_MECH",
|
||||
"value": "PLAIN"
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": 19,
|
||||
"model": "lib.parameter",
|
||||
"fields": {
|
||||
"name": "amavis_quarantine.AM_PDP_SOCKET",
|
||||
"value": "/var/amavis/amavisd.sock"
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": 20,
|
||||
"model": "lib.parameter",
|
||||
"fields": {
|
||||
"name": "amavis_quarantine.AM_PDP_MODE",
|
||||
"value": "inet"
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": 21,
|
||||
"model": "lib.parameter",
|
||||
"fields": {
|
||||
"name": "amavis_quarantine.SELF_SERVICE",
|
||||
"value": "no"
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": 22,
|
||||
"model": "lib.parameter",
|
||||
"fields": {
|
||||
"name": "webmail.IMAP_PORT",
|
||||
"value": "143"
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": 23,
|
||||
"model": "lib.parameter",
|
||||
"fields": {
|
||||
"name": "webmail.SMTP_SECURED_MODE",
|
||||
"value": "none"
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": 24,
|
||||
"model": "lib.parameter",
|
||||
"fields": {
|
||||
"name": "sievefilters.SERVER",
|
||||
"value": "127.0.0.1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": 25,
|
||||
"model": "lib.parameter",
|
||||
"fields": {
|
||||
"name": "webmail.SMTP_SERVER",
|
||||
"value": "127.0.0.1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": 26,
|
||||
"model": "lib.parameter",
|
||||
"fields": {
|
||||
"name": "webmail.SMTP_AUTHENTICATION",
|
||||
"value": "no"
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": 27,
|
||||
"model": "lib.parameter",
|
||||
"fields": {
|
||||
"name": "webmail.MAX_ATTACHMENT_SIZE",
|
||||
"value": "512K"
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": 28,
|
||||
"model": "lib.parameter",
|
||||
"fields": {
|
||||
"name": "stats.RRD_ROOTDIR",
|
||||
"value": "/srv/www/modoboa/tmp"
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": 29,
|
||||
"model": "lib.parameter",
|
||||
"fields": {
|
||||
"name": "amavis_quarantine.RELEASED_MSGS_CLEANUP",
|
||||
"value": "no"
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": 30,
|
||||
"model": "lib.parameter",
|
||||
"fields": {
|
||||
"name": "amavis_quarantine.MAX_MESSAGES_AGE",
|
||||
"value": "14"
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": 31,
|
||||
"model": "lib.parameter",
|
||||
"fields": {
|
||||
"name": "webmail.SMTP_PORT",
|
||||
"value": "25"
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": 33,
|
||||
"model": "lib.parameter",
|
||||
"fields": {
|
||||
"name": "webmail.IMAP_SERVER",
|
||||
"value": "127.0.0.1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": 34,
|
||||
"model": "lib.parameter",
|
||||
"fields": {
|
||||
"name": "sievefilters.STARTTLS",
|
||||
"value": "yes"
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": 35,
|
||||
"model": "lib.parameter",
|
||||
"fields": {
|
||||
"name": "sievefilters.PORT",
|
||||
"value": "2000"
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": 36,
|
||||
"model": "lib.parameter",
|
||||
"fields": {
|
||||
"name": "amavis_quarantine.AM_PDP_HOST",
|
||||
"value": "localhost"
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": 37,
|
||||
"model": "lib.parameter",
|
||||
"fields": {
|
||||
"name": "stats.LOGFILE",
|
||||
"value": "/var/log/mail.log"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@@ -1,10 +1,4 @@
|
||||
# coding: utf-8
|
||||
|
||||
import string
|
||||
import inspect
|
||||
import re
|
||||
import copy
|
||||
|
||||
"""
|
||||
This interface provides a simple way to declare and store parameters
|
||||
in Modoboa's database.
|
||||
@@ -15,6 +9,10 @@ will be available and modifiable directly from the web interface.
|
||||
Only super users will be able to access this part of the web interface.
|
||||
"""
|
||||
|
||||
import inspect
|
||||
import re
|
||||
import copy
|
||||
|
||||
_params = {}
|
||||
_params_order = {}
|
||||
_levels = {'A' : 'admin', 'U' : 'user'}
|
||||
@@ -57,7 +55,7 @@ def register_app(app=None, aparams_opts=None, uparams_opts=None):
|
||||
_params[app]['options']['A'] = aparams_opts
|
||||
if uparams_opts:
|
||||
_params[app]['options']['U'] = uparams_opts
|
||||
|
||||
|
||||
def unregister_app(app):
|
||||
"""Unregister an application
|
||||
|
||||
@@ -86,7 +84,7 @@ def __register(app, level, name, **kwargs):
|
||||
:param name: the application's name
|
||||
:param level: the level this parameter is available from
|
||||
:param name: the parameter's name
|
||||
"""
|
||||
"""
|
||||
if not app in _params.keys():
|
||||
register_app(app)
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ As the two products do not share the same schema, some informations
|
||||
will be lost on the new database. Here is the list:
|
||||
* Description, transport and backup MX for domains
|
||||
* Logs
|
||||
* Fetchmail table
|
||||
* Fetchmail table
|
||||
|
||||
Mailboxes organisation on the filesystem will change. PostfixAdmin
|
||||
uses the following layout::
|
||||
@@ -42,7 +42,6 @@ compatible with PostfixAdmin ``md5crypt`` algorithm...
|
||||
|
||||
"""
|
||||
import os, sys
|
||||
from django.conf import settings
|
||||
from django.db.utils import ConnectionDoesNotExist
|
||||
from django.db.models import Q
|
||||
from django.contrib.auth.models import Group
|
||||
@@ -120,7 +119,7 @@ def migrate_mailboxes(domain, options):
|
||||
new_mb.dates = migrate_dates(old_mb)
|
||||
if old_mb.quota:
|
||||
new_mb.quota = old_mb.quota / 1024000
|
||||
|
||||
|
||||
new_mb.path = "%s/" % old_mb.local_part
|
||||
if options.rename_dirs:
|
||||
oldpath = os.path.join(options.mboxes_path, domain.name, old_mb.maildir)
|
||||
@@ -131,7 +130,7 @@ def migrate_mailboxes(domain, options):
|
||||
sys.exit(1)
|
||||
|
||||
new_mb.save(name=old_mb.name, password=old_mb.password, using=options.to)
|
||||
|
||||
|
||||
|
||||
def migrate_domain(old_dom, options):
|
||||
print "Migrating domain %s" % old_dom.domain
|
||||
@@ -201,9 +200,9 @@ if __name__ == "__main__":
|
||||
help="Rename mailbox directories (default is no)")
|
||||
parser.add_option("-p", "--mboxes-path", default=None,
|
||||
help="Path where directories are stored on the filesystem (used only if --rename-dirs)")
|
||||
|
||||
|
||||
options, args = parser.parse_args()
|
||||
|
||||
|
||||
if options.rename_dirs and options.mboxes_path is None:
|
||||
print "Error: you must provide the --mboxes-path option"
|
||||
sys.exit(1)
|
||||
@@ -212,7 +211,3 @@ if __name__ == "__main__":
|
||||
do_migration(options)
|
||||
except ConnectionDoesNotExist, e:
|
||||
print e
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# coding: utf-8
|
||||
# This is an auto-generated Django model module.
|
||||
# You'll have to do the following manually to clean this up:
|
||||
# * Rearrange models' order
|
||||
@@ -15,10 +16,12 @@ class Admin(models.Model):
|
||||
created = models.DateTimeField()
|
||||
modified = models.DateTimeField()
|
||||
active = models.IntegerField()
|
||||
|
||||
class Meta:
|
||||
db_table = u'admin'
|
||||
app_label = 'pfxadmin_migrate'
|
||||
managed = False
|
||||
managed = False
|
||||
|
||||
|
||||
class Alias(models.Model):
|
||||
address = models.CharField(max_length=765, primary_key=True)
|
||||
@@ -27,10 +30,12 @@ class Alias(models.Model):
|
||||
created = models.DateTimeField()
|
||||
modified = models.DateTimeField()
|
||||
active = models.IntegerField()
|
||||
|
||||
class Meta:
|
||||
db_table = u'alias'
|
||||
app_label = 'pfxadmin_migrate'
|
||||
managed = False
|
||||
managed = False
|
||||
|
||||
|
||||
class AliasDomain(models.Model):
|
||||
alias_domain = models.CharField(max_length=765, primary_key=True)
|
||||
@@ -38,19 +43,23 @@ class AliasDomain(models.Model):
|
||||
created = models.DateTimeField()
|
||||
modified = models.DateTimeField()
|
||||
active = models.IntegerField()
|
||||
|
||||
class Meta:
|
||||
db_table = u'alias_domain'
|
||||
app_label = 'pfxadmin_migrate'
|
||||
managed = False
|
||||
managed = False
|
||||
|
||||
|
||||
class Config(models.Model):
|
||||
id = models.IntegerField(primary_key=True)
|
||||
name = models.CharField(unique=True, max_length=60)
|
||||
value = models.CharField(max_length=60)
|
||||
|
||||
class Meta:
|
||||
db_table = u'config'
|
||||
app_label = 'pfxadmin_migrate'
|
||||
managed = False
|
||||
managed = False
|
||||
|
||||
|
||||
class Domain(models.Model):
|
||||
domain = models.CharField(max_length=765, primary_key=True)
|
||||
@@ -64,20 +73,24 @@ class Domain(models.Model):
|
||||
created = models.DateTimeField()
|
||||
modified = models.DateTimeField()
|
||||
active = models.IntegerField()
|
||||
|
||||
class Meta:
|
||||
db_table = u'domain'
|
||||
app_label = 'pfxadmin_migrate'
|
||||
managed = False
|
||||
managed = False
|
||||
|
||||
|
||||
class DomainAdmins(models.Model):
|
||||
username = models.CharField(max_length=765)
|
||||
domain = models.CharField(max_length=765)
|
||||
created = models.DateTimeField(primary_key=True)
|
||||
active = models.IntegerField()
|
||||
|
||||
class Meta:
|
||||
db_table = u'domain_admins'
|
||||
app_label = 'pfxadmin_migrate'
|
||||
managed = False
|
||||
managed = False
|
||||
|
||||
|
||||
class Fetchmail(models.Model):
|
||||
id = models.IntegerField(primary_key=True)
|
||||
@@ -96,10 +109,12 @@ class Fetchmail(models.Model):
|
||||
returned_text = models.TextField(blank=True)
|
||||
mda = models.CharField(max_length=765)
|
||||
date = models.DateTimeField()
|
||||
|
||||
class Meta:
|
||||
db_table = u'fetchmail'
|
||||
app_label = 'pfxadmin_migrate'
|
||||
managed = False
|
||||
managed = False
|
||||
|
||||
|
||||
class Log(models.Model):
|
||||
timestamp = models.DateTimeField()
|
||||
@@ -107,10 +122,12 @@ class Log(models.Model):
|
||||
domain = models.CharField(max_length=765)
|
||||
action = models.CharField(max_length=765)
|
||||
data = models.TextField()
|
||||
|
||||
class Meta:
|
||||
db_table = u'log'
|
||||
app_label = 'pfxadmin_migrate'
|
||||
managed = False
|
||||
managed = False
|
||||
|
||||
|
||||
class Mailbox(models.Model):
|
||||
username = models.CharField(max_length=765, primary_key=True)
|
||||
@@ -123,28 +140,34 @@ class Mailbox(models.Model):
|
||||
created = models.DateTimeField()
|
||||
modified = models.DateTimeField()
|
||||
active = models.IntegerField()
|
||||
|
||||
class Meta:
|
||||
db_table = u'mailbox'
|
||||
app_label = 'pfxadmin_migrate'
|
||||
managed = False
|
||||
managed = False
|
||||
|
||||
|
||||
class Quota(models.Model):
|
||||
username = models.CharField(max_length=765, primary_key=True)
|
||||
path = models.CharField(max_length=300, primary_key=True)
|
||||
current = models.BigIntegerField(null=True, blank=True)
|
||||
|
||||
class Meta:
|
||||
db_table = u'quota'
|
||||
app_label = 'pfxadmin_migrate'
|
||||
managed = False
|
||||
managed = False
|
||||
|
||||
|
||||
class Quota2(models.Model):
|
||||
username = models.CharField(max_length=300, primary_key=True)
|
||||
bytes = models.BigIntegerField()
|
||||
messages = models.IntegerField()
|
||||
|
||||
class Meta:
|
||||
db_table = u'quota2'
|
||||
app_label = 'pfxadmin_migrate'
|
||||
managed = False
|
||||
managed = False
|
||||
|
||||
|
||||
class Vacation(models.Model):
|
||||
email = models.CharField(max_length=765)
|
||||
@@ -154,16 +177,19 @@ class Vacation(models.Model):
|
||||
domain = models.CharField(max_length=765)
|
||||
created = models.DateTimeField()
|
||||
active = models.IntegerField()
|
||||
|
||||
class Meta:
|
||||
db_table = u'vacation'
|
||||
app_label = 'pfxadmin_migrate'
|
||||
managed = False
|
||||
managed = False
|
||||
|
||||
|
||||
class VacationNotification(models.Model):
|
||||
on_vacation = models.ForeignKey(Vacation, db_column='on_vacation')
|
||||
notified = models.CharField(max_length=765, primary_key=True)
|
||||
notified_at = models.DateTimeField()
|
||||
|
||||
class Meta:
|
||||
db_table = u'vacation_notification'
|
||||
app_label = 'pfxadmin_migrate'
|
||||
managed = False
|
||||
managed = False
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
# coding: utf-8
|
||||
|
||||
from modoboa.lib import parameters, events
|
||||
from django.utils.translation import ugettext_lazy
|
||||
from modoboa.lib import parameters
|
||||
|
||||
parameters.register_user("LANG", type="list", deflt="en",
|
||||
parameters.register_user("LANG", type="list", deflt="en",
|
||||
label=ugettext_lazy("Prefered language"),
|
||||
values=[("de", "deutsch"), ("en", "english"),
|
||||
("es", "español"), ("fr", "français"),
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
# coding: utf-8
|
||||
from django import forms
|
||||
from modoboa.admin.models import User, Domain, Mailbox
|
||||
from django.utils.translation import ugettext as _, ugettext_lazy
|
||||
|
||||
from modoboa.admin.models import User, Domain
|
||||
from modoboa.lib.emailutils import split_mailbox
|
||||
from modoboa.lib import parameters
|
||||
|
||||
|
||||
class BadDestination(Exception):
|
||||
pass
|
||||
|
||||
@@ -25,7 +28,7 @@ class ProfileForm(forms.ModelForm):
|
||||
del self.fields["oldpassword"]
|
||||
del self.fields["newpassword"]
|
||||
del self.fields["confirmation"]
|
||||
|
||||
|
||||
def clean_oldpassword(self):
|
||||
if self.cleaned_data["oldpassword"] == "":
|
||||
return self.cleaned_data["oldpassword"]
|
||||
@@ -53,13 +56,13 @@ class ProfileForm(forms.ModelForm):
|
||||
|
||||
class ForwardForm(forms.Form):
|
||||
dest = forms.CharField(
|
||||
label=ugettext_lazy("Recipient(s)"),
|
||||
label=ugettext_lazy("Recipient(s)"),
|
||||
widget=forms.Textarea,
|
||||
required=False,
|
||||
help_text=ugettext_lazy("Indicate one or more recipients separated by a ','")
|
||||
)
|
||||
keepcopies = forms.BooleanField(
|
||||
label=ugettext_lazy("Keep local copies"),
|
||||
label=ugettext_lazy("Keep local copies"),
|
||||
required=False,
|
||||
help_text=ugettext_lazy("Forward messages and store copies into your local mailbox")
|
||||
)
|
||||
@@ -79,4 +82,4 @@ class ForwardForm(forms.Form):
|
||||
self.dests += [d]
|
||||
else:
|
||||
raise BadDestination(_("You can't define a forward to a local destination. Please ask your administrator to create an alias instead."))
|
||||
|
||||
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
# coding: utf-8
|
||||
from django import template
|
||||
from django.template.loader import render_to_string
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.core.urlresolvers import reverse
|
||||
from modoboa import userprefs
|
||||
from modoboa.lib import events
|
||||
from modoboa.lib.webutils import static_url
|
||||
|
||||
register = template.Library()
|
||||
|
||||
@@ -29,7 +28,7 @@ def uprefs_menu(selection, user):
|
||||
entries += events.raiseQueryEvent("UserMenuDisplay", "uprefs_menu", user)
|
||||
entries = sorted(entries, key=lambda e: e["label"])
|
||||
return render_to_string('common/menu.html', {
|
||||
"entries" : entries,
|
||||
"entries" : entries,
|
||||
"css" : "nav nav-list",
|
||||
"selection" : selection,
|
||||
"user" : user
|
||||
@@ -63,5 +62,5 @@ def user_menu(user, selection):
|
||||
@register.simple_tag
|
||||
def loadextmenu(selection, user):
|
||||
menu = events.raiseQueryEvent("UserMenuDisplay", "top_menu", user)
|
||||
return render_to_string('common/menulist.html',
|
||||
return render_to_string('common/menulist.html',
|
||||
{"selection" : selection, "entries" : menu, "user" : user})
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
from django.conf.urls.defaults import *
|
||||
# coding: utf-8
|
||||
from django.conf.urls.defaults import patterns, url
|
||||
from modoboa.lib import events
|
||||
|
||||
urlpatterns = patterns('modoboa.userprefs.views',
|
||||
|
||||
@@ -1,19 +1,14 @@
|
||||
# coding: utf-8
|
||||
from django.shortcuts import render
|
||||
from django.template.loader import render_to_string
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.http import HttpResponseRedirect
|
||||
from django.contrib.auth.decorators \
|
||||
import login_required, user_passes_test
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.decorators import login_required, user_passes_test
|
||||
from django.utils.translation import ugettext as _
|
||||
from modoboa.lib import parameters, events
|
||||
from modoboa.lib.exceptions import ModoboaException
|
||||
from modoboa.lib.webutils import ajax_response, ajax_simple_response
|
||||
from forms import *
|
||||
from modoboa.admin.models import Mailbox, Alias
|
||||
from modoboa.admin.lib import AdminError
|
||||
from modoboa.auth.lib import encrypt
|
||||
from forms import ForwardForm, BadDestination, ProfileForm
|
||||
|
||||
@login_required
|
||||
def index(request, tplname="userprefs/index.html"):
|
||||
@@ -31,7 +26,7 @@ def forward(request, tplname='userprefs/forward.html'):
|
||||
except IndexError:
|
||||
raise ModoboaException(_("You need a mailbox in order to define a forward"))
|
||||
try:
|
||||
al = Alias.objects.get(address=mb.address,
|
||||
al = Alias.objects.get(address=mb.address,
|
||||
domain__name=mb.domain.name)
|
||||
except Alias.DoesNotExist:
|
||||
al = None
|
||||
@@ -55,7 +50,7 @@ def forward(request, tplname='userprefs/forward.html'):
|
||||
error = str(e)
|
||||
|
||||
return ajax_simple_response(dict(
|
||||
status="ko",
|
||||
status="ko",
|
||||
content=render_to_string(tplname, {"form" : form}),
|
||||
respmsg=error
|
||||
))
|
||||
@@ -70,7 +65,7 @@ def forward(request, tplname='userprefs/forward.html'):
|
||||
else:
|
||||
form.fields["keepcopies"].initial = True
|
||||
return ajax_simple_response({
|
||||
"status" : "ok",
|
||||
"status" : "ok",
|
||||
"content" : render_to_string(tplname, {
|
||||
"form" : form
|
||||
})
|
||||
@@ -92,13 +87,13 @@ def profile(request, tplname='userprefs/profile.html'):
|
||||
status="ok", respmsg=_("Profile updated")
|
||||
))
|
||||
return ajax_simple_response({
|
||||
"status" : "ko",
|
||||
"status" : "ko",
|
||||
"content" : render_to_string(tplname, {"form" : form})
|
||||
})
|
||||
|
||||
form = ProfileForm(update_password, instance=request.user)
|
||||
return ajax_simple_response({
|
||||
"status" : "ok",
|
||||
"status" : "ok",
|
||||
"content" : render_to_string(tplname, {
|
||||
"form" : form
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user