Retrieve mail list for IMAP and POP3 accounts

darcs-hash:20080226194326-86b55-75c821b0474733504a86e66ddf6881af1ec9b431.gz
This commit is contained in:
David Rousselie
2008-02-26 20:43:26 +01:00
parent ebaa5bdc82
commit 9f24171943
5 changed files with 340 additions and 235 deletions

View File

@@ -1,6 +1,6 @@
## ##
## setup.py ## setup.py
## Login : <dax@happycoders.org> ## Login : David Rousselie <dax@happycoders.org>
## Started on Tue Apr 17 21:12:33 2007 David Rousselie ## Started on Tue Apr 17 21:12:33 2007 David Rousselie
## $Id$ ## $Id$
## ##

View File

@@ -221,7 +221,7 @@ class MailFeeder(Feeder):
self.__logger.debug("\t" + _account.login \ self.__logger.debug("\t" + _account.login \
+ "@" + _account.host) + "@" + _account.host)
_account.connect() _account.connect()
mail_list = _account.get_mail_list() mail_list = _account.get_new_mail_list()
default_lang_class = _account.default_lang_class default_lang_class = _account.default_lang_class
if action == MailAccount.RETRIEVE: if action == MailAccount.RETRIEVE:
# TODO : use generator (yield) # TODO : use generator (yield)

View File

@@ -288,7 +288,7 @@ class MailComponent_TestCase(JCLTestCase):
account11.lastcheck = 1 account11.lastcheck = 1
account11.interval = 2 account11.interval = 2
account11.password = "password" account11.password = "password"
account11.get_mail_list = lambda: [] account11.get_new_mail_list = lambda: []
result = self.comp.handler.feeder.feed(account11) result = self.comp.handler.feeder.feed(account11)
self.assertNotEquals(account11.error, None) self.assertNotEquals(account11.error, None)
self.assertEquals(len(result), 0) self.assertEquals(len(result), 0)
@@ -312,7 +312,7 @@ class MailComponent_TestCase(JCLTestCase):
account11.lastcheck = 1 account11.lastcheck = 1
account11.interval = 2 account11.interval = 2
account11.password = "password" account11.password = "password"
account11.get_mail_list = lambda: [] account11.get_new_mail_list = lambda: []
result = self.comp.handler.feeder.feed(account11) result = self.comp.handler.feeder.feed(account11)
self.assertEquals(account11.error, None) self.assertEquals(account11.error, None)
self.assertEquals(result, []) self.assertEquals(result, [])
@@ -336,7 +336,7 @@ class MailComponent_TestCase(JCLTestCase):
account11.lastcheck = 1 account11.lastcheck = 1
account11.interval = 2 account11.interval = 2
account11.password = "password" account11.password = "password"
account11.get_mail_list = lambda: [0, 1] account11.get_new_mail_list = lambda: [0, 1]
account11.get_mail = mock_get_mail account11.get_mail = mock_get_mail
result = self.comp.handler.feeder.feed(account11) result = self.comp.handler.feeder.feed(account11)
self.assertEquals(account11.error, None) self.assertEquals(account11.error, None)
@@ -370,7 +370,7 @@ class MailComponent_TestCase(JCLTestCase):
account11.lastcheck = 1 account11.lastcheck = 1
account11.interval = 2 account11.interval = 2
account11.password = "password" account11.password = "password"
account11.get_mail_list = lambda: [] account11.get_new_mail_list = lambda: []
result = self.comp.handler.feeder.feed(account11) result = self.comp.handler.feeder.feed(account11)
self.assertEquals(account11.error, None) self.assertEquals(account11.error, None)
self.assertEquals(result, []) self.assertEquals(result, [])
@@ -394,7 +394,7 @@ class MailComponent_TestCase(JCLTestCase):
account11.lastcheck = 1 account11.lastcheck = 1
account11.interval = 2 account11.interval = 2
account11.password = "password" account11.password = "password"
account11.get_mail_list = lambda: [0, 1] account11.get_new_mail_list = lambda: [0, 1]
account11.get_mail_summary = mock_get_mail_summary account11.get_mail_summary = mock_get_mail_summary
result = self.comp.handler.feeder.feed(account11) result = self.comp.handler.feeder.feed(account11)
self.assertEquals(account11.error, None) self.assertEquals(account11.error, None)

View File

@@ -29,6 +29,7 @@ from email.Header import Header
from email.MIMEText import MIMEText from email.MIMEText import MIMEText
from email.MIMEMultipart import MIMEMultipart from email.MIMEMultipart import MIMEMultipart
import traceback import traceback
import types
import poplib import poplib
import imaplib import imaplib
@@ -238,6 +239,32 @@ class MailAccount(PresenceAccount):
get_presence_actions_fields = classmethod(_get_presence_actions_fields) get_presence_actions_fields = classmethod(_get_presence_actions_fields)
def get_decoded_header(self, header, charset_hint=None):
decoded_header = email.Header.decode_header(header)
decoded_header_str = u""
for i in range(len(decoded_header)):
try:
if decoded_header[i][1]:
charset_hint = decoded_header[i][1]
decoded_header_str += unicode(decoded_header[i][0].decode(\
decoded_header[i][1]))
else:
decoded_header_str += unicode(decoded_header[i][0].decode(\
MailAccount.default_encoding))
except Exception,e:
try:
decoded_header_str += unicode(decoded_header[i][0])
except Exception, e:
try:
decoded_header_str += unicode(decoded_header[i][0].decode(\
"iso-8859-1"))
except Exception, e:
type, value, stack = sys.exc_info()
print >>sys.stderr, \
"".join(traceback.format_exception
(type, value, stack, 5))
return (decoded_header_str, charset_hint)
def get_decoded_part(self, part, charset_hint): def get_decoded_part(self, part, charset_hint):
content_charset = part.get_content_charset() content_charset = part.get_content_charset()
result = u"" result = u""
@@ -265,64 +292,12 @@ class MailAccount(PresenceAccount):
return result return result
def format_message(self, email_msg, include_body = True): def format_message(self, email_msg, include_body=True):
from_decoded = email.Header.decode_header(email_msg["From"]) (email_from, charset_hint) = self.get_decoded_header(email_msg["From"])
charset_hint = None result = u"From : " + email_from + "\n"
email_from = u"" (email_subject, charset_hint) = self.get_decoded_header(email_msg["Subject"],
result = u"From : " charset_hint)
for i in range(len(from_decoded)): result += u"Subject : " + email_subject + "\n\n"
try:
if from_decoded[i][1]:
charset_hint = from_decoded[i][1]
email_from += unicode(from_decoded[i][0].decode(\
from_decoded[i][1]))
else:
email_from += unicode(from_decoded[i][0].decode(\
MailAccount.default_encoding))
except Exception,e:
try:
email_from += unicode(from_decoded[i][0])
except Exception, e:
try:
email_from += unicode(from_decoded[i][0].decode(\
"iso-8859-1"))
except Exception, e:
type, value, stack = sys.exc_info()
print >>sys.stderr, \
"".join(traceback.format_exception
(type, value, stack, 5))
result += email_from + u"\n"
subject_decoded = email.Header.decode_header(email_msg["Subject"])
result += u"Subject : "
for i in range(len(subject_decoded)):
try:
if subject_decoded[i][1]:
charset_hint = subject_decoded[i][1]
result += unicode(subject_decoded[i][0].decode(\
subject_decoded[i][1]))
else:
result += unicode(subject_decoded[i][0].decode(\
MailAccount.default_encoding))
except Exception,e:
try:
result += unicode(subject_decoded[i][0])
except Exception, e:
try:
result += unicode(subject_decoded[i][0].decode(\
"iso-8859-1"))
except Exception, e:
if charset_hint is not None:
try:
result += unicode(subject_decoded[i][0].decode(\
charset_hint))
except Exception, e:
type, value, stack = sys.exc_info()
print >>sys.stderr, \
"".join(traceback.format_exception
(type, value, stack, 5))
result += u"\n\n"
if include_body: if include_body:
action = { action = {
@@ -340,7 +315,7 @@ class MailAccount(PresenceAccount):
return self.format_message(email_msg, False) return self.format_message(email_msg, False)
def get_default_status_msg(self, lang_class): def get_default_status_msg(self, lang_class):
return self.get_type() + "://" + self.login + "@" + self.host + ":" + \ return self.get_type() + "://" + self.login + "@" + self.host + ":" + \
unicode(self.port) unicode(self.port)
def connect(self): def connect(self):
@@ -349,7 +324,10 @@ class MailAccount(PresenceAccount):
def disconnect(self): def disconnect(self):
raise NotImplementedError raise NotImplementedError
def get_mail_list(self): def get_mail_list_summary(self, start_index=0, end_index=20):
raise NotImplementedError
def get_new_mail_list(self):
raise NotImplementedError raise NotImplementedError
def get_mail(self, index): def get_mail(self, index):
@@ -394,15 +372,15 @@ class IMAPAccount(MailAccount):
get_default_port = classmethod(_get_default_port) get_default_port = classmethod(_get_default_port)
def _init(self, *args, **kw): def _init(self, *args, **kw):
MailAccount._init(self, *args, **kw) MailAccount._init(self, *args, **kw)
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 = {}
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): def _get_real_mailbox(self):
""" """
@@ -412,7 +390,7 @@ class IMAPAccount(MailAccount):
return self.mailbox.replace("/", self.delimiter) 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
def connect(self): def connect(self):
self.__logger.debug("Connecting to IMAP server " self.__logger.debug("Connecting to IMAP server "
@@ -427,36 +405,53 @@ class IMAPAccount(MailAccount):
self.connected = True self.connected = True
def disconnect(self): def disconnect(self):
self.__logger.debug("Disconnecting from IMAP server " self.__logger.debug("Disconnecting from IMAP server "
+ self.host) + self.host)
self.connection.logout() self.connection.logout()
self.connected = False self.connected = False
def get_mail_list(self): def get_mail_list_summary(self, start_index=1, end_index=20):
self.__logger.debug("Getting mail list") self.__logger.debug("Getting mail list summary")
typ, data = self.connection.select(self._get_real_mailbox()) typ, count = self.connection.select(self._get_real_mailbox(), True)
typ, data = self.connection.search(None, 'RECENT') result = []
if typ == 'OK': if typ == "OK":
return data[0].split(' ') typ, data = self.connection.fetch(str(start_index) + ":" +
return None str(end_index),
"RFC822.header")
if typ == 'OK':
index = start_index
for _email in data:
if isinstance(_email, types.TupleType) and len(_email) == 2:
subject_header = self.get_decoded_header(email.message_from_string(_email[1])["Subject"])[0]
result.append((str(index), subject_header))
index += 1
return result
def get_new_mail_list(self):
self.__logger.debug("Getting mail list")
typ, data = self.connection.select(self._get_real_mailbox(), True)
typ, data = self.connection.search(None, 'RECENT')
if typ == 'OK':
return data[0].split(' ')
return None
def get_mail(self, index): def get_mail(self, index):
self.__logger.debug("Getting mail " + str(index)) self.__logger.debug("Getting mail " + str(index))
typ, data = self.connection.select(self.mailbox, True) typ, data = self.connection.select(self._get_real_mailbox(), True)
typ, data = self.connection.fetch(index, '(RFC822)') typ, data = self.connection.fetch(index, '(RFC822)')
if typ == 'OK': if typ == 'OK':
return self.format_message(\ return self.format_message(\
email.message_from_string(data[0][1])) email.message_from_string(data[0][1]))
return u"Error while fetching mail " + str(index) return u"Error while fetching mail " + str(index)
def get_mail_summary(self, index): def get_mail_summary(self, index):
self.__logger.debug("Getting mail summary " + str(index)) self.__logger.debug("Getting mail summary " + str(index))
typ, data = self.connection.select(self.mailbox, True) typ, data = self.connection.select(self._get_real_mailbox(), True)
typ, data = self.connection.fetch(index, '(RFC822)') typ, data = self.connection.fetch(index, '(RFC822.header)')
if typ == 'OK': if typ == 'OK':
return self.format_message_summary(\ return self.format_message_summary(\
email.message_from_string(data[0][1])) email.message_from_string(data[0][1]))
return u"Error while fetching mail " + str(index) return u"Error while fetching mail " + str(index)
def get_next_mail_index(self, mail_list): def get_next_mail_index(self, mail_list):
if self.is_mail_list_valid(mail_list): if self.is_mail_list_valid(mail_list):
@@ -465,7 +460,7 @@ class IMAPAccount(MailAccount):
return None return None
def mark_all_as_read(self): def mark_all_as_read(self):
self.get_mail_list() self.get_new_mail_list()
type = property(get_type) type = property(get_type)
@@ -525,7 +520,8 @@ class IMAPAccount(MailAccount):
self.delimiter = match.group(2) self.delimiter = match.group(2)
else: else:
self.disconnect() self.disconnect()
raise Exception("Cannot find mailbox " + self.mailbox) raise Exception("Cannot find delimiter for mailbox "
+ self.mailbox)
else: else:
self.disconnect() self.disconnect()
raise Exception("Cannot find mailbox " + self.mailbox) raise Exception("Cannot find mailbox " + self.mailbox)
@@ -578,9 +574,24 @@ class POP3Account(MailAccount):
self.connection.quit() self.connection.quit()
self.connected = False self.connected = False
def get_mail_list(self): def get_mail_list_summary(self, start_index=0, end_index=20):
self.__logger.debug("Getting mail list") self.__logger.debug("Getting mail list")
count, size = self.connection.stat() count, size = self.connection.stat()
result = []
for index in xrange(1, count + 1):
(ret, data, octets) = self.connection.top(index, 0)
if ret[0:3] == '+OK':
subject_header = self.get_decoded_header(email.message_from_string('\n'.join(data))["Subject"])[0]
result.append((str(index), subject_header))
try:
self.connection.rset()
except:
pass
return result
def get_new_mail_list(self):
self.__logger.debug("Getting new mail list")
count, size = self.connection.stat()
self.nb_mail = count self.nb_mail = count
return [str(i) for i in range(1, count + 1)] return [str(i) for i in range(1, count + 1)]
@@ -621,7 +632,7 @@ class POP3Account(MailAccount):
return None return None
def mark_all_as_read(self): def mark_all_as_read(self):
self.get_mail_list() self.get_new_mail_list()
self.lastmail = self.nb_mail self.lastmail = self.nb_mail
@@ -719,16 +730,16 @@ class SMTPAccount(Account):
def create_email(self, from_email, to_email, subject, body, other_headers=None): def create_email(self, from_email, to_email, subject, body, other_headers=None):
"""Create new email""" """Create new email"""
email = MIMEText(body) _email = MIMEText(body)
if subject is None: if subject is None:
subject = "" subject = ""
email['Subject'] = Header(str(subject)) _email['Subject'] = Header(str(subject))
email['From'] = Header(str(from_email)) _email['From'] = Header(str(from_email))
email['To'] = Header(str(to_email)) _email['To'] = Header(str(to_email))
if other_headers is not None: if other_headers is not None:
for header_name in other_headers.keys(): for header_name in other_headers.keys():
email[header_name] = Header(other_headers[header_name]) _email[header_name] = Header(other_headers[header_name])
return email return _email
def __say_hello(self, connection): def __say_hello(self, connection):
if not (200 <= connection.ehlo()[0] <= 299): if not (200 <= connection.ehlo()[0] <= 299):
@@ -736,10 +747,10 @@ class SMTPAccount(Account):
if not (200 <= code <= 299): if not (200 <= code <= 299):
raise SMTPHeloError(code, resp) raise SMTPHeloError(code, resp)
def send_email(self, email): def send_email(self, _email):
"""Send email according to current account parameters""" """Send email according to current account parameters"""
self.__logger.debug("Sending email:\n" self.__logger.debug("Sending email:\n"
+ str(email)) + str(_email))
smtp_connection = smtplib.SMTP() smtp_connection = smtplib.SMTP()
if self.__logger.getEffectiveLevel() == logging.DEBUG: if self.__logger.getEffectiveLevel() == logging.DEBUG:
smtp_connection.set_debuglevel(1) smtp_connection.set_debuglevel(1)
@@ -768,6 +779,6 @@ class SMTPAccount(Account):
current_error = error current_error = error
if current_error is not None: if current_error is not None:
raise current_error raise current_error
smtp_connection.sendmail(str(email['From']), str(email['To']), smtp_connection.sendmail(str(_email['From']), str(_email['To']),
email.as_string()) _email.as_string())
smtp_connection.quit() smtp_connection.quit()

View File

@@ -54,70 +54,78 @@ class MailAccount_TestCase(PresenceAccount_TestCase):
test_get_decoded_part_not_encoded = \ test_get_decoded_part_not_encoded = \
make_test((False, False, False), \ make_test((False, False, False), \
lambda self, email: self.account.get_decoded_part(email, None), \ lambda self, email: \
self.account.get_decoded_part(email, None),
u"Not encoded single part") u"Not encoded single part")
test_get_decoded_part_encoded = \ test_get_decoded_part_encoded = \
make_test((True, False, False), \ make_test((True, False, False),
lambda self, email: self.account.get_decoded_part(email, None), \ lambda self, email: \
self.account.get_decoded_part(email, None),
u"Encoded single part with 'iso-8859-15' charset (éàê)") u"Encoded single part with 'iso-8859-15' charset (éàê)")
test_format_message_summary_not_encoded = \ test_format_message_summary_not_encoded = \
make_test((False, False, True), \ make_test((False, False, True),
lambda self, email: self.account.format_message_summary(email), \ lambda self, email: \
(u"From : not encoded from\nSubject : not encoded subject\n\n", \ self.account.format_message_summary(email),
(u"From : not encoded from\nSubject : not encoded subject\n\n",
u"not encoded from")) u"not encoded from"))
test_format_message_summary_encoded = \ test_format_message_summary_encoded = \
make_test((True, False, True), \ make_test((True, False, True),
lambda self, email: self.account.format_message_summary(email), \ lambda self, email: \
self.account.format_message_summary(email),
(u"From : encoded from (éàê)\nSubject : encoded subject " + \ (u"From : encoded from (éàê)\nSubject : encoded subject " + \
u"(éàê)\n\n", \ u"(éàê)\n\n",
u"encoded from (éàê)")) u"encoded from (éàê)"))
test_format_message_summary_partial_encoded = \ test_format_message_summary_partial_encoded = \
make_test((True, False, True), \ make_test((True, False, True),
lambda self, email: \ lambda self, email: \
email.replace_header("Subject", \ email.replace_header("Subject",
"\" " + str(email["Subject"]) \ "\" " + str(email["Subject"]) \
+ " \" not encoded part") or \ + " \" not encoded part") or \
email.replace_header("From", \ email.replace_header("From",
"\" " + str(email["From"]) \ "\" " + str(email["From"]) \
+ " \" not encoded part") or \ + " \" not encoded part") or \
self.account.format_message_summary(email), \ self.account.format_message_summary(email),
(u"From : \"encoded from (éàê)\" not encoded part\nSubject " + \ (u"From : \"encoded from (éàê)\" not encoded part\nSubject " + \
u": \"encoded subject (éàê)\" not encoded part\n\n", \ u": \"encoded subject (éàê)\" not encoded part\n\n",
u"\"encoded from (éàê)\" not encoded part")) u"\"encoded from (éàê)\" not encoded part"))
test_format_message_single_not_encoded = \ test_format_message_single_not_encoded = \
make_test((False, False, True), \ make_test((False, False, True),
lambda self, email: self.account.format_message(email), \ lambda self, email: \
self.account.format_message(email),
(u"From : not encoded from\nSubject : not encoded subject" + \ (u"From : not encoded from\nSubject : not encoded subject" + \
u"\n\nNot encoded single part\n", \ u"\n\nNot encoded single part\n",
u"not encoded from")) u"not encoded from"))
test_format_message_single_encoded = \ test_format_message_single_encoded = \
make_test((True, False, True), \ make_test((True, False, True),
lambda self, email: self.account.format_message(email), \ lambda self, email: \
self.account.format_message(email),
(u"From : encoded from (éàê)\nSubject : encoded subject " + \ (u"From : encoded from (éàê)\nSubject : encoded subject " + \
u"(éàê)\n\nEncoded single part with 'iso-8859-15' charset" + \ u"(éàê)\n\nEncoded single part with 'iso-8859-15' charset" + \
u" (éàê)\n", \ u" (éàê)\n",
u"encoded from (éàê)")) u"encoded from (éàê)"))
test_format_message_multi_not_encoded = \ test_format_message_multi_not_encoded = \
make_test((False, True, True), \ make_test((False, True, True),
lambda self, email: self.account.format_message(email), \ lambda self, email: \
self.account.format_message(email),
(u"From : not encoded from\nSubject : not encoded subject" + \ (u"From : not encoded from\nSubject : not encoded subject" + \
u"\n\nNot encoded multipart1\nNot encoded multipart2\n", \ u"\n\nNot encoded multipart1\nNot encoded multipart2\n",
u"not encoded from")) u"not encoded from"))
test_format_message_multi_encoded = \ test_format_message_multi_encoded = \
make_test((True, True, True), \ make_test((True, True, True),
lambda self, email: self.account.format_message(email), \ lambda self, email: \
self.account.format_message(email),
(u"From : encoded from (éàê)\nSubject : encoded subject (éà" + \ (u"From : encoded from (éàê)\nSubject : encoded subject (éà" + \
u"ê)\n\nutf-8 multipart1 with no charset (éàê)" + \ u"ê)\n\nutf-8 multipart1 with no charset (éàê)" + \
u"\nEncoded multipart2 with 'iso-8859-15' charset (éàê)\n" + \ u"\nEncoded multipart2 with 'iso-8859-15' charset (éàê)\n" + \
u"Encoded multipart3 with no charset (éàê)\n", \ u"Encoded multipart3 with no charset (éàê)\n",
u"encoded from (éàê)")) u"encoded from (éàê)"))
class POP3Account_TestCase(InheritableAccount_TestCase): class POP3Account_TestCase(InheritableAccount_TestCase):
@@ -161,72 +169,90 @@ class POP3Account_TestCase(InheritableAccount_TestCase):
"Sended queries does not match expected queries.") "Sended queries does not match expected queries.")
return inner return inner
test_connection = make_test() test_connection = make_test
test_get_mail_list = \ test_get_mail_list_summary = \
make_test(["+OK 2 20\r\n",
"+OK 10 octets\r\n" + \
"From: user@test.com\r\n" + \
"Subject: mail subject 1\r\n.\r\n",
"+OK 10 octets\r\n" + \
"From: user@test.com\r\n" + \
"Subject: mail subject 2\r\n.\r\n",
"+OK\r\n"],
["STAT\r\n",
"TOP 1 0\r\n",
"TOP 2 0\r\n",
"RSET\r\n"],
lambda self: \
self.assertEquals(self.pop3_account.get_mail_list_summary(),
[("1", "mail subject 1"),
("2", "mail subject 2")]))
test_get_new_mail_list = \
make_test(["+OK 2 20\r\n"], make_test(["+OK 2 20\r\n"],
["STAT\r\n"], ["STAT\r\n"],
lambda self: \ lambda self: \
self.assertEquals(self.pop3_account.get_mail_list(), self.assertEquals(self.pop3_account.get_new_mail_list(),
["1", "2"])) ["1", "2"]))
test_get_mail_summary = \ test_get_mail_summary = \
make_test(["+OK 10 octets\r\n" + make_test(["+OK 10 octets\r\n" + \
"From: user@test.com\r\n" + "From: user@test.com\r\n" + \
"Subject: subject test\r\n\r\n" + "Subject: subject test\r\n\r\n" + \
"mymessage\r\n.\r\n", "mymessage\r\n.\r\n",
"+OK\r\n"], "+OK\r\n"],
["RETR 1\r\n", ["RETR 1\r\n",
"RSET\r\n"], "RSET\r\n"],
lambda self: \ lambda self: \
self.assertEquals(self.pop3_account.get_mail_summary(1), self.assertEquals(self.pop3_account.get_mail_summary(1),
(u"From : user@test.com\n" + (u"From : user@test.com\n" + \
u"Subject : subject test\n\n", u"Subject : subject test\n\n",
u"user@test.com"))) u"user@test.com")))
test_get_mail = \ test_get_mail = \
make_test(["+OK 10 octets\r\n" + make_test(["+OK 10 octets\r\n" + \
"From: user@test.com\r\n" + "From: user@test.com\r\n" + \
"Subject: subject test\r\n\r\n" + "Subject: subject test\r\n\r\n" + \
"mymessage\r\n.\r\n", "mymessage\r\n.\r\n",
"+OK\r\n"], "+OK\r\n"],
["RETR 1\r\n", ["RETR 1\r\n",
"RSET\r\n"], \ "RSET\r\n"],
lambda self: \ lambda self: \
self.assertEquals(self.pop3_account.get_mail(1), \ self.assertEquals(self.pop3_account.get_mail(1),
(u"From : user@test.com\n" + \ (u"From : user@test.com\n" + \
u"Subject : subject test\n\n" + \ u"Subject : subject test\n\n" + \
u"mymessage\n", \ u"mymessage\n",
u"user@test.com"))) u"user@test.com")))
test_unsupported_reset_command_get_mail_summary = \ test_unsupported_reset_command_get_mail_summary = \
make_test(["+OK 10 octets\r\n" + \ make_test(["+OK 10 octets\r\n" + \
"From: user@test.com\r\n" + \ "From: user@test.com\r\n" + \
"Subject: subject test\r\n\r\n" + \ "Subject: subject test\r\n\r\n" + \
"mymessage\r\n.\r\n", "mymessage\r\n.\r\n",
"-ERR unknown command\r\n"], \ "-ERR unknown command\r\n"],
["RETR 1\r\n", ["RETR 1\r\n",
"RSET\r\n"], \ "RSET\r\n"],
lambda self: \ lambda self: \
self.assertEquals(self.pop3_account.get_mail_summary(1), \ self.assertEquals(self.pop3_account.get_mail_summary(1),
(u"From : user@test.com\n" + \ (u"From : user@test.com\n" + \
u"Subject : subject test\n\n", \ u"Subject : subject test\n\n",
u"user@test.com"))) u"user@test.com")))
test_unsupported_reset_command_get_mail = \ test_unsupported_reset_command_get_mail = \
make_test(["+OK 10 octets\r\n" + \ make_test(["+OK 10 octets\r\n" + \
"From: user@test.com\r\n" + \ "From: user@test.com\r\n" + \
"Subject: subject test\r\n\r\n" + \ "Subject: subject test\r\n\r\n" + \
"mymessage\r\n.\r\n", "mymessage\r\n.\r\n",
"-ERR unknown command\r\n"], \ "-ERR unknown command\r\n"],
["RETR 1\r\n", ["RETR 1\r\n",
"RSET\r\n"], \ "RSET\r\n"],
lambda self: \ lambda self: \
self.assertEquals(self.pop3_account.get_mail(1), \ self.assertEquals(self.pop3_account.get_mail(1),
(u"From : user@test.com\n" + \ (u"From : user@test.com\n" + \
u"Subject : subject test\n\n" + \ u"Subject : subject test\n\n" + \
u"mymessage\n", \ u"mymessage\n",
u"user@test.com"))) u"user@test.com")))
class IMAPAccount_TestCase(InheritableAccount_TestCase): class IMAPAccount_TestCase(InheritableAccount_TestCase):
def setUp(self): def setUp(self):
@@ -278,21 +304,43 @@ class IMAPAccount_TestCase(InheritableAccount_TestCase):
test_func = self.make_test() test_func = self.make_test()
test_func() test_func()
def test_get_mail_list(self): def test_get_mail_list_summary(self):
test_func = self.make_test([lambda data: "* 42 EXISTS\n* 1 RECENT\n* OK" +\ test_func = self.make_test(\
" [UNSEEN 9]\n* FLAGS (\Deleted \Seen\*)\n*" +\ [lambda data: "* 42 EXISTS\r\n* 1 RECENT\r\n* OK" +\
" OK [PERMANENTFLAGS (\Deleted \Seen\*)\n" + \ " [UNSEEN 9]\r\n* FLAGS (\Deleted \Seen\*)\r\n*" +\
data.split()[0] + \ " OK [PERMANENTFLAGS (\Deleted \Seen\*)\r\n" + \
" OK [READ-WRITE] SELECT completed\n", \ data.split()[0] + \
lambda data: "* SEARCH 9 10 \n" + \ " OK [READ-WRITE] SELECT completed\r\n",
data.split()[0] + " OK SEARCH completed\n"], \ lambda data: "* 1 FETCH ((RFC822.header) {38}\r\n" + \
["^[^ ]* SELECT INBOX", \ "Subject: mail subject 1\r\n\r\nbody text\r\n)\r\n" + \
"^[^ ]* SEARCH RECENT"], \ "* 2 FETCH ((RFC822.header) {38}\r\n" + \
lambda self: \ "Subject: mail subject 2\r\n\r\nbody text\r\n)\r\n" + \
self.assertEquals(self.imap_account.get_mail_list(), ['9', '10'])) data.split()[0] + " OK FETCH completed\r\n"],
["^[^ ]* EXAMINE INBOX",
"^[^ ]* FETCH 1:20 RFC822.header"],
lambda self: \
self.assertEquals(self.imap_account.get_mail_list_summary(),
[('1', 'mail subject 1'),
('2', 'mail subject 2')]))
test_func() test_func()
def test_get_mail_list_delimiter1(self): def test_get_new_mail_list(self):
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"],
["^[^ ]* EXAMINE INBOX",
"^[^ ]* SEARCH RECENT"],
lambda self: \
self.assertEquals(self.imap_account.get_new_mail_list(),
['9', '10']))
test_func()
def test_get_new_mail_list_delimiter1(self):
self.imap_account.mailbox = "INBOX/dir1/subdir2" self.imap_account.mailbox = "INBOX/dir1/subdir2"
self.imap_account.delimiter = "." self.imap_account.delimiter = "."
test_func = self.make_test( \ test_func = self.make_test( \
@@ -300,16 +348,17 @@ class IMAPAccount_TestCase(InheritableAccount_TestCase):
" [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] + \
" OK [READ-WRITE] SELECT completed\n", \ " OK [READ-WRITE] SELECT completed\n",
lambda data: "* SEARCH 9 10 \n" + \ lambda data: "* SEARCH 9 10 \n" + \
data.split()[0] + " OK SEARCH completed\n"], \ data.split()[0] + " OK SEARCH completed\n"],
["^[^ ]* SELECT \"?INBOX\.dir1\.subdir2\"?", ["^[^ ]* EXAMINE \"?INBOX\.dir1\.subdir2\"?",
"^[^ ]* SEARCH RECENT"], \ "^[^ ]* SEARCH RECENT"],
lambda self: \ lambda self: \
self.assertEquals(self.imap_account.get_mail_list(), ['9', '10'])) self.assertEquals(self.imap_account.get_new_mail_list(),
['9', '10']))
test_func() test_func()
def test_get_mail_list_delimiter2(self): def test_get_new_mail_list_delimiter2(self):
self.imap_account.mailbox = "INBOX/dir1/subdir2" self.imap_account.mailbox = "INBOX/dir1/subdir2"
self.imap_account.delimiter = "/" self.imap_account.delimiter = "/"
test_func = self.make_test( \ test_func = self.make_test( \
@@ -317,45 +366,90 @@ class IMAPAccount_TestCase(InheritableAccount_TestCase):
" [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] + \
" OK [READ-WRITE] SELECT completed\n", \ " OK [READ-WRITE] SELECT completed\n",
lambda data: "* SEARCH 9 10 \n" + \ lambda data: "* SEARCH 9 10 \n" + \
data.split()[0] + " OK SEARCH completed\n"], \ data.split()[0] + " OK SEARCH completed\n"],
["^[^ ]* SELECT \"?INBOX/dir1/subdir2\"?", ["^[^ ]* EXAMINE \"?INBOX/dir1/subdir2\"?",
"^[^ ]* SEARCH RECENT"], \ "^[^ ]* SEARCH RECENT"],
lambda self: \ lambda self: \
self.assertEquals(self.imap_account.get_mail_list(), ['9', '10'])) self.assertEquals(self.imap_account.get_new_mail_list(),
['9', '10']))
test_func() test_func()
def test_get_mail_summary(self): def test_get_mail_summary(self):
test_func = self.make_test([lambda data: "* 42 EXISTS\r\n* 1 RECENT\r\n* OK" +\ test_func = self.make_test(\
" [UNSEEN 9]\r\n* FLAGS (\Deleted \Seen\*)\r\n*" +\ [lambda data: "* 42 EXISTS\r\n* 1 RECENT\r\n* OK" +\
" OK [PERMANENTFLAGS (\Deleted \Seen\*)\r\n" + \ " [UNSEEN 9]\r\n* FLAGS (\Deleted \Seen\*)\r\n*" +\
data.split()[0] + \ " OK [PERMANENTFLAGS (\Deleted \Seen\*)\r\n" + \
" OK [READ-WRITE] SELECT completed\r\n", \ data.split()[0] + \
lambda data: "* 1 FETCH ((RFC822) {12}\r\nbody" + \ " OK [READ-WRITE] SELECT completed\r\n",
" text\r\n)\r\n" + \ lambda data: "* 1 FETCH ((RFC822) {12}\r\nbody" + \
data.split()[0] + " OK FETCH completed\r\n"], " text\r\n)\r\n" + \
["^[^ ]* EXAMINE INBOX", data.split()[0] + " OK FETCH completed\r\n"],
"^[^ ]* FETCH 1 \(RFC822\)"], ["^[^ ]* EXAMINE INBOX",
lambda self: self.assertEquals(self.imap_account.get_mail_summary(1), "^[^ ]* FETCH 1 \(RFC822.header\)"],
(u"From : None\nSubject : None\n\n", lambda self: \
u"None"))) self.assertEquals(self.imap_account.get_mail_summary(1),
(u"From : None\nSubject : None\n\n",
u"None")))
test_func()
def test_get_mail_summary_delimiter(self):
self.imap_account.mailbox = "INBOX/dir1/subdir2"
self.imap_account.delimiter = "."
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\.dir1\.subdir2\"?",
"^[^ ]* FETCH 1 \(RFC822.header\)"],
lambda self: \
self.assertEquals(self.imap_account.get_mail_summary(1),
(u"From : None\nSubject : None\n\n",
u"None")))
test_func() test_func()
def test_get_mail(self): def test_get_mail(self):
test_func = self.make_test([lambda data: "* 42 EXISTS\r\n* 1 RECENT\r\n* OK" +\ test_func = self.make_test(\
" [UNSEEN 9]\r\n* FLAGS (\Deleted \Seen\*)\r\n*" +\ [lambda data: "* 42 EXISTS\r\n* 1 RECENT\r\n* OK" + \
" OK [PERMANENTFLAGS (\Deleted \Seen\*)\r\n" + \ " [UNSEEN 9]\r\n* FLAGS (\Deleted \Seen\*)\r\n*" + \
data.split()[0] + \ " OK [PERMANENTFLAGS (\Deleted \Seen\*)\r\n" + \
" OK [READ-WRITE] SELECT completed\r\n", \ data.split()[0] + \
lambda data: "* 1 FETCH ((RFC822) {11}\r\nbody" + \ " OK [READ-WRITE] SELECT completed\r\n",
" text\r\n)\r\n" + \ lambda data: "* 1 FETCH ((RFC822) {11}\r\nbody" + \
data.split()[0] + " OK FETCH completed\r\n"], \ " text\r\n)\r\n" + \
["^[^ ]* EXAMINE INBOX", \ data.split()[0] + " OK FETCH completed\r\n"],
"^[^ ]* FETCH 1 \(RFC822\)",], \ ["^[^ ]* EXAMINE INBOX",
lambda self: self.assertEquals(self.imap_account.get_mail(1), \ "^[^ ]* FETCH 1 \(RFC822\)"],
(u"From : None\nSubject : None\n\nbody text\r\n\n", \ lambda self: \
u"None"))) self.assertEquals(self.imap_account.get_mail(1),
(u"From : None\nSubject : None\n\nbody text\r\n\n",
u"None")))
test_func()
def test_get_mail_delimiter(self):
self.imap_account.mailbox = "INBOX/dir1/subdir2"
self.imap_account.delimiter = "."
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) {11}\r\nbody" + \
" text\r\n)\r\n" + \
data.split()[0] + " OK FETCH completed\r\n"],
["^[^ ]* EXAMINE \"?INBOX\.dir1\.subdir2\"?",
"^[^ ]* FETCH 1 \(RFC822\)"],
lambda self: \
self.assertEquals(self.imap_account.get_mail(1),
(u"From : None\nSubject : None\n\nbody text\r\n\n",
u"None")))
test_func() test_func()
def test_build_folder_cache(self): def test_build_folder_cache(self):
@@ -576,7 +670,7 @@ class SMTPAccount_TestCase(Account_TestCase):
None, None, None, None, None, None, None, None,
None, None, None, None, None, None, None, None,
"250 OK\r\n"], "250 OK\r\n"],
["ehlo \[127.0.0.1\]\r\n", ["ehlo \[127.0...1\]\r\n",
"mail FROM:<" + str(email['From']) + ">.*", "mail FROM:<" + str(email['From']) + ">.*",
"rcpt TO:<" + str(email['To']) + ">\r\n", "rcpt TO:<" + str(email['To']) + ">\r\n",
"data\r\n"] + "data\r\n"] +
@@ -609,8 +703,8 @@ class SMTPAccount_TestCase(Account_TestCase):
None, None, None, None, None, None, None, None,
None, None, None, None, None, None, None, None,
"250 OK\r\n"], "250 OK\r\n"],
["ehlo \[127.0.0.1\]\r\n", ["ehlo \[127.0...1\]\r\n",
"helo \[127.0.0.1\]\r\n", "helo \[127.0...1\]\r\n",
"mail FROM:<" + str(email['From']) + ">.*", "mail FROM:<" + str(email['From']) + ">.*",
"rcpt TO:<" + str(email['To']) + ">\r\n", "rcpt TO:<" + str(email['To']) + ">\r\n",
"data\r\n"] + "data\r\n"] +
@@ -647,7 +741,7 @@ class SMTPAccount_TestCase(Account_TestCase):
None, None, None, None, None, None, None, None,
None, None, None, None, None, None, None, None,
"250 OK\r\n"], "250 OK\r\n"],
["ehlo \[127.0.0.1\]\r\n", ["ehlo \[127.0...1\]\r\n",
"AUTH CRAM-MD5\r\n", "AUTH CRAM-MD5\r\n",
".*\r\n", ".*\r\n",
"mail FROM:<" + str(email['From']) + ">.*", "mail FROM:<" + str(email['From']) + ">.*",
@@ -688,7 +782,7 @@ class SMTPAccount_TestCase(Account_TestCase):
None, None, None, None, None, None, None, None,
None, None, None, None, None, None, None, None,
"250 OK\r\n"], "250 OK\r\n"],
["ehlo \[127.0.0.1\]\r\n", ["ehlo \[127.0...1\]\r\n",
"AUTH CRAM-MD5\r\n", "AUTH CRAM-MD5\r\n",
".*\r\n", ".*\r\n",
"AUTH LOGIN .*\r\n", "AUTH LOGIN .*\r\n",