mirror of
https://github.com/jwinterm/modoboa.git
synced 2026-10-18 05:51:26 +02:00
wip: Big webmail refactoring.
This commit is contained in:
@@ -7,6 +7,8 @@ class ComposeMailForm(forms.Form):
|
||||
cc = forms.CharField(label=_("Cc"), widget=forms.Textarea(), required=False)
|
||||
subject = forms.CharField(label=_("Subject"), max_length=255, required=False)
|
||||
|
||||
origmsgid = forms.CharField(widget=forms.HiddenInput(), required=False)
|
||||
|
||||
class FolderForm(forms.Form):
|
||||
name = forms.CharField()
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
"""
|
||||
import imaplib, ssl, email
|
||||
import re
|
||||
import time
|
||||
from functools import wraps
|
||||
from imapclient.response_parser import parse_fetch_response
|
||||
from modoboa.lib import parameters
|
||||
@@ -410,11 +411,12 @@ class IMAPconnector(object):
|
||||
"""
|
||||
self._add_flag(mbox, msgset, r'(\Seen)')
|
||||
|
||||
def msgforwarded(self, folder, imapid):
|
||||
self._add_flag(folder, imapid, '($Forwarded)')
|
||||
def msgforwarded(self, mailbox, mailid):
|
||||
self._add_flag(mailbox, mailid, '($Forwarded)')
|
||||
|
||||
def msg_answered(self, folder, imapid):
|
||||
self._add_flag(folder, imapid, r'(\Answered)')
|
||||
def msg_answered(self, mailbox, mailid):
|
||||
"""Add the \Answered flag to this email"""
|
||||
self._add_flag(mailbox, mailid, r'(\Answered)')
|
||||
|
||||
def move(self, msgset, oldmailbox, newmailbox):
|
||||
"""Move messages between mailboxes
|
||||
@@ -521,7 +523,7 @@ class IMAPconnector(object):
|
||||
result += [msg]
|
||||
return result
|
||||
|
||||
def fetchmail(self, mbox, mailid):
|
||||
def fetchmail(self, mbox, mailid, readonly=True, headers=None):
|
||||
"""Retrieve information about a specific message
|
||||
|
||||
Issue a FETCH command to retrieve a message's content from the
|
||||
@@ -532,10 +534,17 @@ class IMAPconnector(object):
|
||||
|
||||
:param mbox: the mailbox containing the message
|
||||
:param mailid: the message's unique id
|
||||
:param fmt: the desired content's format
|
||||
:param readonly:
|
||||
:param extraheaders:
|
||||
"""
|
||||
self.select_mailbox(mbox, False)
|
||||
data = self._cmd("FETCH", mailid, "(BODYSTRUCTURE BODY.PEEK[HEADER.FIELDS (DATE FROM TO CC SUBJECT)])")
|
||||
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,
|
||||
"(BODYSTRUCTURE %s[HEADER.FIELDS (%s)])" % (bcmd, " ".join(headers))
|
||||
)
|
||||
return data[int(mailid)]
|
||||
|
||||
def get_imapconnector(request):
|
||||
|
||||
+89
-50
@@ -1,4 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# coding: utf-8
|
||||
|
||||
import sys, os
|
||||
reload(sys)
|
||||
@@ -92,10 +92,16 @@ class IMAPheader(object):
|
||||
except ValueError:
|
||||
return value
|
||||
|
||||
@staticmethod
|
||||
def parse_message_id(value, **kwargs):
|
||||
return value.strip('\n')
|
||||
|
||||
@staticmethod
|
||||
def parse_subject(value, **kwargs):
|
||||
return decode(u2u_decode.u2u_decode(value))
|
||||
try:
|
||||
return decode(u2u_decode.u2u_decode(value))
|
||||
except UnicodeDecodeError:
|
||||
return value
|
||||
|
||||
class ImapListing(EmailListing):
|
||||
tpl = "webmail/index.html"
|
||||
@@ -148,24 +154,33 @@ class ImapListing(EmailListing):
|
||||
return ImapListing.computequota(self.mbc)
|
||||
|
||||
class ImapEmail(Email):
|
||||
headernames = [
|
||||
('Date', True),
|
||||
('From', True),
|
||||
('To', True),
|
||||
('Cc', True),
|
||||
('Subject', True),
|
||||
]
|
||||
|
||||
def __init__(self, mbox, mailid, request, dformat="DISPLAYMODE", addrfull=False,
|
||||
links=0):
|
||||
mformat = parameters.get_user(request.user, "DISPLAYMODE")
|
||||
dformat = parameters.get_user(request.user, dformat)
|
||||
self.dformat = parameters.get_user(request.user, dformat)
|
||||
|
||||
self.headers = []
|
||||
self.attachments = {}
|
||||
self.imapc = get_imapconnector(request)
|
||||
msg = self.imapc.fetchmail(mbox, mailid)
|
||||
msg = self.imapc.fetchmail(mbox, mailid, readonly=False,
|
||||
headers=self.headers_as_list)
|
||||
self.mbox = mbox
|
||||
self.mailid = mailid
|
||||
headers = msg['BODY[HEADER.FIELDS (DATE FROM TO CC SUBJECT)]']
|
||||
fallback_fmt = "html" if dformat == "plain" else "plain"
|
||||
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
|
||||
|
||||
mformat = dformat if self.bs.contents.has_key(dformat) else fallback_fmt
|
||||
mformat = self.dformat if self.bs.contents.has_key(self.dformat) else fallback_fmt
|
||||
|
||||
pnum = self.bs.contents[mformat]['pnum']
|
||||
data = self.imapc._cmd("FETCH", mailid, "(BODY.PEEK[%s])" % pnum)
|
||||
@@ -182,25 +197,34 @@ class ImapEmail(Email):
|
||||
getattr(self, "viewmail_%s" % mformat)(content, links=links)
|
||||
|
||||
msg = email.message_from_string(headers)
|
||||
fields = ["Subject", "From", "To", "Reply-To", "Cc", "Date"]
|
||||
for f in fields:
|
||||
label = f
|
||||
if not f in msg.keys():
|
||||
f = f.upper()
|
||||
if not f in msg.keys():
|
||||
for hdr in self.headernames:
|
||||
label = hdr[0]
|
||||
name = hdr[0]
|
||||
if not name in msg.keys():
|
||||
name = name.upper()
|
||||
if not name in msg.keys():
|
||||
continue
|
||||
try:
|
||||
key = re.sub("-", "_", f).lower()
|
||||
value = getattr(IMAPheader, "parse_%s" % key)(msg[f], full=addrfull)
|
||||
self.headers += [{"name" : label, "value" : value}]
|
||||
key = re.sub("-", "_", name).lower()
|
||||
value = getattr(IMAPheader, "parse_%s" % key)(msg[name], full=addrfull)
|
||||
except AttributeError:
|
||||
self.headers += [{"name" : label, "value" : msg[f]}]
|
||||
value = msg[name]
|
||||
if hdr[1]:
|
||||
self.headers += [{"name" : label, "value" : value}]
|
||||
try:
|
||||
label = re.sub("-", "_", label)
|
||||
setattr(self, label, value)
|
||||
except:
|
||||
pass
|
||||
|
||||
@property
|
||||
def headers_as_list(self):
|
||||
return map(lambda hdr: hdr[0].upper(), self.headernames)
|
||||
|
||||
@property
|
||||
def headers_as_text(self):
|
||||
return " ".join(map(lambda hdr: hdr[0].upper(), self.headernames))
|
||||
|
||||
def _find_content_charset(self, subtype):
|
||||
for pos, elem in enumerate(self.bs.contents[subtype]["params"]):
|
||||
if elem == "charset":
|
||||
@@ -273,26 +297,45 @@ class ImapEmail(Email):
|
||||
})
|
||||
return res
|
||||
|
||||
class ReplyModifier(ImapEmail):
|
||||
def __init__(self, msg, user, form, all=False, **kwargs):
|
||||
ImapEmail.__init__(self, msg, user, dformat="EDITOR", **kwargs)
|
||||
|
||||
self.textheader = "%s %s" % (self.From, _("wrote:"))
|
||||
class Modifier(ImapEmail):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(Modifier, self).__init__(*args, **kwargs)
|
||||
getattr(self, "_modify_%s" % self.dformat)()
|
||||
|
||||
form.fields["from_"].initial = user.username
|
||||
if not "Reply-To" in msg.keys():
|
||||
def _modify_plain(self):
|
||||
self.body = re.sub("</?pre>", "", self.body)
|
||||
|
||||
def _modify_html(self):
|
||||
pass
|
||||
|
||||
|
||||
class ReplyModifier(Modifier):
|
||||
headernames = ImapEmail.headernames + \
|
||||
[("Reply-To", True),
|
||||
("Message-ID", False)]
|
||||
|
||||
def __init__(self, mbox, mailid, request, form, **kwargs):
|
||||
super(ReplyModifier, self).__init__(
|
||||
mbox, mailid, request, dformat="EDITOR", **kwargs
|
||||
)
|
||||
|
||||
self.textheader = "%s %s" % (self.From, _("wrote:"))
|
||||
|
||||
form.fields["from_"].initial = request.user.username
|
||||
if hasattr(self, "Message_ID"):
|
||||
form.fields["origmsgid"].initial = self.Message_ID
|
||||
if not hasattr(self, "Reply_To"):
|
||||
form.fields["to"].initial = self.From
|
||||
else:
|
||||
form.fields["to"].initial = self.Reply_To
|
||||
if all:
|
||||
if all: # reply-all
|
||||
form.fields["cc"].initial = ""
|
||||
toparse = msg["To"].split(",")
|
||||
if "Cc" in msg.keys():
|
||||
toparse += msg["Cc"].split(",")
|
||||
toparse = self.To.split(",")
|
||||
if hasattr(self, 'Cc'):
|
||||
toparse += self.Cc.split(",")
|
||||
for addr in toparse:
|
||||
tmp = EmailAddress(addr)
|
||||
if tmp.address and tmp.address == user.username:
|
||||
if tmp.address and tmp.address == request.user.username:
|
||||
continue
|
||||
if form.fields["cc"].initial != "":
|
||||
form.fields["cc"].initial += ", "
|
||||
@@ -302,9 +345,9 @@ class ReplyModifier(ImapEmail):
|
||||
form.fields["subject"].initial = self.Subject
|
||||
else:
|
||||
form.fields["subject"].initial = "Re: %s" % self.Subject
|
||||
|
||||
|
||||
def _modify_plain(self):
|
||||
self.body = re.sub("</?pre>", "", self.body)
|
||||
super(ReplyModifier, self)._modify_plain()
|
||||
lines = self.body.split('\n')
|
||||
body = ""
|
||||
for l in lines:
|
||||
@@ -312,27 +355,26 @@ class ReplyModifier(ImapEmail):
|
||||
body += "\n"
|
||||
body += ">%s" % l
|
||||
self.body = body
|
||||
|
||||
def _modify_html(self):
|
||||
pass
|
||||
|
||||
class ForwardModifier(ImapEmail):
|
||||
def __init__(self, msg, user, form, **kwargs):
|
||||
ImapEmail.__init__(self, msg, user, dformat="EDITOR", **kwargs)
|
||||
|
||||
class ForwardModifier(Modifier):
|
||||
def __init__(self, mbox, mailid, request, form, **kwargs):
|
||||
super(ForwardModifier, self).__init__(
|
||||
mbox, mailid, request, dformat="EDITOR", **kwargs
|
||||
)
|
||||
|
||||
self._header(msg)
|
||||
form.fields["from_"].initial = user.username
|
||||
self._header()
|
||||
form.fields["from_"].initial = request.user.username
|
||||
form.fields["subject"].initial = "Fwd: %s" % self.Subject
|
||||
|
||||
def __getfunc(self, name):
|
||||
return getattr(self, "%s_%s" % (name, self.dformat))
|
||||
|
||||
def _header(self, msg):
|
||||
def _header(self):
|
||||
self.textheader = self.__getfunc("_header_begin")() + "\n"
|
||||
self.textheader += \
|
||||
self.__getfunc("_header_line")(_("Subject"), self.Subject) + "\n"
|
||||
self.textheader += \
|
||||
self.__getfunc("_header_line")(_("Date"), msg["Date"]) + "\n"
|
||||
self.__getfunc("_header_line")(_("Date"), self.Date) + "\n"
|
||||
for hdr in ["From", "To", "Reply-To"]:
|
||||
try:
|
||||
key = re.sub("-", "_", hdr)
|
||||
@@ -528,7 +570,7 @@ def create_mail_attachment(attdef):
|
||||
res.add_header("Content-Disposition", "attachment; filename='%s'" % attdef["fname"])
|
||||
return res
|
||||
|
||||
def send_mail(request, origmsg=None, posturl=None):
|
||||
def send_mail(request, posturl=None):
|
||||
"""Email verification and sending.
|
||||
|
||||
If the form does not present any error, a new MIME message is
|
||||
@@ -536,7 +578,6 @@ def send_mail(request, origmsg=None, posturl=None):
|
||||
SMTP server and the message is finally sent.
|
||||
|
||||
:param request: a Request object
|
||||
:param origmsg: the eventual original message (in case of a reply)
|
||||
:param posturl: the url to post the message form to
|
||||
:return: a 2-uple (True|False, HttpResponse)
|
||||
"""
|
||||
@@ -589,8 +630,8 @@ def send_mail(request, origmsg=None, posturl=None):
|
||||
msg["Message-ID"] = make_msgid()
|
||||
msg["User-Agent"] = "Modoboa"
|
||||
msg["Date"] = formatdate(time.time(), True)
|
||||
if origmsg and origmsg.has_key("Message-ID"):
|
||||
msg["References"] = msg["In-Reply-To"] = origmsg["Message-ID"]
|
||||
if form.cleaned_data.has_key("origmsgid"):
|
||||
msg["References"] = msg["In-Reply-To"] = form.cleaned_data["origmsgid"]
|
||||
rcpts = msg['To'].split(',')
|
||||
if form.cleaned_data["cc"] != "":
|
||||
msg["Cc"] = form.cleaned_data["cc"]
|
||||
@@ -621,16 +662,14 @@ def send_mail(request, origmsg=None, posturl=None):
|
||||
password=request.session["password"]).push_mail(sentfolder, msg)
|
||||
clean_attachments(request.session["compose_mail"]["attachments"])
|
||||
del request.session["compose_mail"]
|
||||
return True, ajax_simple_response(getctx("ok", url=get_current_url(request)))
|
||||
return True, dict(url=get_current_url(request))
|
||||
|
||||
listing = _render_to_string(request, "webmail/compose.html",
|
||||
{"form" : form, "noerrors" : True,
|
||||
"body" : request.POST["id_body"].strip(),
|
||||
"posturl" : posturl})
|
||||
error = _("Red fields are mandatories")
|
||||
return False, ajax_simple_response(
|
||||
getctx("ko", level=2, respmsg=error, listing=listing, editor=editormode)
|
||||
)
|
||||
return False, dict(status="ko", respmsg=error, listing=listing, editor=editormode)
|
||||
|
||||
class AttachmentUploadHandler(FileUploadHandler):
|
||||
"""
|
||||
|
||||
@@ -473,7 +473,7 @@ var Webmail = new Class({
|
||||
|
||||
//$$("a[name=back]").addEvent("click", this._listmailbox_loader);
|
||||
$$("a[name=reply]").addEvent("click", this.reply_loader);
|
||||
$$("a[name=replyall]").addEvent("click", this.replyall_loader);
|
||||
$$("a[name=replyall]").addEvent("click", this.reply_loader);
|
||||
$$("a[name=forward]").addEvent("click", this.forward_loader);
|
||||
$$("a[name=delete]").addEvent("click", function(event) {
|
||||
var lnk = event.target;
|
||||
@@ -504,18 +504,9 @@ var Webmail = new Class({
|
||||
* Loader of the 'reply' action (called when the associated button
|
||||
* is clicked).
|
||||
*/
|
||||
reply_loader: function(event) {
|
||||
reply_loader: function(event, all) {
|
||||
event.stop();
|
||||
location.hash += event.target.get("href");
|
||||
},
|
||||
|
||||
/*
|
||||
* Loader of the 'replyall' action (called when the associated button
|
||||
* is clicked).
|
||||
*/
|
||||
replyall_loader: function(event) {
|
||||
event.stop();
|
||||
location.hash += event.target.get("href") + "?all=1";
|
||||
current_anchor.reset().updateparams(this.get("href")).update();
|
||||
},
|
||||
|
||||
/*
|
||||
@@ -524,7 +515,7 @@ var Webmail = new Class({
|
||||
*/
|
||||
forward_loader: function(event) {
|
||||
event.stop();
|
||||
location.hash += event.target.get("href");
|
||||
current_anchor.reset().updateparams(this.get("href")).update();
|
||||
},
|
||||
|
||||
/*
|
||||
@@ -598,12 +589,15 @@ var Webmail = new Class({
|
||||
current_anchor.get_callback("compose")(resp);
|
||||
if ($defined(resp.respmsg)) {
|
||||
infobox.error(resp.respmsg);
|
||||
} else {
|
||||
infobox.hide();
|
||||
}
|
||||
enable_link(this, sendmail_callback);
|
||||
enable_link(link, sendmail_callback);
|
||||
return;
|
||||
}
|
||||
current_anchor.parse_string(resp.url, true).setparams(navparams);
|
||||
current_anchor.update();
|
||||
history.go(-2);
|
||||
infobox.info(gettext("Done"));
|
||||
infobox.hide(1);
|
||||
link.eliminate("editormode");
|
||||
}.bind(this)
|
||||
});
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
{% if body %}
|
||||
<textarea id="id_body" name="id_body" class="editor">{% if bodyheader %}{{ bodyheader }}{% endif %}
|
||||
{{ body }}
|
||||
</textarea>
|
||||
</textarea>
|
||||
{% else %}
|
||||
<textarea id="id_body" name="id_body" class="editor"></textarea>
|
||||
{% endif %}
|
||||
|
||||
@@ -18,20 +18,20 @@ def viewmail_menu(selection, folder, user, mail_id=None):
|
||||
"img" : static_url("pics/back.png"),
|
||||
"label" : _("Back")},
|
||||
{"name" : "reply",
|
||||
"url" : "reply/",
|
||||
"url" : "action=reply&mbox=%s&mailid=%s" % (folder, mail_id),
|
||||
"img" : static_url("pics/reply.png"),
|
||||
"label" : _("Reply")},
|
||||
{"name" : "replyall",
|
||||
"url" : "reply/",
|
||||
"url" : "action=reply&mbox=%s&mailid=%s&all=1" % (folder, mail_id),
|
||||
"img" : static_url("pics/reply-all.png"),
|
||||
"label" : _("Reply all")},
|
||||
{"name" : "forward",
|
||||
"url" : "forward/",
|
||||
"url" : "action=forward&mbox=%s&mailid=%s" % (folder, mail_id),
|
||||
"img" : static_url("pics/alias.png"),
|
||||
"label" : _("Forward")},
|
||||
{"name" : "delete",
|
||||
"img" : static_url("pics/remove.png"),
|
||||
"url" : reverse(webmail.views.delete, args=[folder, mail_id]),
|
||||
"url" : "action=delete&mbox=%s&mailid=%s" % (folder, mail_id),
|
||||
"label" : _("Delete")},
|
||||
{"name" : "display_options",
|
||||
"label" : _("Display options"),
|
||||
|
||||
@@ -28,7 +28,7 @@ urlpatterns = patterns(
|
||||
(r'^(?P<fdname>.+)/(?P<mail_id>[\w\-\+]+)/delete/$', 'delete'),
|
||||
#(r'^(?P<folder>.+)/(?P<mailid>[\w\-\+]+)/content/$', 'getmailcontent'),
|
||||
(r'^(?P<folder>.+)/(?P<mail_id>[\w\-\+]+)/forward/$', 'forward'),
|
||||
(r'^(?P<folder>.+)/(?P<mail_id>[\w\-\+]+)/reply/$', 'reply'),
|
||||
# (r'^(?P<folder>.+)/(?P<mail_id>[\w\-\+]+)/reply/$', 'reply'),
|
||||
# (r'^(?P<folder>.+)/(?P<mail_id>[\w\-\+]+)/$', 'viewmail'),
|
||||
(r'^(?P<name>.+)/$', "folder"),
|
||||
)
|
||||
|
||||
+73
-39
@@ -320,42 +320,42 @@ def compact(request, name):
|
||||
# form.fields["from_"].initial = request.user.username
|
||||
# return render_compose(request, form, reverse(compose), insert_signature=True)
|
||||
|
||||
@login_required
|
||||
@needs_mailbox()
|
||||
def reply(request, folder, mail_id):
|
||||
msg = fetchmail(request, folder, mail_id, True)
|
||||
if request.method == "POST":
|
||||
status, resp = send_mail(request, origmsg=msg,
|
||||
posturl=reverse(reply, args=[folder, mail_id]))
|
||||
if status:
|
||||
IMAPconnector(user=request.user.username,
|
||||
password=request.session["password"]).msg_answered(folder,
|
||||
mail_id)
|
||||
return resp
|
||||
# @login_required
|
||||
# @needs_mailbox()
|
||||
# def reply(request, folder, mail_id):
|
||||
# msg = fetchmail(request, folder, mail_id, True)
|
||||
# if request.method == "POST":
|
||||
# status, resp = send_mail(request, origmsg=msg,
|
||||
# posturl=reverse(reply, args=[folder, mail_id]))
|
||||
# if status:
|
||||
# IMAPconnector(user=request.user.username,
|
||||
# password=request.session["password"]).msg_answered(folder,
|
||||
# mail_id)
|
||||
# return resp
|
||||
|
||||
form = ComposeMailForm()
|
||||
email = ReplyModifier(msg, request.user, form, request.GET.has_key("all"),
|
||||
addrfull=True, links="1")
|
||||
return render_compose(request, form, reverse(reply, args=[folder, mail_id]),
|
||||
email)
|
||||
# form = ComposeMailForm()
|
||||
# email = ReplyModifier(msg, request.user, form, request.GET.has_key("all"),
|
||||
# addrfull=True, links="1")
|
||||
# return render_compose(request, form, reverse(reply, args=[folder, mail_id]),
|
||||
# email)
|
||||
|
||||
@login_required
|
||||
@needs_mailbox()
|
||||
def forward(request, folder, mail_id):
|
||||
if request.method == "POST":
|
||||
status, response = send_mail(request,
|
||||
posturl=reverse(forward, args=[folder, mail_id]))
|
||||
if status:
|
||||
IMAPconnector(user=request.user.username,
|
||||
password=request.session["password"]).msgforwarded(folder,
|
||||
mail_id)
|
||||
return response
|
||||
# @login_required
|
||||
# @needs_mailbox()
|
||||
# def forward(request, folder, mail_id):
|
||||
# if request.method == "POST":
|
||||
# status, response = send_mail(request,
|
||||
# posturl=reverse(forward, args=[folder, mail_id]))
|
||||
# if status:
|
||||
# IMAPconnector(user=request.user.username,
|
||||
# password=request.session["password"]).msgforwarded(folder,
|
||||
# mail_id)
|
||||
# return response
|
||||
|
||||
msg = fetchmail(request, folder, mail_id, True)
|
||||
form = ComposeMailForm()
|
||||
email = ForwardModifier(msg, request.user, form, addrfull=True, links="1")
|
||||
return render_compose(request, form, reverse(forward, args=[folder, mail_id]),
|
||||
email)
|
||||
# msg = fetchmail(request, folder, mail_id, True)
|
||||
# form = ComposeMailForm()
|
||||
# email = ForwardModifier(msg, request.user, form, addrfull=True, links="1")
|
||||
# return render_compose(request, form, reverse(forward, args=[folder, mail_id]),
|
||||
# email)
|
||||
|
||||
def separate_folder(fullname, sep="."):
|
||||
"""Split a folder name
|
||||
@@ -605,12 +605,43 @@ def render_compose(request, form, posturl, email=None, insert_signature=False):
|
||||
return ctx
|
||||
|
||||
def compose(request):
|
||||
url = "?action=compose"
|
||||
if request.method == "POST":
|
||||
return send_mail(request)
|
||||
status, resp = send_mail(request, posturl=url)
|
||||
return resp
|
||||
|
||||
form = ComposeMailForm()
|
||||
form.fields["from_"].initial = request.user.username
|
||||
return render_compose(request, form, "?action=compose", insert_signature=True)
|
||||
return render_compose(request, form, url, insert_signature=True)
|
||||
|
||||
def compose_and_send(request, action, callback=None):
|
||||
mbox = request.GET.get("mbox", None)
|
||||
mailid = request.GET.get("mailid", None)
|
||||
if mbox is None or mailid is None:
|
||||
raise WebmailError(_("Bad request"))
|
||||
url = "?action=%s&mbox=%s&mailid=%s" % (action, mbox, mailid)
|
||||
if request.method == "POST":
|
||||
status, resp = send_mail(request, url)
|
||||
if status and callback:
|
||||
callback(mbox, mailid)
|
||||
return resp
|
||||
|
||||
form = ComposeMailForm()
|
||||
modclass = globals()["%sModifier" % action.capitalize()]
|
||||
email = modclass(mbox, mailid, request, form, addrfull=True, links="1")
|
||||
return render_compose(request, form, url, email)
|
||||
|
||||
def reply(request):
|
||||
def msg_replied(mbox, mailid):
|
||||
get_imapconnector(request).msg_answered(mbox, mailid)
|
||||
|
||||
return compose_and_send(request, "reply", msg_replied)
|
||||
|
||||
def forward(request):
|
||||
def msg_forwarded(mbox, mailid):
|
||||
get_imapconnector(request).msg_forwarded(mbox, mailid)
|
||||
|
||||
return compose_and_send(request, "reply", msg_forwarded)
|
||||
|
||||
@login_required
|
||||
@needs_mailbox()
|
||||
@@ -671,20 +702,19 @@ def newindex(request):
|
||||
|
||||
"""
|
||||
action = request.GET.get("action", None)
|
||||
json = request.GET.get("json", False)
|
||||
|
||||
if action is not None:
|
||||
if not globals().has_key(action):
|
||||
raise WebmailError(_("Undefined action"))
|
||||
response = globals()[action](request)
|
||||
else:
|
||||
if json:
|
||||
if request.is_ajax():
|
||||
raise WebmailError(_("Bad request"))
|
||||
response = dict(deflocation="?action=listmailbox",
|
||||
defcallback="wm_updatelisting")
|
||||
|
||||
curmbox = request.session.get("mbox", "INBOX")
|
||||
if not json:
|
||||
if not request.is_ajax():
|
||||
request.session["lastaction"] = None
|
||||
imapc = get_imapconnector(request)
|
||||
response["refreshrate"] = \
|
||||
@@ -692,6 +722,8 @@ def newindex(request):
|
||||
response["mboxes"] = render_mboxes_list(request, imapc)
|
||||
return _render(request, "webmail/index.html", response)
|
||||
|
||||
if action in ["reply", "forward"]:
|
||||
action = "compose"
|
||||
if request.session["lastaction"] != action:
|
||||
extra_args = {}
|
||||
if response.has_key("menuargs"):
|
||||
@@ -703,5 +735,7 @@ def newindex(request):
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
response.update(status="ok", callback=action)
|
||||
response.update(callback=action)
|
||||
if not response.has_key("status"):
|
||||
response.update(status="ok")
|
||||
return ajax_simple_response(response)
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
{% load i18n %}
|
||||
{% for field in form %}
|
||||
{% for field in form.hidden_fields %}
|
||||
{{ field }}
|
||||
{% endfor %}
|
||||
{% for field in form.visible_fields %}
|
||||
<div class="row clearfix">
|
||||
{% if field.help_text %}
|
||||
<div id="{{ field.name }}_helptext" class="tip">
|
||||
|
||||
Reference in New Issue
Block a user