1
0
mirror of https://github.com/craigerl/aprsd.git synced 2025-08-04 06:22:25 -04:00

Wrap all imap calls with try except blocks

The Email Thread has been unstable due to some IMAP servers
being crap.  This patch wraps more of the imap server calls
in try except blocks to try and trap errors.
This commit is contained in:
Hemna 2021-02-03 11:00:20 -05:00
parent 47135c6086
commit a5cc274ff5

View File

@ -184,7 +184,12 @@ def parse_email(msgid, data, server):
else: else:
from_addr = "noaddr" from_addr = "noaddr"
LOG.debug("Got a message from '{}'".format(from_addr)) LOG.debug("Got a message from '{}'".format(from_addr))
m = server.fetch([msgid], ["RFC822"]) try:
m = server.fetch([msgid], ["RFC822"])
except Exception as e:
LOG.exception("Couldn't fetch email from server in parse_email", e)
return
msg = email.message_from_string(m[msgid][b"RFC822"].decode(errors="ignore")) msg = email.message_from_string(m[msgid][b"RFC822"].decode(errors="ignore"))
if msg.is_multipart(): if msg.is_multipart():
text = "" text = ""
@ -324,7 +329,12 @@ def resend_email(count, fromcall):
LOG.exception("Failed to Connect to IMAP. Cannot resend email ", e) LOG.exception("Failed to Connect to IMAP. Cannot resend email ", e)
return return
messages = server.search(["SINCE", today]) try:
messages = server.search(["SINCE", today])
except Exception as e:
LOG.exception("Couldn't search for emails in resend_email ", e)
return
# LOG.debug("%d messages received today" % len(messages)) # LOG.debug("%d messages received today" % len(messages))
msgexists = False msgexists = False
@ -332,11 +342,21 @@ def resend_email(count, fromcall):
messages.sort(reverse=True) messages.sort(reverse=True)
del messages[int(count) :] # only the latest "count" messages del messages[int(count) :] # only the latest "count" messages
for message in messages: for message in messages:
for msgid, data in list(server.fetch(message, ["ENVELOPE"]).items()): try:
parts = server.fetch(message, ["ENVELOPE"]).items()
except Exception as e:
LOG.exception("Couldn't fetch email parts in resend_email", e)
continue
for msgid, data in list(parts):
# one at a time, otherwise order is random # one at a time, otherwise order is random
(body, from_addr) = parse_email(msgid, data, server) (body, from_addr) = parse_email(msgid, data, server)
# unset seen flag, will stay bold in email client # unset seen flag, will stay bold in email client
server.remove_flags(msgid, [imapclient.SEEN]) try:
server.remove_flags(msgid, [imapclient.SEEN])
except Exception as e:
LOG.exception("Failed to remove SEEN flag in resend_email", e)
if from_addr in shortcuts_inverted: if from_addr in shortcuts_inverted:
# reverse lookup of a shortcut # reverse lookup of a shortcut
from_addr = shortcuts_inverted[from_addr] from_addr = shortcuts_inverted[from_addr]
@ -436,60 +456,81 @@ class APRSDEmailThread(threads.APRSDThread):
continue continue
LOG.debug("{} messages received today".format(len(messages))) LOG.debug("{} messages received today".format(len(messages)))
LOG.debug("Try Server.fetch.")
try: try:
for msgid, data in server.fetch(messages, ["ENVELOPE"]).items(): _msgs = server.fetch(messages, ["ENVELOPE"])
envelope = data[b"ENVELOPE"] except Exception as e:
LOG.debug( LOG.exception("IMAP failed to fetch/flag messages: ", e)
'ID:%d "%s" (%s)' continue
% (msgid, envelope.subject.decode(), envelope.date),
)
f = re.search(
r"'([[A-a][0-9]_-]+@[[A-a][0-9]_-\.]+)",
str(envelope.from_[0]),
)
if f is not None:
from_addr = f.group(1)
else:
from_addr = "noaddr"
# LOG.debug("Message flags/tags: " + str(server.get_flags(msgid)[msgid])) for msgid, data in _msgs.items():
# if "APRS" not in server.get_flags(msgid)[msgid]: envelope = data[b"ENVELOPE"]
# in python3, imap tags are unicode. in py2 they're strings. so .decode them to handle both LOG.debug(
taglist = [ 'ID:%d "%s" (%s)'
x.decode(errors="ignore") % (msgid, envelope.subject.decode(), envelope.date),
for x in server.get_flags(msgid)[msgid] )
] f = re.search(
if "APRS" not in taglist: r"'([[A-a][0-9]_-]+@[[A-a][0-9]_-\.]+)",
# if msg not flagged as sent via aprs str(envelope.from_[0]),
LOG.debug("Try single fetch.") )
if f is not None:
from_addr = f.group(1)
else:
from_addr = "noaddr"
# LOG.debug("Message flags/tags: " + str(server.get_flags(msgid)[msgid]))
# if "APRS" not in server.get_flags(msgid)[msgid]:
# in python3, imap tags are unicode. in py2 they're strings. so .decode them to handle both
taglist = [
x.decode(errors="ignore")
for x in server.get_flags(msgid)[msgid]
]
if "APRS" not in taglist:
# if msg not flagged as sent via aprs
LOG.debug("Try single fetch.")
try:
server.fetch([msgid], ["RFC822"]) server.fetch([msgid], ["RFC822"])
LOG.debug("Did single fetch.") except Exception as e:
(body, from_addr) = parse_email(msgid, data, server) LOG.exception("Failed single server fetch for RFC822", e)
# unset seen flag, will stay bold in email client break
LOG.debug("Did single fetch.")
(body, from_addr) = parse_email(msgid, data, server)
# unset seen flag, will stay bold in email client
try:
LOG.debug("Try remove flags.") LOG.debug("Try remove flags.")
server.remove_flags(msgid, [imapclient.SEEN]) server.remove_flags(msgid, [imapclient.SEEN])
LOG.debug("Did remove flags.") LOG.debug("Did remove flags.")
except Exception as e:
LOG.exception("Failed to remove flags SEEN", e)
# Not much we can do here, so lets try and
# send the aprs message anyway
if from_addr in shortcuts_inverted: if from_addr in shortcuts_inverted:
# reverse lookup of a shortcut # reverse lookup of a shortcut
from_addr = shortcuts_inverted[from_addr] from_addr = shortcuts_inverted[from_addr]
reply = "-" + from_addr + " " + body.decode(errors="ignore") reply = "-" + from_addr + " " + body.decode(errors="ignore")
msg = messaging.TextMessage( msg = messaging.TextMessage(
self.config["aprs"]["login"], self.config["aprs"]["login"],
self.config["ham"]["callsign"], self.config["ham"]["callsign"],
reply, reply,
) )
self.msg_queues["tx"].put(msg) self.msg_queues["tx"].put(msg)
# flag message as sent via aprs # flag message as sent via aprs
try:
server.add_flags(msgid, ["APRS"]) server.add_flags(msgid, ["APRS"])
# unset seen flag, will stay bold in email client # unset seen flag, will stay bold in email client
except Exception as e:
LOG.exception("Couldn't add APRS flag to email", e)
try:
server.remove_flags(msgid, [imapclient.SEEN]) server.remove_flags(msgid, [imapclient.SEEN])
# check email more often since we just received an email except Exception as e:
check_email_delay = 60 LOG.exception("Couldn't remove seen flag from email", e)
except Exception as e:
LOG.exception("IMAP failed to fetch/flag messages: ", e) # check email more often since we just received an email
check_email_delay = 60
# reset clock # reset clock
LOG.debug("Done looping over Server.fetch, logging out.") LOG.debug("Done looping over Server.fetch, logging out.")
past = datetime.datetime.now() past = datetime.datetime.now()