def from_csv(self, user, row, expected_elements=5): 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 does not exist")) 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: int_rcpts += [ Mailbox.objects.get(address=localpart, domain__name=domname) ] except Mailbox.DoesNotExist: raise AdminError(_("Mailbox %s does not exist" % rcpt)) self.save(int_rcpts, ext_rcpts, creator=user)
def from_csv(self, user, row, expected_elements=5): 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 does not exist")) 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: int_rcpts += [Mailbox.objects.get(address=localpart, domain__name=domname)] except Mailbox.DoesNotExist: raise AdminError(_("Mailbox %s does not exist" % rcpt)) self.save(int_rcpts, ext_rcpts, creator=user)
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, 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() == 'True') 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 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 _update_aliases(self, user, account): """Update mailbox aliases.""" aliases = [] for name, value in self.cleaned_data.iteritems(): if not name.startswith("aliases"): continue if value == "": continue aliases.append(value) for alias in self.mb.alias_set.all(): if not alias.full_address in aliases: if len(alias.get_recipients()) >= 2: continue alias.delete() else: aliases.remove(alias.full_address) if not aliases: return events.raiseEvent( "CanCreate", user, "mailbox_aliases", len(aliases) ) for alias in aliases: local_part, domname = split_mailbox(alias) try: self.mb.alias_set.get(address=local_part, domain__name=domname) except Alias.DoesNotExist: pass else: continue al = Alias(address=local_part, enabled=account.is_active) al.domain = Domain.objects.get(name=domname) al.save(int_rcpts=[self.mb]) al.post_create(user)
def _update_aliases(self, user, account): """Update mailbox aliases.""" aliases = [] for name, value in self.cleaned_data.iteritems(): if not name.startswith("aliases"): continue if value == "": continue aliases.append(value) for alias in self.mb.alias_set.all(): if not alias.full_address in aliases: if len(alias.get_recipients()) >= 2: continue alias.delete() else: aliases.remove(alias.full_address) if not aliases: return events.raiseEvent("CanCreate", user, "mailbox_aliases", len(aliases)) for alias in aliases: local_part, domname = split_mailbox(alias) try: self.mb.alias_set.get(address=local_part, domain__name=domname) except Alias.DoesNotExist: pass else: continue al = Alias(address=local_part, enabled=account.is_active) al.domain = Domain.objects.get(name=domname) al.save(int_rcpts=[self.mb]) al.post_create(user)
def get_or_create_user(self, username, ldap_user): """ This must return a (User, created) 2-tuple for the given LDAP user. username is the Django-friendly username of the user. ldap_user.dn is the user's DN and ldap_user.attrs contains all of their LDAP attributes. """ group = 'SimpleUsers' admin_groups = parameters \ .get_admin('LDAP_ADMIN_GROUPS', app='core').split(';') for grp in admin_groups: if grp.strip() in ldap_user.group_names: group = 'DomainAdmins' break if group == 'SimpleUsers': lpart, domain = split_mailbox(username) if domain is None: return None user, created = User.objects.get_or_create( username__iexact=username, defaults={ 'username': username.lower(), 'is_local': False }) if created: populate_callback(user, group) return user, created
def account_auto_created(user): from modoboa.core.models import User from modoboa.lib.permissions import grant_access_to_object localpart, domname = split_mailbox(user.username) if user.group != 'SimpleUsers' and domname is None: return sadmins = User.objects.filter(is_superuser=True) try: domain = Domain.objects.get(name=domname) except Domain.DoesNotExist: domain = Domain(name=domname, enabled=True, quota=0) domain.save(creator=sadmins[0]) for su in sadmins[1:]: grant_access_to_object(su, domain) try: mb = Mailbox.objects.get(domain=domain, address=localpart) except Mailbox.DoesNotExist: mb = Mailbox( address=localpart, domain=domain, user=user, use_domain_quota=True ) mb.set_quota(override_rules=True) mb.save(creator=sadmins[0]) for su in sadmins[1:]: grant_access_to_object(su, mb)
def account_auto_created(user): from modoboa.core.models import User from modoboa.extensions.admin.lib import check_if_domain_exists from modoboa.lib.permissions import grant_access_to_object if parameters.get_admin("AUTO_CREATE_DOMAIN_AND_MAILBOX") == "no": return localpart, domname = split_mailbox(user.username) if user.group != 'SimpleUsers' and domname is None: return sadmins = User.objects.filter(is_superuser=True) try: domain = Domain.objects.get(name=domname) except Domain.DoesNotExist: label = check_if_domain_exists( domname, [(DomainAlias, _('domain alias'))]) if label is not None: return domain = Domain(name=domname, enabled=True, quota=0) domain.save(creator=sadmins[0]) for su in sadmins[1:]: grant_access_to_object(su, domain) try: mb = Mailbox.objects.get(domain=domain, address=localpart) except Mailbox.DoesNotExist: mb = Mailbox( address=localpart, domain=domain, user=user, use_domain_quota=True ) mb.set_quota(override_rules=True) mb.save(creator=sadmins[0]) for su in sadmins[1:]: grant_access_to_object(su, mb)
def migrate_mailbox_aliases(domain, options): print "\tMigrating mailbox aliases" old_aliases = pf_models.Alias.objects.using(options._from).filter(domain=domain.name) for old_al in old_aliases: if old_al.address == old_al.goto: continue new_al = md_models.Alias() local_part, tmp = split_mailbox(old_al.address) if local_part is None or not len(local_part): if tmp is None or not len(tmp): print """Warning: skipping alias %s (cannot retrieve local part). You will need to recreate it manually. """ % old_al.address continue new_al.address = "*" else: new_al.address = local_part new_al.domain = domain new_al.enabled = old_al.active extmboxes = [] intmboxes = [] for goto in old_al.goto.split(","): try: mb = md_models.Mailbox.objects.using(options.to).get(user__username=goto) except md_models.Mailbox.DoesNotExist: extmboxes += [goto] else: intmboxes += [mb] new_al.dates = migrate_dates(old_al) new_al.save(intmboxes, extmboxes, using=options.to)
def migrate_mailbox_aliases(domain, options): print "\tMigrating mailbox aliases" old_aliases = pf_models.Alias.objects.using( options._from).filter(domain=domain.name) for old_al in old_aliases: if old_al.address == old_al.goto: continue new_al = md_models.Alias() local_part, tmp = split_mailbox(old_al.address) if local_part is None or not len(local_part): if tmp is None or not len(tmp): print """Warning: skipping alias %s (cannot retrieve local part). You will need to recreate it manually. """ % old_al.address continue new_al.address = "*" else: new_al.address = local_part new_al.domain = domain new_al.enabled = old_al.active extmboxes = [] intmboxes = [] for goto in old_al.goto.split(","): try: mb = md_models.Mailbox.objects.using( options.to).get(user__username=goto) except md_models.Mailbox.DoesNotExist: extmboxes += [goto] else: intmboxes += [mb] new_al.dates = migrate_dates(old_al) new_al.save(intmboxes, extmboxes, using=options.to)
def populate_callback(user): """Populate callback If the LDAP authentication backend is in use, this callback will be called each time a new user authenticates succesfuly to Modoboa. This function is in charge of creating the mailbox associated to the provided ``User`` object. :param user: a ``User`` instance """ from modoboa.lib.permissions import grant_access_to_object sadmins = User.objects.filter(is_superuser=True) user.set_role("SimpleUsers") user.post_create(sadmins[0]) for su in sadmins[1:]: grant_access_to_object(su, user) localpart, domname = split_mailbox(user.username) try: domain = Domain.objects.get(name=domname) except Domain.DoesNotExist: domain = Domain(name=domname, enabled=True, quota=0) domain.save(creator=sadmins[0]) for su in sadmins[1:]: grant_access_to_object(su, domain) try: mb = Mailbox.objects.get(domain=domain, address=localpart) except Mailbox.DoesNotExist: mb = Mailbox(address=localpart, domain=domain, user=user, use_domain_quota=True) mb.set_quota(override_rules=True) mb.save(creator=sadmins[0]) for su in sadmins[1:]: grant_access_to_object(su, mb)
def migrate_admins(options): print "Migrating administrators" dagroup = Group.objects.using(options.to).get(name="DomainAdmins") for old_admin in pf_models.Admin.objects.using(options._from).all(): local_part, domname = split_mailbox(old_admin.username) try: query = Q(username=old_admin.username) & \ (Q(domain="ALL") | Q(domain=domname)) creds = pf_models.DomainAdmins.objects.using(options._from).get(query) except pf_models.DomainAdmins.DoesNotExist: print "Warning: skipping useless admin %s" % (old_admin.username) continue try: user = md_models.User.objects.using(options.to).get(username=old_admin.username) except md_models.User.DoesNotExist: try: domain = md_models.Domain.objects.using(options.to).get(name=domname) except md_models.Domain.DoesNotExist: print "Warning: skipping domain admin %s, domain not found" \ % old_admin.username continue user = md_models.User() user.username = old_admin.username user.email = old_admin.username user.password = old_admin.password user.is_active = old_admin.active user.save(using=options.to) user.date_joined = old_admin.modified if creds.domain == "ALL": user.is_superuser = True else: user.groups.add(dagroup) user.save(using=options.to)
def get_or_create_user(self, username, ldap_user): """ This must return a (User, created) 2-tuple for the given LDAP user. username is the Django-friendly username of the user. ldap_user.dn is the user's DN and ldap_user.attrs contains all of their LDAP attributes. """ group = 'SimpleUsers' admin_groups = parameters \ .get_admin('LDAP_ADMIN_GROUPS', app='core').split(';') for grp in admin_groups: if grp.strip() in ldap_user.group_names: group = 'DomainAdmins' break if group == 'SimpleUsers': lpart, domain = split_mailbox(username) if domain is None: return None user, created = User.objects.get_or_create( username__iexact=username, defaults={'username': username.lower(), 'is_local': False} ) if created: populate_callback(user, group) return user, created
def account_auto_created(user): from modoboa.core.models import User from modoboa.extensions.admin.lib import check_if_domain_exists from modoboa.lib.permissions import grant_access_to_object if parameters.get_admin("AUTO_CREATE_DOMAIN_AND_MAILBOX") == "no": return localpart, domname = split_mailbox(user.username) if user.group != 'SimpleUsers' and domname is None: return sadmins = User.objects.filter(is_superuser=True) try: domain = Domain.objects.get(name=domname) except Domain.DoesNotExist: label = check_if_domain_exists(domname, [(DomainAlias, _('domain alias'))]) if label is not None: return domain = Domain(name=domname, enabled=True, quota=0) domain.save(creator=sadmins[0]) for su in sadmins[1:]: grant_access_to_object(su, domain) try: mb = Mailbox.objects.get(domain=domain, address=localpart) except Mailbox.DoesNotExist: mb = Mailbox(address=localpart, domain=domain, user=user, use_domain_quota=True) mb.set_quota(override_rules=True) mb.save(creator=sadmins[0]) for su in sadmins[1:]: grant_access_to_object(su, mb)
def get_identities(self, querydict=None): """Return all identities owned by this user :param querydict: a querydict object :return: a queryset """ from modoboa.lib.permissions import get_content_type from itertools import chain if querydict: squery = querydict.get("searchquery", None) idtfilter = querydict.getlist("idtfilter", None) grpfilter = querydict.getlist("grpfilter", None) else: squery = None idtfilter = None grpfilter = None accounts = [] if not idtfilter or "account" in idtfilter: userct = get_content_type(self) ids = self.objectaccess_set.filter(content_type=userct) \ .values_list('object_id', flat=True) q = Q(pk__in=ids) if squery: q &= Q(username__icontains=squery) | Q(email__icontains=squery) if grpfilter and len(grpfilter): if "SuperAdmins" in grpfilter: q &= Q(is_superuser=True) grpfilter.remove("SuperAdmins") if len(grpfilter): q |= Q(groups__name__in=grpfilter) else: q &= Q(groups__name__in=grpfilter) accounts = User.objects.select_related().filter(q) aliases = [] if not idtfilter or ("alias" in idtfilter or "forward" in idtfilter or "dlist" in idtfilter): alct = get_content_type(Alias) ids = self.objectaccess_set.filter(content_type=alct) \ .values_list('object_id', flat=True) q = Q(pk__in=ids) if squery: if '@' in squery: local_part, domname = split_mailbox(squery) if local_part: q &= Q(address__icontains=local_part) if domname: q &= Q(domain__name__icontains=domname) else: q &= Q(address__icontains=squery) | Q( domain__name__icontains=squery) aliases = Alias.objects.select_related().filter(q) if idtfilter: aliases = [al for al in aliases if al.type in idtfilter] return chain(accounts, aliases)
def get_identities(self, querydict=None): """Return all identities owned by this user :param querydict: a querydict object :return: a queryset """ from modoboa.lib.permissions import get_content_type from itertools import chain if querydict: squery = querydict.get("searchquery", None) idtfilter = querydict.getlist("idtfilter", None) grpfilter = querydict.getlist("grpfilter", None) else: squery = None idtfilter = None grpfilter = None accounts = [] if not idtfilter or "account" in idtfilter: userct = get_content_type(self) ids = self.objectaccess_set.filter(content_type=userct) \ .values_list('object_id', flat=True) q = Q(pk__in=ids) if squery: q &= Q(username__icontains=squery) | Q(email__icontains=squery) if grpfilter and len(grpfilter): if "SuperAdmins" in grpfilter: q &= Q(is_superuser=True) grpfilter.remove("SuperAdmins") if len(grpfilter): q |= Q(groups__name__in=grpfilter) else: q &= Q(groups__name__in=grpfilter) accounts = User.objects.select_related().filter(q) aliases = [] if not idtfilter or ("alias" in idtfilter or "forward" in idtfilter or "dlist" in idtfilter): alct = get_content_type(Alias) ids = self.objectaccess_set.filter(content_type=alct) \ .values_list('object_id', flat=True) q = Q(pk__in=ids) if squery: if '@' in squery: local_part, domname = split_mailbox(squery) if local_part: q &= Q(address__icontains=local_part) if domname: q &= Q(domain__name__icontains=domname) else: q &= Q(address__icontains=squery) | Q(domain__name__icontains=squery) aliases = Alias.objects.select_related().filter(q) if idtfilter: aliases = [al for al in aliases if al.type in idtfilter] return chain(accounts, aliases)
def save(self, commit=True): alias = super(AliasForm, self).save(commit=False) localpart, domname = split_mailbox(self.cleaned_data["email"]) alias.address = localpart alias.domain = Domain.objects.get(name=domname) if commit: alias.save(int_rcpts=self.int_rcpts, ext_rcpts=self.ext_rcpts) self.save_m2m() return alias
def clean_email(self): localpart, domname = split_mailbox(self.cleaned_data["email"]) try: domain = Domain.objects.get(name=domname) except Domain.DoesNotExist: raise forms.ValidationError(_("Domain does not exist")) if not self.user.can_access(domain): raise forms.ValidationError(_("You don't have access to this domain")) return self.cleaned_data["email"]
def from_csv(self, user, row, crypt_password=True): """Create a new account from a CSV file entry The expected order is the following:: loginname, password, first name, last name, enabled, group, address[, domain, ...] :param user: :param row: a list containing the expected information :param crypt_password: """ if len(row) < 6: raise AdminError(_("Invalid line")) role = row[6].strip() if not user.is_superuser and not role in [ "SimpleUsers", "DomainAdmins" ]: raise PermDeniedException( _("You can't import an account with a role greater than yours") ) self.username = row[1].strip() 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() == 'True') self.save(creator=user) self.set_role(role) self.email = row[7].strip() if self.email != "": mailbox, domname = split_mailbox(self.email) try: domain = Domain.objects.get(name=domname) except Domain.DoesNotExist: raise AdminError( _("Account import failed (%s): domain does not exist" % self.username)) if not user.can_access(domain): raise PermDeniedException mb = Mailbox(address=mailbox, domain=domain, user=self, use_domain_quota=True) mb.set_quota(override_rules=user.has_perm("admin.change_domain")) mb.save(creator=user) if self.group == "DomainAdmins": for domname in row[8:]: try: dom = Domain.objects.get(name=domname.strip()) except Domain.DoesNotExist: continue dom.add_admin(self)
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 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: account.save() 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 try: mb = Mailbox.objects.get(address=mailbox, domain=domain) except Mailbox.DoesNotExist: pass else: raise Conflict(_("Mailbox %s already exists" % 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.group == "DomainAdmins": for domname in row[2:]: try: dom = Domain.objects.get(name=domname.strip()) except Domain.DoesNotExist: continue dom.add_admin(account)
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: self.create_mailbox(user, account) else: self.update_mailbox(user, account) events.raiseEvent( 'SaveExtraFormFields', 'mailform', self.mb, self.cleaned_data ) account.email = self.cleaned_data["email"] account.save() aliases = [] for name, value in self.cleaned_data.iteritems(): if not name.startswith("aliases"): continue if value == "": continue aliases.append(value) for alias in self.mb.alias_set.all(): if not alias.full_address in aliases: if len(alias.get_recipients()) >= 2: continue alias.delete() else: aliases.remove(alias.full_address) if aliases: events.raiseEvent( "CanCreate", user, "mailbox_aliases", len(aliases) ) for alias in aliases: local_part, domname = split_mailbox(alias) try: self.mb.alias_set.get(address=local_part, domain__name=domname) except Alias.DoesNotExist: pass else: continue al = Alias(address=local_part, enabled=account.is_active) al.domain = Domain.objects.get(name=domname) al.save(int_rcpts=[self.mb], creator=user) return self.mb
def from_csv(self, user, row, crypt_password=True): """Create a new account from a CSV file entry The expected order is the following:: loginname, password, first name, last name, enabled, group, address[, domain, ...] :param user: :param row: a list containing the expected information :param crypt_password: """ if len(row) < 6: raise AdminError(_("Invalid line")) role = row[6].strip() if not user.is_superuser and not role in ["SimpleUsers", "DomainAdmins"]: raise PermDeniedException( _("You can't import an account with a role greater than yours") ) self.username = row[1].strip() 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() == 'True') self.save(creator=user) self.set_role(role) self.email = row[7].strip() if self.email != "": mailbox, domname = split_mailbox(self.email) try: domain = Domain.objects.get(name=domname) except Domain.DoesNotExist: raise AdminError( _("Account import failed (%s): domain does not exist" % self.username) ) if not user.can_access(domain): raise PermDeniedException mb = Mailbox(address=mailbox, domain=domain, user=self, use_domain_quota=True) mb.set_quota(override_rules=user.has_perm("admin.change_domain")) mb.save(creator=user) if self.group == "DomainAdmins": for domname in row[8:]: try: dom = Domain.objects.get(name=domname.strip()) except Domain.DoesNotExist: continue dom.add_admin(self)
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: account.save() 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 try: mb = Mailbox.objects.get(address=mailbox, domain=domain) except Mailbox.DoesNotExist: pass else: raise Conflict(_("Mailbox %s already exists" % 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.group == "DomainAdmins": for domname in row[2:]: try: dom = Domain.objects.get(name=domname.strip()) except Domain.DoesNotExist: continue dom.add_admin(account)
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: self.create_mailbox(user, account) else: self.update_mailbox(user, account) events.raiseEvent('SaveExtraFormFields', 'mailform', self.mb, self.cleaned_data) account.email = self.cleaned_data["email"] account.save() aliases = [] for name, value in self.cleaned_data.iteritems(): if not name.startswith("aliases"): continue if value == "": continue aliases.append(value) for alias in self.mb.alias_set.all(): if not alias.full_address in aliases: if len(alias.get_recipients()) >= 2: continue alias.delete() else: aliases.remove(alias.full_address) if aliases: events.raiseEvent("CanCreate", user, "mailbox_aliases", len(aliases)) for alias in aliases: local_part, domname = split_mailbox(alias) try: self.mb.alias_set.get(address=local_part, domain__name=domname) except Alias.DoesNotExist: pass else: continue al = Alias(address=local_part, enabled=account.is_active) al.domain = Domain.objects.get(name=domname) al.save(int_rcpts=[self.mb], creator=user) return self.mb
def parse_dest(self): self.dests = [] rawdata = self.cleaned_data["dest"].strip() if rawdata == "": return for d in rawdata.split(","): local_part, domname = split_mailbox(d) if not local_part or not domname or not len(domname): raise BadDestination("Invalid mailbox syntax for %s" % d) try: mb = Domain.objects.get(name=domname) except Domain.DoesNotExist: self.dests += [d] else: raise BadDestination(_("You can't define a forward to a local destination. Please ask your administrator to create an alias instead."))
def get_identities(user, searchquery=None, idtfilter=None, grpfilter=None): """Return all the identities owned by a user. :param user: the desired user :param str searchquery: search pattern :param list idtfilter: identity type filters :param list grpfilter: group names filters :return: a queryset """ from itertools import chain accounts = [] if idtfilter is None or not idtfilter or idtfilter == "account": ids = user.objectaccess_set \ .filter(content_type=ContentType.objects.get_for_model(user)) \ .values_list('object_id', flat=True) q = Q(pk__in=ids) if searchquery is not None: q &= Q(username__icontains=searchquery) \ | Q(email__icontains=searchquery) if grpfilter is not None and grpfilter: if grpfilter == "SuperAdmins": q &= Q(is_superuser=True) else: q &= Q(groups__name=grpfilter) accounts = User.objects.select_related().filter(q) aliases = [] if idtfilter is None or not idtfilter \ or (idtfilter in ["alias", "forward", "dlist"]): alct = ContentType.objects.get_for_model(Alias) ids = user.objectaccess_set.filter(content_type=alct) \ .values_list('object_id', flat=True) q = Q(pk__in=ids) if searchquery is not None: if '@' in searchquery: local_part, domname = split_mailbox(searchquery) if local_part: q &= Q(address__icontains=local_part) if domname: q &= Q(domain__name__icontains=domname) else: q &= Q(address__icontains=searchquery) | \ Q(domain__name__icontains=searchquery) aliases = Alias.objects.select_related().filter(q) if idtfilter is not None and idtfilter: aliases = [al for al in aliases if al.type == idtfilter] return chain(accounts, aliases)
def _get_mailbox_from_rcpt(self, rcpt): """Retrieve a mailbox from a recipient address.""" local_part, domname = split_mailbox(rcpt) try: mailbox = Mailbox.objects.select_related("domain").get( address=local_part, domain__name=domname) except Mailbox.DoesNotExist: try: alias = Alias.objects.select_related("domain").get( address=local_part, domain__name=domname) except Alias.DoesNotExist: raise InternalError(_("No recipient found")) if alias.type != "alias": return None mailbox = alias.mboxes.all()[0] return mailbox
def get_or_create_user(self, username, ldap_user): """ This must return a (User, created) 2-tuple for the given LDAP user. username is the Django-friendly username of the user. ldap_user.dn is the user's DN and ldap_user.attrs contains all of their LDAP attributes. """ lpart, domain = split_mailbox(username) if domain is None: return None user, created = User.objects.get_or_create( username__iexact=username, defaults={'username': username.lower(), 'is_local': False} ) if created: populate_callback(user) return user, created
def parse_dest(self): self.dests = [] rawdata = self.cleaned_data["dest"].strip() if rawdata == "": return for d in rawdata.split(","): local_part, domname = split_mailbox(d) if not local_part or not domname or not len(domname): raise BadDestination("Invalid mailbox syntax for %s" % d) try: mb = Domain.objects.get(name=domname) except Domain.DoesNotExist: self.dests += [d] else: raise BadDestination( _("You can't define a forward to a local destination. Please ask your administrator to create an alias instead." ))
def handle(self, *args, **options): if len(args) < 2: raise CommandError("usage: ./manage.py autoreply <sender> <recipient ...>") sender = args[0] for fulladdress in args[1:]: address, domain = split_mailbox(fulladdress) try: mbox = Mailbox.objects.get(address=address, domain__name=domain) except Mailbox.DoesNotExist: print "Unknown recipient %s" % (fulladdress) continue try: armessage = ARmessage.objects.get(mbox=mbox.id, enabled=True) except ARmessage.DoesNotExist: continue send_autoreply(sender, mbox, armessage)
def _migrate_admins(self, options, creator): """Administrators migration.""" print "Migrating administrators" dagroup = Group.objects.using(options["_to"]).get(name="DomainAdmins") for old_admin in pf_models.Admin.objects.using(options["_from"]).all(): local_part, domname = split_mailbox(old_admin.username) try: query = Q(username=old_admin.username) & \ (Q(domain="ALL") | Q(domain=domname)) creds = pf_models.DomainAdmins.objects \ .using(options["_from"]).get(query) except pf_models.DomainAdmins.DoesNotExist: print ( "Warning: skipping useless admin %s" % (old_admin.username) ) continue try: domain = admin_models.Domain.objects \ .using(options["_to"]).get(name=domname) except admin_models.Domain.DoesNotExist: print ( "Warning: skipping domain admin %s, domain not found" % old_admin.username ) continue try: user = core_models.User.objects \ .using(options["_to"]).get(username=old_admin.username) except core_models.User.DoesNotExist: user = core_models.User() user.username = old_admin.username user.email = old_admin.username user.password = old_admin.password user.is_active = old_admin.active user.save(creator=creator, using=options["_to"]) user.date_joined = old_admin.modified if creds.domain == "ALL": user.is_superuser = True else: user.groups.add(dagroup) domain.add_admin(user) user.save(using=options["_to"])
def handle(self, *args, **options): if len(args) < 2: raise CommandError( "usage: ./manage.py autoreply <sender> <recipient ...>") sender = args[0] for fulladdress in args[1:]: address, domain = split_mailbox(fulladdress) try: mbox = Mailbox.objects.get(address=address, domain__name=domain) except Mailbox.DoesNotExist: print "Unknown recipient %s" % (mbox) continue try: armessage = ARmessage.objects.get(mbox=mbox.id, enabled=True) except ARmessage.DoesNotExist: continue send_autoreply(sender, mbox, armessage)
def create_mailbox(self, user, 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)
def save(self): """Custom save method. """ import re from modoboa.lib.emailutils import split_mailbox from modoboa.lib.exceptions import BadRequest from modoboa.extensions.admin.models import Mailbox from .models import AccessRule 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 not rule.mailbox.full_address 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 migrate_admins(options): print "Migrating administrators" dagroup = Group.objects.using(options.to).get(name="DomainAdmins") for old_admin in pf_models.Admin.objects.using(options._from).all(): local_part, domname = split_mailbox(old_admin.username) try: query = Q(username=old_admin.username) & \ (Q(domain="ALL") | Q(domain=domname)) creds = pf_models.DomainAdmins.objects.using( options._from).get(query) except pf_models.DomainAdmins.DoesNotExist: print "Warning: skipping useless admin %s" % (old_admin.username) continue try: user = md_models.User.objects.using( options.to).get(username=old_admin.username) except md_models.User.DoesNotExist: try: domain = md_models.Domain.objects.using( options.to).get(name=domname) except md_models.Domain.DoesNotExist: print "Warning: skipping domain admin %s, domain not found" \ % old_admin.username continue user = md_models.User() user.username = old_admin.username user.email = old_admin.username user.password = old_admin.password user.is_active = old_admin.active user.save(using=options.to) user.date_joined = old_admin.modified if creds.domain == "ALL": user.is_superuser = True else: user.groups.add(dagroup) user.save(using=options.to)
def _migrate_mailbox_aliases(self, domain, options, creator): """Migrate mailbox aliases of a single domain.""" print "\tMigrating mailbox aliases" old_aliases = pf_models.Alias.objects \ .using(options["_from"]).filter(domain=domain.name) for old_al in old_aliases: if old_al.address == old_al.goto: continue new_al = admin_models.Alias() local_part, tmp = split_mailbox(old_al.address) if local_part is None or not len(local_part): if tmp is None or not len(tmp): print ( "Warning: skipping alias %s (cannot retrieve local " "part). You will need to recreate it manually." % old_al.address ) continue new_al.address = "*" else: new_al.address = local_part new_al.domain = domain new_al.enabled = old_al.active extmboxes = [] intmboxes = [] for goto in old_al.goto.split(","): try: mb = admin_models.Mailbox.objects \ .using(options["_to"]).get(user__username=goto) except admin_models.Mailbox.DoesNotExist: extmboxes += [goto] else: intmboxes += [mb] new_al.dates = self._migrate_dates(old_al) new_al.save( int_rcpts=intmboxes, ext_rcpts=extmboxes, creator=creator, using=options["_to"] )
def save(self): """Custom save method.""" import re from modoboa.lib.emailutils import split_mailbox from modoboa.lib.exceptions import BadRequest from modoboa.extensions.admin.models import Mailbox from .models import AccessRule 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 not rule.mailbox.full_address 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 create_mailbox(self, user, 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)
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 update_mailbox(self, user, account): 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: self.mb.old_full_address = self.mb.full_address local_part, domname = split_mailbox(newaddress) try: domain = Domain.objects.get(name=domname) except Domain.DoesNotExist: raise NotFound(_("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() events.raiseEvent('MailboxModified', self.mb)
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: mb = 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([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
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: mb = 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([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