2 restore-mail-inject.py - Tool to inject mails via IMAP
4 Copyright (c) 2012 Intra2net AG
5 Author: Plamen Dimitrov and Thomas Jarosch
7 This program is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
18 import argparse, getpass
19 from mail_iterator import MailIterator
20 from file_iterator import FileIterator
21 from warnings_handler import WarningsHandler
24 LOG_FILENAME = "imap_restore_mail.log"
25 LOG_FILE_LEVEL = logging.DEBUG
26 LOG_SHELL_LEVEL = logging.INFO
27 LOG_UNCLEAN_EXIT_LEVEL = logging.WARNING
32 # prepare configuration
33 args = configure_args()
34 warnings_handler = prepare_logger()
35 logging.info("The module restore_mail_inject.py started with user %s, destination %s and source %s.",
36 args.user, args.destination, args.source)
38 # connect to unix socket or server
39 psw = getpass.getpass()
40 session = MailIterator(args.server, args.user, psw)
41 storage = FileIterator()
43 # retrieve mailbox list from the mailbox list file
44 mailbox_list = storage.load_mailbox_list(args.mboxlistfile)
46 # delete olf IMAP folders if no append requested
48 session.delete_mailboxes(args.destination)
49 if args.destination == "INBOX":
50 session.clear_inbox_acls(args.user)
53 path_generator = storage.load_mails(args.source, args.destination)
54 for message, mailbox, date_modified in path_generator:
56 # mailboxes marked for creating and acl update
57 # add acls after all subfolders or their acls will be derived from parent folder
58 for new_mailbox in storage.created_mailboxes:
59 session.create_mailbox(new_mailbox)
60 for acl_mailbox in storage.acl_mailboxes:
61 session.add_acls(acl_mailbox, mailbox_list, args.ouser, args.user)
62 storage.created_mailboxes = []
63 storage.acl_mailboxes = []
65 session.inject_message(message, mailbox, date_modified)
67 # last iteration mailboxes in case root mailbox has no e-mails for injection
68 for new_mailbox in storage.created_mailboxes:
69 session.create_mailbox(new_mailbox)
70 for acl_mailbox in storage.acl_mailboxes:
71 session.add_acls(acl_mailbox, mailbox_list, args.ouser, args.user)
73 logging.info("Finished injecting mails. Exiting with code %s.", warnings_handler.detected_problems)
74 return warnings_handler.detected_problems
77 """Configure arguments and return them."""
80 parser = argparse.ArgumentParser(description="Tool to inject mails via IMAP.")
81 parser.add_argument('-d', '--directory', dest='source', action='store',
82 required=True, help='file directory to read mails from')
83 parser.add_argument('-s', '--server', dest='server', action='store',
84 default="localhost", help='imap server name with default localhost')
85 parser.add_argument('-u', '--username', dest='user', action='store',
86 required=True, help='user to store mails to')
87 parser.add_argument('-o', '--ouser', dest='ouser', action='store',
88 default="", help='name of the original user (=username if not specified)')
89 parser.add_argument('-f', '--foldername', dest='destination', action='store',
90 default="INBOX", help='folder to store mails to - if not specified we overwrite INBOX')
91 parser.add_argument('-m', '--mboxlistfile', dest='mboxlistfile', action='store',
92 default="", help='mboxlist file (flat file format) to read the ACLs from')
93 parser.add_argument('-a', '--append', dest='append', action='store_true',
94 default=False, help="append mails, don't delete anything")
95 args = parser.parse_args()
97 # some default post processing of arguments
98 if (args.destination != "INBOX"):
99 args.destination = "INBOX/" + args.destination
100 if (args.ouser == ""):
101 args.ouser = args.user
105 def prepare_logger():
106 """Sets up the logging functionality"""
109 with open(LOG_FILENAME, 'w'):
112 # add basic configuration
113 logging.basicConfig(filename=LOG_FILENAME,
114 format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
115 level=LOG_FILE_LEVEL)
117 # add a handler for a console output
118 default_logger = logging.getLogger('')
119 console = logging.StreamHandler()
120 console.setLevel(LOG_SHELL_LEVEL)
121 formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
122 console.setFormatter(formatter)
123 default_logger.addHandler(console)
125 # add a handler for warnings counting
126 warnings_handler = WarningsHandler()
127 warnings_handler.setLevel(LOG_UNCLEAN_EXIT_LEVEL)
128 default_logger.addHandler(warnings_handler)
130 return warnings_handler
132 if __name__ == "__main__":