#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""GMail Important Mails Notifier
A very simple GMail IMAP client which retrieves
only new **important** messages and displays a
notification using pynotify module.
"""
import time
import imaplib
import pynotify
import getpass
from email.header import decode_header
from email.parser import Parser
from optparse import OptionParser
__author__ = "Andrés Gattinoni <andresgattinoni@gmail.com>"
__version__ = "0.1"
__host = 'imap.gmail.com'
__port = 993
__interval = 60*2
class Client(object):
"""Very simple IMAP client"""
def __init__ (self, host, port, username, password):
"""Constructor"""
self._interval = 0
# Connector
self.client = imaplib.IMAP4_SSL(host, port)
# Login
if not self.client.login(username, password):
raise Exception("Invalid login")
# Attempt to select the Important label
status, data = self.client.select('[Gmail]/Important')
if status != 'OK':
raise Exception("Label [Gmail]/Important not found")
# Attempt to init pynotify
if not pynotify.init("GMail Important Messages"):
raise Exception("Failed to initialize pynotify module")
def set_interval (self, time):
"""Define a new check interval"""
self._interval = int(time)
def start (self):
"""Main loop"""
lst = []
while True:
try:
status, data = self.client.search(None, '(UNSEEN)')
if status == 'OK':
if data[0] != '':
for msg_id in sorted(data[0].split()):
# If we have a new message
# fetch it and append it to the list
if msg_id != '' and msg_id not in lst:
lst.append(msg_id)
status, data = self.client.fetch(msg_id, '(RFC822)')
# Mark as unread
self.client.store(msg_id, '-FLAGS', '\\Seen')
self.client.store(msg_id, '-FLAGS', '\\Recent')
if status == 'OK':
msg = Parser().parsestr(data[0][1])
self.notify(self.get_header(msg, 'From'), \
self.get_header(msg, 'Subject'))
else:
print "Failed to fetch message #%s" % str(msg_id)
else:
raise Exception("Failed to retrieve new important messages")
break
time.sleep(self._interval)
except KeyboardInterrupt:
break
def notify (self, title, msg):
"""Notifies new messages"""
pynotify.Notification(title, msg).show()
def get_header (self, msg, header):
"""Gets a header from a message"""
header = decode_header(msg.get(header))
if (header[0][1]):
return unicode(header[0][0], header[0][1]).encode('utf8')
else:
return header[0][0]
if __name__ == '__main__':
"""Starting point of the application.
Defines an option parser and starts the client loop"""
parser = OptionParser(usage='%prog [options]', \
version=__version__, \
description="Simple script for Important messages notifications")
parser.add_option('-u', '--user', dest='user', \
help='Gmail\'s username', \
metavar='USERNAME', default=None)
parser.add_option('-p', '--password', dest='password', \
help='Gmail\'s password', \
metavar='PASSWORD', default=None)
parser.add_option('-H', '--host', dest='host', \
help='IMAP hostname (default: %s)' % __host, \
metavar='HOSTNAME', default=__host)
parser.add_option('-P', '--port', dest='port', \
help='IMAP port (default: %d)' % __port, \
metavar='PORT', default=__port)
parser.add_option('-t', '--time', dest='time', \
help='Check interval (default: %d secs)' % __interval, \
metavar='TIME', default=__interval)
# Parse options and do some input checking
(option, args) = parser.parse_args()
if option.user is None:
option.user = raw_input('Username: ')
if option.password is None:
option.password = getpass.getpass('Password: ')
client = Client(option.host, option.port, option.user, option.password)
client.set_interval(option.time)
client.start()