| |   |
| 29 | 29 | |
| 30 | 30 | import pygtk |
| 31 | 31 | pygtk.require('2.0') |
| 32 | | import time |
| 33 | 32 | import gtk, gobject |
| 34 | 33 | import locale, gettext |
| 35 | 34 | import sys, os |
| … | … | |
| 36 | 36 | from os.path import dirname, pardir |
| 37 | 37 | from gettext import gettext as _ |
| 38 | 38 | from ConfigParser import ConfigParser |
| 39 | | from gmailatom import GmailAtom |
| 39 | from gsentinel.gmailatom import GmailAtom |
| 40 | 40 | from gsentinel.plugin import PluginManager |
| 41 | 41 | |
| 42 | 42 | APP_NAME = "Gmail-Sentinel" |
| 43 | 43 | APP_VERSION = "0.2_beta2" |
| 44 | | APP_COPYRIGHT = "(C)2008 Rodrigo Lazo.\n" + _("GoogleMail and Gmail are trademarks of Google, Inc.") |
| 44 | APP_COPYRIGHT = "(C)2008 Rodrigo Lazo.\n" + \ |
| 45 | _("GoogleMail and Gmail are trademarks of Google, Inc.") |
| 45 | 46 | APP_DESCRIPTION = _('GoogleMail Sentinel') |
| 46 | 47 | APP_WEBSITE = 'http://code.google.com/p/gmail-sentinel/' |
| 47 | 48 | |
| … | … | |
| 102 | 102 | dialog.set_comments(APP_DESCRIPTION) |
| 103 | 103 | dialog.set_website(APP_WEBSITE) |
| 104 | 104 | dialog.set_logo(gtk.gdk.pixbuf_new_from_file(self.gmail_icon)) |
| 105 | | dialog.set_translator_credits(_("translator-credits")) |
| 105 | dialog.set_translator_credits(_("translator-credits")) |
| 106 | 106 | dialog.run() |
| 107 | 107 | dialog.destroy() |
| 108 | 108 | |
| … | … | |
| 119 | 119 | """Initializer. Creates the status icon and opens the |
| 120 | 120 | connection.""" |
| 121 | 121 | self.config = ConfigParser() |
| 122 | | self.plugin_manager = PluginManager() |
| 122 | self.read_msgs = list() |
| 123 | self.plugin_manager = PluginManager() |
| 123 | 124 | self.connection = None |
| 124 | 125 | self.unread_msg_count = 0 |
| 125 | 126 | |
| 126 | | logging.info("[Main] Loading configuration file") |
| 127 | logging.info("[Main] Loading configuration file") |
| 127 | 128 | if not self.load_configuration(): |
| 128 | 129 | logging.critical("[Main] Configuration file does not exist.") |
| 129 | 130 | sys.exit(1) |
| 130 | 131 | |
| 131 | | # plugin system initialization |
| 132 | | logging.info("[Main] Starting PluginManager") |
| 133 | | self.plugin_manager.initialize(self.config.get('plugins', 'path'), |
| 134 | | self.config.get('plugins', 'list')) |
| 135 | | logging.info("[Main] Creating StatusIcon") |
| 132 | logging.info("[Main] Creating StatusIcon") |
| 136 | 133 | self.status_icon = GmailStatusIcon(self.config.get('media', 'path')) |
| 137 | | |
| 134 | |
| 135 | logging.info("[Main] Starting PluginManager") |
| 136 | self.plugin_manager.initialize(self.config) |
| 137 | |
| 138 | 138 | # Make sure the status icon shows up |
| 139 | 139 | while gtk.events_pending(): |
| 140 | 140 | gtk.main_iteration(True) |
| 141 | | logging.info("[Main] First run. Checking for new mail") |
| 141 | logging.info("[Main] First run. Checking for new mail") |
| 142 | 142 | if self.connect() : |
| 143 | 143 | self.check_inbox() |
| 144 | 144 | # The multiplier is to simplify the configuration |
| 145 | 145 | # file. Converts the miliseconds into seconds |
| 146 | | logging.info("[Main] Registering interval function") |
| 146 | logging.info("[Main] Registering interval function") |
| 147 | 147 | interval = int(self.config.get('gmail', 'checkinterval'))*1000 |
| 148 | 148 | self.main_timer = gobject.timeout_add(interval, self.check_inbox) |
| 149 | | logging.info("[Main] Sleeping interval %d miliseconds. Sleeping now.", interval) |
| 149 | logging.info("[Main] Sleeping interval %d miliseconds. Sleeping now.", |
| 150 | interval) |
| 150 | 151 | |
| 151 | 152 | def load_configuration (self): |
| 152 | 153 | """Loads the configuration. If file does not exist returns |
| … | … | |
| 170 | 170 | self.connection = GmailAtom(self.config.get('gmail','username'), |
| 171 | 171 | self.config.get('gmail','password')) |
| 172 | 172 | except: |
| 173 | | logging.error("[Main] Login failed, will retry later") |
| 173 | logging.exception("[Main] Login failed, will retry later") |
| 174 | 174 | self.status_icon.set_tooltip(_("Connection failed")) |
| 175 | 175 | return False |
| 176 | | if self.connection.refreshInfo(): |
| 177 | | logging.info("[Main] Connection open") |
| 178 | | self.status_icon.set_tooltip(_("Connected")) |
| 179 | | return True |
| 180 | | else: |
| 181 | | logging.error("[Main] Connection failed") |
| 182 | | self.status_icon.set_tooltip(_("Not connected")) |
| 183 | | return False |
| 176 | if self.connection.refreshInfo(): |
| 177 | logging.info("[Main] Connection open") |
| 178 | self.status_icon.set_tooltip(_("Connected")) |
| 179 | return True |
| 180 | else: |
| 181 | logging.error("[Main] Connection failed") |
| 182 | self.status_icon.set_tooltip(_("Not connected")) |
| 183 | return False |
| 184 | 184 | |
| 185 | 185 | def check_inbox(self): |
| 186 | 186 | """Checks for new mail.""" |
| 187 | 187 | if self.connection is None or self.connect() is False: |
| 188 | 188 | # Try again latter |
| 189 | 189 | return True |
| 190 | | logging.info("[Main] Checking for new mail.") |
| 190 | logging.info("[Main] Checking for new mail.") |
| 191 | 191 | while gtk.events_pending(): |
| 192 | 192 | gtk.main_iteration( True ) |
| 193 | 193 | |
| 194 | 194 | if not self.has_new_mail(): |
| 195 | | logging.info("[Main] No new messages") |
| 196 | | self.plugin_manager.emit_signal('no_new_messages') |
| 195 | logging.info("[Main] No new messages") |
| 196 | self.plugin_manager.emit_signal('no_new_messages') |
| 197 | 197 | # Check again later |
| 198 | | self.unread_msg_count > 0 or \ |
| 198 | len(self.read_msgs) == 0 or \ |
| 199 | 199 | self.status_icon.set_from_file(self.status_icon.inactive_icon) |
| 200 | 200 | return True |
| 201 | 201 | self.status_icon.set_from_file(self.status_icon.active_icon) |
| 202 | 202 | count = self.connection.getUnreadMsgCount() |
| 203 | | logging.info("[Main] %s New messages found", count) |
| 204 | | last_message = self.get_last_message() |
| 205 | | self.plugin_manager.emit_signal('new_messages', messages=self.connection.getMsgList()) |
| 203 | logging.info("[Main] %s New messages found", count) |
| 204 | self.plugin_manager.emit_signal('new_messages', |
| 205 | messages=self.connection.getMsgList()) |
| 206 | 206 | return True |
| 207 | 207 | |
| 208 | 208 | def has_new_mail (self): |
| 209 | 209 | """Checks if new mail has arrived.""" |
| 210 | # TODO: new mail != read mail != no mail |
| 210 | 211 | try: |
| 211 | | # Hackerish? |
| 212 | 212 | self.connection.refreshInfo() |
| 213 | | current_msg_count = self.connection.getUnreadMsgCount() |
| 214 | | new_mail = current_msg_count > 0 and \ |
| 215 | | current_msg_count != self.unread_msg_count |
| 216 | | self.unread_msg_count = current_msg_count |
| 217 | | return new_mail |
| 218 | | except: |
| 219 | | logging.error("[Main] getUnreadMsgCount() failed, will try again later") |
| 220 | | self.unread_msg_count = 0 |
| 213 | msgs = self.connection.getMsgList() |
| 214 | # are all the messages already seen? |
| 215 | set1 = set(x["id"] for x in self.read_msgs) |
| 216 | same_messages = set1.issuperset(x["id"] for x in msgs) |
| 217 | if not same_messages: |
| 218 | self.read_msgs = msgs |
| 219 | return not same_messages |
| 220 | except Exception, ex: |
| 221 | logging.exception("[Main] getUnreadMsgCount() failed, will try again later") |
| 221 | 222 | return False |
| 222 | 223 | |
| 223 | | def get_last_message (self): |
| 224 | | """ Returns the sender, subject and snippet of the last |
| 225 | | message retrieved.""" |
| 226 | | alist = self.connection.getMsgList() |
| 227 | | return {'sender' : alist[0]['author_name'], |
| 228 | | 'subject' : alist[0]['title'], |
| 229 | | 'snippet' : alist[0]['summary'][:40] + "..."} |
| 230 | | |
| 231 | 224 | def main (self): |
| 232 | 225 | """ Mailoop""" |
| 233 | 226 | gtk.main() |
| 234 | 227 | |
| 235 | 228 | if __name__ == "__main__": |
| 236 | 229 | # Path definition |
| 237 | | SHARE_PATH = os.path.abspath(os.path.join(dirname(__file__), pardir, pardir, 'share')) |
| 230 | SHARE_PATH = os.path.abspath(os.path.join(dirname(__file__), |
| 231 | pardir, pardir, 'share')) |
| 238 | 232 | LOCALE_PATH = os.path.join(SHARE_PATH, 'locale') |
| 239 | 233 | |
| 240 | 234 | # L10n initialization |
| … | … | |
| 238 | 238 | |
| 239 | 239 | # Loggging configuration |
| 240 | 240 | logging.basicConfig(level=logging.INFO, |
| 241 | | format='%(asctime)s %(levelname)s %(message)s') |
| 241 | format='%(asctime)s %(levelname)s %(message)s') |
| 242 | 242 | |
| 243 | 243 | # app itself |
| 244 | 244 | notifier = Gnotify() |
| toggle raw diff |
--- a/gmail-sentinel.py
+++ b/gmail-sentinel.py
@@ -29,7 +29,6 @@ popups.
import pygtk
pygtk.require('2.0')
-import time
import gtk, gobject
import locale, gettext
import sys, os
@@ -37,12 +36,13 @@ import logging
from os.path import dirname, pardir
from gettext import gettext as _
from ConfigParser import ConfigParser
-from gmailatom import GmailAtom
+from gsentinel.gmailatom import GmailAtom
from gsentinel.plugin import PluginManager
APP_NAME = "Gmail-Sentinel"
APP_VERSION = "0.2_beta2"
-APP_COPYRIGHT = "(C)2008 Rodrigo Lazo.\n" + _("GoogleMail and Gmail are trademarks of Google, Inc.")
+APP_COPYRIGHT = "(C)2008 Rodrigo Lazo.\n" + \
+ _("GoogleMail and Gmail are trademarks of Google, Inc.")
APP_DESCRIPTION = _('GoogleMail Sentinel')
APP_WEBSITE = 'http://code.google.com/p/gmail-sentinel/'
@@ -102,7 +102,7 @@ class GmailStatusIcon(gtk.StatusIcon):
dialog.set_comments(APP_DESCRIPTION)
dialog.set_website(APP_WEBSITE)
dialog.set_logo(gtk.gdk.pixbuf_new_from_file(self.gmail_icon))
- dialog.set_translator_credits(_("translator-credits"))
+ dialog.set_translator_credits(_("translator-credits"))
dialog.run()
dialog.destroy()
@@ -119,34 +119,35 @@ class Gnotify:
"""Initializer. Creates the status icon and opens the
connection."""
self.config = ConfigParser()
- self.plugin_manager = PluginManager()
+ self.read_msgs = list()
+ self.plugin_manager = PluginManager()
self.connection = None
self.unread_msg_count = 0
- logging.info("[Main] Loading configuration file")
+ logging.info("[Main] Loading configuration file")
if not self.load_configuration():
logging.critical("[Main] Configuration file does not exist.")
sys.exit(1)
- # plugin system initialization
- logging.info("[Main] Starting PluginManager")
- self.plugin_manager.initialize(self.config.get('plugins', 'path'),
- self.config.get('plugins', 'list'))
- logging.info("[Main] Creating StatusIcon")
+ logging.info("[Main] Creating StatusIcon")
self.status_icon = GmailStatusIcon(self.config.get('media', 'path'))
-
+
+ logging.info("[Main] Starting PluginManager")
+ self.plugin_manager.initialize(self.config)
+
# Make sure the status icon shows up
while gtk.events_pending():
gtk.main_iteration(True)
- logging.info("[Main] First run. Checking for new mail")
+ logging.info("[Main] First run. Checking for new mail")
if self.connect() :
self.check_inbox()
# The multiplier is to simplify the configuration
# file. Converts the miliseconds into seconds
- logging.info("[Main] Registering interval function")
+ logging.info("[Main] Registering interval function")
interval = int(self.config.get('gmail', 'checkinterval'))*1000
self.main_timer = gobject.timeout_add(interval, self.check_inbox)
- logging.info("[Main] Sleeping interval %d miliseconds. Sleeping now.", interval)
+ logging.info("[Main] Sleeping interval %d miliseconds. Sleeping now.",
+ interval)
def load_configuration (self):
"""Loads the configuration. If file does not exist returns
@@ -169,71 +170,65 @@ class Gnotify:
self.connection = GmailAtom(self.config.get('gmail','username'),
self.config.get('gmail','password'))
except:
- logging.error("[Main] Login failed, will retry later")
+ logging.exception("[Main] Login failed, will retry later")
self.status_icon.set_tooltip(_("Connection failed"))
return False
- if self.connection.refreshInfo():
- logging.info("[Main] Connection open")
- self.status_icon.set_tooltip(_("Connected"))
- return True
- else:
- logging.error("[Main] Connection failed")
- self.status_icon.set_tooltip(_("Not connected"))
- return False
+ if self.connection.refreshInfo():
+ logging.info("[Main] Connection open")
+ self.status_icon.set_tooltip(_("Connected"))
+ return True
+ else:
+ logging.error("[Main] Connection failed")
+ self.status_icon.set_tooltip(_("Not connected"))
+ return False
def check_inbox(self):
"""Checks for new mail."""
if self.connection is None or self.connect() is False:
# Try again latter
return True
- logging.info("[Main] Checking for new mail.")
+ logging.info("[Main] Checking for new mail.")
while gtk.events_pending():
gtk.main_iteration( True )
if not self.has_new_mail():
- logging.info("[Main] No new messages")
- self.plugin_manager.emit_signal('no_new_messages')
+ logging.info("[Main] No new messages")
+ self.plugin_manager.emit_signal('no_new_messages')
# Check again later
- self.unread_msg_count > 0 or \
+ len(self.read_msgs) == 0 or \
self.status_icon.set_from_file(self.status_icon.inactive_icon)
return True
self.status_icon.set_from_file(self.status_icon.active_icon)
count = self.connection.getUnreadMsgCount()
- logging.info("[Main] %s New messages found", count)
- last_message = self.get_last_message()
- self.plugin_manager.emit_signal('new_messages', messages=self.connection.getMsgList())
+ logging.info("[Main] %s New messages found", count)
+ self.plugin_manager.emit_signal('new_messages',
+ messages=self.connection.getMsgList())
return True
def has_new_mail (self):
"""Checks if new mail has arrived."""
+ # TODO: new mail != read mail != no mail
try:
- # Hackerish?
self.connection.refreshInfo()
- current_msg_count = self.connection.getUnreadMsgCount()
- new_mail = current_msg_count > 0 and \
- current_msg_count != self.unread_msg_count
- self.unread_msg_count = current_msg_count
- return new_mail
- except:
- logging.error("[Main] getUnreadMsgCount() failed, will try again later")
- self.unread_msg_count = 0
+ msgs = self.connection.getMsgList()
+ # are all the messages already seen?
+ set1 = set(x["id"] for x in self.read_msgs)
+ same_messages = set1.issuperset(x["id"] for x in msgs)
+ if not same_messages:
+ self.read_msgs = msgs
+ return not same_messages
+ except Exception, ex:
+ logging.exception("[Main] getUnreadMsgCount() failed, will try again later")
return False
- def get_last_message (self):
- """ Returns the sender, subject and snippet of the last
- message retrieved."""
- alist = self.connection.getMsgList()
- return {'sender' : alist[0]['author_name'],
- 'subject' : alist[0]['title'],
- 'snippet' : alist[0]['summary'][:40] + "..."}
-
def main (self):
""" Mailoop"""
gtk.main()
if __name__ == "__main__":
# Path definition
- SHARE_PATH = os.path.abspath(os.path.join(dirname(__file__), pardir, pardir, 'share'))
+ SHARE_PATH = os.path.abspath(os.path.join(dirname(__file__),
+ pardir, pardir, 'share'))
LOCALE_PATH = os.path.join(SHARE_PATH, 'locale')
# L10n initialization
@@ -243,7 +238,7 @@ if __name__ == "__main__":
# Loggging configuration
logging.basicConfig(level=logging.INFO,
- format='%(asctime)s %(levelname)s %(message)s')
+ format='%(asctime)s %(levelname)s %(message)s')
# app itself
notifier = Gnotify() |
| |   |
| 0 | | #!/usr/bin/python |
| 1 | | # -*- coding: utf-8 -*- |
| 2 | | |
| 3 | | # gmailatom 0.0.2 |
| 4 | | # |
| 5 | | # by Juan Grande <juan.grande@gmail.com> |
| 6 | | # modified by Rodrigo Lazo <rlazo.paz@gmail.com> |
| 7 | | |
| 8 | | """ |
| 9 | | Gmailatom. |
| 10 | | |
| 11 | | Helps connection to Gmail using the atom interface. |
| 12 | | |
| 13 | | HOW TO USE: |
| 14 | | 1) Create an instance of 'GmailAtom' class. The two arguments |
| 15 | | its constructor take are the username (including '@gmail.com') |
| 16 | | and the password. |
| 17 | | 2) To retrieve the account status call 'refreshInfo()'. |
| 18 | | 3) To get the unread messages count call 'getUnreadMsgCount()'. |
| 19 | | You MUST call 'refreshInfo()' at least one time before using |
| 20 | | this method or it will return zero. |
| 21 | | 4) To get specific information about an unread email you must |
| 22 | | call the corresponding getter method passing to it the number |
| 23 | | of the message. The number zero represents the newest one. |
| 24 | | You MUST call 'refreshInfo()' at least one time before calling getMsgList |
| 25 | | |
| 26 | | The getMsgList returns a list of Messages (dictionary-like) with |
| 27 | | the following data: |
| 28 | | id |
| 29 | | title |
| 30 | | summary |
| 31 | | author_name |
| 32 | | author_email |
| 33 | | link |
| 34 | | """ |
| 35 | | |
| 36 | | from xml.sax.handler import ContentHandler |
| 37 | | from xml import sax |
| 38 | | import urllib2 |
| 39 | | |
| 40 | | # Because Message acts like a struct we only need to inheret from dict |
| 41 | | class Message (dict): |
| 42 | | """Message struct""" |
| 43 | | def __init__ (self): |
| 44 | | self.update( {'id' : "", |
| 45 | | 'title' : "", |
| 46 | | 'summary' : "", |
| 47 | | 'author_name' : "", |
| 48 | | 'author_email' : "", |
| 49 | | 'link' : "" } ) |
| 50 | | |
| 51 | | def __cmp__ (self, msg): |
| 52 | | """Messages are compared by id""" |
| 53 | | return cmp(self['id'], msg['id']) |
| 54 | | |
| 55 | | |
| 56 | | # Sax XML Handler |
| 57 | | class MailHandler(ContentHandler): |
| 58 | | """Sax XML Handler for gmail atom interface""" |
| 59 | | |
| 60 | | # Tags |
| 61 | | TAG_FEED = "feed" |
| 62 | | TAG_FULLCOUNT = "fullcount" |
| 63 | | TAG_ENTRY = "entry" |
| 64 | | TAG_TITLE = "title" |
| 65 | | TAG_SUMMARY = "summary" |
| 66 | | TAG_LINK = "link" |
| 67 | | TAG_ID = "id" |
| 68 | | TAG_AUTHOR = "author" |
| 69 | | TAG_NAME = "name" |
| 70 | | TAG_EMAIL = "email" |
| 71 | | |
| 72 | | # Path the information |
| 73 | | PATH_FULLCOUNT = [ TAG_FEED, TAG_FULLCOUNT ] |
| 74 | | PATH_ENTRY = [ TAG_FEED, TAG_ENTRY ] |
| 75 | | PATH_LINK = PATH_ENTRY + [ TAG_LINK ] |
| 76 | | PATH_ID = PATH_ENTRY + [ TAG_ID ] |
| 77 | | PATH_TITLE = PATH_ENTRY + [ TAG_TITLE ] |
| 78 | | PATH_SUMMARY = PATH_ENTRY + [ TAG_SUMMARY ] |
| 79 | | PATH_AUTHOR = PATH_ENTRY + [ TAG_AUTHOR ] |
| 80 | | PATH_AUTHOR_NAME = PATH_AUTHOR + [ TAG_NAME ] |
| 81 | | PATH_AUTHOR_EMAIL = PATH_AUTHOR + [ TAG_EMAIL ] |
| 82 | | |
| 83 | | def __init__(self): |
| 84 | | ContentHandler.__init__(self) |
| 85 | | self.entries = list() |
| 86 | | self.actual = list() |
| 87 | | self.mail_count = "0" |
| 88 | | self.current_msg = None |
| 89 | | |
| 90 | | def startDocument (self): |
| 91 | | """Document initialization""" |
| 92 | | del self.entries[:] |
| 93 | | del self.actual[:] |
| 94 | | self.mail_count = "0" |
| 95 | | self.current_msg = None |
| 96 | | |
| 97 | | def startElement( self, name, attrs): |
| 98 | | # update actual path |
| 99 | | self.actual.append(name) |
| 100 | | |
| 101 | | # Message link |
| 102 | | if self.actual == self.PATH_LINK: |
| 103 | | self.current_msg['link'] = attrs['href'] |
| 104 | | |
| 105 | | # add a new email to the list |
| 106 | | if name == "entry": |
| 107 | | self.current_msg = Message() |
| 108 | | |
| 109 | | def endElement( self, name): |
| 110 | | # update actual path |
| 111 | | if name == "entry": |
| 112 | | self.entries.append(self.current_msg.copy()) |
| 113 | | self.current_msg.clear() |
| 114 | | self.actual.pop() |
| 115 | | |
| 116 | | def characters( self, content): |
| 117 | | # New messages count |
| 118 | | if (self.actual == self.PATH_FULLCOUNT): |
| 119 | | self.mail_count = content |
| 120 | | |
| 121 | | # Message title |
| 122 | | if (self.actual == self.PATH_TITLE): |
| 123 | | self.current_msg['title'] += content |
| 124 | | |
| 125 | | # Message summary |
| 126 | | if (self.actual == self.PATH_SUMMARY): |
| 127 | | self.current_msg['summary'] += content |
| 128 | | |
| 129 | | # Message id |
| 130 | | if self.actual == self.PATH_ID: |
| 131 | | self.current_msg['id'] += content |
| 132 | | |
| 133 | | # Message author name |
| 134 | | if (self.actual == self.PATH_AUTHOR_NAME): |
| 135 | | self.current_msg['author_name'] += content |
| 136 | | |
| 137 | | # Message author email |
| 138 | | if (self.actual == self.PATH_AUTHOR_EMAIL): |
| 139 | | self.current_msg['author_email'] += content |
| 140 | | |
| 141 | | def getUnreadMsgCount(self): |
| 142 | | return int(self.mail_count) |
| 143 | | |
| 144 | | # The mail class |
| 145 | | class GmailAtom: |
| 146 | | """Gmail's atom interface proxy""" |
| 147 | | |
| 148 | | realm = "New mail feed" |
| 149 | | host = "https://mail.google.com" |
| 150 | | url = host + "/mail/feed/atom" |
| 151 | | |
| 152 | | def __init__(self, user, pswd): |
| 153 | | self.mh = MailHandler() |
| 154 | | # initialize authorization handler |
| 155 | | auth_handler = urllib2.HTTPBasicAuthHandler() |
| 156 | | auth_handler.add_password( self.realm, self.host, user, pswd) |
| 157 | | opener = urllib2.build_opener(auth_handler) |
| 158 | | urllib2.install_opener(opener) |
| 159 | | |
| 160 | | def sendRequest(self): |
| 161 | | """Opens a conection with the remote server""" |
| 162 | | del self.mh.entries[:] |
| 163 | | return urllib2.urlopen(self.url) |
| 164 | | |
| 165 | | def refreshInfo(self): |
| 166 | | """Requests information from the remote server and parses the |
| 167 | | information retrieved""" |
| 168 | | try: |
| 169 | | sax.parseString( self.sendRequest().read(), self.mh) |
| 170 | | return True |
| 171 | | except urllib2.URLError: |
| 172 | | return False |
| 173 | | |
| 174 | | def getMsgList (self): |
| 175 | | """Returns a list containing the new messages or empty. It |
| 176 | | will replace all the getMsg* functions in the next |
| 177 | | release. Every entry on the list acts like a dictionary: |
| 178 | | |
| 179 | | old api |
| 180 | | getMsgSummary(1) #Get the summary of the first message |
| 181 | | |
| 182 | | new api |
| 183 | | l = getMsgList() |
| 184 | | l[0]['summary']""" |
| 185 | | return self.mh.entries |
| 186 | | |
| 187 | | def getUnreadMsgCount(self): |
| 188 | | return self.mh.getUnreadMsgCount() |
| toggle raw diff |
--- a/gmailatom.py
+++ /dev/null
@@ -1,189 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# gmailatom 0.0.2
-#
-# by Juan Grande <juan.grande@gmail.com>
-# modified by Rodrigo Lazo <rlazo.paz@gmail.com>
-
-"""
-Gmailatom.
-
-Helps connection to Gmail using the atom interface.
-
-HOW TO USE:
-1) Create an instance of 'GmailAtom' class. The two arguments
- its constructor take are the username (including '@gmail.com')
- and the password.
-2) To retrieve the account status call 'refreshInfo()'.
-3) To get the unread messages count call 'getUnreadMsgCount()'.
- You MUST call 'refreshInfo()' at least one time before using
- this method or it will return zero.
-4) To get specific information about an unread email you must
- call the corresponding getter method passing to it the number
- of the message. The number zero represents the newest one.
- You MUST call 'refreshInfo()' at least one time before calling getMsgList
-
- The getMsgList returns a list of Messages (dictionary-like) with
- the following data:
- id
- title
- summary
- author_name
- author_email
- link
-"""
-
-from xml.sax.handler import ContentHandler
-from xml import sax
-import urllib2
-
-# Because Message acts like a struct we only need to inheret from dict
-class Message (dict):
- """Message struct"""
- def __init__ (self):
- self.update( {'id' : "",
- 'title' : "",
- 'summary' : "",
- 'author_name' : "",
- 'author_email' : "",
- 'link' : "" } )
-
- def __cmp__ (self, msg):
- """Messages are compared by id"""
- return cmp(self['id'], msg['id'])
-
-
-# Sax XML Handler
-class MailHandler(ContentHandler):
- """Sax XML Handler for gmail atom interface"""
-
- # Tags
- TAG_FEED = "feed"
- TAG_FULLCOUNT = "fullcount"
- TAG_ENTRY = "entry"
- TAG_TITLE = "title"
- TAG_SUMMARY = "summary"
- TAG_LINK = "link"
- TAG_ID = "id"
- TAG_AUTHOR = "author"
- TAG_NAME = "name"
- TAG_EMAIL = "email"
-
- # Path the information
- PATH_FULLCOUNT = [ TAG_FEED, TAG_FULLCOUNT ]
- PATH_ENTRY = [ TAG_FEED, TAG_ENTRY ]
- PATH_LINK = PATH_ENTRY + [ TAG_LINK ]
- PATH_ID = PATH_ENTRY + [ TAG_ID ]
- PATH_TITLE = PATH_ENTRY + [ TAG_TITLE ]
- PATH_SUMMARY = PATH_ENTRY + [ TAG_SUMMARY ]
- PATH_AUTHOR = PATH_ENTRY + [ TAG_AUTHOR ]
- PATH_AUTHOR_NAME = PATH_AUTHOR + [ TAG_NAME ]
- PATH_AUTHOR_EMAIL = PATH_AUTHOR + [ TAG_EMAIL ]
-
- def __init__(self):
- ContentHandler.__init__(self)
- self.entries = list()
- self.actual = list()
- self.mail_count = "0"
- self.current_msg = None
-
- def startDocument (self):
- """Document initialization"""
- del self.entries[:]
- del self.actual[:]
- self.mail_count = "0"
- self.current_msg = None
-
- def startElement( self, name, attrs):
- # update actual path
- self.actual.append(name)
-
- # Message link
- if self.actual == self.PATH_LINK:
- self.current_msg['link'] = attrs['href']
-
- # add a new email to the list
- if name == "entry":
- self.current_msg = Message()
-
- def endElement( self, name):
- # update actual path
- if name == "entry":
- self.entries.append(self.current_msg.copy())
- self.current_msg.clear()
- self.actual.pop()
-
- def characters( self, content):
- # New messages count
- if (self.actual == self.PATH_FULLCOUNT):
- self.mail_count = content
-
- # Message title
- if (self.actual == self.PATH_TITLE):
- self.current_msg['title'] += content
-
- # Message summary
- if (self.actual == self.PATH_SUMMARY):
- self.current_msg['summary'] += content
-
- # Message id
- if self.actual == self.PATH_ID:
- self.current_msg['id'] += content
-
- # Message author name
- if (self.actual == self.PATH_AUTHOR_NAME):
- self.current_msg['author_name'] += content
-
- # Message author email
- if (self.actual == self.PATH_AUTHOR_EMAIL):
- self.current_msg['author_email'] += content
-
- def getUnreadMsgCount(self):
- return int(self.mail_count)
-
-# The mail class
-class GmailAtom:
- """Gmail's atom interface proxy"""
-
- realm = "New mail feed"
- host = "https://mail.google.com"
- url = host + "/mail/feed/atom"
-
- def __init__(self, user, pswd):
- self.mh = MailHandler()
- # initialize authorization handler
- auth_handler = urllib2.HTTPBasicAuthHandler()
- auth_handler.add_password( self.realm, self.host, user, pswd)
- opener = urllib2.build_opener(auth_handler)
- urllib2.install_opener(opener)
-
- def sendRequest(self):
- """Opens a conection with the remote server"""
- del self.mh.entries[:]
- return urllib2.urlopen(self.url)
-
- def refreshInfo(self):
- """Requests information from the remote server and parses the
- information retrieved"""
- try:
- sax.parseString( self.sendRequest().read(), self.mh)
- return True
- except urllib2.URLError:
- return False
-
- def getMsgList (self):
- """Returns a list containing the new messages or empty. It
- will replace all the getMsg* functions in the next
- release. Every entry on the list acts like a dictionary:
-
- old api
- getMsgSummary(1) #Get the summary of the first message
-
- new api
- l = getMsgList()
- l[0]['summary']"""
- return self.mh.entries
-
- def getUnreadMsgCount(self):
- return self.mh.getUnreadMsgCount() |
| |   |
| 1 | #!/usr/bin/python |
| 2 | # -*- coding: utf-8 -*- |
| 3 | |
| 4 | # gmailatom 0.0.2 |
| 5 | # |
| 6 | # by Juan Grande <juan.grande@gmail.com> |
| 7 | # modified by Rodrigo Lazo <rlazo.paz@gmail.com> |
| 8 | |
| 9 | """ |
| 10 | Gmailatom. |
| 11 | |
| 12 | Helps connection to Gmail using the atom interface. |
| 13 | |
| 14 | HOW TO USE: |
| 15 | 1) Create an instance of 'GmailAtom' class. The two arguments |
| 16 | its constructor take are the username (including '@gmail.com') |
| 17 | and the password. |
| 18 | 2) To retrieve the account status call 'refreshInfo()'. |
| 19 | 3) To get the unread messages count call 'getUnreadMsgCount()'. |
| 20 | You MUST call 'refreshInfo()' at least one time before using |
| 21 | this method or it will return zero. |
| 22 | 4) To get specific information about an unread email you must |
| 23 | call the corresponding getter method passing to it the number |
| 24 | of the message. The number zero represents the newest one. |
| 25 | You MUST call 'refreshInfo()' at least one time before calling getMsgList |
| 26 | |
| 27 | The getMsgList returns a list of Messages (dictionary-like) with |
| 28 | the following data: |
| 29 | id |
| 30 | title |
| 31 | summary |
| 32 | author_name |
| 33 | author_email |
| 34 | link |
| 35 | """ |
| 36 | |
| 37 | from gsentinel import Message |
| 38 | from xml.sax.handler import ContentHandler |
| 39 | from datetime import datetime |
| 40 | from xml import sax |
| 41 | import urllib2 |
| 42 | |
| 43 | # Sax XML Handler |
| 44 | class MailHandler(ContentHandler): |
| 45 | """Sax XML Handler for gmail atom interface""" |
| 46 | |
| 47 | # Tags |
| 48 | TAG_FEED = "feed" |
| 49 | TAG_FULLCOUNT = "fullcount" |
| 50 | TAG_ENTRY = "entry" |
| 51 | TAG_TITLE = "title" |
| 52 | TAG_SUMMARY = "summary" |
| 53 | TAG_LINK = "link" |
| 54 | TAG_ID = "id" |
| 55 | TAG_AUTHOR = "author" |
| 56 | TAG_NAME = "name" |
| 57 | TAG_EMAIL = "email" |
| 58 | |
| 59 | # Path the information |
| 60 | PATH_FULLCOUNT = [ TAG_FEED, TAG_FULLCOUNT ] |
| 61 | PATH_ENTRY = [ TAG_FEED, TAG_ENTRY ] |
| 62 | PATH_LINK = PATH_ENTRY + [ TAG_LINK ] |
| 63 | PATH_ID = PATH_ENTRY + [ TAG_ID ] |
| 64 | PATH_TITLE = PATH_ENTRY + [ TAG_TITLE ] |
| 65 | PATH_SUMMARY = PATH_ENTRY + [ TAG_SUMMARY ] |
| 66 | PATH_AUTHOR = PATH_ENTRY + [ TAG_AUTHOR ] |
| 67 | PATH_AUTHOR_NAME = PATH_AUTHOR + [ TAG_NAME ] |
| 68 | PATH_AUTHOR_EMAIL = PATH_AUTHOR + [ TAG_EMAIL ] |
| 69 | |
| 70 | def __init__(self): |
| 71 | ContentHandler.__init__(self) |
| 72 | self.entries = list() |
| 73 | self.actual = list() |
| 74 | self.mail_count = "0" |
| 75 | self.current_msg = None |
| 76 | |
| 77 | def startDocument (self): |
| 78 | """Document initialization""" |
| 79 | del self.entries[:] |
| 80 | del self.actual[:] |
| 81 | self.mail_count = "0" |
| 82 | self.current_msg = None |
| 83 | |
| 84 | def startElement( self, name, attrs): |
| 85 | # update actual path |
| 86 | self.actual.append(name) |
| 87 | |
| 88 | # Message link |
| 89 | if self.actual == self.PATH_LINK: |
| 90 | self.current_msg['link'] = attrs['href'] |
| 91 | |
| 92 | # add a new email to the list |
| 93 | if name == "entry": |
| 94 | self.current_msg = Message() |
| 95 | |
| 96 | def endElement( self, name): |
| 97 | # update actual path |
| 98 | if name == "entry": |
| 99 | self.entries.append(self.current_msg.copy()) |
| 100 | self.current_msg.clear() |
| 101 | self.actual.pop() |
| 102 | |
| 103 | def characters( self, content): |
| 104 | # New messages count |
| 105 | if (self.actual == self.PATH_FULLCOUNT): |
| 106 | self.mail_count = content |
| 107 | |
| 108 | # Message title |
| 109 | if (self.actual == self.PATH_TITLE): |
| 110 | self.current_msg['title'] += content |
| 111 | |
| 112 | # Message summary |
| 113 | if (self.actual == self.PATH_SUMMARY): |
| 114 | self.current_msg['summary'] += content |
| 115 | |
| 116 | # Message id |
| 117 | if self.actual == self.PATH_ID: |
| 118 | self.current_msg['id'] += content |
| 119 | |
| 120 | # Message author name |
| 121 | if (self.actual == self.PATH_AUTHOR_NAME): |
| 122 | self.current_msg['author_name'] += content |
| 123 | |
| 124 | # Message author email |
| 125 | if (self.actual == self.PATH_AUTHOR_EMAIL): |
| 126 | self.current_msg['author_email'] += content |
| 127 | |
| 128 | def getUnreadMsgCount(self): |
| 129 | return int(self.mail_count) |
| 130 | |
| 131 | # The mail class |
| 132 | class GmailAtom: |
| 133 | """Gmail's atom interface proxy""" |
| 134 | |
| 135 | realm = "New mail feed" |
| 136 | host = "https://mail.google.com" |
| 137 | url = host + "/mail/feed/atom" |
| 138 | |
| 139 | def __init__(self, user, pswd): |
| 140 | self.mh = MailHandler() |
| 141 | # initialize authorization handler |
| 142 | auth_handler = urllib2.HTTPBasicAuthHandler() |
| 143 | auth_handler.add_password( self.realm, self.host, user, pswd) |
| 144 | opener = urllib2.build_opener(auth_handler) |
| 145 | urllib2.install_opener(opener) |
| 146 | |
| 147 | def sendRequest(self): |
| 148 | """Opens a conection with the remote server""" |
| 149 | del self.mh.entries[:] |
| 150 | return urllib2.urlopen(self.url) |
| 151 | |
| 152 | def refreshInfo(self): |
| 153 | """Requests information from the remote server and parses the |
| 154 | information retrieved""" |
| 155 | try: |
| 156 | sax.parseString( self.sendRequest().read(), self.mh) |
| 157 | return True |
| 158 | except urllib2.URLError: |
| 159 | return False |
| 160 | |
| 161 | def getMsgList (self): |
| 162 | """Returns a list containing the new messages or empty. It |
| 163 | will replace all the getMsg* functions in the next |
| 164 | release. Every entry on the list acts like a dictionary: |
| 165 | |
| 166 | old api |
| 167 | getMsgSummary(1) #Get the summary of the first message |
| 168 | |
| 169 | new api |
| 170 | l = getMsgList() |
| 171 | l[0]['summary']""" |
| 172 | return self.mh.entries |
| 173 | |
| 174 | def getUnreadMsgCount(self): |
| 175 | return self.mh.getUnreadMsgCount() |
| toggle raw diff |
--- /dev/null
+++ b/gsentinel/gmailatom.py
@@ -0,0 +1,175 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# gmailatom 0.0.2
+#
+# by Juan Grande <juan.grande@gmail.com>
+# modified by Rodrigo Lazo <rlazo.paz@gmail.com>
+
+"""
+Gmailatom.
+
+Helps connection to Gmail using the atom interface.
+
+HOW TO USE:
+1) Create an instance of 'GmailAtom' class. The two arguments
+ its constructor take are the username (including '@gmail.com')
+ and the password.
+2) To retrieve the account status call 'refreshInfo()'.
+3) To get the unread messages count call 'getUnreadMsgCount()'.
+ You MUST call 'refreshInfo()' at least one time before using
+ this method or it will return zero.
+4) To get specific information about an unread email you must
+ call the corresponding getter method passing to it the number
+ of the message. The number zero represents the newest one.
+ You MUST call 'refreshInfo()' at least one time before calling getMsgList
+
+ The getMsgList returns a list of Messages (dictionary-like) with
+ the following data:
+ id
+ title
+ summary
+ author_name
+ author_email
+ link
+"""
+
+from gsentinel import Message
+from xml.sax.handler import ContentHandler
+from datetime import datetime
+from xml import sax
+import urllib2
+
+# Sax XML Handler
+class MailHandler(ContentHandler):
+ """Sax XML Handler for gmail atom interface"""
+
+ # Tags
+ TAG_FEED = "feed"
+ TAG_FULLCOUNT = "fullcount"
+ TAG_ENTRY = "entry"
+ TAG_TITLE = "title"
+ TAG_SUMMARY = "summary"
+ TAG_LINK = "link"
+ TAG_ID = "id"
+ TAG_AUTHOR = "author"
+ TAG_NAME = "name"
+ TAG_EMAIL = "email"
+
+ # Path the information
+ PATH_FULLCOUNT = [ TAG_FEED, TAG_FULLCOUNT ]
+ PATH_ENTRY = [ TAG_FEED, TAG_ENTRY ]
+ PATH_LINK = PATH_ENTRY + [ TAG_LINK ]
+ PATH_ID = PATH_ENTRY + [ TAG_ID ]
+ PATH_TITLE = PATH_ENTRY + [ TAG_TITLE ]
+ PATH_SUMMARY = PATH_ENTRY + [ TAG_SUMMARY ]
+ PATH_AUTHOR = PATH_ENTRY + [ TAG_AUTHOR ]
+ PATH_AUTHOR_NAME = PATH_AUTHOR + [ TAG_NAME ]
+ PATH_AUTHOR_EMAIL = PATH_AUTHOR + [ TAG_EMAIL ]
+
+ def __init__(self):
+ ContentHandler.__init__(self)
+ self.entries = list()
+ self.actual = list()
+ self.mail_count = "0"
+ self.current_msg = None
+
+ def startDocument (self):
+ """Document initialization"""
+ del self.entries[:]
+ del self.actual[:]
+ self.mail_count = "0"
+ self.current_msg = None
+
+ def startElement( self, name, attrs):
+ # update actual path
+ self.actual.append(name)
+
+ # Message link
+ if self.actual == self.PATH_LINK:
+ self.current_msg['link'] = attrs['href']
+
+ # add a new email to the list
+ if name == "entry":
+ self.current_msg = Message()
+
+ def endElement( self, name):
+ # update actual path
+ if name == "entry":
+ self.entries.append(self.current_msg.copy())
+ self.current_msg.clear()
+ self.actual.pop()
+
+ def characters( self, content):
+ # New messages count
+ if (self.actual == self.PATH_FULLCOUNT):
+ self.mail_count = content
+
+ # Message title
+ if (self.actual == self.PATH_TITLE):
+ self.current_msg['title'] += content
+
+ # Message summary
+ if (self.actual == self.PATH_SUMMARY):
+ self.current_msg['summary'] += content
+
+ # Message id
+ if self.actual == self.PATH_ID:
+ self.current_msg['id'] += content
+
+ # Message author name
+ if (self.actual == self.PATH_AUTHOR_NAME):
+ self.current_msg['author_name'] += content
+
+ # Message author email
+ if (self.actual == self.PATH_AUTHOR_EMAIL):
+ self.current_msg['author_email'] += content
+
+ def getUnreadMsgCount(self):
+ return int(self.mail_count)
+
+# The mail class
+class GmailAtom:
+ """Gmail's atom interface proxy"""
+
+ realm = "New mail feed"
+ host = "https://mail.google.com"
+ url = host + "/mail/feed/atom"
+
+ def __init__(self, user, pswd):
+ self.mh = MailHandler()
+ # initialize authorization handler
+ auth_handler = urllib2.HTTPBasicAuthHandler()
+ auth_handler.add_password( self.realm, self.host, user, pswd)
+ opener = urllib2.build_opener(auth_handler)
+ urllib2.install_opener(opener)
+
+ def sendRequest(self):
+ """Opens a conection with the remote server"""
+ del self.mh.entries[:]
+ return urllib2.urlopen(self.url)
+
+ def refreshInfo(self):
+ """Requests information from the remote server and parses the
+ information retrieved"""
+ try:
+ sax.parseString( self.sendRequest().read(), self.mh)
+ return True
+ except urllib2.URLError:
+ return False
+
+ def getMsgList (self):
+ """Returns a list containing the new messages or empty. It
+ will replace all the getMsg* functions in the next
+ release. Every entry on the list acts like a dictionary:
+
+ old api
+ getMsgSummary(1) #Get the summary of the first message
+
+ new api
+ l = getMsgList()
+ l[0]['summary']"""
+ return self.mh.entries
+
+ def getUnreadMsgCount(self):
+ return self.mh.getUnreadMsgCount() |