Chapter 2 IMAP

Source: Internet
Author: User
Tags imap imap port

IMAP is more comprehensive and powerful. Twisted is a framework for compiling network applications using python. It is designed to be multitasking and runs through the entire library using asynchronous I/O.


1. Introduction to IMAP in twisted

Most network client libraries, such as poplib and imaplib, work in the same way. You need to write the program that calls these libraries. The library calls the server and your code (that is, the function does not return) until a result is obtained from the network.

Twisted returns this method in its header. When you access the network, you notify twisted of the function to pass the result to, and your real call will return immediately. When you get a result on the network, your function will be called, and the result will be used as a parameter. Twisted developers call this situation "Don't call us, we will call you". This mode is also applicable to event-based programs. A function called by a result is also called a callback function.


2. Understand the basics of twisted

#!/usr/bin/env pythonfrom twisted.internet import defer, reactor, protocolfrom twisted.mail.imap4 import IMAP4Clientimport sysclass IMAPClient(IMAP4Client):    def connectionMade(self):        print ‘I have successfully connected to the server‘        d=self.getCapabilities()        d.addCallback(self.gotcapabilities)            def gotcapabilities(self, caps):        if caps==None:            print ‘Server did not return a capability list.‘        else:            for key, value in caps.items():                print ‘%s: %s‘ %(key, str(value))                        self.logout()        reactor.stop()        class IMAPFactory(protocol.ClientFactory):    protocol=IMAPClient        def clientConnectionFailed(self, connector, reason):        print ‘Client connection failed:‘, reason        reactor.stop()        reactor.connectTCP(sys.argv[1], 143, IMAPFactory())reactor.run()

Most twisted client programs basically have two classes: a protocol class (imapclient in this example) and a factory class (imapfactory ). Factory class management and server connection, protocol class implementation and server session. In this example, when the program starts, create a network connection. The default IMAP port is 143, and an imapfactory object is also passed. Reactor. Run () in the last line of the program (). In twisted, the reactor is used to process network events. It is returned only when the reactor. Stop () is called and the call to reactor. Run () is returned. After a connection is established, the reactor calls connectionmade ().

Getcapabilities () can return a series of optional features supported by the IMAP server. It returns an object called deferred, which is the core of the event-based model in twisted. It notifies twisted of what to do when receiving a reply. Once a deferred object is received, the program calls addcallback on the object, which notifies the reactor of the function to be called after receiving the response. Here, gotcapabilities is the only method that does not overload the base class method. No parentheses are used when calling gotcapabilities because you do not want to call gotcapabilities () when calling addcallback (). Instead, you only pass the function to addcallback (), and let twisted call it later. The gotcapabilities function receives a parameter from twisted, which is the result of your request to getcapabilities. Log out and stop the reactor. The program ends.


1. Logon:

#!/usr/bin/env python#-*-coding:utf-8-*-from twisted.internet import defer, reactor, protocolfrom twisted.mail.imap4 import IMAP4Clientimport sys, getpassclass IMAPClient(IMAP4Client):    def connectionMade(self):        print ‘I have successfully connected to the server‘        IMAPLogin(self)        print ‘connectionMade returning‘                class IMAPFactory(protocol.ClientFactory):    protocol=IMAPClient        def __init__(self, username, password):        self.username=username        self.password=password    def clientConnectionFailed(self, connector, reason):        print ‘Client connection failed:‘, reason        reactor.stop()        class IMAPLogin(object):    def __init__(self, proto):        self.proto=proto        self.factory=proto.factory                d=self.proto.login(self.factory.username, self.factory.password)                d.addCallback(self.loggedin)        d.addCallback(self.stopreactor)                print "IMAPLogic.__init__returning"            def loggedin(self, data):        print "I‘m logged in"        return self.logout()            def logout(self):        print ‘Logging out‘        d=self.proto.logout()        return d            def stopreactor(self, data=None):        print ‘Stopping reactor‘        reactor.stop()        password=getpass.getpass("Enter password for %s on %s: " %(sys.argv[2], sys.argv[1]))        reactor.connectTCP(sys.argv[1], 143, IMAPFactory(sys.argv[2], password))reactor.run()

The program first connects the reactor and then the reactor runs run. This will call the connectionmade method in the protol class. Connecitonmade initializes an imaplogic instance. When initializing an imaplogic instance, The protol class calls the login method to generate a deferred Object D, and then adds two callback functions. A deferred (deferred) object. After obtaining the result from the network, it takes the result as a parameter and calls the callback function. In this example, when a user logs on, twisted obtains the response from the network and calls the loggedin function as a parameter. The loggedin function drops the yo function logout, And the logout function returns the deferred object generated by the logout method of the proto class. Because this object does not have the callback function, it is directly passed to the next Callback Function of the first deferred object, that is, stopreactor ().

We can simply think that the deferred objects are passed between these functions... (Personal understanding)


2. handle errors

Twisted cannot generate exceptions, but there is a concept of calling errback, which is similar to callback, but it is called only when an error occurs.

#!/usr/bin/env pythonfrom twisted.internet import defer, reactor, protocolfrom twisted.mail.imap4 import IMAP4Clientimport sys, getpassclass IMAPClient(IMAP4Client):    def connectionMade(self):        print ‘I have successfully connected to the server‘        IMAPLogic(self)        print ‘connectionMade returning‘        class IMAPFactory(protocol.ClientFactory):    protocol=IMAPClient        def __init__(self, username, password):        self.username=username        self.password=password            def clientConnectionFailed(self, connector, reason):        print ‘Client connection failed:‘, reason        reactor.stop()        class IMAPLogic(object):    def __init__(self, proto):        self.proto=proto        self.factory=proto.factory        self.logintries=1                d=self.login()        d.addCallback(self.loggedin)        d.addErrback(self.loginerror)        d.addCallback(self.logout)        d.addCallback(self.stopreactor)                d.addErrback(self.errorhappened)                print ‘IMAPLogic.__init__ returning‘            def login(self):        print ‘Logging in..‘        return self.proto.login(self.factory.username, self.factory.password)            def loggedin(self, data):        print "I‘m logged in"            def logout(self, data=None):        d=self.proto.logout()        return d            def stopreactor(self, data=None):        print ‘Stopping reactor‘        reactor.stop()            def errorhappened(self, failure):        print ‘An error occured:‘, failure.getErrorMessage()        print ‘Because of the error , I am logging out and stopping reactor...‘        d=self.logout()        d.addBoth(self.stopreactor)        return failure        def loginerror(self, failure):        print ‘Your login failed (attempt %d).‘ % self.logintries        if self.logintries>=3:            print ‘You have triedto log in three times;I am giving up‘            return failure        self.logintries+=1                sys.stdout.write(‘New username: ‘)        self.factory.username=sys.stdin().readline().strip().encode(‘utf-8‘)        self.factory.password=getpass.getpass("New password: ").encode(‘utf-8‘)                d=self.login()        d.addErrback(self.loginerror)        return d        password=getpass.getpass("Enter password for %s on %s: " % (sys.argv[2], sys.argv[1])).encode(‘utf-8‘)reactor.connectTCP(sys.argv[1], 143, IMAPFactory(sys.argv[2].encode(‘utf-8‘), password))reactor.run()


3. Basic download

Download the entire Email:

#!/usr/bin/env pythonfrom twisted.internet import defer,reactor,protocolfrom twisted.mail.imap4 import IMAP4Clientimport sys, getpass, emailclass IMAPClient(IMAP4Client):    def connectionMade(self):        IMAPLogin(self)class IMAPFactory(protocol.ClientFactory):    protocol=IMAPClient    def __init__(self, username, password):        self.username=username        self.password=password        def clientConnectionFailed(self, connector, reason):        print ‘Client connnection failed:‘, reason        reactor.stop()        class IMAPLogin(object):    def __init__(self, proto):        self.proto=proto        self.factory=proto.factory        d=self.proto.login(self.factory.username, self.factory.password)        d.addCallback(lambda x: self.proto.examine(‘INBOX‘))        d.addCallback(lambda x: self.proto.fetchSpecific(‘1:*‘, peek=1))        d.addCallback(self.gotmessages)        d.addCallback(self.logout)        d.addCallback(self.stopreactor)                d.addErrback(self.errorhappened)            def gotmessages(self, data):        destfd=open(sys.argv[3], ‘at‘)        for key, value in data.items():            print ‘Writing message‘, key            msg=email.message_from_string(value[0][2])            destfd.write(msg.as_string(unixfrom=1))            destfd.write(‘\n‘)        destfd.close()    def logout(self, data=None):        return self.proto.logout()            def stopreactor(self, data=None):        reactor.stop()            def errorhappened(self, failure):        print ‘An error occured:‘, failure.getErrorMessage()        print ‘Because of the error, I am logging out and stopping reactor...‘        d=self.logout()        d.addBoth(self.stopreactor)        return failure        password=getpass.getpass(‘Enter password for %s on %s:‘%(sys.argv[2], sys.argv[1]))#print passwordreactor.connectTCP(sys.argv[1], 143, IMAPFactory(sys.argv[2], password))reactor.run()

The fetchspecific () function can download multiple emails from one email folder. The first parameter, '1: * 'is the range of all emails in the folder. By setting peek to true, emails are not changed when you read them, if peek is not set, the \ seen flag is added to all downloaded emails. The gotmessages () function is called by the downloaded email. It is passed into a dictionary. The key of the dictionary is the number of the email, and its value is a list of the components of the email.



This article from the "Lotus miss" blog, please be sure to keep this source http://liandesinian.blog.51cto.com/7737219/1567661

Chapter 2 IMAP

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.