Email sending: Allow user to stop email jobs (note that stopping may not actually prevent the email from being sent, depending on when the stop happens). Also automatically abort email sending if it takes longer than 15mins. Fixes #795960 (E-mail task hangs)

This commit is contained in:
Kovid Goyal 2011-06-12 15:16:56 -06:00
parent 685ef02000
commit db595796fc

View File

@ -9,6 +9,7 @@ __docformat__ = 'restructuredtext en'
import os, socket, time
from binascii import unhexlify
from functools import partial
from threading import Thread
from itertools import repeat
from calibre.utils.smtp import (compose_mail, sendmail, extract_email_address,
@ -22,9 +23,30 @@ from calibre.library.save_to_disk import get_components
from calibre.utils.config import tweaks
from calibre.gui2.threaded_jobs import ThreadedJob
class Worker(Thread):
def __init__(self, func, args):
Thread.__init__(self)
self.daemon = True
self.exception = self.tb = None
self.func, self.args = func, args
def run(self):
#time.sleep(1000)
try:
self.func(*self.args)
except Exception as e:
import traceback
self.exception = e
self.tb = traceback.format_exc()
finally:
self.func = self.args = None
class Sendmail(object):
MAX_RETRIES = 1
TIMEOUT = 15 * 60 # seconds
def __init__(self):
self.calculate_rate_limit()
@ -42,22 +64,32 @@ class Sendmail(object):
abort=None, notifications=None):
try_count = 0
while try_count <= self.MAX_RETRIES:
while True:
if try_count > 0:
log('\nRetrying in %d seconds...\n' %
self.rate_limit)
try:
self.sendmail(attachment, aname, to, subject, text, log)
try_count = self.MAX_RETRIES
log('Email successfully sent')
except:
worker = Worker(self.sendmail,
(attachment, aname, to, subject, text, log))
worker.start()
start_time = time.time()
while worker.is_alive():
worker.join(0.2)
if abort.is_set():
log('Sending aborted by user')
return
if try_count == self.MAX_RETRIES:
raise
log.exception('\nSending failed...\n')
if time.time() - start_time > self.TIMEOUT:
log('Sending timed out')
raise Exception(
'Sending email %r to %r timed out, aborting'% (subject,
to))
if worker.exception is None:
log('Email successfully sent')
return
log.error('\nSending failed...\n')
log.debug(worker.tb)
try_count += 1
if try_count > self.MAX_RETRIES:
raise worker.exception
def sendmail(self, attachment, aname, to, subject, text, log):
while time.time() - self.last_send_time <= self.rate_limit:
@ -90,7 +122,7 @@ def send_mails(jobnames, callback, attachments, to_s, subjects,
attachments, to_s, subjects, texts, attachment_names):
description = _('Email %s to %s') % (name, to)
job = ThreadedJob('email', description, gui_sendmail, (attachment, aname, to,
subject, text), {}, callback, killable=False)
subject, text), {}, callback)
job_manager.run_threaded_job(job)