[Commits] (bkirsch) Refactored mail messaging logic by moving imap specific code in to imap.py and message parsing code in to message.py

commits at osafoundation.org commits at osafoundation.org
Mon Aug 2 12:49:08 PDT 2004


Commit by: bkirsch
Modified files:
chandler/parcels/osaf/mail/imap.py None 1.1
chandler/parcels/osaf/mail/message.py None 1.1
chandler/parcels/osaf/mail/IMAPMailTask.py 1.11 1.12

Log message:
Refactored mail messaging logic by moving imap specific code in to imap.py and message parsing code in to message.py

ViewCVS links:
http://cvs.osafoundation.org/index.cgi/chandler/parcels/osaf/mail/imap.py?rev=1.1&content-type=text/vnd.viewcvs-markup
http://cvs.osafoundation.org/index.cgi/chandler/parcels/osaf/mail/message.py?rev=1.1&content-type=text/vnd.viewcvs-markup
http://cvs.osafoundation.org/index.cgi/chandler/parcels/osaf/mail/IMAPMailTask.py.diff?r1=text&tr1=1.11&r2=text&tr2=1.12

Index: chandler/parcels/osaf/mail/IMAPMailTask.py
diff -u chandler/parcels/osaf/mail/IMAPMailTask.py:1.11 chandler/parcels/osaf/mail/IMAPMailTask.py:1.12
--- chandler/parcels/osaf/mail/IMAPMailTask.py:1.11	Fri Jul 30 11:35:19 2004
+++ chandler/parcels/osaf/mail/IMAPMailTask.py	Mon Aug  2 12:49:06 2004
@@ -1,22 +1,12 @@
-__revision__  = "$Revision: 1.11 $"
-__date__      = "$Date: 2004/07/30 18:35:19 $"
+__revision__  = "$Revision: 1.12 $"
+__date__      = "$Date: 2004/08/02 19:49:06 $"
 __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 repository.persistence.RepositoryView as RepositoryView
-import mx.DateTime as DateTime
-import email as email
-import email.Utils as Utils
-import logging as logging
-import repository.util.UUID as UUID
+import repository.item.Query as Query
+import imap as imap
 
 
 class MailDownloadAction(Action.Action):
@@ -47,416 +37,4 @@
                 logging.info("IMAP MAIL TASK CHECKING FOR NEW MAIL")
                 printed = True
 
-            IMAPDownloader(account).getMail()
-
-
-class ChandlerIMAP4Client(imap4.IMAP4Client):
-
-    def serverGreeting(self, caps):
-        """
-        This method overides C{imap4.IMAP4Client}.
-
-        It creates a C{defer.Deferred} and adds its factory callback and errorback
-        methods to the C{defer.Deferred}.
-
-        @param caps: The list of server CAPABILITIES
-        @type caps: dict
-        @return C{None}
-        """
-
-        self.serverCapabilities =  self.__disableTLS(caps)
-
-        d = defer.Deferred()
-        d.addCallback(self.factory.callback, self)
-        d.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):
-        """
-        A C{protocol.ClientFactory} that creates C{ChandlerIMAP4Client} instances
-        and stores the callback and errback to be used by the C{ChandlerIMAP4Client} instances
-
-        @param callback: A method name to call when a C{ChandlerIMAP4Client} connects
-                        to a IMAP Server
-        @type callback: string
-        @param errback: A method name to call if an error is thrown in the C{ChandlerIMAPClient}
-                        C{defer.Deferred} callback chain
-        @type errback: string
-        @return: C{None}
-        """
-
-        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: '%s'", reason)
-
-
-class MailException(Exception):
-    pass
-
-class IMAPDownloader(RepositoryView.AbstractRepositoryViewManager):
-
-    def __init__(self, account):
-        """
-        Creates a C{IMAPDownload} instance
-        @param account: An Instance of C{EmailAccountKind}
-        @type account: C{EmailAccountKind}
-        @return: C{None}
-        """
-
-        if account is None:
-            raise MailException("You must pass in a Mail Account instance")
-
-        viewName = "%s_%s" % (account.displayName, str(UUID.UUID()))
-        super(IMAPDownloader, self).__init__(Globals.repository, viewName)
-
-        self.proto = None
-        self.accountUUID = account.itsUUID
-        self.account = None
-        self.downloadedStr = None
-
-
-    def getMail(self):
-        """
-        This method retrieves all mail in an IMAP Server INBOX that has a
-        UID (RFC3501) greater than the UID of the last message downloaded.
-
-        If this is the first time downloading mail, all mail in the INBOX will
-        be downloaded. On the next check only mail greater than the last UID
-        will be downloaded.
-
-        This method is executed in the current thread and calls C{reactor.callFromThread}
-        to utilize a C{imap4.IMAP4Client} via the C{TwistedReactorManager} to connect to an
-        IMAP Server.
-
-        @return: C{None}
-
-        """
-        if __debug__:
-            self.printCurrentView("getMail")
-
-        reactor.callFromThread(self.__getMail)
-
-    def __getMail(self):
-
-        self.setViewCurrent()
-
-        try:
-            if __debug__: 
-                self.printCurrentView("__getMail")
-
-            self.account = self.__getAccount()
-            assert self.account is not None, "Account is None"
-
-            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)
- 
-    def printAccount(self):
-        """
-        Utility method that prints out C{EmailAccountKind} information for debugging
-        purposes
-        @return: C{None}
-        """
-
-        self.printCurrentView("printAccount")
-
-        if self.account is None:
-            return
-
-        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)
-
-    def catchErrors(self, result):
-        """
-        This method captures all errors thrown while in the Twisted Reactor Thread.
-        @return: C{None}
-        """
-
-        self.log.error("Twisted Error %s" % result)
-
-    def loginClient(self, result, proto):
-        """
-        This method is a Twisted C{defer.Deferred} callback that logs in to an IMAP Server
-        based on the account information stored in a C{EmailAccountKind}.
-
-        @param result: A Twisted callback result 
-        @type result: Could be anything
-        @param proto: The C{ChandlerIMAP4Client} protocol instance
-        @type proto: C{ChandlerIMAP4Client}
-        @return: C{None}
-        """
-
-        self.setViewCurrent()
-
-        try:
-            if __debug__: 
-                self.printCurrentView("loginClient")
-
-            """ Save the IMAP4Client instance """
-            self.proto = proto
-
-            """ Login using plain text login """
-
-            assert self.account is not None, "Account is None can not login client"
-
-            return self.proto.login(str(self.account.accountName), 
-                                    str(self.account.password)).addCallback(self.__selectInbox)
-        finally:
-           self.restorePreviousView()
-
-
-    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)
-
-    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()
-
-
-    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()
-
-    def __disconnect(self, result = None):
-
-        if __debug__:
-            self.printCurrentView("disconnect")
-
-        self.proto.close()
-        self.proto.transport.loseConnection()
-
-    def __fetchMessages(self, msgs):
-
-        if __debug__:
-            self.printCurrentView("fetchMessages")
-
-        assert self.account is not None, "Can not fetchMessages Email Account is None"
-
-        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 thread to prevent blocking""" 
-        self.commitView(True)
-
-
-    def _viewCommitSuccess(self):
-        """
-        Overides C{RepositoryView.AbstractRepositoryViewManager}. 
-        It posts a commit event to the GUI thread, unpins the C{EmailAccountKind} from 
-        memory, and writes commit info to the logger
-        @return: C{None}
-        """
-
-        Globals.wxApplication.PostAsyncEvent(Globals.repository.commit)
-
-        self.__printInfo(self.downloadedStr)
-        self.downloadedStr = None
-
-        self.account.setPinned(False)
-        self.account = None
-
-
-    def __getLastUID(self):
-        return self.account.messageDownloadSequence
-
-    def __setLastUID(self, uid):
-        self.account.messageDownloadSequence = uid
-
-    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
-
-    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):
-    """
-    This method formats an email address
-
-    @param addr: The email address to format
-    @type addr: list
-    @return: C{string}
-    """
-
-    str = addr[0]
-    if str != '':
-        str = str + ' '
-    str = str + '<' + addr[1] + '>'
-    return str
-
-
-def make_message(data):
-    """
-    This method converts a email message string to
-    a Chandler C{Mail.MailMessage} object
-
-    @param data: A string representation of a mail message
-    @type data: string
-    @return: C{Mail.MailMessage}
-    """
-
-    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.dateReceived = DateTime.now()
-
-    if msg['Subject'] is None:
-        m.subject = ""
-    else:
-        m.subject = msg['Subject']
-
-    # XXX replyAddress should really be the Reply-to header, not From
-    m.replyAddress = Mail.EmailAddress()
-    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
+            imap.IMAPDownloader(account).getMail()



More information about the Commits mailing list