def setUp(self): options = { "test": True, "host": "localhost", "port": 25, "sender": "*****@*****.**" } self.emailer = Emailer(options)
class EmailerTests(unittest.TestCase): def setUp(self): options = { "test": True, "host": "localhost", "port": 25, "sender": "*****@*****.**" } self.emailer = Emailer(options) def test_recipient_format(self): # Test that we require at least one of "to", "cc" or "bcc" to send an email. recipients = {"fail": "*****@*****.**"} self.assertRaises(NotifyError, self.emailer.format, recipients, u"This is the subject!", u"This is the body!") def test_recipient_dict_format(self): # Test that recipients must be a dict. recipients = "fail" self.assertRaises(NotifyError, self.emailer.format, recipients, u"This is the subject!", u"This is the body!") def test_basic_format(self): # Test the basic case of formatting the email correctly. recipients = {"to": "*****@*****.**"} recipient_addrs, message = self.emailer.format(recipients, u"This is the subject!", u"This is the body!") self.assertEqual(recipient_addrs, ['*****@*****.**']) expected_msg = u"From: [email protected]\r\nTo: [email protected]\r\nSubject: This is the subject!\r\n\r\nThis is the body!" self.assertEqual(message, expected_msg) def test_advanced_format(self): # Make sure we can handle all of the input formats we accept. recipients = { "to": "*****@*****.**", "cc": ["*****@*****.**", "*****@*****.**"], "bcc": "[email protected], [email protected],[email protected]" } recipient_addrs, message = self.emailer.format(recipients, u"This is the subject!", u"This is the body!") expected_recipient_addrs = ['*****@*****.**', '*****@*****.**', '*****@*****.**', '*****@*****.**', '*****@*****.**', '*****@*****.**'] self.assertEqual(recipient_addrs, expected_recipient_addrs) expected_msg = u"From: [email protected]\r\nCc: [email protected], [email protected]\r\nTo: [email protected]\r\nSubject: This is the subject!\r\n\r\nThis is the body!" self.assertEqual(message, expected_msg)
def main(): # Deal with the command line arguments current_dir = os.path.dirname(os.path.realpath(__file__)) settings_path = sys.argv[1] if len(sys.argv) >= 2 else '{0}/settings.json'.format(current_dir) log_path = sys.argv[2] if len(sys.argv) >= 3 else '{0}/flmx-validator.log'.format(current_dir) # First off set up the logging. logger = logging.getLogger('flmx-logger') logger.setLevel(logging.DEBUG) handler = logging.handlers.RotatingFileHandler(log_path, maxBytes=104857600, backupCount=3) formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s') handler.setFormatter(formatter) logger.addHandler(handler) try: # Load json settings, either from command line argument or default location. settings = JsonSettings(settings_path) logger.info("Settings loaded from {0}".format(settings_path)) # Setup validator, emailer and feeds. validator = Validator(**settings.json_data['validator']) logger.info("Validator at endpoint {0} initialised".format(validator.endpoint)) feeds = [] for feed in settings.json_data['feeds']: f = Feed(**feed) feeds.append(f) logger.info("Feed at endpoint {0} initialised".format(f.endpoint)) emailer = Emailer(settings.json_data['email']) # Start validation loop. while (True): for feed in feeds: # If feed is not currently being validated, and it was last validated longer than [next_try] ago, start validation. if feed.validation_start_time is None and (feed.last_validated is None or datetime.now() > feed.last_validated + feed.next_try): logger.info("Sending validation request for {0} [{1}] to {2}".format(feed.name, feed.endpoint, validator.endpoint)) validator.start(feed) # Else if the validation must have started elif feed.validation_start_time is not None: logger.info("Polling validation results for {0} [{1}] from {2}".format(feed.name, feed.endpoint, validator.endpoint)) completed, success, total_issues, response_json = validator.poll_results(feed) # If the process has completed and the result was a failure, send an email notification. if completed: if not success: logger.info("Validation for {0} [{1}] resulted in errors, sending email to {2}".format(feed.name, feed.endpoint, feed.failure_email)) title = u'Validation failed for {feed} [{endpoint}] ({total_issues} {issues})'.format( feed = feed.name, endpoint = feed.endpoint, total_issues = total_issues, issues = "Issues" if total_issues > 1 else "Issue") body = json.dumps(response_json, indent=4, separators=(',', ': '), sort_keys=True) emailer.send(feed.failure_email, title, body) logger.info("Email sent to {0}".format(feed.failure_email)) else: logger.info("Validation completed successfully for {0} [{1}]".format(feed.name, feed.endpoint)) # Check to make sure we haven't hit some weird behaviour and have been stuck polling for > 6 hours. elif feed.last_validated is not None and datetime.now() > feed.last_validated + timedelta(hours=6): # If we have then let's just kick off another validation request. feed.validation_start_time = None logger.debug("Have been polling {0} for > 6 hours, must be a problem lets rinse and repeat.".format(feed.name)) break time.sleep(300) # Wait for a bit to try again, hopefully this should account for most differences in time between the executing and validation server too. except Exception as e: logger.debug("Unhandled exception occured: {0}".format(e)) logger.debug(traceback.format_exc()) logger.debug("Closing application.") sys.exit()