diff --git a/CHANGELOG.md b/CHANGELOG.md index 58b21e7..bea519b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ system path - Fall back to plain text SMTP if `--outgoing-ssl` is not used and `STARTTLS` is not supported by the server - Always use `\n` as the newline when generating CSVs +- Workaround for random Exchange/Office365 `Server Unavailable` IMAP errors 3.9.7 ----- diff --git a/parsedmarc/__init__.py b/parsedmarc/__init__.py index 4bbcd29..0e92ca8 100644 --- a/parsedmarc/__init__.py +++ b/parsedmarc/__init__.py @@ -1524,8 +1524,28 @@ def watch_inbox(host, username, password, callback, reports_folder="INBOX", server.idle() except imapclient.exceptions.IMAPClientError as error: - error = error.__str__().lstrip("b'").rstrip("'").rstrip(".") - raise IMAPError(error) + error = error.__str__().replace("b'", "").replace("'", "") + # Workaround for random Exchange/Office365 IMAP errors + if "Server Unavailable. 15" in error: + logger.debug("IMAP error: {0}".format(error)) + logger.debug("Reconnecting watcher") + server = imapclient.IMAPClient(host) + server.login(username, password) + server.select_folder(rf) + idle_start_time = time.monotonic() + ms = "MOVE" in get_imap_capabilities(server) + res = get_dmarc_reports_from_inbox(connection=server, + move_supported=ms, + reports_folder=rf, + archive_folder=af, + delete=delete, + test=test, + nameservers=ns, + dns_timeout=dt) + callback(res) + server.idle() + else: + raise IMAPError(error) except socket.gaierror: raise IMAPError("DNS resolution failed") except ConnectionRefusedError: diff --git a/parsedmarc/cli.py b/parsedmarc/cli.py index ef9635f..ddb678f 100644 --- a/parsedmarc/cli.py +++ b/parsedmarc/cli.py @@ -227,8 +227,7 @@ def _main(): forensic_reports += reports["forensic_reports"] except IMAPError as error: - error_str = error.__str__().replace("b'", "").lstrip("'") - logger.error("IMAP Error: {0}".format(error_str)) + logger.error("IMAP Error: {0}".format(error.__str__())) exit(1) results = OrderedDict([("aggregate_reports", aggregate_reports), @@ -264,8 +263,7 @@ def _main(): test=args.test, nameservers=args.nameservers, dns_timeout=args.timeout) except IMAPError as error: - error_str = error.__str__().replace("b'", "").lstrip("'") - logger.error("IMAP Error: {0}".format(error_str)) + logger.error("IMAP Error: {0}".format(error.__str__())) exit(1)