You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

245 lines
7.6 KiB

#!/usr/bin/python -OO
# Copyright 2008-2010 The SABnzbd-Team <team@sabnzbd.org>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
"""
sabnzbd.emailer - Send notification emails
"""
#------------------------------------------------------------------------------
from sabnzbd.utils import ssmtplib
import smtplib
import os
import logging
import re
import time
import glob
from sabnzbd.constants import *
import sabnzbd
from sabnzbd.misc import to_units, split_host
from sabnzbd.encoding import LatinFilter
import sabnzbd.cfg as cfg
from sabnzbd.lang import T, Ta
################################################################################
# EMAIL_SEND
#
#
################################################################################
def send(message):
""" Send message if message non-empty and email-parms are set """
if not message.strip('\n\r\t '):
return "Skipped empty message"
if cfg.email_server() and cfg.email_to() and cfg.email_from():
failure = T('error-mailSend')
server, port = split_host(cfg.email_server())
if not port:
port = 25
logging.info("Connecting to server %s:%s", server, port)
try:
mailconn = ssmtplib.SMTP_SSL(server, port)
mailconn.ehlo()
logging.info("Connected to server %s:%s", server, port)
except Exception, errorcode:
if errorcode[0]:
# Non SSL mail server
logging.debug("Non-SSL mail server detected " \
"reconnecting to server %s:%s", server, port)
try:
mailconn = smtplib.SMTP(server, port)
mailconn.ehlo()
except:
logging.error(Ta('error-mailNoConn'))
return failure
else:
logging.error(Ta('error-mailNoConn'))
return failure
# TLS support
if mailconn.ehlo_resp:
m = re.search('STARTTLS', mailconn.ehlo_resp, re.IGNORECASE)
if m:
logging.debug("TLS mail server detected")
try:
mailconn.starttls()
mailconn.ehlo()
except:
logging.error(Ta('error-mailTLS'))
return failure
# Authentication
if (cfg.email_account() != "") and (cfg.email_pwd() != ""):
try:
mailconn.login(cfg.email_account(), cfg.email_pwd())
except:
logging.error(Ta('error-mailAuth'))
return failure
message = _prepare_message(message)
try:
mailconn.sendmail(cfg.email_from(), cfg.email_to(), message)
except:
logging.error(Ta('error-mailSend'))
return failure
try:
mailconn.close()
except:
logging.warning(Ta('warn-noEmailClose'))
logging.info("Notification e-mail succesfully sent")
return T('msg-emailOK')
################################################################################
# email_endjob
#
#
################################################################################
from Cheetah.Template import Template
def send_with_template(prefix, parm):
""" Send an email using template """
parm['to'] = cfg.email_to.get_string()
parm['from'] = cfg.email_from()
parm['date'] = time.strftime("%a, %d %b %Y %H:%M:%S +0000", time.gmtime())
lst = []
path = cfg.email_dir.get_path()
if path and os.path.exists(path):
try:
lst = glob.glob(os.path.join(path, '%s-*.tmpl' % prefix))
except:
logging.error(Ta('error-mailTempl@1'), path)
else:
path = os.path.join(sabnzbd.DIR_PROG, DEF_LANGUAGE)
tpath = os.path.join(path, '%s-%s.tmpl' % (prefix, cfg.language()))
if os.path.exists(tpath):
lst = [tpath]
else:
lst = [os.path.join(path, '%s-us-en.tmpl' % prefix)]
ret = "No templates found"
for temp in lst:
if os.access(temp, os.R_OK):
source = _decode_file(temp)
message = Template(source=source,
searchList=[parm],
filter=LatinFilter,
compilerSettings={'directiveStartToken': '<!--#',
'directiveEndToken': '#-->'})
ret = send(message.respond())
del message
return ret
def endjob(filename, msgid, cat, status, path, bytes, stages, script, script_output, script_ret):
""" Send end-of-job email """
# Translate the stage names
xstages = {}
for stage in stages:
xstages[T('stage-'+stage.lower())] = stages[stage]
parm = {}
parm['status'] = status
parm['name'] = filename
parm['path'] = path
parm['msgid'] = str(msgid)
parm['stages'] = xstages
parm['script'] = script
parm['script_output'] = script_output
parm['script_ret'] = script_ret
parm['cat'] = cat
parm['size'] = "%sB" % to_units(bytes)
parm['end_time'] = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))
return send_with_template('email', parm)
def rss_mail(feed, jobs):
""" Send notification email containing list of files """
parm = {'amount' : len(jobs), 'feed' : feed, 'jobs' : jobs}
return send_with_template('rss', parm)
################################################################################
# EMAIL_DISKFULL
#
#
################################################################################
def diskfull():
""" Send email about disk full, no templates """
if cfg.email_full():
return send(T('email-full@2') % (cfg.email_to.get_string(), cfg.email_from()))
else:
return ""
################################################################################
def _decode_file(path):
""" Return content of file in Unicode string
using encoding as specified in the file.
Work-around for dumb handling of decoding by Cheetah.
"""
fp = open(path, 'r')
txt = fp.readline()
m = re.search(r'#encoding[:\s]+(\S+)', txt)
if m and m.group(1):
encoding = m.group(1)
else:
encoding = 'latin-1'
source = fp.read()
fp.close()
return source.decode(encoding)
################################################################################
from email.message import Message
RE_HEADER = re.compile(r'^([^:]+):(.*)')
def _prepare_message(txt):
""" Do the proper message encodings
"""
msg = Message()
msg.set_charset('UTF-8')
payload = []
body = False
for line in txt.encode('utf-8').split('\n'):
if not line:
body = True
if body:
payload.append(line)
else:
m = RE_HEADER.search(line)
if m:
msg.add_header(m.group(1).strip(), m.group(2).strip())
msg.set_payload('\n'.join(payload), 'UTF-8')
return msg.as_string()