def test_mailer_class_from_settings_factory(self): from pyramid_mailer.mailer import (Mailer, DummyMailer, SMTP_SSLMailer, SMTPMailer, LoggingMailer) from pyramid_mailer import mailer_factory_from_settings settings = {'mymail.mailer': 'pyramid_mailer.mailer.Mailer'} mailer = mailer_factory_from_settings(settings, prefix='mymail.') self.assertIsInstance(mailer, Mailer) settings = {'mymail.mailer': 'pyramid_mailer.mailer.DummyMailer'} mailer = mailer_factory_from_settings(settings, prefix='mymail.') self.assertIsInstance(mailer, DummyMailer) settings = {'mymail.mailer': 'pyramid_mailer.mailer.SMTP_SSLMailer'} mailer = mailer_factory_from_settings(settings, prefix='mymail.') self.assertIsInstance(mailer, SMTP_SSLMailer) settings = {'mymail.mailer': 'pyramid_mailer.mailer.SMTPMailer'} mailer = mailer_factory_from_settings(settings, prefix='mymail.') self.assertIsInstance(mailer, SMTPMailer) settings = {'mymail.mailer': 'pyramid_mailer.mailer.LoggingMailer'} mailer = mailer_factory_from_settings(settings, prefix='mymail.') self.assertIsInstance(mailer, LoggingMailer) settings = {'mymail.mailer': 'pyramid_mailer.mailer.InvalidMailer'} self.assertRaises(NameError, mailer_factory_from_settings, settings, prefix='mymail.') settings = {'mymail.mailer': 'invalid.module'} self.assertRaises(ImportError, mailer_factory_from_settings, settings, prefix='mymail.')
def configure_mailer(self): """Configure outgoing email backend and email test views.""" from pyramid_mailer import IMailer settings = self.settings.copy() # Empty values are not handled gracefully, so mutate them here before passing forward to mailer if settings.get("mail.username", "x") == "": settings["mail.username"] = None if settings.get("mail.password", "x") == "": settings["mail.password"] = None mailer_class = settings.get("websauna.mailer", "") if mailer_class in ("mail", ""): # TODO: Make mailer_class explicit so we can dynamically load pyramid_mail.Mailer # Default from pyramid_mailer import mailer_factory_from_settings mailer = mailer_factory_from_settings(settings) self.config.registry.registerUtility(mailer, IMailer) else: # debug backend resolver = DottedNameResolver() mailer_cls = resolver.resolve(mailer_class) mailer = mailer_cls() self.config.registry.registerUtility(mailer, IMailer) if settings.get("websauna.sample_html_email", False): from websauna.system.mail import views self.config.scan(views) self.config.add_jinja2_search_path('websauna.system:mail/templates', name='.html')
def create_mailer(registry: Registry) -> IMailer: """Create a new mailer instance. """ settings = registry.settings # Empty values are not handled gracefully, so mutate them here before passing forward to mailer if settings.get("mail.username", "x") == "": settings["mail.username"] = None if settings.get("mail.password", "x") == "": settings["mail.password"] = None mailer_class = settings.get("websauna.mailer", "") if mailer_class in ("mail", ""): # TODO: Make mailer_class explicit so we can dynamically load pyramid_mail.Mailer # Default from pyramid_mailer import mailer_factory_from_settings mailer = mailer_factory_from_settings(settings) else: # debug backend resolver = DottedNameResolver() mailer_cls = resolver.resolve(mailer_class) mailer = mailer_cls() return mailer
def configure_mailer(self): """Configure outgoing email backend and email test views.""" from pyramid_mailer import IMailer settings = self.settings.copy() # Empty values are not handled gracefully, so mutate them here before passing forward to mailer if settings.get("mail.username", "x") == "": settings["mail.username"] = None if settings.get("mail.password", "x") == "": settings["mail.password"] = None mailer_class = settings.get("websauna.mailer", "") if mailer_class in ("mail", ""): # TODO: Make mailer_class explicit so we can dynamically load pyramid_mail.Mailer # Default from pyramid_mailer import mailer_factory_from_settings mailer = mailer_factory_from_settings(settings) self.config.registry.registerUtility(mailer, IMailer) else: # debug backend resolver = DottedNameResolver() mailer_cls = resolver.resolve(mailer_class) mailer = mailer_cls() self.config.registry.registerUtility(mailer, IMailer) if settings.get("websauna.sample_html_email", False): from websauna.system.mail import views self.config.scan(views) self.config.add_jinja2_search_path( 'websauna.system:mail/templates', name='.html')
def _notification_callback( event, job_id, request, email, subdomain ): if event.job_id != job_id: return if event.code == EVENT_JOB_EXECUTED: subject = _(u'Company created') html = render( 'travelcrm:templates/companies/email_success.mako', {'subdomain': subdomain}, request=request, ) mailer = mailer_factory_from_settings(request.registry.settings) message = Message( subject=subject, sender=mailer.default_sender, recipients=(email,), html=html ) mailer.send_immediately(message) scheduler = get_scheduler(request) scheduler.remove_listener(_notification_callback)
def _user_notification(email, subject, html, mailer_settings): mailer = mailer_factory_from_settings(mailer_settings) message = Message(subject=subject, sender=mailer.default_sender, recipients=(email, ), html=html) mailer.send_immediately(message)
def configure_mailer(self, settings): """Configure outgoing email backend based on the INI settings.""" settings = settings.copy() # Empty values are not handled gracefully, so mutate them here before passing forward to mailer if settings.get("mail.username", "x") == "": settings["mail.username"] = None if settings.get("mail.password", "x") == "": settings["mail.password"] = None mailer_class = settings.get("websauna.mailer", "") if mailer_class in ("mail", ""): # TODO: Make mailer_class explicit so we can dynamically load pyramid_mail.Mailer # Default from pyramid_mailer import mailer_factory_from_settings mailer = mailer_factory_from_settings(settings) self.config.registry.registerUtility(mailer, IMailer) else: # debug backend resolver = DottedNameResolver() mailer_cls = resolver.resolve(mailer_class) mailer = mailer_cls() self.config.registry.registerUtility(mailer, IMailer)
def main(): # read configuration import sys try: fs_config = sys.argv[1] except IndexError: fs_config = path.join(path.dirname(__file__), '..', 'etc/watchdog.ini') fs_config = path.abspath(fs_config) parser = ConfigParser(allow_no_value=True) parser.read(fs_config) config = parser.as_dict()['briefkasten'] # read history of previous runs errors = [] fs_history = path.abspath(path.join(path.dirname(__file__), '..', 'var', 'watchdog-history.json')) if path.exists(fs_history): history = json.load(open(fs_history, 'r')) else: history = dict() # fetch submissions from mail server history = fetch_test_submissions(previous_history=history, config=config) # check for failed test submissions max_process_secs = int(config.get('max_process_secs', 600)) now = datetime.now() for token, timestamp_str in history.items(): timestamp = datetime.utcfromtimestamp((timegm(time.strptime(timestamp_str.split('.')[0] + 'UTC', "%Y-%m-%dT%H:%M:%S%Z")))) age = now - timestamp if age.seconds > max_process_secs: errors.append(WatchdogError(subject="Submission '%s' not received" % token, message=u"The submission with token %s which was submitted on %s was not received after %d seconds." % (token, timestamp, max_process_secs))) # perform test submission token, submission_errors = perform_submission(app_url=config['app_url'], testing_secret=config['testing_secret']) history[token] = datetime.now().isoformat() errors += submission_errors # record updated history file_history = open(fs_history, 'w') file_history.write(json.dumps(history).encode('utf-8')) file_history.close() if len(errors) == 0: exit() from pyramid_mailer import mailer_factory_from_settings from pyramid_mailer.message import Message from urlparse import urlparse mailer = mailer_factory_from_settings(config, prefix='smtp_') hostname = urlparse(config['app_url']).hostname recipients = [recipient for recipient in config['notify_email'].split('\n') if recipient] message = Message(subject="[Briefkasten %s] Submission failure" % hostname, sender=config['the_sender'], recipients=recipients, body="\n".join([str(error) for error in errors])) mailer.send_immediately(message, fail_silently=False)
def main(): # read configuration import sys try: fs_config = sys.argv[1] except IndexError: fs_config = path.join(path.dirname(__file__), '..', 'watchdog-development.ini') fs_config = path.abspath(fs_config) parser = ConfigParser(allow_no_value=True) parser.read(fs_config) config = parser.as_dict()['briefkasten'] # read history of previous runs errors = [] fs_history = path.abspath(path.join(path.dirname(__file__), '..', 'var', 'watchdog-history.json')) if path.exists(fs_history): history = json.load(open(fs_history, 'r')) else: history = dict() # fetch submissions from mail server history = fetch_test_submissions(previous_history=history, config=config) # check for failed test submissions max_process_secs = int(config.get('max_process_secs', 600)) now = datetime.now() for token, timestamp_str in history.items(): timestamp = datetime.utcfromtimestamp((timegm(time.strptime(timestamp_str.split('.')[0] + 'UTC', "%Y-%m-%dT%H:%M:%S%Z")))) age = now - timestamp if age.seconds > max_process_secs: errors.append(WatchdogError(subject="Submission '%s' not received" % token, message=u"The submission with token %s which was submitted on %s was not received after %d seconds." % (token, timestamp, max_process_secs))) # perform test submission token, submission_errors = perform_submission(app_url=config['app_url'], testing_secret=config['testing_secret']) history[token] = datetime.now().isoformat() errors += submission_errors # record updated history file_history = open(fs_history, 'w') file_history.write(json.dumps(history).encode('utf-8')) file_history.close() if len(errors) == 0: exit() from pyramid_mailer import mailer_factory_from_settings from pyramid_mailer.message import Message from urlparse import urlparse mailer = mailer_factory_from_settings(config, prefix='smtp_') hostname = urlparse(config['app_url']).hostname recipients = [recipient for recipient in config['notify_email'].split('\n') if recipient] message = Message(subject="[Briefkasten %s] Submission failure" % hostname, sender=config['the_sender'], recipients=recipients, body="\n".join([str(error) for error in errors])) mailer.send_immediately(message, fail_silently=False)
def main(argv=sys.argv): parser = ArgumentParser(description=__doc__, formatter_class=RawTextHelpFormatter) parser.add_argument('-v', '--verbose', action='count') parser.add_argument('-S', '--send', action='store_true', default=False) parser.add_argument('--active', action='store_true', default=True) parser.add_argument('-s', '--subject', action='store') parser.add_argument('config') parser.add_argument('textfile') args = parser.parse_args() log_level = logging.WARNING if args.verbose is not None: verbose = int(args.verbose) if verbose == 1: log_level = logging.INFO elif verbose >= 2: log_level = logging.DEBUG logging.basicConfig(level=log_level) config_uri = args.config setup_logging(config_uri) settings = get_appsettings(config_uri) engine = engine_from_config(settings, 'sqlalchemy.') DBSession.configure(bind=engine) mailer = mailer_factory_from_settings(settings) if not args.subject: print('Require a subject.') exit(1) message_in = open(args.textfile, 'r').read() if not message_in: print('Require a message.') exit(1) q = DBSession.query(User) q = q.filter(User.email != '') q = q.filter(User.email is not None) if args.active: q = q.filter_by(is_paid=True) users = list(q.all()) print('Sending to: %d users.' % (len(users))) if args.verbose: for u in users: print('- %s [%s]' % (u.email, u.username)) for u in users: if not args.send: print('Not sending message to %s.' % u.email) continue message = Message(subject=args.subject, recipients=[u.email], body=message_in) mailer.send_immediately(message)
def _send(settings, subject, recepient, body, html): mailer = mailer_factory_from_settings(settings) message = Message( subject=subject, sender=mailer.default_sender, recipients=(recepient,), body=body, html=html ) mailer.send_immediately(message)
def _setup_from_config(config_path): from sqlalchemy import engine_from_config config = _load_config(config_path) load_settings_from_environ(config, ENVIRON_SETTINGS_MAP) engine = engine_from_config(config, prefix='sqlalchemy.') Session.configure(bind=engine) Base.metadata.bind = engine global cli_mailer cli_mailer = mailer_factory_from_settings(config)
def _user_notification(email, html, mailer_settings): subject = _(u'Password recovery') mailer = mailer_factory_from_settings(mailer_settings) message = Message( subject=subject, sender=mailer.default_sender, recipients=(email,), html=html ) mailer.send_immediately(message)
def main(argv=sys.argv): parser = ArgumentParser(description=__doc__, formatter_class=RawTextHelpFormatter) parser.add_argument('-v', '--verbose', action='count') parser.add_argument('-s', '--send', action='store_true', default=False) parser.add_argument('config') args = parser.parse_args() log_level = logging.WARNING if args.verbose is not None: verbose = int(args.verbose) if verbose == 1: log_level = logging.INFO elif verbose >= 2: log_level = logging.DEBUG logging.basicConfig(level=log_level) config_uri = args.config setup_logging(config_uri) settings = get_appsettings(config_uri) engine = engine_from_config(settings, 'sqlalchemy.') DBSession.configure(bind=engine) if 'mako.directories' not in settings: settings['mako.directories'] = 'ccvpn:templates/' if 'mako.imports' not in settings: settings['mako.imports'] = 'from ccvpn.filters import check' config = Configurator(settings=settings) config.include('pyramid_mako') config.commit() config.begin() mailer = mailer_factory_from_settings(settings) try: days = int(settings.get('expire_mail_days', 3)) except ValueError: log.warning('Invalid integer value for expire_mail_days. Using default') days = 3 users = get_future_expire(days) + get_expired() if args.send: for u in users: print('sending notice to %s (%s)' % (u.username, u.email)) send_notice(u, mailer) transaction.commit() else: for u in users: print('not sending notice to %s (%s)' % (u.username, u.email)) print('Use -s to send messages')
def on_configure_with_settings(self, settings): global notify_process_mailer notify_process_mailer = mailer_factory_from_settings(settings) # setup SETTINGS_SMTP_DELAY for name, val in settings.items(): if name.startswith(SETTINGS_SMTP_DELAY): try: val = timedelta(seconds=float(val)) except ValueError: log.error("Not a valid value for %s: %s" % (name, val)) continue SMTP_DOMAIN_DELAYS[name[len(SETTINGS_SMTP_DELAY):]] = val log.info("SMTP_DOMAIN_DELAYS: " + repr(SMTP_DOMAIN_DELAYS))
def main(global_config, **settings): """ This function returns a Pyramid WSGI application. """ engine = engine_from_config(settings, 'sqlalchemy.') DBSession.configure(bind=engine) Base.metadata.bind = engine Base.metadata.reflect(only=('anlicenses', 'pdidx', 'anproducts')) config = Configurator(settings=settings) config.registry['mailer'] = mailer_factory_from_settings(settings) config.add_static_view('static', 'static', cache_max_age=3600) config.add_route('home', '/') config.scan() return config.make_wsgi_app()
def init_from_celery(self): # A task is called through celery, so it may not have basic # configuration setup. Go through that setup the first time. global _settings, SMTP_DOMAIN_DELAYS rootdir = getcwd() settings_file = join(rootdir, 'local.ini') if not exists(settings_file): settings_file = join(rootdir, 'production.ini') if not exists(settings_file): rootdir = dirname(dirname(dirname(realpath(__file__)))) settings_file = join(rootdir, 'local.ini') if not exists(settings_file): settings_file = join(rootdir, 'production.ini') if not exists(settings_file): raise RuntimeError("Missing settings file") _settings = settings = get_appsettings(settings_file, 'assembl') configure_zmq(settings['changes_socket'], False) config = ConfigParser.SafeConfigParser() config.read(settings_file) registry = getGlobalSiteManager() registry.settings = settings set_config(settings) configure_engine(settings, True) configure_indexing() if settings.get('%s_debug_signal' % (self.main,), False): from assembl.lib import signals signals.listen() configure(registry, self.main) from .threaded_model_watcher import ThreadDispatcher threaded_watcher_class_name = settings.get( '%s.threadedmodelwatcher' % (self.main,), "assembl.lib.model_watcher.BaseModelEventWatcher") ThreadDispatcher.mw_class = resolver.resolve( threaded_watcher_class_name) self.mailer = mailer_factory_from_settings(settings) # setup SETTINGS_SMTP_DELAY for name, val in settings.iteritems(): if name.startswith(SETTINGS_SMTP_DELAY): try: val = timedelta(seconds=float(val)) except ValueError: print "Not a valid value for %s: %s" % (name, val) continue SMTP_DOMAIN_DELAYS[name[len(SETTINGS_SMTP_DELAY):]] = val getLogger().info("SMTP_DOMAIN_DELAYS", delays=SMTP_DOMAIN_DELAYS) import assembl.tasks.imap import assembl.tasks.notify import assembl.tasks.notification_dispatch import assembl.tasks.translate import assembl.tasks.watson assembl.tasks.notification_dispatch.create_dispatcher()
def init_from_celery(self): # A task is called through celery, so it may not have basic # configuration setup. Go through that setup the first time. global _settings, SMTP_DOMAIN_DELAYS rootdir = getcwd() settings_file = join(rootdir, 'local.ini') if not exists(settings_file): settings_file = join(rootdir, 'production.ini') if not exists(settings_file): rootdir = dirname(dirname(dirname(realpath(__file__)))) settings_file = join(rootdir, 'local.ini') if not exists(settings_file): settings_file = join(rootdir, 'production.ini') if not exists(settings_file): raise RuntimeError("Missing settings file") _settings = settings = get_appsettings(settings_file, 'assembl') configure_zmq(settings['changes_socket'], False) config = ConfigParser.SafeConfigParser() config.read(settings_file) registry = getGlobalSiteManager() registry.settings = settings set_config(settings) configure_engine(settings, True) configure_indexing() if settings.get('%s_debug_signal' % (self.main, ), False): from assembl.lib import signals signals.listen() configure(registry, self.main) from .threaded_model_watcher import ThreadDispatcher threaded_watcher_class_name = settings.get( '%s.threadedmodelwatcher' % (self.main, ), "assembl.lib.model_watcher.BaseModelEventWatcher") ThreadDispatcher.mw_class = resolver.resolve( threaded_watcher_class_name) self.mailer = mailer_factory_from_settings(settings) # setup SETTINGS_SMTP_DELAY for name, val in settings.iteritems(): if name.startswith(SETTINGS_SMTP_DELAY): try: val = timedelta(seconds=float(val)) except ValueError: print "Not a valid value for %s: %s" % (name, val) continue SMTP_DOMAIN_DELAYS[name[len(SETTINGS_SMTP_DELAY):]] = val getLogger().info("SMTP_DOMAIN_DELAYS", delays=SMTP_DOMAIN_DELAYS) import assembl.tasks.imap import assembl.tasks.notify import assembl.tasks.notification_dispatch import assembl.tasks.translate import assembl.tasks.watson assembl.tasks.notification_dispatch.create_dispatcher()
def includeme(config: Configurator) -> None: config.include('tet.services') settings = config.registry.settings prefix = settings.get('tet.mailer.prefix', 'tet.mailer.') mailer = mailer_factory_from_settings(settings, prefix=prefix) debug_path = settings.get(prefix + 'debug_directory') if debug_path: mailer = DebugCoalescingMailer(mailer, debug_path) config.registry['tet.mailer.factory'] = mailer config.register_tet_service(MailerService, scope='request', interface=IMailerService)
def devpiserver_pyramid_configure(config, pyramid_config): from pyramid_mailer import mailer_factory_from_settings # by using include, the package name doesn't need to be set explicitly # for registrations of static views etc pyramid_config.include('devpi_passwd_reset.main') settings = {} passwd_reset_config = config.args.passwd_reset_config if passwd_reset_config: if not os.path.exists(passwd_reset_config): fatal("No config at '%s'." % passwd_reset_config) with open(passwd_reset_config) as f: _config = yaml.load(f) settings.update(_config.get('pyramid_mailer', {})) pyramid_config.registry['mailer'] = mailer_factory_from_settings(settings)
def main(global_config, **settings): """Returns the Pyramid WSGI application""" # Ensure that the production configuration has been updated with "real" # values (at least where required for security) for key in ("authn.secret", "session.secret"): if settings.get(key) == "CHANGEME": raise ValueError("You must specify a new value for %s" % key) mimetypes.init() session_factory = session_factory_from_settings(settings) mailer_factory = mailer_factory_from_settings(settings) licenses_factory = licenses_factory_from_settings(settings) authn_policy = authentication_policy_from_settings(settings) authz_policy = ACLAuthorizationPolicy() engine = engine_from_config(settings, "sqlalchemy.") DBSession.configure(bind=engine) config = Configurator( settings=settings, root_factory=RootContextFactory, authentication_policy=authn_policy, authorization_policy=authz_policy, session_factory=session_factory, ) config.registry["mailer"] = mailer_factory config.registry["licenses"] = licenses_factory # XXX Deprecated in 1.4 config.set_request_property(get_user, b"user", reify=True) # XXX For 1.4: # config.add_request_method(get_user, b'user', reify=True) config.add_static_view("static", "static", cache_max_age=3600) for name, url in ROUTES.items(): if "{collection_id:" in url: factory = CollectionContextFactory elif "{sample_id:" in url: factory = SampleContextFactory else: factory = RootContextFactory config.add_route(name, url, factory=factory) config.scan() app = config.make_wsgi_app() # XXX Dirty horrid hack for functional testing if settings.get("testing", "0") == "1": app.engine = engine return app
def _notification_callback(event, job_id, request, email, subdomain): if event.job_id != job_id: return if event.code == EVENT_JOB_EXECUTED: subject = _(u'Company created') html = render( 'travelcrm:templates/companies/email_success.mako', {'subdomain': subdomain}, request=request, ) mailer = mailer_factory_from_settings(request.registry.settings) message = Message(subject=subject, sender=mailer.default_sender, recipients=(email, ), html=html) mailer.send_immediately(message) scheduler.remove_listener(_notification_callback)
def send(settings, recipients, subject, body, html=None): """ Send an email. :param recipients: the list of email addresses to send the email to :type recipients: list of unicode strings :param subject: the subject of the email :type subject: unicode :param body: the body of the email :type body: unicode """ email = pyramid_mailer.message.Message(subject=subject, recipients=recipients, body=body, html=html) mailer = mailer_factory_from_settings(settings) mailer.send_immediately(email)
def test_from_settings_factory(self): try: from smtplib import SMTP_SSL ssl_enabled = True except ImportError: # pragma: no cover from smtplib import SMTP ssl_enabled = False from pyramid_mailer.mailer import (Mailer, DummyMailer, SMTP_SSLMailer, SMTPMailer, LoggingMailer) from pyramid_mailer import mailer_factory_from_settings settings = { 'mymail.host': 'my.server.com', 'mymail.port': 123, 'mymail.username': '******', 'mymail.password': '******', 'mymail.tls': True, 'mymail.ssl': True, 'mymail.keyfile': 'ssl.key', 'mymail.certfile': 'ssl.crt', 'mymail.queue_path': '/tmp', 'mymail.debug': 1 } mailer = mailer_factory_from_settings(settings, prefix='mymail.') self.assert_(mailer.direct_delivery.mailer.hostname == 'my.server.com') self.assert_(mailer.direct_delivery.mailer.port == 123) self.assert_(mailer.direct_delivery.mailer.username == 'tester') self.assert_(mailer.direct_delivery.mailer.password == 'test') self.assert_(mailer.direct_delivery.mailer.force_tls == True) if ssl_enabled: self.assert_(mailer.direct_delivery.mailer.smtp == SMTP_SSL) else: # pragma: no cover self.assert_(mailer.direct_delivery.mailer.smtp == SMTP) self.assert_(mailer.direct_delivery.mailer.keyfile == 'ssl.key') self.assert_(mailer.direct_delivery.mailer.certfile == 'ssl.crt') self.assert_(mailer.queue_delivery.queuePath == '/tmp') self.assert_(mailer.direct_delivery.mailer.debug_smtp == 1)
def test_from_settings_factory(self): try: from smtplib import SMTP_SSL ssl_enabled = True except ImportError: # pragma: no cover from smtplib import SMTP ssl_enabled = False from pyramid_mailer import mailer_factory_from_settings settings = { "mymail.host": "my.server.com", "mymail.port": 123, "mymail.username": "******", "mymail.password": "******", "mymail.tls": True, "mymail.ssl": True, "mymail.keyfile": "ssl.key", "mymail.certfile": "ssl.crt", "mymail.queue_path": "/tmp", "mymail.debug": 1, } mailer = mailer_factory_from_settings(settings, prefix="mymail.") self.assertEqual(mailer.direct_delivery.mailer.hostname, "my.server.com") self.assertEqual(mailer.direct_delivery.mailer.port, 123) self.assertEqual(mailer.direct_delivery.mailer.username, "tester") self.assertEqual(mailer.direct_delivery.mailer.password, "test") self.assertEqual(mailer.direct_delivery.mailer.force_tls, True) if ssl_enabled: self.assertEqual(mailer.direct_delivery.mailer.smtp, SMTP_SSL) else: # pragma: no cover self.assertEqual(mailer.direct_delivery.mailer.smtp, SMTP) self.assertEqual(mailer.direct_delivery.mailer.keyfile, "ssl.key") self.assertEqual(mailer.direct_delivery.mailer.certfile, "ssl.crt") self.assertEqual(mailer.queue_delivery.queuePath, "/tmp") self.assertEqual(mailer.direct_delivery.mailer.debug_smtp, 1)
def test_from_settings_factory(self): try: from smtplib import SMTP_SSL ssl_enabled = True except ImportError: # pragma: no cover from smtplib import SMTP ssl_enabled = False from pyramid_mailer.mailer import (Mailer, DummyMailer, SMTP_SSLMailer, SMTPMailer, LoggingMailer) from pyramid_mailer import mailer_factory_from_settings settings = {'mymail.host' : 'my.server.com', 'mymail.port' : 123, 'mymail.username' : 'tester', 'mymail.password' : 'test', 'mymail.tls' : True, 'mymail.ssl' : True, 'mymail.keyfile' : 'ssl.key', 'mymail.certfile' : 'ssl.crt', 'mymail.queue_path' : '/tmp', 'mymail.debug' : 1} mailer = mailer_factory_from_settings(settings, prefix='mymail.') self.assert_(mailer.direct_delivery.mailer.hostname=='my.server.com') self.assert_(mailer.direct_delivery.mailer.port==123) self.assert_(mailer.direct_delivery.mailer.username=='tester') self.assert_(mailer.direct_delivery.mailer.password=='test') self.assert_(mailer.direct_delivery.mailer.force_tls==True) if ssl_enabled: self.assert_(mailer.direct_delivery.mailer.smtp == SMTP_SSL) else: # pragma: no cover self.assert_(mailer.direct_delivery.mailer.smtp == SMTP) self.assert_(mailer.direct_delivery.mailer.keyfile == 'ssl.key') self.assert_(mailer.direct_delivery.mailer.certfile == 'ssl.crt') self.assert_(mailer.queue_delivery.queuePath == '/tmp') self.assert_(mailer.direct_delivery.mailer.debug_smtp == 1)
def includeme(config): global notify_process_mailer config_celery_app(notify_celery_app, config.registry.settings) notify_process_mailer = mailer_factory_from_settings(config.registry.settings)
def send_mail(to, etype, request, data=None): add_cc = ['mentoring_request', 'mentoring_request_intro'] if data is None: data = {} mi = emails.get(etype, 'data').copy() if mi.get('mailer'): mailer = mailer_factory_from_settings(mi.get('mailer'), '') else: mailer = get_mailer(request) if 'user' not in data: from alchemist.models import User data['user'] = User.fr(request) if request.authenticated_userid and data['user'].id != request.authenticated_userid: from alchemist.models import User data['auth_user'] = User.fr(request) for k, v in mi.iteritems(): if callable(v): v = v(data, request) if '/templates/' in v: v = render(v, data, request) elif isinstance(v, basestring): if '{{' in v and '}}' in v: v = Template(v).render(**data) else: v = v.format(**data) mi[k] = v if 'attachments' in data: attachments = data['attachments'] elif 'attachments' in mi and mi['attachments'] and mi['attachments'] != 'None': with open(os.path.dirname(__file__) + mi['attachments']) as fo: a_file = fo.read() attachments = [Attachment(os.path.basename(mi['attachments']), 'application/' + mi['attachments'][-3:], a_file)] else: attachments = None if not isinstance(to, list): to = to.split(',') from alchemist.models.settings import Settings send_from = mi.get('from') bcc = [bc for bc in mi.get('bcc', '').split(',') if bc] sender = Settings.get('admin_mail', '*****@*****.**') sender = sender.split(',') main_admin_mail = sender[0].strip() if main_admin_mail: bcc.append(main_admin_mail) if not send_from: send_from = main_admin_mail or '*****@*****.**' cc = mi.get('cc') if mi.get('cc') else [] if '@' not in cc and not isinstance(cc, list): cc = Settings.get(cc, cc).split(',') if not cc and etype in add_cc: cc = [email.strip() for email in Settings.get('cc_emails', '').split(',')] mail = Message(mi['subject'], to, mi['text'], mi['html'], sender=send_from, bcc=bcc, cc=cc) if attachments: mail.attachments = attachments mailer.send(mail)
def send_mail(to, etype, request, data=None): add_cc = ["mentoring_request", "mentoring_request_intro"] if data is None: data = {} mi = emails.get(etype, "data").copy() if mi.get("mailer"): mailer = mailer_factory_from_settings(mi.get("mailer"), "") else: mailer = get_mailer(request) if "user" not in data and request.user: data["user"] = request.user if request and request.authenticated_userid and data["user"].id != request.authenticated_userid: data["auth_user"] = request.user for k, v in mi.iteritems(): if callable(v): v = v(data, request) if ".jinja2" in v: v = render(v, data, request) elif isinstance(v, basestring): if "{{" in v and "}}" in v: v = Template(v).render(**data) else: v = v.format(**data) mi[k] = v if "attachments" in data: attachments = data["attachments"] elif "attachments" in mi and mi["attachments"] and mi["attachments"] != "None": with open(os.path.dirname(os.path.dirname(__file__)) + mi["attachments"]) as fo: a_file = fo.read() attachments = [Attachment(os.path.basename(mi["attachments"]), "application/" + mi["attachments"][-3:], a_file)] else: attachments = None if not isinstance(to, list): to = to.split(",") from alchemist.models.settings import Settings send_from = mi.get("from") bcc = [bc for bc in data.get("bcc", mi.get("bcc", "").split(",")) if bc] sender = Settings.get("admin_mail", "*****@*****.**") sender = sender.split(",") main_admin_mail = sender[0].strip() if main_admin_mail: bcc.append(main_admin_mail) if not send_from: send_from = main_admin_mail or "*****@*****.**" cc = mi.get("cc") if mi.get("cc") else [] if "@" not in cc and not isinstance(cc, list): cc = Settings.get(cc, cc).split(",") if not cc and etype in add_cc: cc = [email.strip() for email in Settings.get("cc_emails", "").split(",")] if debug and not set(Settings.get("allowed_outgoing", "").split(",")).issuperset(bcc + cc + to): print "Wanted to send email %s to %s, didn't" % (etype, bcc + cc + to) return None mail = Message(mi["subject"], to, mi["text"], mi["html"], sender=send_from, bcc=bcc, cc=cc) if attachments: mail.attachments = attachments mailer.send(mail)
def main(fs_config=None, sleep_seconds=None): # read configuration config = default_config() if fs_config is not None: fs_config = path.abspath(fs_config) config.update(config_from_file(fs_config)) config.update(config_from_env()) if sleep_seconds is not None: config['sleep_seconds'] = sleep_seconds else: config['sleep_seconds'] = int(config['sleep_seconds']) logging.basicConfig(stream=sys.stdout, level=getattr(logging, config['log_level'].upper())) # read history of previous runs errors = [] fs_history = path.abspath( path.join(path.dirname(fs_config), 'watchdog-history.json')) zbx = None result_code = None if 'zabbix_host' in config: zbx = ZabbixSender(config['zabbix_host']) while True: try: if path.exists(fs_history): previous_history = json.load(open(fs_history, 'r')) else: log.info("Starting with empty history.") previous_history = dict() # fetch submissions from mail server log.debug("Fetching previous submissions from IMAP server") history = fetch_test_submissions(previous_history=previous_history, config=config) # check for failed test submissions max_process_secs = int(config['max_process_secs']) now = datetime.now() for token, timestamp_str in history.items(): timestamp = datetime.utcfromtimestamp((timegm( time.strptime( timestamp_str.split('.')[0] + 'UTC', "%Y-%m-%dT%H:%M:%S%Z")))) age = now - timestamp if age.seconds > max_process_secs and token not in previous_history: errors.append( WatchdogError( subject="Submission '%s' not received" % token, message= u"The submission with token %s which was submitted on %s was not received after %d seconds." % (token, timestamp, max_process_secs))) # perform test submission log.debug("Performing test submissions against {app_url}".format( **config)) token, submission_errors = perform_submission( app_url=config['app_url'], testing_secret=config['testing_secret']) if token: history[token] = datetime.now().isoformat() errors += submission_errors # record updated history file_history = open(fs_history, 'w') file_history.write(json.dumps(history).encode('utf-8')) file_history.close() if len(errors) > 0: log.warning("Errors were found.") from pyramid_mailer import mailer_factory_from_settings from pyramid_mailer.message import Message from urlparse import urlparse mailer = mailer_factory_from_settings(config, prefix='smtp_') hostname = urlparse(config['app_url']).hostname recipients = [ recipient for recipient in config['notify_email'].split() if recipient ] message = Message( subject="[Briefkasten %s] Submission failure" % hostname, sender=config['the_sender'], recipients=recipients, body="\n".join([str(error) for error in errors])) mailer.send_immediately(message, fail_silently=False) result_code = 0 except Exception as exc: log.error(exc) result_code = 1 if zbx is not None: log.info("Pinging Zabbix") metric = ZabbixMetric(config.get('zabbix_sender', 'localhost'), 'briefkasten.watchdog.last_completed_run', result_code) sent = zbx.send([metric]) if sent.failed > 0: log.warning("Failed to ping Zabbix host") if config['sleep_seconds'] > 0: log.info("Sleeping {sleep_seconds} seconds".format(**config)) sleep(config['sleep_seconds']) else: exit(0)
def main(global_config, **settings): "Returns the Pyramid WSGI application" # Ensure we're not using production.ini verbatim for key in ( 'site.store', 'session.secret', 'login.google.consumer_key', 'login.google.consumer_secret', 'login.facebook.consumer_key', 'login.facebook.consumer_secret', 'login.twitter.consumer_key', 'login.twitter.consumer_secret', 'login.github.consumer_key', 'login.github.consumer_secret', ): if settings.get(key) == 'CHANGEME': raise ValueError('You must specify a new value for %s' % key) # Ensure path is configured appropriately files_dir = os.path.normpath(os.path.expanduser(settings['site.files'])) licenses_dir = os.path.normpath(os.path.expanduser(settings['licenses.cache_dir'])) check_path(settings['site.files']) check_path(settings['licenses.cache_dir']) session_factory = session_factory_from_settings(settings) mailer_factory = mailer_factory_from_settings(settings) licenses_factory = licenses_factory_from_settings(settings) engine = engine_from_config(settings, 'sqlalchemy.') # Configure the database session; the session is deliberately separated # from the model to enable us to bind it to an engine before importing # the model which will then use the bound engine to reflect the database from .db_session import DBSession DBSession.configure(bind=engine, info={'site.files': files_dir}) from .security import RequestWithUser, group_finder config = Configurator( settings=settings, session_factory=session_factory, request_factory=RequestWithUser, ) if settings.get('login.google.consumer_key'): config.include('velruse.providers.google_oauth2') config.add_google_oauth2_login_from_settings(prefix='login.google.') if settings.get('login.facebook.consumer_key'): config.include('velruse.providers.facebook') config.add_facebook_login_from_settings(prefix='login.facebook.') if settings.get('login.twitter.consumer_key'): config.include('velruse.providers.twitter') config.add_twitter_login_from_settings(prefix='login.twitter.') if settings.get('login.github.consumer_key'): config.include('velruse.providers.github') config.add_github_login_from_settings(prefix='login.github.') config.include('pyramid_chameleon') # XXX Need some way of grabbing the authentication secret from config authn_policy = AuthTktAuthenticationPolicy( 'secret', hashalg='sha512', callback=group_finder) authz_policy = ACLAuthorizationPolicy() config.set_authentication_policy(authn_policy) config.set_authorization_policy(authz_policy) config.registry['mailer'] = mailer_factory config.registry['licenses'] = licenses_factory config.add_static_view('static', 'static', cache_max_age=3600) from .views.comics import routes as comic_routes from .views.admin import routes as admin_routes from .security import ( RootContextFactory, ComicContextFactory, IssueContextFactory, PageContextFactory, ) for name, pattern in comic_routes() + admin_routes(): if '{page' in pattern: factory = PageContextFactory elif '{issue' in pattern: factory = IssueContextFactory elif '{comic' in pattern: factory = ComicContextFactory else: factory = RootContextFactory config.add_route(name, pattern, factory=factory) config.scan() return config.make_wsgi_app()
def config_mailer(registry, settings): registry['mailer'] = mailer_factory_from_settings(settings)
def main(global_config, **settings): """ This function returns a Pyramid WSGI application. """ # Database setup engine = engine_from_config(settings, 'sqlalchemy.') DBSession.configure(bind=engine) Base.metadata.bind = engine # Session, config my_session_factory = SignedCookieSessionFactory('itsaseekreet') config = Configurator(settings=settings, session_factory=my_session_factory, root_factory='.models.Root') config.include('pyramid_chameleon') config.registry['mailer'] = mailer_factory_from_settings(settings) # Security policies authn_policy = AuthTktAuthenticationPolicy(settings['flax.secret'], callback=groupfinder, hashalg='sha512') authz_policy = ACLAuthorizationPolicy() config.set_authentication_policy(authn_policy) config.set_authorization_policy(authz_policy) # Views # Home/Main views config.add_static_view('static', 'static', cache_max_age=int(settings['cache_max_age'])) config.add_route('home', '/') config.add_route('game', '/game') config.add_route('test_view', '/test') # Game/Action views config.add_route('hex_view', '/game/{loc_name}') config.add_route('get_ammo', '/game/action/ammo') config.add_route('recruit', '/game/action/recruit') config.add_route('upgrade_industry', '/game/action/industry') config.add_route('upgrade_infrastructure', '/game/action/infrastructure') config.add_route('attack_player', 'game/action/attack') config.add_route('movement', '/game/action/go_to') config.add_route('level_up', '/game/action/level_up') config.add_route('send_message', '/game/action/message') config.add_route('dig_in', '/game/action/dig_in') # Game info views config.add_route('my_info', '/game/info/my_info') config.add_route('current_hex_info', '/game/info/current_loc_info') config.add_route('map_info', '/game/info/map') # Personal/Information views config.add_route('team_info', '/team/{team}') config.add_route('profile', '/profile') config.add_route('levelup', '/settings/levelup') config.add_route('change_setting', '/settings/modify') # Authentication views config.add_route('register', '/register') config.add_route('login', '/login') config.add_route('ip_login', 'oneclick') config.add_route('logout', '/logout') config.add_route('verify', '/verify') config.add_route('recover_password', '/recover') # Admin views config.add_route('admin', '/admin') config.add_route('ban_player', '/ban') config.add_route('unban_player', '/unban') config.add_route('player_info', '/pinfo') config.add_route('broadcast', '/broadcast') config.add_route('hide_broadcast', '/hide_broadcast') config.scan('.views') return config.make_wsgi_app()
def __init__(self, settings ): self.settings = settings #self.mailer = get_mailer(config.registry) self.mailer = mailer_factory_from_settings(settings)
def main(global_config, **settings): """ This function returns a Pyramid WSGI application. """ engine = engine_from_config(settings, 'sqlalchemy.') initialize_sql(engine) session_factory = session_factory_from_settings(settings) #authn_policy = AuthTktAuthenticationPolicy( # '21(*^=s2ws%^~1`~|2JHFG1267fYTsaa1kjgh325URHfa', # callback=groupfinder, # cookie_name='authcookie', # secure=True, # timeout=3600, # reissue_time=360, # ) authn_policy = SessionAuthenticationPolicy( callback=groupfinder, #debug=True, ) authz_policy = ACLAuthorizationPolicy() config = Configurator( settings=settings, root_factory=RootFactory, authentication_policy=authn_policy, authorization_policy=authz_policy, introspection=False ) config.registry['mailer'] = mailer_factory_from_settings(settings) config.set_session_factory(session_factory) config.set_locale_negotiator(locale_negotiator) #this add a ".user" property to the request object and run #"get_user" internal functions only when assigned to a variable #to get the user data: "user = request.user" config.set_request_property(get_user, 'user', reify=True) config.add_subscriber('myproject.subscribers.add_renderer_globals', 'pyramid.events.BeforeRender') #config.add_subscriber('myproject.subscribers.add_localizer', # 'pyramid.events.NewRequest') #config.add_subscriber('myproject.subscribers.csrf_validation_event', # 'pyramid.events.NewRequest') config.add_subscriber('myproject.subscribers.new_request', 'pyramid.events.NewRequest') config.add_translation_dirs('myproject:locale') #config.add_static_view('captcha_imgs', 'myproject:captcha_imgs') #config.add_static_view('static-deform', 'deform:static') #config.add_static_view('static', 'myproject:static') config.add_static_view(name='http://cdn.mumberla.com/static', path='myproject:static') #config.add_static_view('static', 'myproject:static', cache_max_age=3600) #config.include('deform_bootstrap') config.add_route('home', '/') config.add_route('login', '/login') config.add_route('signup', '/signup') config.add_route('captcha-img', '/captcha-img/{captcha_image}') config.add_route('logout', '/logout') config.add_route('users', '/users', factory=UserFactory) config.add_route('user', '/user/{login}', factory=UserFactory, traverse='/{login}') config.add_route('support-key', '/support-key/{username}/{key}') config.add_route('support-pwd', '/support-pwd/{username}/{key}') config.add_route('change-locale', '/support-loc/{locale}') config.add_route('dids', '/dids', factory=UserFactory) config.add_route('twitter_login', '/twitter/login') config.add_route('twitter_process', '/twitter/process') config.add_route('agile_sms', '/agile/post') config.add_route('speak', '/speak') config.add_route('call', '/call') config.add_route('chat', '/chat') config.add_route('pages', '/pages', factory=PageFactory) config.add_route('create_page', '/create_page', factory=PageFactory) config.add_route('page', '/page/{title}', factory=PageFactory, traverse='/{title}') #config.add_route('page', '/page/{title}', factory=PageFactory) config.add_route('edit_page', '/page/{title}/edit', factory=PageFactory, traverse='/{title}') #config.add_route('edit_page', '/page/{title}/edit', factory=PageFactory) #config.add_static_view('static', 'myproject:static', cache_max_age=3600) #config.add_route('main_view', '/') #config.add_view('myproject.views.main_view', route_name='main_view') #config.add_route('login', '/login') #config.add_view('myproject.views.login', # context='pyramid.httpexceptions.HTTPForbidden', # renderer='myproject:templates/login.pt') #config.add_view('myproject.views.login', route_name='login', # renderer='myproject:templates/login.pt') #config.add_route('user', '/{login}' factory=UserFactory) #config.add_route('user', '/user/{login}', factory=UserFactory, traverse='/{login}') #config.add_view('myproject.views.view_page', route_name='view_page', # permission='edit', # renderer='myproject:templates/view.pt') #config.add_route('register', '/register') #config.add_view('myproject.views.user_add', route_name='register', # permission='view', # renderer='templates/user_add.pt') #config.add_route('add_page', '/add_page/{pagename}') #config.add_view('myproject.views.add_page', route_name='add_page', # renderer='myproject:templates/edit.pt', permission='edit') #config.add_route('edit_page', '/{pagename}/edit_page') #config.add_view('myproject.views.edit_page', route_name='edit_page', # renderer='myproject:templates/edit.pt', permission='edit') #config.add_route('logout', '/logout') #config.add_view('myproject.views.logout', route_name='logout') #config.add_route('home', '/home') #config.add_view('myproject.views.my_view', # route_name='home', # renderer='templates/mytemplate.pt') config.scan() return config.make_wsgi_app()