Store mailbox with "/" delimiter and discover when populating account what is the real delimiter
darcs-hash:20071031165547-86b55-50bb56e0db9ff77385656b126d7f0f2a02ff3d3a.gz
This commit is contained in:
@@ -56,9 +56,11 @@ class MailAccountManager(AccountManager):
|
|||||||
from_jid,
|
from_jid,
|
||||||
account_type,
|
account_type,
|
||||||
lang_class):
|
lang_class):
|
||||||
"""Handle get_register on an IMAP account.
|
"""
|
||||||
|
Handle get_register on an IMAP account.
|
||||||
Return a preinitialized form.
|
Return a preinitialized form.
|
||||||
account_type contains 'account_type + imap_dir'"""
|
account_type contains 'account_type + imap_dir'
|
||||||
|
"""
|
||||||
splitted_node = account_type.split("/")
|
splitted_node = account_type.split("/")
|
||||||
splitted_node_len = len(splitted_node)
|
splitted_node_len = len(splitted_node)
|
||||||
if splitted_node_len == 1 or \
|
if splitted_node_len == 1 or \
|
||||||
@@ -71,6 +73,7 @@ class MailAccountManager(AccountManager):
|
|||||||
else:
|
else:
|
||||||
info_query = info_query.make_result_response()
|
info_query = info_query.make_result_response()
|
||||||
model.db_connect()
|
model.db_connect()
|
||||||
|
# TODO : "/" is default, "." could be
|
||||||
imap_dir = "/".join(splitted_node[1:])
|
imap_dir = "/".join(splitted_node[1:])
|
||||||
bare_from_jid = from_jid.bare()
|
bare_from_jid = from_jid.bare()
|
||||||
_account = account.get_account_filter(\
|
_account = account.get_account_filter(\
|
||||||
@@ -80,17 +83,20 @@ class MailAccountManager(AccountManager):
|
|||||||
account_class=IMAPAccount)
|
account_class=IMAPAccount)
|
||||||
query = info_query.new_query("jabber:iq:register")
|
query = info_query.new_query("jabber:iq:register")
|
||||||
if _account is not None:
|
if _account is not None:
|
||||||
|
# update account
|
||||||
result = self.generate_registration_form_init(lang_class,
|
result = self.generate_registration_form_init(lang_class,
|
||||||
_account)
|
_account)
|
||||||
else:
|
else:
|
||||||
_account = account.get_account(bare_from_jid, name,
|
_account = account.get_account(bare_from_jid, name,
|
||||||
IMAPAccount)
|
IMAPAccount)
|
||||||
if _account is not None:
|
if _account is not None:
|
||||||
|
# create new account based on current one
|
||||||
result = self.generate_registration_form_init(lang_class,
|
result = self.generate_registration_form_init(lang_class,
|
||||||
_account)
|
_account)
|
||||||
result["name"].value = None
|
result["name"].value = None
|
||||||
result["name"].type = "text-single"
|
result["name"].type = "text-single"
|
||||||
else:
|
else:
|
||||||
|
# create new account from scratch
|
||||||
result = self.generate_registration_form(\
|
result = self.generate_registration_form(\
|
||||||
lang_class,
|
lang_class,
|
||||||
IMAPAccount,
|
IMAPAccount,
|
||||||
|
|||||||
@@ -137,17 +137,17 @@ class Lang(jcl.lang.Lang):
|
|||||||
send_mail_ok_body = u"Votre email a été envoyé à %s."
|
send_mail_ok_body = u"Votre email a été envoyé à %s."
|
||||||
|
|
||||||
help_message_body = u"Pour envoyer un email avec JMC, vous avez le choix " \
|
help_message_body = u"Pour envoyer un email avec JMC, vous avez le choix " \
|
||||||
+ "entre :\n" \
|
+ u"entre :\n" \
|
||||||
+ " - Envoyer un message à la passerelle JMC: le sujet de l'email" \
|
+ u" - Envoyer un message à la passerelle JMC: le sujet de l'email" \
|
||||||
+ " sera le sujet du message Jabber ou le sujet spécifié avec la " \
|
+ u" sera le sujet du message Jabber ou le sujet spécifié avec la " \
|
||||||
+ "syntaxe suivant dans le corps du message Jabber :\n" \
|
+ u"syntaxe suivant dans le corps du message Jabber :\n" \
|
||||||
+ "\tSubject: votre sujet\n" \
|
+ u"\tSubject: votre sujet\n" \
|
||||||
+ " Pour spécifier les destinataires de l'email, il faut ajouter une" \
|
+ u" Pour spécifier les destinataires de l'email, il faut ajouter une" \
|
||||||
+ " ligne au corps du message Jabber avec la syntaxe suivante:\n" \
|
+ u" ligne au corps du message Jabber avec la syntaxe suivante:\n" \
|
||||||
+ "\tTo: to_email@test.com\n\n" \
|
+ u"\tTo: to_email@test.com\n\n" \
|
||||||
+ " - Ajouter un contact à votre roster, avec comme JID " \
|
+ u" - Ajouter un contact à votre roster, avec comme JID " \
|
||||||
+ "to_email\%test.com@jmc.test.com, où to_email@test.com est " \
|
+ u"to_email\%test.com@jmc.test.com, où to_email@test.com est " \
|
||||||
+ "l'adresse du destinataire."
|
+ u"l'adresse du destinataire."
|
||||||
|
|
||||||
class nl(jcl.lang.Lang.nl):
|
class nl(jcl.lang.Lang.nl):
|
||||||
# TODO: when finish, delete this line and uncomment in tests/lang.py the makeSuite(Language_nl_TestCase, 'test') line
|
# TODO: when finish, delete this line and uncomment in tests/lang.py the makeSuite(Language_nl_TestCase, 'test') line
|
||||||
|
|||||||
@@ -373,6 +373,7 @@ class MailAccount(PresenceAccount):
|
|||||||
|
|
||||||
class IMAPAccount(MailAccount):
|
class IMAPAccount(MailAccount):
|
||||||
mailbox = StringCol(default="INBOX")
|
mailbox = StringCol(default="INBOX")
|
||||||
|
delimiter = StringCol(default=".")
|
||||||
|
|
||||||
def _get_register_fields(cls, real_class=None):
|
def _get_register_fields(cls, real_class=None):
|
||||||
"""See Account._get_register_fields
|
"""See Account._get_register_fields
|
||||||
@@ -397,13 +398,19 @@ class IMAPAccount(MailAccount):
|
|||||||
self.__logger = logging.getLogger("jmc.IMAPConnection")
|
self.__logger = logging.getLogger("jmc.IMAPConnection")
|
||||||
self._regexp_list = re.compile("\((.*)\) \"(.)\" \"?([^\"]*)\"?$")
|
self._regexp_list = re.compile("\((.*)\) \"(.)\" \"?([^\"]*)\"?$")
|
||||||
self.__cached_folders = {}
|
self.__cached_folders = {}
|
||||||
self.default_delimiter = "."
|
|
||||||
|
|
||||||
def get_type(self):
|
def get_type(self):
|
||||||
if self.ssl:
|
if self.ssl:
|
||||||
return "imaps"
|
return "imaps"
|
||||||
return "imap"
|
return "imap"
|
||||||
|
|
||||||
|
def _get_real_mailbox(self):
|
||||||
|
"""
|
||||||
|
mailbox attribute is stored with "/" to delimit folders.
|
||||||
|
real mailbox is the folder with the delimiter used by the IMAP server
|
||||||
|
"""
|
||||||
|
return self.mailbox.replace("/", self.delimiter)
|
||||||
|
|
||||||
def get_status(self):
|
def get_status(self):
|
||||||
return MailAccount.get_status(self) + "/" + self.mailbox
|
return MailAccount.get_status(self) + "/" + self.mailbox
|
||||||
|
|
||||||
@@ -427,7 +434,7 @@ class IMAPAccount(MailAccount):
|
|||||||
|
|
||||||
def get_mail_list(self):
|
def get_mail_list(self):
|
||||||
self.__logger.debug("Getting mail list")
|
self.__logger.debug("Getting mail list")
|
||||||
typ, data = self.connection.select(self.mailbox)
|
typ, data = self.connection.select(self._get_real_mailbox())
|
||||||
typ, data = self.connection.search(None, 'RECENT')
|
typ, data = self.connection.search(None, 'RECENT')
|
||||||
if typ == 'OK':
|
if typ == 'OK':
|
||||||
return data[0].split(' ')
|
return data[0].split(' ')
|
||||||
@@ -476,8 +483,8 @@ class IMAPAccount(MailAccount):
|
|||||||
for line in data:
|
for line in data:
|
||||||
match = self._regexp_list.match(line)
|
match = self._regexp_list.match(line)
|
||||||
if match is not None:
|
if match is not None:
|
||||||
self.default_delimiter = match.group(2)
|
delimiter = match.group(2)
|
||||||
subdir = match.group(3).split(self.default_delimiter)
|
subdir = match.group(3).split(delimiter)
|
||||||
self._add_full_path_to_cache(subdir)
|
self._add_full_path_to_cache(subdir)
|
||||||
return self.__cached_folders
|
return self.__cached_folders
|
||||||
|
|
||||||
@@ -485,7 +492,6 @@ class IMAPAccount(MailAccount):
|
|||||||
"""
|
"""
|
||||||
imap_dir: IMAP directory to list. subdirs must be delimited by '/'
|
imap_dir: IMAP directory to list. subdirs must be delimited by '/'
|
||||||
"""
|
"""
|
||||||
# TODO : implement with cache (ie. only one connection)
|
|
||||||
self.__logger.debug("Listing IMAP dir '" + str(imap_dir) + "'")
|
self.__logger.debug("Listing IMAP dir '" + str(imap_dir) + "'")
|
||||||
if self.__cached_folders == {}:
|
if self.__cached_folders == {}:
|
||||||
if not self.connected:
|
if not self.connected:
|
||||||
@@ -504,6 +510,31 @@ class IMAPAccount(MailAccount):
|
|||||||
current_folder = current_folder[folder]
|
current_folder = current_folder[folder]
|
||||||
return current_folder.keys()
|
return current_folder.keys()
|
||||||
|
|
||||||
|
def populate_handler(self):
|
||||||
|
"""
|
||||||
|
Handler called when populating account
|
||||||
|
"""
|
||||||
|
# Get delimiter
|
||||||
|
if not self.connected:
|
||||||
|
self.connect()
|
||||||
|
typ, data = self.connection.list(self.mailbox)
|
||||||
|
if typ == 'OK':
|
||||||
|
line = data[0]
|
||||||
|
match = self._regexp_list.match(line)
|
||||||
|
if match is not None:
|
||||||
|
self.delimiter = match.group(2)
|
||||||
|
else:
|
||||||
|
self.disconnect()
|
||||||
|
raise Exception("Cannot find mailbox " + self.mailbox)
|
||||||
|
else:
|
||||||
|
self.disconnect()
|
||||||
|
raise Exception("Cannot find mailbox " + self.mailbox)
|
||||||
|
self.disconnect()
|
||||||
|
# replace any previous delimiter in self.mailbox by "/"
|
||||||
|
if self.delimiter != "/":
|
||||||
|
self.mailbox = self.mailbox.replace(self.delimiter, "/")
|
||||||
|
|
||||||
|
|
||||||
class POP3Account(MailAccount):
|
class POP3Account(MailAccount):
|
||||||
nb_mail = IntCol(default=0)
|
nb_mail = IntCol(default=0)
|
||||||
lastmail = IntCol(default=0)
|
lastmail = IntCol(default=0)
|
||||||
|
|||||||
@@ -242,8 +242,8 @@ class IMAPAccount_TestCase(InheritableAccount_TestCase):
|
|||||||
self.imap_account.ssl = False
|
self.imap_account.ssl = False
|
||||||
self.account_class = IMAPAccount
|
self.account_class = IMAPAccount
|
||||||
|
|
||||||
def make_test(responses=None, queries=None, core=None):
|
def make_test(self, responses=None, queries=None, core=None):
|
||||||
def inner(self):
|
def inner():
|
||||||
self.server = server.DummyServer("localhost", 1143)
|
self.server = server.DummyServer("localhost", 1143)
|
||||||
thread.start_new_thread(self.server.serve, ())
|
thread.start_new_thread(self.server.serve, ())
|
||||||
self.server.responses = ["* OK [CAPABILITY IMAP4 LOGIN-REFERRALS " + \
|
self.server.responses = ["* OK [CAPABILITY IMAP4 LOGIN-REFERRALS " + \
|
||||||
@@ -261,20 +261,25 @@ class IMAPAccount_TestCase(InheritableAccount_TestCase):
|
|||||||
if queries:
|
if queries:
|
||||||
self.server.queries += queries
|
self.server.queries += queries
|
||||||
self.server.queries += ["^[^ ]* LOGOUT"]
|
self.server.queries += ["^[^ ]* LOGOUT"]
|
||||||
self.imap_account.connect()
|
if not self.imap_account.connected:
|
||||||
|
self.imap_account.connect()
|
||||||
self.failUnless(self.imap_account.connection, \
|
self.failUnless(self.imap_account.connection, \
|
||||||
"Cannot establish connection")
|
"Cannot establish connection")
|
||||||
if core:
|
if core:
|
||||||
model.db_connect()
|
model.db_connect()
|
||||||
core(self)
|
core(self)
|
||||||
model.db_disconnect()
|
model.db_disconnect()
|
||||||
self.imap_account.disconnect()
|
if self.imap_account.connected:
|
||||||
|
self.imap_account.disconnect()
|
||||||
self.failUnless(self.server.verify_queries())
|
self.failUnless(self.server.verify_queries())
|
||||||
return inner
|
return inner
|
||||||
|
|
||||||
test_connection = make_test()
|
def test_connection(self):
|
||||||
|
test_func = self.make_test()
|
||||||
|
test_func()
|
||||||
|
|
||||||
test_get_mail_list = make_test([lambda data: "* 42 EXISTS\n* 1 RECENT\n* OK" +\
|
def test_get_mail_list(self):
|
||||||
|
test_func = self.make_test([lambda data: "* 42 EXISTS\n* 1 RECENT\n* OK" +\
|
||||||
" [UNSEEN 9]\n* FLAGS (\Deleted \Seen\*)\n*" +\
|
" [UNSEEN 9]\n* FLAGS (\Deleted \Seen\*)\n*" +\
|
||||||
" OK [PERMANENTFLAGS (\Deleted \Seen\*)\n" + \
|
" OK [PERMANENTFLAGS (\Deleted \Seen\*)\n" + \
|
||||||
data.split()[0] + \
|
data.split()[0] + \
|
||||||
@@ -285,22 +290,60 @@ class IMAPAccount_TestCase(InheritableAccount_TestCase):
|
|||||||
"^[^ ]* SEARCH RECENT"], \
|
"^[^ ]* SEARCH RECENT"], \
|
||||||
lambda self: \
|
lambda self: \
|
||||||
self.assertEquals(self.imap_account.get_mail_list(), ['9', '10']))
|
self.assertEquals(self.imap_account.get_mail_list(), ['9', '10']))
|
||||||
|
test_func()
|
||||||
|
|
||||||
test_get_mail_summary = make_test([lambda data: "* 42 EXISTS\r\n* 1 RECENT\r\n* OK" +\
|
def test_get_mail_list_delimiter1(self):
|
||||||
" [UNSEEN 9]\r\n* FLAGS (\Deleted \Seen\*)\r\n*" +\
|
self.imap_account.mailbox = "INBOX/dir1/subdir2"
|
||||||
" OK [PERMANENTFLAGS (\Deleted \Seen\*)\r\n" + \
|
self.imap_account.delimiter = "."
|
||||||
data.split()[0] + \
|
test_func = self.make_test( \
|
||||||
" OK [READ-WRITE] SELECT completed\r\n", \
|
[lambda data: "* 42 EXISTS\n* 1 RECENT\n* OK" + \
|
||||||
lambda data: "* 1 FETCH ((RFC822) {12}\r\nbody" + \
|
" [UNSEEN 9]\n* FLAGS (\Deleted \Seen\*)\n*" + \
|
||||||
" text\r\n)\r\n" + \
|
" OK [PERMANENTFLAGS (\Deleted \Seen\*)\n" + \
|
||||||
data.split()[0] + " OK FETCH completed\r\n"], \
|
data.split()[0] + \
|
||||||
["^[^ ]* EXAMINE INBOX", \
|
" OK [READ-WRITE] SELECT completed\n", \
|
||||||
"^[^ ]* FETCH 1 \(RFC822\)"], \
|
lambda data: "* SEARCH 9 10 \n" + \
|
||||||
lambda self: self.assertEquals(self.imap_account.get_mail_summary(1), \
|
data.split()[0] + " OK SEARCH completed\n"], \
|
||||||
(u"From : None\nSubject : None\n\n", \
|
["^[^ ]* SELECT \"?INBOX\.dir1\.subdir2\"?",
|
||||||
u"None")))
|
"^[^ ]* SEARCH RECENT"], \
|
||||||
|
lambda self: \
|
||||||
|
self.assertEquals(self.imap_account.get_mail_list(), ['9', '10']))
|
||||||
|
test_func()
|
||||||
|
|
||||||
test_get_mail = make_test([lambda data: "* 42 EXISTS\r\n* 1 RECENT\r\n* OK" +\
|
def test_get_mail_list_delimiter2(self):
|
||||||
|
self.imap_account.mailbox = "INBOX/dir1/subdir2"
|
||||||
|
self.imap_account.delimiter = "/"
|
||||||
|
test_func = self.make_test( \
|
||||||
|
[lambda data: "* 42 EXISTS\n* 1 RECENT\n* OK" + \
|
||||||
|
" [UNSEEN 9]\n* FLAGS (\Deleted \Seen\*)\n*" + \
|
||||||
|
" OK [PERMANENTFLAGS (\Deleted \Seen\*)\n" + \
|
||||||
|
data.split()[0] + \
|
||||||
|
" OK [READ-WRITE] SELECT completed\n", \
|
||||||
|
lambda data: "* SEARCH 9 10 \n" + \
|
||||||
|
data.split()[0] + " OK SEARCH completed\n"], \
|
||||||
|
["^[^ ]* SELECT \"?INBOX/dir1/subdir2\"?",
|
||||||
|
"^[^ ]* SEARCH RECENT"], \
|
||||||
|
lambda self: \
|
||||||
|
self.assertEquals(self.imap_account.get_mail_list(), ['9', '10']))
|
||||||
|
test_func()
|
||||||
|
|
||||||
|
def test_get_mail_summary(self):
|
||||||
|
test_func = self.make_test([lambda data: "* 42 EXISTS\r\n* 1 RECENT\r\n* OK" +\
|
||||||
|
" [UNSEEN 9]\r\n* FLAGS (\Deleted \Seen\*)\r\n*" +\
|
||||||
|
" OK [PERMANENTFLAGS (\Deleted \Seen\*)\r\n" + \
|
||||||
|
data.split()[0] + \
|
||||||
|
" 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"],
|
||||||
|
["^[^ ]* EXAMINE INBOX",
|
||||||
|
"^[^ ]* FETCH 1 \(RFC822\)"],
|
||||||
|
lambda self: self.assertEquals(self.imap_account.get_mail_summary(1),
|
||||||
|
(u"From : None\nSubject : None\n\n",
|
||||||
|
u"None")))
|
||||||
|
test_func()
|
||||||
|
|
||||||
|
def test_get_mail(self):
|
||||||
|
test_func = self.make_test([lambda data: "* 42 EXISTS\r\n* 1 RECENT\r\n* OK" +\
|
||||||
" [UNSEEN 9]\r\n* FLAGS (\Deleted \Seen\*)\r\n*" +\
|
" [UNSEEN 9]\r\n* FLAGS (\Deleted \Seen\*)\r\n*" +\
|
||||||
" OK [PERMANENTFLAGS (\Deleted \Seen\*)\r\n" + \
|
" OK [PERMANENTFLAGS (\Deleted \Seen\*)\r\n" + \
|
||||||
data.split()[0] + \
|
data.split()[0] + \
|
||||||
@@ -313,8 +356,10 @@ class IMAPAccount_TestCase(InheritableAccount_TestCase):
|
|||||||
lambda self: self.assertEquals(self.imap_account.get_mail(1), \
|
lambda self: self.assertEquals(self.imap_account.get_mail(1), \
|
||||||
(u"From : None\nSubject : None\n\nbody text\r\n\n", \
|
(u"From : None\nSubject : None\n\nbody text\r\n\n", \
|
||||||
u"None")))
|
u"None")))
|
||||||
|
test_func()
|
||||||
|
|
||||||
test_build_folder_cache = make_test(\
|
def test_build_folder_cache(self):
|
||||||
|
test_func = self.make_test(\
|
||||||
[lambda data: '* LIST () "." "INBOX"\r\n' + \
|
[lambda data: '* LIST () "." "INBOX"\r\n' + \
|
||||||
'* LIST () "." "INBOX.dir1"\r\n' + \
|
'* LIST () "." "INBOX.dir1"\r\n' + \
|
||||||
'* LIST () "." "INBOX.dir1.subdir1"\r\n' + \
|
'* LIST () "." "INBOX.dir1.subdir1"\r\n' + \
|
||||||
@@ -328,6 +373,7 @@ class IMAPAccount_TestCase(InheritableAccount_TestCase):
|
|||||||
{"subdir1": {},
|
{"subdir1": {},
|
||||||
"subdir2": {}},
|
"subdir2": {}},
|
||||||
"dir2": {}}}))
|
"dir2": {}}}))
|
||||||
|
test_func()
|
||||||
|
|
||||||
def test_ls_dir_base(self):
|
def test_ls_dir_base(self):
|
||||||
self.test_build_folder_cache()
|
self.test_build_folder_cache()
|
||||||
@@ -356,6 +402,34 @@ class IMAPAccount_TestCase(InheritableAccount_TestCase):
|
|||||||
self.assertEquals(result,
|
self.assertEquals(result,
|
||||||
["subdir1", "subdir2"])
|
["subdir1", "subdir2"])
|
||||||
|
|
||||||
|
def test_populate_handler(self):
|
||||||
|
self.assertEquals(".", self.imap_account.delimiter)
|
||||||
|
self.imap_account.mailbox = "INBOX.dir1.subdir2"
|
||||||
|
def call_func(self):
|
||||||
|
self.imap_account.populate_handler()
|
||||||
|
self.assertEquals("INBOX/dir1/subdir2", self.imap_account.mailbox)
|
||||||
|
test_func = self.make_test(\
|
||||||
|
[lambda data: '* LIST () "." "INBOX.dir1.subdir2"\r\n' + \
|
||||||
|
data.split()[0] + ' OK LIST completed\r\n'],
|
||||||
|
["^[^ ]* LIST \"?INBOX.dir1.subdir2\"? \*"],
|
||||||
|
call_func)
|
||||||
|
test_func()
|
||||||
|
|
||||||
|
def test_populate_handler_wrong_mailbox(self):
|
||||||
|
self.assertEquals(".", self.imap_account.delimiter)
|
||||||
|
self.imap_account.mailbox = "INBOX.dir1.subdir2"
|
||||||
|
def call_func(self):
|
||||||
|
try:
|
||||||
|
self.imap_account.populate_handler()
|
||||||
|
except Exception, e:
|
||||||
|
return
|
||||||
|
self.fail("Exception should have been raised")
|
||||||
|
test_func = self.make_test(\
|
||||||
|
[lambda data: data.split()[0] + ' ERR LIST completed\r\n'],
|
||||||
|
["^[^ ]* LIST \"?INBOX.dir1.subdir2\"? \*"],
|
||||||
|
call_func)
|
||||||
|
test_func()
|
||||||
|
|
||||||
class SMTPAccount_TestCase(Account_TestCase):
|
class SMTPAccount_TestCase(Account_TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
JCLTestCase.setUp(self, tables=[Account, ExampleAccount, User,
|
JCLTestCase.setUp(self, tables=[Account, ExampleAccount, User,
|
||||||
|
|||||||
Reference in New Issue
Block a user