from notify.notification import Notification from notify.service import NotificationService from sqlalchemy import asc from . import config, Session from .decorators import background from .models import NotificationEmailData import logging import smtplib @background def notify(): session = Session() if config.SMTP_USE_SSL: smtp = smtplib.SMTP_SSL(host=config.SMTP_SERVER, port=config.SMTP_PORT) else: smtp = smtplib.SMTP(host=config.SMTP_SERVER, port=config.SMTP_PORT) if config.SMTP_USE_TLS: smtp.starttls() try: smtp.login(config.SMTP_USERNAME, config.SMTP_PASSWORD) except smtplib.SMTPHeloError: logging.warning('The server didn’t reply properly to the HELO ' 'greeting.') return except smtplib.SMTPAuthenticationError as e: logging.warning('The server didn’t accept the username/password ' 'combination.') logging.warning(e) return except smtplib.SMTPNotSupportedError: logging.warning('The AUTH command is not supported by the server.') return except smtplib.SMTPException: logging.warning('No suitable authentication method was found.') return notification_service = NotificationService(smtp) # create notifications (content, recipient etc.) notifications = __create_mail_notifications(notification_service, session) # only login and send mails if there are any notifications if (len(notifications) > 0): # combine new and unsent notifications notifications.update(notification_service.not_sent) # send all notifications __send_mail_notifications(notifications, notification_service) # remove unsent notifications because they have been sent now # but only if mail limit has not been exceeded if (notification_service.mail_limit_exceeded is not True): notification_service.not_sent = {} smtp.quit() Session.remove() # Email notification functions def __create_mail_notifications(notification_service, session): notification_email_data = session.query(NotificationEmailData).order_by(asc(NotificationEmailData.creation_date)).all() # noqa notifications = {} for data in notification_email_data: notification = Notification() notification.set_addresses(config.SMTP_DEFAULT_SENDER, data.job.user.email) subject_template = ('[nopaque] Status update for your Job/Corpora: ' '{title}!') subject_template_values_dict = {'title': data.job.title} url = '{}://{}/{}/{}'.format(config.PROTOCOL, config.DOMAIN, 'jobs', data.job.id) body_template_values_dict = {'username': data.job.user.username, 'id': data.job.id, 'title': data.job.title, 'status': data.notify_status, 'time': data.creation_date, 'url': url} txt_tmplt = 'notify/templates/notification_messages/notification.txt' html_tmplt = 'notify/templates/notification_messages/notification.html' notification.set_notification_content(subject_template, subject_template_values_dict, txt_tmplt, html_tmplt, body_template_values_dict) notifications[data.job.id] = notification # Using a dictionary for notifications avoids sending multiple mails # if the status of a job changes in a few seconds. The user will not # get swamped with mails for queued, running and complete if those # happen in in a few seconds. Only the last update will be sent. # This depends on the sleep time interval though. session.delete(data) session.commit() return notifications def __send_mail_notifications(notifications, notification_service): for key, notification in notifications.items(): try: notification_service.send(notification) notification_service.mail_limit_exceeded = False except Exception: # Adds notifications to unsent if mail server exceded limit for # consecutive mail sending logging.warning('limit') notification_service.not_sent[key] = notification notification_service.mail_limit_exceeded = True notification_service.not_sent.update(notifications)