From: Plamen Dimitrov Date: Mon, 9 Jul 2012 09:35:29 +0000 (+0200) Subject: File and console logging added for exception handling and information X-Git-Url: http://developer.intra2net.com/git/?p=imap-restore-mail;a=commitdiff_plain;h=f797b0fde37ce15cd108bd8527756a410ef42efb File and console logging added for exception handling and information --- diff --git a/file_iterator.py b/file_iterator.py index 5c3512d..b597928 100644 --- a/file_iterator.py +++ b/file_iterator.py @@ -6,6 +6,7 @@ Copyright (c) 2012 Intra2net AG import sys, os import re +import logging MAIL_FILENAME = re.compile("^[0-9]+\.$") MBOXFILE_LINE = re.compile("^(.*?)\t(?:\d )?default[\t ](.*)$") @@ -35,8 +36,9 @@ class FileIterator: try: with open(filename, "r") as msgfile: message = msgfile.read() - except: - print("Could not open the e-mail file %s.", filename) + except IOError: + logging.warning("Could not open the e-mail file %s", filename) + raise return message def load_mailbox_list(self, mboxlistfile = ""): @@ -49,8 +51,8 @@ class FileIterator: linedata = MBOXFILE_LINE.match(line).groups() #!!! test this condition if len(linedata) == 0: - print("Illegal line in mailbox list dump: %s" % line) - sys.exit() + logging.warning("Illegal line in mailbox list dump: %s" % line) + continue key = linedata[0] aclstr = linedata[1] @@ -58,60 +60,58 @@ class FileIterator: while(aclstr != ""): acldata = ACL_STRING.match(aclstr).groups() if len(acldata) == 0: - print("Illegal line in mailbox list dump: %s" % line) - sys.exit() + logging.error("Illegal acl string in mailbox list dump: %s" % line) + continue aclstr = acldata[2] acls[acldata[0]]=acldata[1] mboxdb[key] = acls - except IOError: - print("Could not open mboxlist file %s." % mboxlistfile) + logging.warning("Could not open mboxlist file %s" % mboxlistfile) return mboxdb def load_mails(self, filepath, mailpath): """Loads all e-mails from file hierarchy. This recursive generator always returns a tuple of the next found (e-mail, mailbox to store, internaldate).""" - #print("Entered directory %s -> %s." % (filepath, mailpath)) + logging.debug("Entered directory %s -> %s" % (filepath, mailpath)) try: filepath = os.path.abspath(filepath) os.chdir(filepath) except OSError: - print("Can't open the directory %s." % filepath) + logging.warning("Can't open the directory %s" % filepath) return # mark mailboxes that should be created self.created_mailboxes.append(mailpath) subpaths = os.listdir(filepath) for subpath in subpaths: - #print("Now checking subpath %s in %s" % (subpath, filepath)) if subpath == "." or subpath == "..": continue new_filepath = filepath + "/" + subpath if (os.path.isfile(new_filepath)): if os.path.getsize(new_filepath) == 0: - print("Skipping empty file %s." % subpath) + logging.info("Skipping empty file %s" % subpath) else: if MAIL_FILENAME.match(subpath): - #print("Injecting file %s." % subpath) + logging.info("Injecting file %s" % subpath) try: message = self._message_read(new_filepath) # suggest file modification date for internaldate yield (message, mailpath, os.path.getmtime(new_filepath)) - except: - print("Could not retrieve mail from file: %s" % new_filepath) + except IOError: + logging.warning("Could not retrieve mail from the file %s" % new_filepath) else: if os.path.isdir(new_filepath): # cyrus ^ vs . storage replacement subpath = subpath.replace("^", ".") new_mailpath = mailpath + "/" + subpath - #print("Inserting mails from directory %s into mailbox %s." % (new_filepath, new_mailpath)) + logging.debug("Inserting mails from directory %s into mailbox %s" % (new_filepath, new_mailpath)) # load_mails($mboxdbref, $origuser, $targetuser) rcrs_generator = self.load_mails(new_filepath, new_mailpath) # you enter the generator in the for loop for rcr in rcrs_generator: yield rcr - #print("Done with directory %s and mailbox %s." % (new_filepath, new_mailpath)) + logging.debug("Done with directory %s and mailbox %s" % (new_filepath, new_mailpath)) # mark mailboxes that need acl update self.acl_mailboxes.append(mailpath) return \ No newline at end of file diff --git a/mail_iterator.py b/mail_iterator.py index fa1de73..518a8d1 100644 --- a/mail_iterator.py +++ b/mail_iterator.py @@ -4,8 +4,10 @@ restore-mail-inject.py - Tool to inject mails via IMAP Copyright (c) 2012 Intra2net AG ''' +import sys import socket, imaplib import re +import logging MAILBOX_RESP = re.compile(r'\((?P.*?)\) "(?P.*)" (?P.*)') UIDVAL_RESP = re.compile(r'(?P.*) \(UIDVALIDITY (?P.*)\)') @@ -33,26 +35,27 @@ class MailIterator: imap_socket.connect("/var/imap/socket/imap") self.mail_con.sock = imap_socket self.mail_con.file = self.mail_con.sock.makefile('rb') - print("Connected to mail server.") - except Exception as ex: - #raise UserWarning("Could not connect to host: %s" % (ex)) - raise + logging.info("Connected to mail server.") + except (self.mail_con.error, socket.error) as ex: + logging.error("Could not connect to host: %s" % (ex)) + sys.exit() # log in try: self.mail_con.login("cyrus", "geheim") self.logged_in = True #self.mail_con.proxyauth(username) - print("Logged in as %s." % username) - except: + logging.info("Logged in as %s." % username) + except self.mail_con.error as ex: self.logged_in = False - raise UserWarning("Could not log in as user " + username) + logging.error("Could not log in as user %s: %s" % (username, ex)) + sys.exit() # list mailboxes try: _result, mailboxes = self.mail_con.list() - except (self.mail_con.error): - raise UserWarning("Could not retrieve mailboxes for user " + username) + except self.mail_con.error as ex: + logging.warning("Could not retrieve mailboxes for user %s: %s" % (username, ex)) self.mailboxes = [] for mailbox in mailboxes: mailbox = MAILBOX_RESP.match(mailbox.decode('iso-8859-1')).groups() @@ -71,17 +74,18 @@ class MailIterator: """Resets the inbox acls for a given user.""" try: _result, inbox_acls = self.mail_con.getacl("INBOX") - except: - print("Could not get the acls of INBOX.") + except self.mail_con.error as ex: + logging.warning("Could not get the acls of INBOX: %s" % ex) + return inbox_acls = ACLS_RESP.findall(inbox_acls[0][6:]) - #print(inbox_acls) + logging.debug("Retrieved acls from INBOX are %s" % inbox_acls) for acl_ref in inbox_acls: if acl_ref[0] != user: try: - self.mail_con.setacl("INBOX", acl_ref[0], "") - print("Reset acls on INBOX for user %s" % acl_ref[0]) - except: - print("Could not reset acls on INBOX for user %s" % acl_ref[0]) + self.mail_con.deleteacl("INBOX", acl_ref[0]) + logging.debug("Reset acls on INBOX for user %s" % acl_ref[0].decode('iso-8859-1')) + except self.mail_con.error as ex: + logging.warning("Could not reset acls on INBOX for user %s: %s" % (acl_ref[0], ex)) return def add_acls(self, mailbox, mailbox_list, original_user, target_user): @@ -102,9 +106,9 @@ class MailIterator: if acl_user != target_user and acl_user != original_user: try: self.mail_con.setacl(mailbox, acl_user, mbox_acls[acl_user]) - print("Set acls %s for user %s on mailbox %s." % (mbox_acls[acl_user], acl_user, mailbox)) - except: - print("Could not set acls %s for user %s on mailbox %s." % (mbox_acls[acl_user], acl_user, mailbox)) + logging.debug("Set acls %s for user %s on mailbox %s" % (mbox_acls[acl_user], acl_user, mailbox)) + except self.mail_con.error as ex: + logging.warning("Could not set acls %s for user %s on mailbox %s: %s" % (mbox_acls[acl_user], acl_user, mailbox, ex)) return @@ -118,9 +122,9 @@ class MailIterator: if re.compile(pattern).match(mailbox[2]): result, data = self.mail_con.delete(mailbox[2]) if result == "OK": - print("Deleted mailbox %s" % mailbox[2]) + logging.debug("Deleted mailbox %s" % mailbox[2]) else: - print("Could not delete folder %s: %s" % (mailbox[2], data[0])) + logging.warning("Could not delete mailbox %s: %s" % (mailbox[2], data[0])) return def create_mailbox(self, mailbox): @@ -128,16 +132,16 @@ class MailIterator: if mailbox != "INBOX": result, data = self.mail_con.create(mailbox) if result == "OK": - print("Creating mailbox %s" % mailbox) + logging.debug("Creating mailbox %s" % mailbox) else: - print("Could not create mailbox %s: %s" % (mailbox, data[0])) + logging.warning("Could not create mailbox %s: %s" % (mailbox, data[0])) return def inject_message(self, message, mailbox, internal_date): """Inject a message into a mailbox.""" result, data = self.mail_con.append(mailbox, "\\Seen", internal_date, message.encode()) if result == "OK": - print("Appending message to mailbox %s" % mailbox) + logging.debug("Appending message to mailbox %s" % mailbox) else: - print("Could not append the e-mail %s: %s" % (message, data[0])) + logging.warning("Could not append the e-mail %s: %s" % (message, data[0])) return \ No newline at end of file diff --git a/restore_mail_inject.py b/restore_mail_inject.py index 791e380..c67e6ed 100644 --- a/restore_mail_inject.py +++ b/restore_mail_inject.py @@ -8,27 +8,28 @@ This program relies on the following assumptions: - INBOX maps to user/[username] - internal encoding of . etc. as of cyrus 2.2 ''' - +import logging import argparse from mail_iterator import MailIterator from file_iterator import FileIterator +LOG_FILENAME = "restore_mail_inject.log" +LOG_FILE_LEVEL = logging.DEBUG +LOG_SHELL_LEVEL = logging.INFO + def main(): """Main function.""" # prepare configuration args = configure_args() - print("The module restore_mail_inject.py started with user %s, folder %s and source %s." % + prepare_logger() + logging.info("The module restore_mail_inject.py started with user %s, folder %s and source %s." % (args.user, args.folder, args.srcdir)) # connect - try: - session = MailIterator(args.user) - #session = MailIterator("/var/imap/socket/imap", "cyrus", "geheim") - storage = FileIterator() - except UserWarning as ex: - print(ex) - return + session = MailIterator(args.user) + #session = MailIterator("/var/imap/socket/imap", "cyrus", "geheim") + storage = FileIterator() # retrieve mailbox list from the mailbox list file mailbox_list = storage.load_mailbox_list(args.mboxlistfile) @@ -42,26 +43,25 @@ def main(): # inject emails path_generator = storage.load_mails(args.srcdir, args.folder) for message, mailbox, date_modified in path_generator: - + # mailboxes marked for creating and acl update # add acls after all subfolders or their acls will be derived from parent folder - #print(storage.created_mailboxes, storage.acl_mailboxes) for new_mailbox in storage.created_mailboxes: session.create_mailbox(new_mailbox) for acl_mailbox in storage.acl_mailboxes: session.add_acls(acl_mailbox, mailbox_list, args.ouser, args.user) storage.created_mailboxes = [] storage.acl_mailboxes = [] - + session.inject_message(message, mailbox, date_modified) - + # last iteration mailboxes in case root mailbox has no e-mails for injection for new_mailbox in storage.created_mailboxes: session.create_mailbox(new_mailbox) for acl_mailbox in storage.acl_mailboxes: session.add_acls(acl_mailbox, mailbox_list, args.ouser, args.user) - - print("Finished injecting mails. Exiting.") + + logging.info("Finished injecting mails. Exiting.") return def configure_args(): @@ -89,6 +89,25 @@ def configure_args(): return args +def prepare_logger(): + """Sets up the logging functionality""" + + # reset the log + with open(LOG_FILENAME, 'w'): + pass + + # add basic configuration + logging.basicConfig(filename=LOG_FILENAME, + format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', + level=LOG_FILE_LEVEL) + + # add a handler for a console output + console = logging.StreamHandler() + console.setLevel(LOG_SHELL_LEVEL) + formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') + console.setFormatter(formatter) + logging.getLogger('').addHandler(console) + return if __name__ == "__main__": main()