use special flags (keywords) instead of FLAGGED for mail states

This commit is contained in:
Mathieu Agopian
2013-03-20 13:22:33 +01:00
parent 4031fa6c9b
commit f00da6493b
4 changed files with 46 additions and 11 deletions

View File

@@ -147,6 +147,12 @@ If each provided rule (either as a class parameter or using the register)
matches the mail's subject, from, to, cc and body, the callback will be matches the mail's subject, from, to, cc and body, the callback will be
triggered. triggered.
Mails are flagged according to their state, in the ``process_messages`` method:
* ``UNPROCESSED``: MailBot hasn't started looking at this mail
* ``PROCESSING``: MailBot is checking callbacks, and triggering them if needed
* ``PROCESSED``: MailBot is done with this mail, and won't process it anymore
Specifying rules Specifying rules
---------------- ----------------

View File

@@ -1,7 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from email import message_from_string from email import message_from_string
from imapclient import FLAGGED
from os.path import dirname, join from os.path import dirname, join
from .. import register, MailBot, Callback from .. import register, MailBot, Callback
@@ -62,19 +61,35 @@ class MailReceivedTest(MailBotTestCase):
{1: {'SEQ': 1, 'RFC822': '\r\n'}, {1: {'SEQ': 1, 'RFC822': '\r\n'},
2: {'FLAGS': ('\\Seen',), 'SEQ': 2, 'RFC822': '\r\n'}}) 2: {'FLAGS': ('\\Seen',), 'SEQ': 2, 'RFC822': '\r\n'}})
def test_mark_processing(self):
self.mb.client.append(self.home_folder,
message_from_string('').as_string())
ids = self.mb.client.search(['NOT KEYWORD PROCESSING'])
self.assertEqual(ids, [1])
self.mb.mark_processing(1)
self.assertEquals(self.mb.client.get_flags([1]), {1: ('PROCESSING',)})
ids = self.mb.client.search(['KEYWORD PROCESSING'])
self.assertEqual(ids, [1])
ids = self.mb.client.search(['NOT KEYWORD PROCESSING'])
self.assertEqual(ids, [])
def test_mark_processed(self): def test_mark_processed(self):
self.mb.client.append(self.home_folder, self.mb.client.append(self.home_folder,
message_from_string('').as_string()) message_from_string('').as_string())
ids = self.mb.client.search(['UNDELETED']) ids = self.mb.client.search(['NOT KEYWORD PROCESSED'])
self.assertEqual(ids, [1]) self.assertEqual(ids, [1])
self.mb.mark_processing(1)
self.mb.mark_processed(1) self.mb.mark_processed(1)
self.assertEquals(self.mb.client.get_flags([1]), {1: (FLAGGED,)}) self.assertEquals(self.mb.client.get_flags([1]), {1: ('PROCESSED',)})
ids = self.mb.client.search(['FLAGGED']) ids = self.mb.client.search(['KEYWORD PROCESSED'])
self.assertEqual(ids, [1]) self.assertEqual(ids, [1])
ids = self.mb.client.search(['UNFLAGGED']) ids = self.mb.client.search(['NOT KEYWORD PROCESSED'])
self.assertEqual(ids, []) self.assertEqual(ids, [])
def test_process_messages(self): def test_process_messages(self):

View File

@@ -2,7 +2,7 @@
from email import message_from_string from email import message_from_string
from imapclient import IMAPClient, FLAGGED from imapclient import IMAPClient
class MailBot(object): class MailBot(object):
@@ -25,7 +25,8 @@ class MailBot(object):
def get_message_ids(self): def get_message_ids(self):
"""Return the list of IDs of messages to process.""" """Return the list of IDs of messages to process."""
return self.client.search(['UNFLAGGED']) return self.client.search(['NOT KEYWORD PROCESSED',
'NOT KEYWORD PROCESSING'])
def get_messages(self): def get_messages(self):
"""Return the list of messages to process.""" """Return the list of messages to process."""
@@ -44,11 +45,17 @@ class MailBot(object):
messages = self.get_messages() messages = self.get_messages()
for uid, msg in messages.items(): for uid, msg in messages.items():
self.mark_processing(uid)
message = message_from_string(msg['RFC822']) message = message_from_string(msg['RFC822'])
for callback_class, rules in CALLBACKS_MAP.items(): for callback_class, rules in CALLBACKS_MAP.items():
self.process_message(message, callback_class, rules) self.process_message(message, callback_class, rules)
self.mark_processed(uid) self.mark_processed(uid)
def mark_processing(self, uid):
"""Mark the message corresponding to uid as processed."""
self.client.add_flags([uid], ['PROCESSING'])
def mark_processed(self, uid): def mark_processed(self, uid):
"""Mark the message corresponding to uid as processed.""" """Mark the message corresponding to uid as processed."""
self.client.add_flags([uid], [FLAGGED]) self.client.remove_flags([uid], ['PROCESSING'])
self.client.add_flags([uid], ['PROCESSED'])

View File

@@ -1,6 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from imapclient import FLAGGED
from mock import patch, sentinel, Mock, DEFAULT, call from mock import patch, sentinel, Mock, DEFAULT, call
from . import MailBotTestCase from . import MailBotTestCase
@@ -42,7 +41,8 @@ class MailBotTest(MailBotClientTest):
res = self.bot.get_message_ids() res = self.bot.get_message_ids()
self.bot.client.search.assert_called_once_with(['UNFLAGGED']) self.bot.client.search.assert_called_once_with(
['NOT KEYWORD PROCESSED', 'NOT KEYWORD PROCESSING'])
self.assertEqual(res, sentinel.id_list) self.assertEqual(res, sentinel.id_list)
def test_get_messages(self): def test_get_messages(self):
@@ -104,7 +104,14 @@ class MailBotTest(MailBotClientTest):
call(sentinel.mail2, sentinel.callback2, sentinel.rules2)], call(sentinel.mail2, sentinel.callback2, sentinel.rules2)],
any_order=True) any_order=True)
def test_mark_processing(self):
self.bot.mark_processing(sentinel.id)
self.bot.client.add_flags.assert_called_once_with([sentinel.id],
['PROCESSING'])
def test_mark_processed(self): def test_mark_processed(self):
self.bot.mark_processed(sentinel.id) self.bot.mark_processed(sentinel.id)
self.bot.client.remove_flags.assert_called_once_with([sentinel.id],
['PROCESSING'])
self.bot.client.add_flags.assert_called_once_with([sentinel.id], self.bot.client.add_flags.assert_called_once_with([sentinel.id],
[FLAGGED]) ['PROCESSED'])