1.1 --- a/docs/wiki/MailboxIntegration Tue Oct 17 22:58:26 2017 +0200
1.2 +++ b/docs/wiki/MailboxIntegration Wed Oct 18 00:19:26 2017 +0200
1.3 @@ -25,8 +25,20 @@
1.4 The Dovecot documentation provides guides for integrating Dovecot with
1.5 [[http://wiki2.dovecot.org/LMTP/Exim|Exim]] and with
1.6 [[http://wiki2.dovecot.org/HowTo/PostfixDovecotLMTP|Postfix]].
1.7 +==
1.8 +Traditional Unix mailboxes for local system users
1.9 +||
1.10 +If routing is defined for local users and if
1.11 +[[../MailIntegration/LocalSMTP|local SMTP]] is employed, no other mail storage
1.12 +solution is required.
1.13 }}}
1.14
1.15 +With the traditional Unix mailbox approach, no further configuration should be
1.16 +necessary because Exim and Postfix support delivery to such mailboxes amongst
1.17 +their normal configuration rules. The rest of this document describes the
1.18 +integration of these mail transport agents with other mail storage solutions
1.19 +using LMTP.
1.20 +
1.21 == Exim ==
1.22
1.23 Example configuration files for Exim are distributed in `conf/exim/lmtp`:
2.1 --- a/imiptools/__init__.py Tue Oct 17 22:58:26 2017 +0200
2.2 +++ b/imiptools/__init__.py Wed Oct 18 00:19:26 2017 +0200
2.3 @@ -26,7 +26,8 @@
2.4 is_returned_message
2.5 from imiptools.data import get_address, get_addresses, get_uri
2.6 from imiptools.mail import Messenger
2.7 -from imiptools.stores import get_store, get_publisher, get_journal
2.8 +from imiptools.stores import get_store, get_publisher, get_journal, \
2.9 + StoreInitialisationError
2.10 import sys, os
2.11
2.12 # Postfix exit codes.
2.13 @@ -69,15 +70,21 @@
2.14
2.15 def get_publisher(self):
2.16
2.17 - "Return any configured publisher or None if not explicitly configured."
2.18 + "Return any configured publisher or None if not configured."
2.19
2.20 - return self.publishing_dir and get_publisher(self.publishing_dir) or None
2.21 + try:
2.22 + return get_publisher(self.publishing_dir)
2.23 + except StoreInitialisationError:
2.24 + return None
2.25
2.26 def get_journal(self):
2.27
2.28 - "Return any configured journal or None if not explicitly configured."
2.29 + "Return any configured journal or None if not configured."
2.30
2.31 - return self.journal_dir and get_journal(self.store_type, self.journal_dir) or None
2.32 + try:
2.33 + return get_journal(self.store_type, self.journal_dir)
2.34 + except StoreInitialisationError:
2.35 + return None
2.36
2.37 def process(self, f, original_recipients):
2.38
3.1 --- a/imiptools/stores/__init__.py Tue Oct 17 22:58:26 2017 +0200
3.2 +++ b/imiptools/stores/__init__.py Wed Oct 18 00:19:26 2017 +0200
3.3 @@ -20,6 +20,7 @@
3.4 """
3.5
3.6 from imiptools.config import settings
3.7 +from imiptools.stores.common import StoreInitialisationError
3.8 from imiptools.stores.manifest import stores
3.9
3.10 # Access functions.
3.11 @@ -42,7 +43,7 @@
3.12 """
3.13
3.14 return stores["file"].Publisher(
3.15 - publishing_dir or settings["PUBLISHING_DIR"])
3.16 + publishing_dir or settings["PUBLISH_DIR"])
3.17
3.18 def get_journal(store_type=None, journal_dir=None):
3.19
4.1 --- a/imiptools/stores/common.py Tue Oct 17 22:58:26 2017 +0200
4.2 +++ b/imiptools/stores/common.py Wed Oct 18 00:19:26 2017 +0200
4.3 @@ -21,6 +21,12 @@
4.4
4.5 from imiptools.dates import format_datetime, get_datetime
4.6
4.7 +class StoreInitialisationError(Exception):
4.8 +
4.9 + "An error occurring when the initialisation of a store fails."
4.10 +
4.11 + pass
4.12 +
4.13 class StoreBase:
4.14
4.15 "The core operations of a data store."
5.1 --- a/imiptools/stores/database/postgresql.py Tue Oct 17 22:58:26 2017 +0200
5.2 +++ b/imiptools/stores/database/postgresql.py Wed Oct 18 00:19:26 2017 +0200
5.3 @@ -20,6 +20,7 @@
5.4 """
5.5
5.6 from imiptools.config import settings
5.7 +from imiptools.stores.common import StoreInitialisationError
5.8 from imiptools.stores.database.common import DatabaseStore, DatabaseJournal
5.9 import psycopg2
5.10
5.11 @@ -34,7 +35,11 @@
5.12
5.13 "Interpret 'store_dir' as a connection string."
5.14
5.15 - connection = psycopg2.connect(store_dir or STORE_DIR)
5.16 + try:
5.17 + connection = psycopg2.connect(store_dir or STORE_DIR)
5.18 + except psycopg2.OperationalError, exc:
5.19 + raise StoreInitialisationError, exc
5.20 +
5.21 connection.autocommit = True
5.22 DatabaseStore.__init__(self, connection, psycopg2.paramstyle)
5.23
5.24 @@ -54,7 +59,11 @@
5.25
5.26 "Interpret 'store_dir' as a connection string."
5.27
5.28 - connection = psycopg2.connect(store_dir or JOURNAL_DIR)
5.29 + try:
5.30 + connection = psycopg2.connect(store_dir or JOURNAL_DIR)
5.31 + except psycopg2.OperationalError, exc:
5.32 + raise StoreInitialisationError, exc
5.33 +
5.34 connection.autocommit = True
5.35 DatabaseJournal.__init__(self, connection, psycopg2.paramstyle)
5.36
6.1 --- a/imiptools/stores/file.py Tue Oct 17 22:58:26 2017 +0200
6.2 +++ b/imiptools/stores/file.py Wed Oct 18 00:19:26 2017 +0200
6.3 @@ -19,7 +19,8 @@
6.4 this program. If not, see <http://www.gnu.org/licenses/>.
6.5 """
6.6
6.7 -from imiptools.stores.common import StoreBase, PublisherBase, JournalBase
6.8 +from imiptools.stores.common import StoreBase, PublisherBase, JournalBase, \
6.9 + StoreInitialisationError
6.10
6.11 from datetime import datetime
6.12 from imiptools.config import settings
6.13 @@ -62,7 +63,10 @@
6.14 "A file store of tabular free/busy data and objects."
6.15
6.16 def __init__(self, store_dir=None):
6.17 - FileBase.__init__(self, store_dir or STORE_DIR)
6.18 + try:
6.19 + FileBase.__init__(self, store_dir or STORE_DIR)
6.20 + except OSError, exc:
6.21 + raise StoreInitialisationError, exc
6.22
6.23 # Store object access.
6.24
6.25 @@ -707,7 +711,10 @@
6.26 "A publisher of objects."
6.27
6.28 def __init__(self, store_dir=None):
6.29 - FileBase.__init__(self, store_dir or PUBLISH_DIR)
6.30 + try:
6.31 + FileBase.__init__(self, store_dir or PUBLISH_DIR)
6.32 + except OSError, exc:
6.33 + raise StoreInitialisationError, exc
6.34
6.35 def set_freebusy(self, user, freebusy):
6.36