diff --git a/jabber/component.py b/jabber/component.py index 85e7b03..50e4f62 100644 --- a/jabber/component.py +++ b/jabber/component.py @@ -850,17 +850,10 @@ class MailComponent(Component): + "@" + account.host) account.connect() mail_list = account.get_mail_list() - if not mail_list or mail_list[0] == '': - num = 0 - else: - num = len(mail_list) - # unseen mails checked by external client - # TODO : better test to find - if num < account.lastmail: - account.lastmail = 0 if action == mailconnection.RETRIEVE: - while account.lastmail < num: - (body, email_from) = account.get_mail(int(mail_list[account.lastmail])) + mail_index = account.get_next_mail_index(mail_list) + while mail_index is not None: + (body, email_from) = account.get_mail(mail_index) mesg = Message(from_jid = name + "@" + \ unicode(self.jid), \ to_jid = jid, \ @@ -868,15 +861,16 @@ class MailComponent(Component): subject = account.default_lang_class.new_mail_subject % (email_from), \ body = body) self.stream.send(mesg) - account.lastmail += 1 + account.get_next_mail_index(mail_list) else: body = "" new_mail_count = 0 - while account.lastmail < num: + mail_index = account.get_next_mail_index(mail_list) + while mail_index: (tmp_body, from_email) = \ - account.get_mail_summary(int(mail_list[account.lastmail])) + account.get_mail_summary(mail_index) body += tmp_body + "\n----------------------------------\n" - account.lastmail += 1 + mail_index = account.get_next_mail_index(mail_list) new_mail_count += 1 if body != "": mesg = Message(from_jid = name + "@" + \ @@ -915,11 +909,7 @@ class MailComponent(Component): return try: account.connect() - mail_list = account.get_mail_list() - if not mail_list or mail_list[0] == '': - account.lastmail = 0 - else: - account.lastmail = len(mail_list) + account.mark_all_as_read() account.disconnect() account.in_error = False except Exception,e: diff --git a/jabber/mailconnection.py b/jabber/mailconnection.py index 0744055..c7ba8f7 100644 --- a/jabber/mailconnection.py +++ b/jabber/mailconnection.py @@ -157,7 +157,6 @@ class MailConnection(object): self.host = host self.port = port self.ssl = ssl - self.lastmail = 0 self.status = "offline" self.connection = None self.chat_action = RETRIEVE @@ -306,6 +305,13 @@ class MailConnection(object): def get_mail_summary(self, index): return None + def get_next_mail_index(self, mail_list): + pass + + # Does not modify server state but just internal JMC state + def mark_all_as_read(self): + pass + def get_action(self): mapping = {"online": self.online_action, "chat": self.chat_action, @@ -366,29 +372,35 @@ class IMAPConnection(MailConnection): def get_mail_list(self): IMAPConnection._logger.debug("Getting mail list") typ, data = self.connection.select(self.mailbox) - typ, data = self.connection.search(None, 'UNSEEN') + typ, data = self.connection.search(None, 'RECENT') if typ == 'OK': return data[0].split(' ') return None def get_mail(self, index): IMAPConnection._logger.debug("Getting mail " + str(index)) - typ, data = self.connection.select(self.mailbox) + typ, data = self.connection.select(self.mailbox, True) typ, data = self.connection.fetch(index, '(RFC822)') - self.connection.store(index, "FLAGS", "UNSEEN") if typ == 'OK': return self.format_message(email.message_from_string(data[0][1])) return u"Error while fetching mail " + str(index) def get_mail_summary(self, index): IMAPConnection._logger.debug("Getting mail summary " + str(index)) - typ, data = self.connection.select(self.mailbox) + typ, data = self.connection.select(self.mailbox, True) typ, data = self.connection.fetch(index, '(RFC822)') - self.connection.store(index, "FLAGS", "UNSEEN") if typ == 'OK': return self.format_message_summary(email.message_from_string(data[0][1])) return u"Error while fetching mail " + str(index) + def get_next_mail_index(self, mail_list): + if not mail_list or mail_list[0] == '': + return None + return mail_list.pop(0) + + def mark_all_as_read(self): + self.get_mail_list() + type = property(get_type) class POP3Connection(MailConnection): @@ -402,6 +414,8 @@ class POP3Connection(MailConnection): else: port = 110 MailConnection.__init__(self, login, password, host, port, ssl) + self.__nb_mail = 0 + self.__lastmail = 0 def get_type(self): if self.ssl: @@ -431,7 +445,12 @@ class POP3Connection(MailConnection): def get_mail_list(self): POP3Connection._logger.debug("Getting mail list") count, size = self.connection.stat() - return [str(i) for i in range(1, count + 1)] + result = [str(i) for i in range(1, count + 1)] + if not result or result[0] == '': + self.__nb_mail = 0 + else: + self.__nb_mail = len(result) + return result def get_mail(self, index): POP3Connection._logger.debug("Getting mail " + str(index)) @@ -447,4 +466,17 @@ class POP3Connection(MailConnection): return self.format_message_summary(email.message_from_string('\n'.join(data))) return u"Error while fetching mail " + str(index) + def get_next_mail_index(self, mail_list): + if self.__nb_mail == self.__lastmail: + return None + if self.__nb_mail < self.__lastmail: + self.__lastmail = 0 + result = self.__lastmail + self.__lastmail += 1 + return result + + def mark_all_as_read(self): + self.get_mail_list() + self.__lastmail = self.__nb_mail + type = property(get_type) diff --git a/tests/dummy_server.py b/tests/dummy_server.py index 04d055e..4d9dca7 100644 --- a/tests/dummy_server.py +++ b/tests/dummy_server.py @@ -56,29 +56,34 @@ class DummyServer: self.real_queries = [] def serve(self): - conn, addr = self.socket.accept() - rfile = conn.makefile('rb', -1) - if self.responses: - data = None - for idx in range(len(self.responses)): - # if response is a function apply it (it must return a string) - # it is given previous received data - if isinstance(self.responses[idx], types.FunctionType): - response = self.responses[idx](data) - else: - response = self.responses[idx] - if response is not None: -# print >>sys.stderr, 'Sending : ', response - conn.send(response) - data = rfile.readline() - if not data: - break - else: - self.real_queries.append(data) -# print >>sys.stderr, 'Receive : ', data - conn.close() - self.socket.close() - self.socket = None + try: + conn, addr = self.socket.accept() + rfile = conn.makefile('rb', -1) + if self.responses: + data = None + for idx in range(len(self.responses)): + # if response is a function apply it (it must return a string) + # it is given previous received data + if isinstance(self.responses[idx], types.FunctionType): + response = self.responses[idx](data) + else: + response = self.responses[idx] + if response is not None: + #print >>sys.stderr, 'Sending : ', response + conn.send(response) + data = rfile.readline() + if not data: + break + else: + self.real_queries.append(data) + #print >>sys.stderr, 'Receive : ', data + conn.close() + self.socket.close() + self.socket = None + except: + type, value, stack = sys.exc_info() + print >>sys.stderr, "".join(traceback.format_exception + (type, value, stack, 5)) def verify_queries(self): result = True @@ -95,7 +100,8 @@ class DummyServer: else: result = False print >>sys.stderr, "Expected " + str(queries_len) + \ - " queries, got " + str(len(self.real_queries)) + " queries, got " + str(len(self.real_queries)) + \ + "\t" + str(self.real_queries) return result class XMLDummyServer(DummyServer): diff --git a/tests/test_mailconnection.py b/tests/test_mailconnection.py index d5d6a65..7a5aec0 100644 --- a/tests/test_mailconnection.py +++ b/tests/test_mailconnection.py @@ -236,7 +236,7 @@ class IMAPConnection_TestCase(unittest.TestCase): lambda data: "* SEARCH 9 10 \n" + \ data.split()[0] + " OK SEARCH completed\n"], \ ["^[^ ]* SELECT INBOX", \ - "^[^ ]* SEARCH UNSEEN"], \ + "^[^ ]* SEARCH RECENT"], \ lambda self: \ self.assertEquals(self.imap_connection.get_mail_list(), ['9', '10'])) @@ -247,12 +247,9 @@ class IMAPConnection_TestCase(unittest.TestCase): " OK [READ-WRITE] SELECT completed\r\n", \ lambda data: "* 1 FETCH ((RFC822) {12}\r\nbody" + \ " text\r\n)\r\n" + \ - data.split()[0] + " OK FETCH completed\r\n", \ - lambda data: "* 1 FETCH (FLAGS (\UNSEEN))\r\n" + \ - data.split()[0] + " OK STORE completed\r\n"], \ - ["^[^ ]* SELECT INBOX", \ - "^[^ ]* FETCH 1 \(RFC822\)", \ - "^[^ ]* STORE 1 FLAGS \(UNSEEN\)"], \ + data.split()[0] + " OK FETCH completed\r\n"], \ + ["^[^ ]* EXAMINE INBOX", \ + "^[^ ]* FETCH 1 \(RFC822\)"], \ lambda self: self.assertEquals(self.imap_connection.get_mail_summary(1), \ (u"From : None\nSubject : None\n\n", \ u"None"))) @@ -264,12 +261,9 @@ class IMAPConnection_TestCase(unittest.TestCase): " OK [READ-WRITE] SELECT completed\r\n", \ lambda data: "* 1 FETCH ((RFC822) {11}\r\nbody" + \ " text\r\n)\r\n" + \ - data.split()[0] + " OK FETCH completed\r\n", \ - lambda data: "* 1 FETCH (FLAGS (\UNSEEN))\r\n" + \ - data.split()[0] + " OK STORE completed\r\n"], \ - ["^[^ ]* SELECT INBOX", \ - "^[^ ]* FETCH 1 \(RFC822\)", \ - "^[^ ]* STORE 1 FLAGS \(UNSEEN\)"], \ + data.split()[0] + " OK FETCH completed\r\n"], \ + ["^[^ ]* EXAMINE INBOX", \ + "^[^ ]* FETCH 1 \(RFC822\)",], \ lambda self: self.assertEquals(self.imap_connection.get_mail(1), \ (u"From : None\nSubject : None\n\nbody text\r\n\n", \ u"None")))