Moved VirtualMailManager/Exceptions to VirtualMailManager/errors. v0.6.x
authorPascal Volk <neverseen@users.sourceforge.net>
Fri, 26 Feb 2010 02:35:25 +0000
branchv0.6.x
changeset 216 0c8c053b451c
parent 215 33f727efa7c4
child 217 eecd05e31517
Moved VirtualMailManager/Exceptions to VirtualMailManager/errors. Renamed VMM*Exception classes to *Error. No longer add the attribute 'message' to VMMError if it doesn't exist, like in Python 2.4. It has been deprecated as of Python 2.6. Also removed the methods code() and msg(), the values are now accessible via the attributes 'code' and 'msg'.
VirtualMailManager/Account.py
VirtualMailManager/Alias.py
VirtualMailManager/AliasDomain.py
VirtualMailManager/Config.py
VirtualMailManager/Domain.py
VirtualMailManager/EmailAddress.py
VirtualMailManager/Exceptions.py
VirtualMailManager/Handler.py
VirtualMailManager/MailLocation.py
VirtualMailManager/Relocated.py
VirtualMailManager/Transport.py
VirtualMailManager/__init__.py
VirtualMailManager/cli/Config.py
VirtualMailManager/cli/Handler.py
VirtualMailManager/errors.py
VirtualMailManager/ext/Postconf.py
doc/source/index.rst
doc/source/vmm.rst
doc/source/vmm_config.rst
doc/source/vmm_constants_error.rst
doc/source/vmm_emailaddress.rst
doc/source/vmm_errors.rst
doc/source/vmm_exceptions.rst
doc/source/vmm_relocated.rst
--- a/VirtualMailManager/Account.py	Thu Feb 25 17:56:08 2010 +0000
+++ b/VirtualMailManager/Account.py	Fri Feb 26 02:35:25 2010 +0000
@@ -7,14 +7,14 @@
 import VirtualMailManager.constants.ERROR as ERR
 from VirtualMailManager.Domain import Domain
 from VirtualMailManager.EmailAddress import EmailAddress
-from VirtualMailManager.Exceptions import VMMAccountException as AccE
+from VirtualMailManager.errors import AccountError as AccE
 from VirtualMailManager.MailLocation import MailLocation
 from VirtualMailManager.Transport import Transport
-import VirtualMailManager as VMM
 
 class Account(object):
     """Class to manage e-mail accounts."""
     __slots__ = ('_addr','_base','_gid','_mid','_passwd','_tid','_uid','_dbh')
+
     def __init__(self, dbh, address, password=None):
         self._dbh = dbh
         self._base = None
@@ -29,24 +29,23 @@
         self._passwd = password
         self._setAddr()
         self._exists()
-        if self._uid < 1 and VMM.VirtualMailManager.aliasExists(self._dbh,
-                self._addr):
+        from VirtualMailManager.Handler import Handler
+        if self._uid < 1 and Handler.aliasExists(self._dbh, self._addr):
             # TP: Hm, what quotation marks should be used?
             # If you are unsure have a look at:
             # http://en.wikipedia.org/wiki/Quotation_mark,_non-English_usage
-            raise AccE(_(u"There is already an alias with the address “%s”.") %\
-                    self._addr, ERR.ALIAS_EXISTS)
-        if self._uid < 1 and VMM.VirtualMailManager.relocatedExists(self._dbh,
-                self._addr):
+            raise AccE(_(u"There is already an alias with the address “%s”.") %
+                       self._addr, ERR.ALIAS_EXISTS)
+        if self._uid < 1 and Handler.relocatedExists(self._dbh, self._addr):
             raise AccE(
-              _(u"There is already a relocated user with the address “%s”.") %\
-                    self._addr, ERR.RELOCATED_EXISTS)
+              _(u"There is already a relocated user with the address “%s”.") %
+                       self._addr, ERR.RELOCATED_EXISTS)
 
     def _exists(self):
         dbc = self._dbh.cursor()
-        dbc.execute("SELECT uid, mid, tid FROM users \
-WHERE gid=%s AND local_part=%s",
-                self._gid, self._addr._localpart)
+        dbc.execute(
+            "SELECT uid, mid, tid FROM users WHERE gid=%s AND local_part=%s",
+                    self._gid, self._addr._localpart)
         result = dbc.fetchone()
         dbc.close()
         if result is not None:
@@ -59,8 +58,8 @@
         dom = Domain(self._dbh, self._addr._domainname)
         self._gid = dom.getID()
         if self._gid == 0:
-            raise AccE(_(u"The domain “%s” doesn't exist.") %\
-                    self._addr._domainname, ERR.NO_SUCH_DOMAIN)
+            raise AccE(_(u"The domain “%s” doesn't exist.") %
+                       self._addr._domainname, ERR.NO_SUCH_DOMAIN)
         self._base = dom.getDir()
         self._tid = dom.getTransportID()
 
--- a/VirtualMailManager/Alias.py	Thu Feb 25 17:56:08 2010 +0000
+++ b/VirtualMailManager/Alias.py	Fri Feb 26 02:35:25 2010 +0000
@@ -10,7 +10,7 @@
 
 from VirtualMailManager.Domain import get_gid
 from VirtualMailManager.EmailAddress import EmailAddress
-from VirtualMailManager.Exceptions import VMMAliasException as VMMAE
+from VirtualMailManager.errors import AliasError as AErr
 from VirtualMailManager.constants.ERROR import ALIAS_ADDR_DEST_IDENTICAL, \
      ALIAS_EXCEEDS_EXPANSION_LIMIT, ALIAS_EXISTS, NO_SUCH_ALIAS
 
@@ -63,9 +63,9 @@
 So its unusable, all messages addressed to this alias will be bounced.
 Hint: Delete some destination addresses.""")
         if failed:
-            raise VMMAE(errmsg % {'address': str(self._addr), 'count': dcount,
-                                  'limit': limit},
-                        ALIAS_EXCEEDS_EXPANSION_LIMIT)
+            raise AErr(errmsg % {'address': str(self._addr), 'count': dcount,
+                                 'limit': limit},
+                       ALIAS_EXCEEDS_EXPANSION_LIMIT)
 
     def __delete(self, destination=None):
         """Deletes a destination from the alias, if ``destination`` is
@@ -93,13 +93,13 @@
         """Adds the ``destination`` `EmailAddress` to the alias."""
         assert isinstance(destination, EmailAddress)
         if self._addr == destination:
-            raise VMMAE(_(u"Address and destination are identical."),
-                        ALIAS_ADDR_DEST_IDENTICAL)
+            raise AErr(_(u"Address and destination are identical."),
+                       ALIAS_ADDR_DEST_IDENTICAL)
         if destination in self._dests:
-            raise VMMAE(_(
+            raise AErr(_(
                 u'The alias %(a)r has already the destination %(d)r.') %
-                        {'a': str(self._addr), 'd': str(destination)},
-                        ALIAS_EXISTS)
+                       {'a': str(self._addr), 'd': str(destination)},
+                       ALIAS_EXISTS)
         self.__check_expansion(expansion_limit)
         dbc = self._dbh.cursor()
         dbc.execute('INSERT INTO alias (gid, address, destination) \
@@ -113,28 +113,28 @@
         """Deletes the specified ``destination`` address from the alias."""
         assert isinstance(destination, EmailAddress)
         if not self._dests:
-            raise VMMAE(_(u"The alias %r doesn't exist.") % str(self._addr),
-                        NO_SUCH_ALIAS)
+            raise AErr(_(u"The alias %r doesn't exist.") % str(self._addr),
+                       NO_SUCH_ALIAS)
         if not destination in self._dests:
-            raise VMMAE(_(u"The address %(d)r isn't a destination of \
+            raise AErr(_(u"The address %(d)r isn't a destination of \
 the alias %(a)r.") %
-                        {'a': str(self._addr), 'd': str(destination)},
-                        NO_SUCH_ALIAS)
+                       {'a': str(self._addr), 'd': str(destination)},
+                       NO_SUCH_ALIAS)
         self.__delete(destination)
         self._dests.remove(destination)
 
     def get_destinations(self):
         """Returns an iterator for all destinations of the alias."""
         if not self._dests:
-            raise VMMAE(_(u"The alias %r doesn't exist.") % str(self._addr),
-                        NO_SUCH_ALIAS)
+            raise AErr(_(u"The alias %r doesn't exist.") % str(self._addr),
+                       NO_SUCH_ALIAS)
         return iter(self._dests)
 
     def delete(self):
         """Deletes the alias with all it's destinations."""
         if not self._dests:
-            raise VMMAE(_(u"The alias %r doesn't exist.") % str(self._addr),
-                        NO_SUCH_ALIAS)
+            raise AErr(_(u"The alias %r doesn't exist.") % str(self._addr),
+                       NO_SUCH_ALIAS)
         self.__delete()
         del self._dests[:]
 
--- a/VirtualMailManager/AliasDomain.py	Thu Feb 25 17:56:08 2010 +0000
+++ b/VirtualMailManager/AliasDomain.py	Fri Feb 26 02:35:25 2010 +0000
@@ -6,7 +6,7 @@
 
 import VirtualMailManager.constants.ERROR as ERR
 from VirtualMailManager import check_domainname
-from VirtualMailManager.Exceptions import VMMAliasDomainException as VADE
+from VirtualMailManager.errors import AliasDomainError as ADE
 
 class AliasDomain(object):
     """Class to manage e-mail alias domains."""
@@ -27,18 +27,18 @@
         if alias is not None:
             self.__gid, primary = alias
             if primary:
-                raise VADE(_(u"The domain “%s” is a primary domain.") %
+                raise ADE(_(u"The domain “%s” is a primary domain.") %
                         self.__name, ERR.ALIASDOMAIN_ISDOMAIN)
 
     def save(self):
         if self.__gid > 0:
-            raise VADE(_(u'The alias domain “%s” already exists.') %self.__name,
+            raise ADE(_(u'The alias domain “%s” already exists.') %self.__name,
                     ERR.ALIASDOMAIN_EXISTS)
         if self._domain is None:
-            raise VADE(_(u'No destination domain specified for alias domain.'),
+            raise ADE(_(u'No destination domain specified for alias domain.'),
                     ERR.ALIASDOMAIN_NO_DOMDEST)
         if self._domain._id < 1:
-            raise VADE (_(u"The target domain “%s” doesn't exist.") %
+            raise ADE (_(u"The target domain “%s” doesn't exist.") %
                     self._domain._name, ERR.NO_SUCH_DOMAIN)
         dbc = self._dbh.cursor()
         dbc.execute('INSERT INTO domain_name (domainname, gid, is_primary)\
@@ -56,25 +56,25 @@
             if domain is not None:
                 return {'alias': self.__name, 'domain': domain[0]}
             else:# an almost unlikely case, isn't it?
-                raise VADE(
+                raise ADE(
                     _(u'There is no primary domain for the alias domain “%s”.')\
                             % self.__name, ERR.NO_SUCH_DOMAIN)
         else:
-            raise VADE(_(u"The alias domain “%s” doesn't exist.") %
-                    self.__name, ERR.NO_SUCH_ALIASDOMAIN)
+            raise ADE(_(u"The alias domain “%s” doesn't exist.") % self.__name,
+                        ERR.NO_SUCH_ALIASDOMAIN)
 
     def switch(self):
         if self._domain is None:
-            raise VADE(_(u'No destination domain specified for alias domain.'),
+            raise ADE(_(u'No destination domain specified for alias domain.'),
                     ERR.ALIASDOMAIN_NO_DOMDEST)
         if self._domain._id < 1:
-            raise VADE (_(u"The target domain “%s” doesn't exist.") %
+            raise ADE (_(u"The target domain “%s” doesn't exist.") %
                     self._domain._name, ERR.NO_SUCH_DOMAIN)
         if self.__gid < 1:
-            raise VADE(_(u"The alias domain “%s” doesn't exist.") %
-                    self.__name, ERR.NO_SUCH_ALIASDOMAIN)
+            raise ADE(_(u"The alias domain “%s” doesn't exist.") % self.__name,
+                        ERR.NO_SUCH_ALIASDOMAIN)
         if self.__gid == self._domain._id:
-            raise VADE(_(u"The alias domain “%(alias)s” is already assigned to\
+            raise ADE(_(u"The alias domain “%(alias)s” is already assigned to\
  the domain “%(domain)s”.") %
                     {'alias': self.__name, 'domain': self._domain._name},
                     ERR.ALIASDOMAIN_EXISTS)
@@ -93,7 +93,6 @@
             if dbc.rowcount > 0:
                 self._dbh.commit()
         else:
-            raise VADE(
-                  _(u"The alias domain “%s” doesn't exist.") % self.__name,
-                  ERR.NO_SUCH_ALIASDOMAIN)
+            raise ADE(_(u"The alias domain “%s” doesn't exist.") % self.__name,
+                        ERR.NO_SUCH_ALIASDOMAIN)
 
--- a/VirtualMailManager/Config.py	Thu Feb 25 17:56:08 2010 +0000
+++ b/VirtualMailManager/Config.py	Fri Feb 26 02:35:25 2010 +0000
@@ -16,7 +16,7 @@
 
 from VirtualMailManager import exec_ok, get_unicode, is_dir
 from VirtualMailManager.constants.ERROR import CONF_ERROR
-from VirtualMailManager.Exceptions import VMMConfigException
+from VirtualMailManager.errors import ConfigError
 
 
 _ = lambda msg: msg
@@ -188,6 +188,8 @@
         `LazyConfigOption.cls`.
 
         """
+        # pylint: disable-msg=W0221
+        # @pylint: _L A Z Y_
         section, option = self._get_section_option(option)
         val = self._cfg[section][option].cls(value)
         if self._cfg[section][option].validate:
@@ -206,6 +208,8 @@
         configuration option.
 
         """
+        # pylint: disable-msg=W0221
+        # @pylint: _L A Z Y_
         try:
             self._get_section_option(option)
             return True
@@ -349,7 +353,7 @@
     def load(self):
         """Loads the configuration, read only.
 
-        Raises a VMMConfigException if the configuration syntax is
+        Raises a ConfigError if the configuration syntax is
         invalid.
 
         """
@@ -357,7 +361,7 @@
             self._cfg_file = open(self._cfg_filename, 'r')
             self.readfp(self._cfg_file)
         except (MissingSectionHeaderError, ParsingError), err:
-            raise VMMConfigException(str(err), CONF_ERROR)
+            raise ConfigError(str(err), CONF_ERROR)
         finally:
             if self._cfg_file and not self._cfg_file.closed:
                 self._cfg_file.close()
@@ -365,7 +369,7 @@
     def check(self):
         """Performs a configuration check.
 
-        Raises a VMMConfigException if the check fails.
+        Raises a ConfigError if the check fails.
 
         """
         # TODO: There are only two settings w/o defaults.
@@ -379,7 +383,7 @@
                 errmsg.write(_(u'* Section: %s\n') % section)
                 for option in options:
                     errmsg.write((u'    %s\n') % option)
-            raise VMMConfigException(errmsg.getvalue(), CONF_ERROR)
+            raise ConfigError(errmsg.getvalue(), CONF_ERROR)
 
     def known_scheme(self, scheme):
         """Converts `scheme` to upper case and checks if is known by
--- a/VirtualMailManager/Domain.py	Thu Feb 25 17:56:08 2010 +0000
+++ b/VirtualMailManager/Domain.py	Fri Feb 26 02:35:25 2010 +0000
@@ -10,7 +10,7 @@
 from VirtualMailManager.constants.ERROR import \
      ACCOUNT_AND_ALIAS_PRESENT, ACCOUNT_PRESENT, ALIAS_PRESENT, \
      DOMAIN_ALIAS_EXISTS, DOMAIN_EXISTS, NO_SUCH_DOMAIN
-from VirtualMailManager.Exceptions import VMMDomainException as VMMDE
+from VirtualMailManager.errors import DomainError as DomErr
 from VirtualMailManager.Transport import Transport
 
 
@@ -38,8 +38,8 @@
         self._id = 0
         self._domaindir = None
         if not self._exists() and self._isAlias():
-            raise VMMDE(_(u"The domain “%s” is an alias domain.") % self._name,
-                        DOMAIN_ALIAS_EXISTS)
+            raise DomErr(_(u"The domain “%s” is an alias domain.") %
+                         self._name, DOMAIN_ALIAS_EXISTS)
 
     def _exists(self):
         """Checks if the domain already exists.
@@ -123,12 +123,12 @@
         else:
             hasAlias = False
         if hasUser and hasAlias:
-            raise VMMDE(_(u'There are accounts and aliases.'),
-                ACCOUNT_AND_ALIAS_PRESENT)
+            raise DomErr(_(u'There are accounts and aliases.'),
+                         ACCOUNT_AND_ALIAS_PRESENT)
         elif hasUser:
-            raise VMMDE(_(u'There are accounts.'), ACCOUNT_PRESENT)
+            raise DomErr(_(u'There are accounts.'), ACCOUNT_PRESENT)
         elif hasAlias:
-            raise VMMDE(_(u'There are aliases.'), ALIAS_PRESENT)
+            raise DomErr(_(u'There are aliases.'), ALIAS_PRESENT)
 
     def save(self):
         """Stores the new domain in the database."""
@@ -142,8 +142,8 @@
             self._dbh.commit()
             dbc.close()
         else:
-            raise VMMDE(_(u'The domain “%s” already exists.') % self._name,
-                        DOMAIN_EXISTS)
+            raise DomErr(_(u'The domain “%s” already exists.') % self._name,
+                         DOMAIN_EXISTS)
 
     def delete(self, delUser=False, delAlias=False):
         """Deletes the domain.
@@ -160,8 +160,8 @@
             self._dbh.commit()
             dbc.close()
         else:
-            raise VMMDE(_(u"The domain “%s” doesn't exist.") % self._name,
-                        NO_SUCH_DOMAIN)
+            raise DomErr(_(u"The domain “%s” doesn't exist.") % self._name,
+                         NO_SUCH_DOMAIN)
 
     def updateTransport(self, transport, force=False):
         """Sets a new transport for the domain.
@@ -186,8 +186,8 @@
                     self._dbh.commit()
             dbc.close()
         else:
-            raise VMMDE(_(u"The domain “%s” doesn't exist.") % self._name,
-                        NO_SUCH_DOMAIN)
+            raise DomErr(_(u"The domain “%s” doesn't exist.") % self._name,
+                         NO_SUCH_DOMAIN)
 
     def getID(self):
         """Returns the ID of the domain."""
@@ -217,8 +217,8 @@
         info = dbc.fetchone()
         dbc.close()
         if info is None:
-            raise VMMDE(_(u"The domain “%s” doesn't exist.") % self._name,
-                        NO_SUCH_DOMAIN)
+            raise DomErr(_(u"The domain “%s” doesn't exist.") % self._name,
+                         NO_SUCH_DOMAIN)
         else:
             keys = ['gid', 'domainname', 'transport', 'domaindir',
                     'aliasdomains', 'accounts', 'aliases', 'relocated']
@@ -315,7 +315,7 @@
 def get_gid(dbh, domainname):
     """Returns the *GID* of the domain *domainname*.
 
-    Raises an `VMMDomainException` if the domain does not exist.
+    Raises an `DomainError` if the domain does not exist.
     """
     domainname = check_domainname(domainname)
     dbc = dbh.cursor()
@@ -325,5 +325,5 @@
     if gid:
         return gid[0]
     else:
-        raise VMMDE(_(u"The domain “%s” doesn't exist.") % domainname,
-                    NO_SUCH_DOMAIN)
+        raise DomErr(_(u"The domain “%s” doesn't exist.") % domainname,
+                     NO_SUCH_DOMAIN)
--- a/VirtualMailManager/EmailAddress.py	Thu Feb 25 17:56:08 2010 +0000
+++ b/VirtualMailManager/EmailAddress.py	Fri Feb 26 02:35:25 2010 +0000
@@ -11,7 +11,7 @@
 from VirtualMailManager import check_domainname, check_localpart
 from VirtualMailManager.constants.ERROR import \
      DOMAIN_NO_NAME, INVALID_ADDRESS, LOCALPART_INVALID
-from VirtualMailManager.Exceptions import VMMEmailAddressException as VMMEAE
+from VirtualMailManager.errors import EmailAddressError as EAErr
 
 
 _ = lambda msg: msg
@@ -63,17 +63,17 @@
         parts = address.split('@')
         p_len = len(parts)
         if p_len < 2:
-            raise VMMEAE(_(u"Missing the '@' sign in address %r") % address,
-                         INVALID_ADDRESS)
+            raise EAErr(_(u"Missing the '@' sign in address %r") % address,
+                        INVALID_ADDRESS)
         elif p_len > 2:
-            raise VMMEAE(_(u"Too many '@' signs in address %r") % address,
-                         INVALID_ADDRESS)
+            raise EAErr(_(u"Too many '@' signs in address %r") % address,
+                        INVALID_ADDRESS)
         if not parts[0]:
-            raise VMMEAE(_(u"Missing local-part in address %r") % address,
-                         LOCALPART_INVALID)
+            raise EAErr(_(u'Missing local-part in address %r') % address,
+                        LOCALPART_INVALID)
         if not parts[1]:
-            raise VMMEAE(_(u"Missing domain name in address %r") % address,
-                         DOMAIN_NO_NAME)
+            raise EAErr(_(u'Missing domain name in address %r') % address,
+                        DOMAIN_NO_NAME)
         self._localpart = check_localpart(parts[0])
         self._domainname = check_domainname(parts[1])
 
--- a/VirtualMailManager/Exceptions.py	Thu Feb 25 17:56:08 2010 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,83 +0,0 @@
-# -*- coding: UTF-8 -*-
-# Copyright (c) 2007 - 2010, Pascal Volk
-# See COPYING for distribution information.
-
-"""
-    VirtualMailManager.Exceptions
-
-    VMM's Exception classes
-"""
-
-
-class VMMException(Exception):
-    """Exception base class for VirtualMailManager exceptions"""
-
-    def __init__(self, msg, code):
-        Exception.__init__(self, msg)
-        self._code = int(code)
-        ### for older python versions, like py 2.4.4 on OpenBSD 4.2
-        if not hasattr(self, 'message'):
-            self.message = msg
-
-    def msg(self):
-        """Returns the exception message."""
-        return self.message
-
-    def code(self):
-        """Returns the numeric exception error code."""
-        return self._code
-
-
-class VMMConfigException(VMMException):
-    """Exception class for configuration exceptions"""
-    pass
-
-
-class VMMPermException(VMMException):
-    """Exception class for permissions exceptions"""
-    pass
-
-
-class VMMNotRootException(VMMException):
-    """Exception class for non-root exceptions"""
-    pass
-
-
-class VMMDomainException(VMMException):
-    """Exception class for Domain exceptions"""
-    pass
-
-
-class VMMAliasDomainException(VMMException):
-    """Exception class for AliasDomain exceptions"""
-    pass
-
-
-class VMMAccountException(VMMException):
-    """Exception class for Account exceptions"""
-    pass
-
-
-class VMMAliasException(VMMException):
-    """Exception class for Alias exceptions"""
-    pass
-
-
-class VMMEmailAddressException(VMMException):
-    """Exception class for EmailAddress exceptions"""
-    pass
-
-
-class VMMMailLocationException(VMMException):
-    """Exception class for MailLocation exceptions"""
-    pass
-
-
-class VMMRelocatedException(VMMException):
-    """Exception class for Relocated exceptions"""
-    pass
-
-
-class VMMTransportException(VMMException):
-    """Exception class for Transport exceptions"""
-    pass
--- a/VirtualMailManager/Handler.py	Thu Feb 25 17:56:08 2010 +0000
+++ b/VirtualMailManager/Handler.py	Fri Feb 26 02:35:25 2010 +0000
@@ -28,7 +28,7 @@
 from VirtualMailManager.Config import Config as Cfg
 from VirtualMailManager.Domain import Domain
 from VirtualMailManager.EmailAddress import EmailAddress
-from VirtualMailManager.Exceptions import *
+from VirtualMailManager.errors import VMMError, AliasError
 from VirtualMailManager.Relocated import Relocated
 from VirtualMailManager.ext.Postconf import Postconf
 
@@ -52,7 +52,7 @@
             argument may be ``True``. By default it is ``False`` and
             all checks will be performed.
 
-        Throws a VMMNotRootException if your uid is greater 0.
+        Throws a NotRootError if your uid is greater 0.
         """
         self._cfgFileName = ''
         self.__warnings = []
@@ -60,7 +60,7 @@
         self._dbh = None
 
         if os.geteuid():
-            raise VMMNotRootException(_(u"You are not root.\n\tGood bye!\n"),
+            raise NotRootError(_(u"You are not root.\n\tGood bye!\n"),
                 ERR.CONF_NOPERM)
         if self.__chkCfgFile():
             self._Cfg = Cfg(self._cfgFileName)
@@ -78,7 +78,7 @@
                 self._cfgFileName = tmp
                 break
         if not len(self._cfgFileName):
-            raise VMMException(
+            raise VMMError(
                 _(u"No “vmm.cfg” found in: /root:/usr/local/etc:/etc"),
                 ERR.CONF_NOFILE)
 
@@ -89,7 +89,7 @@
         fmode = int(oct(fstat.st_mode & 0777))
         if fmode % 100 and fstat.st_uid != fstat.st_gid or \
             fmode % 10 and fstat.st_uid == fstat.st_gid:
-                raise VMMPermException(_(
+                raise PermissionError(_(
                     u'fix permissions (%(perms)s) for “%(file)s”\n\
 `chmod 0600 %(file)s` would be great.') % {'file':
                     self._cfgFileName, 'perms': fmode}, ERR.CONF_WRONGPERM)
@@ -105,21 +105,20 @@
             os.chown(basedir, 0, self._Cfg.dget('misc.gid_mail'))
             os.umask(old_umask)
         elif not os.path.isdir(basedir):
-            raise VMMException(_(u'“%s” is not a directory.\n\
+            raise VMMError(_(u'“%s” is not a directory.\n\
 (vmm.cfg: section "misc", option "base_directory")') %
                                  basedir, ERR.NO_SUCH_DIRECTORY)
         for opt, val in self._Cfg.items('bin'):
             try:
                 exec_ok(val)
-            except VMMException, e:
-                code = e.code()
-                if code is ERR.NO_SUCH_BINARY:
-                    raise VMMException(_(u'“%(binary)s” doesn\'t exist.\n\
+            except VMMError, e:
+                if e.code is ERR.NO_SUCH_BINARY:
+                    raise VMMError(_(u'“%(binary)s” doesn\'t exist.\n\
 (vmm.cfg: section "bin", option "%(option)s")') %
                                        {'binary': val, 'option': opt},
                                        ERR.NO_SUCH_BINARY)
-                elif code is ERR.NOT_EXECUTABLE:
-                    raise VMMException(_(u'“%(binary)s” is not executable.\
+                elif e.code is ERR.NOT_EXECUTABLE:
+                    raise VMMError(_(u'“%(binary)s” is not executable.\
 \n(vmm.cfg: section "bin", option "%(option)s")') %
                                        {'binary': val, 'option': opt},
                                        ERR.NOT_EXECUTABLE)
@@ -141,7 +140,7 @@
                 dbc.execute("SET NAMES 'UTF8'")
                 dbc.close()
             except PgSQL.libpq.DatabaseError, e:
-                raise VMMException(str(e), ERR.DATABASE_ERROR)
+                raise VMMError(str(e), ERR.DATABASE_ERROR)
 
     def _exists(dbh, query):
         dbc = dbh.cursor()
@@ -298,19 +297,19 @@
         if uid > 0 and gid > 0:
             userdir = '%s' % uid
             if userdir.count('..') or domdir.count('..'):
-                raise VMMException(_(u'Found ".." in home directory path.'),
+                raise VMMError(_(u'Found ".." in home directory path.'),
                                    ERR.FOUND_DOTS_IN_PATH)
             if os.path.isdir(domdir):
                 os.chdir(domdir)
                 if os.path.isdir(userdir):
                     mdstat = os.stat(userdir)
                     if (mdstat.st_uid, mdstat.st_gid) != (uid, gid):
-                        raise VMMException(_(
+                        raise VMMError(_(
                           u'Detected owner/group mismatch in home directory.'),
                           ERR.MAILDIR_PERM_MISMATCH)
                     rmtree(userdir, ignore_errors=True)
                 else:
-                    raise VMMException(_(u"No such directory: %s") %
+                    raise VMMError(_(u"No such directory: %s") %
                         os.path.join(domdir, userdir), ERR.NO_SUCH_DIRECTORY)
 
     def __domDirDelete(self, domdir, gid):
@@ -321,12 +320,12 @@
             domdirdirs = domdir.replace(basedir + '/', '').split('/')
             domdirparent = os.path.join(basedir, domdirdirs[0])
             if basedir.count('..') or domdir.count('..'):
-                raise VMMException(_(u'Found ".." in domain directory path.'),
+                raise VMMError(_(u'Found ".." in domain directory path.'),
                         ERR.FOUND_DOTS_IN_PATH)
             if os.path.isdir(domdirparent):
                 os.chdir(domdirparent)
                 if os.lstat(domdirdirs[1]).st_gid != gid:
-                    raise VMMException(_(
+                    raise VMMError(_(
                         u'Detected group mismatch in domain directory.'),
                         ERR.DOMAINDIR_GROUP_MISMATCH)
                 rmtree(domdirdirs[1], ignore_errors=True)
@@ -411,7 +410,7 @@
 
     def domainTransport(self, domainname, transport, force=None):
         if force is not None and force != 'force':
-            raise VMMDomainException(_(u"Invalid argument: “%s”") % force,
+            raise DomainError(_(u"Invalid argument: “%s”") % force,
                 ERR.INVALID_OPTION)
         dom = self.__getDomain(domainname, None)
         if force is None:
@@ -422,7 +421,7 @@
     def domainDelete(self, domainname, force=None):
         if not force is None and force not in ['deluser', 'delalias',
                                                'delall']:
-                raise VMMDomainException(_(u'Invalid argument: “%s”') %
+                raise DomainError(_(u'Invalid argument: “%s”') %
                                          force, ERR.INVALID_OPTION)
         dom = self.__getDomain(domainname)
         gid = dom.getID()
@@ -441,7 +440,7 @@
     def domainInfo(self, domainname, details=None):
         if details not in [None, 'accounts', 'aliasdomains', 'aliases', 'full',
                            'relocated']:
-            raise VMMException(_(u'Invalid argument: “%s”') % details,
+            raise VMMError(_(u'Invalid argument: “%s”') % details,
                                ERR.INVALID_AGUMENT)
         dom = self.__getDomain(domainname)
         dominfo = dom.getInfo()
@@ -511,7 +510,7 @@
                 elif pattern.endswith('%'):
                     domain = pattern[:-1]
                 if not re.match(RE_DOMAIN_SRCH, domain):
-                    raise VMMException(
+                    raise VMMError(
                     _(u"The pattern “%s” contains invalid characters.") %
                     pattern, ERR.DOMAIN_INVALID)
         self.__dbConnect()
@@ -546,7 +545,7 @@
 
     def userDelete(self, emailaddress, force=None):
         if force not in [None, 'delalias']:
-            raise VMMException(_(u"Invalid argument: “%s”") % force,
+            raise VMMError(_(u"Invalid argument: “%s”") % force,
                     ERR.INVALID_AGUMENT)
         acc = self.__getAccount(emailaddress)
         uid = acc.getUID()
@@ -555,15 +554,15 @@
         if self._Cfg.dget('account.delete_directory'):
             try:
                 self.__userDirDelete(acc.getDir('domain'), uid, gid)
-            except VMMException, e:
-                if e.code() in [ERR.FOUND_DOTS_IN_PATH,
+            except VMMError, e:
+                if e.code in [ERR.FOUND_DOTS_IN_PATH,
                         ERR.MAILDIR_PERM_MISMATCH, ERR.NO_SUCH_DIRECTORY]:
                     warning = _(u"""\
 The account has been successfully deleted from the database.
     But an error occurred while deleting the following directory:
     “%(directory)s”
     Reason: %(reason)s""") % \
-                    {'directory': acc.getDir('home'), 'reason': e.msg()}
+                    {'directory': acc.getDir('home'), 'reason': e.msg}
                     self.__warnings.append(warning)
                 else:
                     raise
@@ -574,14 +573,14 @@
         alias = self.__getAlias(aliasaddress)
         try:
             return alias.get_destinations()
-        except VMMAliasException, e:
-            if e.code() == ERR.NO_SUCH_ALIAS:
+        except AliasError, e:
+            if e.code == ERR.NO_SUCH_ALIAS:
                 if Handler.accountExists(self._dbh, alias._addr):
-                    raise VMMException(
+                    raise VMMError(
                         _(u'There is already an account with address “%s”.') %
                                        aliasaddress, ERR.ACCOUNT_EXISTS)
                 if Handler.relocatedExists(self._dbh, alias._addr):
-                    raise VMMException(_(u'There is already a relocated user \
+                    raise VMMError(_(u'There is already a relocated user \
 with the address “%s”.') %
                                        aliasaddress, ERR.RELOCATED_EXISTS)
                 raise
@@ -600,7 +599,7 @@
 
     def userInfo(self, emailaddress, details=None):
         if details not in (None, 'du', 'aliases', 'full'):
-            raise VMMException(_(u'Invalid argument: “%s”') % details,
+            raise VMMError(_(u'Invalid argument: “%s”') % details,
                                ERR.INVALID_AGUMENT)
         acc = self.__getAccount(emailaddress)
         info = acc.getInfo(self._Cfg.dget('misc.dovecot_version'))
@@ -623,7 +622,7 @@
             raise ValueError('could not accept password: %r' % password)
         acc = self.__getAccount(emailaddress)
         if acc.getUID() == 0:
-            raise VMMException(_(u"Account doesn't exist"),
+            raise VMMError(_(u"Account doesn't exist"),
                                ERR.NO_SUCH_ACCOUNT)
         acc.modify('password', self.__pwhash(password, user=emailaddress))
 
--- a/VirtualMailManager/MailLocation.py	Thu Feb 25 17:56:08 2010 +0000
+++ b/VirtualMailManager/MailLocation.py	Fri Feb 26 02:35:25 2010 +0000
@@ -8,7 +8,7 @@
 import re
 
 import VirtualMailManager.constants.ERROR as ERR
-from VirtualMailManager.Exceptions import VMMMailLocationException as MLE
+from VirtualMailManager.errors import MailLocationError as MLE
 
 RE_MAILLOCATION = """^\w{1,20}$"""
 
--- a/VirtualMailManager/Relocated.py	Thu Feb 25 17:56:08 2010 +0000
+++ b/VirtualMailManager/Relocated.py	Fri Feb 26 02:35:25 2010 +0000
@@ -10,7 +10,7 @@
 
 from VirtualMailManager.Domain import get_gid
 from VirtualMailManager.EmailAddress import EmailAddress
-from VirtualMailManager.Exceptions import VMMRelocatedException as VMMRE
+from VirtualMailManager.errors import RelocatedError as RErr
 from VirtualMailManager.constants.ERROR import \
      NO_SUCH_RELOCATED, RELOCATED_ADDR_DEST_IDENTICAL, RELOCATED_EXISTS
 
@@ -57,12 +57,12 @@
         update = False
         assert isinstance(destination, EmailAddress)
         if self._addr == destination:
-            raise VMMRE(_(u'Address and destination are identical.'),
-                        RELOCATED_ADDR_DEST_IDENTICAL)
+            raise RErr(_(u'Address and destination are identical.'),
+                       RELOCATED_ADDR_DEST_IDENTICAL)
         if self._dest:
             if self._dest == destination:
-                raise VMMRE(_(u'The relocated user %r already exists.') %
-                            self._addr, RELOCATED_EXISTS)
+                raise RErr(_(u'The relocated user %r already exists.') %
+                           self._addr, RELOCATED_EXISTS)
             else:
                 self._dest = destination
                 update = True
@@ -83,15 +83,15 @@
     def get_info(self):
         """Returns the address to which mails should be sent."""
         if not self._dest:
-            raise VMMRE(_(u"The relocated user %r doesn't exist.") %
-                        self._addr, NO_SUCH_RELOCATED)
+            raise RErr(_(u"The relocated user %r doesn't exist.") %
+                       self._addr, NO_SUCH_RELOCATED)
         return self._dest
 
     def delete(self):
         """Deletes the relocated entry from the database."""
         if not self._dest:
-            raise VMMRE(_(u"The relocated user %r doesn't exist.") %
-                        self._addr, NO_SUCH_RELOCATED)
+            raise RErr(_(u"The relocated user %r doesn't exist.") % self._addr,
+                       NO_SUCH_RELOCATED)
         dbc = self._dbh.cursor()
         dbc.execute("DELETE FROM relocated WHERE gid = %s AND address = %s",
                     self._gid, self._addr.localpart)
--- a/VirtualMailManager/Transport.py	Thu Feb 25 17:56:08 2010 +0000
+++ b/VirtualMailManager/Transport.py	Fri Feb 26 02:35:25 2010 +0000
@@ -6,7 +6,7 @@
 domains and accounts."""
 
 import VirtualMailManager.constants.ERROR as ERR
-from VirtualMailManager.Exceptions import VMMTransportException
+from VirtualMailManager.errors import TransportError
 
 class Transport(object):
     """A wrapper class that provides access to the transport table"""
@@ -23,14 +23,14 @@
         """
         self._dbh = dbh
         if tid is None and transport is None:
-            raise VMMTransportException(
+            raise TransportError(
                 _('Either tid or transport must be specified.'),
                 ERR.TRANSPORT_INIT)
         elif tid is not None:
             try:
                 self.__id = long(tid)
             except ValueError:
-                raise VMMTransportException(_('tid must be an int/long.'),
+                raise TransportError(_('tid must be an int/long.'),
                     ERR.TRANSPORT_INIT)
             self._loadByID()
         else:
@@ -58,7 +58,7 @@
         if result is not None:
             self.__transport = result[0]
         else:
-            raise VMMTransportException(_('Unknown tid specified.'),
+            raise TransportError(_('Unknown tid specified.'),
                 ERR.UNKNOWN_TRANSPORT_ID)
 
     def _loadByName(self):
--- a/VirtualMailManager/__init__.py	Thu Feb 25 17:56:08 2010 +0000
+++ b/VirtualMailManager/__init__.py	Fri Feb 26 02:35:25 2010 +0000
@@ -20,7 +20,7 @@
      NOT_EXECUTABLE, NO_SUCH_BINARY, NO_SUCH_DIRECTORY
 from VirtualMailManager.constants.version import __author__, __date__, \
      __version__
-from VirtualMailManager.Exceptions import VMMException
+from VirtualMailManager.errors import VMMError
 
 
 __all__ = [
@@ -69,30 +69,30 @@
 def is_dir(path):
     """Checks if `path` is a directory.
 
-    Throws a `VMMException` if `path` is not a directory.
+    Throws a `VMMError` if `path` is not a directory.
 
     """
     path = expand_path(path)
     if not os.path.isdir(path):
-        raise VMMException(_(u"'%s' is not a directory") %
-                            get_unicode(path), NO_SUCH_DIRECTORY)
+        raise VMMError(_(u"'%s' is not a directory") % get_unicode(path),
+                       NO_SUCH_DIRECTORY)
     return path
 
 
 def exec_ok(binary):
     """Checks if the `binary` exists and if it is executable.
 
-    Throws a `VMMException` if the `binary` isn't a file or is not
+    Throws a `VMMError` if the `binary` isn't a file or is not
     executable.
 
     """
     binary = expand_path(binary)
     if not os.path.isfile(binary):
-        raise VMMException(_(u"'%s' is not a file") % get_unicode(binary),
-                           NO_SUCH_BINARY)
+        raise VMMError(_(u"'%s' is not a file") % get_unicode(binary),
+                       NO_SUCH_BINARY)
     if not os.access(binary, os.X_OK):
-        raise VMMException(_(u"File is not executable: '%s'") %
-                           get_unicode(binary), NOT_EXECUTABLE)
+        raise VMMError(_(u"File is not executable: '%s'") % 
+                       get_unicode(binary), NOT_EXECUTABLE)
     return binary
 
 
@@ -112,37 +112,37 @@
     It also converts the name of the domain from IDN to ASCII, if
     necessary.
 
-    Throws an `VMMException`, if the domain name is too long or doesn't
+    Throws an `VMMError`, if the domain name is too long or doesn't
     look like a valid domain name (label.label.label).
 
     """
     if not RE_DOMAIN.match(domainname):
         domainname = idn2ascii(domainname)
     if len(domainname) > 255:
-        raise VMMException(_(u'The domain name is too long'), DOMAIN_TOO_LONG)
+        raise VMMError(_(u'The domain name is too long'), DOMAIN_TOO_LONG)
     if not RE_DOMAIN.match(domainname):
-        raise VMMException(_(u'The domain name %r is invalid') % domainname,
-                           DOMAIN_INVALID)
+        raise VMMError(_(u'The domain name %r is invalid') % domainname,
+                       DOMAIN_INVALID)
     return domainname
 
 
 def check_localpart(localpart):
     """Returns the validated local-part `localpart`.
 
-    Throws a `VMMException` if the local-part is too long or contains
+    Throws a `VMMError` if the local-part is too long or contains
     invalid characters.
 
     """
     if len(localpart) > 64:
-        raise VMMException(_(u'The local-part %r is too long') % localpart,
-                           LOCALPART_TOO_LONG)
+        raise VMMError(_(u'The local-part %r is too long') % localpart,
+                       LOCALPART_TOO_LONG)
     invalid_chars = set(RE_LOCALPART.findall(localpart))
     if invalid_chars:
         i_chars = u''.join((u'"%s" ' % c for c in invalid_chars))
-        raise VMMException(_(u"The local-part %(l_part)r contains invalid \
+        raise VMMError(_(u"The local-part %(l_part)r contains invalid \
 characters: %(i_chars)s") %
-                           {'l_part': localpart, 'i_chars': i_chars},
-                           LOCALPART_INVALID)
+                       {'l_part': localpart, 'i_chars': i_chars},
+                       LOCALPART_INVALID)
     return localpart
 
 
--- a/VirtualMailManager/cli/Config.py	Thu Feb 25 17:56:08 2010 +0000
+++ b/VirtualMailManager/cli/Config.py	Fri Feb 26 02:35:25 2010 +0000
@@ -13,7 +13,7 @@
 
 from VirtualMailManager import ENCODING
 from VirtualMailManager.Config import Config, ConfigValueError, LazyConfig
-from VirtualMailManager.Exceptions import VMMConfigException
+from VirtualMailManager.errors import ConfigError
 from VirtualMailManager.cli import w_std
 from VirtualMailManager.constants.ERROR import VMM_TOO_MANY_FAILURES
 
@@ -47,9 +47,9 @@
                             w_std(_(u'Warning: %s') % e)
                             failures += 1
                             if failures > 2:
-                                raise VMMConfigException(
+                                raise ConfigError(
                                     _(u'Too many failures - try again later.'),
-                                                         VMM_TOO_MANY_FAILURES)
+                                                  VMM_TOO_MANY_FAILURES)
                     else:
                         break
             print
--- a/VirtualMailManager/cli/Handler.py	Thu Feb 25 17:56:08 2010 +0000
+++ b/VirtualMailManager/cli/Handler.py	Fri Feb 26 02:35:25 2010 +0000
@@ -10,7 +10,7 @@
 
 import os
 
-from VirtualMailManager.Exceptions import VMMException
+from VirtualMailManager.errors import VMMError
 from VirtualMailManager.Handler import Handler
 from VirtualMailManager.cli import read_pass
 from VirtualMailManager.cli.Config import CliConfig as Cfg
@@ -33,7 +33,7 @@
     def __init__(self):
         """Creates a new CliHandler instance.
 
-        Throws a VMMNotRootException if your uid is greater 0.
+        Throws a NotRootError if your uid is greater 0.
         """
         # Overwrite the parent CTor partly, we use the CliConfig class
         # and add some command line checks.
@@ -64,8 +64,8 @@
         elif self._Cfg.has_section(section):
             self._Cfg.configure([section])
         else:
-            raise VMMException(_(u'Invalid section: “%s”') % section,
-                               INVALID_SECTION)
+            raise VMMError(_(u'Invalid section: “%s”') % section,
+                           INVALID_SECTION)
 
     def userAdd(self, emailaddress, password):
         if password is None:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/VirtualMailManager/errors.py	Fri Feb 26 02:35:25 2010 +0000
@@ -0,0 +1,75 @@
+# -*- coding: UTF-8 -*-
+# Copyright (c) 2007 - 2010, Pascal Volk
+# See COPYING for distribution information.
+
+"""
+    VirtualMailManager.errors
+
+    VMM's Exception classes
+"""
+
+
+class VMMError(Exception):
+    """Exception base class for VirtualMailManager exceptions"""
+
+    def __init__(self, msg, code):
+        Exception.__init__(self, msg)
+        self.msg = msg
+        self.code = int(code)
+
+    def __repr__(self):
+        return '%s(%r, %r)' % (self.__class__.__name__, self.msg, self.code)
+
+class ConfigError(VMMError):
+    """Exception class for configuration exceptions"""
+    pass
+
+
+class PermissionError(VMMError):
+    """Exception class for permissions exceptions"""
+    pass
+
+
+class NotRootError(VMMError):
+    """Exception class for non-root exceptions"""
+    pass
+
+
+class DomainError(VMMError):
+    """Exception class for Domain exceptions"""
+    pass
+
+
+class AliasDomainError(VMMError):
+    """Exception class for AliasDomain exceptions"""
+    pass
+
+
+class AccountError(VMMError):
+    """Exception class for Account exceptions"""
+    pass
+
+
+class AliasError(VMMError):
+    """Exception class for Alias exceptions"""
+    pass
+
+
+class EmailAddressError(VMMError):
+    """Exception class for EmailAddress exceptions"""
+    pass
+
+
+class MailLocationError(VMMError):
+    """Exception class for MailLocation exceptions"""
+    pass
+
+
+class RelocatedError(VMMError):
+    """Exception class for Relocated exceptions"""
+    pass
+
+
+class TransportError(VMMError):
+    """Exception class for Transport exceptions"""
+    pass
--- a/VirtualMailManager/ext/Postconf.py	Thu Feb 25 17:56:08 2010 +0000
+++ b/VirtualMailManager/ext/Postconf.py	Fri Feb 26 02:35:25 2010 +0000
@@ -8,7 +8,7 @@
 from subprocess import Popen, PIPE
 
 import VirtualMailManager.constants.ERROR as ERR
-from VirtualMailManager.Exceptions import VMMException
+from VirtualMailManager.errors import VMMError
 
 RE_PC_PARAMS = """^\w+$"""
 RE_PC_VARIABLES = r"""\$\b\w+\b"""
@@ -39,7 +39,7 @@
         expand_vars -- default True (bool)
         """
         if not re.match(RE_PC_PARAMS, parameter):
-            raise VMMException(_(u'The value “%s” doesn\'t look like a valid\
+            raise VMMError(_(u'The value “%s” doesn\'t look like a valid\
  postfix configuration parameter name.') % parameter, ERR.VMM_ERROR)
         self.__val = self.__read(parameter)
         if expand_vars:
@@ -66,7 +66,7 @@
         out, err = Popen([self.__bin, '-h', parameter], stdout=PIPE,
                 stderr=PIPE).communicate()
         if len(err):
-            raise VMMException(err.strip(), ERR.VMM_ERROR)
+            raise VMMError(err.strip(), ERR.VMM_ERROR)
         return out.strip()
 
     def __readMulti(self, parameters):
@@ -75,7 +75,7 @@
             cmd.append(parameter[1:])
         out, err = Popen(cmd, stdout=PIPE, stderr=PIPE).communicate()
         if len(err):
-            raise VMMException(err.strip(), ERR.VMM_ERROR)
+            raise VMMError(err.strip(), ERR.VMM_ERROR)
         par_val = {}
         for line in out.splitlines():
             par, val = line.split(' = ')
--- a/doc/source/index.rst	Thu Feb 25 17:56:08 2010 +0000
+++ b/doc/source/index.rst	Fri Feb 26 02:35:25 2010 +0000
@@ -16,7 +16,7 @@
    vmm_config.rst
    vmm_emailaddress.rst
    vmm_relocated.rst
-   vmm_exceptions.rst
+   vmm_errors.rst
    vmm_constants_error.rst
 
 Indices and tables
--- a/doc/source/vmm.rst	Thu Feb 25 17:56:08 2010 +0000
+++ b/doc/source/vmm.rst	Fri Feb 26 02:35:25 2010 +0000
@@ -45,7 +45,7 @@
   :param domainname: the name of the domain
   :type domainname: :obj:`basestring`
   :rtype: str
-  :raise VirtualMailManager.Exceptions.VMMException: if the domain name is
+  :raise VirtualMailManager.errors.VMMError: if the domain name is
     too long or doesn't look like a valid domain name (label.label.label).
 
 .. function:: check_localpart(localpart)
@@ -55,7 +55,7 @@
   :param localpart: The local-part of an e-mail address.
   :type localpart: str
   :rtype: str
-  :raise VirtualMailManager.Exceptions.VMMException: if the local-part is too
+  :raise VirtualMailManager.errors.VMMError: if the local-part is too
     long or contains invalid characters.
 
 .. function:: exec_ok(binary)
@@ -65,7 +65,7 @@
   :param binary: path to the binary
   :type binary: str
   :rtype: str
-  :raise VirtualMailManager.Exceptions.VMMException: if *binary* isn't a file
+  :raise VirtualMailManager.errors.VMMError: if *binary* isn't a file
     or is not executable.
 
 .. function:: expand_path(path)
@@ -99,8 +99,7 @@
   :param path: Path to a directory
   :type path: str
   :rtype: str
-  :raise VirtualMailManager.Exceptions.VMMException: if *path* is not a
-    directory.
+  :raise VirtualMailManager.errors.VMMError: if *path* is not a directory.
 
 
 Examples
@@ -120,7 +119,7 @@
     File "<stdin>", line 1, in <module>
     File "./VirtualMailManager/__init__.py", line 93, in exec_ok
       NO_SUCH_BINARY)
-  VirtualMailManager.Exceptions.VMMException: 'usr/bin/vim' is not a file
+  VirtualMailManager.errors.VMMError: 'usr/bin/vim' is not a file
   >>> exec_ok('/usr/bin/vim')
   '/usr/bin/vim'
   >>> expand_path('.')
--- a/doc/source/vmm_config.rst	Thu Feb 25 17:56:08 2010 +0000
+++ b/doc/source/vmm_config.rst	Fri Feb 26 02:35:25 2010 +0000
@@ -158,7 +158,7 @@
       and it fails
     :raise ValueError: if an other setter (:attr:`LazyConfigOption.cls`) or
       validator (:attr:`LazyConfigOption.validate`) fails.
-    :raise VirtualMailManager.Exceptions.VMMException: if
+    :raise VirtualMailManager.errors.VMMError: if
       :attr:`LazyConfigOption.validate` is set to
       :func:`VirtualMailManager.exec_ok` or :func:`VirtualMailManager.is_dir`.
 
@@ -232,13 +232,13 @@
 
     Checks all section's options for settings w/o a default value.
 
-    :raise VirtualMailManager.Exceptions.VMMConfigException: if the check fails
+    :raise VirtualMailManager.errors.ConfigError: if the check fails
 
   .. method:: load()
 
     Loads the configuration read-only.
 
-    :raise VirtualMailManager.Exceptions.VMMConfigException: if the
+    :raise VirtualMailManager.errors.ConfigError: if the
       configuration syntax is invalid
 
   .. method:: unicode(section, option)
@@ -256,19 +256,19 @@
 Exceptions
 ----------
 
-.. exception:: BadOptionError (msg)
+.. exception:: BadOptionError(msg)
 
   Bases: :exc:`ConfigParser.Error`
 
   Raised when a option isn't in the format 'section.option'.
 
-.. exception:: ConfigValueError (msg)
+.. exception:: ConfigValueError(msg)
 
   Bases: :exc:`ConfigParser.Error`
 
   Raised when creating or validating of new values fails.
 
-.. exception:: NoDefaultError (section, option)
+.. exception:: NoDefaultError(section, option)
 
   Bases: :exc:`ConfigParser.Error`
 
--- a/doc/source/vmm_constants_error.rst	Thu Feb 25 17:56:08 2010 +0000
+++ b/doc/source/vmm_constants_error.rst	Fri Feb 26 02:35:25 2010 +0000
@@ -9,7 +9,7 @@
 .. toctree::
    :maxdepth: 2
 
-Error codes, used by all :mod:`VirtualMailManager.Exceptions`.
+Error codes, used by all :mod:`VirtualMailManager.errors`.
 
 .. data:: ACCOUNT_AND_ALIAS_PRESENT
 
--- a/doc/source/vmm_emailaddress.rst	Thu Feb 25 17:56:08 2010 +0000
+++ b/doc/source/vmm_emailaddress.rst	Fri Feb 26 02:35:25 2010 +0000
@@ -23,9 +23,9 @@
 
   :param address: string representation of an e-mail addresses
   :type address: :obj:`basestring`
-  :raise VirtualMailManager.Exceptions.VMMEmailAddressException: if the
+  :raise VirtualMailManager.errors.EmailAddressError: if the
     *address* is syntactically wrong.
-  :raise VirtualMailManager.Exceptions.VMMException: if the validation of the
+  :raise VirtualMailManager.errors.VMMError: if the validation of the
     local-part or domain name fails.
 
   An EmailAddress instance has the both read-only attributes:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/source/vmm_errors.rst	Fri Feb 26 02:35:25 2010 +0000
@@ -0,0 +1,122 @@
+:mod:`VirtualMailManager.errors` --- Exception classes
+======================================================
+
+.. module:: VirtualMailManager.errors
+  :synopsis: Exception classes
+
+.. moduleauthor:: Pascal Volk <neverseen@users.sourceforge.net>
+
+.. toctree::
+   :maxdepth: 2
+
+Exceptions, used by VirtualMailManager's classes.
+
+
+Exceptions
+----------
+
+.. exception:: VMMError(msg, code)
+
+  Bases: :exc:`exceptions.Exception`
+
+  :param msg: the error message
+  :type msg: :obj:`basestring`
+  :param code: the error code (one of :mod:`VirtualMailManager.constants.ERROR`)
+  :type code: :obj:`int`
+
+  Base class for all other Exceptions in the VirtualMailManager package.
+
+  The *msg* and *code* are accessible via the both attributes:
+
+  .. attribute:: msg
+
+    The error message of the exception.
+
+
+  .. attribute:: code
+
+    The numerical error code of the exception.
+
+
+.. exception:: ConfigError(msg, code)
+
+  Bases: :exc:`VirtualMailManager.errors.VMMError`
+
+  Exception class for configuration (:mod:`VirtualMailManager.Config`)
+  exceptions.
+
+
+.. exception:: PermissionError(msg, code)
+
+  Bases: :exc:`VirtualMailManager.errors.VMMError`
+
+  Exception class for file permission exceptions.
+
+
+.. exception:: NotRootError(msg, code)
+
+  Bases: :exc:`VirtualMailManager.errors.VMMError`
+
+  Exception class for non-root exceptions.
+
+
+.. exception:: DomainError(msg, code)
+
+  Bases: :exc:`VirtualMailManager.errors.VMMError`
+
+  Exception class for Domain (:mod:`VirtualMailManager.Domain`) exceptions.
+
+
+.. exception:: AliasDomainError(msg, code)
+
+  Bases: :exc:`VirtualMailManager.errors.VMMError`
+
+  Exception class for AliasDomain (:mod:`VirtualMailManager.AliasDomain`)
+  exceptions.
+
+
+.. exception:: AccountError(msg, code)
+
+  Bases: :exc:`VirtualMailManager.errors.VMMError`
+
+  Exception class for Account (:mod:`VirtualMailManager.Account`) exceptions.
+
+
+.. exception:: AliasError(msg, code)
+
+  Bases: :exc:`VirtualMailManager.errors.VMMError`
+
+  Exception class for Alias (:mod:`VirtualMailManager.Alias`) exceptions.
+
+
+.. exception:: EmailAddressError(msg, code)
+
+  Bases: :exc:`VirtualMailManager.errors.VMMError`
+
+  Exception class for EmailAddress (:mod:`VirtualMailManager.EmailAddress`)
+  exceptions.
+
+
+.. exception:: MailLocationError(msg, code)
+
+  Bases: :exc:`VirtualMailManager.errors.VMMError`
+
+  Exception class for MailLocation (:mod:`VirtualMailManager.MailLocation`)
+  exceptions.
+
+
+.. exception:: RelocatedError(msg, code)
+
+  Bases: :exc:`VirtualMailManager.errors.VMMError`
+
+  Exception class for Relocated (:mod:`VirtualMailManager.Relocated`)
+  exceptions.
+
+
+.. exception:: TransportError(msg, code)
+
+  Bases: :exc:`VirtualMailManager.errors.VMMError`
+
+  Exception class for Transport (:mod:`VirtualMailManager.Transport`)
+  exceptions.
+
--- a/doc/source/vmm_exceptions.rst	Thu Feb 25 17:56:08 2010 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,118 +0,0 @@
-:mod:`VirtualMailManager.Exceptions` --- Exception classes
-==========================================================
-
-.. module:: VirtualMailManager.Exceptions
-  :synopsis: Exception classes
-
-.. moduleauthor:: Pascal Volk <neverseen@users.sourceforge.net>
-
-.. toctree::
-   :maxdepth: 2
-
-Exceptions, used by VirtualMailManager's classes.
-
-
-Exceptions
-----------
-
-.. exception:: VMMException(msg, code)
-
-  Bases: :exc:`exceptions.Exception`
-
-  :param msg: the error message
-  :type msg: :obj:`basestring`
-  :param code: the error code (one of :mod:`VirtualMailManager.constants.ERROR`)
-  :type code: :obj:`int`
-
-  Base class for all other Exceptions in the VirtualMailManager package.
-
-
-  .. method:: msg
-
-    :rtype: :obj:`basestring`
-
-    Returns the error message of the exception.
-
-
-  .. method:: code
-
-    :rtype: :obj:`int`
-
-    Returns the numerical error code of the exception.
-
-
-.. exception:: VMMConfigException(msg, code)
-
-  Bases: :exc:`VirtualMailManager.Exceptions.VMMException`
-
-  Exception class for configuration (:mod:`VirtualMailManager.Config`)
-  exceptions.
-
-
-.. exception:: VMMNotRootException(msg, code)
-
-  Bases: :exc:`VirtualMailManager.Exceptions.VMMException`
-
-  Exception class for non-root exceptions.
-
-
-.. exception:: VMMDomainException(msg, code)
-
-  Bases: :exc:`VirtualMailManager.Exceptions.VMMException`
-
-  Exception class for Domain (:mod:`VirtualMailManager.Domain`) exceptions.
-
-
-.. exception:: VMMAliasDomainException(msg, code)
-
-  Bases: :exc:`VirtualMailManager.Exceptions.VMMException`
-
-  Exception class for AliasDomain (:mod:`VirtualMailManager.AliasDomain`)
-  exceptions.
-
-
-.. exception:: VMMAccountException(msg, code)
-
-  Bases: :exc:`VirtualMailManager.Exceptions.VMMException`
-
-  Exception class for Account (:mod:`VirtualMailManager.Account`) exceptions.
-
-
-.. exception:: VMMAliasException(msg, code)
-
-  Bases: :exc:`VirtualMailManager.Exceptions.VMMException`
-
-  Exception class for Alias (:mod:`VirtualMailManager.Alias`) exceptions.
-
-
-.. exception:: VMMEmailAddressException(msg, code)
-
-  Bases: :exc:`VirtualMailManager.Exceptions.VMMException`
-
-  Exception class for EmailAddress (:mod:`VirtualMailManager.EmailAddress`)
-  exceptions.
-
-
-.. exception:: VMMMailLocationException(msg, code)
-
-  Bases: :exc:`VirtualMailManager.Exceptions.VMMException`
-
-  Exception class for MailLocation (:mod:`VirtualMailManager.MailLocation`)
-  exceptions.
-
-
-.. exception:: VMMRelocatedException(msg, code)
-
-  Bases: :exc:`VirtualMailManager.Exceptions.VMMException`
-
-  Exception class for Relocated (:mod:`VirtualMailManager.Relocated`)
-  exceptions.
-
-
-.. exception:: VMMTransportException(msg, code)
-
-  Bases: :exc:`VirtualMailManager.Exceptions.VMMException`
-
-  Exception class for Transport (:mod:`VirtualMailManager.Transport`)
-  exceptions.
-
--- a/doc/source/vmm_relocated.rst	Thu Feb 25 17:56:08 2010 +0000
+++ b/doc/source/vmm_relocated.rst	Fri Feb 26 02:35:25 2010 +0000
@@ -34,8 +34,8 @@
   .. method:: delete()
   
     :rtype: :obj:`None`
-    :raise VirtualMailManager.Exceptions.VMMRelocatedException: if the
-      relocated user doesn't exist.
+    :raise VirtualMailManager.errors.RelocatedError: if the relocated user
+      doesn't exist.
 
     Deletes the relocated user from the database.
 
@@ -43,8 +43,8 @@
   .. method:: get_info()
 
     :rtype: :class:`VirtualMailManager.EmailAddress.EmailAddress`
-    :raise VirtualMailManager.Exceptions.VMMRelocatedException: if the
-      relocated user doesn't exist.
+    :raise VirtualMailManager.errors.RelocatedError: if the relocated user
+      doesn't exist.
 
     Returns the destination e-mail address of the relocated user.
 
@@ -54,8 +54,7 @@
     :param destination: the new address where the relocated user has moved to
     :type destination: :class:`VirtualMailManager.EmailAddress.EmailAddress`
     :rtype: :obj:`None`
-    :raise VirtualMailManager.Exceptions.VMMRelocatedException: if the
-      *destination* address is already saved or is the same as the relocated
-      user's address.
+    :raise VirtualMailManager.errors.RelocatedError: if the *destination*
+      address is already saved or is the same as the relocated user's address.
 
     Sets or updates the *destination* address of the relocated user.