VirtualMailManager/VirtualMailManager.py
changeset 54 1fc1f82c662f
parent 53 5b50eb306d37
child 55 15c873f94ba6
equal deleted inserted replaced
53:5b50eb306d37 54:1fc1f82c662f
   260         if gid is None:
   260         if gid is None:
   261             gid = 0
   261             gid = 0
   262         os.makedirs(directory, mode)
   262         os.makedirs(directory, mode)
   263         os.chown(directory, uid, gid)
   263         os.chown(directory, uid, gid)
   264 
   264 
   265     def __domdirmake(self, domdir, gid):
   265     def __domDirMake(self, domdir, gid):
   266         os.umask(0006)
   266         os.umask(0006)
   267         oldpwd = os.getcwd()
   267         oldpwd = os.getcwd()
   268         basedir = self.__Cfg.get('domdir', 'base')
   268         basedir = self.__Cfg.get('domdir', 'base')
   269         domdirdirs = domdir.replace(basedir+'/', '').split('/')
   269         domdirdirs = domdir.replace(basedir+'/', '').split('/')
   270 
   270 
   276         os.umask(0007)
   276         os.umask(0007)
   277         self.__makedir(domdirdirs[1], self.__Cfg.getint('domdir', 'mode'), 0,
   277         self.__makedir(domdirdirs[1], self.__Cfg.getint('domdir', 'mode'), 0,
   278                 gid)
   278                 gid)
   279         os.chdir(oldpwd)
   279         os.chdir(oldpwd)
   280 
   280 
   281     def __maildirmake(self, domdir, uid, gid):
   281     def __mailDirMake(self, domdir, uid, gid):
   282         """Creates maildirs and maildir subfolders.
   282         """Creates maildirs and maildir subfolders.
   283 
   283 
   284         Keyword arguments:
   284         Keyword arguments:
   285         uid -- user id from the account
   285         uid -- user id from the account
   286         gid -- group id from the account
   286         gid -- group id from the account
   301             self.__makedir(folder, mode, uid, gid)
   301             self.__makedir(folder, mode, uid, gid)
   302             for subdir in subdirs:
   302             for subdir in subdirs:
   303                 self.__makedir(folder+'/'+subdir, mode, uid, gid)
   303                 self.__makedir(folder+'/'+subdir, mode, uid, gid)
   304         os.chdir(oldpwd)
   304         os.chdir(oldpwd)
   305 
   305 
   306     def __userdirdelete(self, domdir, uid, gid):
   306     def __userDirDelete(self, domdir, uid, gid):
   307         if uid > 0 and gid > 0:
   307         if uid > 0 and gid > 0:
   308             userdir = '%s' % uid
   308             userdir = '%s' % uid
   309             if userdir.count('..') or domdir.count('..'):
   309             if userdir.count('..') or domdir.count('..'):
   310                 raise VMMException(_(u'Found ".." in home directory path.'),
   310                 raise VMMException(_(u'Found ".." in home directory path.'),
   311                     ERR.FOUND_DOTS_IN_PATH)
   311                     ERR.FOUND_DOTS_IN_PATH)
   320                     rmtree(userdir, ignore_errors=True)
   320                     rmtree(userdir, ignore_errors=True)
   321                 else:
   321                 else:
   322                     raise VMMException(_(u"No such directory: %s") %
   322                     raise VMMException(_(u"No such directory: %s") %
   323                         domdir+'/'+userdir, ERR.NO_SUCH_DIRECTORY)
   323                         domdir+'/'+userdir, ERR.NO_SUCH_DIRECTORY)
   324 
   324 
   325     def __domdirdelete(self, domdir, gid):
   325     def __domDirDelete(self, domdir, gid):
   326         if gid > 0:
   326         if gid > 0:
   327             if not self.__isdir(domdir):
   327             if not self.__isdir(domdir):
   328                 return
   328                 return
   329             basedir = '%s' % self.__Cfg.get('domdir', 'base')
   329             basedir = '%s' % self.__Cfg.get('domdir', 'base')
   330             domdirdirs = domdir.replace(basedir+'/', '').split('/')
   330             domdirdirs = domdir.replace(basedir+'/', '').split('/')
   444             self.__Cfg.configure([section])
   444             self.__Cfg.configure([section])
   445         else:
   445         else:
   446             raise VMMException(_(u"Invalid section: '%s'") % section,
   446             raise VMMException(_(u"Invalid section: '%s'") % section,
   447                 ERR.INVALID_SECTION)
   447                 ERR.INVALID_SECTION)
   448 
   448 
   449     def domain_add(self, domainname, transport=None):
   449     def domainAdd(self, domainname, transport=None):
   450         dom = self.__getDomain(domainname, transport)
   450         dom = self.__getDomain(domainname, transport)
   451         dom.save()
   451         dom.save()
   452         self.__domdirmake(dom.getDir(), dom.getID())
   452         self.__domDirMake(dom.getDir(), dom.getID())
   453 
   453 
   454     def domain_transport(self, domainname, transport, force=None):
   454     def domainTransport(self, domainname, transport, force=None):
   455         if force is not None and force != 'force':
   455         if force is not None and force != 'force':
   456             raise VMMDomainException(_(u"Invalid argument: '%s'") % force,
   456             raise VMMDomainException(_(u"Invalid argument: '%s'") % force,
   457                 ERR.INVALID_OPTION)
   457                 ERR.INVALID_OPTION)
   458         dom = self.__getDomain(domainname, None)
   458         dom = self.__getDomain(domainname, None)
   459         if force is None:
   459         if force is None:
   460             dom.updateTransport(transport)
   460             dom.updateTransport(transport)
   461         else:
   461         else:
   462             dom.updateTransport(transport, force=True)
   462             dom.updateTransport(transport, force=True)
   463 
   463 
   464     def domain_delete(self, domainname, force=None):
   464     def domainDelete(self, domainname, force=None):
   465         if not force is None and force not in ['deluser','delalias','delall']:
   465         if not force is None and force not in ['deluser','delalias','delall']:
   466             raise VMMDomainException(_(u"Invalid argument: »%s«") % force,
   466             raise VMMDomainException(_(u"Invalid argument: »%s«") % force,
   467                 ERR.INVALID_OPTION)
   467                 ERR.INVALID_OPTION)
   468         dom = self.__getDomain(domainname)
   468         dom = self.__getDomain(domainname)
   469         gid = dom.getID()
   469         gid = dom.getID()
   475         elif force == 'delalias':
   475         elif force == 'delalias':
   476             dom.delete(delAlias=True)
   476             dom.delete(delAlias=True)
   477         else:
   477         else:
   478             dom.delete()
   478             dom.delete()
   479         if self.__Cfg.getboolean('domdir', 'delete'):
   479         if self.__Cfg.getboolean('domdir', 'delete'):
   480             self.__domdirdelete(domdir, gid)
   480             self.__domDirDelete(domdir, gid)
   481 
   481 
   482     def domain_info(self, domainname, detailed=None):
   482     def domainInfo(self, domainname, detailed=None):
   483         dom = self.__getDomain(domainname)
   483         dom = self.__getDomain(domainname)
   484         dominfo = dom.getInfo()
   484         dominfo = dom.getInfo()
   485         if dominfo['domainname'].startswith('xn--'):
   485         if dominfo['domainname'].startswith('xn--'):
   486             dominfo['domainname'] += ' (%s)'\
   486             dominfo['domainname'] += ' (%s)'\
   487                 % VirtualMailManager.ace2idna(dominfo['domainname'])
   487                 % VirtualMailManager.ace2idna(dominfo['domainname'])
   494                     dom.getAliases())
   494                     dom.getAliases())
   495         else:
   495         else:
   496             raise VMMDomainException(_(u'Invalid argument: »%s«') % detailed,
   496             raise VMMDomainException(_(u'Invalid argument: »%s«') % detailed,
   497                 ERR.INVALID_OPTION)
   497                 ERR.INVALID_OPTION)
   498 
   498 
   499     def domain_alias_add(self, aliasname, domainname):
   499     def domainAliasAdd(self, aliasname, domainname):
   500         """Adds an alias name to the domain.
   500         """Adds an alias name to the domain.
   501 
   501 
   502         Keyword arguments:
   502         Keyword arguments:
   503         aliasname -- the alias name of the domain (str)
   503         aliasname -- the alias name of the domain (str)
   504         domainname -- name of the target domain (str)
   504         domainname -- name of the target domain (str)
   505         """
   505         """
   506         dom = self.__getDomain(domainname)
   506         dom = self.__getDomain(domainname)
   507         domAlias = DomainAlias(self.__dbh, aliasname, dom)
   507         domAlias = DomainAlias(self.__dbh, aliasname, dom)
   508         domAlias.save()
   508         domAlias.save()
   509 
   509 
   510     def domain_alias_info(self, aliasname):
   510     def domainAliasInfo(self, aliasname):
   511         self.__dbConnect()
   511         self.__dbConnect()
   512         domAlias = DomainAlias(self.__dbh, aliasname, None)
   512         domAlias = DomainAlias(self.__dbh, aliasname, None)
   513         return domAlias.info()
   513         return domAlias.info()
   514 
   514 
   515     def domain_alias_delete(self, aliasname):
   515     def domainAliasDelete(self, aliasname):
   516         """Deletes the specified alias name.
   516         """Deletes the specified alias name.
   517 
   517 
   518         Keyword arguments:
   518         Keyword arguments:
   519         aliasname -- the alias name of the domain (str)
   519         aliasname -- the alias name of the domain (str)
   520         """
   520         """
   521         self.__dbConnect()
   521         self.__dbConnect()
   522         domAlias = DomainAlias(self.__dbh, aliasname, None)
   522         domAlias = DomainAlias(self.__dbh, aliasname, None)
   523         domAlias.delete()
   523         domAlias.delete()
   524 
   524 
   525     def domain_list(self, pattern=None):
   525     def domainList(self, pattern=None):
   526         from Domain import search
   526         from Domain import search
   527         like = False
   527         like = False
   528         if pattern is not None:
   528         if pattern is not None:
   529             if pattern.startswith('%') or pattern.endswith('%'):
   529             if pattern.startswith('%') or pattern.endswith('%'):
   530                 like = True
   530                 like = True
   540                     _(u"The pattern »%s« contains invalid characters.") %
   540                     _(u"The pattern »%s« contains invalid characters.") %
   541                     pattern, ERR.DOMAIN_INVALID)
   541                     pattern, ERR.DOMAIN_INVALID)
   542         self.__dbConnect()
   542         self.__dbConnect()
   543         return search(self.__dbh, pattern=pattern, like=like)
   543         return search(self.__dbh, pattern=pattern, like=like)
   544 
   544 
   545     def user_add(self, emailaddress, password):
   545     def userAdd(self, emailaddress, password):
   546         acc = self.__getAccount(emailaddress, password)
   546         acc = self.__getAccount(emailaddress, password)
   547         if password is None:
   547         if password is None:
   548             password = self._readpass()
   548             password = self._readpass()
   549             acc.setPassword(self.__pwhash(password))
   549             acc.setPassword(self.__pwhash(password))
   550         acc.save(self.__Cfg.get('maildir', 'folder'),
   550         acc.save(self.__Cfg.get('maildir', 'folder'),
   551                 self.__Cfg.getboolean('services', 'smtp'),
   551                 self.__Cfg.getboolean('services', 'smtp'),
   552                 self.__Cfg.getboolean('services', 'pop3'),
   552                 self.__Cfg.getboolean('services', 'pop3'),
   553                 self.__Cfg.getboolean('services', 'imap'),
   553                 self.__Cfg.getboolean('services', 'imap'),
   554                 self.__Cfg.getboolean('services', 'managesieve'))
   554                 self.__Cfg.getboolean('services', 'managesieve'))
   555         self.__maildirmake(acc.getDir('domain'), acc.getUID(), acc.getGID())
   555         self.__mailDirMake(acc.getDir('domain'), acc.getUID(), acc.getGID())
   556 
   556 
   557     def alias_add(self, aliasaddress, targetaddress):
   557     def aliasAdd(self, aliasaddress, targetaddress):
   558         alias = self.__getAlias(aliasaddress, targetaddress)
   558         alias = self.__getAlias(aliasaddress, targetaddress)
   559         alias.save()
   559         alias.save()
   560 
   560 
   561     def user_delete(self, emailaddress):
   561     def userDelete(self, emailaddress):
   562         acc = self.__getAccount(emailaddress)
   562         acc = self.__getAccount(emailaddress)
   563         uid = acc.getUID()
   563         uid = acc.getUID()
   564         gid = acc.getGID()
   564         gid = acc.getGID()
   565         acc.delete()
   565         acc.delete()
   566         if self.__Cfg.getboolean('maildir', 'delete'):
   566         if self.__Cfg.getboolean('maildir', 'delete'):
   567             try:
   567             try:
   568                 self.__userdirdelete(acc.getDir('domain'), uid, gid)
   568                 self.__userDirDelete(acc.getDir('domain'), uid, gid)
   569             except VMMException, e:
   569             except VMMException, e:
   570                 if e.code() in [ERR.FOUND_DOTS_IN_PATH,
   570                 if e.code() in [ERR.FOUND_DOTS_IN_PATH,
   571                         ERR.MAILDIR_PERM_MISMATCH, ERR.NO_SUCH_DIRECTORY]:
   571                         ERR.MAILDIR_PERM_MISMATCH, ERR.NO_SUCH_DIRECTORY]:
   572                     warning = _(u"""\
   572                     warning = _(u"""\
   573 The account has been successfully deleted from the database.
   573 The account has been successfully deleted from the database.
   576     Reason: %(raeson)s""") % {'directory': acc.getDir('home'),'raeson': e.msg()}
   576     Reason: %(raeson)s""") % {'directory': acc.getDir('home'),'raeson': e.msg()}
   577                     self.__warnings.append(warning)
   577                     self.__warnings.append(warning)
   578                 else:
   578                 else:
   579                     raise e
   579                     raise e
   580 
   580 
   581     def alias_info(self, aliasaddress):
   581     def aliasInfo(self, aliasaddress):
   582         alias = self.__getAlias(aliasaddress)
   582         alias = self.__getAlias(aliasaddress)
   583         return alias.getInfo()
   583         return alias.getInfo()
   584 
   584 
   585     def alias_delete(self, aliasaddress, targetaddress=None):
   585     def aliasDelete(self, aliasaddress, targetaddress=None):
   586         alias = self.__getAlias(aliasaddress, targetaddress)
   586         alias = self.__getAlias(aliasaddress, targetaddress)
   587         alias.delete()
   587         alias.delete()
   588 
   588 
   589     def user_info(self, emailaddress, diskusage=False):
   589     def userInfo(self, emailaddress, diskusage=False):
   590         acc = self.__getAccount(emailaddress)
   590         acc = self.__getAccount(emailaddress)
   591         info = acc.getInfo()
   591         info = acc.getInfo()
   592         if self.__Cfg.getboolean('maildir', 'diskusage') or diskusage:
   592         if self.__Cfg.getboolean('maildir', 'diskusage') or diskusage:
   593             info['disk usage'] = self.__getDiskUsage('%(maildir)s' % info)
   593             info['disk usage'] = self.__getDiskUsage('%(maildir)s' % info)
   594         return info
   594         return info
   595 
   595 
   596     def user_byID(self, uid):
   596     def userByID(self, uid):
   597         from Account import getAccountByID
   597         from Account import getAccountByID
   598         self.__dbConnect()
   598         self.__dbConnect()
   599         return getAccountByID(uid, self.__dbh)
   599         return getAccountByID(uid, self.__dbh)
   600 
   600 
   601     def user_password(self, emailaddress, password):
   601     def userPassword(self, emailaddress, password):
   602         acc = self.__getAccount(emailaddress)
   602         acc = self.__getAccount(emailaddress)
   603         if acc.getUID() == 0:
   603         if acc.getUID() == 0:
   604            raise VMMException(_(u"Account doesn't exists"),
   604            raise VMMException(_(u"Account doesn't exists"),
   605                ERR.NO_SUCH_ACCOUNT)
   605                ERR.NO_SUCH_ACCOUNT)
   606         if password is None:
   606         if password is None:
   607             password = self._readpass()
   607             password = self._readpass()
   608         acc.modify('password', self.__pwhash(password))
   608         acc.modify('password', self.__pwhash(password))
   609 
   609 
   610     def user_name(self, emailaddress, name):
   610     def userName(self, emailaddress, name):
   611         acc = self.__getAccount(emailaddress)
   611         acc = self.__getAccount(emailaddress)
   612         acc.modify('name', name)
   612         acc.modify('name', name)
   613 
   613 
   614     def user_transport(self, emailaddress, transport):
   614     def userTransport(self, emailaddress, transport):
   615         acc = self.__getAccount(emailaddress)
   615         acc = self.__getAccount(emailaddress)
   616         acc.modify('transport', transport)
   616         acc.modify('transport', transport)
   617 
   617 
   618     def user_disable(self, emailaddress, service=None):
   618     def userDisable(self, emailaddress, service=None):
   619         acc = self.__getAccount(emailaddress)
   619         acc = self.__getAccount(emailaddress)
   620         acc.disable(service)
   620         acc.disable(service)
   621 
   621 
   622     def user_enable(self, emailaddress, service=None):
   622     def userEnable(self, emailaddress, service=None):
   623         acc = self.__getAccount(emailaddress)
   623         acc = self.__getAccount(emailaddress)
   624         acc.enable(service)
   624         acc.enable(service)
   625 
   625 
   626     def __del__(self):
   626     def __del__(self):
   627         if not self.__dbh is None and self.__dbh._isOpen:
   627         if not self.__dbh is None and self.__dbh._isOpen: