2 restore-mail-inject.py - Tool to inject mails via IMAP
4 Copyright (c) 2012 Intra2net AG
12 MAILBOX_RESP = re.compile(r'\((?P<flags>.*?)\) "(?P<delimiter>.*)" (?P<name>.*)')
13 UIDVAL_RESP = re.compile(r'(?P<name>.*) \(UIDVALIDITY (?P<uidval>.*)\)')
14 ACLS_RESP = re.compile(b'(?P<user>.*) (?P<acls>.*)')
17 """This class communicates with the e-mail server."""
20 # IMAP4_SSL for connection with an IMAP server
22 # list of tuples (uidvalidity, mailboxname) for the retrieved mailboxes
27 def __init__(self, username, server = "/var/imap/socket/imap"):
28 """Creates a connection and a user session."""
32 self.mail_con = imaplib.IMAP4("intranator.m.i2n")
34 imap_socket = socket.socket(socket.AF_UNIX)
35 imap_socket.connect(server)
36 self.mail_con.sock = imap_socket
37 self.mail_con.file = self.mail_con.sock.makefile('rb')
38 logging.info("Connected to mail server %s", server)
39 except (socket.error, self.mail_con.error) as ex:
40 logging.error("Could not connect to host: %s", ex)
45 self.mail_con.login("cyrus", "geheim")
47 #self.mail_con.proxyauth(username)
48 logging.info("Logged in as %s.", username)
49 except self.mail_con.error as ex:
50 self.logged_in = False
51 logging.error("Could not log in as user %s: %s", username, ex)
56 _result, mailboxes = self.mail_con.list()
57 except self.mail_con.error as ex:
58 logging.warning("Could not retrieve mailboxes for user %s: %s", username, ex)
60 for mailbox in mailboxes:
61 mailbox = MAILBOX_RESP.match(mailbox.decode('iso-8859-1')).groups()
62 self.mailboxes.append(mailbox)
63 self.mailboxes = sorted(self.mailboxes, key=lambda box: box[2], reverse=True)
68 """Closes the connection and the user session."""
70 # self.mail_con.close()
71 # self.mail_con.logout()
73 def clear_inbox_acls(self, user):
74 """Resets the inbox acls for a given user."""
76 _result, inbox_acls = self.mail_con.getacl("INBOX")
77 except self.mail_con.error as ex:
78 logging.warning("Could not get the acls of INBOX: %s", ex)
80 inbox_acls = ACLS_RESP.findall(inbox_acls[0][6:])
81 logging.debug("Retrieved acls from INBOX are %s", inbox_acls)
82 for acl_ref in inbox_acls:
83 if acl_ref[0] != user:
85 self.mail_con.deleteacl("INBOX", acl_ref[0])
86 logging.debug("Reset acls on INBOX for user %s", acl_ref[0].decode('iso-8859-1'))
87 except self.mail_con.error as ex:
88 logging.warning("Could not reset acls on INBOX for user %s: %s", acl_ref[0], ex)
91 def add_acls(self, mailbox, mailbox_list, original_user, target_user):
92 """Add acls to mailbox."""
94 # change encoding to internal cyrus format and make folder absolute
95 mailbox = mailbox.replace("INBOX/", "user/" + original_user + "/")
96 mailbox = mailbox.replace(".", "^")
97 mailbox = mailbox.replace("/", ".")
99 # find folder to set all acls
101 mbox_acls = mailbox_list[mailbox]
103 # no rights for the mailbox were found
105 for acl_user in mbox_acls:
106 if acl_user != target_user and acl_user != original_user:
108 self.mail_con.setacl(mailbox, acl_user, mbox_acls[acl_user])
109 logging.debug("Set acls %s for user %s on mailbox %s", mbox_acls[acl_user], acl_user, mailbox)
110 except self.mail_con.error as ex:
111 logging.warning("Could not set acls %s for user %s on mailbox %s: %s", mbox_acls[acl_user], acl_user, mailbox, ex)
115 def delete_mailboxes(self, deleted_mailbox):
116 """Delete specified mailbox or empty inbox."""
117 for mailbox in self.mailboxes:
118 pattern = '^\"?' + deleted_mailbox
119 # if INBOX it cannot be deleted so add delimiter
120 if (deleted_mailbox == "INBOX"):
121 pattern += mailbox[1]
122 if re.compile(pattern).match(mailbox[2]):
123 result, data = self.mail_con.delete(mailbox[2])
125 logging.debug("Deleted mailbox %s", mailbox[2])
127 logging.warning("Could not delete mailbox %s: %s", mailbox[2], data[0])
130 def create_mailbox(self, mailbox):
131 """Create new mailbox to inject messages."""
132 if mailbox != "INBOX":
133 result, data = self.mail_con.create(mailbox)
135 logging.debug("Creating mailbox %s", mailbox)
137 logging.warning("Could not create mailbox %s: %s", mailbox, data[0])
140 def inject_message(self, message, mailbox, internal_date):
141 """Inject a message into a mailbox."""
142 result, data = self.mail_con.append(mailbox, "\\Seen", internal_date, message.encode())
144 logging.debug("Appending message to mailbox %s", mailbox)
146 logging.warning("Could not append the e-mail %s: %s", message, data[0])