Having error when using FTPtool module for Python
class FTPHost(object):
"""Represent a connection to a remote host.
A remote host has a working directory, and an ftplib object connected.
"""
def __init__(self, ftp_obj):
"""Initialize with a ftplib.FTP instance (or an instance of a
subclass). Use the classmethod connect to create an actual ftplib
connection and get an FTPHost instance.
"""
self.ftp_obj = ftp_obj
def __repr__(self):
return "%s(%r)" % (self.__class__.__name__, self.ftp_obj)
def __str__(self):
return "<%s at %s:%d (%s)>" % (self.__class__.__name__,
self.ftp_obj.host, self.ftp_obj.port, self.ftp_obj)
#classmethod
def connect(cls, host, port=21, user=None, password=None, account=None,
ftp_client=ftplib.FTP, debuglevel=0, timeout=None):
"""Connect to host, using port. If user is given, login with given
user, password and account. The two latter can be None, in which case
ftplib will set the password to 'anonymous#'. You can choose which
class to instance by means of ftp_client.
"""
ftp_obj = ftp_client()
ftp_obj.set_debuglevel(debuglevel)
if timeout is not None:
old_timeout = socket.getdefaulttimeout()
socket.setdefaulttimeout(float(timeout))
ftp_obj.connect(host, port)
socket.setdefaulttimeout(old_timeout)
else:
ftp_obj.connect(host, port)
# And log in.
if user:
ftp_obj.login(user, password, account)
return cls(ftp_obj)
When calling FTPhost.connect(server, name, pass) i get the error FTPhost not defined. New to Python and have tried looking all around the code but to no avail.
I'm fresh to ftptool as well, and I met the same problem.
Here's my way.
from ftptool import FTPHost
Related
I need to trigger a python script every time an email is received by my webserver on a specific account. I will also need the email to be passed to the script as an argument. My webserver is using Dovecot. How do I go about doing this?
I recommend you have a look at Twisted and specifically its IMAP and POP protocols and client modules.
As an example:
#!/usr/bin/env python
# Copyright (c) Twisted Matrix Laboratories.
# See LICENSE for details.
"""
Simple IMAP4 client which displays the subjects of all messages in a
particular mailbox.
"""
import sys
from twisted.internet import protocol
from twisted.internet import ssl
from twisted.internet import defer
from twisted.internet import stdio
from twisted.mail import imap4
from twisted.protocols import basic
from twisted.python import util
from twisted.python import log
class TrivialPrompter(basic.LineReceiver):
from os import linesep as delimiter
promptDeferred = None
def prompt(self, msg):
assert self.promptDeferred is None
self.display(msg)
self.promptDeferred = defer.Deferred()
return self.promptDeferred
def display(self, msg):
self.transport.write(msg)
def lineReceived(self, line):
if self.promptDeferred is None:
return
d, self.promptDeferred = self.promptDeferred, None
d.callback(line)
class SimpleIMAP4Client(imap4.IMAP4Client):
"""
A client with callbacks for greeting messages from an IMAP server.
"""
greetDeferred = None
def serverGreeting(self, caps):
self.serverCapabilities = caps
if self.greetDeferred is not None:
d, self.greetDeferred = self.greetDeferred, None
d.callback(self)
class SimpleIMAP4ClientFactory(protocol.ClientFactory):
usedUp = False
protocol = SimpleIMAP4Client
def __init__(self, username, onConn):
self.ctx = ssl.ClientContextFactory()
self.username = username
self.onConn = onConn
def buildProtocol(self, addr):
"""
Initiate the protocol instance. Since we are building a simple IMAP
client, we don't bother checking what capabilities the server has. We
just add all the authenticators twisted.mail has. Note: Gmail no
longer uses any of the methods below, it's been using XOAUTH since
2010.
"""
assert not self.usedUp
self.usedUp = True
p = self.protocol(self.ctx)
p.factory = self
p.greetDeferred = self.onConn
p.registerAuthenticator(imap4.PLAINAuthenticator(self.username))
p.registerAuthenticator(imap4.LOGINAuthenticator(self.username))
p.registerAuthenticator(
imap4.CramMD5ClientAuthenticator(self.username))
return p
def clientConnectionFailed(self, connector, reason):
d, self.onConn = self.onConn, None
d.errback(reason)
def cbServerGreeting(proto, username, password):
"""
Initial callback - invoked after the server sends us its greet message.
"""
# Hook up stdio
tp = TrivialPrompter()
stdio.StandardIO(tp)
# And make it easily accessible
proto.prompt = tp.prompt
proto.display = tp.display
# Try to authenticate securely
return proto.authenticate(password
).addCallback(cbAuthentication, proto
).addErrback(ebAuthentication, proto, username, password
)
def ebConnection(reason):
"""
Fallback error-handler. If anything goes wrong, log it and quit.
"""
log.startLogging(sys.stdout)
log.err(reason)
return reason
def cbAuthentication(result, proto):
"""
Callback after authentication has succeeded.
Lists a bunch of mailboxes.
"""
return proto.list("", "*"
).addCallback(cbMailboxList, proto
)
def ebAuthentication(failure, proto, username, password):
"""
Errback invoked when authentication fails.
If it failed because no SASL mechanisms match, offer the user the choice
of logging in insecurely.
If you are trying to connect to your Gmail account, you will be here!
"""
failure.trap(imap4.NoSupportedAuthentication)
return proto.prompt(
"No secure authentication available. Login insecurely? (y/N) "
).addCallback(cbInsecureLogin, proto, username, password
)
def cbInsecureLogin(result, proto, username, password):
"""
Callback for "insecure-login" prompt.
"""
if result.lower() == "y":
# If they said yes, do it.
return proto.login(username, password
).addCallback(cbAuthentication, proto
)
return defer.fail(Exception("Login failed for security reasons."))
def cbMailboxList(result, proto):
"""
Callback invoked when a list of mailboxes has been retrieved.
"""
result = [e[2] for e in result]
s = '\n'.join(['%d. %s' % (n + 1, m) for (n, m) in zip(range(len(result)), result)])
if not s:
return defer.fail(Exception("No mailboxes exist on server!"))
return proto.prompt(s + "\nWhich mailbox? [1] "
).addCallback(cbPickMailbox, proto, result
)
def cbPickMailbox(result, proto, mboxes):
"""
When the user selects a mailbox, "examine" it.
"""
mbox = mboxes[int(result or '1') - 1]
return proto.examine(mbox
).addCallback(cbExamineMbox, proto
)
def cbExamineMbox(result, proto):
"""
Callback invoked when examine command completes.
Retrieve the subject header of every message in the mailbox.
"""
return proto.fetchSpecific('1:*',
headerType='HEADER.FIELDS',
headerArgs=['SUBJECT'],
).addCallback(cbFetch, proto
)
def cbFetch(result, proto):
"""
Finally, display headers.
"""
if result:
keys = result.keys()
keys.sort()
for k in keys:
proto.display('%s %s' % (k, result[k][0][2]))
else:
print "Hey, an empty mailbox!"
return proto.logout()
def cbClose(result):
"""
Close the connection when we finish everything.
"""
from twisted.internet import reactor
reactor.stop()
def main():
hostname = raw_input('IMAP4 Server Hostname: ')
port = raw_input('IMAP4 Server Port (the default is 143, 993 uses SSL): ')
username = raw_input('IMAP4 Username: ')
password = util.getPassword('IMAP4 Password: ')
onConn = defer.Deferred(
).addCallback(cbServerGreeting, username, password
).addErrback(ebConnection
).addBoth(cbClose)
factory = SimpleIMAP4ClientFactory(username, onConn)
from twisted.internet import reactor
if port == '993':
reactor.connectSSL(hostname, int(port), factory, ssl.ClientContextFactory())
else:
if not port:
port = 143
reactor.connectTCP(hostname, int(port), factory)
reactor.run()
if __name__ == '__main__':
main()
From here you need to just call your Python script in a subprocess when you detect a new email from your IMAP folder that you're checking... Here you could also use Twisted's Process handling as documented here: https://twistedmatrix.com/documents/13.0.0/core/howto/process.html
Good luck!
IMAP server may notify you about new messages if it supports IDLE command. If it doesn't support it then you could poll the inbox periodically using imaplib from stdlib (code example to retrieve messages from a time period).
imaplib doesn't support IDLE command but it could be easily added e.g., imapidle:
from imapidle import imaplib
m = imaplib.IMAP4_SSL('imap.gmail.com')
m.login('robert', 'pa55w0rd')
m.select()
for uid, msg in m.idle(): # yield new messages
print msg
See also How do I enable push-notification for IMAP (Gmail) using Python imaplib?
I am beginner in programming and trying to develop simple console messenger on Python. I have an idea to extend standard socket.socket object and add to it additional attribute "account_name". I created new class "NamedSoket" based on standard socket class. Here is my code:
class NamedSocket(socket):
def __init__(self, family=-1, type=-1, proto=-1, fileno=None, name=None):
super().__init__(family=-1, type=-1, proto=-1, fileno=None)
self.name = name
def accept(self):
fd, addr = self._accept()
sock = NamedSocket(self.family, self.type, self.proto, fileno=fd, name=self.name)
if getdefaulttimeout() is None and self.gettimeout():
sock.setblocking(True)
return sock, addr
server = NamedSocket()
server.bind(('', 8000))
server.listen()
client = NamedSocket('Bob')
client.connect(('localhost', 8000))
new_client, address = server.accept()
Although new socket objects are created successfully, they do not work properly.. Methods 'recv' and 'send' do not work.. Could you please explain to me, where is the problem?
P.S.: I understand, that my 'idea', maybe, is not good 'at all', but now I became very interested in 'inheritance issue'. From first look, it should work, but it does not...
I've replicated described actions as accurate as possible. This code is working without any error.
import socket as sk
class NamedSocket(sk.socket):
def __init__(self, family=sk.AF_INET, type=sk.SOCK_STREAM, proto=0, fileno=None, name=None):
super().__init__(family, type, proto, fileno)
self.name = name
def accept(self):
fd, addr = self._accept()
sock = NamedSocket(self.family, self.type, self.proto, fileno=fd, name=self.name)
if sk.getdefaulttimeout() is None and self.gettimeout():
sock.setblocking(True)
return sock, addr
server = NamedSocket()
server.bind(('', 8000))
server.listen()
client = NamedSocket(name='Bob')
client.connect(('localhost', 8000))
new_client, address = server.accept()
client.send('hello'.encode())
new_client.recv(1024)
I replaced default parameters in __init()__ method of NamedSocket class to AF_INET, SOCK_STREAM and 0 for the first three arguments. Running such script does not imply any error. You could try do the same changes or edit something related to IP address binded to socket being established on the server side, according to error message.
As you may see, your constructor method takes a bunch of optional parameters:
def __init__(self, family=-1, type=-1, proto=-1, fileno=None, name=None):
super().__init__(family=-1, type=-1, proto=-1, fileno=None)
self.name = name
When you try to create an object of class NamedSocket for client, you pass the only 'Bob' parameter, which, by precedence of function argument, will be passed to family argument, but not to name. For doing things in the key you want, you may write:
client = NamedSocket(name='Bob')
I am requesting advice for running concurrent pysftp API commands, such as listing files in a directory and downloading them from a server. It seems that when I test this all requests are blocked until the previous is finished.
I'm using pysftp with Django and I'm not sure how to implement this in a way that will scale a bit so I can have multiple users on the page making requests without them being blocked until another users request has been served.
I tried something like this:
class sftp:
def __init__(self):
self.response = HttpResponse()
self.cnopts = pysftp.CnOpts()
self.cnopts.hostkeys = None
def download(self):
with pysftp.Connection('host.exmaple.com', username='user1', password='test_password',
cnopts=self.cnopts) as sftp:
sftp.getfo(
'/var/lib/stuff/file.mp3',
self.response)
self.response['Content-Type'] = 'audio/mp3'
return self.response
Then in my view I would call something like this:
return sftp().download()
I needed something similar for one of my projects.
I wrote a module that handle listing and reading files on remote server over SSH.
Difference is that it's not using pysftp but paramiko, but it should do the job I guess.
import paramiko
class SSHClient:
__slots__ = ['transport', 'sftp']
def __init__(self, host, user, passw, port):
"""Init connection to SFTP server.
Args:
host (str): Server IP address
user (str): Server username
passw (str): Server password
port (int): connection port
"""
self.transport = paramiko.Transport((host, port))
self.transport.connect(username=user, password=passw)
self.sftp = paramiko.SFTPClient.from_transport(t=self.transport)
def __enter__(self):
return self
def __exit__(self, exception_type, exception_value, traceback):
"""Close SFTP connection"""
self.transport.close()
self.sftp.close()
def list_files(self, remote_path) -> list:
"""List files from specific server directory.
Args:
remote_path (str): SFTP server path directory.
Returns:
list of files & folders in directory.
"""
return self.sftp.listdir(path=remote_path)
def read_remote_file(self, remote_path, filename):
"""Read remote file content from server.
Args:
remote_path (str): SFTP server path.
filename (str): name of file.
"""
return self.sftp.open(
filename='{path}/{file}'.format(path=remote_path, file=filename),
mode='r'
)
def close_conn(self) -> None:
"""Close SFTP connection"""
self.transport.close()
self.sftp.close()
Then you could download a file using the content fetched using read_remote_file() to one of your views in your Django app.
I'm attempting to do the following:
connect as client to an existing websocket
process the streaming data received from this socket, and publish it on another websocket
I'm using twisted and autobahn to do so. I have managed to have the two parts working separately, by deriving a WebSocketClientProtocol for the client, and deriving an ApplicationSession in the second. The two run with the same reactor.
I am not sure however as to how to make them communicate. I would like to send a message on my server when the client receives a message, but I don't know how to get the running instance of the WebSocketClientProtocol...
Perhaps this isn't the right approach to do this either. What's the right way to do this?
I've been trying to solve similiar problem recently, here's what worked:
f = XLeagueBotFactory()
app = Application(f)
reactor.connectTCP("irc.gamesurge.net", 6667, f)
reactor.listenTCP(port, app, interface=host)
^ This is in if __name__ == "__main__":
class Application(web.Application):
def __init__(self, botfactory):
self.botfactory = botfactory
Define the instance as self, then in my instance I was sending it to another handler for http post request (using cyclone)
class requestvouch(web.RequestHandler):
def __init__(self, application, request, **kwargs):
super(requestvouch, self).__init__(application, request, **kwargs)
self.botfactory = application.botfactory
def msg(self, channel, msg):
bot = self.botfactory.getProtocolByName("XLeagueBot")
sendmsg(bot, channel, msg) # function that processed the msg through stuff like encoding and logging and then sent it to bot.msg() function that posts it to IRC (endpoint in my case)
def post(self):
msg = "What I'm sending to the protocol of the other thing"
self.msg("#xleague", msg)
Now the important part comes in factory
class XLeagueBotFactory(protocol.ClientFactory):
protocol = XLeagueBot
def __init__(self):
self.protocols = {}
def getProtocolByName(self, name):
return self.protocols.get(name)
def registerProtocol(self, protocol):
self.protocols[protocol.nickname] = protocol
def unregisterProtocol(self, protocol):
del self.protocols[protocol.nickname]
Finally in my client class:
class XLeagueBot(irc.IRCClient):
nickname = "XLeagueBot"
def connectionMade(self):
irc.IRCClient.connectionMade(self)
self.factory.registerProtocol(self)
def connectionLost(self, reason):
self.factory.unregisterProtocol(self)
irc.IRCClient.connectionLost(self, reason)
I'm not entirely sure that this code is perfect, or bugfree, but it should +- tell you how to deal with calling instance of protocol class. The problem afaik comes from name of instance protocol being generated inside of it's factory and not being sent elsewhere.
I am adding a feature to my current project that will allow network admins to install the software to the network. I need to code a DNS server in Python that will allow me to redirect to a certain page if the request address is in my list. I was able to write the server, just not sure how to redirect.
Thank you. I am using Python 2.6 on Windows XP.
There's little, simple example here that can easily be adapted to make all kinds of "mini fake dns servers". Note that absolutely no "redirect" is involved (that's not how DNS works): rather, the request is for a domain name, and the result of that request is an IP address. If what you want to do is drastically different from translating names to addresses, then maybe what you need is not actually a DNS server...?
Using circuits and dnslib here's a full recursive dns server written in Python in only 143 lines of code:
#!/usr/bin/env python
from __future__ import print_function
from uuid import uuid4 as uuid
from dnslib import CLASS, QR, QTYPE
from dnslib import DNSHeader, DNSQuestion, DNSRecord
from circuits.net.events import write
from circuits import Component, Debugger, Event
from circuits.net.sockets import UDPClient, UDPServer
class lookup(Event):
"""lookup Event"""
class query(Event):
"""query Event"""
class response(Event):
"""response Event"""
class DNS(Component):
def read(self, peer, data):
record = DNSRecord.parse(data)
if record.header.qr == QR["QUERY"]:
return self.fire(query(peer, record))
return self.fire(response(peer, record))
class ReturnResponse(Component):
def response(self, peer, response):
return response
class Client(Component):
channel = "client"
def init(self, server, port, channel=channel):
self.server = server
self.port = int(port)
self.transport = UDPClient(0, channel=self.channel).register(self)
self.protocol = DNS(channel=self.channel).register(self)
self.handler = ReturnResponse(channel=self.channel).register(self)
class Resolver(Component):
def init(self, server, port):
self.server = server
self.port = port
def lookup(self, qname, qclass="IN", qtype="A"):
channel = uuid()
client = Client(
self.server,
self.port,
channel=channel
).register(self)
yield self.wait("ready", channel)
self.fire(
write(
(self.server, self.port),
DNSRecord(
q=DNSQuestion(
qname,
qclass=CLASS[qclass],
qtype=QTYPE[qtype]
)
).pack()
)
)
yield (yield self.wait("response", channel))
client.unregister()
yield self.wait("unregistered", channel)
del client
class ProcessQuery(Component):
def query(self, peer, query):
qname = query.q.qname
qtype = QTYPE[query.q.qtype]
qclass = CLASS[query.q.qclass]
response = yield self.call(lookup(qname, qclass=qclass, qtype=qtype))
record = DNSRecord(
DNSHeader(id=query.header.id, qr=1, aa=1, ra=1),
q=query.q,
)
for rr in response.value.rr:
record.add_answer(rr)
yield record.pack()
class Server(Component):
def init(self, bind=("0.0.0.0", 53)):
self.bind = bind
self.transport = UDPServer(self.bind).register(self)
self.protocol = DNS().register(self)
self.handler = ProcessQuery().register(self)
class App(Component):
def init(self, bind=("0.0.0.0", 53), server="8.8.8.8", port=53,
verbose=False):
if verbose:
Debugger().register(self)
self.resolver = Resolver(server, port).register(self)
self.server = Server(bind).register(self)
def main():
App().run()
if __name__ == "__main__":
main()
Usage:
By default this example binds go 0.0.0.0:53 so you will need to do something like:
sudo ./dnsserver.py
Otherwise change the bind parameter.
Here is a dns serer/proxy that works for me written in python:
http://thesprawl.org/projects/dnschef/
I wrote a DNS Server using Python Twisted library for NameOcean.net. You can see examples on https://twistedmatrix.com/documents/16.5.0/names/howto/custom-server.html.