--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/VirtualMailManager/maillocation.py Thu Jun 28 19:26:50 2012 +0000
@@ -0,0 +1,161 @@
+# -*- coding: UTF-8 -*-
+# Copyright (c) 2008 - 2012, Pascal Volk
+# See COPYING for distribution information.
+"""
+ VirtualMailManager.maillocation
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ Virtual Mail Manager's maillocation module to handle Dovecot's
+ mail_location setting for accounts.
+
+"""
+
+from VirtualMailManager.constants import MAILLOCATION_INIT
+from VirtualMailManager.errors import MailLocationError as MLErr
+from VirtualMailManager.pycompat import all
+
+
+__all__ = ('MailLocation', 'known_format')
+
+_ = lambda msg: msg
+_format_info = {
+ 'maildir': dict(dovecot_version=0x10000f00, postfix=True),
+ 'mdbox': dict(dovecot_version=0x20000b05, postfix=False),
+ 'sdbox': dict(dovecot_version=0x20000c03, postfix=False),
+}
+
+
+class MailLocation(object):
+ """Class to handle mail_location relevant information."""
+ __slots__ = ('_directory', '_mbfmt', '_mid', '_dbh')
+ _kwargs = ('mid', 'mbfmt', 'directory')
+
+ def __init__(self, dbh, **kwargs):
+ """Creates a new MailLocation instance.
+
+ Either the mid keyword or the mbfmt and directory keywords must be
+ specified.
+
+ Arguments:
+
+ `dbh` : pyPgSQL.PgSQL.Connection
+ A database connection for the database access.
+
+ Keyword arguments:
+
+ `mid` : int
+ the id of a mail_location
+ `mbfmt` : str
+ the mailbox format of the mail_location. One out of: ``maildir``,
+ ``sdbox`` and ``mdbox``.
+ `directory` : str
+ name of the mailbox root directory.
+ """
+ self._dbh = dbh
+ self._directory = None
+ self._mbfmt = None
+ self._mid = 0
+
+ for key in kwargs.iterkeys():
+ if key not in self.__class__._kwargs:
+ raise ValueError('unrecognized keyword: %r' % key)
+ mid = kwargs.get('mid')
+ if mid:
+ assert isinstance(mid, (int, long))
+ self._load_by_mid(mid)
+ else:
+ args = kwargs.get('mbfmt'), kwargs.get('directory')
+ assert all(isinstance(arg, basestring) for arg in args)
+ if args[0].lower() not in _format_info:
+ raise MLErr(_(u"Unsupported mailbox format: '%s'") % args[0],
+ MAILLOCATION_INIT)
+ directory = args[1].strip()
+ if not directory:
+ raise MLErr(_(u"Empty directory name"), MAILLOCATION_INIT)
+ if len(directory) > 20:
+ raise MLErr(_(u"Directory name is too long: '%s'") % directory,
+ MAILLOCATION_INIT)
+ self._load_by_names(args[0].lower(), directory)
+
+ def __str__(self):
+ return u'%s:~/%s' % (self._mbfmt, self._directory)
+
+ @property
+ def directory(self):
+ """The mail_location's directory name."""
+ return self._directory
+
+ @property
+ def dovecot_version(self):
+ """The required Dovecot version for this mailbox format."""
+ return _format_info[self._mbfmt]['dovecot_version']
+
+ @property
+ def postfix(self):
+ """`True` if Postfix supports this mailbox format, else `False`."""
+ return _format_info[self._mbfmt]['postfix']
+
+ @property
+ def mbformat(self):
+ """The mail_location's mailbox format."""
+ return self._mbfmt
+
+ @property
+ def mail_location(self):
+ """The mail_location, e.g. ``maildir:~/Maildir``"""
+ return self.__str__()
+
+ @property
+ def mid(self):
+ """The mail_location's unique ID."""
+ return self._mid
+
+ def _load_by_mid(self, mid):
+ """Load mail_location relevant information by *mid*"""
+ dbc = self._dbh.cursor()
+ dbc.execute('SELECT format, directory FROM mailboxformat, '
+ 'maillocation WHERE mid = %u AND '
+ 'maillocation.fid = mailboxformat.fid' % mid)
+ result = dbc.fetchone()
+ dbc.close()
+ if not result:
+ raise ValueError('Unknown mail_location id specified: %r' % mid)
+ self._mid = mid
+ self._mbfmt, self._directory = result
+
+ def _load_by_names(self, mbfmt, directory):
+ """Try to load mail_location relevant information by *mbfmt* and
+ *directory* name. If it fails goto _save()."""
+ dbc = self._dbh.cursor()
+ dbc.execute("SELECT mid FROM maillocation WHERE fid = (SELECT fid "
+ "FROM mailboxformat WHERE format = %s) AND directory = %s",
+ (mbfmt, directory))
+ result = dbc.fetchone()
+ dbc.close()
+ if not result:
+ self._save(mbfmt, directory)
+ else:
+ self._mid = result[0]
+ self._mbfmt = mbfmt
+ self._directory = directory
+
+ def _save(self, mbfmt, directory):
+ """Save a new mail_location in the database."""
+ dbc = self._dbh.cursor()
+ dbc.execute("SELECT nextval('maillocation_id')")
+ mid = dbc.fetchone()[0]
+ dbc.execute("INSERT INTO maillocation (fid, mid, directory) VALUES ("
+ "(SELECT fid FROM mailboxformat WHERE format = %s), %s, "
+ "%s)", (mbfmt, mid, directory))
+ self._dbh.commit()
+ dbc.close()
+ self._mid = mid
+ self._mbfmt = mbfmt
+ self._directory = directory
+
+
+def known_format(mbfmt):
+ """Checks if the mailbox format *mbfmt* is known, returns bool."""
+ return mbfmt.lower() in _format_info
+
+del _