view ImapFeed.py @ 8:4d61c56473c2 default tip

Fixed a problem where some feeds would have unpickleable expatreaders.
author Atul Varma <varmaa@toolness.com>
date Fri, 18 Apr 2008 17:13:02 -0700
parents c461e818f4ca
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)