Conducting Telnet with telnetlib
The Apache James mail server comes with a batch file to start it. As a
convenient option, the example program can invoke the batch file via a call to
def start(): print "Starting server...", os.system("c:/apps/bin/james.bat") print "done." def stop(host): import telnetlib print "Stoping server...", telnet = telnetlib.Telnet(host, 4555) telnet.read_until("Login id:") telnet.write("root\n") telnet.read_until("Password:") telnet.write("root\n") telnet.read_until("Welcome") telnet.write("shutdown\n") telnet.close() print "done."
Shutting down the server, on the other hand, requires a Telnet session.
Manually, you can do it through a Telnet client program connected to port 4555
of the server. Enter the user name as
root, password as
root, and the command
shutdown, respectively. To
shutdown the server programmatically in Python, use class
from the core module
To establish a Telnet session, create a
Telnet object with the
Telnet server address and port number specified. To interact with the telnet
server, interleave calls to methods
read_until method reads data from the
server until it receives a specified string, while the
method sends a string to the server. Note that the Apache James mail server
expects a trailing carriage return in the string from the Telnet client, so the
"\n" to the end of the parameter to
write. The Telnet session ends with the invocation of method
close on the
The Twisted Framework
Beyond the core Python modules, Twisted is a networking framework in a different style. As demonstrated in the previous example, Python's core networking modules use a procedural approach. To perform a task, your code must invoke a method that holds the thread of execution until the task either completes successfully or fails. Such a method is straightforward to use since it is synchronous and communicates any results of execution to its caller by means of some return value. The code to perform a sequence of tasks simply invokes the appropriate methods one by one, possibly with some structural constructs and checking of return values.
On the other hand, the Twisted framework adopts a different approach of asynchronous invocation. A method call will schedule a task to do in the framework's execution thread, returning control to its caller immediately and before the completion of the task. An event-driven mechanism communicates the results of the execution. The object returned by the asynchronous method call can register success and failure callbacks that will be invoked when the scheduled task completes successfully and fails, respectively. Performing a sequence of tasks is relatively more complex, since you must typically define each task in a method registered as the success callback to the object returned by the previous task's method.
In Twisted, get used to receiving a
twisted.internet.defer) object from an asynchronous method call.
There is also a
DeferredList object which can watch for
asynchronous method calls completing or failing. The engine
twisted.internet) controls the
framework's execution thread. Start it and shut it down with the methods
Sending Mails the Twisted Way
twisted.mail.smtp) method is
the workhorse for sending mails in Twisted. It takes similar parameters as the
sendmail method of a
smtplib.SMTP object, with the
additional first parameter of the SMTP host name. The return value is a
Deferred object to which you can attach success and failure
def sendMail(host, addr, to, subject, content): from twisted.mail.smtp import sendmail from email.MIMEText import MIMEText print "Sending mail from", addr, "to", to, "..." msg = MIMEText(content) msg["Subject"] = subject msg["From"] = addr msg["To"] = to return sendmail(host, addr, [to], msg.as_string()) def main(): ... elif "s" == sys.argv: print len(addrs), "messages to be sent." dlist =  for addr in addrs: toaddr = user + "@" + host text = "Test mail: " + addr + " to " + toaddr dlist.append( sendMail(host, addr, toaddr, text, text) ) DeferredList(dlist).addBoth(lambda _: reactor.stop()) reactor.run()
To send more than one mails with
sendmail, you don't need to
attach the callbacks to each of the returned
Deferreds in a list to create a
object. The code then attaches a callback to that single
DeferredList object via its
addBoth method. It will
fire when all the
sendmail actions succeed or any of them fails.
The callback simply stops the Twisted's execution thread by
reactor.stop(). Note that the tasks scheduled or registered by
addBoth are not executing until the call
reactor.run(), which starts Twisted's execution thread.