mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
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:
parent
685ef02000
commit
db595796fc
@ -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)
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user