Converted to unit sockets and cyrus server log in
[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
7aad8dab 7import socket, imaplib_private as imaplib
67e2ec02
PD
8import re
9
10MAILBOX_RESP = re.compile(r'\((?P<flags>.*?)\) "(?P<delimiter>.*)" (?P<name>.*)')
11UIDVAL_RESP = re.compile(r'(?P<name>.*) \(UIDVALIDITY (?P<uidval>.*)\)')
9ce1038d 12ACLS_RESP = re.compile(r'(?P<user>.*) (?P<acls>.*)')
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
7aad8dab 25 def __init__(self, username):
67e2ec02 26 """Creates a connection and a user session."""
9ce1038d 27
b2bbd1f5 28 # connect to server
67e2ec02 29 try:
7aad8dab
PD
30 self.mail_con = imaplib.IMAP4("intranator.m.i2n")
31 #imap_socket = socket.socket(socket.AF_UNIX)
32 #imap_socket.connect("/var/imap/socket/imap")
33 #self.mail_con.socket = imap_socket
34 print("Connected to mail server.")
b2bbd1f5 35 except Exception as ex:
7aad8dab
PD
36 #raise UserWarning("Could not connect to host: %s" % (ex))
37 raise
b2bbd1f5
PD
38
39 # log in
40 try:
7aad8dab 41 self.mail_con.login("cyrus", "geheim")
b2bbd1f5 42 self.logged_in = True
7aad8dab 43 #self.mail_con.proxyauth(username)
67e2ec02
PD
44 print("Logged in as %s." % username)
45 except:
46 self.logged_in = False
b2bbd1f5 47 raise UserWarning("Could not log in as user " + username)
9ce1038d 48
b2bbd1f5
PD
49 # list mailboxes
50 try:
51 _result, mailboxes = self.mail_con.list()
52 except (self.mail_con.error):
53 raise UserWarning("Could not retrieve mailboxes for user " + username)
67e2ec02
PD
54 self.mailboxes = []
55 for mailbox in mailboxes:
56 mailbox = MAILBOX_RESP.match(mailbox.decode('iso-8859-1')).groups()
57 self.mailboxes.append(mailbox)
58 self.mailboxes = sorted(self.mailboxes, key=lambda box: box[2], reverse=True)
9ce1038d 59
67e2ec02
PD
60 return
61
62 def __del__(self):
63 """Closes the connection and the user session."""
b2bbd1f5
PD
64 #if self.logged_in:
65 # self.mail_con.close()
66 # self.mail_con.logout()
67e2ec02
PD
67
68 def clear_inbox_acls(self, user):
b2bbd1f5 69 """Resets the inbox acls for a given user."""
67e2ec02 70 try:
b2bbd1f5 71 _result, inbox_acls = self.mail_con.getacl("INBOX")
67e2ec02
PD
72 except:
73 print("Could not get the acls of INBOX.")
9ce1038d
PD
74 inbox_acls = ACLS_RESP.findall(inbox_acls[0][6:])
75 #print(inbox_acls)
76 for acl_ref in inbox_acls:
77 if acl_ref[0] != user:
67e2ec02 78 try:
9ce1038d
PD
79 self.mail_con.setacl("INBOX", acl_ref[0], "")
80 print("Reset acls on INBOX for user %s" % acl_ref[0])
67e2ec02 81 except:
9ce1038d 82 print("Could not reset acls on INBOX for user %s" % acl_ref[0])
67e2ec02
PD
83 return
84
e42bd6a5 85 def add_acls(self, mailbox, mailbox_list, original_user, target_user):
67e2ec02 86 """Add acls to mailbox."""
b2bbd1f5 87
e42bd6a5
PD
88 # change encoding to internal cyrus format and make folder absolute
89 mailbox = mailbox.replace("INBOX/", "user/" + original_user + "/")
67e2ec02
PD
90 mailbox = mailbox.replace(".", "^")
91 mailbox = mailbox.replace("/", ".")
b2bbd1f5 92
b0169e56
PD
93 # find folder to set all acls
94 try:
95 mbox_acls = mailbox_list[mailbox]
96 except KeyError:
97 # no rights for the mailbox were found
98 return
99 for acl_user in mbox_acls:
b0169e56
PD
100 if acl_user != target_user and acl_user != original_user:
101 try:
b2bbd1f5 102 self.mail_con.setacl(mailbox, acl_user, mbox_acls[acl_user])
b0169e56
PD
103 print("Set acls %s for user %s on mailbox %s." % (mbox_acls[acl_user], acl_user, mailbox))
104 except:
105 print("Could not set acls %s for user %s on mailbox %s." % (mbox_acls[acl_user], acl_user, mailbox))
b2bbd1f5 106
67e2ec02
PD
107 return
108
109 def delete_mailboxes(self, deleted_mailbox):
110 """Delete specified mailbox or empty inbox."""
111 for mailbox in self.mailboxes:
112 pattern = '^\"?' + deleted_mailbox
113 # if INBOX it cannot be deleted so add delimiter
114 if (deleted_mailbox == "INBOX"):
115 pattern += mailbox[1]
e42bd6a5 116 if re.compile(pattern).match(mailbox[2]):
67e2ec02 117 result, data = self.mail_con.delete(mailbox[2])
e42bd6a5 118 if result == "OK":
67e2ec02
PD
119 print("Deleted mailbox %s" % mailbox[2])
120 else:
121 print("Could not delete folder %s: %s" % (mailbox[2], data[0]))
122 return
123
124 def create_mailbox(self, mailbox):
125 """Create new mailbox to inject messages."""
e42bd6a5 126 if mailbox != "INBOX":
67e2ec02 127 result, data = self.mail_con.create(mailbox)
e42bd6a5 128 if result == "OK":
67e2ec02
PD
129 print("Creating mailbox %s" % mailbox)
130 else:
131 print("Could not create mailbox %s: %s" % (mailbox, data[0]))
132 return
133
134 def inject_message(self, message, mailbox, internal_date):
135 """Inject a message into a mailbox."""
7aad8dab 136 result, data = self.mail_con.append(mailbox, "\\Seen", internal_date, message.encode())
b2bbd1f5 137 if result == "OK":
67e2ec02 138 print("Appending message to mailbox %s" % mailbox)
b2bbd1f5
PD
139 else:
140 print("Could not append the e-mail %s: %s" % (message, data[0]))
67e2ec02 141 return