def from_csv(self, user, row): if len(row) < 4: raise AdminError(_("Invalid line")) self.name = row[1].strip() try: self.quota = int(row[2].strip()) except ValueError: raise AdminError( _("Invalid quota value for domain '%s'" % self.name)) self.enabled = (row[3].strip() == 'True') 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 AdminError(_("Invalid request")) try: account = User.objects.get(pk=daid) domain = Domain.objects.get(pk=domid) except (User.DoesNotExist, Domain.DoesNotExist): raise AdminError(_("Invalid request")) if not request.user.can_access(account) or not request.user.can_access( domain): raise PermDeniedException domain.remove_admin(account) return ajax_simple_response({"status": "ok"})
def _validate_alias(request, form, successmsg, tplname, commonctx, callback=None): """Alias validation Common function shared between creation and modification actions. """ error = None if form.is_valid(): form.set_recipients() try: alias = form.save() except IntegrityError: raise AdminError(_("Alias with this name already exists")) if callback: callback(request.user, alias) return ajax_simple_response({"status": "ok", "respmsg": successmsg}) if "targets" in request.POST: targets = request.POST.getlist("targets") commonctx["targets"] = targets[:-1] commonctx["form"] = form commonctx["error"] = error return ajax_response(request, status="ko", template=tplname, **commonctx)
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 AdminError(_("Invalid request")) page = get_listing_page(mboxes, request.GET.get("page", 1)) return ajax_simple_response({ "status": "ok", "page": page.number, "paginbar": pagination_bar(page), "table": _render_to_string(request, tplname, {"mboxes": page}) })
def mail_home(self): """Retrieve the home directory of this mailbox. The home directory refers to the place on the file system where the mailbox data is stored. We ask dovecot to give us this information because there are several patterns to understand and we don't want to implement them. """ hm = parameters.get_admin("HANDLE_MAILBOXES", raise_error=False) if hm is None or hm == "no": return None if self.__mail_home is None: curuser = pwd.getpwuid(os.getuid()).pw_name mbowner = parameters.get_admin("MAILBOXES_OWNER") options = {} if curuser != mbowner: options['sudo_user'] = mbowner code, output = exec_cmd( "doveadm user %s -f home" % self.full_address, **options) if code: raise AdminError( _("Failed to retrieve mailbox location (%s)" % output)) self.__mail_home = output.strip() return self.__mail_home
def import_account_mailbox(user, account, row): account.email = row[0].strip() if account.email != "": account.save() mailbox, domname = split_mailbox(account.email) try: domain = Domain.objects.get(name=domname) except Domain.DoesNotExist: raise AdminError( _("Account import failed (%s): domain does not exist" % account.username)) if not user.can_access(domain): raise PermDeniedException mb = Mailbox(address=mailbox, domain=domain, user=account, use_domain_quota=True) mb.set_quota(override_rules=user.has_perm("admin.change_domain")) mb.save(creator=user) if account.group == "DomainAdmins": for domname in row[1:]: try: dom = Domain.objects.get(name=domname.strip()) except Domain.DoesNotExist: continue dom.add_admin(account)
def save(self, user, domain): if self.cleaned_data["create_dom_admin"] == "no": return username = "******" % (self.cleaned_data["dom_admin_username"], domain.name) try: da = User.objects.get(username=username) except User.DoesNotExist: pass else: raise AdminError(_("User '%s' already exists" % username)) da = User(username=username, email=username, is_active=True) da.set_password("password") da.save() da.set_role("DomainAdmins") da.post_create(user) mb = Mailbox(address=self.cleaned_data["dom_admin_username"], domain=domain, user=da, use_domain_quota=True) mb.set_quota(override_rules=user.has_perm("admin.change_domain")) mb.save(creator=user) if self.cleaned_data["create_aliases"] == "yes": al = Alias(address="postmaster", domain=domain, enabled=True) al.save(int_rcpts=[mb], creator=user) domain.add_admin(da)
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 AdminError("%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 AdminError(_("Local recipient %s not found" % v)) if rcpt in self.int_rcpts: raise AdminError(_("Recipient %s already present" % v)) self.int_rcpts += [rcpt] total += 1 continue if v in self.ext_rcpts: raise AdminError(_("Recipient %s already present" % v)) self.ext_rcpts += [v] total += 1 if total == 0: raise AdminError(_("No recipient defined"))
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 AdminError(_("Invalid line")) self.name = row[1].strip() domname = row[2].strip() try: self.target = Domain.objects.get(name=domname) except Domain.DoesNotExist: raise AdminError(_("Unknown domain %s" % domname)) self.enabled = row[3].strip() == 'True' self.save(creator=user)
def save(self, commit=True): account = super(AccountFormGeneral, self).save(commit=False) if self.user == account and not self.cleaned_data["is_active"]: raise AdminError(_("You can't disable your own account")) if commit: if "password1" in self.cleaned_data \ and self.cleaned_data["password1"] != "": account.set_password(self.cleaned_data["password1"]) account.save() account.set_role(self.cleaned_data["role"]) return account
def from_csv(self, user, row, expected_elements=5): """Create a new alias from a CSV file entry """ if len(row) < expected_elements: raise AdminError(_("Invalid line: %s" % row)) localpart, domname = split_mailbox(row[1].strip()) try: domain = Domain.objects.get(name=domname) except Domain.DoesNotExist: raise AdminError(_("Domain '%s' does not exist" % domname)) if not user.can_access(domain): raise PermDeniedException self.address = localpart self.domain = domain self.enabled = (row[2].strip() == 'True') int_rcpts = [] ext_rcpts = [] for rcpt in row[3:]: rcpt = rcpt.strip() 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 AdminError(_("Local recipient %s not found" % rcpt)) int_rcpts += [target] self.save(int_rcpts=int_rcpts, ext_rcpts=ext_rcpts, 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 AdminError( _("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 AdminError(_("A quota is required"))
def newaccount(request, tplname='common/wizard_forms.html'): def create_account(steps): """Account creation callback Called when all creation steps have been validated. :param steps: the steps data """ genform = steps[0]["form"] genform.is_valid() account = genform.save() account.post_create(request.user) mailform = steps[1]["form"] try: mailform.save(request.user, account) except AdminError: # A bit uggly: transaction management doesn't work very # well with nested functions. Need to wait for django 1.6 # and atomicity. account.delete(request.user, False) raise ctx = dict(title=_("New account"), action=reverse(newaccount), formid="newaccount_form", submit_label=_("Create")) cwizard = CreationWizard(create_account) cwizard.add_step(AccountFormGeneral, _("General"), [dict(classes="btn-inverse next", label=_("Next"))], new_args=[request.user]) cwizard.add_step(AccountFormMail, _("Mail"), [ dict(classes="btn-primary submit", label=_("Create")), dict(classes="btn-inverse prev", label=_("Previous")) ], formtpl="admin/mailform.html") if request.method == "POST": retcode, data = cwizard.validate_step(request) if retcode == -1: raise AdminError(data) if retcode == 1: return ajax_simple_response( dict(status="ok", title=cwizard.get_title(data + 1), stepid=data)) if retcode == 2: return ajax_simple_response( dict(status="ok", respmsg=_("Account created"))) from modoboa.lib.templatetags.lib_tags import render_form return ajax_simple_response( dict(status="ko", stepid=data, form=render_form(cwizard.steps[data]["form"]))) cwizard.create_forms() ctx.update(steps=cwizard.steps) ctx.update(subtitle="1. %s" % cwizard.steps[0]['title']) return render(request, tplname, ctx)
def save(self, user, account): if self.cleaned_data["email"] == "": return None if self.cleaned_data["quota_act"]: self.cleaned_data["quota"] = None if not hasattr(self, "mb") or self.mb is None: locpart, domname = split_mailbox(self.cleaned_data["email"]) try: domain = Domain.objects.get(name=domname) except Domain.DoesNotExist: raise AdminError(_("Domain does not exist")) if not user.can_access(domain): raise PermDeniedException try: Mailbox.objects.get(address=locpart, domain=domain) except Mailbox.DoesNotExist: pass else: raise AdminError( _("Mailbox %s already exists" % self.cleaned_data["email"])) events.raiseEvent("CanCreate", user, "mailboxes") self.mb = Mailbox(address=locpart, domain=domain, user=account, use_domain_quota=self.cleaned_data["quota_act"]) self.mb.set_quota(self.cleaned_data["quota"], user.has_perm("admin.add_domain")) self.mb.save(creator=user) else: newaddress = None if self.cleaned_data["email"] != self.mb.full_address: newaddress = self.cleaned_data["email"] elif account.group == "SimpleUsers" and account.username != self.mb.full_address: newaddress = account.username if newaddress is not None: local_part, domname = split_mailbox(newaddress) try: domain = Domain.objects.get(name=domname) except Domain.DoesNotExist: raise AdminError(_("Domain does not exist")) if not user.can_access(domain): raise PermDeniedException self.mb.rename(local_part, domain) self.mb.use_domain_quota = self.cleaned_data["quota_act"] override_rules = True \ if not self.mb.quota or user.has_perm("admin.add_domain") \ else False self.mb.set_quota(self.cleaned_data["quota"], override_rules) self.mb.save() account.email = self.cleaned_data["email"] account.save() for name, value in self.cleaned_data.iteritems(): if not name.startswith("aliases"): continue if value == "": continue local_part, domname = split_mailbox(value) try: self.mb.alias_set.get(address=local_part, domain__name=domname) except Alias.DoesNotExist: pass else: continue events.raiseEvent("CanCreate", user, "mailbox_aliases") al = Alias(address=local_part, enabled=account.is_active) al.domain = Domain.objects.get(name=domname) al.save(int_rcpts=[self.mb], creator=user) for alias in self.mb.alias_set.all(): if len(alias.get_recipients()) >= 2: continue if not len( filter( lambda name: self.cleaned_data[name] == alias. full_address, self.cleaned_data.keys())): alias.delete() return self.mb