bigboard r7336 - in trunk/bigboard: gmailimap stocks/files stocks/mail
- From: marinaz svn gnome org
- To: svn-commits-list gnome org
- Subject: bigboard r7336 - in trunk/bigboard: gmailimap stocks/files stocks/mail
- Date: Wed, 7 May 2008 21:52:52 +0100 (BST)
Author: marinaz
Date: Wed May 7 20:52:52 2008
New Revision: 7336
URL: http://svn.gnome.org/viewvc/bigboard?rev=7336&view=rev
Log:
Use the modified gmailimap library to get Google e-mail in the MailStock. This works for both Gmail and GAFYD accounts.
MailStock no longer depends on libgmail.
Added:
trunk/bigboard/gmailimap/__init__.py
Modified:
trunk/bigboard/gmailimap/gmailimap.py
trunk/bigboard/gmailimap/libgmail-imap.py
trunk/bigboard/stocks/files/FilesStock.py
trunk/bigboard/stocks/mail/MailStock.py
Added: trunk/bigboard/gmailimap/__init__.py
==============================================================================
--- (empty file)
+++ trunk/bigboard/gmailimap/__init__.py Wed May 7 20:52:52 2008
@@ -0,0 +1 @@
+# This file needs to be present for the gmailimap module to be found.
Modified: trunk/bigboard/gmailimap/gmailimap.py
==============================================================================
--- trunk/bigboard/gmailimap/gmailimap.py (original)
+++ trunk/bigboard/gmailimap/gmailimap.py Wed May 7 20:52:52 2008
@@ -61,7 +61,7 @@
for option,val in imap_options.items():
if option in ('imap_port','smtp_port'):
val = int(val)
- setattr(self,option,val)
+ setattr(self,option,val)
else:
self.logger.debug("Parsing imap file")
try:
@@ -95,13 +95,20 @@
#self.logger.debug("Parsing message list: %s" % mlist)
msg_objects_list = []
proper_msg_list = []
- for i in range(0,len(mlist),2):# jump over crap returnt by imap
- try:
+ for i in range(0,len(mlist),2): # even parts of the list are flags which we process together with the corresponding messages
+ try:
id = int(mlist[i][0].split('(RFC822')[0])
except (ValueError,AttributeError),e:
EmailParseError,"Message # %s parse error: %s" % (i,e)
- proper_msg_list.append((id,mlist[i][1]))
-
+ seenFlag = False
+ if len(mlist) > i and mlist[i+1].find("Seen") >= 0:
+ seenFlag = True
+ proper_msg_list.append((id, mlist[i][1], seenFlag))
+
+ #self.logger.debug("message %s" % mlist[i][1])
+ #if len(mlist[i]) > 2:
+ # self.logger.debug("flags %s" % mlist[i][2])
+
proper_msg_list.sort(reverse=True)# we use tuples with the gmail id as the first member
for item in proper_msg_list:
try:
@@ -109,7 +116,7 @@
except email.Errors.MessageError, e:
self.logger.error("Message %s parse error: %s" % (item[1],e))
raise EmailParseError,"Message %s parse error: %s" % (item[1],e)
- msg_objects_list.append((item[0],msgs))
+ msg_objects_list.append((item[0],msgs,item[2]))
return msg_objects_list
def _make_message_threads(self,mlist):
@@ -135,7 +142,7 @@
except imaplib.IMAP4.error,e:
self.logger.error("imap server login raised an exception, check your ~/.imap file")
self.logger.error("reason for the exception: %s" % e)
- sys.exit(1)
+ raise NoLoginError, e
else:
self.logger.debug("Logged into Imap_ssl server")
return True
@@ -150,7 +157,7 @@
except imaplib.IMAP4.error,e:
self.logger.error("imap server login raised an exception, check your ~/.imap file")
self.logger.error("reason for the exception: %s" % e)
- sys.exit(1)
+ raise GmailError, 'Failed to parse data returned from gmail.'
else:
self.logger.debug("Logged into Imap server")
return True
@@ -168,25 +175,11 @@
except Exception:
self.logger.exception("Error while closing connection")
- def get_unread_message_count(self):
+ def get_unread_message_id_list(self):
"""Get a list of unread message ids from the inbox.
Return a list with ids (integers)
"""
- result, message = self.AC.select(readonly=1)
- if result != 'OK':
- raise ServerError,message
- # fetch message ids from server
- self.logger.debug("Fetching ids from unread messages, if any")
- try:
- typ, data = self.AC.search(None, '(UNSEEN UNDELETED)')
- msg_id_list = [m for m in data[0].split()]
- except KeyError,e:
- print "get_unread_message_count raised unkown error", e
- # TODO: XXX Can't remember what this except catches :-(
- if not msg_id_list:
- self.logger.debug("No new messages")
- return []
- return msg_id_list
+ return self.get_message_ids_by_folder('INBOX', '(UNSEEN UNDELETED)')
def get_all_messages(self):
"""Get all messages from inbox.
@@ -194,7 +187,7 @@
there are no unread messages. The message objects are message objects from the
Python email module.
Message objects can have multiple messages representing message threads."""
- return self.get_messages_by_folder('INBOX',all=True)
+ return self.get_messages_by_folder('INBOX')
def get_unread_messages(self):
"""Get unread messages from the inbox.
@@ -203,37 +196,35 @@
Python email module.
Message objects can have multiple messages representing message threads.
"""
- result, message = self.AC.select(readonly=1)
- if result != 'OK':
- raise ServerError,message
-
- msg_id_list = self.get_unread_message_count()
- if not msg_id_list:
- return []
-
- # we have unread message ids
- msg_list = []
- self.logger.debug("Getting new messages")
- msg_list = self.AC.fetch(','.join(msg_id_list),'(RFC822)')[1]
- return self._parse_message_list(msg_list)
+ return self.get_messages_by_folder("INBOX", '(UNSEEN UNDELETED)')
- def get_messages_by_folder(self,folder,all=None):
+ def get_messages_by_folder(self,folder,criterion=None,max_count=None):
"""Get contents of the @folder.
Returns a list of email.message.Message objects.
"""
+ msg_id_list = self.get_message_ids_by_folder(folder, criterion)
+ if max_count and max_count < len(msg_id_list):
+ msg_id_list = msg_id_list[-max_count:]
+ comma_separated_msg_id_list = ','.join([m for m in msg_id_list])
+ msg_list = self.AC.fetch(comma_separated_msg_id_list,'(RFC822 FLAGS)')[1]
+ return self._parse_message_list(msg_list)
+
+ def get_message_ids_by_folder(self,folder,criterion=None):
+ """Get the ids of messages in the @folder.
+ Suitable for getting the count of messages of a certain type in the folder.
+ """
result, message = self.AC.select(folder,readonly=1)
if result != 'OK':
raise ServerError,message
- self.logger.debug("Getting messages from %s" % folder)
- if all:
- result, data = self.AC.search(None,'ALL')
+ self.logger.debug("Getting message ids from %s" % folder)
+ if criterion:
+ result, data = self.AC.search(None, criterion)
else:
- result, data = self.AC.search(None, '(UNDELETED)')
+ result, data = self.AC.search(None,'ALL')
if result != 'OK':
raise ServerError,message
- msg_id_list = ','.join([m for m in data[0].split()])
- msg_list = self.AC.fetch(msg_id_list,'(RFC822)')[1]
- return self._parse_message_list(msg_list)
+ msg_id_list = data[0].split()
+ return msg_id_list
def get_folder_names(self):
"""List all the Gmail mailfolders.
@@ -246,6 +237,25 @@
raise ServerError,data
return data
+ def get_folder_unread_counts(self):
+ """ this includes INBOX """
+ data = self.get_folder_names()
+ labels = {}
+ # parse the list with strings to get the names
+ for item in data:
+ # self.logger.debug("item is %s" % (item))
+ line = item.split('"/"')[1].split('/')
+ if '[Gmail]' in item and len(line) > 1:
+ # since Gmail specific names such as "Spam" or "Trash" are not allowed as Gmail labels,
+ # there should not be any danger of duplicate keys here
+ labels["[Gmail]/" + line[1][0:-1]] = len(self.get_message_ids_by_folder("[Gmail]/" + line[1][0:-1],'(UNSEEN UNDELETED)'))
+ elif '[Gmail]' not in item:
+ labels[line[0][2:-1]] = len(self.get_message_ids_by_folder(line[0][2:-1],'(UNSEEN UNDELETED)'))
+ return labels
+
+ def get_folder_unread_count(self, folder):
+ return len(self.get_message_ids_by_folder(folder,'(UNSEEN UNDELETED)'))
+
def search(self,folder,pattern):
"""Search for messages in @folder which match @pattern.
Returns a list with email.message.Message objects or an empty list
@@ -260,7 +270,7 @@
if result != 'OK':
raise ServerError,data
msg_id_list = ','.join([m for m in data[0].split()])
- msg_list = self.AC.fetch(msg_id_list,'(RFC822)')[1]
+ msg_list = self.AC.fetch(msg_id_list,'(RFC822 FLAGS)')[1]
return self._parse_message_list(msg_list)
## THIS DON'T WORK ON GMAIL IMAP, seems that THREAD is a unkown command ???
@@ -344,7 +354,7 @@
server.ehlo()
server.starttls()
server.ehlo()
- server.login(self.imap_user,self.imap_password)
+ server.login(self.imap_user,self.imap_pass)
server.sendmail(mesg.sender, [mesg.recipient], mesg.msg.as_string())
except (smtplib.SMTPHeloError,\
smtplib.SMTPAuthenticationError,\
@@ -392,7 +402,7 @@
ac.login_ssl()
print "number of unread messages"
- print ac.get_unread_message_count()
+ print len(ac.get_unread_message_id_list())
print "unread messages from inbox"
mgs = ac.get_unread_messages()
Modified: trunk/bigboard/gmailimap/libgmail-imap.py
==============================================================================
--- trunk/bigboard/gmailimap/libgmail-imap.py (original)
+++ trunk/bigboard/gmailimap/libgmail-imap.py Wed May 7 20:52:52 2008
@@ -35,7 +35,8 @@
`folderName` -- As set in Gmail interface.
libgmail: Returns a `GmailSearchResult` instance."""
- result = self.get_messages_by_folder(self,folderName,allPages)
+ # TODO: convert allPages to criterion
+ result = self.get_messages_by_folder(self,folderName)
def getMessagesByQuery(self, query, allPages = False):
@@ -101,7 +102,8 @@
# There are issues with Gmail labels
# When messages are deleted, moved to Trash, with there label attached
# they still returnt by GM.search(None, '(UNDELETED)')
- return self.get_messages_by_folder(label,all)
+ # TODO: convert all to criterion
+ return self.get_messages_by_folder(label)
def getLabelNames(self,foo):
"""List all the Gmail labels.
@@ -151,14 +153,16 @@
ac.login_ssl()
## print "number of unread messages"
-## print ac.get_unread_message_count()
+## print len(ac.get_unread_message_id_list())
##
## print "unread messages from inbox"
## pprint.pprint(ac.get_unread_messages())
print "all INBOX folder messages:"
# same as get_unread_messages but now also the read messages
- pprint.pprint(ac.get_all_messages())
+ messages = ac.get_all_messages()
+ for message in messages:
+ print message[1].as_string()
print "folders:",ac.get_folder_names()
Modified: trunk/bigboard/stocks/files/FilesStock.py
==============================================================================
--- trunk/bigboard/stocks/files/FilesStock.py (original)
+++ trunk/bigboard/stocks/files/FilesStock.py Wed May 7 20:52:52 2008
@@ -189,7 +189,6 @@
def get_type(self):
if self._mimetype:
- _logger.debug("mimetype is %s class is %s dir %s" % (self._mimetype, self._mimetype.__class__, dir(self._mimetype)))
return gnomevfs.mime_get_description(self._mimetype)
return None
@@ -365,7 +364,6 @@
_launch_vfsmimeapp(app, fobj.get_url())
directory = apps_directory.get_app_directory()
for app in apps:
- _logger.debug("mime type: %s got app %s", mime, app)
button = hippo.CanvasButton()
labelhbox = gtk.HBox()
labelhbox.set_border_width(1)
Modified: trunk/bigboard/stocks/mail/MailStock.py
==============================================================================
--- trunk/bigboard/stocks/mail/MailStock.py (original)
+++ trunk/bigboard/stocks/mail/MailStock.py Wed May 7 20:52:52 2008
@@ -14,11 +14,10 @@
import bigboard.google_stock as google_stock
from bigboard.big_widgets import CanvasHBox, CanvasVBox, Button, Header, PrelightingCanvasBox
import bigboard.libbig as libbig
+import bigboard.gmailimap.gmailimap as gmailimap
#TODO: add a scrollable view for emails
#import bigboard.scroll_ribbon as scroll_ribbon
-import libgmail_patched as libgmail
-
_logger = logging.getLogger('bigboard.stocks.MailStock')
def replace_chr(m):
@@ -55,6 +54,11 @@
# Return the sanely filtered content
return textContent.getvalue()
+def make_folder_name_pretty(folder_name):
+ if folder_name.find("[Gmail]/") == 0:
+ return folder_name[len("[Gmail]/"):]
+ return folder_name
+
class LabelSlideout(ThemedSlideout):
__gsignals__ = {
'changed' : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_STRING, )),
@@ -64,12 +68,11 @@
vbox = CanvasVBox(border_color=0x0000000ff, spacing=4)
self.get_root().append(vbox)
header = Header(topborder=False)
- account_text = hippo.CanvasText(classes='header', text=ga.name)
+ account_text = hippo.CanvasText(classes='header', text=ga.imap_user)
header.append(account_text, hippo.PACK_EXPAND)
vbox.append(header)
try:
- folderCounts = ga.getFolderCounts()
- folderCounts["unread"] = ga.getUnreadMsgCount()
+ folderCounts = ga.get_folder_unread_counts()
except urllib2.URLError:
error = hippo.CanvasText(text=google_stock.FAILED_TO_CONNECT_STRING)
vbox.append(error)
@@ -80,14 +83,15 @@
box.connect('button-release-event', self.on_button_release_event, label)
vbox.append(box)
hbox = CanvasHBox(spacing=4, padding=4)
- text= hippo.CanvasText(text=label, xalign=hippo.ALIGNMENT_START)
+ text= hippo.CanvasText(text=make_folder_name_pretty(label), xalign=hippo.ALIGNMENT_START)
hbox.append(text)
text= hippo.CanvasText(text=number, xalign=hippo.ALIGNMENT_START)
hbox.append(text, flags=hippo.PACK_END)
box.append(hbox)
- def on_button_release_event (self, hippo_item, event, label_text):
- self.emit('changed', label_text)
+ def on_button_release_event (self, hippo_item, event, label):
+ self.emit('changed', label)
+ self.emit('close', True)
class EmailSlideout(ThemedSlideout):
def __init__(self, thread):
@@ -95,25 +99,31 @@
vbox = CanvasVBox(border_color=0x0000000ff, spacing=4)
self.get_root().append(vbox)
self.__header = Header(topborder=False)
- self.id = thread.id
+ self.id = thread[0]
- subject = gmail_jshtml_str_parse(thread.subject)
+ subject = gmail_jshtml_str_parse(thread[1]['subject'])
subject_box = hippo.CanvasText(classes='header', text=subject)
self.__header.append(subject_box, hippo.PACK_EXPAND)
vbox.append(self.__header)
- for key in ("date", "categories", "snippet"):
- value = getattr(thread, key, None)
- if value:
- if type(value) is list:
- s = ", ".join(value)
- if type(value) is str:
- _logger.debug("passing in %s" % value)
- s = gmail_jshtml_str_parse(value)
-
- box = hippo.CanvasText(text=s, xalign=hippo.ALIGNMENT_START)
- vbox.append(box)
+ # for key in thread[1].keys():
+ # _logger.debug("key %s" % key)
+
+ value = thread[1]["date"]
+ s = gmail_jshtml_str_parse(value)
+ box = hippo.CanvasText(text=s, xalign=hippo.ALIGNMENT_START)
+ vbox.append(box)
+ message = thread[1]
+ while message.is_multipart():
+ message = message.get_payload(0)
+
+ if len(message.get_payload()) <= 200:
+ value = message.get_payload()
+ else:
+ value = message.get_payload()[:200] + "..."
+ box = hippo.CanvasText(text=value, xalign=hippo.ALIGNMENT_START)
+ vbox.append(box)
#todo: nicify email, strip out junk, and show actual email
#email_source = thread[len(thread)-1].source
@@ -153,10 +163,9 @@
def update_google_data(self, gobj):
self.__current_gobj = gobj
- username = gobj.get_account().get_username()
+ username = gobj.get_account().get_username_as_google_email()
password = gobj.get_account().get_password()
- domain = gobj.get_account().get_url()
- self.__update_email_box(username, password, domain)
+ self.__update_email_box(username, password)
def remove_google_data(self, gobj):
# sometimes we don't even get the self.__current_gobj because the polling task didn't start, so
@@ -168,61 +177,65 @@
self.__google_account = None
self.__logged_in = False
- def __update_email_box (self, username, password, domain):
+ def __update_email_box (self, username, password):
_logger.debug("will update mailbox")
try:
- if self.__google_account is None or username != self.__google_account.name or \
- password != self.__google_account.password:
- if domain and (len(domain) == 0 or domain == "gmail.com"):
- domain = None
- _logger.debug("username %s domain %s" % (username, domain))
- self.__google_account = libgmail.GmailAccount(username, password, domain = domain)
- self.__google_account.login()
+ if self.__google_account is None or username != self.__google_account.imap_user or \
+ password != self.__google_account.imap_pass:
+ self.__google_account = gmailimap.ImapAccount({'imap_server' : 'imap.gmail.com', 'imap_port' : 993, 'imap_user' : username, 'imap_pass' : password, 'smtp_server' : 'smtp.gmail.com', 'smtp_port' : 587})
+ self.__google_account.login_ssl()
elif not self.__logged_in:
- self.__google_account.login()
+ self.__google_account.login_ssl()
self.__logged_in = True
- if self.__folder == 'inbox':
- threads = self.__google_account.getMessagesByFolder(self.__folder)
- elif self.__folder == 'unread':
- threads = self.__google_account.getUnreadMessages()
- else:
- threads = self.__google_account.getMessagesByLabel(self.__folder)
-
+ threads = self.__google_account.get_messages_by_folder(self.__folder, max_count=self.__display_limit)
+
self._box.remove_all()
- account = hippo.CanvasText(classes='header', text=self.__google_account.name)
+ account = hippo.CanvasText(classes='header', text=self.__google_account.imap_user)
self._box.append(account)
box = PrelightingCanvasBox()
box.connect("button-press-event", self.create_label_slideout, self.__google_account)
self._box.append(box)
- label = hippo.CanvasText(text=self.__folder, font="14px Bold Italic")
+ label = hippo.CanvasText(text=make_folder_name_pretty(self.__folder), font="14px Bold Italic")
box.append(label)
i = 0
for thread in threads:
if i >= self.__display_limit: break
- subject = gmail_jshtml_str_parse(thread.subject, True)
+ subject = gmail_jshtml_str_parse(thread[1]['subject'], True)
box = PrelightingCanvasBox()
box.connect("button-press-event", self.create_email_slideout, thread)
self._box.append(box)
- email = hippo.CanvasText(markup=subject, xalign=hippo.ALIGNMENT_START)
+ seenFlag = thread[2]
+ if seenFlag:
+ email = hippo.CanvasText(markup=subject, xalign=hippo.ALIGNMENT_START)
+ else:
+ email = hippo.CanvasText(markup=subject, xalign=hippo.ALIGNMENT_START, font="Bold")
box.append(email)
i += 1
- labelsDict = self.__google_account.getFolderCounts()
- footer = hippo.CanvasText(classes='footer', text="%s unread" % labelsDict['inbox'], font="14px Bold Italic")
+ folder_unread_count = self.__google_account.get_folder_unread_count(self.__folder)
+ footer = hippo.CanvasText(classes='footer', text="%s unread" % folder_unread_count, font="14px Bold Italic")
self._box.append(footer)
print "updated mailbox"
- except libgmail.GmailLoginFailure:
+ except gmailimap.NoLoginError, e:
self._box.remove_all()
self.__logged_in = False
if self._login_button.get_property("text") == google_stock.CHECKING_LOGIN_STRING:
- error = hippo.CanvasText(text=google_stock.FAILED_TO_LOGIN_STRING, size_mode=hippo.CANVAS_SIZE_WRAP_WORD)
- self._box.append(error)
+ error_text = google_stock.FAILED_TO_LOGIN_STRING
+ elif str(e.message).find("not enabled for IMAP") >=0:
+ # TODO: provide a link to the settings page once the mail stock design is finalized
+ error_text = "Enable IMAP in your Google mail settings for " + username
+ # this will force us to check the account again during the next polling task
+ self.__google_account = None
+ else:
+ error_text = e.message
+ error = hippo.CanvasText(text=error_text, size_mode=hippo.CANVAS_SIZE_WRAP_WORD)
+ self._box.append(error)
self._login_button.set_property('text', google_stock.LOGIN_TO_GOOGLE_STRING)
self._box.append(self._login_button)
except urllib2.URLError:
@@ -257,7 +270,7 @@
self.show_slideout(widget)
def create_email_slideout(self, widget, hippo_event, data):
- if type(self.__slideout) is EmailSlideout and self.__slideout.id == data.id and \
+ if type(self.__slideout) is EmailSlideout and self.__slideout.id == data[0] and \
self.__last_slideout_event_time == gtk.get_current_event_time():
self.__slideout = None
return
@@ -266,7 +279,7 @@
def on_label_changed (self, slideout, label):
self.__folder = label
- self.__update_email_box(self.__google_account.name, None)
+ self.__update_email_box(self.__google_account.imap_user, self.__google_account.imap_pass)
def __on_more_button(self):
libbig.show_url("http://mail.google.com/mail")
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]