def from_csv(self, user, row): """Create a domain alias from a CSV row Expected format: ["domainalias", domain alias name, targeted domain, enabled] :param user: a ``User`` object :param row: a list containing the alias definition """ if len(row) < 4: raise BadRequest(_("Invalid line")) self.name = row[1].strip().lower() for model in [DomainAlias, Domain]: if model.objects.filter(name=self.name).exists(): raise Conflict domname = row[2].strip() try: self.target = Domain.objects.get(name=domname) except Domain.DoesNotExist: raise BadRequest(_("Unknown domain %s") % domname) core_signals.can_create_object.send(sender="import", context=self.target, object_type="domain_aliases") self.enabled = row[3].strip().lower() in ["true", "1", "yes", "y"] self.save(creator=user)
def release_selfservice(request, mail_id): """Release view, self-service mode.""" rcpt = request.GET.get("rcpt", None) secret_id = request.GET.get("secret_id", None) if rcpt is None or secret_id is None: raise BadRequest(_("Invalid request")) connector = SQLconnector() try: msgrcpt = connector.get_recipient_message(rcpt, mail_id) except Msgrcpt.DoesNotExist: raise BadRequest(_("Invalid request")) if secret_id != smart_text(msgrcpt.mail.secret_id): raise BadRequest(_("Invalid request")) if not param_tools.get_global_parameter("user_can_release"): connector.set_msgrcpt_status(rcpt, mail_id, "p") msg = _("Request sent") else: amr = AMrelease() result = amr.sendreq(mail_id, secret_id, rcpt) if result: connector.set_msgrcpt_status(rcpt, mail_id, "R") msg = _("Message released") else: raise BadRequest(result) return render_to_json_response(msg)
def release_selfservice(request, mail_id): """Release view, self-service mode.""" rcpt = request.GET.get("rcpt", None) secret_id = request.GET.get("secret_id", None) if rcpt is None or secret_id is None: raise BadRequest(_("Invalid request")) connector = get_connector() try: msgrcpt = connector.get_recipient_message(rcpt, mail_id) except Msgrcpt.DoesNotExist: raise BadRequest(_("Invalid request")) if secret_id != str(msgrcpt.mail.secret_id): raise BadRequest(_("Invalid request")) if parameters.get_admin("USER_CAN_RELEASE") == "no": connector.set_msgrcpt_status(rcpt, mail_id, 'p') msg = _("Request sent") else: amr = AMrelease() result = amr.sendreq(mail_id, secret_id, rcpt) if result: connector.set_msgrcpt_status(rcpt, mail_id, 'R') msg = _("Message released") else: raise BadRequest(result) return render_to_json_response(msg)
def from_csv(self, user, row, expected_elements=5): """Create a new alias from a CSV file entry.""" if len(row) < expected_elements: raise BadRequest(_("Invalid line: %s" % row)) address = row[1].strip() localpart, domname = split_mailbox(address) try: domain = Domain.objects.get(name=domname) except Domain.DoesNotExist: raise BadRequest(_("Domain '%s' does not exist" % domname)) if not user.can_access(domain): raise PermDeniedException core_signals.can_create_object.send(sender="import", context=user, klass=Alias) core_signals.can_create_object.send(sender="import", context=domain, object_type="mailbox_aliases") if Alias.objects.filter(address=address).exists(): raise Conflict self.address = address self.domain = domain self.enabled = (row[2].strip().lower() in ["true", "1", "yes", "y"]) self.save() self.set_recipients([raddress.strip() for raddress in row[3:]]) self.post_create(user)
def from_csv(self, user, row): """Create a new domain from a CSV entry. The expected fields order is the following:: "domain", name, quota, default_mailbox_quota, enabled :param ``core.User`` user: user creating the domain :param str row: a list containing domain's definition """ if len(row) < 5: raise BadRequest(_("Invalid line")) self.name = row[1].strip() if Domain.objects.filter(name=self.name).exists(): raise Conflict try: self.quota = int(row[2].strip()) except ValueError: raise BadRequest( _("Invalid quota value for domain '{}'").format(self.name)) try: self.default_mailbox_quota = int(row[3].strip()) except ValueError: raise BadRequest( _("Invalid default mailbox quota value for domain '{}'"). format(self.name)) self.enabled = (row[4].strip() in ["True", "1", "yes", "y"]) core_signals.can_create_object.send(sender=self.__class__, context=user, klass=Domain, instance=self) self.save(creator=user)
def from_csv(self, user, row): """Create a new domain from a CSV entry. The expected fields order is the following:: "domain", name, quota, enabled :param ``core.User`` user: user creating the domain :param str row: a list containing domain's definition """ if len(row) < 4: raise BadRequest(_("Invalid line")) self.name = row[1].strip() try: Domain.objects.get(name=self.name) except Domain.DoesNotExist: pass else: raise Conflict try: self.quota = int(row[2].strip()) except ValueError: raise BadRequest( _("Invalid quota value for domain '%s'" % self.name)) self.enabled = (row[3].strip() in ["True", "1", "yes", "y"]) self.save(creator=user)
def from_csv(self, user, row): """Create a domain alias from a CSV row Expected format: ["domainalias", domain alias name, targeted domain, enabled] :param user: a ``User`` object :param row: a list containing the alias definition """ if len(row) < 4: raise BadRequest(_("Invalid line")) self.name = row[1].strip() for model in [DomainAlias, Domain]: try: model.objects.get(name=self.name) except model.DoesNotExist: pass else: raise Conflict domname = row[2].strip() try: self.target = Domain.objects.get(name=domname) except Domain.DoesNotExist: raise BadRequest(_("Unknown domain %s" % domname)) self.enabled = row[3].strip() in ["True", "1", "yes", "y"] self.save(creator=user)
def set_quota(self, value=None, override_rules=False): """Set or update quota's value for this mailbox. A value equal to 0 means the mailbox won't have any quota. The following cases allow people to define such behaviour: * The domain has no quota * :keyword:`override_rules` is True :param integer value: the quota's value :param bool override_rules: allow to override defined quota rules """ if value is None: if self.use_domain_quota: self.quota = self.domain.quota else: self.quota = 0 elif int(value) > self.domain.quota and not override_rules: raise BadRequest( _("Quota is greater than the allowed domain's limit (%dM)" % self.domain.quota) ) else: self.quota = value if not self.quota and self.domain.quota and not override_rules: raise BadRequest(_("A quota is required"))
def from_csv(self, user, row, crypt_password=True): """Create a new account from a CSV file entry. The expected order is the following:: "account", loginname, password, first name, last name, enabled, group Additional fields can be added using the *AccountImported* event. :param user: a ``core.User`` instance :param row: a list containing the expected information :param crypt_password: """ from modoboa.lib.permissions import get_account_roles if len(row) < 7: raise BadRequest(_("Invalid line")) desired_role = row[6].strip() if not user.is_superuser: allowed_roles = get_account_roles(user) allowed_roles = [role[0] for role in allowed_roles] if desired_role not in allowed_roles: raise PermDeniedException( _("You can't import an account with a role greater than " "yours")) self.username = row[1].strip() try: User.objects.get(username=self.username) except User.DoesNotExist: pass else: raise Conflict if desired_role == "SimpleUsers": if len(row) < 8 or not row[7].strip(): raise BadRequest( _("The simple user '%s' must have a valid email address" % self.username)) if self.username != row[7].strip(): raise BadRequest( _("username and email fields must not differ for '%s'" % self.username)) if crypt_password: self.set_password(row[2].strip()) else: self.password = row[2].strip() self.first_name = row[3].strip() self.last_name = row[4].strip() self.is_active = (row[5].strip() in ["True", "1", "yes", "y"]) self.save() self.set_role(desired_role) self.post_create(user) if len(row) < 8: return events.raiseEvent("AccountImported", user, self, row[7:])
def _get_step_id(self): """Retrieve the step identifier from the request.""" stepid = self.request.POST.get("stepid", None) if stepid is None: raise BadRequest(_("Invalid request")) stepid = int(stepid.replace("step", "")) if stepid < 0: raise BadRequest(_("Invalid request")) return min(stepid, len(self.steps))
def delete_selfservice(request, mail_id): rcpt = request.GET.get("rcpt", None) if rcpt is None: raise BadRequest(_("Invalid request")) try: SQLconnector().set_msgrcpt_status(rcpt, mail_id, "D") except Msgrcpt.DoesNotExist: raise BadRequest(_("Invalid request")) return render_to_json_response(_("Message deleted"))
def import_account_mailbox(user, account, row): """Handle extra fields when an account is imported. Expected fields: email address; quota; [domain; ...] :param User user: user importing the account :param User account: account being imported :param list rom: list of fields (strings) """ account.email = row[0].strip() if account.email: mailbox, domname = split_mailbox(account.email) try: domain = Domain.objects.get(name=domname) except Domain.DoesNotExist: raise BadRequest( _("Account import failed (%s): domain does not exist" % account.username)) if not user.can_access(domain): raise PermDeniedException core_signals.can_create_object.send(sender="import", context=user, object_type="mailboxes") core_signals.can_create_object.send(sender="import", context=domain, object_type="mailboxes") account.save() if Mailbox.objects.filter(address=mailbox, domain=domain).exists(): raise Conflict( _("Mailbox {} already exists").format(account.email)) if len(row) == 1: quota = None else: try: quota = int(row[1].strip()) except ValueError: raise BadRequest( _("Account import failed (%s): wrong quota value" % account.username)) use_domain_quota = True if not quota else False mb = Mailbox(address=mailbox, domain=domain, user=account, use_domain_quota=use_domain_quota) mb.set_quota(quota, override_rules=user.has_perm("admin.change_domain")) mb.save(creator=user) if account.role == "DomainAdmins": for domname in row[2:]: try: dom = Domain.objects.get(name=domname.strip()) except Domain.DoesNotExist: continue dom.add_admin(account)
def set_recipients(self): """Recipients dispatching We make a difference between 'local' recipients (the ones hosted by Modoboa) and 'external' recipients. """ self.ext_rcpts = [] self.int_rcpts = [] total = 0 for k, v in self.cleaned_data.items(): if not k.startswith("recipients"): continue if v == "": continue local_part, domname = split_mailbox(v) if domname is None: raise BadRequest( u"%s %s" % (_("Invalid mailbox"), v) ) try: domain = Domain.objects.get(name=domname) except Domain.DoesNotExist: domain = None if domain is not None: try: rcpt = Alias.objects.get(domain=domain, address=local_part) if rcpt.full_address == self.cleaned_data["email"]: rcpt = None except Alias.DoesNotExist: rcpt = None if rcpt is None: try: rcpt = Mailbox.objects.get(domain=domain, address=local_part) except Mailbox.DoesNotExist: raise NotFound( _("Local recipient %s not found" % v) ) if rcpt in self.int_rcpts: raise Conflict( _("Recipient %s already present" % v) ) self.int_rcpts += [rcpt] total += 1 continue if v in self.ext_rcpts: raise Conflict( _("Recipient %s already present" % v) ) self.ext_rcpts += [v] total += 1 if total == 0: raise BadRequest(_("No recipient defined"))
def from_csv(self, user, row, expected_elements=5): """Create a new alias from a CSV file entry """ if len(row) < expected_elements: raise BadRequest(_("Invalid line: %s" % row)) localpart, domname = split_mailbox(row[1].strip()) try: domain = Domain.objects.get(name=domname) except Domain.DoesNotExist: raise BadRequest(_("Domain '%s' does not exist" % domname)) if not user.can_access(domain): raise PermDeniedException try: Alias.objects.get(address=localpart, domain__name=domain) except Alias.DoesNotExist: pass else: raise Conflict self.address = localpart self.domain = domain self.enabled = (row[2].strip() in ["True", "1", "yes", "y"]) int_rcpts = [] ext_rcpts = [] for rcpt in row[3:]: rcpt = rcpt.strip() if not rcpt: continue localpart, domname = split_mailbox(rcpt) try: Domain.objects.get(name=domname) except Domain.DoesNotExist: ext_rcpts += [rcpt] continue try: target = Alias.objects.get( domain__name=domname, address=localpart ) if target.full_address == self.full_address: target = None except Alias.DoesNotExist: target = None if target is None: try: target = Mailbox.objects.get(address=localpart, domain__name=domname) except Mailbox.DoesNotExist: raise BadRequest(_("Local recipient %s not found" % rcpt)) int_rcpts += [target] self.save(int_rcpts=int_rcpts, ext_rcpts=ext_rcpts, creator=user)
def from_csv(self, user, row): """Create a new domain from a CSV entry. The expected fields order is the following:: "domain", name, quota, default_mailbox_quota, enabled :param ``core.User`` user: user creating the domain :param str row: a list containing domain's definition """ from .. import lib if len(row) < 5: raise BadRequest(_("Invalid line")) self.name = row[1].strip() if Domain.objects.filter(name=self.name).exists(): raise Conflict domains_must_have_authorized_mx = ( param_tools.get_global_parameter("domains_must_have_authorized_mx") ) if domains_must_have_authorized_mx and not user.is_superuser: if not lib.domain_has_authorized_mx(self.name): raise BadRequest( _("No authorized MX record found for domain {}") .format(self.name) ) try: self.quota = int(row[2].strip()) except ValueError: raise BadRequest( _("Invalid quota value for domain '{}'") .format(self.name) ) try: self.default_mailbox_quota = int(row[3].strip()) except ValueError: raise BadRequest( _("Invalid default mailbox quota value for domain '{}'") .format(self.name) ) if self.quota != 0 and self.default_mailbox_quota > self.quota: raise BadRequest( _("Default mailbox quota cannot be greater than domain " "quota") ) self.enabled = (row[4].strip().lower() in ["true", "1", "yes", "y"]) core_signals.can_create_object.send( sender=self.__class__, context=user, klass=Domain, instance=self) self.save(creator=user)
def remove_permission(request): domid = request.GET.get("domid", None) daid = request.GET.get("daid", None) if domid is None or daid is None: raise BadRequest(_("Invalid request")) try: account = User.objects.get(pk=daid) domain = Domain.objects.get(pk=domid) except (User.DoesNotExist, Domain.DoesNotExist): raise BadRequest(_("Invalid request")) if not request.user.can_access(account) or \ not request.user.can_access(domain): raise PermDeniedException domain.remove_admin(account) return render_to_json_response({})
def list_quotas(request): from modoboa.lib.dbutils import db_type sort_order, sort_dir = get_sort_order(request.GET, "address") mboxes = Mailbox.objects.get_for_admin( request.user, request.GET.get("searchquery", None)) mboxes = mboxes.exclude(quota=0) if sort_order in ["address", "quota", "quota_value__bytes"]: mboxes = mboxes.order_by("%s%s" % (sort_dir, sort_order)) elif sort_order == "quota_usage": where = "admin_mailbox.address||'@'||admin_domain.name" db_type = db_type() if db_type == "postgres": select = '(admin_quota.bytes::float / (CAST(admin_mailbox.quota AS BIGINT) * 1048576)) * 100' else: select = 'admin_quota.bytes / (admin_mailbox.quota * 1048576) * 100' if db_type == "mysql": where = "CONCAT(admin_mailbox.address,'@',admin_domain.name)" mboxes = mboxes.extra(select={'quota_usage': select}, where=["admin_quota.username=%s" % where], tables=["admin_quota", "admin_domain"], order_by=["%s%s" % (sort_dir, sort_order)]) else: raise BadRequest(_("Invalid request")) page = get_listing_page(mboxes, request.GET.get("page", 1)) context = {} if page is None: context["length"] = 0 else: context["headers"] = _render_to_string(request, "admin/quota_headers.html", {}) context["rows"] = _render_to_string(request, "admin/quotas.html", {"mboxes": page}) context["pages"] = [page.number] return render_to_json_response(context)
def graphs(request): gset = request.GET.get("gset", None) gsets = events.raiseDictEvent("GetGraphSets") if not gset in gsets: raise NotFound(_("Unknown graphic set")) searchq = request.GET.get("searchquery", None) period = request.GET.get("period", "day") tplvars = dict(graphs={}, period=period) domain = check_domain_access(request.user, searchq) if domain is None: return render_to_json_response({}) tplvars["domain"] = domain if period == "custom": if not "start" in request.GET or not "end" in request.GET: raise BadRequest(_("Bad custom period")) start = request.GET["start"] end = request.GET["end"] expr = re.compile(r'[:\- ]') period_name = "%s_%s" % (expr.sub('', start), expr.sub('', end)) start = date_to_timestamp(expr.split(start)) end = date_to_timestamp(expr.split(end)) else: end = int(time.mktime(time.localtime())) start = "-1%s" % period period_name = period tplvars['graphs'] = gsets[gset].export(tplvars["domain"], start, end) tplvars["period_name"] = period_name tplvars["start"] = start tplvars["end"] = end return render_to_json_response(tplvars)
def save(self): """Custom save method.""" usernames = {} for name, value in self.cleaned_data.iteritems(): if not name.startswith("username") or not value: continue res = re.match(r"[^_]+_(\d+)$", name) pos = int(res.group(1)) if res else None usernames[value] = pos for rule in self.calendar.rules.select_related().all(): if rule.mailbox.full_address not in usernames: rule.delete() for username, pos in usernames.iteritems(): local_part, domname = split_mailbox(username) try: mbox = Mailbox.objects.get(address=local_part, domain__name=domname) except Mailbox.DoesNotExist: raise BadRequest(_("Mailbox %s does not exist")) if pos: raccess = self.cleaned_data.get("read_access_%d" % pos, False) waccess = self.cleaned_data.get("write_access_%d" % pos, False) else: raccess = self.cleaned_data.get("read_access", False) waccess = self.cleaned_data.get("write_access", False) acr, created = AccessRule.objects.get_or_create( mailbox=mbox, calendar=self.calendar) acr.read = raccess acr.write = waccess acr.save()
def viewmail(request): mbox = request.GET.get("mbox", None) mailid = request.GET.get("mailid", None) if mbox is None or mailid is None: raise BadRequest(_("Invalid request")) links = request.GET.get("links", None) if links is None: links = int(request.user.parameters.get_value("enable_links")) else: links = int(links) email = ImapEmail(request, "%s:%s" % (mbox, mailid), dformat="DISPLAYMODE", links=links) email.fetch_headers() context = { "mbox": mbox, "mailid": mailid, "links": links, "headers": email.headers, "attachments": email.attachments } content = render_to_string("modoboa_webmail/headers.html", context, request) return {"listing": content, "menuargs": {"mail_id": mailid}}
def submitfilter(request, setname, okmsg, tplname, tplctx, update=False, sc=None): form = build_filter_form_from_qdict(request) if form.is_valid(): if sc is None: sc = SieveClient(user=request.user.username, password=request.session["password"]) fset = sc.getscript(setname, format="fset") conditions, actions = form.tofilter() match_type = form.cleaned_data["match_type"] if match_type == "all": match_type = "anyof" conditions = [("true", )] fltname = form.cleaned_data["name"].encode("utf-8") try: if not update: fset.addfilter(fltname, conditions, actions, match_type) else: oldname = request.POST["oldname"].encode("utf-8") fset.updatefilter(oldname, fltname, conditions, actions, match_type) except (BadArgument, BadValue) as inst: raise BadRequest(str(inst)) sc.pushscript(fset.name, str(fset)) return render_to_json_response(okmsg) return render_to_json_response({'form_errors': form.errors}, status=400)
def list_quotas(request, tplname="admin/quotas.html"): from modoboa.lib.dbutils import db_type sort_order, sort_dir = get_sort_order(request.GET, "address") mboxes = Mailbox.objects.get_for_admin( request.user, request.GET.get("searchquery", None)) mboxes = mboxes.exclude(quota=0) if sort_order in ["address", "quota", "quota_value__bytes"]: mboxes = mboxes.order_by("%s%s" % (sort_dir, sort_order)) elif sort_order == "quota_usage": if db_type() == "postgres": select = '(admin_quota.bytes::float / (CAST(admin_mailbox.quota AS BIGINT) * 1048576)) * 100' else: select = 'admin_quota.bytes / (admin_mailbox.quota * 1048576) * 100' mboxes = mboxes.extra(select={'quota_usage': select}, where=["admin_quota.mbox_id=admin_mailbox.id"], tables=["admin_quota"], order_by=["%s%s" % (sort_dir, sort_order)]) else: raise BadRequest(_("Invalid request")) page = get_listing_page(mboxes, request.GET.get("page", 1)) return render_to_json_response({ "page": page.number, "paginbar": pagination_bar(page), "table": _render_to_string(request, tplname, {"mboxes": page}) })
def graphs(request): gset = request.GET.get("gset", None) graph_sets = {} for result in signals.get_graph_sets.send(sender="index"): graph_sets.update(result[1]) if gset not in graph_sets: raise NotFound(_("Unknown graphic set")) searchq = request.GET.get("searchquery", None) period = request.GET.get("period", "day") tplvars = dict(graphs={}, period=period) domain = check_domain_access(request.user, searchq) if domain is None: return render_to_json_response({}) tplvars["domain"] = domain if period == "custom": if "start" not in request.GET or "end" not in request.GET: raise BadRequest(_("Bad custom period")) start = request.GET["start"] end = request.GET["end"] expr = re.compile(r'[:\- ]') period_name = "%s_%s" % (expr.sub('', start), expr.sub('', end)) start = date_to_timestamp(expr.split(start)) end = date_to_timestamp(expr.split(end)) else: end = int(time.mktime(time.localtime())) start = "-1%s" % period period_name = period tplvars["graphs"] = graph_sets[gset].export(tplvars["domain"], start, end) tplvars["period_name"] = period_name tplvars["start"] = start tplvars["end"] = end return render_to_json_response(tplvars)
def get_mail_info(request): """Retrieve a mailbox and an email ID from a request. """ mbox = request.GET.get("mbox", None) mailid = request.GET.get("mailid", None) if mbox is None or mailid is None: raise BadRequest(_("Invalid request")) return mbox, mailid
def folder_compress(request): """Compress a mailbox.""" name = request.GET.get("name", None) if name is None: raise BadRequest(_("Invalid request")) imapc = get_imapconnector(request) imapc.compact(name) return render_to_json_response({})
def delfolder(request): name = request.GET.get("name", None) if name is None: raise BadRequest(_("Invalid request")) mbc = IMAPconnector(user=request.user.username, password=request.session["password"]) mbc.delete_folder(name) WebmailNavigationParameters(request).remove('mbox') return ajax_response(request)
def move(request): for arg in ["msgset", "to"]: if arg not in request.GET: raise BadRequest(_("Invalid request")) mbc = get_imapconnector(request) navparams = WebmailNavigationParameters(request) mbc.move(request.GET["msgset"], navparams.get('mbox'), request.GET["to"]) resp = listmailbox(request, navparams.get('mbox'), update_session=False) return render_to_json_response(resp)
def editfolder(request, tplname="modoboa_webmail/folder.html"): mbc = IMAPconnector(user=request.user.username, password=request.session["password"]) ctx = { "title": _("Edit folder"), "formid": "mboxform", "action": reverse("modoboa_webmail:folder_change"), "action_label": _("Update"), "action_classes": "submit", "withunseen": False, "selectonly": True, "hdelimiter": mbc.hdelimiter } if request.method == "POST": form = FolderForm(request.POST) if form.is_valid(): pf = request.POST.get("parent_folder", None) oldname, oldparent = separate_mailbox(request.POST["oldname"], sep=mbc.hdelimiter) res = {'respmsg': _("Folder updated")} if form.cleaned_data["name"] != oldname \ or (pf != oldparent): newname = form.cleaned_data["name"] if pf is None \ else mbc.hdelimiter.join([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 WebmailNavigationParameters(request).remove('mbox') return render_to_json_response(res) return render_to_json_response({'form_errors': form.errors}, status=400) name = request.GET.get("name") if name is None: raise BadRequest(_("Invalid request")) shortname, parent = separate_mailbox(name, sep=mbc.hdelimiter) ctx = { "title": _("Edit folder"), "formid": "mboxform", "action": reverse("modoboa_webmail:folder_change"), "action_label": _("Update"), "action_classes": "submit", "withunseen": False, "selectonly": True, "hdelimiter": mbc.hdelimiter, "mboxes": mbc.getmboxes(request.user, until_mailbox=parent), "form": FolderForm(), "selected": parent } ctx["form"].fields["oldname"].initial = name ctx["form"].fields["name"].initial = shortname return render(request, tplname, ctx)
def _move_selection_to_folder(request, folder): """Move selected messages to the given folder.""" mbox = request.GET.get("mbox") selection = request.GET.getlist("selection[]") if mbox is None or selection is None: raise BadRequest(_("Invalid request")) selection = [item for item in selection if item.isdigit()] mbc = get_imapconnector(request) mbc.move(",".join(selection), mbox, folder) return len(selection)
def check_unseen_messages(request): mboxes = request.GET.get("mboxes", None) if not mboxes: raise BadRequest(_("Invalid request")) mboxes = mboxes.split(",") counters = {} imapc = get_imapconnector(request) for mb in mboxes: counters[mb] = imapc.unseen_messages(mb) return render_to_json_response(counters)