restore-mail-inject.py - Tool to inject mails via IMAP
Copyright (c) 2012 Intra2net AG
-'''
+This program relies on the following assumptions:
+- IMAP hierarchy separator is / (unixhierarysep=yes)
+- INBOX maps to user/[username]
+- internal encoding of . etc. as of cyrus 2.2
+'''
+import logging
import argparse
from mail_iterator import MailIterator
from file_iterator import FileIterator
+from warnings_handler import WarningsHandler
+
+LOG_FILENAME = "restore_mail_inject.log"
+LOG_FILE_LEVEL = logging.DEBUG
+LOG_SHELL_LEVEL = logging.INFO
+LOG_UNCLEAN_EXIT_LEVEL = logging.WARNING
def main():
"""Main function."""
# prepare configuration
args = configure_args()
- print("The module restore_mail_inject.py started with user %s, folder %s and source %s." %
- (args.user, args.folder, args.srcdir))
+ warnings_handler = prepare_logger()
+ logging.info("The module restore_mail_inject.py started with user %s, folder %s and source %s.",
+ args.user, args.folder, args.srcdir)
- # connect
- try:
- session = MailIterator("gwt-intranator.m.i2n", "mit.punkt", "mit.punkt")
+ # connect to unix socket or server
+ if(args.unix_socket_disabled):
+ session = MailIterator(args.user)
+ else:
+ session = MailIterator(args.user)
#session = MailIterator("/var/imap/socket/imap", "cyrus", "geheim")
- storage = FileIterator(args.mboxlist)
- except UserWarning:
- print("Couldn't connect to IMAP server.")
- return
+ storage = FileIterator()
+
+ # retrieve mailbox list from the mailbox list file
+ mailbox_list = storage.load_mailbox_list(args.mboxlistfile)
# delete olf IMAP folders if no append requested
- if(not args.append):
+ if not args.append:
session.delete_mailboxes(args.folder)
- if(args.folder == "INBOX"):
+ if args.folder == "INBOX":
session.clear_inbox_acls(args.user)
# inject emails
path_generator = storage.load_mails(args.srcdir, args.folder)
for message, mailbox, date_modified in path_generator:
+
+ # mailboxes marked for creating and acl update
+ # add acls after all subfolders or their acls will be derived from parent folder
for new_mailbox in storage.created_mailboxes:
session.create_mailbox(new_mailbox)
for acl_mailbox in storage.acl_mailboxes:
- session.add_acls(acl_mailbox, args)
+ session.add_acls(acl_mailbox, mailbox_list, args.ouser, args.user)
+ storage.created_mailboxes = []
+ storage.acl_mailboxes = []
+
session.inject_message(message, mailbox, date_modified)
- # add acls after all subfolders or their acls will be derived from parent folder
- print("Finished injecting mails.")
+ # last iteration mailboxes in case root mailbox has no e-mails for injection
+ for new_mailbox in storage.created_mailboxes:
+ session.create_mailbox(new_mailbox)
+ for acl_mailbox in storage.acl_mailboxes:
+ session.add_acls(acl_mailbox, mailbox_list, args.ouser, args.user)
- return
+ logging.info("Finished injecting mails. Exiting with code %s.", warnings_handler.detected_problems)
+ return warnings_handler.detected_problems
def configure_args():
"""Configure arguments and return them."""
+
# parse arguments
parser = argparse.ArgumentParser(description="Tool to inject mails via IMAP.")
parser.add_argument('-u', '--username', dest='user', action='store',
default="INBOX", help='folder to store mails to - if not specified we overwrite INBOX')
parser.add_argument('-s', '--sourcedir', dest='srcdir', action='store',
required=True, help='folder to read mail from')
- parser.add_argument('-m', '--mboxlist', dest='mboxlist', action='store',
+ parser.add_argument('-m', '--mboxlistfile', dest='mboxlistfile', action='store',
default="", help='mboxlist file (flat file format) to read the ACLs from')
parser.add_argument('-o', '--ouser', dest='ouser', action='store',
default="", help='name of the original user (=username if not specified)')
parser.add_argument('-a', '--append', dest='append', action='store_true',
default=False, help="append mails, don't delete anything")
+ parser.add_argument('-n', '--normal', dest='unix_socket_disabled', action='store_true',
+ default=False, help='disable unix socket usage for the IMAP connection')
args = parser.parse_args()
if (args.folder != "INBOX"):
return args
+def prepare_logger():
+ """Sets up the logging functionality"""
+
+ # reset the log
+ with open(LOG_FILENAME, 'w'):
+ pass
+
+ # add basic configuration
+ logging.basicConfig(filename=LOG_FILENAME,
+ format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
+ level=LOG_FILE_LEVEL)
+
+ # add a handler for a console output
+ default_logger = logging.getLogger('')
+ console = logging.StreamHandler()
+ console.setLevel(LOG_SHELL_LEVEL)
+ formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
+ console.setFormatter(formatter)
+ default_logger.addHandler(console)
+
+ # add a handler for warnings counting
+ warnings_handler = WarningsHandler()
+ warnings_handler.setLevel(LOG_UNCLEAN_EXIT_LEVEL)
+ default_logger.addHandler(warnings_handler)
+
+ return warnings_handler
-if(__name__ == "__main__"):
+if __name__ == "__main__":
main()