Commits

Juan Gomez committed a5851ad

Initial upload, finished code, compliant with PEP 8

  • Participants

Comments (0)

Files changed (1)

File newsfetcher.py

+# newsfetcher.py - fetches news from an NNTP group and sends them by email
+#
+# Copyright 2010 Juan Gomez <juandg@gmail.com>
+#
+# This software may be used and distributed according to the terms of the
+# GNU General Public License version 2, incorporated herein by reference.
+
+
+from datetime import datetime, timedelta
+from nntplib import NNTP, NNTPError
+from smtplib import SMTP
+from email.mime.text import MIMEText
+from email.mime.multipart import MIMEMultipart
+
+
+__author__ = 'JuanDG'
+__copyright__ = "Copyright (C) 2010 Juan Gomez"
+__license__ = "Public Domain"
+__version__ = "1.0"
+
+
+class ProtocolProxy():
+    '''Base class for all protocol proxies. It acts a litle bit as a factory
+    because it's really the one that instantiates the actual protocol it also
+    aides in testing'''
+
+    def __init__(self, protocol, server_uri, port):
+        self.uri = server_uri
+        self.port = port
+        self.server = protocol(self.uri, self.port)
+
+class NNTPGroupProxy(ProtocolProxy):
+    '''Proxy class for the NNTP news group'''
+
+    def __init__(self, nntp_server_uri, name, port=119):
+        try:
+            ProtocolProxy.__init__(self, NNTP, nntp_server_uri, port)
+        except NNTPError as error:
+            print(error)
+        else:
+            resp, self.post_count, self.first_id, self.last_id, self.name = \
+                                                self.server.group(name)
+
+    def get_new_news(self, date):
+        '''gets all the newsgroup post that have a date later than the
+        supplied 'date'
+
+        This is a very powerful generator method that showcases all the
+        strenghts of Python it returns an iterator (via the 'yields' keyword)
+        and it uses the power of Python's functional programming to filter all
+        the posts headers'''
+
+        self.date = date
+        resp, subject_list = self.server.xhdr('subject', self.first_id + '-' +
+                                                         self.last_id)
+        for id, date_header in filter(self.__is_new_post,
+                                      map(self.__get_post_date, subject_list)):
+            yield NNTPNewsPost(self, id)
+
+    def __is_new_post(self, date_header):
+        id, str_date = date_header
+        return datetime.strptime(str_date.lstrip('Date: ')[:-6],
+                                 '%a, %d %b %Y %H:%M:%S') >= self.date
+
+    def __get_post_date(self, subject):
+        id, str_subject = subject
+        return (id, filter(self.__get_date_header, self.server.head(id)[3])[0])
+
+    def __get_date_header(self, header):
+        return header.startswith('Date')
+
+
+class NNTPNewsPost:
+    '''Helper class to encapsultae the fetching of the actual NNTP post'''
+
+    def __init__(self, nntp_proxy, id):
+        self.__proxy = nntp_proxy
+        self.msg_id = id
+
+    def get_post_body(self):
+        resp, line_count, self.msg_id, message = \
+                                        self.__proxy.server.body(self.msg_id)
+        return message
+
+    def get_post_headers(self):
+        resp, header_count, self.msg_id, headers = \
+                                        self.__proxy.server.head(self.msg_id)
+        return headers
+
+
+class EmailProxy(ProtocolProxy):
+    '''Proxy class for the email server'''
+
+    def __init__(self, smtp_server_uri, smtp_username, smtp_password,
+                 port=587):
+        ProtocolProxy.__init__(self, SMTP, smtp_server_uri, port)
+        self.user = smtp_username
+        self.password = smtp_password
+
+    def send_msg(self, from_, to_, subject, body):
+        self.server.ehlo()
+        self.server.starttls()
+        self.server.ehlo()
+        self.server.login(self.user, self.password)
+
+        email_message = MIMEMultipart()
+
+        email_message['From'] = from_
+        email_message['To'] = to_
+        email_message['Subject'] = subject
+        email_message.attach(MIMEText(body))
+
+        self.server.sendmail(from_, to_, email_message.as_string())
+        self.server.close()
+
+
+def main():
+    '''Main execution of the News Fetcher program'''
+
+    nntp_uri = 'news.cs.mum.edu'
+    nntp_group = 'courses.de.cs425'
+
+    smtp_uri = 'smtp.gmail.com'
+    smtp_user = '<user>@gmail.com'
+    smtp_password = '<password>'
+
+    news_proxy = NNTPGroupProxy(nntp_server_uri=nntp_uri, name=nntp_group)
+    diff = timedelta(days=-2)
+    last_date = datetime.now() + diff
+    message_body = ''
+    for post in news_proxy.get_new_news(last_date):
+        message_body += '\n'.join(post.get_post_headers()) + '\n' + \
+                        '\n'.join(post.get_post_body()) + \
+                        '\n \n-----new message-----\n\n'
+
+    mail_proxy = EmailProxy(smtp_server_uri=smtp_uri,
+                            smtp_username=smtp_user,
+                            smtp_password=smtp_password)
+
+    sender = '<user>@gmail.com'
+    recipients = '<someone@email.com>'
+    subject = 'Latest Posts on \'courses.de.cs425\''
+    mail_proxy.send_msg(from_=sender, to_=recipients, subject=subject,
+                       body=message_body[:-25])
+
+
+if __name__ == '__main__':
+    main()