summaryrefslogtreecommitdiffstats
path: root/deluge/plugins/Notifications/deluge_notifications/core.py
diff options
context:
space:
mode:
Diffstat (limited to 'deluge/plugins/Notifications/deluge_notifications/core.py')
-rw-r--r--deluge/plugins/Notifications/deluge_notifications/core.py228
1 files changed, 228 insertions, 0 deletions
diff --git a/deluge/plugins/Notifications/deluge_notifications/core.py b/deluge/plugins/Notifications/deluge_notifications/core.py
new file mode 100644
index 0000000..aa200f9
--- /dev/null
+++ b/deluge/plugins/Notifications/deluge_notifications/core.py
@@ -0,0 +1,228 @@
+#
+# 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.encode())
+ 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)