Ejemplo n.º 1
0
    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"))
Ejemplo n.º 2
0
    def save(self, user, domain):
        if not self.fields:
            return
        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 Conflict(_("User '%s' already exists" % username))
        events.raiseEvent("CanCreate", user, "mailboxes")
        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":
            events.raiseEvent("CanCreate", user, "mailbox_aliases")
            alias = Alias(address="postmaster", domain=domain, enabled=True)
            alias.save(int_rcpts=[mb])
            alias.post_create(user)

        domain.add_admin(da)
Ejemplo n.º 3
0
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)
Ejemplo n.º 4
0
def importdata(request, formclass=ImportDataForm):
    """Generic import function

    As the process of importing data from a CSV file is the same
    whatever the type, we do a maximum of the work here.

    :param request: a ``Request`` instance
    :param typ: a string indicating the object type being imported
    :return: a ``Response`` instance
    """
    error = None
    form = formclass(request.POST, request.FILES)
    if form.is_valid():
        try:
            reader = csv.reader(request.FILES['sourcefile'],
                                delimiter=form.cleaned_data['sepchar'])
        except csv.Error as inst:
            error = str(inst)

        if error is None:
            try:
                cpt = 0
                for row in reader:
                    if not row:
                        continue
                    try:
                        fct = getattr(lib, "import_%s" % row[0].strip())
                    except AttributeError:
                        fct = events.raiseQueryEvent('ImportObject',
                                                     row[0].strip())
                        if not fct:
                            continue
                        fct = fct[0]
                    with transaction.atomic():
                        try:
                            fct(request.user, row, form.cleaned_data)
                        except Conflict:
                            if form.cleaned_data["continue_if_exists"]:
                                continue
                            raise Conflict(
                                _("Object already exists: %s" %
                                  form.cleaned_data['sepchar'].join(row[:2])))
                    cpt += 1
                msg = _("%d objects imported successfully" % cpt)
                return render(request, "admin/import_done.html", {
                    "status": "ok",
                    "msg": msg
                })
            except (ModoboaException) as e:
                error = str(e)

    return render(request, "admin/import_done.html", {
        "status": "ko",
        "msg": error
    })
Ejemplo n.º 5
0
    def save(self, *args, **kwargs):
        if not self.fields:
            return
        if not self.cleaned_data["create_dom_admin"]:
            return
        user = kwargs.pop("user")
        domain = kwargs.pop("domain")
        username = "******" % (self.cleaned_data["dom_admin_username"],
                              domain.name)
        try:
            da = User.objects.get(username=username)
        except User.DoesNotExist:
            pass
        else:
            raise Conflict(_("User '%s' already exists") % username)
        core_signals.can_create_object.send(self.__class__,
                                            context=user,
                                            klass=Mailbox)
        da = User(username=username, email=username, is_active=True)
        if self.cleaned_data["random_password"]:
            password = lib.make_password()
        else:
            password = param_tools.get_global_parameter("default_password",
                                                        app="core")
        da.set_password(password)
        da.save()
        da.role = "DomainAdmins"
        da.post_create(user)

        if self.cleaned_data["with_mailbox"]:
            dom_admin_username = self.cleaned_data["dom_admin_username"]
            mb = Mailbox(address=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)

            condition = (domain.type == "domain"
                         and self.cleaned_data["create_aliases"]
                         and dom_admin_username != "postmaster")
            if condition:
                core_signals.can_create_object.send(self.__class__,
                                                    context=user,
                                                    klass=Alias)
                address = u"postmaster@{}".format(domain.name)
                alias = Alias.objects.create(address=address,
                                             domain=domain,
                                             enabled=True)
                alias.set_recipients([mb.full_address])
                alias.post_create(user)

        domain.add_admin(da)
Ejemplo n.º 6
0
def importdata(request, formclass=ImportDataForm):
    """Generic import function

    As the process of importing data from a CSV file is the same
    whatever the type, we do a maximum of the work here.

    :param request: a ``Request`` instance
    :param typ: a string indicating the object type being imported
    :return: a ``Response`` instance
    """
    error = None
    form = formclass(request.POST, request.FILES)
    if form.is_valid():
        try:
            infile = io.TextIOWrapper(request.FILES['sourcefile'].file,
                                      encoding="utf8")
            reader = csv.reader(infile, delimiter=form.cleaned_data['sepchar'])
        except csv.Error as inst:
            error = smart_text(inst)
        else:
            try:
                cpt = 0
                for row in reader:
                    if not row:
                        continue
                    fct = signals.import_object.send(sender="importdata",
                                                     objtype=row[0].strip())
                    fct = [func for x_, func in fct if func is not None]
                    if not fct:
                        continue
                    fct = fct[0]
                    with transaction.atomic():
                        try:
                            fct(request.user, row, form.cleaned_data)
                        except Conflict:
                            if form.cleaned_data["continue_if_exists"]:
                                continue
                            raise Conflict(
                                _("Object already exists: %s" %
                                  form.cleaned_data['sepchar'].join(row[:2])))
                    cpt += 1
                msg = _("%d objects imported successfully" % cpt)
                return render(request, "admin/import_done.html", {
                    "status": "ok",
                    "msg": msg
                })
            except (ModoboaException) as e:
                error = str(e)

    return render(request, "admin/import_done.html", {
        "status": "ko",
        "msg": error
    })
Ejemplo n.º 7
0
def _validate_alias(request, form, successmsg, callback=None):
    """Alias validation

    Common function shared between creation and modification actions.
    """
    if form.is_valid():
        try:
            alias = form.save()
        except IntegrityError:
            raise Conflict(_("Alias with this name already exists"))
        if callback:
            callback(request.user, alias)
        return render_to_json_response(successmsg)

    return render_to_json_response({'form_errors': form.errors}, status=400)
Ejemplo n.º 8
0
    def save(self, *args, **kwargs):
        if not self.fields:
            return
        if self.cleaned_data["create_dom_admin"] == "no":
            return
        user = kwargs.pop("user")
        domain = kwargs.pop("domain")
        username = "******" % (self.cleaned_data["dom_admin_username"],
                              domain.name)
        try:
            da = User.objects.get(username=username)
        except User.DoesNotExist:
            pass
        else:
            raise Conflict(_("User '%s' already exists") % username)
        core_signals.can_create_object.send(self.__class__,
                                            context=user,
                                            object_type="mailboxes")
        da = User(username=username, email=username, is_active=True)
        da.set_password("password")
        da.save()
        da.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 domain.type == "domain" and \
           self.cleaned_data["create_aliases"] == "yes":
            core_signals.can_create_object.send(self.__class__,
                                                context=user,
                                                object_type="mailbox_aliases")
            alias = Alias(address=u"postmaster@{}".format(domain.name),
                          domain=domain,
                          enabled=True)
            alias.save()
            alias.set_recipients([mb.full_address])
            alias.post_create(user)

        domain.add_admin(da)
Ejemplo n.º 9
0
def import_data(user, file_object, options: dict):
    """Generic import function

    As the process of importing data from a CSV file is the same
    whatever the type, we do a maximum of the work here.
    """
    try:
        infile = io.TextIOWrapper(file_object.file, encoding="utf8")
        reader = csv.reader(infile, delimiter=options["sepchar"])
    except csv.Error as inst:
        error = str(inst)
    else:
        try:
            cpt = 0
            for row in reader:
                if not row:
                    continue
                fct = signals.import_object.send(sender="importdata",
                                                 objtype=row[0].strip())
                fct = [func for x_, func in fct if func is not None]
                if not fct:
                    continue
                fct = fct[0]
                with transaction.atomic():
                    try:
                        fct(user, row, options)
                    except Conflict:
                        if options["continue_if_exists"]:
                            continue
                        raise Conflict(
                            _("Object already exists: %s") %
                            options["sepchar"].join(row[:2]))
                cpt += 1
            msg = _("%d objects imported successfully") % cpt
            return True, msg
        except (ModoboaException) as e:
            error = str(e)
    return False, error
Ejemplo n.º 10
0
 def create_mailbox(self, user, account):
     """Create a mailbox associated to :kw:`account`."""
     locpart, domname = split_mailbox(self.cleaned_data["email"])
     try:
         domain = Domain.objects.get(name=domname)
     except Domain.DoesNotExist:
         raise NotFound(_("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 Conflict(
             _("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)
Ejemplo n.º 11
0
def import_csv(filename, options):
    """Import objects from a CSV file."""
    superadmin = User.objects.filter(is_superuser=True).first()
    if not os.path.exists(filename):
        print('File not found')
        sys.exit(1)

    num_lines = sum(1 for line in open(filename))
    pbar = ProgressBar(widgets=[Percentage(), Bar(),
                                ETA()], maxval=num_lines).start()
    with open(filename, 'r') as f:
        reader = csv.reader(f, delimiter=';')
        i = 0
        for row in reader:
            i += 1
            pbar.update(i)
            if not row:
                continue

            try:
                fct = getattr(lib, "import_%s" % row[0].strip())
            except AttributeError:
                fct = events.raiseQueryEvent('ImportObject', row[0].strip())
                if not fct:
                    continue
                fct = fct[0]

            try:
                fct(superadmin, row, options)
            except Conflict:
                if options['continue_if_exists']:
                    continue

                raise Conflict("Object already exists: %s" %
                               options['sepchar'].join(row[:2]))

    pbar.finish()