From c2c5b372c26c250af44b9820348788d5e455d2ef Mon Sep 17 00:00:00 2001 From: Stacy Brock Date: Tue, 28 Nov 2023 12:06:32 -0800 Subject: [PATCH] Add support for adding a category to a message --- filter-rules.py | 35 +++++++++++++++++++++++++---------- mail-filter.py | 12 +++++++++++- 2 files changed, 36 insertions(+), 11 deletions(-) diff --git a/filter-rules.py b/filter-rules.py index 9847a41..22e79ac 100644 --- a/filter-rules.py +++ b/filter-rules.py @@ -132,12 +132,20 @@ ALLOW = [ normalized = {} folder_cache = {} +category_cache = {} def filter_message(self, message): # normalize message attributes normalized_to = [x.address.lower() for x in message.to] normalized_from = message.sender.address.lower() + # process message headers into a sane data structure + headers = [] + for header in message.message_headers: + h = {} + h[header['name']] = header['value'].lower() + headers.append(h) + # filter unactionable IAR emails automated_sources = [ 'coresys@lists.oregonstate.edu', @@ -284,6 +292,10 @@ def filter_message(self, message): move_message(message, 'Junk Email') return + # add category to internal messages sent to DLs + if '@oregonstate.edu' in normalized_from and not get_header('To', headers): + add_category(message, 'OSU Inform') + # keep messages from allowed emails and domains for good in ALLOW: if good in normalized_from and normalized_from not in BLOCK_EMAIL: @@ -303,13 +315,6 @@ def filter_message(self, message): move_message(message, 'Junk Email') return - # process message headers into a sane data structure - headers = [] - for header in message.message_headers: - h = {} - h[header['name']] = header['value'].lower() - headers.append(h) - # junk messages from blocked domains is_spam = False for domain in BLOCK_DOMAINS: @@ -352,15 +357,25 @@ def is_in_message(list_, message): break return is_found -def move_message(message, folder): - if folder not in folder_cache: +def move_message(message, folder_name): + """ move a message to a folder stored in the folder cache """ + if folder_name not in folder_cache: return False - message.move(folder_cache[folder]) + message.move(folder_cache[folder_name]) + +def add_category(message, category_name): + """ add an Outlook category to a message """ + if category_name not in category_cache: + return False + message.add_category(category_cache[category_name]) + message.save_message() def init_filters(self): # hack to copy a dict from parent object into local object for k,v in self._folders.items(): folder_cache[k] = v + for k,v in self._categories.items(): + category_cache[k] = v # normalize filter keyword lists normalized['BLOCK_KEYWORDS'] = [x.lower() for x in BLOCK_KEYWORDS] diff --git a/mail-filter.py b/mail-filter.py index 15427cf..3e1077f 100644 --- a/mail-filter.py +++ b/mail-filter.py @@ -54,13 +54,15 @@ def log(msg, level=logging.INFO): class O365MailFilter(object): _scopes = [ 'basic', - 'https://graph.microsoft.com/Mail.ReadWrite' + 'https://graph.microsoft.com/Mail.ReadWrite', + 'https://graph.microsoft.com/MailboxSettings.Read' ] def __init__(self, config): self._config = config self._is_canceled = False self._folders = {} + self._categories = {} self._filtered_cache = { 'last_reset': None, 'ids': set() @@ -114,6 +116,13 @@ class O365MailFilter(object): self._load_folders(mailbox, folder.get_folders(), current_folder_path) + def _load_categories(self): + """ cache Outlook categories for this account """ + oc = self._account.outlook_categories() + categories = oc.get_categories() + for category in categories: + self._categories[category.name] = category + def _clear_cache(self): """ clear the filtered message cache """ log('Clearing filtered message cache...', logging.DEBUG) @@ -135,6 +144,7 @@ class O365MailFilter(object): inbox = mailbox.inbox_folder() self._load_folders(mailbox) + self._load_categories() self._load_filters() # set limit to max allowed by O365, which is 999 messages