Skip to content

Commit e0daba6

Browse files
committed
Repeat SSL/TLS handshake on error (rather than just catching)
Fixes an issue with sending large attachments (SMTP), which was a regression in 4651993 (#121)
1 parent 22365f8 commit e0daba6

File tree

1 file changed

+17
-20
lines changed

1 file changed

+17
-20
lines changed

emailproxy.py

+17-20
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
__author__ = 'Simon Robinson'
77
__copyright__ = 'Copyright (c) 2022 Simon Robinson'
88
__license__ = 'Apache 2.0'
9-
__version__ = '2023-01-21' # ISO 8601 (YYYY-MM-DD)
9+
__version__ = '2023-02-08' # ISO 8601 (YYYY-MM-DD)
1010

1111
import argparse
1212
import base64
@@ -805,20 +805,17 @@ def _ssl_handshake(self):
805805
# see: https://github.com/python/cpython/issues/54293
806806
try:
807807
self.socket.do_handshake()
808-
except self.ssl_handshake_errors as e:
809-
self._ssl_handshake_error(e)
810-
else:
811-
Log.debug(self.info_string(), '<-> [', self.socket.version(), 'handshake complete ]')
812-
self.ssl_handshake_attempts = 0
813-
self.ssl_handshake_completed = True
814-
815-
def _ssl_handshake_error(self, error):
816-
if isinstance(error, ssl.SSLWantReadError):
808+
except ssl.SSLWantReadError:
817809
select.select([self.socket], [], [], 0.01) # wait for the socket to be readable (10ms timeout)
818-
elif isinstance(error, ssl.SSLWantWriteError):
810+
except ssl.SSLWantWriteError:
819811
select.select([], [self.socket], [], 0.01) # wait for the socket to be writable (10ms timeout)
820-
else:
812+
except self.ssl_handshake_errors: # also includes SSLWant[Read/Write]Error, but already handled above
821813
self.handle_close()
814+
else:
815+
if not self.ssl_handshake_completed: # only notify once (we may need to repeat the handshake later)
816+
Log.debug(self.info_string(), '<-> [', self.socket.version(), 'handshake complete ]')
817+
self.ssl_handshake_attempts = 0
818+
self.ssl_handshake_completed = True
822819

823820
def handle_read_event(self):
824821
# additional Exceptions are propagated to handle_error(); no need to handle here
@@ -830,8 +827,8 @@ def handle_read_event(self):
830827
# have to deal with both unsecured, wrapped *and* STARTTLS-type sockets would only need this in recv/send
831828
try:
832829
super().handle_read_event()
833-
except self.ssl_handshake_errors as e:
834-
self._ssl_handshake_error(e)
830+
except self.ssl_handshake_errors:
831+
self._ssl_handshake()
835832

836833
def handle_write_event(self):
837834
# additional Exceptions are propagated to handle_error(); no need to handle here
@@ -841,23 +838,23 @@ def handle_write_event(self):
841838
# as in handle_read_event, we need to handle SSL handshake events
842839
try:
843840
super().handle_write_event()
844-
except self.ssl_handshake_errors as e:
845-
self._ssl_handshake_error(e)
841+
except self.ssl_handshake_errors:
842+
self._ssl_handshake()
846843

847844
def recv(self, buffer_size):
848845
# additional Exceptions are propagated to handle_error(); no need to handle here
849846
try:
850847
return super().recv(buffer_size)
851-
except self.ssl_handshake_errors as e:
852-
self._ssl_handshake_error(e)
848+
except self.ssl_handshake_errors:
849+
self._ssl_handshake()
853850
return b''
854851

855852
def send(self, byte_data):
856853
# additional Exceptions are propagated to handle_error(); no need to handle here
857854
try:
858855
return super().send(byte_data) # buffers before sending via the socket, so failure is okay; will auto-retry
859-
except self.ssl_handshake_errors as e:
860-
self._ssl_handshake_error(e)
856+
except self.ssl_handshake_errors:
857+
self._ssl_handshake()
861858
return 0
862859

863860
def handle_error(self):

0 commit comments

Comments
 (0)