Skip to content

Commit

Permalink
Lots of bug fixes!
Browse files Browse the repository at this point in the history
Just little bug fixes here and there regarding lots of things. Files
weren't currently processed for attaching to outgoing emails.

Unsent emails will now be saved to a user specified file, specified
using the unsent_save_location tag in config files.

There was a bug in the MPD script, for random songs that are currently
playing, the title may not be retrievable for whatever reason. This is
caught and ignored when it occurs.

Emails that contained script processing didn't specify who sent the
emails they're sending back, this is now fixed.

Whenever locking occurs now in code that may bomb out with exceptions,
the lock is ALWAYS released in a finally block. This way we know it will
always be run.
  • Loading branch information
Nathan Hoad committed Feb 26, 2011
1 parent 0bd8eab commit d0f1803
Show file tree
Hide file tree
Showing 6 changed files with 46 additions and 31 deletions.
Binary file modified .rabbit
Binary file not shown.
21 changes: 12 additions & 9 deletions emails.py
Expand Up @@ -11,7 +11,9 @@
import re
import time
import os
import sys
import tempfile
import traceback

from smtplib import SMTPAuthenticationError
from email import encoders
Expand Down Expand Up @@ -185,9 +187,10 @@ def login_smtp(self):
self.sender.login(self.username, self.password)
logging.info("SMTP logged in")
except SMTPAuthenticationError as e:
message = "Error logging into SMTP: {0}".format(e)
trace = traceback.format_exc()
message = "Error logging into SMTP: {0}".format(trace)
logging.critical(message)
print(message)
print(message, file=sys.stderr)
raise ShutdownException(2)

def login_imap(self):
Expand Down Expand Up @@ -228,12 +231,13 @@ def send_email(self, email):

msg.attach(MIMEText(email.body))

if email.filename:
data = open(email.filename, 'rb').read()
part = MIMEBase('application', 'octet-stream')
part.set_payload(data)
encoders.encode_base64(part)
part.add_header('Content-Disposition', 'attachment; filename="{0}"'.format(os.path.basename(email.filename)))
if len(email.files) > 0:
for name, path in email.files:
data = open(name, 'rb').read()
part = MIMEBase('application', 'octet-stream')
part.set_payload(data)
encoders.encode_base64(part)
part.add_header('Content-Disposition', 'attachment; filename="{0}"'.format(os.path.basename(name)))

msg.attach(part)

Expand Down Expand Up @@ -306,7 +310,6 @@ def receive_mail(self):

e.attach_file(filename, filepath)

print(e)
emails.append(e)
else:
logging.debug("There are NO new emails!")
Expand Down
16 changes: 9 additions & 7 deletions functions.py
Expand Up @@ -15,19 +15,21 @@
import config


def save_emails_to_file(emails, filename):
def save_emails_to_file(emails, filename, reason):
"""Save a list of emails to a file in the current working directory.
Keyword arguments:
emails -- list of Email objects to be saved to file.
filename -- the filename to save unsent emails to.
reason -- the text or exception reason the emails couldn't be sent.
"""
now = datetime.datetime.now()
date = '{0}-{1}-{2}'.format(now.day, now.month, now.year)
time = '{0}:{1}:{2}'.format(now.hour, now.minute, now.second)
with open(filename, 'a') as f:
f.write('On the {0}, at {1}, the following emails could not be sent:\n'.format(date, time))
f.write('The reason for this: {0}\n'.format(reason))

for e in emails:
f.write('{0}\n'.format(e))
Expand All @@ -43,7 +45,7 @@ def monitor(filename, server):
server -- the EmailServer currently running, to pass the new values to when they're changed.
"""
print("Beginning Monitoring for {0}".format(filename))
logging.info('Monitoring {0} for changes'.format(filename))

class PClose(ProcessEvent):
def __init__(self, server, filename):
Expand Down Expand Up @@ -71,10 +73,9 @@ def process_IN_CLOSE(self, event):
lock.release()

except KeyError as e:
print("{0} could not be found in the config file. Consult the documentation for help.".format(e), file=sys.stderr)
print(dir(e))
raise e
sys.exit(4)
logging.info("{0} could not be found in the config file. Consult the documentation for help.".format(e), file=sys.stderr)
self.stop()
raise ShutdownException(15)

wm = WatchManager()
notifier = ThreadedNotifier(wm, PClose(server, filename))
Expand Down Expand Up @@ -136,6 +137,7 @@ def get_smtp_settings(conf):

return imap_server, imap_port, imap_use_ssl
except KeyError as e:
print("{0} could not be found in the config file. Default server options will be used (i.e. gmail).".format(e))
smtp_server = 'smtp.gmail.com'
smtp_port = 587
smtp_use_tls = True
Expand All @@ -157,7 +159,7 @@ def get_log_settings(conf):
date_format = conf['settings']['date_format']
return log_file, log_level, log_format, date_format
except KeyError as e:
print("{0} could not be found in the config file. Defaults log options will be used.".format(e))
print("{0} could not be found in the config file. Default log options will be used.".format(e))

log_file = 'makeme.log'
log_level = 'debug'
Expand Down
20 changes: 14 additions & 6 deletions main.py
Expand Up @@ -9,6 +9,7 @@
import os
import signal
import sys
import traceback

from smtplib import SMTPAuthenticationError

Expand All @@ -34,6 +35,7 @@
monitor_config = False
should_fork = True
first_email_sent = False
unsent_save_location = 'unsent_emails.log'

if not conf:
print("No .makemerc file could be found. Check the documentation for details.", file=sys.stderr)
Expand All @@ -60,6 +62,9 @@
if 'monitor_config' in conf['settings']:
monitor_config = eval(conf['settings']['monitor_config'])

if 'unsent_save_location' in conf['settings']:
unsent_save_location = conf['settings']['unsent_save_location']

log_file, log_level, log_format, date_format = functions.get_log_settings(conf)
smtp_server, smtp_port, smtp_use_tls = functions.get_smtp_settings(conf)
imap_server, imap_port, imap_use_ssl = functions.get_imap_settings(conf)
Expand All @@ -83,6 +88,7 @@
server.contact_address = contact_address
server.patterns = patterns
server.reconnect_attempts = reconnect_attempts
server.unsent_save_location = unsent_save_location
server.set_imap(imap_server, imap_port, imap_use_ssl)
server.set_smtp(smtp_server, smtp_port, smtp_use_tls)
server.login_smtp()
Expand Down Expand Up @@ -112,9 +118,11 @@
monitor.stop()
shutdown(1)
# when the code is very nice and it rarely crashes, I intend on using the below code to safely trap all errors.
#except Exception as e:
# print("UNKNOWN ERROR OCCURRED: {0}".format(e))
# logging.critical("UNKNOWN ERROR OCCURRED: {0}".format(e))
# if monitor:
# monitor.stop()
# shutdown(5)
except Exception as e:
trace = traceback.format_exc()
print(trace, file=sys.stderr)
logging.critical("UNKNOWN ERROR OCCURRED: {0}".format(trace))
logging.critical('PLEASE CONTACT THE DEVELOPERS REGARDING THIS ISSUE')
if monitor:
monitor.stop()
shutdown(5)
5 changes: 4 additions & 1 deletion scripts/mpd-remote.py
Expand Up @@ -69,7 +69,10 @@ def stderr_print(output):

song = client.currentsong()

print "Now Playing: %s - %s" % (song['artist'], song['title'])
try:
print "Now Playing: %s - %s" % (song['artist'], song['title'])
except KeyError:
pass

result = re.search(r'VOLUME (\S+)', sys.argv[4])

Expand Down
15 changes: 7 additions & 8 deletions threads.py
Expand Up @@ -46,8 +46,8 @@ def run(self):
command.append(str(self.message.files))

pipe = Popen(command, stdout=PIPE, stderr=PIPE)

pipe.wait()

logging.debug("Popen for {0} complete".format(command))
# stdout is the "script"
self.script = str(pipe.stdout.read(), encoding='utf8')
Expand All @@ -67,8 +67,6 @@ def run(self):

self.lock.release()

return

def process_script(self):
"""Process the standard output for any scripting commands to be handled."""
if len(self.script) == 0:
Expand All @@ -92,7 +90,9 @@ def process_script(self):
if result:
email.receiver = result.groups()[0]

email.sender = self.sender.username
self.sender.send_email(email)

return True

def process_message(self):
Expand Down Expand Up @@ -142,13 +142,13 @@ def run(self):
raise ShutdownException(10)
time.sleep(30)
continue

self.lock.release()
finally:
self.lock.release()

if len(self.messages) == 0:
logging.info("No instructions were received!")
else:
logging.info("{0} instructions were received!".format(len(self.message)))
logging.info("{0} instructions were received!".format(len(self.messages)))

for message in self.messages:
new_thread = MessageProcessThread(message, self.patterns, self.server, self.lock)
Expand All @@ -164,7 +164,6 @@ def run(self):
if f.is_alive():
f.join()

# TODO: this should handle unsent emails much tidier. If it can't manage to log in, it should save them to a file.
if len(self.server.unsent_emails) > 0:
self.lock.acquire()
try:
Expand All @@ -174,7 +173,7 @@ def run(self):
self.server.send_email(e)

except Exception as e:
functions.save_emails_to_file(self.server.unsent_emails, 'unsent_emails.log')
functions.save_emails_to_file(self.server.unsent_emails, self.server.unsent_save_location, e)
raise ShutdownException(12)
finally:
self.lock.release()

0 comments on commit d0f1803

Please sign in to comment.