Ticket #5697: 5697-imap4client-20120612.patch
| File 5697-imap4client-20120612.patch, 7.0 KB (added by argonemyth, 13 months ago) |
|---|
-
doc/mail/examples/imap4client.py
20 20 from twisted.python import util 21 21 from twisted.python import log 22 22 23 24 23 25 class TrivialPrompter(basic.LineReceiver): 24 26 from os import linesep as delimiter 25 27 … … 40 42 d, self.promptDeferred = self.promptDeferred, None 41 43 d.callback(line) 42 44 45 46 43 47 class SimpleIMAP4Client(imap4.IMAP4Client): 48 """ 49 Add callbacks when the client receives greeting messages from 50 an IMAP server. 51 """ 44 52 greetDeferred = None 45 53 46 54 def serverGreeting(self, caps): … … 49 57 d, self.greetDeferred = self.greetDeferred, None 50 58 d.callback(self) 51 59 60 61 52 62 class SimpleIMAP4ClientFactory(protocol.ClientFactory): 53 63 usedUp = False 54 64 55 65 protocol = SimpleIMAP4Client 56 66 67 57 68 def __init__(self, username, onConn): 58 69 self.ctx = ssl.ClientContextFactory() 59 70 60 71 self.username = username 61 72 self.onConn = onConn 62 73 74 63 75 def buildProtocol(self, addr): 76 """ 77 Initiate the protocol instance. Since we are building a simple 78 IMAP client, we don't bother checking what capabilities the server 79 has. We just add all the authenticators twisted.mail has. 80 Note: Gmail no longer uses any of the method below, it's been 81 using XOAUTH since 2010. 82 """ 64 83 assert not self.usedUp 65 84 self.usedUp = True 66 85 … … 68 87 p.factory = self 69 88 p.greetDeferred = self.onConn 70 89 71 auth = imap4.CramMD5ClientAuthenticator(self.username) 72 p.registerAuthenticator(auth) 73 90 p.registerAuthenticator(imap4.PLAINAuthenticator(self.username)) 91 p.registerAuthenticator(imap4.LOGINAuthenticator(self.username)) 92 p.registerAuthenticator( 93 imap4.CramMD5ClientAuthenticator(self.username)) 94 74 95 return p 75 96 97 76 98 def clientConnectionFailed(self, connector, reason): 77 99 d, self.onConn = self.onConn, None 78 100 d.errback(reason) 79 101 80 # Initial callback - invoked after the server sends us its greet message 102 103 81 104 def cbServerGreeting(proto, username, password): 105 """ 106 Initial callback - invoked after the server sends us its greet message. 107 """ 82 108 # Hook up stdio 83 109 tp = TrivialPrompter() 84 110 stdio.StandardIO(tp) … … 93 119 ).addErrback(ebAuthentication, proto, username, password 94 120 ) 95 121 96 # Fallback error-handler. If anything goes wrong, log it and quit. 122 97 123 def ebConnection(reason): 124 """ 125 Fallback error-handler. If anything goes wrong, log it and quit. 126 """ 98 127 log.startLogging(sys.stdout) 99 128 log.err(reason) 100 from twisted.internet import reactor 101 reactor.stop() 129 return reason 102 130 103 # Callback after authentication has succeeded 131 104 132 def cbAuthentication(result, proto): 105 # List a bunch of mailboxes 133 """ 134 Callback after authentication has succeeded. 135 List a bunch of mailboxes. 136 """ 106 137 return proto.list("", "*" 107 138 ).addCallback(cbMailboxList, proto 108 139 ) 109 140 110 # Errback invoked when authentication fails 141 111 142 def ebAuthentication(failure, proto, username, password): 112 # If it failed because no SASL mechanisms match, offer the user the choice 113 # of logging in insecurely. 143 """ 144 Errback invoked when authentication fails. 145 If it failed because no SASL mechanisms match, offer the user the choice 146 of logging in insecurely. 147 If you are trying to connect to your Gmail account, you will be here! 148 """ 114 149 failure.trap(imap4.NoSupportedAuthentication) 115 return proto.prompt("No secure authentication available. Login insecurely? (y/N) " 150 return proto.prompt( 151 "No secure authentication available. Login insecurely? (y/N) " 116 152 ).addCallback(cbInsecureLogin, proto, username, password 117 153 ) 118 154 119 # Callback for "insecure-login" prompt 155 120 156 def cbInsecureLogin(result, proto, username, password): 157 """ 158 Callback for "insecure-login" prompt. 159 """ 121 160 if result.lower() == "y": 122 161 # If they said yes, do it. 123 162 return proto.login(username, password … … 125 164 ) 126 165 return defer.fail(Exception("Login failed for security reasons.")) 127 166 128 # Callback invoked when a list of mailboxes has been retrieved 167 129 168 def cbMailboxList(result, proto): 169 """ 170 Callback invoked when a list of mailboxes has been retrieved. 171 """ 130 172 result = [e[2] for e in result] 131 173 s = '\n'.join(['%d. %s' % (n + 1, m) for (n, m) in zip(range(len(result)), result)]) 132 174 if not s: … … 135 177 ).addCallback(cbPickMailbox, proto, result 136 178 ) 137 179 138 # When the user selects a mailbox, "examine" it. 180 139 181 def cbPickMailbox(result, proto, mboxes): 182 """ 183 When the user selects a mailbox, "examine" it. 184 """ 140 185 mbox = mboxes[int(result or '1') - 1] 141 186 return proto.examine(mbox 142 187 ).addCallback(cbExamineMbox, proto 143 188 ) 144 189 145 # Callback invoked when examine command completes. 190 146 191 def cbExamineMbox(result, proto): 147 # Retrieve the subject header of every message on the mailbox. 192 """ 193 Callback invoked when examine command completes. 194 Retrieve the subject header of every message on the mailbox. 195 """ 148 196 return proto.fetchSpecific('1:*', 149 197 headerType='HEADER.FIELDS', 150 headerArgs=['SUBJECT'] 198 headerArgs=['SUBJECT'], 151 199 ).addCallback(cbFetch, proto 152 200 ) 153 201 154 # Finally, display headers. 202 155 203 def cbFetch(result, proto): 156 keys = result.keys() 157 keys.sort() 158 for k in keys: 159 proto.display('%s %s' % (k, result[k][0][2])) 204 """ 205 Finally, display headers. 206 """ 207 if result: 208 keys = result.keys() 209 keys.sort() 210 for k in keys: 211 proto.display('%s %s' % (k, result[k][0][2])) 212 else: 213 print "Hey, an empty mailbox!" 214 160 215 return proto.logout() 161 216 162 PORT = 143163 217 218 def cbClose(result): 219 """ 220 Close the connection when we finish everything. 221 """ 222 from twisted.internet import reactor 223 reactor.stop() 224 225 164 226 def main(): 165 227 hostname = raw_input('IMAP4 Server Hostname: ') 228 port = raw_input('IMAP4 Server Port (the default is 143): ') 166 229 username = raw_input('IMAP4 Username: ') 167 230 password = util.getPassword('IMAP4 Password: ') 168 231 169 232 onConn = defer.Deferred( 170 233 ).addCallback(cbServerGreeting, username, password 171 234 ).addErrback(ebConnection 172 ) 235 ).addBoth(cbClose) 173 236 174 237 factory = SimpleIMAP4ClientFactory(username, onConn) 175 238 176 239 from twisted.internet import reactor 177 conn = reactor.connectTCP(hostname, PORT, factory) 240 if port == '993': 241 conn = reactor.connectSSL(hostname, int(port), factory, ssl.ClientContextFactory()) 242 else: 243 if not port: 244 port = 143 245 conn = reactor.connectTCP(hostname, int(port), factory) 178 246 reactor.run() 179 247 248 180 249 if __name__ == '__main__': 181 250 main()
