Revert "Email Send Cron Worker"

This reverts commit 264d6f82883ef51f94186fde7044a1ec24ed2699.

Change-Id: I2bd4a7ef0b6d18e600c9270fcd4a2b5291163f84
This commit is contained in:
Michael Krotscheck 2015-05-11 09:16:16 -07:00
parent b0e82d23cd
commit 260a68fd9a
3 changed files with 0 additions and 222 deletions
setup.cfg
storyboard
plugin/email
tests/plugin/email

@ -40,7 +40,6 @@ storyboard.plugin.user_preferences =
email = storyboard.plugin.email.preferences:EmailPreferences
storyboard.plugin.scheduler =
token-cleaner = storyboard.plugin.token_cleaner.cleaner:TokenCleaner
email-sender = storyboard.plugin.email.workers:EmailSender
[build_sphinx]
source-dir = doc/source

@ -1,78 +0,0 @@
# Copyright (c) 2015 Hewlett-Packard Development Company, L.P.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied. See the License for the specific language governing permissions and
# limitations under the License.
import pytz
import smtplib
from apscheduler.triggers.interval import IntervalTrigger
from oslo_log import log
from storyboard.plugin.email.base import EmailPluginBase
from storyboard.plugin.email.outbox import get_outbox
from storyboard.plugin.email.smtp_client import get_smtp_client
from storyboard.plugin.scheduler.base import SchedulerPluginBase
LOG = log.getLogger(__name__)
class EmailSender(SchedulerPluginBase, EmailPluginBase):
"""A Cron Plugin which goes through all email messages that have been
written to the outbox in its provided time interval, and sends them using
the email sender.
"""
def trigger(self):
"""This plugin executes every minute. APScheduler will collate the
executions of this plugin, so there will be no overlap between
executions.
"""
return IntervalTrigger(minutes=1, timezone=pytz.utc)
def run(self):
"""Send all the messages between the given timestamps. If a message
cannot be sent, or if the sender is not retrievable,
then discard all messages - we don't want to build up a massive
backlog and then spam people.
"""
# Try to send email.
try:
with get_outbox() as outbox:
with get_smtp_client() as smtp_client:
for key, message in outbox.iteritems():
from_addr = message.get('From')
to_addrs = message.get('To')
try:
smtp_client.sendmail(from_addr=from_addr,
to_addrs=to_addrs,
msg=message.as_string())
except smtplib.SMTPException as e:
LOG.error(
'Cannot send email, discarding: %s' % (e,))
finally:
outbox.discard(key)
except Exception as e:
LOG.error("Error while trying to send email.")
LOG.error(e)
# After everything's said and done, clear out anything that hasn't
# been handled.
try:
with get_outbox() as outbox:
for key, message in outbox.iteritems():
outbox.discard(key)
except Exception as e:
LOG.error("Unable to flush remaining emails.", e)

@ -1,143 +0,0 @@
# Copyright (c) 2015 Hewlett-Packard Development Company, L.P.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied. See the License for the specific language governing permissions and
# limitations under the License.
import email
from mock import patch
from random import random
import smtplib
from oslo_config import cfg
from storyboard.plugin.email.factory import EmailFactory
from storyboard.plugin.email.outbox import Outbox
from storyboard.plugin.email.workers import EmailSender
from storyboard.tests import base
CONF = cfg.CONF
class TestEmailSender(base.WorkingDirTestCase):
"""Test the email sender plugin. Makes use of the dummy smtp sender."""
def setUp(self):
"""Add messages to the outbox. Note that the outbox directory will be
deleted when the working directory is cleared in the parent test class.
"""
super(TestEmailSender, self).setUp()
# Build a test outbox.
outbox = Outbox()
self.assertIsNotNone(outbox)
factory = EmailFactory('test@example.org',
'test_subject',
'test.txt',
'plugin.email')
# Generate 25 emails that are now-ish
for i in range(0, 25):
recipient = 'test_%s@example.com' % (i,)
message = factory.build(recipient, test_parameter=i)
outbox.add(message)
# Generate 25 emails that are in the 0-60 timeframe.
for i in range(0, 25):
recipient = 'test_%s@example.com' % (i,)
message = factory.build(recipient, test_parameter=i)
# Override the date header with our actual date + some random
# seconds, so that all timestamps fall between 1 and 59
message.replace_header('Date',
email.utils.formatdate(1 + (random() * 58)))
outbox.add(message)
outbox.flush()
def test_trigger(self):
"""Assert that the this plugin runs every minute."""
plugin = EmailSender(CONF)
trigger = plugin.trigger()
self.assertEqual(60, trigger.interval_length)
@patch('storyboard.plugin.email.workers.get_smtp_client')
def test_failing_sender_causes_flush(self, get_smtp_client):
"""Assert that running against a failing sender causes no errors,
and discards all messages, so we don't build up a massive send queue.
"""
# Raise an exception when this is called.
get_smtp_client.side_effect = smtplib.SMTPException
# Run the plugin.
plugin = EmailSender(CONF)
plugin.run()
# Read the outbox, making sure there's no messages left.
outbox = Outbox()
self.assertEqual(0, len(outbox))
@patch('mock_smtp.DummySMTP.sendmail')
def test_successful_run(self, mock_sendmail):
"""Assert that running with a valid sender and outbox sends all the
messages in the provided time frame, and leaves other messages alone.
"""
# Run the plugin.
plugin = EmailSender(CONF)
plugin.run()
# The outbox should be clean.
outbox = Outbox()
self.assertEqual(0, len(outbox))
# The dummy SMTP library should have received 50 messages.
self.assertEqual(50, mock_sendmail.call_count)
@patch('mock_smtp.DummySMTP.sendmail')
def test_badly_formatted_email_causes_flush(self, mock_sendmail):
"""Assert that a message that would otherwise cause a send exceptoin
creates no side_effect, and flushes the message from the queue.
"""
# Create a sideffect
mock_sendmail.side_effect = smtplib.SMTPException
# Run the plugin.
plugin = EmailSender(CONF)
plugin.run()
# Read the outbox, making sure that all messages have been flushed.
outbox = Outbox()
self.assertEqual(0, len(outbox))
# Assert that the sendmail message was called 50 times.
self.assertEqual(50, mock_sendmail.call_count)
@patch('storyboard.plugin.email.workers.get_outbox')
def test_failing_outbox_causes_no_side_effects(self, mock_get_outbox):
"""Assert that running with a valid sender but invalid outbox does
nothing, since we can't get at any messages.
"""
# Raise an exception when this is called.
mock_get_outbox.side_effect = OSError
# Run the plugin.
plugin = EmailSender(CONF)
plugin.run()
# Read the outbox, making sure we still have 50 messages (since the
# outbox was never accessible via the context handler.
outbox = Outbox()
self.assertEqual(50, len(outbox))