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