2020-06-05 12:42:04 +00:00
|
|
|
|
from notify.notification import Notification
|
|
|
|
|
from notify.service import NotificationService
|
|
|
|
|
from sqlalchemy import asc
|
2020-10-08 10:34:02 +00:00
|
|
|
|
from . import config, Session
|
|
|
|
|
from .decorators import background
|
|
|
|
|
from .models import NotificationEmailData
|
|
|
|
|
import logging
|
|
|
|
|
import smtplib
|
2020-06-05 12:42:04 +00:00
|
|
|
|
|
|
|
|
|
|
2020-06-10 12:18:02 +00:00
|
|
|
|
@background
|
2020-10-08 10:34:02 +00:00
|
|
|
|
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)
|
2020-06-08 08:23:32 +00:00
|
|
|
|
# create notifications (content, recipient etc.)
|
2020-10-08 10:34:02 +00:00
|
|
|
|
notifications = __create_mail_notifications(notification_service, session)
|
2020-06-08 08:23:32 +00:00
|
|
|
|
# only login and send mails if there are any notifications
|
|
|
|
|
if (len(notifications) > 0):
|
2020-10-08 10:34:02 +00:00
|
|
|
|
# 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()
|
2020-06-08 08:23:32 +00:00
|
|
|
|
|
|
|
|
|
|
2020-06-05 12:42:04 +00:00
|
|
|
|
# Email notification functions
|
2020-10-08 10:34:02 +00:00
|
|
|
|
def __create_mail_notifications(notification_service, session):
|
|
|
|
|
notification_email_data = session.query(NotificationEmailData).order_by(asc(NotificationEmailData.creation_date)).all() # noqa
|
2020-06-05 12:42:04 +00:00
|
|
|
|
notifications = {}
|
|
|
|
|
for data in notification_email_data:
|
|
|
|
|
notification = Notification()
|
2020-10-08 10:34:02 +00:00
|
|
|
|
notification.set_addresses(config.SMTP_DEFAULT_SENDER,
|
2020-06-05 12:42:04 +00:00
|
|
|
|
data.job.user.email)
|
2020-10-08 10:34:02 +00:00
|
|
|
|
subject_template = ('[nopaque] Status update for your Job/Corpora: '
|
|
|
|
|
'{title}!')
|
2020-06-05 12:42:04 +00:00
|
|
|
|
subject_template_values_dict = {'title': data.job.title}
|
2020-10-08 10:34:02 +00:00
|
|
|
|
url = '{}://{}/{}/{}'.format(config.PROTOCOL,
|
|
|
|
|
config.DOMAIN,
|
|
|
|
|
'jobs',
|
|
|
|
|
data.job.id)
|
2020-06-05 12:42:04 +00:00
|
|
|
|
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}
|
2020-06-08 08:23:32 +00:00
|
|
|
|
txt_tmplt = 'notify/templates/notification_messages/notification.txt'
|
|
|
|
|
html_tmplt = 'notify/templates/notification_messages/notification.html'
|
2020-06-05 12:42:04 +00:00
|
|
|
|
notification.set_notification_content(subject_template,
|
|
|
|
|
subject_template_values_dict,
|
2020-06-08 08:23:32 +00:00
|
|
|
|
txt_tmplt,
|
|
|
|
|
html_tmplt,
|
2020-06-05 12:42:04 +00:00
|
|
|
|
body_template_values_dict)
|
|
|
|
|
notifications[data.job.id] = notification
|
|
|
|
|
# Using a dictionary for notifications avoids sending multiple mails
|
2020-06-08 08:23:32 +00:00
|
|
|
|
# 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.
|
2020-10-08 10:34:02 +00:00
|
|
|
|
session.delete(data)
|
|
|
|
|
session.commit()
|
2020-06-05 12:42:04 +00:00
|
|
|
|
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
|
2020-10-08 10:34:02 +00:00
|
|
|
|
except Exception:
|
2020-06-05 12:42:04 +00:00
|
|
|
|
# Adds notifications to unsent if mail server exceded limit for
|
|
|
|
|
# consecutive mail sending
|
2020-10-08 10:34:02 +00:00
|
|
|
|
logging.warning('limit')
|
2020-06-05 12:42:04 +00:00
|
|
|
|
notification_service.not_sent[key] = notification
|
|
|
|
|
notification_service.mail_limit_exceeded = True
|
2020-10-08 10:34:02 +00:00
|
|
|
|
notification_service.not_sent.update(notifications)
|