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