asfcm
asfcm

Reputation: 43

Python FTPS upload error: 425 Unable to build data connection: Operation not permitted

I'm trying to use ftps to send a file to a FTP server. Login and changing directory work:

import ftplib
ftps = ftplib.FTP_TLS('host','user','pwd')
ftps.set_pasv(True)
ftps.prot_p()
ftps.cwd('/target_directory')

however when I try to upload my file:

file = open(file, 'rb')
send_cmd = 'STOR file_name.txt'
ftps.storbinary(send_cmd, file)
file.close()
ftps.quit()

I get the following error:

File "/script/location/script.py", line 161, in <module>
ftps.storbinary(send_cmd,file)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/ftplib.py", line 772, in storbinary
return self.voidresp()
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/ftplib.py", line 229, in voidresp
resp = self.getresp()
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/ftplib.py", line 222, in getresp
raise error_temp, resp
ftplib.error_temp: 425 Unable to build data connection: Operation not permitted

I've read that the 425 response code is often a result of being in active mode, which is why I included ftps.set_pasv(True) (although this is True by default).

I've also tried just listing the directory contents using ftps.retrlines('LIST') but get essentially the same error. I'm using Python 2.7.10. Any help would be greatly appreciated.

Upvotes: 3

Views: 4041

Answers (2)

snhou
snhou

Reputation: 3

thanks @pin3da, finaly I fix the bug, it takes a while to find your answer. But for me, it needs to modify a little bit, like below, hope it could help someone else who are struggling on this problem (a decade ago problem) like me.

import ftplib
import ssl

class ImplicitFTP_TLS(ftplib.FTP_TLS):

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self._sock = None

    @property
    def sock(self):
        return self._sock

    @sock.setter
    def sock(self, value):
        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):
        conn, size = ftplib.FTP.ntransfercmd(self, cmd, rest)
        if self._prot_p:
            conn = self.context.wrap_socket(conn,
                                            server_hostname=self.host,
                                            session=self.sock.session)
        return conn, size

Demo code

ftps = ImplicitFTP_TLS()
ftps.connect(host={your_ftp_host}, port=990, timeout=300)
ftps.login({your_ftp_account},{your_ftp_password})
ftps.prot_p()
# do something
print(ftps.getwelcome())
ftps.close()

Upvotes: 0

pin3da
pin3da

Reputation: 31

This is a reported bug in python: https://bugs.python.org/issue19500

You can apply the patch in a new class

class Explicit_FTP_TLS(ftplib.FTP_TLS):
    """Explicit FTPS, with shared TLS session"""
    def ntransfercmd(self, cmd, rest=None):
        conn, size = ftplib.FTP.ntransfercmd(self, cmd, rest)
        if self._prot_p:
            conn = self.context.wrap_socket(conn,
                                            server_hostname=self.host,
                                            session=self.sock.session)
        return conn, size

Upvotes: 3

Related Questions