DjLegolas 897955f0a1
Remove all Python 2 support
* Removed all __future__ imports from code
* Removed all six dependencies
* Removed all future_builtins imports
* Removed all Python 2 related code

Closes: deluge-torrent/deluge#325
2021-12-28 19:26:38 +00:00

230 lines
7.7 KiB
Python

# -*- coding: utf-8 -*-
#
# Copyright (C) 2009-2010 Pedro Algarvio <pedro@algarvio.me>
#
# Basic plugin template created by:
# Copyright (C) 2008 Martijn Voncken <mvoncken@gmail.com>
# Copyright (C) 2007-2009 Andrew Resch <andrewresch@gmail.com>
# Copyright (C) 2009 Damien Churchill <damoxc@gmail.com>
#
# This file is part of Deluge and is licensed under GNU General Public License 3.0, or later, with
# the additional special exception to link portions of this program with the OpenSSL library.
# See LICENSE for more details.
#
import logging
import smtplib
from email.utils import formatdate
from twisted.internet import defer, threads
import deluge.configmanager
from deluge import component
from deluge.core.rpcserver import export
from deluge.event import known_events
from deluge.plugins.pluginbase import CorePluginBase
from .common import CustomNotifications
log = logging.getLogger(__name__)
DEFAULT_PREFS = {
'smtp_enabled': False,
'smtp_host': '',
'smtp_port': 25,
'smtp_user': '',
'smtp_pass': '',
'smtp_from': '',
'smtp_tls': False, # SSL or TLS
'smtp_recipients': [],
# Subscriptions
'subscriptions': {'email': []},
}
class CoreNotifications(CustomNotifications):
def __init__(self, plugin_name=None):
CustomNotifications.__init__(self, plugin_name)
def enable(self):
CustomNotifications.enable(self)
self.register_custom_email_notification(
'TorrentFinishedEvent', self._on_torrent_finished_event
)
def disable(self):
self.deregister_custom_email_notification('TorrentFinishedEvent')
CustomNotifications.disable(self)
def register_custom_email_notification(self, eventtype, handler):
"""This is used to register email notifications for custom event types.
:param event: str, the event name
:param handler: function, to be called when `:param:event` is emitted
Your handler should return a tuple of (email_subject, email_contents).
"""
self._register_custom_provider('email', eventtype, handler)
def deregister_custom_email_notification(self, eventtype):
self._deregister_custom_provider('email', eventtype)
def handle_custom_email_notification(self, result, eventtype):
if not self.config['smtp_enabled']:
return defer.succeed('SMTP notification not enabled.')
subject, message = result
log.debug(
'Spawning new thread to send email with subject: %s: %s', subject, message
)
# Spawn thread because we don't want Deluge to lock up while we send the
# email.
return threads.deferToThread(self._notify_email, subject, message)
def get_handled_events(self):
handled_events = []
for evt in sorted(known_events):
if known_events[evt].__module__.startswith('deluge.event'):
if evt not in ('TorrentFinishedEvent',):
# Skip all un-handled built-in events
continue
classdoc = known_events[evt].__doc__.strip()
handled_events.append((evt, classdoc))
log.debug('Handled Notification Events: %s', handled_events)
return handled_events
def _notify_email(self, subject='', message=''):
log.debug('Email prepared')
to_addrs = self.config['smtp_recipients']
to_addrs_str = ', '.join(self.config['smtp_recipients'])
headers_dict = {
'smtp_from': self.config['smtp_from'],
'subject': subject,
'smtp_recipients': to_addrs_str,
'date': formatdate(),
}
headers = (
"""\
From: %(smtp_from)s
To: %(smtp_recipients)s
Subject: %(subject)s
Date: %(date)s
"""
% headers_dict
)
message = '\r\n'.join((headers + message).splitlines())
try:
server = smtplib.SMTP(
self.config['smtp_host'], self.config['smtp_port'], timeout=60
)
except Exception as ex:
err_msg = _('There was an error sending the notification email: %s') % ex
log.error(err_msg)
return ex
security_enabled = self.config['smtp_tls']
if security_enabled:
server.ehlo()
if 'starttls' not in server.esmtp_features:
log.warning('TLS/SSL enabled but server does not support it')
else:
server.starttls()
server.ehlo()
if self.config['smtp_user'] and self.config['smtp_pass']:
try:
server.login(self.config['smtp_user'], self.config['smtp_pass'])
except smtplib.SMTPHeloError as ex:
err_msg = _('Server did not reply properly to HELO greeting: %s') % ex
log.error(err_msg)
return ex
except smtplib.SMTPAuthenticationError as ex:
err_msg = _('Server refused username/password combination: %s') % ex
log.error(err_msg)
return ex
try:
try:
server.sendmail(self.config['smtp_from'], to_addrs, message)
except smtplib.SMTPException as ex:
err_msg = (
_('There was an error sending the notification email: %s') % ex
)
log.error(err_msg)
return ex
finally:
if security_enabled:
# avoid false failure detection when the server closes
# the SMTP connection with TLS enabled
import socket
try:
server.quit()
except socket.sslerror:
pass
else:
server.quit()
return _('Notification email sent.')
def _on_torrent_finished_event(self, torrent_id):
log.debug('Handler for TorrentFinishedEvent called for CORE')
torrent = component.get('TorrentManager')[torrent_id]
torrent_status = torrent.get_status(['name', 'num_files'])
# Email
subject = _('Finished Torrent "%(name)s"') % torrent_status
message = (
_(
'This email is to inform you that Deluge has finished '
'downloading "%(name)s", which includes %(num_files)i files.'
'\nTo stop receiving these alerts, simply turn off email '
"notification in Deluge's preferences.\n\n"
'Thank you,\nDeluge.'
)
% torrent_status
)
return subject, message
# d = defer.maybeDeferred(self.handle_custom_email_notification,
# [subject, message],
# 'TorrentFinishedEvent')
# d.addCallback(self._on_notify_sucess, 'email')
# d.addErrback(self._on_notify_failure, 'email')
# return d
class Core(CorePluginBase, CoreNotifications):
def __init__(self, plugin_name):
CorePluginBase.__init__(self, plugin_name)
CoreNotifications.__init__(self)
def enable(self):
CoreNotifications.enable(self)
self.config = deluge.configmanager.ConfigManager(
'notifications-core.conf', DEFAULT_PREFS
)
log.debug('ENABLING CORE NOTIFICATIONS')
def disable(self):
log.debug('DISABLING CORE NOTIFICATIONS')
CoreNotifications.disable(self)
@export
def set_config(self, config):
"""Sets the config dictionary."""
for key in config:
self.config[key] = config[key]
self.config.save()
@export
def get_config(self):
"""Returns the config dictionary."""
return self.config.config
@export
def get_handled_events(self):
return CoreNotifications.get_handled_events(self)