From: Plamen Dimitrov Date: Wed, 11 Jul 2012 10:39:46 +0000 (+0200) Subject: Refactoring of cyrus stored acls formatting - now performed by FileIterator where... X-Git-Url: http://developer.intra2net.com/git/?p=imap-restore-mail;a=commitdiff_plain;h=ed8dc19fe99a4386600560efbfc9a4b8605effaf Refactoring of cyrus stored acls formatting - now performed by FileIterator where it should belong --- diff --git a/src/file_iterator.py b/src/file_iterator.py index c704142..7cfc42c 100644 --- a/src/file_iterator.py +++ b/src/file_iterator.py @@ -31,14 +31,15 @@ class FileIterator: created_mailboxes = None # mailboxes to update during file traversal acl_mailboxes = None + # acls retrieved from a file + file_acls = None def __init__(self): """Creates a connection and a user session.""" self.created_mailboxes = [] self.acl_mailboxes = [] - - return + self.file_acls = {} @classmethod def _message_read(cls, filename): @@ -53,41 +54,41 @@ class FileIterator: return message - @classmethod - def load_mailbox_list(cls, mboxlistfile = ""): + def load_mailbox_list(self, mboxlistfile, original_user): """Load the list of mailboxes and acl rights for each from file.""" - mboxdb = {} - if mboxlistfile != "": - try: - with open(mboxlistfile, 'r') as acl_file: - for line in acl_file: - - acls = {} + try: + with open(mboxlistfile, 'r') as acl_file: + for line in acl_file: + + # read a line using regex + acls = {} + try: + linedata = MBOXFILE_LINE.match(line).groups() + except AttributeError: + logging.warning("Illegal line in mailbox list dump: %s", line) + continue + aclstr = linedata[1] + + # changes acls key encoding to internal cyrus format and makes it absolute (as folder). + key = linedata[0].replace("INBOX/", "user/" + original_user + "/") + key = key.replace(".", "^") + key = key.replace("/", ".") + + # loop through acl rights string and build dictionary of users and rights + while(aclstr != ""): try: - linedata = MBOXFILE_LINE.match(line).groups() + acldata = ACL_STRING.match(aclstr).groups() except AttributeError: - logging.warning("Illegal line in mailbox list dump: %s", line) + logging.warning("Illegal acl string in mailbox list dump: %s", line) + aclstr = "" continue - key = linedata[0] - aclstr = linedata[1] - - # loop through acl rights string and build dictionary of users and rights - while(aclstr != ""): - try: - acldata = ACL_STRING.match(aclstr).groups() - except AttributeError: - logging.warning("Illegal acl string in mailbox list dump: %s", line) - aclstr = "" - continue - aclstr = acldata[2] - acls[acldata[0]] = acldata[1] - - mboxdb[key] = acls - except IOError: - logging.warning("Could not open mboxlist file %s", mboxlistfile) - - return mboxdb + aclstr = acldata[2] + acls[acldata[0]] = acldata[1] + + self.acl_mailboxes[key] = acls + except IOError: + logging.warning("Could not open mboxlist file %s", mboxlistfile) def load_mails(self, filepath, mailpath): """Loads all e-mails from file hierarchy. @@ -140,5 +141,3 @@ class FileIterator: # mark mailboxes that need acl update self.acl_mailboxes.append(mailpath) - - return \ No newline at end of file diff --git a/src/imap_restore_mail.py b/src/imap_restore_mail.py index 093c7a2..e681ec0 100644 --- a/src/imap_restore_mail.py +++ b/src/imap_restore_mail.py @@ -40,8 +40,9 @@ def main(): session = MailIterator(args.server, args.user, psw) storage = FileIterator() - # retrieve mailbox list from the mailbox list file - mailbox_list = storage.load_mailbox_list(args.mboxlistfile) + # retrieve mailbox list if a mailbox list file is specified + if args.mboxlistfile != "": + storage.load_mailbox_list(args.mboxlistfile, args.ouser) # delete olf IMAP folders if no append requested if not args.append: @@ -52,27 +53,36 @@ def main(): # inject emails path_generator = storage.load_mails(args.source, args.destination) 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, mailbox_list, args.ouser, args.user) - storage.created_mailboxes = [] - storage.acl_mailboxes = [] - + update_mailboxes(storage, session, args) session.inject_message(message, mailbox, date_modified) - # 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) + # last iteration for mailboxes in case root mailbox has no e-mails for injection + update_mailboxes(storage, session, args) logging.info("Finished injecting mails. Exiting with code %s.", warnings_handler.detected_problems) return warnings_handler.detected_problems +def update_mailboxes(storage, session, args): + """Create new mailboxes if necessary and add acls to mailboxes if necessary.""" + + # create new mailboxes if found by the file iterator + for new_mailbox in storage.created_mailboxes: + session.create_mailbox(new_mailbox) + + # add acls after all subfolders or their acls will be derived from parent folder + for acl_mailbox in storage.acl_mailboxes: + # find folder acls record and retrieve them + try: + mb_acls = storage.file_acls[acl_mailbox] + except KeyError: + # no rights for the mailbox were found and warn if acl file loaded + if len(storage.file_acls) > 0: + logging.warning("Could not find the acls for mailbox %s for user %s.", acl_mailbox, args.ouser) + mb_acls = {} + session.add_acls(acl_mailbox, mb_acls, args.ouser, args.user) + storage.created_mailboxes = [] + storage.acl_mailboxes = [] + def configure_args(): """Configure arguments and return them.""" diff --git a/src/mail_iterator.py b/src/mail_iterator.py index e46c312..ccd5706 100644 --- a/src/mail_iterator.py +++ b/src/mail_iterator.py @@ -107,31 +107,19 @@ class MailIterator: return - def add_acls(self, mailbox, mailbox_list, original_user, target_user): + def add_acls(self, mailbox, mb_acls, original_user, target_user): """Add acls to mailbox.""" - # change encoding to internal cyrus format and make folder absolute - mailbox = mailbox.replace("INBOX/", "user/" + original_user + "/") - mailbox = mailbox.replace(".", "^") - mailbox = mailbox.replace("/", ".") - - # find folder to set all acls - try: - mbox_acls = mailbox_list[mailbox] - except KeyError: - # no rights for the mailbox were found - logging.warning("Could not find the acls for mailbox %s for user %s.", mailbox, original_user) - return - for acl_user in mbox_acls: + for acl_user in mb_acls: # (in case target user != original user): # - don't overwrite acls eventually set for the current targetuser # - don't set the default owner acls for the new folder if acl_user != target_user and acl_user != original_user: try: - self.mail_con.setacl(mailbox, acl_user, mbox_acls[acl_user]) - logging.debug("Set acls %s for user %s on mailbox %s", mbox_acls[acl_user], acl_user, mailbox) + self.mail_con.setacl(mailbox, acl_user, mb_acls[acl_user]) + logging.debug("Set acls %s for user %s on mailbox %s", mb_acls[acl_user], acl_user, mailbox) except self.mail_con.error as ex: - logging.warning("Could not set acls %s for user %s on mailbox %s: %s", mbox_acls[acl_user], acl_user, mailbox, ex) + logging.warning("Could not set acls %s for user %s on mailbox %s: %s", mb_acls[acl_user], acl_user, mailbox, ex) return @@ -141,7 +129,7 @@ class MailIterator: for mailbox in self.mailboxes: pattern = '^\"?' + deleted_mailbox # if INBOX it cannot be deleted so add delimiter - if (deleted_mailbox == "INBOX"): + if deleted_mailbox == "INBOX": pattern += mailbox[1] if re.compile(pattern).match(mailbox[2]): result, data = self.mail_con.delete(mailbox[2]) @@ -153,8 +141,8 @@ class MailIterator: return def create_mailbox(self, mailbox): - """Create new mailbox to inject messages.""" + if mailbox != "INBOX": result, data = self.mail_con.create(mailbox) if result == "OK": @@ -165,8 +153,8 @@ class MailIterator: return def inject_message(self, message, mailbox, internal_date): - """Inject a message into a mailbox.""" + result, data = self.mail_con.append(mailbox, "\\Seen", internal_date, message.encode()) if result == "OK": logging.debug("Appending message to mailbox %s", mailbox)