From 4cb5952d34b7847f1ee038ac6218108f996e3e3a Mon Sep 17 00:00:00 2001 From: Justin Campbell Date: Sun, 26 Jul 2020 23:31:45 -0400 Subject: [PATCH] Commit old ECNQueue module for reference --- api/ECNQueue_old.py | 473 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 473 insertions(+) create mode 100755 api/ECNQueue_old.py diff --git a/api/ECNQueue_old.py b/api/ECNQueue_old.py new file mode 100755 index 0000000..8bef24b --- /dev/null +++ b/api/ECNQueue_old.py @@ -0,0 +1,473 @@ +#!/usr/local/bin/python + +#------------------------------------------------------------# +# Summary: Generates pages viewed by end users +#------------------------------------------------------------# + + +#------------------------------------------------------------# +# Import Libraries +#------------------------------------------------------------# +import email +import base64 +import os +import sys +import time +from string import digits +from email.Utils import parseaddr + + +#------------------------------------------------------------# +# Configure Script Environment +#------------------------------------------------------------# +c_queue_command_dir = '/usr/local/etc/ecn/queue/' + +# Use Live Queue: +# c_queue_dir = '/home/pier/e/queue/Mail/' + +# Use Test Queue: +c_queue_dir = '/Users/justincampbell/GitHub/ecn-queue/webqueue/q-snapshot' + +c_queues_to_skip = ['archives', 'drafts', 'inbox'] + +""" +c_header_map = { + 'priority':'qpriority', + 'status':'qstatus', + 'building':'qbuilding', + 'status-updated-by':'qstatus-updated-by', + 'time':'qtime', + 'assigned-to':'qassigned-to' +} +""" + + +class QueueItem: + + def __init__(self, queue_name, number, archive=''): + " Initialize a new Queue Item " + self.queue_name = queue_name # name of the queue containing the item + self.number = int(number) # queue item number + self.attributes = {'number': int(number), 'queue_name': queue_name} # dictionary of headers, attributes, etc. + self.headers = '' # text version of e-mail headers + self.content = '' # text version of e-mail content + self.body = {} # text version of the body of the e-mail + self.attachments = {} # dictionary of attachments keyed on filename + self.message = None # python e-mail representation of the message + self.archive = archive + + def load(self, headers_only=0): + " Load the content of this queue item " + + # Get an open file ready to read the queue item + # file = qCmd('qshow', self.queue_name, self.number, file=1) + if self.archive: + queue_dir = '%sarchives/%s/%s/' % (c_queue_dir, + self.queue_name, self.archive) + else: + queue_dir = '%s%s/' % (c_queue_dir, self.queue_name) + + if os.access(queue_dir + str(self.number), os.R_OK): + file = open(queue_dir + str(self.number)) + else: + return False + + self.attributes['last_updated'] = os.path.getmtime( + queue_dir + str(self.number)) + + in_headers = True + self.headers = '' + self.content = '' + + sys.stdout.flush() + line = 1 + num_lines = 0 + while line: + if in_headers: + line = file.readline() + num_lines += 1 + + # Skip lines beginning with [ or ( in the headers + if len(line) and line[0] in '[(': + if line.find('[%s] ' % self.queue_name) == 0: + line = line.replace('[%s] ' % self.queue_name, '') + else: + continue + + # a newline designates the end of the headers + if len(line) and line[0] == '\n': + in_headers = False + if headers_only: break + + self.headers += line + + else: + self.content += file.read() + break + + file.close() + + self.content = self.stripAttachments(self.content) + + self.message = email.message_from_string(self.headers + self.content) + + # Populate the message attributes from the + # message headers + for key in self.message.keys(): + self[key.lower()] = self.message[key] + + self['from_username'] = parseaddr(self['from'])[1].split('@')[0] + self['subject_status'] = '
%(subject)s
%(qstatus)s
' % self + self['for_username'] = self['qassigned-to'].lower() + + if not headers_only: + # Populate the message attachments from the + # message objects + self.body = {} + + if self.message.is_multipart(): + for part in self.message.walk(): + if part.get_filename(): + self.attachments[part.get_filename()] = {'content-type':part.get_content_type(), 'file':part.get_payload(decode=True)} + + elif part.get_content_type()[:5] == 'text/': + content_type = part.get_content_type() + + if not self.body.has_key(content_type): + self.body[content_type] = '' + + self.body[content_type] += part.get_payload(decode=True) + + else: + # If the message is not multipart then + # this is the body of the document + self.body[self.message.get_content_type()] = self.message.get_payload(decode=True) + + return True + + + def locked(self): + if self.archive: + queue_dir = '%sarchives/%s/%s/' % (c_queue_dir, self.queue_name, self.archive) + else: + queue_dir = '%s%s/' % (c_queue_dir, self.queue_name) + + if os.access(queue_dir + str(self.number) + '.lck', os.R_OK): + file = open(queue_dir + str(self.number) + '.lck') + parts = file.read().replace('\n', '').split(' ') + lock_info = { + 'file':parts[0], + 'program':parts[1], + 'user':parts[-1] + } + return lock_info + return False + + + def stripAttachments(self, message): + if not message: return '' + + lines = message.split('\n') + + attachments = [] + attachment_boundary = '' + attachment_data = '' + message_data = '' + + for line_index, line in enumerate(lines): + if attachment_boundary: + if line.find(attachment_boundary) == 0: + attachments.append(attachment_data) + attachment_boundary = '' + attachment_data = '' + else: + attachment_data += line + '\n' + + elif line.lower().find('content-type:') == 0: + header, value = line.split(':', 1) + value = value.strip().lower() + if value.find('text') == 0 or \ + value.find('multipart') == 0 or \ + value.find('message') == 0: + message_data += line + '\n' + else: + for x in range(line_index-1, 0, -1): + if lines[x].find('--') == 0: + attachment_boundary = lines[x] + for y in range(x+1, line_index): + attachment_data += lines[y] + '\n' + break + attachment_data += line + '\n' + + else: + message_data += line + '\n' + + for attachment in attachments: + message = email.message_from_string(attachment) + self.message = message + self.attachments[str(message.get_filename())] = {'content-type':message.get_content_type(), 'file':message.get_payload(decode=True)} + + return message_data + + def loadHeaders(self): + """ Helper function which calls load with headers_only=1 """ + self.load(headers_only=1) + + def getHeaders(self): + " Return the HTML Headers for this queue item " + if not self.headers: self.loadHeaders() + return self.headers + + def getBody(self, content_types=['text/plain','text/html']): + """ + Return the body of the e-mail using the content_types + to specify a prefered content type. If no content type + matching the prefered type is found it returns the first + body element + """ + + if not self.content: self.load() + + body_text = '' + for content_type in content_types: + if content_type in self.body: + body_text += '\n' + self.body[content_type] + if self.message.epilogue: + body_text += '\n' + self.message.epilogue + if body_text: + return body_text + """ + for content_type in content_types: + if content_type in self.body: + return self.body[content_type] + """ + + if len(self.body.keys()): + return self.body[self.body.keys()[0]] + else: + return '' + + def getAttachments(self): + " Return a list of filenames for all attachments " + if not self.content: self.load() + return self.attachments.keys() + + def getAttachment(self, filename): + " Return the content of a specific attachment " + if not self.content: self.load() + return self.attachments[filename]['file'] + + def getAttachmentContentType(self, filename): + " Return the content-type of a specific attachment " + if not self.content: self.load() + return self.attachments[filename]['content-type'] + + def getNumber(self): + " Returns the number of the queue item " + return self.number + + def numAttachments(self): + " Returns the number of attachments " + if not self.content: self.load() + return len(self.getAttachments()) + + def lastUpdated(self): + return self.attributes['last_updated'] + + def __contains__(self, item): + return item in self.attributes + + def __getitem__(self, key): + if not self.headers: + try: + self.loadHeaders() + except: + raise Exception('Error In Headers', 'Queue Item #%s' % self.number) + + key = key.lower() + # key = c_header_map.get(key, key) + return self.attributes.get(key,'') + + def __setitem__(self, key, value): + self.attributes[key.lower()] = value + + def __str__(self): + return "%14s:%-4s %-10s %-40s" % (self.queue_name, self.number, self['from'], self['subject']) + +class Queue: + + + def __init__(self, queue_name, archive=''): + self.loaded = False + self.queue_name = queue_name + self.archive = archive + self.num_items = None + self.items = [] + self.filtered_items = [] + self.filters = {} + self.sort_on = '' + self.sort_direction = 'ascending' + + def loadItems(self): + self.loaded = True + self.items = [] + + if self.archive: + # Where self.archive = 'YM0502' + queue_dir = c_queue_dir + 'archives/' + self.queue_name + '/' + self.archive + '/' + else: + # lines = qCmd('qscan', self.queue_name).split('\n')[1:] + queue_dir = c_queue_dir + self.queue_name + '/' + + if not os.access(queue_dir, os.F_OK): + return + + for file in os.listdir(queue_dir): + valid = True + for letter in file: + if letter not in digits: + valid = False + break + + if valid and os.access(queue_dir + file, os.R_OK): + item_num = file + item = QueueItem(self.queue_name, file, self.archive) + self.items.append(item) + + self.num_items = len(self.items) + + def sort(self, sort_on, sort_direction='ascending'): + if not self.loaded: self.loadItems() + self.sort_on = sort_on + self.sort_direction = sort_direction + if self.sort_on == 'qpriority': + self.items.sort(lambda a,b:cmp(a[sort_on].upper(), b[sort_on].upper())) + elif self.sort_on == 'date': + self.items.sort(lambda a,b:cmp(time.mktime(email.utils.parsedate(a[sort_on])), time.mktime(email.utils.parsedate(b[sort_on])))) + else: + self.items.sort(lambda a,b:cmp(a[sort_on], b[sort_on])) + + if sort_direction == 'descending': + self.items.reverse() + + self.filtered_items = [] + + def setFilter(self, name, value): + self.filters[name.lower()] = value.lower() + self.filtered_items = [] + + def addItems(self, items): + self.items.extend(items) + self.num_items = len(self.items) + self.loaded = True + + def setItems(self, items): + self.items = items[:] + self.num_items = len(self.items) + self.loaded = True + + def getItems(self, exact_match=False): + if not self.loaded: self.loadItems() + + if not self.filters: + return self.items + + elif self.filtered_items: + return self.filtered_items + + for item in self.items: + matches = False + for filter in self.filters: + for word in self.filters[filter].split(' or '): + word = word.strip() + + if not word: + continue + + if word[0] == '!': + if item[filter].lower().find(word[1:]) < 0: + matches = True + + elif exact_match and item[filter].lower() == word: + matches = True + break + elif not exact_match and item[filter].lower().find(word) >= 0: + matches = True + break + + if matches: + self.filtered_items.append(item) + + return self.filtered_items + + def getName(self): + return self.queue_name + + def setNumItems(self, num): + self.num_items = num + + def getNumItems(self): + if self.num_items is None: + self.num_items = 0 + + if self.archive: + queue_dir = c_queue_dir + 'archives/' + self.queue_name + '/' + self.archive + else: + queue_dir = c_queue_dir + self.queue_name + + files = os.listdir(queue_dir) + for file in files: + valid = 1 + for c in str(file): + if c not in digits: + valid = 0 + break + if valid: + self.num_items += 1 + + return self.num_items + + def lastUpdated(self): + update_times = [] + for item in self.getItems(): + update_times.append(item['last_updated']) + update_times.sort() + update_times.reverse() + if len(update_times): + return update_times[0] + return -1 + + def __len__(self): + return self.getNumItems() + + def __str__(self): + return "%-20s %s" % (self.getName(), self.getNumItems()) + + def __add__(self, other): + new_queue = Queue(self.getName() + '+' + other.getName()) + new_queue.addItems(self.getItems()) + new_queue.addItems(other.getItems()) + return new_queue + + def __cmp__(self, other): + return cmp(self.getName(), other.getName()) + + def __getitem__(self, index): + return self.getItems()[index] + +def getQueues(): + queues = [] + + for file in os.listdir(c_queue_dir): + if os.access(c_queue_dir + file, os.R_OK) and os.path.isdir(c_queue_dir + file) and file not in c_queues_to_skip: + queue = Queue(file) + queues.append(queue) + + return queues + +if __name__ == '__main__': + + # Create a combined Queue + item = QueueItem('webmaster', 22) + body = item.getBody() +