Revert "Email Send Cron Worker"
This reverts commit 264d6f82883ef51f94186fde7044a1ec24ed2699. Change-Id: I2bd4a7ef0b6d18e600c9270fcd4a2b5291163f84
This commit is contained in:
parent
b0e82d23cd
commit
260a68fd9a
@ -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))
|
Loading…
x
Reference in New Issue
Block a user