Refactoring of cyrus stored acls formatting - now performed by FileIterator where...
[imap-restore-mail] / src / imap_restore_mail.py
CommitLineData
67e2ec02
PD
1'''
2restore-mail-inject.py - Tool to inject mails via IMAP
3
4Copyright (c) 2012 Intra2net AG
20760d94 5Author: Plamen Dimitrov and Thomas Jarosch
e42bd6a5 6
20760d94
PD
7This program is free software: you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation, either version 3 of the License, or
10(at your option) any later version.
11
12This program is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
67e2ec02 16'''
f797b0fd 17import logging
f72ba42a 18import argparse, getpass
67e2ec02
PD
19from mail_iterator import MailIterator
20from file_iterator import FileIterator
5737b10e 21from warnings_handler import WarningsHandler
67e2ec02 22
12d5b37a 23# logging settings
f72ba42a 24LOG_FILENAME = "imap_restore_mail.log"
f797b0fd
PD
25LOG_FILE_LEVEL = logging.DEBUG
26LOG_SHELL_LEVEL = logging.INFO
5737b10e 27LOG_UNCLEAN_EXIT_LEVEL = logging.WARNING
f797b0fd 28
67e2ec02
PD
29def main():
30 """Main function."""
31
32 # prepare configuration
33 args = configure_args()
5737b10e 34 warnings_handler = prepare_logger()
d6b22227
PD
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)
67e2ec02 37
38f15e57 38 # connect to unix socket or server
f72ba42a 39 psw = getpass.getpass()
d6b22227 40 session = MailIterator(args.server, args.user, psw)
f797b0fd 41 storage = FileIterator()
67e2ec02 42
ed8dc19f
PD
43 # retrieve mailbox list if a mailbox list file is specified
44 if args.mboxlistfile != "":
45 storage.load_mailbox_list(args.mboxlistfile, args.ouser)
e42bd6a5 46
67e2ec02 47 # delete olf IMAP folders if no append requested
e42bd6a5 48 if not args.append:
d6b22227
PD
49 session.delete_mailboxes(args.destination)
50 if args.destination == "INBOX":
67e2ec02
PD
51 session.clear_inbox_acls(args.user)
52
53 # inject emails
d6b22227 54 path_generator = storage.load_mails(args.source, args.destination)
67e2ec02 55 for message, mailbox, date_modified in path_generator:
ed8dc19f 56 update_mailboxes(storage, session, args)
67e2ec02 57 session.inject_message(message, mailbox, date_modified)
f797b0fd 58
ed8dc19f
PD
59 # last iteration for mailboxes in case root mailbox has no e-mails for injection
60 update_mailboxes(storage, session, args)
f797b0fd 61
38f15e57 62 logging.info("Finished injecting mails. Exiting with code %s.", warnings_handler.detected_problems)
5737b10e 63 return warnings_handler.detected_problems
67e2ec02 64
ed8dc19f
PD
65def update_mailboxes(storage, session, args):
66 """Create new mailboxes if necessary and add acls to mailboxes if necessary."""
67
68 # create new mailboxes if found by the file iterator
69 for new_mailbox in storage.created_mailboxes:
70 session.create_mailbox(new_mailbox)
71
72 # add acls after all subfolders or their acls will be derived from parent folder
73 for acl_mailbox in storage.acl_mailboxes:
74 # find folder acls record and retrieve them
75 try:
76 mb_acls = storage.file_acls[acl_mailbox]
77 except KeyError:
78 # no rights for the mailbox were found and warn if acl file loaded
79 if len(storage.file_acls) > 0:
80 logging.warning("Could not find the acls for mailbox %s for user %s.", acl_mailbox, args.ouser)
81 mb_acls = {}
82 session.add_acls(acl_mailbox, mb_acls, args.ouser, args.user)
83 storage.created_mailboxes = []
84 storage.acl_mailboxes = []
85
67e2ec02
PD
86def configure_args():
87 """Configure arguments and return them."""
0cf4dc33 88
67e2ec02
PD
89 # parse arguments
90 parser = argparse.ArgumentParser(description="Tool to inject mails via IMAP.")
d6b22227
PD
91 parser.add_argument('-d', '--directory', dest='source', action='store',
92 required=True, help='file directory to read mails from')
93 parser.add_argument('-s', '--server', dest='server', action='store',
94 default="localhost", help='imap server name with default localhost')
67e2ec02
PD
95 parser.add_argument('-u', '--username', dest='user', action='store',
96 required=True, help='user to store mails to')
f72ba42a
PD
97 parser.add_argument('-o', '--ouser', dest='ouser', action='store',
98 default="", help='name of the original user (=username if not specified)')
d6b22227 99 parser.add_argument('-f', '--foldername', dest='destination', action='store',
67e2ec02 100 default="INBOX", help='folder to store mails to - if not specified we overwrite INBOX')
e42bd6a5 101 parser.add_argument('-m', '--mboxlistfile', dest='mboxlistfile', action='store',
67e2ec02 102 default="", help='mboxlist file (flat file format) to read the ACLs from')
67e2ec02
PD
103 parser.add_argument('-a', '--append', dest='append', action='store_true',
104 default=False, help="append mails, don't delete anything")
105 args = parser.parse_args()
106
d6b22227
PD
107 # some default post processing of arguments
108 if (args.destination != "INBOX"):
109 args.destination = "INBOX/" + args.destination
67e2ec02
PD
110 if (args.ouser == ""):
111 args.ouser = args.user
112
113 return args
114
f797b0fd
PD
115def prepare_logger():
116 """Sets up the logging functionality"""
117
118 # reset the log
119 with open(LOG_FILENAME, 'w'):
120 pass
121
122 # add basic configuration
123 logging.basicConfig(filename=LOG_FILENAME,
124 format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
125 level=LOG_FILE_LEVEL)
126
127 # add a handler for a console output
5737b10e 128 default_logger = logging.getLogger('')
f797b0fd
PD
129 console = logging.StreamHandler()
130 console.setLevel(LOG_SHELL_LEVEL)
131 formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
132 console.setFormatter(formatter)
5737b10e 133 default_logger.addHandler(console)
79c28101 134
5737b10e
PD
135 # add a handler for warnings counting
136 warnings_handler = WarningsHandler()
137 warnings_handler.setLevel(LOG_UNCLEAN_EXIT_LEVEL)
138 default_logger.addHandler(warnings_handler)
0cf4dc33 139
5737b10e 140 return warnings_handler
67e2ec02 141
e42bd6a5 142if __name__ == "__main__":
67e2ec02 143 main()