[Commits] (bkirsch) Post code review changes / updates TODO epydoc

commits at osafoundation.org commits at osafoundation.org
Tue Jul 6 17:09:33 PDT 2004


Commit by: bkirsch
Modified files:
chandler/parcels/osaf/mail/IMAPMailTask.py 1.4 1.5

Log message:
Post code review changes / updates TODO epydoc

ViewCVS links:
http://cvs.osafoundation.org/index.cgi/chandler/parcels/osaf/mail/IMAPMailTask.py.diff?r1=text&tr1=1.4&r2=text&tr2=1.5

Index: chandler/parcels/osaf/mail/IMAPMailTask.py
diff -u /dev/null chandler/parcels/osaf/mail/IMAPMailTask.py:1.5
--- /dev/null	Tue Jul  6 17:09:33 2004
+++ chandler/parcels/osaf/mail/IMAPMailTask.py	Tue Jul  6 17:09:32 2004
@@ -0,0 +1,361 @@
+__revision__  = "$Revision: 1.5 $"
+__date__      = "$Date: 2004/07/07 00:09:32 $"
+__copyright__ = "Copyright (c) 2002 Open Source Applications Foundation"
+__license__   = "http://osafoundation.org/Chandler_0.1_license_terms.htm"
+
+import application.Globals as Globals
+import osaf.framework.tasks.Action as Action
+import osaf.contentmodel.mail.Mail as Mail
+import repository.item.Query as Query 
+import twisted.internet.defer as defer
+import twisted.internet.reactor as reactor
+import twisted.internet.protocol as protocol
+import twisted.protocols.imap4 as imap4
+import osaf.framework.twisted.RepositoryViewBase as RepositoryViewBase
+import mx.DateTime as DateTime
+import email as email
+import email.Utils as Utils
+import logging as logging
+
+
+
+class MailDownloadAction(Action.Action): 
+
+    # In Thread
+    def Execute(self, task):
+
+        accountKind = Mail.MailParcel.getEmailAccountKind()
+        printed = False 
+
+        for account in Query.KindQuery().run([accountKind]):
+            if account.accountType != 'IMAP4':
+                str =  "WARNING: Only IMAP Accounts are currently supported. "
+                str1 = "%s of type %s will be ignored" % (account.displayName, account.accountType)
+                logging.error(str, str1)
+                continue
+            
+            if not printed:
+                logging.info("IMAP MAIL TASK CHECKING FOR NEW MAIL")
+                printed = True
+               
+            viewName = "%s_%s" % (account.displayName, account.itsUUID)
+            
+            IMAPDownloader(account.itsUUID, viewName).getMail()        
+        
+
+class ChandlerIMAP4Client(imap4.IMAP4Client):
+    
+    def serverGreeting(self, caps):
+
+        self.serverCapabilities =  self.__disableTLS(caps)
+
+        d = defer.Deferred().addCallback(self.factory.callback, self
+                           ).addErrback(self.factory.errback)
+        
+        d.callback(True)
+        
+
+    def __disableTLS(self, caps):
+        """Disables SSL support for debugging so
+           a tcpflow trace can be done on the Client / Server
+           command exchange"""
+
+        if caps != None:
+            try:
+                del caps["STARTTLS"]
+
+            except KeyError:
+                pass
+
+        return caps
+    
+    
+class ChandlerIMAP4Factory(protocol.ClientFactory):
+    protocol = ChandlerIMAP4Client
+
+    def __init__(self, callback, errback):
+        self.callback = callback
+        self.errback = errback
+    
+    def buildProtocol(self, addr):
+        p = self.protocol()
+        p.factory = self
+        return p
+       
+    def clientConnectionFailed(self, connector, reason):  
+        logging.error("Unable to connect to server ", reason)
+
+    
+        
+class IMAPDownloader(RepositoryViewBase.RepositoryViewBase):
+    
+    # In Thread
+    def __init__(self, accountUUID, viewName):    
+        
+        super(IMAPDownloader, self).__init__(viewName)
+        
+        self.proto = None
+        self.accountUUID = accountUUID
+        self.account = None
+        self.downloadedStr = None
+                 
+         
+    # In Thread
+    def getMail(self):
+        if __debug__:
+            self.printCurrentView("getMail")
+                
+        reactor.callFromThread(self.__getMail)  
+       
+    # In Twisted
+    def __getMail(self):
+        """If in the thread of execution and not the Twisted Reactor 
+           thread one must manually reset the view to the previous view.
+           Other classes using that thread will assume one view per thread 
+           and will try repository operations on the wrong view"""
+        self.setViewCurrent()
+        
+        try:
+            if __debug__: 
+                self.printCurrentView("__getMail")
+                
+            self.account = self.getAccount()
+            self.account.setPinned()
+             
+            serverName = self.account.serverName
+            serverPort = self.account.serverPort
+                    
+            if __debug__: 
+                self.printAccount()
+        
+        finally:
+            self.restorePreviousView()
+        
+        factory = ChandlerIMAP4Factory(self.loginClient, self.catchErrors)
+        reactor.connectTCP(serverName, serverPort, factory)     
+ 
+    # In Twisted Reactor or in Thread
+    def printAccount(self):
+        self.printCurrentView("printAccount")
+        
+        str  = "\nHost: %s\n" % self.account.serverName
+        str += "Port: %d\n" % self.account.serverPort
+        str += "Username: %s\n" % self.account.accountName
+        str += "Password: %s\n" % self.account.password
+        
+        self.log.info(str)
+
+    # In Twisted Reactor
+    def catchErrors(self, result):
+        self.log.error("Twisted Error %s" % result)
+   
+    # In Twisted Reactor
+    def loginClient(self, result, proto):
+
+        self.setViewCurrent()  
+       
+        try:       
+            if __debug__: 
+                self.printCurrentView("loginClient")  
+                
+            """ Save the IMAP4Client instance """
+            self.proto = proto
+
+            """ Login using plain text login """
+
+            return self.proto.login(str(self.account.accountName), 
+                                    str(self.account.password)).addCallback(self.selectInbox)
+        finally:
+           self.restorePreviousView()
+
+        
+    # In Twisted Reactor
+    def selectInbox(self, result):
+        if __debug__:
+            self.printCurrentView("selectInbox ***Could be wrong view***")
+
+        self.printInfo("Checking Inbox for new mail messages")
+        
+        return self.proto.select("INBOX").addCallback(self.checkForNewMessages)
+    
+    # In Twisted Reactor
+    def checkForNewMessages(self, msgs):   
+        
+        self.setViewCurrent()   
+        
+        try:
+            if __debug__:
+                self.printCurrentView("checkForNewMessages")
+        
+            exists = msgs['EXISTS']
+        
+            if exists != 0:
+                """ Fetch everything newer than the last UID we saw. """
+            
+                if self.getLastUID() == 0:                  
+                    msgSet = imap4.MessageSet(1, None)       
+                else: 
+                    msgSet = imap4.MessageSet(self.getLastUID(), None)     
+
+                d = self.proto.fetchUID(msgSet, uid=True) 
+                d.addCallback(self.getMessagesFromUIDS)     
+            
+                return d
+        
+            self.printInfo("No messages present to download")
+            
+        finally:
+            self.restorePreviousView()
+        
+    # In Twisted Reactor     
+    def getMessagesFromUIDS(self, msgs):
+
+        self.setViewCurrent()
+        
+        try:
+            if __debug__:
+                self.printCurrentView("getMessagesFromUIDS")
+        
+            v = [int(v['UID']) for v in msgs.itervalues()]
+            low = min(v)
+            high = max(v)
+
+            if high <= self.getLastUID():
+                self.printInfo("No new messages found")
+            
+            else:
+                if self.getLastUID() == 0:
+                    msgSet = imap4.MessageSet(low, high)
+                else:
+                    msgSet = imap4.MessageSet(max(low, self.getLastUID() + 1), high)
+                
+                d = self.proto.fetchMessage(msgSet, uid=True)
+                d.addCallback(self.fetchMessages).addCallback(self.disconnect)
+                
+        finally:
+            self.restorePreviousView()
+            
+    # In Twisted Reactor 
+    def disconnect(self, result = None):
+        
+        if __debug__:
+            self.printCurrentView("disconnect")
+
+        self.proto.close()
+        self.proto.transport.loseConnection()
+
+    # In Twisted Reactor 
+    def fetchMessages(self, msgs):
+        
+        if __debug__:
+            self.printCurrentView("fetchMessages")
+
+        self.setViewCurrent()       
+      
+        try:
+            """ Refresh our view before adding items to our mail account
+                and commiting. Will not cause merge conflicts since
+                no data changed in view in yet """ 
+            self.view.commit()
+    
+            totalDownloaded = 0  
+
+            for msg in msgs:
+                repMessage = make_message(msgs[msg]['RFC822'])
+                self.account.downloadedMail.append(repMessage)
+
+                uid = long(msgs[msg]['UID'])
+            
+                if uid > self.getLastUID():
+                    self.setLastUID(uid)
+                    totalDownloaded += 1
+
+            self.downloadedStr = "%d messages downloaded to Chandler" % (totalDownloaded)
+                      
+        finally:
+            self.restorePreviousView()
+            
+        """Commit the view in a Twisted thread to prevent blocking"""  
+        self.commitView()
+           
+            
+    def _viewCommitSuccess(self):
+        super(IMAPDownloader, self)._viewCommitSuccess()
+        
+        self.printInfo(self.downloadedStr)
+        self.downloadedStr = None
+
+        self.account.setPinned(False)
+        
+              
+    # In Twisted Reactor or in Thread    
+    def getLastUID(self):
+        return self.account.messageDownloadSequence
+    
+    # In Twisted Reactor or in Thread
+    def setLastUID(self, uid):
+        self.account.messageDownloadSequence = uid
+        
+    # In Twisted Reactor or in Thread        
+    def getAccount(self):   
+        
+        accountKind = Mail.MailParcel.getEmailAccountKind()
+        account = accountKind.findUUID(self.accountUUID)
+        
+        if account is None: 
+            self.log.error("No Account for UUID: %s"% self.account.itsUUID)
+    
+        return account
+
+    # In Twisted Reactor or in Thread        
+    def printInfo(self, info):
+
+        if self.account.serverPort != 143:
+            str = "[Server: %s:%d User: %s] %s" % (self.account.serverName, 
+                                                   self.account.serverPort,  
+                                                   self.account.accountName, info)
+        else:
+            str = "[Server: %s User: %s] %s" % (self.account.serverName, 
+                                                self.account.accountName, info)
+            
+        self.log.info(str)
+
+        
+           
+def format_addr(addr):
+    str = addr[0]
+    if str != '':
+        str = str + ' '
+    str = str + '<' + addr[1] + '>'
+    return str
+        
+
+def make_message(data):
+    msg = email.message_from_string(data)
+
+    m = Mail.MailMessage()
+    
+    if m is None:
+        print "MailMessage was NULL"
+        return None
+    
+    m.dateSent = DateTime.mktime(Utils.parsedate(msg['Date']))
+    m.subject = msg['Subject']
+
+    # XXX replyAddress should really be the Reply-to header, not From
+    m.replyAddress = Mail.EmailAddressEmailAddress()
+    m.replyAddress.emailAddress = format_addr(Utils.parseaddr(msg['From']))
+    
+    m.toAddress = []
+    for addr in Utils.getaddresses(msg.get_all('To', [])):
+        ea = Mail.EmailAddress()
+        ea.emailAddress = format_addr(addr)
+        m.toAddress.append(ea)
+    
+    m.ccAddress = []
+    for addr in Utils.getaddresses(msg.get_all('Cc', [])):
+        ea = Mail.EmailAddress()
+        ea.emailAddress = format_addr(addr)
+        m.ccAddress.append(ea)
+
+    return m



More information about the Commits mailing list