|
4 | 4 | __author__ = 'Simon Robinson' |
5 | 5 | __copyright__ = 'Copyright (c) 2022 Simon Robinson' |
6 | 6 | __license__ = 'Apache 2.0' |
7 | | -__version__ = '2022-06-01' # ISO 8601 (YYYY-MM-DD) |
| 7 | +__version__ = '2022-06-09' # ISO 8601 (YYYY-MM-DD) |
8 | 8 |
|
9 | 9 | import argparse |
10 | 10 | import asyncore |
@@ -301,7 +301,7 @@ def get_oauth2_credentials(username, password, connection_info, recurse_retries= |
301 | 301 | (success, authorisation_code) = OAuth2Helper.get_oauth2_authorisation_code(permission_url, redirect_uri, |
302 | 302 | username, connection_info) |
303 | 303 | if not success: |
304 | | - Log.error('Authentication request failed or expired for account', username, '- aborting login') |
| 304 | + Log.info('Authentication request failed or expired for account', username, '- aborting login') |
305 | 305 | return False, '%s: Login failed - the authentication request expired or was cancelled for ' \ |
306 | 306 | 'account %s' % (APP_NAME, username) |
307 | 307 |
|
@@ -502,7 +502,7 @@ def construct_oauth2_string(username, access_token): |
502 | 502 |
|
503 | 503 | @staticmethod |
504 | 504 | def encode_oauth2_string(input_string): |
505 | | - """We use encode() from imaplib's _Authenticator, but it is a private class so we can't just import it. That |
| 505 | + """We use encode() from imaplib's _Authenticator, but it is a private class so we shouldn't just import it. That |
506 | 506 | method's docstring is: |
507 | 507 | Invoke binascii.b2a_base64 iteratively with short even length buffers, strip the trailing line feed from |
508 | 508 | the result and append. 'Even' means a number that factors to both 6 and 8, so when it gets to the end of |
@@ -1107,8 +1107,13 @@ def run_server(client, socket_map, address): |
1107 | 1107 | asyncore.loop(map=socket_map) # loop for a single connection thread |
1108 | 1108 | except Exception as e: |
1109 | 1109 | if not EXITING: |
1110 | | - Log.info('Caught asyncore exception in', address, 'thread loop:', Log.error_string(e)) |
1111 | | - client.close() |
| 1110 | + # OSError 9 = 'Bad file descriptor', thrown when closing connections after network interruption |
| 1111 | + if isinstance(e, OSError) and e.errno == errno.EBADF: |
| 1112 | + Log.info(client.proxy_type, address, '[ Connection closed ]') |
| 1113 | + else: |
| 1114 | + Log.info('Caught asyncore exception in', client.proxy_type, address, 'thread loop:', |
| 1115 | + Log.error_string(e)) |
| 1116 | + client.close() |
1112 | 1117 |
|
1113 | 1118 | def start(self): |
1114 | 1119 | Log.info('Starting', self.info_string()) |
@@ -1172,6 +1177,11 @@ def handle_error(self): |
1172 | 1177 | # OSError 65 = 'No route to host' |
1173 | 1178 | Log.info('Caught network error in', self.info_string(), '- is there a network connection?', |
1174 | 1179 | 'Error type', error_type, 'with message:', value) |
| 1180 | + elif error_type == ssl.SSLError and 'SSLV3_ALERT_BAD_CERTIFICATE' in value.args[1] and \ |
| 1181 | + self.custom_configuration['local_certificate_path'] and self.custom_configuration['local_key_path']: |
| 1182 | + Log.error('Caught SSLV3_ALERT_BAD_CERTIFICATE error in', self.info_string(), '- when using a self-signed', |
| 1183 | + 'local certificate you may need to disable SSL verification (and/or add an exception) in your', |
| 1184 | + 'client for the local host and port') |
1175 | 1185 | else: |
1176 | 1186 | super().handle_error() |
1177 | 1187 |
|
|
0 commit comments