view ImapFeed.py @ 7:c461e818f4ca

Changed ImapFeed.py so that it now looks for unread and flagged (starred in gmail) messages. This also looks like it will solve the problem w/ marking an entire conversation as unread in gmail, since starring a conversation doesn't make every single msg in the conversation flagged, it only flags the latest message.
author Atul Varma <varmaa@toolness.com>
date Sat, 05 Apr 2008 22:49:39 -0700
parents df9d4e704257
children
line wrap: on
line source

import imaplib
import time
from email.feedparser import FeedParser
from email.utils import parsedate
import elementtree.ElementTree as ET

from LocalAuth import IMAP_AUTH
from Config import IMAP_FEEDS

def getFeedInfo():
    for feed in IMAP_FEEDS:
        info = dict( importance = 1 )
        info.update( feed )
        yield info

def getImapUnreadMailInfo( server, port, username, password,
                           mailbox = "INBOX", isSsl = True ):
    if isSsl:
        imap = imaplib.IMAP4_SSL( server, port )
    else:
        imap = imaplib.IMAP4( server, port )

    imap.login( username, password )
    imap.select( mailbox )

    # For more information on searching IMAP, see:
    # http://tools.ietf.org/html/rfc3501#section-6.4.4
    typ, msgnums = imap.search( None, "(OR (FLAGGED) (UNSEEN))" )

    if typ != "OK":
        raise IOError( "Error searching IMAP folder" )
    msgnums = [ int( num ) for num in msgnums[0].split() ]
    for num in msgnums:
        typ, result = imap.fetch( str(num), "(BODY.PEEK[HEADER])" )
        if typ != "OK":
            raise IOError( "Error fetching IMAP messages" )
        headers = result[0][1]
        parser = FeedParser()
        parser.feed( headers )
        message = parser.close()
        # TODO: Make sure that the timezone info is converted properly.
        timestamp = time.mktime( parsedate(message["Date"]) )
        yield dict( timestamp = timestamp,
                    sender = message["From"],
                    subject = message["Subject"] )
    imap.close()
    imap.logout()

def _addTextNode( element, name, text ):
    subElement = ET.SubElement( element, name )
    subElement.text = text

def makeFeedFromMailInfo( infoIterator, url ):    
    root = ET.Element( "rss" )
    root.set( "version", "2.0" )
    channel = ET.SubElement( root, "channel" )
    for info in infoIterator:
        item = ET.SubElement( channel, "item" )
        _addTextNode( item, "title", info["subject"] )
        _addTextNode( item, "pubDate",
                      time.ctime( info["timestamp"] ) )
        _addTextNode( item, "link", url )
        _addTextNode( item, "description",
                      "From %s" % info["sender"] )
    tree = ET.ElementTree( root )

    import StringIO
    strFile = StringIO.StringIO()
    tree.write( strFile )
    return strFile.getvalue()

def generateFeed( feed, auth ):
    imapParams = dict( server = feed["server"],
                       port = feed["port"],
                       mailbox = feed["mailbox"],
                       isSsl = feed["isSsl"] )
    imapParams.update( auth[imapParams["server"]] )
    open( feed["filename"], "w" ).write(
        makeFeedFromMailInfo( getImapUnreadMailInfo(**imapParams),
                              feed["url"] )
        )

def update( feed ):
    print "Generating feed for %s" % feed["name"]
    generateFeed( feed, IMAP_AUTH)