# HG changeset patch # User Paul Boddie # Date 1508278766 -7200 # Node ID ef0326fbdc1dd440d21b2423260013f9e27af768 # Parent f5b485cc5a930f6b8595d92d399286b1a6586a5c# Parent 0403458605e5eefe97462e3fb153dd90f4dba54f Merged changes from the default branch. diff -r f5b485cc5a93 -r ef0326fbdc1d docs/wiki/MailboxIntegration --- a/docs/wiki/MailboxIntegration Tue Oct 17 22:58:26 2017 +0200 +++ b/docs/wiki/MailboxIntegration Wed Oct 18 00:19:26 2017 +0200 @@ -25,8 +25,20 @@ The Dovecot documentation provides guides for integrating Dovecot with [[http://wiki2.dovecot.org/LMTP/Exim|Exim]] and with [[http://wiki2.dovecot.org/HowTo/PostfixDovecotLMTP|Postfix]]. +== +Traditional Unix mailboxes for local system users +|| +If routing is defined for local users and if +[[../MailIntegration/LocalSMTP|local SMTP]] is employed, no other mail storage +solution is required. }}} +With the traditional Unix mailbox approach, no further configuration should be +necessary because Exim and Postfix support delivery to such mailboxes amongst +their normal configuration rules. The rest of this document describes the +integration of these mail transport agents with other mail storage solutions +using LMTP. + == Exim == Example configuration files for Exim are distributed in `conf/exim/lmtp`: diff -r f5b485cc5a93 -r ef0326fbdc1d imiptools/__init__.py --- a/imiptools/__init__.py Tue Oct 17 22:58:26 2017 +0200 +++ b/imiptools/__init__.py Wed Oct 18 00:19:26 2017 +0200 @@ -26,7 +26,8 @@ is_returned_message from imiptools.data import get_address, get_addresses, get_uri from imiptools.mail import Messenger -from imiptools.stores import get_store, get_publisher, get_journal +from imiptools.stores import get_store, get_publisher, get_journal, \ + StoreInitialisationError import sys, os # Postfix exit codes. @@ -69,15 +70,21 @@ def get_publisher(self): - "Return any configured publisher or None if not explicitly configured." + "Return any configured publisher or None if not configured." - return self.publishing_dir and get_publisher(self.publishing_dir) or None + try: + return get_publisher(self.publishing_dir) + except StoreInitialisationError: + return None def get_journal(self): - "Return any configured journal or None if not explicitly configured." + "Return any configured journal or None if not configured." - return self.journal_dir and get_journal(self.store_type, self.journal_dir) or None + try: + return get_journal(self.store_type, self.journal_dir) + except StoreInitialisationError: + return None def process(self, f, original_recipients): diff -r f5b485cc5a93 -r ef0326fbdc1d imiptools/stores/__init__.py --- a/imiptools/stores/__init__.py Tue Oct 17 22:58:26 2017 +0200 +++ b/imiptools/stores/__init__.py Wed Oct 18 00:19:26 2017 +0200 @@ -20,6 +20,7 @@ """ from imiptools.config import settings +from imiptools.stores.common import StoreInitialisationError from imiptools.stores.manifest import stores # Access functions. @@ -42,7 +43,7 @@ """ return stores["file"].Publisher( - publishing_dir or settings["PUBLISHING_DIR"]) + publishing_dir or settings["PUBLISH_DIR"]) def get_journal(store_type=None, journal_dir=None): diff -r f5b485cc5a93 -r ef0326fbdc1d imiptools/stores/common.py --- a/imiptools/stores/common.py Tue Oct 17 22:58:26 2017 +0200 +++ b/imiptools/stores/common.py Wed Oct 18 00:19:26 2017 +0200 @@ -21,6 +21,12 @@ from imiptools.dates import format_datetime, get_datetime +class StoreInitialisationError(Exception): + + "An error occurring when the initialisation of a store fails." + + pass + class StoreBase: "The core operations of a data store." diff -r f5b485cc5a93 -r ef0326fbdc1d imiptools/stores/database/postgresql.py --- a/imiptools/stores/database/postgresql.py Tue Oct 17 22:58:26 2017 +0200 +++ b/imiptools/stores/database/postgresql.py Wed Oct 18 00:19:26 2017 +0200 @@ -20,6 +20,7 @@ """ from imiptools.config import settings +from imiptools.stores.common import StoreInitialisationError from imiptools.stores.database.common import DatabaseStore, DatabaseJournal import psycopg2 @@ -34,7 +35,11 @@ "Interpret 'store_dir' as a connection string." - connection = psycopg2.connect(store_dir or STORE_DIR) + try: + connection = psycopg2.connect(store_dir or STORE_DIR) + except psycopg2.OperationalError, exc: + raise StoreInitialisationError, exc + connection.autocommit = True DatabaseStore.__init__(self, connection, psycopg2.paramstyle) @@ -54,7 +59,11 @@ "Interpret 'store_dir' as a connection string." - connection = psycopg2.connect(store_dir or JOURNAL_DIR) + try: + connection = psycopg2.connect(store_dir or JOURNAL_DIR) + except psycopg2.OperationalError, exc: + raise StoreInitialisationError, exc + connection.autocommit = True DatabaseJournal.__init__(self, connection, psycopg2.paramstyle) diff -r f5b485cc5a93 -r ef0326fbdc1d imiptools/stores/file.py --- a/imiptools/stores/file.py Tue Oct 17 22:58:26 2017 +0200 +++ b/imiptools/stores/file.py Wed Oct 18 00:19:26 2017 +0200 @@ -19,7 +19,8 @@ this program. If not, see . """ -from imiptools.stores.common import StoreBase, PublisherBase, JournalBase +from imiptools.stores.common import StoreBase, PublisherBase, JournalBase, \ + StoreInitialisationError from datetime import datetime from imiptools.config import settings @@ -62,7 +63,10 @@ "A file store of tabular free/busy data and objects." def __init__(self, store_dir=None): - FileBase.__init__(self, store_dir or STORE_DIR) + try: + FileBase.__init__(self, store_dir or STORE_DIR) + except OSError, exc: + raise StoreInitialisationError, exc # Store object access. @@ -707,7 +711,10 @@ "A publisher of objects." def __init__(self, store_dir=None): - FileBase.__init__(self, store_dir or PUBLISH_DIR) + try: + FileBase.__init__(self, store_dir or PUBLISH_DIR) + except OSError, exc: + raise StoreInitialisationError, exc def set_freebusy(self, user, freebusy):