Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save hoogenm/de42e2ef85b38179297a0bba8d60778b to your computer and use it in GitHub Desktop.

Select an option

Save hoogenm/de42e2ef85b38179297a0bba8d60778b to your computer and use it in GitHub Desktop.
# Combines several solutions found on the internet
class ImplicitFTP_TLS(ftplib.FTP_TLS):
"""FTP_TLS subclass to support implicit FTPS."""
"""Constructor takes a boolean parameter ignore_PASV_host whether o ignore the hostname"""
"""in the PASV response, and use the hostname from the session instead"""
def __init__(self, *args, **kwargs):
self.ignore_PASV_host = kwargs.get('ignore_PASV_host') == True
super().__init__(*args, {k: v for k, v in kwargs.items() if not k == 'ignore_PASV_host'})
self._sock = None
@property
def sock(self):
"""Return the socket."""
return self._sock
@sock.setter
def sock(self, value):
"""When modifying the socket, ensure that it is ssl wrapped."""
if value is not None and not isinstance(value, ssl.SSLSocket):
value = self.context.wrap_socket(value)
self._sock = value
def ntransfercmd(self, cmd, rest=None):
"""Override the ntransfercmd method"""
conn, size = ftplib.FTP.ntransfercmd(self, cmd, rest)
conn = self.sock.context.wrap_socket(
conn, server_hostname=self.host, session=self.sock.session
)
return conn, size
def makepasv(self):
host, port = super().makepasv()
return (self.host if self.ignore_PASV_host else host), port
@thenickg

thenickg commented Feb 4, 2025

Copy link
Copy Markdown

Worked for me. Thank you for saving me so much time, I was in a very deep rabbit hole without this. Thank you!

@Negaihoshi

Copy link
Copy Markdown

Thanks for the helpful post—our team encountered a similar issue and wanted to share how we resolved it.

We had no problems running this on Python 3.8 and 3.9. However, after upgrading to Python 3.11, we started seeing the following SSL error:

ssl.SSLEOFError: [SSL: UNEXPECTED_EOF_WHILE_READING] EOF occurred in violation of protocol (_ssl.c:2716)

After some investigation, we found it might be related to this issue:
https://bugs.python.org/issue43794

To address this, we updated our code with the following:

self.ftp = _ImplicitFTP_TLS()
self.ftp.context.options |= ssl.OP_IGNORE_UNEXPECTED_EOF
self.ftp.connect(self.host, self.port)

This fixed the problem on Python 3.11.

@Lionel-cl

Copy link
Copy Markdown

I was facing the same errors for 3 hours before finding this thread. Thank you so much everyone.

@jporradre

Copy link
Copy Markdown

Thank you so much buddy! It work like a charm from scratch...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment