Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
a9d129a
Begin sender rewrite
mishaturnbull Sep 24, 2018
a3a86a0
Add EmailSendHandler class
mishaturnbull Sep 24, 2018
f1cd8f3
Add the email builder class.
mishaturnbull Sep 24, 2018
550db55
Add Header class
mishaturnbull Sep 24, 2018
5a18fcc
Break config into settings and content subsections
mishaturnbull Sep 24, 2018
32b521d
Start GUI redo, coordinator class
mishaturnbull Sep 24, 2018
a9cdb7c
Add GUI settings front, improvements to look of content menu
mishaturnbull Sep 25, 2018
6ff5d22
Add more functionality to GUI
mishaturnbull Sep 25, 2018
627107a
Fix callback wrapper issue
mishaturnbull Sep 25, 2018
7cbdcaf
Add value dump method between main GUI and coordinator
mishaturnbull Sep 25, 2018
0c9f38d
Add HeaderGUI menu
mishaturnbull Sep 26, 2018
3cacc23
Make parts of the program talk to each other
mishaturnbull Sep 26, 2018
937c605
Fix more bugs
mishaturnbull Sep 26, 2018
a188b68
Miscellaneous bugfixes and minor improvements
mishaturnbull Sep 27, 2018
5e27937
Code cleanup
mishaturnbull Oct 1, 2018
1393be2
More attempts to debug .get() issue
mishaturnbull Oct 2, 2018
8340570
Add debug option; continue working send freeze issue
mishaturnbull Oct 2, 2018
25c0981
Add connect every n emails feature
mishaturnbull Oct 3, 2018
195be75
Move coordinator variable push&pull to GUIBase instead of EmailGUI
mishaturnbull Oct 3, 2018
b49ce8f
Rework settings auto-selection helper
mishaturnbull Oct 3, 2018
ebfd4d3
Fix issue in new auto-selection, auto-loading for checkboxes
mishaturnbull Oct 3, 2018
8d86815
Fixes #23
mishaturnbull Oct 3, 2018
b9c8160
Code cleanup
mishaturnbull Oct 3, 2018
d0df344
More code cleanup
mishaturnbull Oct 3, 2018
cd2e464
Tell Travis to ignore invalid syntax
mishaturnbull Oct 3, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ install:
script:
- >
git fetch origin $TRAVIS_BRANCH:$TRAVIS_BRANCH --depth 1;
flake8-diff --flake8-options $TRAVIS_BRANCH;
flake8-diff --flake8-options --ignore=E999 $TRAVIS_BRANCH;
644 changes: 0 additions & 644 deletions src/EmailGUI.py

This file was deleted.

109 changes: 109 additions & 0 deletions src/coordinator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
# -*- coding: utf-8 -*-
"""
Contains the Coordinator class that is responsible for communications between
all different modules of the program.
"""

import copy
import sys
import os

from emailbuilder import Email
from headers import Headers
from sender import EmailSendHandler
from gui import EmailGUI

from prereqs import CONFIG, FakeSTDOUT
from gui_callbacks import CALLBACKS


class Coordinator(object):
"""
Primarily responsible for coordinating communications between all different
classes in the program.
"""

def __init__(self):
"""Instantiate the Coordinator object. Automatically creates & links
the required modules."""

if CONFIG['settings']['debug']:
print("coordinator.__init__: starting instantiation")

self.settings = copy.deepcopy(CONFIG['settings'])
self.contents = copy.deepcopy(CONFIG['contents'])
self.callbacks = {}
self.register_callbacks()

self.headers = Headers(self, None)
self.email = Email(self, self.headers)
self.headers.email = self.email
self.sender = EmailSendHandler(self)
self.gui = EmailGUI(self)

self.headers.auto_make_basics()

if self.settings['debug']:
print("coordinator.__init__: instantiation complete")

def register_callbacks(self):
"""Given a name and a function, register the callback function."""
# we have to convert the callback to take this as an argument...

for cb in CALLBACKS:
cbname = cb.__name__.split('_')[1]

def wrapit(cbfunc):
def wrapped():
return cbfunc(self)
return wrapped

if self.settings['debug']:
print("coordinator.register_callbacks: registering " + cbname)

self.callbacks.update({cbname: wrapit(cb)})

def retrieve_data_from_uis(self):
"""Get all the data from various UI elements."""

if self.settings['debug']:
print("coordinator.retrieve_data_from_uis: pulling data")

self.gui.dump_values_to_coordinator()

def send(self):
"""Send emails as configured."""

if self.settings['debug']:
print("coordinator: send command recieved")

self.retrieve_data_from_uis()
self.email.pull_data_from_coordinator()
self.sender.run()

def callback_sent(self):
"""Action to take when an email has been sent."""
if self.settings['debug']:
print("coordinator recieved notification of email sent")
self.gui.callback_sent()
if self.settings['debug']:
print("coordinator notification actions completed")


if __name__ == '__main__':
C = Coordinator()

for log in [C.settings['log_stdout'], C.settings['log_stderr']]:
if os.path.exists(log):
os.remove(log)

sys.stdout = FakeSTDOUT(sys.stdout, C.settings['log_stdout'],
realtime=C.settings['debug'])
sys.stderr = FakeSTDOUT(sys.stderr, C.settings['log_stderr'],
realtime=C.settings['debug'])

C.gui.spawn_gui()
C.gui.run()

sys.stdout = sys.stdout.FSO_close()
sys.stderr = sys.stderr.FSO_close()
71 changes: 71 additions & 0 deletions src/emailbuilder.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# -*- coding: utf-8 -*-
"""
Contains the Email class that handles generation of the email message
per configuration defined in the Coordinator class.
"""

from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email.mime.text import MIMEText
from email import encoders

import os


class Email(object):
"""
This class is responsible for constructing a MIMEMultipart message
given details defined in the Coordinator class and the Header class.

It is able to output the final email message as a string.
"""

def __init__(self, coordinator, headers):
"""Instantiate the Email object given the Coordinator and headers."""

self.coordinator = coordinator
self.headers = headers

self.mimemulti = MIMEMultipart()

def add_text(self, text):
"""Attach a chunk of text to the message."""
mimetext = MIMEText(text)
self.mimemulti.attach(mimetext)

def add_header(self, header, value, **options):
"""Add a header to the message header section."""
self.mimemulti.add_header(header, value, **options)

def add_attachment(self, filename):
"""Add a file attachment."""
# I'm absolutely sure I stole this code off stackoverflow somewhere
# about 2 years ago, but I have absolutely no idea where.
# Credit to StackOverflow for this method.
part = MIMEBase('application', 'octet-stream')
part.set_payload(open(filename, 'rb').read())
encoders.encode_base64(part) # modifies in-place. magic.
filepath = os.path.basename(filename)
part.add_header('Content-Disposition',
'attachment; filename="{}"'.format(filepath))
self.mimemulti.attach(part)

def pull_data_from_coordinator(self):
"""Pull in the data from the coordinator."""
self.add_text(self.coordinator.contents['text'])
for attach in self.coordinator.contents['attach'].split(','):
if not attach:
continue
attach = attach.strip()
self.add_attachment(attach)
self.headers.dump_headers_to_email()
# subject is technically a header in MIME...
self.add_header('subject', self.coordinator.contents['subject'])

def getmime(self):
"""Returns the MIMEMultipart object."""
return self.mimemulti

def as_string(self):
"""Returns the stored email message as a string."""
return self.mimemulti.as_string()
Loading