diff --git a/product/CMFActivity/Activity/SQLDict.py b/product/CMFActivity/Activity/SQLDict.py
index 3eb066c61e2756f320747ad02a01ef92e56f9a2e..47aaefc45450a272894ba56c1cfce5b550bc34fd 100644
--- a/product/CMFActivity/Activity/SQLDict.py
+++ b/product/CMFActivity/Activity/SQLDict.py
@@ -120,12 +120,12 @@ class SQLDict(RAMDict):
 
   def isMessageRegistered(self, activity_buffer, activity_tool, m):
     uid_set = activity_buffer.getUidSet(self)
-    return (tuple(m.object_path), m.method_id) in uid_set
+    return (tuple(m.object_path), m.method_id, m.activity_kw.get('tag')) in uid_set
 
   def registerMessage(self, activity_buffer, activity_tool, m):
     m.is_registered = 1
     uid_set = activity_buffer.getUidSet(self)
-    uid_set.add((tuple(m.object_path), m.method_id))
+    uid_set.add((tuple(m.object_path), m.method_id, m.activity_kw.get('tag')))
     message_list = activity_buffer.getMessageList(self)
     message_list.append(m)
 
@@ -133,7 +133,7 @@ class SQLDict(RAMDict):
     m.is_registered = 0 # This prevents from inserting deleted messages into the queue
     class_name = self.__class__.__name__
     uid_set = activity_buffer.getUidSet(self)
-    uid_set.discard((tuple(m.object_path), m.method_id))
+    uid_set.discard((tuple(m.object_path), m.method_id, m.activity_kw.get('tag')))
 
   def getRegisteredMessageList(self, activity_buffer, activity_tool):
     message_list = activity_buffer.getMessageList(self)
diff --git a/product/CMFActivity/skins/activity/SQLDict_readMessageList.zsql b/product/CMFActivity/skins/activity/SQLDict_readMessageList.zsql
index f6333e86efe3c662a40fcae1bfe1a7ebb7222816..0235caff96462ce922f9b03e0d3ead1b8314c06a 100644
--- a/product/CMFActivity/skins/activity/SQLDict_readMessageList.zsql
+++ b/product/CMFActivity/skins/activity/SQLDict_readMessageList.zsql
@@ -35,6 +35,6 @@ WHERE
 <dtml-if path>AND path = <dtml-sqlvar path type="string"> </dtml-if>
 <dtml-if method_id> AND method_id = <dtml-sqlvar method_id type="string"> </dtml-if>
 GROUP BY
-     path, method_id, processing_node, processing
+     path, method_id, tag, processing_node, processing
 ORDER BY
      priority, date
diff --git a/product/CMFActivity/tests/testCMFActivity.py b/product/CMFActivity/tests/testCMFActivity.py
index 00f351f1303c81a78aca4e464ed8c16a5e19d25b..5235724e850350b4f31994c26efc1c447aff944f 100644
--- a/product/CMFActivity/tests/testCMFActivity.py
+++ b/product/CMFActivity/tests/testCMFActivity.py
@@ -784,6 +784,58 @@ class TestCMFActivity(ERP5TypeTestCase):
       DB.query = DB.original_query
       del DB.original_query
 
+  def checkIsMessageRegisteredMethod(self, activity):
+    activity_tool = self.getPortal().portal_activities
+    object_a = self.getOrganisationModule()
+    if not object_a.hasContent(self.company_id):
+      object_a.newContent(id=self.company_id)
+    object_b = object_a._getOb(self.company_id)
+    activity_tool.manageClearActivities(keep=0)
+    get_transaction().commit()
+    # First case: creating the same activity twice must only register one.
+    self.assertEquals(len(activity_tool.getMessageList()), 0) # Sanity check
+    object_a.activate(activity=activity).getId()
+    object_a.activate(activity=activity).getId()
+    get_transaction().commit()
+    self.assertEquals(len(activity_tool.getMessageList()), 1)
+    activity_tool.manageClearActivities(keep=0)
+    get_transaction().commit()
+    # Second case: creating activity with same tag must only register one.
+    # This behaviour is actually the same as the no-tag behaviour.
+    self.assertEquals(len(activity_tool.getMessageList()), 0) # Sanity check
+    object_a.activate(activity=activity, tag='foo').getId()
+    object_a.activate(activity=activity, tag='foo').getId()
+    get_transaction().commit()
+    self.assertEquals(len(activity_tool.getMessageList()), 1)
+    activity_tool.manageClearActivities(keep=0)
+    get_transaction().commit()
+    # Third case: creating activities with different tags must register both.
+    self.assertEquals(len(activity_tool.getMessageList()), 0) # Sanity check
+    object_a.activate(activity=activity, tag='foo').getId()
+    object_a.activate(activity=activity, tag='bar').getId()
+    get_transaction().commit()
+    self.assertEquals(len(activity_tool.getMessageList()), 2)
+    activity_tool.manageClearActivities(keep=0)
+    get_transaction().commit()
+    # Fourth case: creating activities on different objects must register
+    # both.
+    self.assertEquals(len(activity_tool.getMessageList()), 0) # Sanity check
+    object_a.activate(activity=activity).getId()
+    object_b.activate(activity=activity).getId()
+    get_transaction().commit()
+    self.assertEquals(len(activity_tool.getMessageList()), 2)
+    activity_tool.manageClearActivities(keep=0)
+    get_transaction().commit()
+    # Fifth case: creating activities with different method must register
+    # both.
+    self.assertEquals(len(activity_tool.getMessageList()), 0) # Sanity check
+    object_a.activate(activity=activity).getId()
+    object_a.activate(activity=activity).getTitle()
+    get_transaction().commit()
+    self.assertEquals(len(activity_tool.getMessageList()), 2)
+    activity_tool.manageClearActivities(keep=0)
+    get_transaction().commit()
+
   def test_01_DeferedSetTitleSQLDict(self, quiet=0, run=run_all_test):
     # Test if we can add a complete sales order
     if not run: return
@@ -1688,6 +1740,17 @@ class TestCMFActivity(ERP5TypeTestCase):
     get_transaction().commit()
     self.assertEqual(len(activity_tool.getMessageList()), 0)
 
+  def test_78_IsMessageRegisteredSQLDict(self, quiet=0, run=run_all_test):
+    """
+      This test tests behaviour of IsMessageRegistered method.
+    """
+    if not run: return
+    if not quiet:
+      message = '\nTest IsMessageRegistered behaviour with SQLDict'
+      ZopeTestCase._print(message)
+      LOG('Testing... ',0,message)
+    self.checkIsMessageRegisteredMethod('SQLDict')
+
 if __name__ == '__main__':
     framework()
 else: