def tearDown(self): Router.clear_routes() Router.clear_states() for key in Router.HANDLERS.keys(): del sys.modules[key] Router.HANDLERS.clear() utils.settings = None
def test_forward(self): utils.import_settings(False) import salmon.handlers.forward # noqa salmon.handlers.forward.settings.relay = Mock() Router.deliver(create_message()) self.assertEqual(salmon.handlers.forward.settings.relay.deliver.call_count, 1)
def test_forward(smtp_mock): smtp_mock.return_value = Mock() import salmon.handlers.forward # noqa Router.deliver(create_message()) assert smtp_mock.return_value.sendmail.called assert smtp_mock.return_value.quit.called
def test_routes_deliver_to_not_existing_address(self): Router.load(['inboxen.router.app.server']) message = MailRequest("locahost", "test@localhost", "root1@localhost", TEST_MSG) with self.assertRaises(SMTPError) as excp: Router.deliver(message) self.assertEqual(excp.exception.code, 550) self.assertEqual(excp.exception.message, "No such address")
def test_routes(self): from salmon.routing import Router user = factories.UserFactory() inbox = factories.InboxFactory(user=user) Router.load(['app.server']) with mock.patch("router.app.server.Relay") as relay_mock, \ mock.patch("router.app.server.make_email") as mock_make_email, \ mock.patch("salmon.server.smtplib.SMTP") as smtp_mock: deliver_mock = mock.Mock() relay_mock.return_value.deliver = deliver_mock message = MailRequest("locahost", "test@localhost", str(inbox), TEST_MSG) Router.deliver(message) self.assertEqual(mock_make_email.call_count, 1) self.assertEqual(relay_mock.call_count, 0) self.assertEqual(deliver_mock.call_count, 0) mock_make_email.reset_mock() relay_mock.reset_mock() deliver_mock.reset_mock() message = MailRequest("locahost", "test@localhost", "root@localhost", TEST_MSG) Router.deliver(message) self.assertEqual(mock_make_email.call_count, 0) self.assertEqual(relay_mock.call_count, 1) self.assertEqual(deliver_mock.call_count, 1) self.assertEqual(message, deliver_mock.call_args[0][0]) mock_make_email.reset_mock() relay_mock.reset_mock() deliver_mock.reset_mock() message = MailRequest("locahost", "test@localhost", "root1@localhost", TEST_MSG) with self.assertRaises(SMTPError) as excp: Router.deliver(message) self.assertEqual(excp.exception.code, 550) self.assertEqual(excp.exception.message, "No such address") self.assertEqual(mock_make_email.call_count, 0) self.assertEqual(relay_mock.call_count, 0) self.assertEqual(deliver_mock.call_count, 0) mock_make_email.reset_mock() relay_mock.reset_mock() deliver_mock.reset_mock() smtp_mock.return_value.sendmail.side_effect = Exception() message = MailRequest("locahost", "test@localhost", "root@localhost", TEST_MSG) with self.assertRaises(SMTPError) as excp: Router.deliver(message) self.assertEqual(excp.exception.code, 450) self.assertEqual(excp.exception.message, "Error while forwarding admin message %s" % id(message)) self.assertEqual(mock_make_email.call_count, 0) self.assertEqual(relay_mock.call_count, 0) self.assertEqual(deliver_mock.call_count, 0)
def test_forward(smtp_mock): smtp_mock.return_value = Mock() utils.import_settings(False) import salmon.handlers.forward # noqa Router.deliver(create_message()) assert_equal(smtp_mock.return_value.sendmail.call_count, 1) assert_equal(smtp_mock.return_value.quit.call_count, 1)
def test_routes_deliver_to_admin_raise_smtperror_on_other_errors(self): Router.load(['inboxen.router.app.server']) with mock.patch("salmon.server.smtplib.SMTP") as smtp_mock: smtp_mock.return_value.sendmail.side_effect = Exception() message = MailRequest("locahost", "test@localhost", "root@localhost", TEST_MSG) with self.assertRaises(SMTPError) as excp: Router.deliver(message) self.assertEqual(excp.exception.code, 450) self.assertEqual(excp.exception.message, "Error while forwarding admin message %s" % id(message))
def test_routes_deliver_to_admin_raise_smtperror_on_other_errors(self): Router.load(['inboxen.router.app.server']) with mock.patch("salmon.server.smtplib.SMTP") as smtp_mock: smtp_mock.return_value.sendmail.side_effect = Exception() message = MailRequest("locahost", "test@localhost", "root@localhost", TEST_MSG) with self.assertRaises(SMTPError) as excp: Router.deliver(message) self.assertEqual(excp.exception.code, 450) self.assertEqual( excp.exception.message, "Error while forwarding admin message %s" % id(message))
def test_routes_deliver_to_admin(self): Router.load(['inboxen.router.app.server']) with mock.patch("inboxen.router.app.server.Relay") as relay_mock, \ mock.patch("inboxen.router.app.server.make_email") as mock_make_email: deliver_mock = mock.Mock() relay_mock.return_value.deliver = deliver_mock message = MailRequest("locahost", "test@localhost", "root@localhost", TEST_MSG) Router.deliver(message) self.assertEqual(mock_make_email.call_count, 0) self.assertEqual(relay_mock.call_count, 1) self.assertEqual(deliver_mock.call_count, 1) self.assertEqual(message, deliver_mock.call_args[0][0])
def test_routes_deliver_to_inbox(self): user = factories.UserFactory() inbox = factories.InboxFactory(user=user) Router.load(['inboxen.router.app.server']) with mock.patch("inboxen.router.app.server.Relay") as relay_mock, \ mock.patch("inboxen.router.app.server.make_email") as mock_make_email: deliver_mock = mock.Mock() relay_mock.return_value.deliver = deliver_mock message = MailRequest("locahost", "test@localhost", str(inbox), TEST_MSG) Router.deliver(message) self.assertEqual(mock_make_email.call_count, 1) self.assertEqual(relay_mock.call_count, 0) self.assertEqual(deliver_mock.call_count, 0)
def test_reload_raises(): Router.LOG_EXCEPTIONS = True Router.reload() assert_equal(routing.LOG.exception.call_count, 1) Router.LOG_EXCEPTIONS = False routing.LOG.exception.reset_mock() assert_raises(ImportError, Router.reload) assert_equal(routing.LOG.exception.call_count, 0) routing.LOG.exception.reset_mock() Router.LOG_EXCEPTIONS = True Router.load(['fake.handler']) assert_equal(routing.LOG.exception.call_count, 1) Router.LOG_EXCEPTIONS = False routing.LOG.exception.reset_mock() assert_raises(ImportError, Router.load, ['fake.handler']) assert_equal(routing.LOG.exception.call_count, 0)
def test_reload_raises(): Router.LOG_EXCEPTIONS = True Router.reload() assert routing.LOG.exception.called Router.LOG_EXCEPTIONS = False routing.LOG.exception.reset_mock() assert_raises(ImportError, Router.reload) assert not routing.LOG.exception.called routing.LOG.exception.reset_mock() Router.LOG_EXCEPTIONS = True Router.load(['fake.handler']) assert routing.LOG.exception.called Router.LOG_EXCEPTIONS = False routing.LOG.exception.reset_mock() assert_raises(ImportError, Router.load, ['fake.handler']) assert not routing.LOG.exception.called
def test_soft_bounce_tells_them(): setup() # get them into a posting state admin_tests.test_existing_user_posts_message() assert_in_state('app.handlers.admin', list_addr, sender, 'POSTING') clear_queue() assert mailinglist.find_subscriptions(sender, list_addr) # force them to soft bounce msg = create_bounce(list_addr, sender) msg.bounce.primary_status = (3, bounce.PRIMARY_STATUS_CODES[u'3']) assert msg.bounce.is_soft() Router.deliver(msg) assert_in_state('app.handlers.admin', list_addr, sender, 'BOUNCING') assert_in_state('app.handlers.bounce', list_addr, sender, 'BOUNCING') assert delivered('unbounce'), "Looks like unbounce didn't go out." assert_equal(len(queue(queue_dir=settings.BOUNCE_ARCHIVE).keys()), 1) assert not mailinglist.find_subscriptions(sender, list_addr) # make sure that any attempts to post return a "you're bouncing dude" message unbounce = client.say(list_addr, 'So anyway as I was saying.', 'unbounce') assert_in_state('app.handlers.admin', list_addr, sender, 'BOUNCING') # now have them try to unbounce msg = client.say(unbounce['from'], "Please put me back on, I'll be good.", 'unbounce-confirm') # handle the bounce confirmation client.say(msg['from'], "Confirmed to unbounce.", 'noreply') # alright they should be in the unbounce state for the global bounce handler assert_in_state('app.handlers.bounce', list_addr, sender, 'UNBOUNCED') # and they need to be back to POSTING for regular operations assert_in_state('app.handlers.admin', list_addr, sender, 'POSTING') assert mailinglist.find_subscriptions(sender, list_addr) # and make sure that only the original bounce is in the bounce archive assert_equal(len(queue(queue_dir=settings.BOUNCE_ARCHIVE).keys()), 1)
def test_Router_undeliverable_queue(): Router.clear_routes() Router.clear_states() Router.UNDELIVERABLE_QUEUE = Mock() msg = MailRequest('fakepeer', 'from@localhost', 'to@localhost', "Nothing") Router.deliver(msg) assert Router.UNDELIVERABLE_QUEUE.push.called
def test_Router_undeliverable_queue(self): Router.clear_routes() Router.clear_states() Router.UNDELIVERABLE_QUEUE = Mock() msg = MailRequest('fakepeer', 'from@localhost', 'to@localhost', "Nothing") Router.deliver(msg) self.assertEqual(Router.UNDELIVERABLE_QUEUE.push.call_count, 1)
def test_reload_raises(self): Router.LOG_EXCEPTIONS = True Router.reload() self.assertEqual(routing.LOG.exception.call_count, 1) Router.LOG_EXCEPTIONS = False routing.LOG.exception.reset_mock() with self.assertRaises(ImportError): Router.reload() self.assertEqual(routing.LOG.exception.call_count, 0) routing.LOG.exception.reset_mock() Router.LOG_EXCEPTIONS = True Router.load(['fake.handler']) self.assertEqual(routing.LOG.exception.call_count, 1) Router.LOG_EXCEPTIONS = False routing.LOG.exception.reset_mock() with self.assertRaises(ImportError): Router.load(['fake.handler']) self.assertEqual(routing.LOG.exception.call_count, 0)
def test_routes(self): from salmon.routing import Router user = factories.UserFactory() inbox = factories.InboxFactory(user=user) Router.load(['app.server']) with mock.patch("router.app.server.Relay") as relay_mock, \ mock.patch("router.app.server.make_email") as mock_make_email: deliver_mock = mock.Mock() relay_mock.return_value.deliver = deliver_mock message = MailRequest("locahost", "test@localhost", str(inbox), TEST_MSG) Router.deliver(message) self.assertEqual(mock_make_email.call_count, 1) self.assertEqual(relay_mock.call_count, 0) self.assertEqual(deliver_mock.call_count, 0) mock_make_email.reset_mock() relay_mock.reset_mock(); deliver_mock.reset_mock(); message = MailRequest("locahost", "test@localhost", "root@localhost", TEST_MSG) Router.deliver(message) self.assertEqual(mock_make_email.call_count, 0) self.assertEqual(relay_mock.call_count, 1) self.assertEqual(deliver_mock.call_count, 1) self.assertEqual(message, deliver_mock.call_args[0][0]) mock_make_email.reset_mock() relay_mock.reset_mock(); deliver_mock.reset_mock(); message = MailRequest("locahost", "test@localhost", "root1@localhost", TEST_MSG) with self.assertRaises(SMTPError): Router.deliver(message) self.assertEqual(mock_make_email.call_count, 0) self.assertEqual(relay_mock.call_count, 0) self.assertEqual(deliver_mock.call_count, 0)
def test_queue_handler(): import salmon.handlers.queue # noqa Router.deliver(create_message())
def test_log_handler(): import salmon.handlers.log # noqa Router.deliver(create_message())
def cleanup_router(): Router.clear_routes() Router.clear_states() Router.HANDLERS.clear() utils.settings = None
def test_bounce_to_decorator(): import bounce_filtered_mod msg = mail.MailRequest(None,None,None, open("tests/bounce.msg").read()) Router.deliver(msg) assert Router.in_state(bounce_filtered_mod.START, msg) assert bounce_filtered_mod.HARD_RAN, "Hard bounce state didn't actually run: %r" % msg.route_to msg.bounce.primary_status = (4, u'Persistent Transient Failure') Router.clear_states() Router.deliver(msg) assert Router.in_state(bounce_filtered_mod.START, msg) assert bounce_filtered_mod.SOFT_RAN, "Soft bounce didn't actually run." msg = mail.MailRequest(None, None, None, open("tests/signed.msg").read()) Router.clear_states() Router.deliver(msg) assert Router.in_state(bounce_filtered_mod.END, msg), "Regular messages aren't delivering."
def test_spam_sent_by_confirmed_user(): test_confirmed_user_comments() clear_queue("run/posts") Router.deliver(make_spam())
def setUp(self): super(BounceTestCase, self).setUp() Router.load(["tests.handlers.bounce_filtered_mod"]) Router.reload()
def setup_router(handlers): Router.clear_routes() Router.clear_states() Router.HANDLERS.clear() Router.load(handlers) Router.reload()
def setup(): Router.clear_routes() Router.clear_states() Router.load(['salmon_tests.simple_fsm_mod'])
import os from django.conf import settings as dj_settings from salmon import queue from salmon.routing import Router from config import settings __all__ = ["settings"] try: os.mkdir("logs", 0700) except OSError: pass try: os.mkdir("run", 0710) # group can access files in "run" except OSError: pass logconfig_path = os.path.join(dj_settings.BASE_DIR, "router", "config", "logging.conf") if not os.path.exists(logconfig_path): logconfig_path = os.path.join(dj_settings.BASE_DIR, "router", "config", "logging.conf.default") logging.config.fileConfig(logconfig_path) Router.load(['app.server']) Router.RELOAD = False Router.LOG_EXCEPTIONS = True Router.UNDELIVERABLE_QUEUE = queue.Queue("run/undeliverable")
from config import settings from salmon.routing import Router from salmon.server import Relay, QueueReceiver from salmon import view import logging import logging.config import jinja2 # configure logging to go to a log file logging.config.fileConfig("config/logging.conf") # the relay host to actually send the final message to settings.relay = Relay(host=settings.relay_config['host'], port=settings.relay_config['port'], debug=1) # where to listen for incoming messages settings.receiver = QueueReceiver('run/undeliverable', settings.queue_config['sleep']) Router.defaults(**settings.router_defaults) Router.load(['salmon.handlers.forward']) Router.RELOAD = True Router.UNDELIVERABLE_QUEUE = None view.LOADER = jinja2.Environment(loader=jinja2.PackageLoader( settings.template_config['dir'], settings.template_config['module']))
def setup_router(handlers): Router.clear_routes() Router.clear_states() Router.HANDLERS.clear() Router.load(handlers)
def test_spam_sent_by_unconfirmed_user(): setup() client.begin() Router.deliver(make_spam())
def tearDown(self): super(BounceTestCase, self).tearDown() Router.HANDLERS.clear() Router.reload()
logging.config.fileConfig("config/logging.conf") settings.receiver = QueueReceiver(settings.SENDER_QUEUE_PATH, settings.sender_queue_sleep) # the relay host to actually send the final message to settings.relay = Relay(host=settings.relay_config['host'], port=settings.relay_config['port'], debug=1) # when silent, it won't reply to emails it doesn't know settings.silent = settings.is_silent_config # owner email to send all unknown emails settings.owner_email = settings.owner_email_config # server for email settings.server_name = settings.server_name_config # server for website settings.web_server_name = settings.server_name_config # start backend table.r = table.start_table() Router.defaults(**settings.router_defaults) Router.load(settings.sender_handlers) Router.RELOAD=True Router.SEND_QUEUE=queue.Queue(settings.SENDER_QUEUE_PATH) # mails to send Router.UNDELIVERABLE_QUEUE=queue.Queue("run/error_send") Router.STATE_STORE=state_storage.UserStateStorage()
from __future__ import print_function from salmon.routing import Router, nolocking, route, route_like, state_key_generator, stateless @state_key_generator def simple_key_gen(module_name, message): return module_name # common routing capture regexes go in here, you can override them in @route Router.defaults(host="localhost", action="[a-zA-Z0-9]+", list_name="[a-zA-Z.0-9]+") @route("(list_name)-(action)@(host)") def START(message, list_name=None, action=None, host=None): print("START", message, list_name, action, host) if action == 'explode': print("EXPLODE!") raise RuntimeError("Exploded on purpose.") return CONFIRM @route("(list_name)-confirm-(id_number)@(host)", id_number="[0-9]+") def CONFIRM(message, list_name=None, id_number=None, host=None): print("CONFIRM", message, list_name, id_number, host) return POSTING
def cleanup_router(): Router.clear_routes() Router.clear_states() Router.HANDLERS.clear()
def test_RoutingBase(self): # check that Router is in a pristine state self.assertEqual(len(Router.ORDER), 0) self.assertEqual(len(Router.REGISTERED), 0) setup_router(['tests.handlers.simple_fsm_mod']) self.assertEqual(len(Router.ORDER), 5) self.assertEqual(len(Router.REGISTERED), 5) message = MailRequest('fakepeer', 'zedshaw@localhost', 'users-subscribe@localhost', "") Router.deliver(message) assert Router.in_state(simple_fsm_mod.CONFIRM, message) confirm = MailRequest('fakepeer', '"Zed Shaw" <zedshaw@localhost>', 'users-confirm-1@localhost', "") Router.deliver(confirm) assert Router.in_state(simple_fsm_mod.POSTING, message) Router.deliver(message) assert Router.in_state(simple_fsm_mod.NEXT, message) Router.deliver(message) assert Router.in_state(simple_fsm_mod.END, message) Router.deliver(message) assert Router.in_state(simple_fsm_mod.START, message) Router.clear_states() Router.LOG_EXCEPTIONS = True explosion = MailRequest('fakepeer', '<hacker@localhost>', 'start-explode@localhost', "") Router.deliver(explosion) assert Router.in_error(simple_fsm_mod.END, explosion) Router.clear_states() Router.LOG_EXCEPTIONS = False explosion = MailRequest('fakepeer', 'hacker@localhost', 'start-explode@localhost', "") with self.assertRaises(RuntimeError): Router.deliver(explosion) Router.reload() assert 'tests.handlers.simple_fsm_mod' in Router.HANDLERS self.assertEqual(len(Router.ORDER), 5) self.assertEqual(len(Router.REGISTERED), 5)
def test_log_handler(): Router.deliver(message_tests.test_mail_request())
from config import settings from salmon.routing import Router from salmon.server import Relay, QueueReceiver from salmon import view import logging import logging.config import jinja2 # configure logging to go to a log file logging.config.fileConfig("config/logging.conf") # the relay host to actually send the final message to settings.relay = Relay(host=settings.relay_config['host'], port=settings.relay_config['port'], debug=1) # where to listen for incoming messages settings.receiver = QueueReceiver('run/undeliverable', settings.queue_config['sleep']) Router.defaults(**settings.router_defaults) Router.load(['salmon.handlers.forward']) Router.RELOAD=True Router.UNDELIVERABLE_QUEUE=None view.LOADER = jinja2.Environment( loader=jinja2.PackageLoader(settings.template_config['dir'], settings.template_config['module']))
import logging import logging.config from salmon import queue from salmon.routing import Router from salmon.server import SMTPReceiver from . import settings logging.config.fileConfig("tests/config/logging.conf") settings.receiver = SMTPReceiver(**settings.receiver_config) Router.defaults(**settings.router_defaults) Router.load(settings.dump_handlers) Router.RELOAD = True Router.UNDELIVERABLE_QUEUE = queue.Queue(settings.UNDELIVERABLE_QUEUE)
from salmon import queue from salmon.routing import Router import logging import logging.config import os logging.config.fileConfig("config/logging.conf") Router.defaults(**{}) Router.load(['app.server']) Router.RELOAD=False Router.LOG_EXCEPTIONS=True Router.UNDELIVERABLE_QUEUE=queue.Queue("run/undeliverable")
def test_queue_handler(): import salmon.handlers.queue # noqa Router.deliver(message_tests.test_mail_request())
import jinja2 import logging import logging.config import os # configure logging to go to a log file logging.config.fileConfig("config/test_logging.conf") # the relay host to actually send the final message to (set debug=1 to see what # the relay is saying to the log server). settings.relay = Relay(host=settings.relay_config['host'], port=settings.relay_config['port'], debug=0) settings.receiver = None Router.defaults(**settings.router_defaults) Router.load(settings.handlers + settings.queue_handlers) Router.RELOAD=True view.LOADER = jinja2.Environment( loader=jinja2.PackageLoader(settings.template_config['dir'], settings.template_config['module'])) # if you have pyenchant and enchant installed then the template tests will do # spell checking for you, but you need to tell pyenchant where to find itself if 'PYENCHANT_LIBRARY_PATH' not in os.environ: os.environ['PYENCHANT_LIBRARY_PATH'] = '/opt/local/lib/libenchant.dylib'
def test_queue_handler(): Router.deliver(message_tests.test_mail_request())
def test_RoutingBase(): assert len(Router.ORDER) == 0 assert len(Router.REGISTERED) == 0 setup_router(['salmon_tests.handlers.simple_fsm_mod']) from handlers import simple_fsm_mod assert len(Router.ORDER) > 0 assert len(Router.REGISTERED) > 0 message = MailRequest('fakepeer', 'zedshaw@localhost', 'users-subscribe@localhost', "") Router.deliver(message) assert Router.in_state(simple_fsm_mod.CONFIRM, message) confirm = MailRequest('fakepeer', '"Zed Shaw" <zedshaw@localhost>', 'users-confirm-1@localhost', "") Router.deliver(confirm) assert Router.in_state(simple_fsm_mod.POSTING, message) Router.deliver(message) assert Router.in_state(simple_fsm_mod.NEXT, message) Router.deliver(message) assert Router.in_state(simple_fsm_mod.END, message) Router.deliver(message) assert Router.in_state(simple_fsm_mod.START, message) Router.clear_states() Router.LOG_EXCEPTIONS = True explosion = MailRequest('fakepeer', '<hacker@localhost>', 'start-explode@localhost', "") Router.deliver(explosion) assert Router.in_error(simple_fsm_mod.END, explosion) Router.clear_states() Router.LOG_EXCEPTIONS = False explosion = MailRequest('fakepeer', 'hacker@localhost', 'start-explode@localhost', "") assert_raises(RuntimeError, Router.deliver, explosion) Router.reload() assert 'salmon_tests.handlers.simple_fsm_mod' in Router.HANDLERS assert len(Router.ORDER) assert len(Router.REGISTERED)
def test_bounce_to_decorator(): msg = mail.MailRequest(None, Data=open("tests/bounce.msg").read()) Router.deliver(msg) assert Router.in_state(bounce_filtered_mod.START, msg) assert bounce_filtered_mod.HARD_RAN, "Hard bounce state didn't actually run: %r" % msg.route_to msg.bounce.primary_status = (4, u'Persistent Transient Failure') Router.clear_states() Router.deliver(msg) assert Router.in_state(bounce_filtered_mod.START, msg) assert bounce_filtered_mod.SOFT_RAN, "Soft bounce didn't actually run." msg = mail.MailRequest(None, Data=open("tests/signed.msg").read()) Router.clear_states() Router.deliver(msg) assert Router.in_state(bounce_filtered_mod.END, msg), "Regular messages aren't delivering."
## import logging import logging.config import os from django.conf import settings as dj_settings from salmon import queue from salmon.routing import Router from inboxen.router.config import settings __all__ = ["settings"] try: os.mkdir("logs", 0o700) except OSError: pass try: os.mkdir("run", 0o710) # group can access files in "run" except OSError: pass logging.config.dictConfig(dj_settings.SALMON_LOGGING) Router.load(['inboxen.router.app.server']) Router.RELOAD = False Router.LOG_EXCEPTIONS = True Router.UNDELIVERABLE_QUEUE = queue.Queue("run/undeliverable")