diff --git a/index.html b/index.html
index 57bebba..e4ca1f2 100644
--- a/index.html
+++ b/index.html
@@ -449,10 +449,10 @@ while (await new Promise(o => setTimeout(o, 1000, true))) {
$('#timezoneLabel').innerText = Temporal.Now.zonedDateTimeISO(locale.timezone).toLocaleString(locale.name);
let { done, skip, email, subject, recipient } = await Rpc2.invoke('progress').catch(() => new Object());
- let index = done + skip;
let limit = minor || major - 1;
let chunk = $('#chunksize').valueAsNumber;
let total = $('#slice').checked ? Math.min(chunk, limit - chunk * $('#offset').valueAsNumber) : limit;
+ let index = $('#slice').checked ? done : done + skip;
$('#progressLabel').innerText = `${parseFloat(index / total * 100).toFixed(2)}% (${index}/${total})`;
$('#subjectLabel').innerText = subject ?? '';
@@ -463,7 +463,7 @@ while (await new Promise(o => setTimeout(o, 1000, true))) {
let rate = index / uptime;
let remaining = index ? Math.floor((total - index) / rate) : 0;
- $('#remainingLabel').innerText = remaining ? `${Temporal.Duration.from({ seconds: remaining }).round({ largestUnit: 'hours' }).toLocaleString('en')} (${rate.toFixed(2)}/min)` : '';
+ $('#remainingLabel').innerText = remaining >= 0 ? `${Temporal.Duration.from({ seconds: remaining }).round({ largestUnit: 'hours' }).toLocaleString('en')} (${rate.toFixed(2)}/min)` : '';
break;
case 'STANDBY':
$('#send > span.text').innerText = 'Resume';
diff --git a/main.py b/main.py
index 6cc1eac..49fd1d5 100644
--- a/main.py
+++ b/main.py
@@ -393,12 +393,14 @@ def main(driver: Chrome, logger = logging.getLogger('main')):
try:
flow.react(Wait)
attempts += 1
- email = cell(index, column.email).value
-
try: code = str(cell(index, column.code).value)
except ValueError: code = None
occurrence.setdefault(code, 0)
+ if (target := cell(index, column.email).value) is None or not (email := str(target).strip()):
+ logger.warning("[%d/%d] Not an email address; skipping", index-1, limit-1)
+ raise Skip()
+
if attempts > parameters['attempts']:
logger.warning("[%d/%d] Exhausted all allowed attempts; skipping", index-1, limit-1)
raise Skip()
@@ -416,7 +418,7 @@ def main(driver: Chrome, logger = logging.getLogger('main')):
case o if o is None:
pass
case o if o > 0 and code is None:
- logger.error("Column '%s' contains invalid ID; could not enforce spam control", column.code)
+ logger.error("Column '%s' cannot be used for spam control", column.code)
raise Cancel()
case o if o > 0 and occurrence[code] >= o:
logger.info("[%d/%d] No Spam! Skipping '%s'", index-1, limit-1, email)
@@ -432,7 +434,7 @@ def main(driver: Chrome, logger = logging.getLogger('main')):
click(mails[0].find_element(By.CSS_SELECTOR, "button[data-action='close']"), wait=False)
click("div.modal-footer button[data-action='delete']", wait=False)
except Exception as e:
- logger.warning('Unable to close off email compose windows', exc_info=e)
+ logger.debug('Unable to close off email compose windows', exc_info=e)
break
flow.allow(Cancel)