Perl lists turned to python dictionaries for performance and code readability
[imap-restore-mail] / mail_iterator.py
1 '''
2 restore-mail-inject.py - Tool to inject mails via IMAP
3
4 Copyright (c) 2012 Intra2net AG
5 '''
6
7 import imaplib
8 import re
9
10 MAILBOX_RESP = re.compile(r'\((?P<flags>.*?)\) "(?P<delimiter>.*)" (?P<name>.*)')
11 UIDVAL_RESP = re.compile(r'(?P<name>.*) \(UIDVALIDITY (?P<uidval>.*)\)')
12
13 class MailIterator:
14     """This class communicates with the e-mail server."""
15
16     # class attributes
17     # IMAP4_SSL for connection with an IMAP server
18     mail_con = None
19     # list of tuples (uidvalidity, mailboxname) for the retrieved mailboxes
20     mailboxes = None
21     # logged in status
22     logged_in = None
23
24     def __init__(self, server, username, password):
25         """Creates a connection and a user session."""
26         # authentication
27         try:
28             self.mail_con = imaplib.IMAP4_SSL(server)
29             self.mail_con.login(username, password)
30             print("Logged in as %s." % username)
31         except:
32             self.logged_in = False
33             print("Could not log in as user " + username + ".")
34             raise UserWarning
35         self.logged_in = True
36
37         # prepare mailboxes
38         _result, mailboxes = self.mail_con.list()
39         self.mailboxes = []
40         for mailbox in mailboxes:
41             mailbox = MAILBOX_RESP.match(mailbox.decode('iso-8859-1')).groups()
42             self.mailboxes.append(mailbox)
43         self.mailboxes = sorted(self.mailboxes, key=lambda box: box[2], reverse=True)
44         return
45
46     def __del__(self):
47         """Closes the connection and the user session."""
48         if self.logged_in:
49             try:
50                 self.mail_con.close()
51                 self.mail_con.logout()
52             except:
53                 pass
54
55     def clear_inbox_acls(self, user):
56         """Resets the inbox acls for each user."""
57         try:
58             hashref = self.mail_con.getacl("INBOX")
59         except:
60             print("Could not get the acls of INBOX.")
61         print(hashref)
62         for acluser in hashref:
63             if acluser != user:
64                 try:
65                     #print(self.mail_con.setacl("INBOX", acluser, ""))
66                     print("Reset acls on INBOX for user %s" % acluser)
67                 except:
68                     print("Could not reset acls on INBOX for user %s" % acluser)
69         return
70
71     def add_acls(self, mailbox, mailbox_list, original_user, target_user):
72         """Add acls to mailbox."""
73         
74         # change encoding to internal cyrus format and make folder absolute
75         mailbox = mailbox.replace("INBOX/", "user/" + original_user + "/")
76         mailbox = mailbox.replace(".", "^")
77         mailbox = mailbox.replace("/", ".")
78         
79         # find folder to set all acls
80         try:
81             mbox_acls = mailbox_list[mailbox]
82         except KeyError:
83             # no rights for the mailbox were found
84             return
85         for acl_user in mbox_acls:
86             print(acl_user, target_user, original_user)
87             if acl_user != target_user and acl_user != original_user:
88                 try:
89                     #self.mail_con.setacl(mailbox, thisaclref[0], thisaclref[1])
90                     print("Set acls %s for user %s on mailbox %s." % (mbox_acls[acl_user], acl_user, mailbox))
91                 except:
92                     print("Could not set acls %s for user %s on mailbox %s." % (mbox_acls[acl_user], acl_user, mailbox))    
93         
94         return
95
96     def delete_mailboxes(self, deleted_mailbox):
97         """Delete specified mailbox or empty inbox."""
98         for mailbox in self.mailboxes:
99             pattern = '^\"?' + deleted_mailbox
100             # if INBOX it cannot be deleted so add delimiter
101             if (deleted_mailbox == "INBOX"):
102                 pattern += mailbox[1]
103             if re.compile(pattern).match(mailbox[2]):
104                 result, data = self.mail_con.delete(mailbox[2])
105                 if result == "OK":
106                     print("Deleted mailbox %s" % mailbox[2])
107                 else:
108                     print("Could not delete folder %s: %s" % (mailbox[2], data[0]))         
109         return
110
111     def create_mailbox(self, mailbox):
112         """Create new mailbox to inject messages."""
113         if mailbox != "INBOX":
114             result, data = self.mail_con.create(mailbox)
115             if result == "OK":
116                 print("Creating mailbox %s" % mailbox)
117             else:
118                 print("Could not create mailbox %s: %s" % (mailbox, data[0]))
119         return
120
121     def inject_message(self, message, mailbox, internal_date):
122         """Inject a message into a mailbox."""
123         
124         #$imap->append_file($folder, $full_path, undef, "\\Seen", true)
125         try:
126             result, data = self.mail_con.append(mailbox, "\\Seen",
127                                                 internal_date, message)
128             print("Appending message to mailbox %s" % mailbox)
129         except:
130             raise UserWarning("Could not append the e-mail." % message)
131         return