Merged in jpcaruana/modoboa/menage (pull request #2)

1st run througth the webmail module
This commit is contained in:
Antoine Nguyen
2013-02-08 13:36:25 +01:00
9 changed files with 130 additions and 133 deletions
+11 -11
View File
@@ -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()
+3 -4
View File
@@ -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'), ')']
+2 -1
View File
@@ -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()
+33 -33
View File
@@ -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
+29 -30
View File
@@ -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
+2 -3
View File
@@ -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)))
@@ -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) \
+5 -4
View File
@@ -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'),
)
)
+35 -35
View File
@@ -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"]: