mirror of
https://gitlab.ub.uni-bielefeld.de/sfb1288inf/nopaque.git
synced 2024-12-26 11:24:18 +00:00
112 lines
4.9 KiB
Python
112 lines
4.9 KiB
Python
from sqlalchemy import asc
|
||
from .libnotify.notification import Notification
|
||
from .libnotify.service import NotificationService
|
||
from .. import configuration as config
|
||
from .. import Session
|
||
from ..decorators import background
|
||
from ..models import NotificationEmailData
|
||
import logging
|
||
import os
|
||
import smtplib
|
||
|
||
|
||
ROOT_DIR = os.path.abspath(os.path.dirname(__file__))
|
||
|
||
|
||
@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 = os.path.join(ROOT_DIR,
|
||
'libnotify/templates/notification.txt')
|
||
html_tmplt = os.path.join(ROOT_DIR,
|
||
'libnotify/templates/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)
|