Skip to content

Commit ef6b0fd

Browse files
committed
Catch SSL errors caused by self-signed certificates (#32)
1 parent b26c7b4 commit ef6b0fd

File tree

1 file changed

+15
-5
lines changed

1 file changed

+15
-5
lines changed

emailproxy.py

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
__author__ = 'Simon Robinson'
55
__copyright__ = 'Copyright (c) 2022 Simon Robinson'
66
__license__ = 'Apache 2.0'
7-
__version__ = '2022-06-01' # ISO 8601 (YYYY-MM-DD)
7+
__version__ = '2022-06-09' # ISO 8601 (YYYY-MM-DD)
88

99
import argparse
1010
import asyncore
@@ -301,7 +301,7 @@ def get_oauth2_credentials(username, password, connection_info, recurse_retries=
301301
(success, authorisation_code) = OAuth2Helper.get_oauth2_authorisation_code(permission_url, redirect_uri,
302302
username, connection_info)
303303
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')
305305
return False, '%s: Login failed - the authentication request expired or was cancelled for ' \
306306
'account %s' % (APP_NAME, username)
307307

@@ -502,7 +502,7 @@ def construct_oauth2_string(username, access_token):
502502

503503
@staticmethod
504504
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
506506
method's docstring is:
507507
Invoke binascii.b2a_base64 iteratively with short even length buffers, strip the trailing line feed from
508508
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):
11071107
asyncore.loop(map=socket_map) # loop for a single connection thread
11081108
except Exception as e:
11091109
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()
11121117

11131118
def start(self):
11141119
Log.info('Starting', self.info_string())
@@ -1172,6 +1177,11 @@ def handle_error(self):
11721177
# OSError 65 = 'No route to host'
11731178
Log.info('Caught network error in', self.info_string(), '- is there a network connection?',
11741179
'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')
11751185
else:
11761186
super().handle_error()
11771187

0 commit comments

Comments
 (0)