Check mail and interval storage

- interval per account is stored
- check mail algorithm implemented
- new timer method

darcs-hash:20060122165510-86b55-f432cb2c421fac7069cf45a6cd288b8a9998b924.gz
This commit is contained in:
David Rousselie
2006-01-22 17:55:10 +01:00
parent f8ded9a3d5
commit ccde3a2bc9
6 changed files with 72 additions and 53 deletions

View File

@@ -23,10 +23,12 @@
import re import re
import signal import signal
import threading import threading
import thread
import logging import logging
import sys import sys
import anydbm import anydbm
import os import os
import time
import mailconnection import mailconnection
from mailconnection import * from mailconnection import *
@@ -77,8 +79,9 @@ class MailComponent(Component):
self.__storage.nb_pk_fields = 2 self.__storage.nb_pk_fields = 2
self.__reg_form = None self.__reg_form = None
self.__reg_form_init = None self.__reg_form_init = None
# dump registered accounts (save) at least every hour # dump registered accounts (save) every hour
self.__count = 60 / self.__interval self.__count = 60
self.running = False
def __del__(self): def __del__(self):
logging.shutdown() logging.shutdown()
@@ -352,8 +355,8 @@ class MailComponent(Component):
""" Looping method """ """ Looping method """
def run(self, timeout): def run(self, timeout):
self.connect() self.connect()
# Set check mail timer self.running = True
threading.Timer(self.__interval * 60, self.time_handler) thread.start_new_thread(self.time_handler, ())
try: try:
while (not self.__shutdown and self.stream while (not self.__shutdown and self.stream
and not self.stream.eof and self.stream.socket is not None): and not self.stream.eof and self.stream.socket is not None):
@@ -367,6 +370,7 @@ class MailComponent(Component):
finally: finally:
## TODO : for jid in self.__storage.keys(()) ## TODO : for jid in self.__storage.keys(())
## for name in self.__storage.keys((jid,)) ## for name in self.__storage.keys((jid,))
self.running = False
if self.stream: if self.stream:
for jid in self.__storage.keys(()): for jid in self.__storage.keys(()):
p = Presence(from_jid = unicode(self.jid), to_jid = jid, \ p = Presence(from_jid = unicode(self.jid), to_jid = jid, \
@@ -399,30 +403,31 @@ class MailComponent(Component):
self.__shutdown = 1 self.__shutdown = 1
""" SIGALRM signal handler """ """ SIGALRM signal handler """
def time_handler(self, signum, frame): def time_handler(self):
self.__logger.debug("Signal %i received, checking mail..." % (signum,)) self.__logger.debug("Check mail thread started...")
while self.running:
self.check_all_mail() self.check_all_mail()
self.__logger.debug("Resetting alarm signal") self.__logger.debug("Resetting alarm signal")
threading.Timer(self.__interval * 60, self.time_handler)
if self.__count == 0: if self.__count == 0:
self.__logger.debug("Dumping registered accounts Database") self.__logger.debug("Dumping registered accounts Database")
self.__storage.sync() self.__storage.sync()
self.__count = 60 / self.__interval self.__count = 60
else: else:
self.__count -= 1 self.__count -= 1
time.sleep(60)
""" Component authentication handler """ """ Component authentication handler """
def authenticated(self): def authenticated(self):
self.__logger.debug("AUTHENTICATED") self.__logger.debug("AUTHENTICATED")
Component.authenticated(self) Component.authenticated(self)
for jid, name in self.__storage.keys():
p = Presence(from_jid = name + "@" + unicode(self.jid), \
to_jid = jid, stanza_type = "probe")
self.stream.send(p)
for jid in self.__storage.keys(()): for jid in self.__storage.keys(()):
p = Presence(from_jid = unicode(self.jid), \ p = Presence(from_jid = unicode(self.jid), \
to_jid = jid, stanza_type = "probe") to_jid = jid, stanza_type = "probe")
self.stream.send(p) self.stream.send(p)
for jid, name in self.__storage.keys():
p = Presence(from_jid = name + "@" + unicode(self.jid), \
to_jid = jid, stanza_type = "probe")
self.stream.send(p)
self.stream.set_iq_get_handler("query", "jabber:iq:version", \ self.stream.set_iq_get_handler("query", "jabber:iq:version", \
self.get_version) self.get_version)
@@ -473,8 +478,8 @@ class MailComponent(Component):
base_from_jid = unicode(iq.get_from().bare()) base_from_jid = unicode(iq.get_from().bare())
di = DiscoItems() di = DiscoItems()
if not node: if not node:
for jid, name in self.__storage.keys(): for name in self.__storage.keys((base_from_jid,)):
account = self.__storage[(jid, name)] account = self.__storage[(base_from_jid, name)]
str_name = account.get_type() + " connection " + name str_name = account.get_type() + " connection " + name
if account.get_type()[0:4] == "imap": if account.get_type()[0:4] == "imap":
str_name += " (" + account.mailbox + ")" str_name += " (" + account.mailbox + ")"
@@ -687,7 +692,10 @@ class MailComponent(Component):
elif self.__storage.has_key((base_from_jid, name)): elif self.__storage.has_key((base_from_jid, name)):
account = self.__storage[(base_from_jid, name)] account = self.__storage[(base_from_jid, name)]
# Make available to receive mail only when online # Make available to receive mail only when online
if show is None:
account.status = "online" # TODO get real status = (not show) account.status = "online" # TODO get real status = (not show)
else:
account.status = show
p = Presence(from_jid = name + "@" + \ p = Presence(from_jid = name + "@" + \
unicode(self.jid), \ unicode(self.jid), \
to_jid = from_jid, \ to_jid = from_jid, \
@@ -704,7 +712,7 @@ class MailComponent(Component):
base_from_jid = unicode(from_jid.bare()) base_from_jid = unicode(from_jid.bare())
if stanza.get_to() == unicode(self.jid): if stanza.get_to() == unicode(self.jid):
for jid, name in self.__storage.keys(): for jid, name in self.__storage.keys():
self.__storage[(base_from_jid, name)].status = "offline" # TODO get real status self.__storage[(base_from_jid, name)].status = "offline"
p = Presence(from_jid = name + "@" + unicode(self.jid), \ p = Presence(from_jid = name + "@" + unicode(self.jid), \
to_jid = from_jid, \ to_jid = from_jid, \
stanza_type = "unavailable") stanza_type = "unavailable")
@@ -784,13 +792,12 @@ class MailComponent(Component):
""" Check mail account """ """ Check mail account """
def check_mail(self, jid, name): def check_mail(self, jid, name):
self.__logger.debug("CHECK_MAIL") self.__logger.debug("CHECK_MAIL " + unicode(jid) + " " + name)
account = self.__storage[(jid, name)] account = self.__storage[(jid, name)]
action = account.action action = account.action
if action != "nothing": if action != mailconnection.DO_NOTHING:
try: try:
self.__logger.debug("Checking " \ self.__logger.debug("Checking " + name)
+ name)
self.__logger.debug("\t" + account.login \ self.__logger.debug("\t" + account.login \
+ "@" + account.host) + "@" + account.host)
account.connect() account.connect()
@@ -800,25 +807,26 @@ class MailComponent(Component):
else: else:
num = len(mail_list) num = len(mail_list)
# unseen mails checked by external client # unseen mails checked by external client
if num < account.lastcheck: # TODO : better test to find
account.lastcheck = 0 if num < account.lastmail:
if action == "retrieve": account.lastmail = 0
while account.lastcheck < num: if action == mailconnection.RETRIEVE:
body = account.get_mail(int(mail_list[account.lastcheck])) while account.lastmail < num:
body = account.get_mail(int(mail_list[account.lastmail]))
mesg = Message(from_jid = name + "@" + \ mesg = Message(from_jid = name + "@" + \
unicode(self.jid), \ unicode(self.jid), \
to_jid = jid, \ to_jid = jid, \
stanza_type = "message", \ stanza_type = "message", \
body = body) body = body)
self.stream.send(mesg) self.stream.send(mesg)
account.lastcheck += 1 account.lastmail += 1
else: else:
body = "" body = ""
while account.lastcheck < num: while account.lastmail < num:
body += \ body += \
account.get_mail_summary(int(mail_list[account.lastcheck])) \ account.get_mail_summary(int(mail_list[account.lastmail])) \
+ "\n----------------------------------\n" + "\n----------------------------------\n"
account.lastcheck += 1 account.lastmail += 1
if body != "": if body != "":
mesg = Message(from_jid = name + "@" + \ mesg = Message(from_jid = name + "@" + \
unicode(self.jid), \ unicode(self.jid), \
@@ -826,7 +834,6 @@ class MailComponent(Component):
stanza_type = "headline", \ stanza_type = "headline", \
body = body) body = body)
self.stream.send(mesg) self.stream.send(mesg)
account.disconnect() account.disconnect()
except Exception,e: except Exception,e:
self.__logger.debug("Error while checking mail : %s" \ self.__logger.debug("Error while checking mail : %s" \
@@ -835,7 +842,9 @@ class MailComponent(Component):
""" check mail handler """ """ check mail handler """
def check_all_mail(self): def check_all_mail(self):
self.__logger.debug("CHECK_ALL_MAIL") self.__logger.debug("CHECK_ALL_MAIL")
## TODO for jid, name in self.__storage.keys():
# for jid in self.__registered.keys(): account = self.__storage[(jid, name)]
# for name in self.__registered[jid].keys(): account.lastcheck += 1
# self.check_mail(jid, name) if account.lastcheck == account.interval:
account.lastcheck = 0
self.check_mail(jid, name)

View File

@@ -148,7 +148,7 @@ class MailConnection(object):
self.host = host self.host = host
self.port = port self.port = port
self.ssl = ssl self.ssl = ssl
self.lastcheck = 0 self.lastmail = 0
self.status = "offline" self.status = "offline"
self.connection = None self.connection = None
self.chat_action = RETRIEVE self.chat_action = RETRIEVE
@@ -158,6 +158,7 @@ class MailConnection(object):
self.dnd_action = RETRIEVE self.dnd_action = RETRIEVE
self.offline_action = DO_NOTHING self.offline_action = DO_NOTHING
self.interval = 5 self.interval = 5
self.lastcheck = 0
def __eq__(self, other): def __eq__(self, other):
return self.get_type() == other.get_type() \ return self.get_type() == other.get_type() \
@@ -178,7 +179,7 @@ class MailConnection(object):
return self.get_type() + "#" + self.login + "#" + self.password + "#" \ return self.get_type() + "#" + self.login + "#" + self.password + "#" \
+ self.host + "#" + str(self.port) + "#" + str(self.chat_action) + "#" \ + self.host + "#" + str(self.port) + "#" + str(self.chat_action) + "#" \
+ str(self.online_action) + "#" + str(self.away_action) + "#" + \ + str(self.online_action) + "#" + str(self.away_action) + "#" + \
str(self.xa_action) + "#" + str(self.dnd_action) + "#" + str(self.offline_action) str(self.xa_action) + "#" + str(self.dnd_action) + "#" + str(self.offline_action) + "#" + str(self.interval)
def get_decoded_part(self, part): def get_decoded_part(self, part):
content_charset = part.get_content_charset() content_charset = part.get_content_charset()
@@ -251,7 +252,7 @@ class MailConnection(object):
"offline": self.offline_action} "offline": self.offline_action}
if mapping.has_key(self.status): if mapping.has_key(self.status):
return mapping[self.status] return mapping[self.status]
return NOTHING return DO_NOTHING
action = property(get_action) action = property(get_action)

View File

@@ -68,6 +68,7 @@ def str_to_mail_connection(connection_string):
xa_action = int(arg_list.pop()) xa_action = int(arg_list.pop())
dnd_action = int(arg_list.pop()) dnd_action = int(arg_list.pop())
offline_action = int(arg_list.pop()) offline_action = int(arg_list.pop())
interval = int(arg_list.pop())
result = None result = None
if type == "imap": if type == "imap":
mailbox = arg_list.pop() mailbox = arg_list.pop()
@@ -105,6 +106,7 @@ def str_to_mail_connection(connection_string):
result.xa_action = xa_action result.xa_action = xa_action
result.dnd_action = dnd_action result.dnd_action = dnd_action
result.offline_action = offline_action result.offline_action = offline_action
result.interval = interval
return result return result

View File

@@ -101,7 +101,7 @@ class DBMStorage(Storage):
registered[key], key) registered[key], key)
else: else:
self.__str_registered[pk] = str(registered) self.__str_registered[pk] = str(registered)
print "STORING : " + pk + " = " + str(registered) # print "STORING : " + pk + " = " + str(registered)
def store(self): def store(self):
# print "DBM STORE" # print "DBM STORE"
@@ -161,7 +161,7 @@ class DBMStorage(Storage):
return result.keys() return result.keys()
def dump(self): def dump(self):
print "dumping" # print "dumping"
for pk in self.__registered.keys(): for pk in self.__registered.keys():
print pk + " = " + str(self.__registered[pk]) print pk + " = " + str(self.__registered[pk])

View File

@@ -42,7 +42,7 @@ class MailConnectionFactory_TestCase(unittest.TestCase):
self.assertEquals(mc, mc) self.assertEquals(mc, mc)
def test_str_to_mail_connection_imap(self): def test_str_to_mail_connection_imap(self):
mc = str_to_mail_connection("imap#login#passwd#host#193#0#0#0#1#1#2#INBOX") mc = str_to_mail_connection("imap#login#passwd#host#193#0#0#0#1#1#2#4#INBOX")
self.assertEquals(mc.get_type(), "imap") self.assertEquals(mc.get_type(), "imap")
self.assertEquals(mc.login, "login") self.assertEquals(mc.login, "login")
self.assertEquals(mc.password, "passwd") self.assertEquals(mc.password, "passwd")
@@ -55,9 +55,10 @@ class MailConnectionFactory_TestCase(unittest.TestCase):
self.assertEquals(mc.xa_action, mailconnection.DIGEST) self.assertEquals(mc.xa_action, mailconnection.DIGEST)
self.assertEquals(mc.dnd_action, mailconnection.DIGEST) self.assertEquals(mc.dnd_action, mailconnection.DIGEST)
self.assertEquals(mc.offline_action, mailconnection.RETRIEVE) self.assertEquals(mc.offline_action, mailconnection.RETRIEVE)
self.assertEquals(mc.interval, 4)
def test_str_to_mail_connection_imaps(self): def test_str_to_mail_connection_imaps(self):
mc = str_to_mail_connection("imaps#login#passwd#host#993#0#0#0#1#1#2#INBOX.SubDir") mc = str_to_mail_connection("imaps#login#passwd#host#993#0#0#0#1#1#2#4#INBOX.SubDir")
self.assertEquals(mc.get_type(), "imaps") self.assertEquals(mc.get_type(), "imaps")
self.assertEquals(mc.login, "login") self.assertEquals(mc.login, "login")
self.assertEquals(mc.password, "passwd") self.assertEquals(mc.password, "passwd")
@@ -70,9 +71,10 @@ class MailConnectionFactory_TestCase(unittest.TestCase):
self.assertEquals(mc.xa_action, mailconnection.DIGEST) self.assertEquals(mc.xa_action, mailconnection.DIGEST)
self.assertEquals(mc.dnd_action, mailconnection.DIGEST) self.assertEquals(mc.dnd_action, mailconnection.DIGEST)
self.assertEquals(mc.offline_action, mailconnection.RETRIEVE) self.assertEquals(mc.offline_action, mailconnection.RETRIEVE)
self.assertEquals(mc.interval, 4)
def test_str_to_mail_connection_pop3(self): def test_str_to_mail_connection_pop3(self):
mc = str_to_mail_connection("pop3#login#passwd#host#110#0#0#0#1#1#2") mc = str_to_mail_connection("pop3#login#passwd#host#110#0#0#0#1#1#2#4")
self.assertEquals(mc.get_type(), "pop3") self.assertEquals(mc.get_type(), "pop3")
self.assertEquals(mc.login, "login") self.assertEquals(mc.login, "login")
self.assertEquals(mc.password, "passwd") self.assertEquals(mc.password, "passwd")
@@ -84,9 +86,10 @@ class MailConnectionFactory_TestCase(unittest.TestCase):
self.assertEquals(mc.xa_action, mailconnection.DIGEST) self.assertEquals(mc.xa_action, mailconnection.DIGEST)
self.assertEquals(mc.dnd_action, mailconnection.DIGEST) self.assertEquals(mc.dnd_action, mailconnection.DIGEST)
self.assertEquals(mc.offline_action, mailconnection.RETRIEVE) self.assertEquals(mc.offline_action, mailconnection.RETRIEVE)
self.assertEquals(mc.interval, 4)
def test_str_to_mail_connection_pop3s(self): def test_str_to_mail_connection_pop3s(self):
mc = str_to_mail_connection("pop3s#login#passwd#host#995#0#0#0#1#1#2") mc = str_to_mail_connection("pop3s#login#passwd#host#995#0#0#0#1#1#2#4")
self.assertEquals(mc.get_type(), "pop3s") self.assertEquals(mc.get_type(), "pop3s")
self.assertEquals(mc.login, "login") self.assertEquals(mc.login, "login")
self.assertEquals(mc.password, "passwd") self.assertEquals(mc.password, "passwd")
@@ -98,4 +101,5 @@ class MailConnectionFactory_TestCase(unittest.TestCase):
self.assertEquals(mc.xa_action, mailconnection.DIGEST) self.assertEquals(mc.xa_action, mailconnection.DIGEST)
self.assertEquals(mc.dnd_action, mailconnection.DIGEST) self.assertEquals(mc.dnd_action, mailconnection.DIGEST)
self.assertEquals(mc.offline_action, mailconnection.RETRIEVE) self.assertEquals(mc.offline_action, mailconnection.RETRIEVE)
self.assertEquals(mc.interval, 4)

View File

@@ -45,7 +45,8 @@ class SQLiteStorage_TestCase(unittest.TestCase):
class DBMStorage_TestCase(unittest.TestCase): class DBMStorage_TestCase(unittest.TestCase):
def setUp(self): def setUp(self):
self._storage = DBMStorage(nb_pk_fields = 2) spool_dir = "./spool/test"
self._storage = DBMStorage(nb_pk_fields = 2, spool_dir = spool_dir)
self._account1 = IMAPConnection(login = "login1", self._account1 = IMAPConnection(login = "login1",
password = "password1", password = "password1",
host = "host1", host = "host1",
@@ -58,6 +59,7 @@ class DBMStorage_TestCase(unittest.TestCase):
self._account1.xa_action = mailconnection.DO_NOTHING self._account1.xa_action = mailconnection.DO_NOTHING
self._account1.dnd_action = mailconnection.DO_NOTHING self._account1.dnd_action = mailconnection.DO_NOTHING
self._account1.offline_action = mailconnection.DO_NOTHING self._account1.offline_action = mailconnection.DO_NOTHING
self._account1.interval = 4
self._account2 = IMAPConnection(login = "login2", self._account2 = IMAPConnection(login = "login2",
password = "password2", password = "password2",
host = "host2", host = "host2",
@@ -70,6 +72,7 @@ class DBMStorage_TestCase(unittest.TestCase):
self._account2.xa_action = mailconnection.DO_NOTHING self._account2.xa_action = mailconnection.DO_NOTHING
self._account2.dnd_action = mailconnection.DO_NOTHING self._account2.dnd_action = mailconnection.DO_NOTHING
self._account2.offline_action = mailconnection.DO_NOTHING self._account2.offline_action = mailconnection.DO_NOTHING
self._account2.interval = 4
def tearDown(self): def tearDown(self):
os.remove(self._storage.file) os.remove(self._storage.file)
@@ -84,7 +87,7 @@ class DBMStorage_TestCase(unittest.TestCase):
def test_set_sync_get(self): def test_set_sync_get(self):
self._storage[("test@localhost", "account1")] = self._account1 self._storage[("test@localhost", "account1")] = self._account1
self._storage[("test@localhost", "account2")] = self._account2 self._storage[("test@localhost", "account2")] = self._account2
loaded_storage = DBMStorage(nb_pk_fields = 2) loaded_storage = DBMStorage(nb_pk_fields = 2, spool_dir = "./spool/test")
self.assertEquals(loaded_storage[("test@localhost", "account1")], self._account1) self.assertEquals(loaded_storage[("test@localhost", "account1")], self._account1)
self.assertEquals(loaded_storage[("test@localhost", "account2")], self._account2) self.assertEquals(loaded_storage[("test@localhost", "account2")], self._account2)