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 """ 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) partdef, payload = imapc.fetchpart(mailid, mbox, pnum) resp = HttpResponse(decode_payload(partdef["encoding"], payload)) resp["Content-Type"] = partdef["Content-Type"] resp["Content-Transfer-Encoding"] = partdef["encoding"] if partdef["disposition"] != 'NIL': disp = partdef["disposition"] # FIXME : ugly hack, see fetch_parser.py for more explanation # :p if type(disp[1][0]) != dict: cd = '%s; %s="%s"' % (disp[0], disp[1][0], disp[1][1]) else: cd = '%s; %s="%s"' % (disp[0], disp[1][0]['struct'][0], disp[1][0]['struct'][1]) else: cd = 'attachment; filename="%s"' % request.GET["fname"] resp["Content-Disposition"] = cd resp["Content-Length"] = partdef["size"] return resp
def create_folder(self, name, parent=None): if parent is not None: name = "%s.%s" % (parent, name) typ, data = self.m.create(self._encode_mbox_name(name)) if typ == "NO": raise WebmailError(data[0]) return True
def empty(request, name): if name != parameters.get_user(request.user, "TRASH_FOLDER"): raise WebmailError(_("Invalid request")) get_imapconnector(request).empty(name) content = "<div class='alert alert-info'>%s</div>" % _("Empty mailbox") return ajax_simple_response( dict(status="ok", listing=content, mailbox=name))
def mark(request, name): status = request.GET.get("status", None) ids = request.GET.get("ids", None) if status is None or ids is None: raise WebmailError(_("Invalid request")) imapc = get_imapconnector(request) try: getattr(imapc, "mark_messages_%s" % status)(name, ids) except AttributeError: raise WebmailError(_("Unknown action")) return ajax_simple_response( dict(status="ok", action=status, mbox=name, unseen=imapc.unseen_messages(name)))
def delete(request): mbox = request.GET.get("mbox", None) mailid = request.GET.get("mailid", None) if mbox is None or mailid is None: raise WebmailError(_("Invalid request")) mbc = get_imapconnector(request) mbc.move(mailid, mbox, parameters.get_user(request.user, "TRASH_FOLDER")) resp = dict(status="ok") return ajax_simple_response(resp)
def move(request): for arg in ["msgset", "to"]: if not arg in request.GET: raise WebmailError(_("Invalid request")) mbc = get_imapconnector(request) mbc.move(request.GET["msgset"], request.session["mbox"], request.GET["to"]) resp = listmailbox(request, request.session["mbox"], update_session=False) resp.update(status="ok") return ajax_simple_response(resp)
def check_unseen_messages(request): mboxes = request.GET.get("mboxes", None) if not mboxes: raise WebmailError(_("Invalid request")) mboxes = mboxes.split(",") counters = dict() imapc = get_imapconnector(request) for mb in mboxes: counters[mb] = imapc.unseen_messages(mb) return ajax_simple_response(dict(status="ok", counters=counters))
def delfolder(request): name = request.GET.get("name", None) if name is None: raise WebmailError(_("Bad request")) mbc = IMAPconnector(user=request.user.username, password=request.session["password"]) mbc.delete_folder(name) if request.session.has_key("mbox"): del request.session["mbox"] return ajax_response(request)
def getmailcontent(request): mbox = request.GET.get("mbox", None) mailid = request.GET.get("mailid", None) if mbox is None or mailid is None: 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), "folder": mbox, "imapid": mailid, "mailbody": email.body if email.body else "" })
def hdelimiter(self): """Return the default hierachy delimiter. This is a simple way to retrieve the default delimiter (see http://www.imapwiki.org/ClientImplementation/MailboxList). :return: a string """ if self.__hdelimiter is None: data = self._cmd("LIST", "", "") m = self.list_response_pattern.match(data[0]) if m is None: raise WebmailError(_("Failed to retrieve hierarchy delimiter")) self.__hdelimiter = m.group('delimiter') return self.__hdelimiter
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 delete(request): mbox = request.GET.get("mbox", None) selection = request.GET.getlist("selection[]", None) if mbox is None or selection is None: raise WebmailError(_("Invalid request")) selection = [item for item in selection if item.isdigit()] mbc = get_imapconnector(request) mbc.move(",".join(selection), mbox, parameters.get_user(request.user, "TRASH_FOLDER")) count = len(selection) message = ungettext("%(count)d message deleted", "%(count)d messages deleted", count) % { "count": count } resp = dict(status="ok", respmsg=message) return ajax_simple_response(resp)
def editfolder(request, tplname="webmail/folder.html"): mbc = IMAPconnector(user=request.user.username, password=request.session["password"]) ctx = { "title": _("Edit mailbox"), "formid": "mboxform", "action": reverse(editfolder), "action_label": _("Update"), "action_classes": "submit", "withunseen": False, "selectonly": True } if request.method == "POST": form = FolderForm(request.POST) if form.is_valid(): pf = request.POST.get("parent_folder", None) ctx["selected"] = pf oldname, oldparent = separate_mailbox(request.POST["oldname"]) res = dict(status="ok", respmsg=_("Mailbox updated")) if form.cleaned_data["name"] != oldname \ or (pf != oldparent): newname = form.cleaned_data["name"] if pf is None \ else "%s.%s" % (pf, form.cleaned_data["name"]) mbc.rename_folder(request.POST["oldname"], newname) res["oldmb"] = oldname res["newmb"] = form.cleaned_data["name"] res["oldparent"] = oldparent res["newparent"] = pf if "mbox" in request.session: del request.session["mbox"] return ajax_simple_response(res) ctx["mboxes"] = mbc.getmboxes(request.user) ctx["form"] = form return ajax_response(request, status="ko", template=tplname, **ctx) name = request.GET.get("name", None) if name is None: raise WebmailError(_("Invalid request")) shortname, parent = separate_mailbox(name) ctx["mboxes"] = mbc.getmboxes(request.user, until_mailbox=parent) ctx["form"] = FolderForm() ctx["form"].fields["oldname"].initial = name ctx["form"].fields["name"].initial = shortname ctx["selected"] = parent return _render(request, tplname, ctx)
def viewmail(request): mbox = request.GET.get("mbox", None) mailid = request.GET.get("mailid", None) if mbox is None or mailid is None: raise WebmailError(_("Invalid request")) links = request.GET.get("links", None) if links is None: links = 1 if parameters.get_user(request.user, "ENABLE_LINKS") == "yes" else 0 else: links = int(links) url = reverse(getmailcontent) + "?mbox=%s&mailid=%s&links=%d" % \ (mbox, mailid, links) content = Template(""" <iframe src="{{ url }}" id="mailcontent"></iframe> """).render(Context({"url": url})) return dict(listing=content, menuargs=dict(mail_id=mailid))
def rename_folder(self, oldname, newname): typ, data = self.m.rename(self._encode_mbox_name(oldname), self._encode_mbox_name(newname)) if typ == "NO": raise WebmailError(data[0], ajax=True) return True
def delete_folder(self, name): typ, data = self.m.delete(self._encode_mbox_name(name)) if typ == "NO": raise WebmailError(data[0]) return True
def index(request): """Webmail actions handler Problèmes liés à la navigation 'anchor based' ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Lors d'un rafraichissemt complet, une première requête est envoyée vers /webmail/. On ne connait pas encore l'action qui va être demandée mais on peut déjà envoyer des informations indépendantes (comme les dossiers, le quota). Si on se contente de cela, l'affichage donnera un aspect décomposé qui n'est pas très séduisant (à cause de la latence notamment). Il faudrait pouvoir envoyer le menu par la même occasion, le souci étant de savoir lequel... Une solution possible : il suffirait de déplacer le menu vers la droite pour l'aligner avec le contenu, remonter la liste des dossiers (même hauteur que le menu) et renvoyer le menu en même temps que le contenu. Le rendu sera plus uniforme je pense. """ action = request.GET.get("action", None) if action is not None: if not globals().has_key(action): raise WebmailError(_("Undefined action")) response = globals()[action](request) else: if request.is_ajax(): raise WebmailError(_("Bad request")) response = dict(selection="webmail") curmbox = request.session.get("mbox", "INBOX") if not request.is_ajax(): request.session["lastaction"] = None imapc = get_imapconnector(request) response["mboxes"] = render_mboxes_list(request, imapc) imapc.getquota(curmbox) response["refreshrate"] = \ int(parameters.get_user(request.user, "REFRESH_INTERVAL")) response["quota"] = ImapListing.computequota(imapc) 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"]: action = "compose" if request.session["lastaction"] != action: extra_args = {} if response.has_key("menuargs"): extra_args = response["menuargs"] del response["menuargs"] try: response["menu"] = \ getattr(webextras, "%s_menu" % action)("", curmbox, request.user, **extra_args) except KeyError: pass response.update(callback=action) if not response.has_key("status"): response.update(status="ok") return ajax_simple_response(response)