[Twisted-Python] using ClientFactory from within a server
![](https://secure.gravatar.com/avatar/548173279e0fec7ba3a791b36b925b0b.jpg?s=120&d=mm&r=g)
I am having trouble using ClientFactory to communicate from within a server. Specifically, I can't figure out the proper way to exit from the client process. Included is some example code illustrating the problem I am having. It is the simple echo server example, but when someone sends some text to the server, I am trying to talk to an SMTP server to send an email. This is just an example (there are probably better ways to fire off an email), but you get the idea. The client code never "exits" and if I try to use reactor.stop() it causes a traceback. So how do I properly exit from this client code, or (being new to twisted) am I going about this in the entirely wrong way? Thanks. #!/usr/bin/env python from twisted.internet import reactor from twisted.internet.protocol import Protocol, ClientFactory, ServerFactory import sys class Echo(Protocol): """This is just about the simplest possible protocol""" def dataReceived(self, data): "As soon as any data is received, write it back." self.transport.write(data) factory2 = MySMTPClientFactory() host = 'localhost' port = 25 reactor.connectTCP(host, port, factory2) reactor.run() print "Returned from sending email" # ^ Never gets to this point class MySMTP(Protocol): def dataReceived(self, data): sys.stdout.write('Server said: ' + data) if data[:3] == "220": self.transport.write("helo foo.com\n") self.stage = 1 if data[:3] == "250": if self.stage == 1: self.transport.write("MAIL FROM:<greg@foo.com>\n") self.stage = 2 elif self.stage == 2: self.transport.write("RCPT TO:<greg@foo.com>\n") self.stage = 3 elif self.stage == 3: self.transport.write("DATA\n") self.stage = 4 elif self.stage == 4: self.transport.write("QUIT\n") self.transport.loseConnection() #reactor.stop() # ^ This causes a traceback if data[:3] == "354": # Ready to send actual email self.transport.write("This is a test email\n.\n") class MySMTPClientFactory(ClientFactory): def startedConnection(self, connector): print 'Started to connect.' def buildProtocol(self, addr): print 'Connected.' return MySMTP() def clientConnectionLost(self, connector, reason): print 'Lost connection. Reason:', reason #reactor.stop() # ^ Causes a traceback here too def clientConnectionFailed(self, connector, reason): print 'Connection failed. Reason:', reason def main(): """This runs the protocol on port 8000""" factory = ServerFactory() factory.protocol = Echo reactor.listenTCP(8000,factory) reactor.run() # this only runs if the module was *not* imported if __name__ == '__main__': main()
![](https://secure.gravatar.com/avatar/56e4cc78ea7fcf3bb37888ebf23bc1f0.jpg?s=120&d=mm&r=g)
On Sun, Sep 28, 2003 at 09:30:33PM -0400, Greg wrote:
reactor.run() enters the twisted mainloop. reactor.stop() causes the mainloop to terminate in the near future. You cannot nest calls to the mainloop (nor do you need to do so).
Remove the above call to "reactor.run() and see what happens.
I don't understand why you aren't using twisted.protocols.smtp.
[snip]
![](https://secure.gravatar.com/avatar/548173279e0fec7ba3a791b36b925b0b.jpg?s=120&d=mm&r=g)
Greg wrote:
Never mind, I suck. I finally noticed that it was of course immediately returning from the reactor.connectTCP() and immediately printing "Returned from sending email", then getting around to actually running the MySMTPClientFactory stuff. I guess I have to learn about using deferreds. Thanks again for your previous help.
![](https://secure.gravatar.com/avatar/56e4cc78ea7fcf3bb37888ebf23bc1f0.jpg?s=120&d=mm&r=g)
On Sun, Sep 28, 2003 at 09:30:33PM -0400, Greg wrote:
reactor.run() enters the twisted mainloop. reactor.stop() causes the mainloop to terminate in the near future. You cannot nest calls to the mainloop (nor do you need to do so).
Remove the above call to "reactor.run() and see what happens.
I don't understand why you aren't using twisted.protocols.smtp.
[snip]
![](https://secure.gravatar.com/avatar/548173279e0fec7ba3a791b36b925b0b.jpg?s=120&d=mm&r=g)
Greg wrote:
Never mind, I suck. I finally noticed that it was of course immediately returning from the reactor.connectTCP() and immediately printing "Returned from sending email", then getting around to actually running the MySMTPClientFactory stuff. I guess I have to learn about using deferreds. Thanks again for your previous help.
participants (2)
-
Greg
-
Jp Calderone