from libdesklets.controls import Control from IConnect import IConnect from MyHtmlParser import MyHtmlParser import thread from gobject import markup_escape_text from StringIO import StringIO import email import email.Utils import email.header import quopri class MyPop3Client(): def __init__(self): self.html_parser = MyHtmlParser() def do_connection(self, host, user, password): import poplib try: self.pop = poplib.POP3(host) self.pop.user(user) self.pop.pass_(password) except: import sys print "ERROR: ",sys.exc_type return False return True def safe_quit(self): try: self.pop.rset() self.pop.quit() except: pass def make_string(self, items): data = str() for item in items: data += item+"\r\n" return data def show_list(self, callback, limit): rounds = 0 current_id = self.pop.stat()[0] data = [] while current_id > 0 and rounds != limit: msg = self.make_string( self.pop.retr(current_id)[1] ) data.append( callback(msg, rounds, self.html_parser) ) rounds += 1 current_id -= 1 return data class MyImapClient: def __init__(self): self.html_parser = MyHtmlParser() def do_connection(self, host, user, password): import imaplib try: self.imap = imaplib.IMAP4(host) self.imap.login(user, password) self.imap.select(readonly=True) except imaplib.IMAP4.error: import sys print "ERROR: ",sys.exc_type return False return True def safe_quit(self): try: self.imap.close() self.imap.logout() except: pass def show_list(self, callback, limit): data = [] response, num_messages = self.imap.search(None, 'ALL') rounds = 0 current_id = int(num_messages[0].split().pop()) while current_id > 0 and rounds != limit: response, msg = self.imap.fetch(current_id, '(RFC822)') data.append( callback(msg[0][1], rounds, self.html_parser) ) rounds += 1 current_id -= 1 return data class MyImapsClient: def __init__(self): self.html_parser = MyHtmlParser() def do_connection(self, host, user, password): import imaplib try: self.imaps = imaplib.IMAP4_SSL(host) self.imaps.login(user, password) self.imaps.select(readonly=True) except imaplib.IMAP4_SSL.error: import sys print "ERROR: ",sys.exc_type return False return True def safe_quit(self): try: self.imaps.close() self.imaps.logout() except: pass def show_list(self, callback, limit): data = [] response, num_messages = self.imaps.search(None, 'ALL') rounds = 0 current_id = int(num_messages[0].split().pop()) while current_id > 0 and rounds != limit: response, msg = self.imaps.fetch(current_id, '(RFC822)') data.append( callback(msg[0][1], rounds, self.html_parser) ) rounds += 1 current_id -= 1 return data class Connect(Control, IConnect): status_table = { "ready" : "ready", "error" : "error", "connecting" : "connecting", "read" : "read", } def handle_msg(self, msg, id, html_parser): # ID is number added to the list to make reference in the display # in that way I'm able to know which content in the one I'll show file = StringIO(msg) message = email.message_from_file(file) content = {} content["from"] = self.decode_header(message, message["from"], 1) content["subject"] = self.decode_header(message, message["subject"], 0) content["to"] = self.decode_header(message, message["to"], 1) if not message.is_multipart(): text = self.decode_part(html_parser, message) if text is not None: content["string"] = text else: for s in message.walk(): f = s.get_filename() if f: #"There's attachment" pass else: text = self.decode_part(html_parser, s) if text is not None: content["string"] = text content["id"] = id return content def encode_content(self, part, content): charset = part.get_content_charset() # FIXME: utf-8 should not be forced to latin1 if charset == "utf-8" or not charset: charset = "latin1" try: content = unicode(content, charset).encode("utf-8") except: pass return content def decode_header(self, message, header, is_addr): dec = email.header.decode_header(header)[0] if dec[1]: text = dec[0].decode(dec[1]) else: text = dec[0] if is_addr: addr = email.Utils.parseaddr(text) if addr[0]: text = addr[0] return markup_escape_text(self.encode_content(message, text)) def get_part_payload(self, part): payload = part.get_payload(decode = 1) return self.encode_content(part, payload) def decode_part(self, html_parser, part): text = None if part.get_content_type() == "text/plain": text = self.get_part_payload(part) elif part.get_content_type() == "text/html": html_parser.set_feed(self.get_part_payload(part)) text = html_parser.get_parsed_data() if text: text = markup_escape_text(text).strip() return text def __init__(self): self._status = Connect.status_table["ready"] self._method = None self._password = None self._user = None self._host = None self._data = None Control.__init__(self) self._update("status") def __set_status(self, value): #TODO: I need to blank every attrs if I want to do #a new connection. self._status = value def connect_server(self): self._status = Connect.status_table["connecting"] self._update("status") if self._method == "pop3": connection = MyPop3Client() elif self._method == "imap": connection = MyImapClient() elif self._method == "imaps": connection = MyImapsClient() if connection.do_connection(self._host, self._user, self._password) is False: self._status = Connect.status_table["error"] self._update("status") else: self._status = Connect.status_table["read"] self._data = connection.show_list(self.handle_msg, limit=7) self._update("status") connection.safe_quit() def __set_method(self, value): if value == "pop3": self._method = value elif value == "imap": self._method = value elif value == "imaps": self._method = value thread.start_new_thread(self.connect_server, ()) def __set_user(self, value): self._user = value def __set_password(self, value): self._password = value def __set_host(self, value): self._host = value def __get_status(self): return self._status def __get_data(self): return self._data status = property(fget=__get_status, fset=__set_status, doc="Tell if we are working or now") method = property(fset=__set_method, doc="Tell if connect to POP3 or IMAP") user = property(fset=__set_user, doc="Tell if connect to POP3 or IMAP") password = property(fset=__set_password, doc="Tell if connect to POP3 or IMAP") host = property(fset=__set_host, doc="Host where fetch emails") data = property(fget=__get_data, doc="This will have the emails abstract") def get_class(): return Connect