2013-01-04 3 views
-1

Gmail 계정에서 꼬인 메일을 사용하여 이메일을 가져 오려고 노력 중이며 이메일을 보는 것이 고통스럽지 않다는 것을 분명히 말하면서 설명과 구조가 명확합니다 (잘 해킹 된 것 같습니다).). 나는 첨부 파일을 잡으려고 노력하고 있는데, 첨부 파일은 어디에서 발견되지 않습니다.IMAP을 사용하여 Twisted에서 이메일 가져 오기

예 IMAP 클라이언트를 꼬인 상태에서 수정 한 상태에서 fetchAll ('1 : ')을 사용하여 전자 메일을 얻은 다음 첫 번째 전자 메일을 받고 있지만 첨부 파일을 찾을 수 없습니다. 그 이메일 (나는 그것이 구글에 있음을 확인했다). 또한 1 :과 함께 무엇을 실제로 (아무도 그것을 이해하는 것처럼) 전자 메일을 설명하는 것을 찾을 수없는 것 같아요

그럼 내가 뭘 놓치고 있니?

코드

#!/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. 
     """ 
    # FETCH ALL HEADERS? WHERE IS A ONE FOR AN ATTACHMENT 
    return proto.fetchAll('1:*').addCallback(cbFetch, proto) 


def cbFetch(result, proto): 
    """ 
     Finally, display headers. 
     """ 
    if result: 
     keys = result.keys() 
     keys.sort() 
     k = keys[-1] 
     proto.display('%s %s' % (k, result[k])) 
    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() 

답변

3

우선은, IMAP4 메일 처리를위한 (아마도 불필요) 복잡한 프로토콜이며,의 트위스트 클라이언트 구현은 (반드시) 복잡한 완전히 그 프로토콜을 지원하는 것입니다. 어디서나 많은 것을 얻으려면 프로토콜을 설명하는 표준 인 rfc3501과 관련된 부분을 읽으면서 twisted's api이라는 관련 부분을 읽는 것이 좋습니다.

즉, IMAP4Client.fetchAll()을 사용하고있는 것처럼 보입니다.이 메시지는 역설적으로 메시지의 헤더와 메타 데이터 인 "봉투"데이터를 가져옵니다. 전자 메일 본문을 반환하는 비슷한 호출도 실제로는 fetchFull()입니다.

+0

감사합니다. RFC를 읽을 것입니다. 그러나 나중에 fetchAll이 모든 것을 가져 오지 않는 것 같아요. – Zimm3r

+0

특히 참조 : "ALL ... 매크로와 같습니다 : (FLAGS INTERNALDATE RFC822.SIZE ENVELOPE) " –

관련 문제