2 restore-mail-inject.py - Tool to inject mails via IMAP
4 Copyright (c) 2012 Intra2net AG
11 MAIL_FILENAME = re.compile("^[0-9]+\.$")
12 MBOXFILE_LINE = re.compile("^(.*?)\t(?:\d )?default[\t ](.*)$")
13 ACL_STRING = re.compile("^(.*?)[\t ](.*?)\t(.*)$")
16 """This class iterates through the e-mail files."""
19 # mailboxes created during file traversal
20 created_mailboxes = None
21 # mailboxes to update during file traversal
25 """Creates a connection and a user session."""
26 self.created_mailboxes = []
27 self.acl_mailboxes = []
31 """Closes the connection and the user session."""
35 def _message_read(cls, filename):
36 """Retrieves a message from the message file."""
38 with open(filename, "r") as msgfile:
39 message = msgfile.read()
41 logging.warning("Could not open the e-mail file %s", filename)
46 def load_mailbox_list(cls, mboxlistfile = ""):
47 """Load the list of mailboxes and acl rights for each from file."""
49 if mboxlistfile != "":
51 with open(mboxlistfile, 'r') as acl_file:
54 linedata = MBOXFILE_LINE.match(line).groups()
55 if len(linedata) == 0:
56 logging.warning("Illegal line in mailbox list dump: %s", line)
61 # loop through acl rights string and build dictionary of users and rights
63 acldata = ACL_STRING.match(aclstr).groups()
65 logging.error("Illegal acl string in mailbox list dump: %s", line)
68 acls[acldata[0]] = acldata[1]
72 logging.warning("Could not open mboxlist file %s", mboxlistfile)
75 def load_mails(self, filepath, mailpath):
76 """Loads all e-mails from file hierarchy.
77 This recursive generator always returns a tuple of
78 the next found (e-mail, mailbox to store, internaldate)."""
79 logging.debug("Entered directory %s -> %s", filepath, mailpath)
81 filepath = os.path.abspath(filepath)
84 logging.warning("Can't open the directory %s", filepath)
86 # mark mailboxes that should be created
87 self.created_mailboxes.append(mailpath)
88 subpaths = os.listdir(filepath)
89 for subpath in subpaths:
90 if subpath == "." or subpath == "..":
92 new_filepath = filepath + "/" + subpath
93 if (os.path.isfile(new_filepath)):
94 if os.path.getsize(new_filepath) == 0:
95 logging.info("Skipping empty file %s", subpath)
97 if MAIL_FILENAME.match(subpath):
98 logging.info("Injecting file %s", subpath)
100 message = self._message_read(new_filepath)
101 # suggest file modification date for internaldate
102 yield (message, mailpath, os.path.getmtime(new_filepath))
104 logging.warning("Could not retrieve mail from the file %s", new_filepath)
106 if os.path.isdir(new_filepath):
107 # cyrus ^ vs . storage replacement
108 subpath = subpath.replace("^", ".")
109 new_mailpath = mailpath + "/" + subpath
110 logging.debug("Inserting mails from directory %s into mailbox %s", new_filepath, new_mailpath)
111 # load_mails($mboxdbref, $origuser, $targetuser)
112 rcrs_generator = self.load_mails(new_filepath, new_mailpath)
113 # you enter the generator in the for loop
114 for rcr in rcrs_generator:
116 logging.debug("Done with directory %s and mailbox %s", new_filepath, new_mailpath)
117 # mark mailboxes that need acl update
118 self.acl_mailboxes.append(mailpath)