From 3cf18ece38905724bc9c8efbca75cb3f98adb455 Mon Sep 17 00:00:00 2001 From: nnako Date: Sun, 5 Jul 2015 13:36:24 +0200 Subject: [PATCH 1/3] NEW: function to get PDF attachments from eMail --- mailbot/callback.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/mailbot/callback.py b/mailbot/callback.py index 6d0090a..f58dc3c 100644 --- a/mailbot/callback.py +++ b/mailbot/callback.py @@ -93,6 +93,28 @@ def get_email_body(self, message=None): return '' + def get_attachments(self, message=None): + """Return a list of attachments. + + Return all attached files within a list of 2-tuples filename and + content of the attachment to be stored locally. + + """ + if message is None: + message = self.message + + if not hasattr(message, 'walk'): # not an email.Message instance? + return None + + content = [] + for part in message.walk(): + content_type = part.get_content_type() + filename = part.get_filename() + if content_type == 'application/pdf' and filename is not None: + # PDF file of the mail + content = content + [(filename,part.get_payload(decode=True))] + return content + def trigger(self): """Called when a mail matching the registered rules is received.""" raise NotImplementedError("Must be implemented in a child class.") From 404d40ddc51164ca9e30a944a29667d2647fdd9d Mon Sep 17 00:00:00 2001 From: nnako Date: Sun, 5 Jul 2015 18:00:17 +0200 Subject: [PATCH 2/3] NEW: optional choice (binary coded) of eMails to be checked ("not deleted", "unseen" and "unflagged") --- mailbot/mailbot.py | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/mailbot/mailbot.py b/mailbot/mailbot.py index b9520f3..60af619 100644 --- a/mailbot/mailbot.py +++ b/mailbot/mailbot.py @@ -17,6 +17,11 @@ class MailBot(object): home_folder = 'INBOX' imapclient = IMAPClient + # DEFINITIONS + CHECK_PRESENT_EMAILS = 1 # check all not deleted eMails + CHECK_UNSEEN_EMAILS = 2 # check all unseen eMails + CHECK_UNFLAGGED_EMAILS = 4 # check all unflagged eMails + def __init__(self, host, username, password, port=None, use_uid=True, ssl=False, stream=False, timeout=None): """Create, connect and login the MailBot. @@ -36,13 +41,23 @@ def __init__(self, host, username, password, port=None, use_uid=True, self.client.normalise_times = False # deal with UTC everywhere self.timeout = timeout - def get_message_ids(self): + def get_message_ids(self, check_pref=6): """Return the list of IDs of messages to process.""" - return self.client.search(['Unseen', 'Unflagged']) - def get_messages(self): + # choose eMails to be regarded in check + lstSearchPref = [] + if check_pref & self.CHECK_PRESENT_EMAILS: + lstSearchPref.append('not deleted') + if check_pref & self.CHECK_UNSEEN_EMAILS: + lstSearchPref.append('Unseen') + if check_pref & self.CHECK_UNFLAGGED_EMAILS: + lstSearchPref.append('Unflagged') + + return self.client.search(lstSearchPref) + + def get_messages(self, check_pref=6): """Return the list of messages to process.""" - ids = self.get_message_ids() + ids = self.get_message_ids(check_pref) return self.client.fetch(ids, ['RFC822']) def process_message(self, message, callback_class, rules): @@ -51,11 +66,11 @@ def process_message(self, message, callback_class, rules): if callback.check_rules(): return callback.trigger() - def process_messages(self): + def process_messages(self, check_pref=6): """Process messages: check which callbacks should be triggered.""" from . import CALLBACKS_MAP self.reset_timeout_messages() - messages = self.get_messages() + messages = self.get_messages(check_pref) for uid, msg in messages.items(): self.mark_processing(uid) From 874ef121e26c1a724cdce7b1eac800b40c423490 Mon Sep 17 00:00:00 2001 From: nnako Date: Mon, 6 Jul 2015 22:02:18 +0200 Subject: [PATCH 3/3] MOD: better specification of file types to be obtained as attachments --- mailbot/callback.py | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/mailbot/callback.py b/mailbot/callback.py index f58dc3c..d8b9379 100644 --- a/mailbot/callback.py +++ b/mailbot/callback.py @@ -12,6 +12,12 @@ class Callback(object): """Base class for callbacks.""" + # DEFINITIONS + GET_ALL_ATTACHMENTS = 255 # get all attachments from eMail + GET_PDF_ATTACHMENTS = 1 # get only PDFs + GET_MSOFFICE_ATTACHMENTS = 2 # get only Word documents + GET_IMAGE_ATTACHMENTS = 4 # get only images + def __init__(self, message, rules): self.matches = defaultdict(list) self.message = message @@ -93,7 +99,7 @@ def get_email_body(self, message=None): return '' - def get_attachments(self, message=None): + def get_attachments(self, message=None, documents=GET_ALL_ATTACHMENTS): """Return a list of attachments. Return all attached files within a list of 2-tuples filename and @@ -110,9 +116,28 @@ def get_attachments(self, message=None): for part in message.walk(): content_type = part.get_content_type() filename = part.get_filename() - if content_type == 'application/pdf' and filename is not None: - # PDF file of the mail - content = content + [(filename,part.get_payload(decode=True))] + + # check for desired file types + if documents == self.GET_ALL_ATTACHMENTS: + + # get any file + if filename is not None: + content = content + [(filename, part.get_payload(decode=True))] + + else: + + # PDF file type + if documents & self.GET_PDF_ATTACHMENTS and content_type == 'application/pdf' and filename is not None: + content = content + [(filename,part.get_payload(decode=True))] + + # MS OFFICE file types + if documents & self.GET_MSOFFICE_ATTACHMENTS and content_type.find('application/ms') > -1 and filename is not None: + content = content + [(filename,part.get_payload(decode=True))] + + # IMAGE file types + if documents & self.GET_IMAGE_ATTACHMENTS and content_type.find('image') > -1 and filename is not None: + content = content + [(filename,part.get_payload(decode=True))] + return content def trigger(self):