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

View File

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

View File

@@ -73,7 +73,7 @@ class DBMStorage(Storage):
self.sync()
def load(self):
# print "DBM LOAD"
# print "DBM LOAD"
str_registered = anydbm.open(self.file, \
'c')
result = {}
@@ -101,7 +101,7 @@ class DBMStorage(Storage):
registered[key], key)
else:
self.__str_registered[pk] = str(registered)
print "STORING : " + pk + " = " + str(registered)
# print "STORING : " + pk + " = " + str(registered)
def store(self):
# print "DBM STORE"
@@ -161,7 +161,7 @@ class DBMStorage(Storage):
return result.keys()
def dump(self):
print "dumping"
# print "dumping"
for pk in self.__registered.keys():
print pk + " = " + str(self.__registered[pk])

View File

@@ -42,7 +42,7 @@ class MailConnectionFactory_TestCase(unittest.TestCase):
self.assertEquals(mc, mc)
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.login, "login")
self.assertEquals(mc.password, "passwd")
@@ -55,9 +55,10 @@ class MailConnectionFactory_TestCase(unittest.TestCase):
self.assertEquals(mc.xa_action, mailconnection.DIGEST)
self.assertEquals(mc.dnd_action, mailconnection.DIGEST)
self.assertEquals(mc.offline_action, mailconnection.RETRIEVE)
self.assertEquals(mc.interval, 4)
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.login, "login")
self.assertEquals(mc.password, "passwd")
@@ -70,9 +71,10 @@ class MailConnectionFactory_TestCase(unittest.TestCase):
self.assertEquals(mc.xa_action, mailconnection.DIGEST)
self.assertEquals(mc.dnd_action, mailconnection.DIGEST)
self.assertEquals(mc.offline_action, mailconnection.RETRIEVE)
self.assertEquals(mc.interval, 4)
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.login, "login")
self.assertEquals(mc.password, "passwd")
@@ -84,9 +86,10 @@ class MailConnectionFactory_TestCase(unittest.TestCase):
self.assertEquals(mc.xa_action, mailconnection.DIGEST)
self.assertEquals(mc.dnd_action, mailconnection.DIGEST)
self.assertEquals(mc.offline_action, mailconnection.RETRIEVE)
self.assertEquals(mc.interval, 4)
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.login, "login")
self.assertEquals(mc.password, "passwd")
@@ -98,4 +101,5 @@ class MailConnectionFactory_TestCase(unittest.TestCase):
self.assertEquals(mc.xa_action, mailconnection.DIGEST)
self.assertEquals(mc.dnd_action, mailconnection.DIGEST)
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):
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",
password = "password1",
host = "host1",
@@ -58,6 +59,7 @@ class DBMStorage_TestCase(unittest.TestCase):
self._account1.xa_action = mailconnection.DO_NOTHING
self._account1.dnd_action = mailconnection.DO_NOTHING
self._account1.offline_action = mailconnection.DO_NOTHING
self._account1.interval = 4
self._account2 = IMAPConnection(login = "login2",
password = "password2",
host = "host2",
@@ -70,6 +72,7 @@ class DBMStorage_TestCase(unittest.TestCase):
self._account2.xa_action = mailconnection.DO_NOTHING
self._account2.dnd_action = mailconnection.DO_NOTHING
self._account2.offline_action = mailconnection.DO_NOTHING
self._account2.interval = 4
def tearDown(self):
os.remove(self._storage.file)
@@ -84,7 +87,7 @@ class DBMStorage_TestCase(unittest.TestCase):
def test_set_sync_get(self):
self._storage[("test@localhost", "account1")] = self._account1
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", "account2")], self._account2)