Skip to content

Commit

Permalink
Added email mixin
Browse files Browse the repository at this point in the history
  • Loading branch information
colin committed Jul 24, 2016
1 parent f327c01 commit ef94bdf
Show file tree
Hide file tree
Showing 11 changed files with 97 additions and 10 deletions.
2 changes: 1 addition & 1 deletion pete/broadcaster/__init__.py
@@ -1 +1 @@
from .broadcaster import Broadcaster, SQLiteBroadcaster, BasicSQLiteBroadcaster # noqa
from .broadcaster import Broadcaster, SQLiteBroadcaster, BasicSQLiteBroadcaster, EmailBroadcaster # noqa
13 changes: 13 additions & 0 deletions pete/broadcaster/broadcaster.py
@@ -1,9 +1,11 @@
from abc import ABCMeta, abstractmethod, abstractproperty
import json
import os
import sqlite3
import time

from .. import db
from .. import petemail


class Broadcaster(object, metaclass=ABCMeta):
Expand Down Expand Up @@ -74,3 +76,14 @@ def send(self, messages):
))
with self.get_connection() as connection:
self.insert_rows(connection, db_messages)


class EmailBroadcaster(petemail.EmailMixin, Broadcaster):
def send(self, messages):
for message in messages:
try:
message_dict = json.loads(message)
except ValueError:
continue
else:
self.send_message(message_dict)
2 changes: 1 addition & 1 deletion pete/examples/time_checker.py
Expand Up @@ -8,4 +8,4 @@ def should_run(self):
return True

def run(self):
return "It is now {}".format(datetime.now().strftime("%H:%M:%S"))
return ["It is now {}".format(datetime.now().strftime("%H:%M:%S"))]
1 change: 1 addition & 0 deletions pete/petemail/__init__.py
@@ -0,0 +1 @@
from .petemail import EmailMixin # noqa
76 changes: 76 additions & 0 deletions pete/petemail/petemail.py
@@ -0,0 +1,76 @@
from abc import abstractproperty
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
import json
import smtplib


def sample_config():

return json.dumps()


class EmailMixin(object):
"""
Helps sending emails. Requires a config file json file that looks something like this:
{
"username": "myuser@gmail.com",
"from": "myuser@gmail.com",
"password": "mypassword",
"smtp": "smtp.gmail.com:587",
"to": [
"myuser@gmail.com",
"youruser@gmail.com"
]
}
"""
required_keys = ('from', 'to', 'smtp', 'username', 'password')

@abstractproperty
def email_config_filename(self):
return None

@abstractproperty
def subject_formatter(self):
return None

@abstractproperty
def message_formatter(self):
return None

def _get_config(self):
with open(self.email_config_filename, 'r') as buff:
config = json.load(buff)
for required_key in EmailMixin.required_keys:
if required_key not in config:
raise KeyError('Config must include {}'.format(required_key))

def send_message(self, message_dict):
"""Email a message given a dictionary.
Formatting is set using EmailMixin.subject_formatter and
EmailMixin.message_formatter, and configuration is loaded from
EmailMixin.email_config_filename.
Args:
message_json: A json string defining a message.
"""
config = self._get_config()
from_email = config['from']
to_emails = config['to']

message = json.loads(message_json)

msg = MIMEMultipart('alternative')
msg['Subject'] = self.subject_formatter.format(**message)
msg['From'] = from_email
msg['To'] = ",".join(to_emails)

msg.attach(MIMEText(self.message_formatter.format(**message), 'plain'))

server = smtplib.SMTP(config['smtp'])
server.ehlo()
server.starttls()
server.login(config['username'], config['password'])
server.sendmail(from_email, to_emails, msg.as_string())
server.quit()
4 changes: 1 addition & 3 deletions pete/runner/runner.py
Expand Up @@ -16,9 +16,7 @@ def run(self):
messages = []
for task in self.tasks:
if task.should_run():
task_message = task.run()
if task_message:
messages.append(task_message)
messages += task.run()
return messages

def broadcast(self, messages):
Expand Down
2 changes: 1 addition & 1 deletion pete/task/task.py
Expand Up @@ -14,7 +14,7 @@ def should_run(self):

@abstractmethod
def run(self):
"""Run the task and return a string."""
"""Run the task and return a list of strings."""
pass


Expand Down
2 changes: 1 addition & 1 deletion setup.py
Expand Up @@ -11,7 +11,7 @@

setup(
name='pete',
version='0.0.1',
version='0.1.0',
description='A simple taskrunner',
long_description=long_description,
author='Colin Carroll',
Expand Down
1 change: 0 additions & 1 deletion test/test_examples.py
Expand Up @@ -13,7 +13,6 @@ def __call__(self, *args, **kwargs):


class TestExamples(unittest.TestCase):

def test_example_runner(self):
runner = time_to_string_runner()
# Capture print, make sure
Expand Down
2 changes: 1 addition & 1 deletion test/test_utils.py
Expand Up @@ -20,4 +20,4 @@ def should_run(self):

def run(self):
self.run_count += 1
return "{0.name} {0.run_count}".format(self)
return ["{0.name} {0.run_count}".format(self)]
2 changes: 1 addition & 1 deletion tox.ini
Expand Up @@ -5,4 +5,4 @@ envlist = py33, py34, py35
deps=
pytest
pytest-cov
commands=py.test --cov {envsitepackagesdir}/pete
commands=py.test --cov {envsitepackagesdir}/pete --cov-report=html --cov-report=term

0 comments on commit ef94bdf

Please sign in to comment.