Add unit testing for the mailbox acls parsing functionality
[imap-restore-mail] / restore_mail_inject.py
CommitLineData
67e2ec02
PD
1'''
2restore-mail-inject.py - Tool to inject mails via IMAP
3
4Copyright (c) 2012 Intra2net AG
e42bd6a5
PD
5
6This program relies on the following assumptions:
7- IMAP hierarchy separator is / (unixhierarysep=yes)
8- INBOX maps to user/[username]
9- internal encoding of . etc. as of cyrus 2.2
67e2ec02 10'''
f797b0fd 11import logging
67e2ec02
PD
12import argparse
13from mail_iterator import MailIterator
14from file_iterator import FileIterator
5737b10e 15from warnings_handler import WarningsHandler
67e2ec02 16
f797b0fd
PD
17LOG_FILENAME = "restore_mail_inject.log"
18LOG_FILE_LEVEL = logging.DEBUG
19LOG_SHELL_LEVEL = logging.INFO
5737b10e 20LOG_UNCLEAN_EXIT_LEVEL = logging.WARNING
f797b0fd 21
67e2ec02
PD
22def main():
23 """Main function."""
24
25 # prepare configuration
26 args = configure_args()
5737b10e 27 warnings_handler = prepare_logger()
38f15e57
PD
28 logging.info("The module restore_mail_inject.py started with user %s, folder %s and source %s.",
29 args.user, args.folder, args.srcdir)
67e2ec02 30
38f15e57
PD
31 # connect to unix socket or server
32 if(args.unix_socket_disabled):
33 session = MailIterator(args.user)
34 else:
35 session = MailIterator(args.user)
79c28101 36 #session = MailIterator("/var/imap/socket/imap", "cyrus", "geheim")
f797b0fd 37 storage = FileIterator()
67e2ec02 38
e42bd6a5
PD
39 # retrieve mailbox list from the mailbox list file
40 mailbox_list = storage.load_mailbox_list(args.mboxlistfile)
41
67e2ec02 42 # delete olf IMAP folders if no append requested
e42bd6a5 43 if not args.append:
67e2ec02 44 session.delete_mailboxes(args.folder)
e42bd6a5 45 if args.folder == "INBOX":
67e2ec02
PD
46 session.clear_inbox_acls(args.user)
47
48 # inject emails
49 path_generator = storage.load_mails(args.srcdir, args.folder)
50 for message, mailbox, date_modified in path_generator:
f797b0fd 51
e42bd6a5
PD
52 # mailboxes marked for creating and acl update
53 # add acls after all subfolders or their acls will be derived from parent folder
67e2ec02
PD
54 for new_mailbox in storage.created_mailboxes:
55 session.create_mailbox(new_mailbox)
56 for acl_mailbox in storage.acl_mailboxes:
e42bd6a5
PD
57 session.add_acls(acl_mailbox, mailbox_list, args.ouser, args.user)
58 storage.created_mailboxes = []
59 storage.acl_mailboxes = []
f797b0fd 60
67e2ec02 61 session.inject_message(message, mailbox, date_modified)
f797b0fd 62
e42bd6a5
PD
63 # last iteration mailboxes in case root mailbox has no e-mails for injection
64 for new_mailbox in storage.created_mailboxes:
65 session.create_mailbox(new_mailbox)
66 for acl_mailbox in storage.acl_mailboxes:
67 session.add_acls(acl_mailbox, mailbox_list, args.ouser, args.user)
f797b0fd 68
38f15e57 69 logging.info("Finished injecting mails. Exiting with code %s.", warnings_handler.detected_problems)
5737b10e 70 return warnings_handler.detected_problems
67e2ec02
PD
71
72def configure_args():
73 """Configure arguments and return them."""
0cf4dc33 74
67e2ec02
PD
75 # parse arguments
76 parser = argparse.ArgumentParser(description="Tool to inject mails via IMAP.")
77 parser.add_argument('-u', '--username', dest='user', action='store',
78 required=True, help='user to store mails to')
79 parser.add_argument('-f', '--foldername', dest='folder', action='store',
80 default="INBOX", help='folder to store mails to - if not specified we overwrite INBOX')
81 parser.add_argument('-s', '--sourcedir', dest='srcdir', action='store',
82 required=True, help='folder to read mail from')
e42bd6a5 83 parser.add_argument('-m', '--mboxlistfile', dest='mboxlistfile', action='store',
67e2ec02
PD
84 default="", help='mboxlist file (flat file format) to read the ACLs from')
85 parser.add_argument('-o', '--ouser', dest='ouser', action='store',
86 default="", help='name of the original user (=username if not specified)')
87 parser.add_argument('-a', '--append', dest='append', action='store_true',
88 default=False, help="append mails, don't delete anything")
38f15e57
PD
89 parser.add_argument('-n', '--normal', dest='unix_socket_disabled', action='store_true',
90 default=False, help='disable unix socket usage for the IMAP connection')
67e2ec02
PD
91 args = parser.parse_args()
92
93 if (args.folder != "INBOX"):
94 args.folder = "INBOX/" + args.folder
95 if (args.ouser == ""):
96 args.ouser = args.user
97
98 return args
99
f797b0fd
PD
100def prepare_logger():
101 """Sets up the logging functionality"""
102
103 # reset the log
104 with open(LOG_FILENAME, 'w'):
105 pass
106
107 # add basic configuration
108 logging.basicConfig(filename=LOG_FILENAME,
109 format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
110 level=LOG_FILE_LEVEL)
111
112 # add a handler for a console output
5737b10e 113 default_logger = logging.getLogger('')
f797b0fd
PD
114 console = logging.StreamHandler()
115 console.setLevel(LOG_SHELL_LEVEL)
116 formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
117 console.setFormatter(formatter)
5737b10e 118 default_logger.addHandler(console)
79c28101 119
5737b10e
PD
120 # add a handler for warnings counting
121 warnings_handler = WarningsHandler()
122 warnings_handler.setLevel(LOG_UNCLEAN_EXIT_LEVEL)
123 default_logger.addHandler(warnings_handler)
0cf4dc33 124
5737b10e 125 return warnings_handler
67e2ec02 126
e42bd6a5 127if __name__ == "__main__":
67e2ec02 128 main()