Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Issue 2035: Add email notifier with per show notification lists #428

Open
wants to merge 1 commit into from

4 participants

Derek Battams xombiemp thezoggy Nyghto
Derek Battams

This patch provides email notifications, with support for TLS and SMTP AUTH. It provides the regular notifications on snatch and download. It provides the ability to give a list of "global" emails, which receive notifications for all shows and it also allows configuration of email notification lists on a per show basis. This addresses Google Code issue 2035. Screenshot attached to that issue.

Tested using Gmail's SMTP server (TLS + SMTP AUTH) and my ISP's SMTP server (no TLS, no AUTH). Both worked as expected.

Tested on my (relatively old) Linux VM (Ubuntu) using python 2.6.5 and Cheetah 2.0.1. Also tested on WinXP using python 2.7.3 and Cheetah 2.4.4.

Changes are pretty standard except I added a new column to the tv_shows table, which stores the list of email addresses configured for each show.

xombiemp

I just tested this with my gmail account and it works great! Please merge this!

thezoggy

new code needs to be based off the development branch, not master

Derek Battams
Nyghto

Is email notification going to be implemented? really needing this:)

xombiemp

I created a new pull request for this against the development branch. #569

Nyghto

Much thanks, looking forward to it. couch potato also finally has email notification.

thezoggy

why not just use sab's email notification ability?

xombiemp

I don't use sab. I use rutorrent.

Nyghto

i am using sabs mail notifications, but things are changing.. So want couch (it is possible with couch) and sickbeard only send mail upon complete download.

Jean-Michel GARCIA jmichelgarcia referenced this pull request in xombiemp/Sick-Beard
Closed

Email Notifications #1

Jean-Michel GARCIA jmichelgarcia referenced this pull request in bricky/Sick-Beard
Closed

Email Notifications #44

bricky bricky referenced this pull request from a commit in bricky/Sick-Beard
xombiemp xombiemp Email Notifications
"This patch provides email notifications, with support for TLS and SMTP
AUTH. It provides the regular notifications on snatch and download. It
provides the ability to give a list of "global" emails, which receive
notifications for all shows and it also allows configuration of email
notification lists on a per show basis."

This is Sluggers pull request from
midgetspy#428

I made the changes in the Development branch and changed a few things
to get it to work with the current version of SickBeard.  I've tested
it and it seems to be working great.
ee34671
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Showing 1 unique commit by 1 author.

Jul 04, 2012
Derek Battams Slugger Add email notifier with per show notification lists e0b7859
This page is out of date. Refresh to see the latest.
BIN  data/images/notifiers/email.jpg
123 data/interfaces/default/config_notifications.tmpl
@@ -730,6 +730,129 @@
730 730 <h1>Online</h1>
731 731 <br />
732 732
  733 + <div class="component-group clearfix">
  734 + <div class="component-group-desc">
  735 + <h3><img src="$sbRoot/images/notifiers/email.jpg" title="Email" width="16" height="11" />Email</h3>
  736 + <p>Allows configuration of email notifications on a per show basis.</p>
  737 + </div>
  738 + <fieldset class="component-group-list">
  739 + <div class="field-pair">
  740 + <input type="checkbox" class="enabler" name="use_email" id="use_email" #if $sickbeard.USE_EMAIL then "checked=\"checked\"" else ""# />
  741 + <label class="clearfix" for="use_email">
  742 + <span class="component-title">Enable</span>
  743 + <span class="component-desc">Should Sick Beard send email notifications?</span>
  744 + </label>
  745 + </div>
  746 +
  747 + <div id="content_use_email">
  748 + <div class="field-pair">
  749 + <input type="checkbox" name="email_notify_onsnatch" id="email_notify_onsnatch" #if $sickbeard.EMAIL_NOTIFY_ONSNATCH then "checked=\"checked\"" else ""# />
  750 + <label class="clearfix" for="email_notify_onsnatch">
  751 + <span class="component-title">Notify on Snatch</span>
  752 + <span class="component-desc">Send notification when we start a download?</span>
  753 + </label>
  754 + </div>
  755 + <div class="field-pair">
  756 + <input type="checkbox" name="email_notify_ondownload" id="email_notify_ondownload" #if $sickbeard.EMAIL_NOTIFY_ONDOWNLOAD then "checked=\"checked\"" else ""# />
  757 + <label class="clearfix" for="email_notify_ondownload">
  758 + <span class="component-title">Notify on Download</span>
  759 + <span class="component-desc">Send notification when we finish a download?</span>
  760 + </label>
  761 + </div>
  762 + <div class="field-pair">
  763 + <label class="nocheck clearfix">
  764 + <span class="component-title">SMTP Host</span>
  765 + <input type="text" name="email_host" id="email_host" value="$sickbeard.EMAIL_HOST" size="35" />
  766 + </label>
  767 + <label class="nocheck clearfix">
  768 + <span class="component-title">&nbsp;</span>
  769 + <span class="component-desc">Hostname of your SMTP email server.</span>
  770 + </label>
  771 + </div>
  772 + <div class="field-pair">
  773 + <label class="nocheck clearfix">
  774 + <span class="component-title">SMTP Port</span>
  775 + <input type="text" name="email_port" id="email_port" value="$sickbeard.EMAIL_PORT" size="35" />
  776 + </label>
  777 + <label class="nocheck clearfix">
  778 + <span class="component-title">&nbsp;</span>
  779 + <span class="component-desc">The port number used to connect to your SMTP host.</span>
  780 + </label>
  781 + </div>
  782 + <div class="field-pair">
  783 + <label class="nocheck clearfix">
  784 + <span class="component-title">SMTP From</span>
  785 + <input type="text" name="email_from" id="email_from" value="$sickbeard.EMAIL_FROM" size="35" />
  786 + </label>
  787 + <label class="nocheck clearfix">
  788 + <span class="component-title">&nbsp;</span>
  789 + <span class="component-desc">Sender email address; some hosts require a real address.</span>
  790 + </label>
  791 + </div>
  792 + <div class="field-pair">
  793 + <label class="nocheck clearfix">
  794 + <span class="component-title">Use TLS</span>
  795 + <input type="checkbox" name="email_tls" id="email_tls" #if $sickbeard.EMAIL_TLS then "checked=\"checked\"" else ""# size="35" />
  796 + </label>
  797 + <label class="nocheck clearfix">
  798 + <span class="component-title">&nbsp;</span>
  799 + <span class="component-desc">Check to use TLS encryption.</span>
  800 + </label>
  801 + </div>
  802 + <div class="field-pair">
  803 + <label class="nocheck clearfix">
  804 + <span class="component-title">SMTP User</span>
  805 + <input type="text" name="email_user" id="email_user" value="$sickbeard.EMAIL_USER" size="35" />
  806 + </label>
  807 + <label class="nocheck clearfix">
  808 + <span class="component-title">&nbsp;</span>
  809 + <span class="component-desc">(Optional) Your SMTP server username.</span>
  810 + </label>
  811 + </div>
  812 + <div class="field-pair">
  813 + <label class="nocheck clearfix">
  814 + <span class="component-title">SMTP Password</span>
  815 + <input type="password" name="email_password" id="email_password" value="$sickbeard.EMAIL_PASSWORD" size="35" />
  816 + </label>
  817 + <label class="nocheck clearfix">
  818 + <span class="component-title">&nbsp;</span>
  819 + <span class="component-desc">(Optional) Your SMTP server password.</span>
  820 + </label>
  821 + </div>
  822 + <div class="field-pair">
  823 + <label class="nocheck clearfix">
  824 + <span class="component-title">Global Email List</span>
  825 + <input type="text" name="email_list" id="email_list" value="$sickbeard.EMAIL_LIST" size="35" />
  826 + </label>
  827 + <label class="nocheck clearfix">
  828 + <span class="component-title">&nbsp;</span>
  829 + <span class="component-desc">All emails here receive notifications for ALL shows.</span>
  830 + </label>
  831 + </div>
  832 + <div class="field-pair">
  833 + <label class="nocheck clearfix">
  834 + <span class="component-title">Show Notification Lists</span>
  835 + <select name="email_show" id="email_show">
  836 + <option value="-1">-- Select a Show --</option>
  837 + </select>
  838 + </label>
  839 + <label class="nocheck clearfix">
  840 + <span class="component-title">&nbsp;</span>
  841 + <input style="margin-top: 3px;" type="text" name="email_show_list" id="email_show_list" size="35" />
  842 + </label>
  843 +
  844 + <label class="nocheck clearfix">
  845 + <span class="component-title">&nbsp;</span>
  846 + <span class="component-desc">Configure per show notifications here.</span>
  847 + </label>
  848 + </div>
  849 +
  850 + <div class="testNotification" id="testEmail-result">Click below to test.</div>
  851 + <input type="button" value="Test Email" id="testEmail" />
  852 + <input type="submit" class="config_submitter" value="Save Changes" />
  853 + </div><!-- /content_use_email //-->
  854 + </fieldset>
  855 + </div>
733 856
734 857 <div class="component-group clearfix">
735 858 <div class="component-group-desc">
3  data/js/config.js
@@ -45,4 +45,5 @@ function config_success(){
45 45 $(this).next().remove();
46 46 $(this).show();
47 47 });
48   -}
  48 + $('#email_show').trigger('notify');
  49 +}
65 data/js/configNotifications.js
... ... @@ -1,5 +1,6 @@
1 1 $(document).ready(function(){
2 2 var loading = '<img src="'+sbRoot+'/images/loading16.gif" height="16" width="16" />';
  3 + var notify_data = null;
3 4
4 5 $('#testGrowl').click(function(){
5 6 $('#testGrowl-result').html(loading);
@@ -64,7 +65,41 @@ $(document).ready(function(){
64 65 $.get(sbRoot+"/home/testLibnotify",
65 66 function(message){ $('#testLibnotify-result').html(message); });
66 67 });
67   -
  68 +
  69 + $('#testEmail').click(function(){
  70 + var status = $('#testEmail-result');
  71 + status.html(loading);
  72 + var host = $("#email_host").val();
  73 + host = host.length > 0 ? host : null;
  74 + var port = $("#email_port").val();
  75 + port = port.length > 0 ? port : null;
  76 + var tls = $("#email_tls").attr('checked') != undefined ? 1 : 0;
  77 + var from = $("#email_from").val();
  78 + from = from.length > 0 ? from : 'root@localhost';
  79 + var user = $("#email_user").val().trim();
  80 + var pwd = $("#email_password").val();
  81 +
  82 + var err = '';
  83 + if(host == null)
  84 + err += '<li style="color: red;">You must specify an SMTP hostname!</li>';
  85 + if(port == null)
  86 + err += '<li style="color: red;">You must specify an SMTP port!</li>';
  87 + else if(port.match(/^\d+$/) == null || parseInt(port) > 65535)
  88 + err += '<li style="color: red;">SMTP port must be between 0 and 65535!</li>';
  89 + if(err.length > 0) {
  90 + err = '<ol>' + err + '</ol>';
  91 + status.html(err);
  92 + } else {
  93 + var to = prompt('Enter an email address to send the test to:', null);
  94 + if(to == null || to.length == 0 || to.match(/.*@.*/) == null)
  95 + status.html('<p style="color: red;">You must provide a recipient email address!</p>');
  96 + else {
  97 + $.get(sbRoot+"/home/testEmail", {host: host, port: port, smtp_from: from, use_tls: tls, user: user, pwd: pwd, to: to},
  98 + function(msg){ $('#testEmail-result').html(msg); });
  99 + }
  100 + }
  101 + });
  102 +
68 103 $('#twitterStep1').click(function(){
69 104 $('#testTwitter-result').html(loading);
70 105 var twitter1_result = $.get(sbRoot+"/home/twitterStep1", function (data){window.open(data)})
@@ -142,4 +177,32 @@ $(document).ready(function(){
142 177 var nma_result = $.get(sbRoot+"/home/testNMA", {'nma_api': nma_api, 'nma_priority': nma_priority},
143 178 function (data){ $('#testNMA-result').html(data); });
144 179 });
  180 +
  181 + $('#email_show').change(function(){
  182 + var key = parseInt($('#email_show').val());
  183 + $('#email_show_list').val(key >= 0 ? notify_data[key.toString()].list : '');
  184 + });
  185 +
  186 + // Update the internal data struct anytime settings are saved to the server
  187 + $('#email_show').bind('notify', function(){ load_show_notify_lists(); });
  188 +
  189 + function load_show_notify_lists() {
  190 + $.get(sbRoot+"/home/loadShowNotifyLists", function(data) {
  191 + var list = $.parseJSON(data);
  192 + notify_data = list;
  193 + if(list['_size'] == 0)
  194 + return;
  195 + var html = '<option value="-1">-- Select --</option>';
  196 + for(var s in list) {
  197 + if(s.charAt(0) == '_')
  198 + continue;
  199 + html += '<option value="' + list[s].id + '">' + $('<div/>').text(list[s].name).html() + '</option>';
  200 + }
  201 + $('#email_show').html(html);
  202 + $('#email_show_list').val('');
  203 + });
  204 + }
  205 + // Load the per show notify lists everytime this page is loaded
  206 + load_show_notify_lists();
145 207 });
  208 +
35 sickbeard/__init__.py
@@ -227,6 +227,17 @@
227 227 PROWL_API = None
228 228 PROWL_PRIORITY = 0
229 229
  230 +USE_EMAIL = False
  231 +EMAIL_NOTIFY_ONSNATCH = False
  232 +EMAIL_NOTIFY_ONDOWNLOAD = False
  233 +EMAIL_HOST = None
  234 +EMAIL_PORT = 25
  235 +EMAIL_TLS = False
  236 +EMAIL_USER = None
  237 +EMAIL_PASSWORD = None
  238 +EMAIL_FROM = None
  239 +EMAIL_LIST = None
  240 +
230 241 USE_TWITTER = False
231 242 TWITTER_NOTIFY_ONSNATCH = False
232 243 TWITTER_NOTIFY_ONDOWNLOAD = False
@@ -406,6 +417,7 @@ def initialize(consoleLogging=True):
406 417 RENAME_EPISODES, properFinderScheduler, PROVIDER_ORDER, autoPostProcesserScheduler, \
407 418 NAMING_EP_NAME, NAMING_SEP_TYPE, NAMING_USE_PERIODS, WOMBLE, \
408 419 NZBSRUS, NZBSRUS_UID, NZBSRUS_HASH, NAMING_QUALITY, providerList, newznabProviderList, \
  420 + USE_EMAIL, EMAIL_HOST, EMAIL_PORT, EMAIL_TLS, EMAIL_USER, EMAIL_PASSWORD, EMAIL_FROM, EMAIL_NOTIFY_ONSNATCH, EMAIL_NOTIFY_ONDOWNLOAD, EMAIL_LIST, \
409 421 NAMING_DATES, EXTRA_SCRIPTS, USE_TWITTER, TWITTER_USERNAME, TWITTER_PASSWORD, TWITTER_PREFIX, \
410 422 USE_NOTIFO, NOTIFO_USERNAME, NOTIFO_APISECRET, NOTIFO_NOTIFY_ONDOWNLOAD, NOTIFO_NOTIFY_ONSNATCH, \
411 423 USE_BOXCAR, BOXCAR_USERNAME, BOXCAR_PASSWORD, BOXCAR_NOTIFY_ONDOWNLOAD, BOXCAR_NOTIFY_ONSNATCH, \
@@ -615,6 +627,17 @@ def initialize(consoleLogging=True):
615 627 PROWL_API = check_setting_str(CFG, 'Prowl', 'prowl_api', '')
616 628 PROWL_PRIORITY = check_setting_str(CFG, 'Prowl', 'prowl_priority', "0")
617 629
  630 + USE_EMAIL = bool(check_setting_int(CFG, 'Email', 'use_email', 0))
  631 + EMAIL_NOTIFY_ONSNATCH = bool(check_setting_int(CFG, 'Email', 'email_notify_onsnatch', 0))
  632 + EMAIL_NOTIFY_ONDOWNLOAD = bool(check_setting_int(CFG, 'Email', 'email_notify_ondownload', 0))
  633 + EMAIL_HOST = check_setting_str(CFG, 'Email', 'email_host', '')
  634 + EMAIL_PORT = check_setting_int(CFG, 'Email', 'email_port', 25)
  635 + EMAIL_TLS = bool(check_setting_int(CFG, 'Email', 'email_tls', 0))
  636 + EMAIL_USER = check_setting_str(CFG, 'Email', 'email_user', '')
  637 + EMAIL_PASSWORD = check_setting_str(CFG, 'Email', 'email_password', '')
  638 + EMAIL_FROM = check_setting_str(CFG, 'Email', 'email_from', '')
  639 + EMAIL_LIST = check_setting_str(CFG, 'Email', 'email_list', '')
  640 +
618 641 USE_TWITTER = bool(check_setting_int(CFG, 'Twitter', 'use_twitter', 0))
619 642 TWITTER_NOTIFY_ONSNATCH = bool(check_setting_int(CFG, 'Twitter', 'twitter_notify_onsnatch', 0))
620 643 TWITTER_NOTIFY_ONDOWNLOAD = bool(check_setting_int(CFG, 'Twitter', 'twitter_notify_ondownload', 0))
@@ -1151,6 +1174,18 @@ def save_config():
1151 1174 new_config['Prowl']['prowl_api'] = PROWL_API
1152 1175 new_config['Prowl']['prowl_priority'] = PROWL_PRIORITY
1153 1176
  1177 + new_config['Email'] = {}
  1178 + new_config['Email']['use_email'] = int(USE_EMAIL)
  1179 + new_config['Email']['email_notify_onsnatch'] = int(EMAIL_NOTIFY_ONSNATCH)
  1180 + new_config['Email']['email_notify_ondownload'] = int(EMAIL_NOTIFY_ONDOWNLOAD)
  1181 + new_config['Email']['email_host'] = EMAIL_HOST
  1182 + new_config['Email']['email_port'] = int(EMAIL_PORT)
  1183 + new_config['Email']['email_tls'] = int(EMAIL_TLS)
  1184 + new_config['Email']['email_user'] = EMAIL_USER
  1185 + new_config['Email']['email_password'] = EMAIL_PASSWORD
  1186 + new_config['Email']['email_from'] = EMAIL_FROM
  1187 + new_config['Email']['email_list'] = EMAIL_LIST
  1188 +
1154 1189 new_config['Twitter'] = {}
1155 1190 new_config['Twitter']['use_twitter'] = int(USE_TWITTER)
1156 1191 new_config['Twitter']['twitter_notify_onsnatch'] = int(TWITTER_NOTIFY_ONSNATCH)
9 sickbeard/databases/mainDB.py
@@ -398,3 +398,12 @@ def execute(self):
398 398 self.connection.action("UPDATE tv_shows SET air_by_date = ? WHERE tvdb_id = ?", [1, cur_show["tvdb_id"]])
399 399
400 400 self.incDBVersion()
  401 +
  402 +class AddEmailSubscriptionTable(FixAirByDateSetting):
  403 + def test(self):
  404 + return self.hasColumn("tv_shows", "notify_list")
  405 +
  406 + def execute(self):
  407 + self.addColumn('tv_shows', 'notify_list', 'TEXT', None)
  408 + self.incDBVersion()
  409 +
3  sickbeard/notifiers/__init__.py
@@ -32,6 +32,7 @@
32 32 import trakt
33 33 import pytivo
34 34 import nma
  35 +import emailnotify
35 36
36 37 from sickbeard.common import *
37 38
@@ -49,6 +50,7 @@
49 50 trakt_notifier = trakt.TraktNotifier()
50 51 pytivo_notifier = pytivo.pyTivoNotifier()
51 52 nma_notifier = nma.NMA_Notifier()
  53 +email_notifier = emailnotify.EmailNotifier()
52 54
53 55 notifiers = [
54 56 # Libnotify notifier goes first because it doesn't involve blocking on
@@ -66,6 +68,7 @@
66 68 trakt_notifier,
67 69 pytivo_notifier,
68 70 nma_notifier,
  71 + email_notifier,
69 72 ]
70 73
71 74 def notify_download(ep_name):
133 sickbeard/notifiers/emailnotify.py
... ... @@ -0,0 +1,133 @@
  1 +# Author: Derek Battams <derek@battams.ca>
  2 +# URL: http://code.google.com/p/sickbeard/
  3 +#
  4 +# This file is part of Sick Beard.
  5 +#
  6 +# Sick Beard is free software: you can redistribute it and/or modify
  7 +# it under the terms of the GNU General Public License as published by
  8 +# the Free Software Foundation, either version 3 of the License, or
  9 +# (at your option) any later version.
  10 +#
  11 +# Sick Beard is distributed in the hope that it will be useful,
  12 +# but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14 +# GNU General Public License for more details.
  15 +#
  16 +# You should have received a copy of the GNU General Public License
  17 +# along with Sick Beard. If not, see <http://www.gnu.org/licenses/>.
  18 +
  19 +import smtplib
  20 +from email.mime.text import MIMEText
  21 +
  22 +import sickbeard
  23 +
  24 +from sickbeard import logger
  25 +from sickbeard import db
  26 +from sickbeard.exceptions import ex
  27 +from sickbeard import config
  28 +
  29 +class EmailNotifier:
  30 + def __init__(self):
  31 + self.last_err = None
  32 +
  33 + def test_notify(self, host, port, smtp_from, use_tls, user, pwd, to):
  34 + msg = MIMEText('This is a test message from Sick Beard. If you\'re reading this, the test succeeded!')
  35 + msg['Subject'] = 'Test Message from Sick Beard'
  36 + msg['From'] = smtp_from
  37 + msg['To'] = to
  38 + return self._sendmail(host, port, smtp_from, use_tls, user, pwd, [to], msg, True)
  39 +
  40 + def notify_snatch(self, ep_name, title="Snatched:"):
  41 + """
  42 + Send a notification that an episode was snatched
  43 +
  44 + ep_name: The name of the episode that was snatched
  45 + title: The title of the notification (optional)
  46 + """
  47 + if sickbeard.EMAIL_NOTIFY_ONSNATCH:
  48 + show = self._parseEp(ep_name)
  49 + to = self._generate_recepients(show)
  50 + if len(to) == 0:
  51 + logger.log('Skipping email notify because there are no configured recepients!', logger.WARN)
  52 + else:
  53 + msg = MIMEText("'%s' snatched!" % ep_name)
  54 + msg['Subject'] = 'Sick Beard has snatched a new episode!'
  55 + msg['From'] = sickbeard.EMAIL_FROM
  56 + msg['To'] = ','.join(to)
  57 + if self._sendmail(sickbeard.EMAIL_HOST, sickbeard.EMAIL_PORT, sickbeard.EMAIL_FROM, sickbeard.EMAIL_TLS, sickbeard.EMAIL_USER, sickbeard.EMAIL_PASSWORD, to, msg):
  58 + logger.log("Snatch notification sent to [%s] for '%s'" % (to, ep_name), logger.DEBUG)
  59 + else:
  60 + logger.log("Snatch notification ERROR: %s" % self.last_err, logger.ERROR)
  61 +
  62 + def notify_download(self, ep_name, title="Completed:"):
  63 + """
  64 + Send a notification that an episode was downloaded
  65 +
  66 + ep_name: The name of the episode that was downloaded
  67 + title: The title of the notification (optional)
  68 + """
  69 + if sickbeard.EMAIL_NOTIFY_ONDOWNLOAD:
  70 + show = self._parseEp(ep_name)
  71 + to = self._generate_recepients(show)
  72 + if len(to) == 0:
  73 + logger.log('Skipping email notify because there are no configured recepients!', logger.WARN)
  74 + else:
  75 + msg = MIMEText("'%s' downloaded!" % ep_name)
  76 + msg['Subject'] = 'Sick Beard has downloaded a new episode!'
  77 + msg['From'] = sickbeard.EMAIL_FROM
  78 + msg['To'] = ','.join(to)
  79 + if self._sendmail(sickbeard.EMAIL_HOST, sickbeard.EMAIL_PORT, sickbeard.EMAIL_FROM, sickbeard.EMAIL_TLS, sickbeard.EMAIL_USER, sickbeard.EMAIL_PASSWORD, to, msg):
  80 + logger.log("Download notification sent to [%s] for '%s'" % (to, ep_name), logger.DEBUG)
  81 + else:
  82 + logger.log("Download notification ERROR: %s" % self.last_err, logger.ERROR)
  83 +
  84 + def _generate_recepients(self, show):
  85 + addrs = []
  86 +
  87 + # Grab the global recipients
  88 + for addr in sickbeard.EMAIL_LIST.split(','):
  89 + if(len(addr.strip()) > 0):
  90 + addrs.append(addr)
  91 +
  92 + # Grab the recipients for the show
  93 + mydb = db.DBConnection()
  94 + for s in show:
  95 + for subs in mydb.select("SELECT notify_list FROM tv_shows WHERE show_name = ?", (s,)):
  96 + for addr in subs['notify_list'].split(','):
  97 + if(len(addr.strip()) > 0):
  98 + addrs.append(addr)
  99 +
  100 + addrs = set(addrs)
  101 + logger.log('Notification recepients: %s' % addrs, logger.DEBUG)
  102 + return addrs
  103 +
  104 + def _sendmail(self, host, port, smtp_from, use_tls, user, pwd, to, msg, smtpDebug=False):
  105 + logger.log('HOST: %s; PORT: %s; FROM: %s, TLS: %s, USER: %s, PWD: %s, TO: %s' % (host, port, smtp_from, use_tls, user, pwd, to), logger.DEBUG)
  106 + srv = smtplib.SMTP(host, int(port))
  107 + if smtpDebug:
  108 + srv.set_debuglevel(1)
  109 + try:
  110 + if (use_tls == '1' or use_tls == True) or (len(user) > 0 and len(pwd) > 0):
  111 + srv.ehlo()
  112 + logger.log('Sent initial EHLO command!', logger.DEBUG)
  113 + if use_tls == '1' or use_tls == True:
  114 + srv.starttls()
  115 + logger.log('Sent STARTTLS command!', logger.DEBUG)
  116 + if len(user) > 0 and len(pwd) > 0:
  117 + srv.login(user, pwd)
  118 + logger.log('Sent LOGIN command!', logger.DEBUG)
  119 + srv.sendmail(smtp_from, to, msg.as_string())
  120 + srv.quit()
  121 + return True
  122 + except Exception as e:
  123 + self.last_err = '%s' % e
  124 + return False
  125 +
  126 + def _parseEp(self, ep_name):
  127 + sep = config.naming_sep_type[sickbeard.NAMING_SEP_TYPE]
  128 + titles = ep_name.split(sep)
  129 + titles.sort(key=len, reverse=True)
  130 + logger.log("TITLES: %s" % titles, logger.DEBUG)
  131 + return titles
  132 +
  133 +notifier = EmailNotifier
71 sickbeard/webserve.py
@@ -910,6 +910,12 @@ def savePostProcessing(self, season_folders_format=None, naming_show_name=None,
910 910
911 911 sickbeard.metadata_provider_dict['XBMC'].set_config(xbmc_data)
912 912 sickbeard.metadata_provider_dict['MediaBrowser'].set_config(mediabrowser_data)
  913 +
  914 +
  915 +
  916 +
  917 +
  918 +
913 919 sickbeard.metadata_provider_dict['Synology'].set_config(synology_data)
914 920 sickbeard.metadata_provider_dict['Sony PS3'].set_config(sony_ps3_data)
915 921 sickbeard.metadata_provider_dict['WDTV'].set_config(wdtv_data)
@@ -1214,7 +1220,9 @@ def saveNotifications(self, use_xbmc=None, xbmc_notify_onsnatch=None, xbmc_notif
1214 1220 use_trakt=None, trakt_username=None, trakt_password=None, trakt_api=None,
1215 1221 use_pytivo=None, pytivo_notify_onsnatch=None, pytivo_notify_ondownload=None, pytivo_update_library=None,
1216 1222 pytivo_host=None, pytivo_share_name=None, pytivo_tivo_name=None,
1217   - use_nma=None, nma_notify_onsnatch=None, nma_notify_ondownload=None, nma_api=None, nma_priority=0 ):
  1223 + use_nma=None, nma_notify_onsnatch=None, nma_notify_ondownload=None, nma_api=None, nma_priority=0, use_email=None,
  1224 + email_notify_onsnatch=None, email_notify_ondownload=None, email_host=None, email_port=25, email_from=None,
  1225 + email_tls=None, email_user=None, email_password=None, email_list=None, email_show_list=None, email_show=None ):
1218 1226
1219 1227 results = []
1220 1228
@@ -1292,6 +1300,31 @@ def saveNotifications(self, use_xbmc=None, xbmc_notify_onsnatch=None, xbmc_notif
1292 1300 else:
1293 1301 use_prowl = 0
1294 1302
  1303 + if email_notify_onsnatch == "on":
  1304 + email_notify_onsnatch = 1
  1305 + else:
  1306 + email_notify_onsnatch = 0
  1307 +
  1308 + if email_notify_ondownload == "on":
  1309 + email_notify_ondownload = 1
  1310 + else:
  1311 + email_notify_ondownload = 0
  1312 +
  1313 + if use_email == "on":
  1314 + use_email = 1
  1315 + else:
  1316 + use_email = 0
  1317 +
  1318 + if email_tls == "on":
  1319 + email_tls = 1
  1320 + else:
  1321 + email_tls = 0
  1322 +
  1323 + # Update per show notifications, if provided
  1324 + if int(email_show) >= 0:
  1325 + mydb = db.DBConnection()
  1326 + mydb.action("UPDATE tv_shows SET notify_list = ? WHERE show_id = ?", (email_show_list, int(email_show)))
  1327 +
1295 1328 if twitter_notify_onsnatch == "on":
1296 1329 twitter_notify_onsnatch = 1
1297 1330 else:
@@ -1339,6 +1372,7 @@ def saveNotifications(self, use_xbmc=None, xbmc_notify_onsnatch=None, xbmc_notif
1339 1372 else:
1340 1373 pushover_notify_onsnatch = 0
1341 1374
  1375 +
1342 1376 if pushover_notify_ondownload == "on":
1343 1377 pushover_notify_ondownload = 1
1344 1378 else:
@@ -1428,6 +1462,17 @@ def saveNotifications(self, use_xbmc=None, xbmc_notify_onsnatch=None, xbmc_notif
1428 1462 sickbeard.PROWL_API = prowl_api
1429 1463 sickbeard.PROWL_PRIORITY = prowl_priority
1430 1464
  1465 + sickbeard.USE_EMAIL = use_email
  1466 + sickbeard.EMAIL_NOTIFY_ONSNATCH = email_notify_onsnatch
  1467 + sickbeard.EMAIL_NOTIFY_ONDOWNLOAD = email_notify_ondownload
  1468 + sickbeard.EMAIL_HOST = email_host
  1469 + sickbeard.EMAIL_PORT = email_port
  1470 + sickbeard.EMAIL_FROM = email_from
  1471 + sickbeard.EMAIL_TLS = email_tls
  1472 + sickbeard.EMAIL_USER = email_user
  1473 + sickbeard.EMAIL_PASSWORD = email_password
  1474 + sickbeard.EMAIL_LIST = email_list
  1475 +
1431 1476 sickbeard.USE_TWITTER = use_twitter
1432 1477 sickbeard.TWITTER_NOTIFY_ONSNATCH = twitter_notify_onsnatch
1433 1478 sickbeard.TWITTER_NOTIFY_ONDOWNLOAD = twitter_notify_ondownload
@@ -1783,6 +1828,7 @@ def finishAddShow():
1783 1828
1784 1829 # blanket policy - if the dir exists you should have used "add existing show" numbnuts
1785 1830 if ek.ek(os.path.isdir, show_dir) and not fullShowPath:
  1831 +
1786 1832 ui.notifications.error("Unable to add show", "Folder "+show_dir+" exists already")
1787 1833 redirect('/home/addShows/existingShows')
1788 1834
@@ -2079,6 +2125,29 @@ def testPushover(self, userKey=None):
2079 2125 return "Error sending Pushover notification"
2080 2126
2081 2127 @cherrypy.expose
  2128 + def loadShowNotifyLists(self):
  2129 + cherrypy.response.headers['Cache-Control'] = "max-age=0,no-cache,no-store"
  2130 +
  2131 + mydb = db.DBConnection()
  2132 + rows = mydb.select("SELECT show_id, show_name, notify_list FROM tv_shows")
  2133 + data = {}
  2134 + size = 0
  2135 + for r in rows:
  2136 + data[r['show_id']] = {'id': r['show_id'], 'name': r['show_name'], 'list': r['notify_list']}
  2137 + size += 1
  2138 + data['_size'] = size
  2139 + return json.dumps(data)
  2140 +
  2141 + @cherrypy.expose
  2142 + def testEmail(self, host=None, port=None, smtp_from=None, use_tls=None, user=None, pwd=None, to=None):
  2143 + cherrypy.response.headers['Cache-Control'] = "max-age=0,no-cache,no-store"
  2144 +
  2145 + if notifiers.email_notifier.test_notify(host, port, smtp_from, use_tls, user, pwd, to):
  2146 + return 'Test email sent successfully! Check inbox.'
  2147 + else:
  2148 + return 'ERROR: %s' % notifiers.email_notifier.last_err
  2149 +
  2150 + @cherrypy.expose
2082 2151 def twitterStep1(self):
2083 2152 cherrypy.response.headers['Cache-Control'] = "max-age=0,no-cache,no-store"
2084 2153

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.