Refactoring of cyrus stored acls formatting - now performed by FileIterator where...
authorPlamen Dimitrov <plamen.dimitrov@intra2net.com>
Wed, 11 Jul 2012 10:39:46 +0000 (12:39 +0200)
committerPlamen Dimitrov <plamen.dimitrov@intra2net.com>
Wed, 11 Jul 2012 10:39:46 +0000 (12:39 +0200)
src/file_iterator.py
src/imap_restore_mail.py
src/mail_iterator.py

index c704142..7cfc42c 100644 (file)
@@ -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
index 093c7a2..e681ec0 100644 (file)
@@ -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."""
 
index e46c312..ccd5706 100644 (file)
@@ -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)