Connection error handling and some formatting
[imap-restore-mail] / file_iterator.py
CommitLineData
67e2ec02
PD
1'''
2restore-mail-inject.py - Tool to inject mails via IMAP
3
4Copyright (c) 2012 Intra2net AG
5'''
6
e42bd6a5 7import sys, os
67e2ec02
PD
8import re
9
10MAIL_FILENAME = re.compile("^[0-9]+\.$")
e42bd6a5
PD
11MBOXFILE_LINE = re.compile("^(.*?)\t(?:\d )?default[\t ](.*)$")
12ACL_STRING = re.compile("^(.*?)[\t ](.*?)\t(.*)$")
67e2ec02
PD
13
14class FileIterator:
15 """This class iterates through the e-mail files."""
16
17 # class attributes
67e2ec02
PD
18 # mailboxes created during file traversal
19 created_mailboxes = None
20 # mailboxes to update during file traversal
21 acl_mailboxes = None
22
e42bd6a5 23 def __init__(self):
67e2ec02 24 """Creates a connection and a user session."""
e42bd6a5
PD
25 self.created_mailboxes = []
26 self.acl_mailboxes = []
67e2ec02
PD
27 return
28
29 def __del__(self):
30 """Closes the connection and the user session."""
31 return
32
67e2ec02
PD
33 def _message_read(self, filename):
34 """Retrieves a message from the message file."""
35 try:
36 with open(filename, "r") as msgfile:
37 message = msgfile.read()
38 except:
39 print("Could not open the e-mail file %s.", filename)
40 return message
41
e42bd6a5 42 def load_mailbox_list(self, mboxlistfile = ""):
b0169e56 43 mboxdb = {}
e42bd6a5
PD
44 if mboxlistfile != "":
45 try:
46 with open(mboxlistfile, 'r') as acl_file:
47 for line in acl_file:
b0169e56 48 acls = {}
e42bd6a5 49 linedata = MBOXFILE_LINE.match(line).groups()
b0169e56 50 #!!! test this condition
e42bd6a5
PD
51 if len(linedata) == 0:
52 print("Illegal line in mailbox list dump: %s" % line)
53 sys.exit()
b0169e56 54 key = linedata[0]
e42bd6a5 55 aclstr = linedata[1]
b0169e56
PD
56
57 # loop through acl rights string and build dictionary of users and rights
e42bd6a5 58 while(aclstr != ""):
e42bd6a5
PD
59 acldata = ACL_STRING.match(aclstr).groups()
60 if len(acldata) == 0:
61 print("Illegal line in mailbox list dump: %s" % line)
62 sys.exit()
63 aclstr = acldata[2]
b0169e56
PD
64 acls[acldata[0]]=acldata[1]
65
66 mboxdb[key] = acls
67
e42bd6a5
PD
68 except IOError:
69 print("Could not open mboxlist file %s." % mboxlistfile)
70 return mboxdb
71
67e2ec02
PD
72 def load_mails(self, filepath, mailpath):
73 """Loads all e-mails from file hierarchy.
74 This recursive generator always returns a tuple of
75 the next found (e-mail, mailbox to store, internaldate)."""
67e2ec02
PD
76 #print("Entered directory %s -> %s." % (filepath, mailpath))
77 try:
78 filepath = os.path.abspath(filepath)
79 os.chdir(filepath)
80 except OSError:
81 print("Can't open the directory %s." % filepath)
82 return
83 # mark mailboxes that should be created
84 self.created_mailboxes.append(mailpath)
85 subpaths = os.listdir(filepath)
86 for subpath in subpaths:
87 #print("Now checking subpath %s in %s" % (subpath, filepath))
e42bd6a5 88 if subpath == "." or subpath == "..":
67e2ec02
PD
89 continue
90 new_filepath = filepath + "/" + subpath
91 if (os.path.isfile(new_filepath)):
e42bd6a5 92 if os.path.getsize(new_filepath) == 0:
67e2ec02
PD
93 print("Skipping empty file %s." % subpath)
94 else:
e42bd6a5
PD
95 if MAIL_FILENAME.match(subpath):
96 #print("Injecting file %s." % subpath)
67e2ec02
PD
97 try:
98 message = self._message_read(new_filepath)
99 # suggest file modification date for internaldate
100 yield (message, mailpath, os.path.getmtime(new_filepath))
101 except:
b0169e56 102 print("Could not retrieve mail from file: %s" % new_filepath)
67e2ec02 103 else:
e42bd6a5 104 if os.path.isdir(new_filepath):
67e2ec02
PD
105 # cyrus ^ vs . storage replacement
106 subpath = subpath.replace("^", ".")
107 new_mailpath = mailpath + "/" + subpath
108 #print("Inserting mails from directory %s into mailbox %s." % (new_filepath, new_mailpath))
109 # load_mails($mboxdbref, $origuser, $targetuser)
110 rcrs_generator = self.load_mails(new_filepath, new_mailpath)
111 # you enter the generator in the for loop
112 for rcr in rcrs_generator:
113 yield rcr
114 #print("Done with directory %s and mailbox %s." % (new_filepath, new_mailpath))
115 # mark mailboxes that need acl update
116 self.acl_mailboxes.append(mailpath)
b2bbd1f5 117 return