diff --git a/src/chat_control.py b/src/chat_control.py
index bd3056ec5d13acf0cb80a009d573c8521591a71c..391396693f2ed90bec4653058a343dde7ad8db70 100644
--- a/src/chat_control.py
+++ b/src/chat_control.py
@@ -54,6 +54,7 @@ from common.pep import MOODS, ACTIVITIES
 from common.xmpp.protocol import NS_XHTML, NS_XHTML_IM, NS_FILE, NS_MUC
 from common.xmpp.protocol import NS_RECEIPTS, NS_ESESSION
 from common.xmpp.protocol import NS_JINGLE_RTP_AUDIO, NS_JINGLE_RTP_VIDEO, NS_JINGLE_ICE_UDP
+from common.connection_handlers_events import MessageOutgoingEvent
 
 from command_system.implementation.middleware import ChatCommandProcessor
 from command_system.implementation.middleware import CommandTools
@@ -517,6 +518,7 @@ class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools):
         menu.show_all()
 
     def shutdown(self):
+        super(ChatControlBase, self).shutdown()
         # PluginSystem: removing GUI extension points connected with ChatControlBase
         # instance object
         gajim.plugin_manager.remove_gui_extension_point('chat_control_base', self)
@@ -848,8 +850,8 @@ class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools):
         return label
 
     def send_message(self, message, keyID='', type_='chat', chatstate=None,
-                    msg_id=None, composing_xep=None, resource=None, xhtml=None,
-                    callback=None, callback_args=[], process_commands=True):
+    msg_id=None, composing_xep=None, resource=None, xhtml=None, callback=None,
+    callback_args=[], process_commands=True):
         """
         Send the given message to the active tab. Doesn't return None if error
         """
@@ -860,11 +862,12 @@ class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools):
             return
 
         label = self.get_seclabel()
-        MessageControl.send_message(self, message, keyID, type_=type_,
-                chatstate=chatstate, msg_id=msg_id, composing_xep=composing_xep,
-                resource=resource, user_nick=self.user_nick, xhtml=xhtml,
-                label=label,
-                callback=callback, callback_args=callback_args)
+
+        gajim.nec.push_outgoing_event(MessageOutgoingEvent(None,
+            account=self.account, message=message, keyID=keyID, type_=type_,
+            chatstate=chatstate, msg_id=msg_id, composing_xep=composing_xep,
+            resource=resource, user_nick=self.user_nick, xhtml=xhtml,
+            label=label, callback=callback, callback_args= callback_args))
 
         # Record the history of sent messages
         self.save_message(message, 'sent')
@@ -2209,6 +2212,7 @@ class ChatControl(ChatControlBase):
         """
         Send a message to contact
         """
+        message = helpers.remove_invalid_xml_chars(message)
         if message in ('', None, '\n'):
             return None
 
@@ -2624,12 +2628,14 @@ class ChatControl(ChatControlBase):
         # if we're inactive prevent composing (JEP violation)
         if contact.our_chatstate == 'inactive' and state == 'composing':
             # go active before
-            MessageControl.send_message(self, None, chatstate='active')
+            gajim.nec.push_outgoing_event(MessageOutgoingEvent(None,
+                account=self.account, chatstate='active'))
             contact.our_chatstate = 'active'
             self.reset_kbd_mouse_timeout_vars()
 
-        MessageControl.send_message(self, "", chatstate = state,
-                msg_id = contact.msg_id, composing_xep = contact.composing_xep)
+        gajim.nec.push_outgoing_event(MessageOutgoingEvent(None,
+            account=self.account, chatstate=state, msg_id=contact.msg_id,
+            composing_xep=contact.composing_xep))
 
         contact.our_chatstate = state
         if contact.our_chatstate == 'active':
diff --git a/src/common/connection.py b/src/common/connection.py
index 9ec3bea1e7721087a910ec76b8569af2c3f67b7a..18824b3aa2a5863fe30350ba8e904c12a08279d3 100644
--- a/src/common/connection.py
+++ b/src/common/connection.py
@@ -717,6 +717,8 @@ class Connection(CommonConnection, ConnectionHandlers):
             self._nec_agent_info_error_received)
         gajim.ged.register_event_handler('agent-info-received', ged.CORE,
             self._nec_agent_info_received)
+        gajim.ged.register_event_handler('message-outgoing', ged.OUT_CORE,
+            self._nec_message_outgoing)
     # END __init__
 
     def cleanup(self):
@@ -727,6 +729,8 @@ class Connection(CommonConnection, ConnectionHandlers):
             self._nec_agent_info_error_received)
         gajim.ged.remove_event_handler('agent-info-received', ged.CORE,
             self._nec_agent_info_received)
+        gajim.ged.remove_event_handler('message-outgoing', ged.OUT_CORE,
+            self._nec_message_outgoing)
 
     def get_config_values_or_default(self):
         if gajim.config.get_per('accounts', self.name, 'keep_alives_enabled'):
@@ -1764,6 +1768,30 @@ class Connection(CommonConnection, ConnectionHandlers):
             session=session, forward_from=forward_from, form_node=form_node,
             original_message=original_message, delayed=delayed, callback=cb)
 
+    def _nec_message_outgoing(self, obj):
+        if obj.account != self.name:
+            return
+
+        def cb(jid, msg, keyID, forward_from, session, original_message,
+        subject, type_, msg_iq):
+            msg_id = self.connection.send(msg_iq, now=obj.now)
+            jid = helpers.parse_jid(obj.jid)
+            gajim.nec.push_incoming_event(MessageSentEvent(None, conn=self,
+                jid=jid, message=msg, keyID=keyID, chatstate=obj.chatstate))
+            if obj.callback:
+                obj.callback(msg_id, *obj.callback_args)
+
+            self.log_message(jid, msg, forward_from, session, original_message,
+                    subject, type_)
+
+        self._prepare_message(obj.jid, obj.message, obj.keyID, type_=obj.type_,
+            subject=obj.subject, chatstate=obj.chatstate, msg_id=obj.msg_id,
+            composing_xep=obj.composing_xep, resource=obj.resource,
+            user_nick=obj.user_nick, xhtml=obj.xhtml, label=obj.label,
+            session=obj.session, forward_from=obj.forward_from,
+            form_node=obj.form_node, original_message=obj.original_message,
+            delayed=obj.delayed, callback=cb)
+
     def send_contacts(self, contacts, jid):
         """
         Send contacts with RosterX (Xep-0144)
diff --git a/src/common/connection_handlers_events.py b/src/common/connection_handlers_events.py
index 976bc0f13270d3238f5fcfa39293b440e5dd4b43..df850a28440b47bd41de7cf9575b30f77f6c50a7 100644
--- a/src/common/connection_handlers_events.py
+++ b/src/common/connection_handlers_events.py
@@ -2042,3 +2042,31 @@ class NotificationEvent(nec.NetworkIncomingEvent):
         elif self.notif_type == 'pres':
             self.handle_incoming_pres_event(self.base_event)
         return True
+
+class MessageOutgoingEvent(nec.NetworkIncomingEvent):
+    name = 'message-outgoing'
+    base_network_events = []
+
+    def init(self):
+        self.message = ''
+        self.keyID = None
+        self.type_ = 'chat'
+        self.subject = ''
+        self.chatstate = None
+        self.msg_id = None
+        self.composing_xep = None
+        self.resource = None
+        self.user_nick = None
+        self.xhtml = None
+        self.label = None
+        self.session = None
+        self.forward_from = None
+        self.form_node = None
+        self.original_message = ''
+        self.delayed = None
+        self.callback = None
+        self.callback_args = []
+        self.now = False
+
+    def generate(self):
+        return True
\ No newline at end of file
diff --git a/src/common/ged.py b/src/common/ged.py
index 81af8d9955c1d019642c21e6ae37df607e8293d2..e4035fefb16878a0e23010119fe20464aa96bcc9 100644
--- a/src/common/ged.py
+++ b/src/common/ged.py
@@ -21,6 +21,7 @@ Global Events Dispatcher module.
 :author: Mateusz Biliński <mateusz@bilinski.it>
 :since: 8th August 2008
 :copyright: Copyright (2008) Mateusz Biliński <mateusz@bilinski.it>
+:copyright: Copyright (2011) Yann Leboulanger <asterix@lagaule.org>
 :license: GPL
 '''
 
@@ -39,6 +40,18 @@ GUI2 = 90
 POSTGUI2 = 100
 POSTGUI = 110
 
+OUT_PREGUI = 10
+OUT_PREGUI1 = 20
+OUT_GUI1 = 30
+OUT_POSTGUI1 = 40
+OUT_PREGUI2 = 50
+OUT_GUI2 = 60
+OUT_POSTGUI2 = 70
+OUT_POSTGUI = 80
+OUT_PRECORE = 90
+OUT_CORE = 100
+OUT_POSTCORE = 110
+
 class GlobalEventsDispatcher(object):
 
     def __init__(self):
diff --git a/src/common/nec.py b/src/common/nec.py
index dcb03ad1e5454860343a45a6d6eb7a2a19a06986..229771ad5ad1ac90627765de3aecdd8deebff091 100644
--- a/src/common/nec.py
+++ b/src/common/nec.py
@@ -21,6 +21,7 @@ Network Events Controller.
 :author: Mateusz Biliński <mateusz@bilinski.it>
 :since: 10th August 2008
 :copyright: Copyright (2008) Mateusz Biliński <mateusz@bilinski.it>
+:copyright: Copyright (2011) Yann Leboulanger <asterix@lagaule.org>
 :license: GPL
 '''
 
@@ -38,23 +39,38 @@ class NetworkEventsController(object):
         Values: list of class objects that are subclasses
         of `NetworkIncomingEvent`
         '''
+        self.outgoing_events_generators = {}
+        '''
+        Keys: names of events
+        Values: list of class objects that are subclasses
+        of `NetworkOutgoingEvent`
+        '''
 
     def register_incoming_event(self, event_class):
         for base_event_name in event_class.base_network_events:
-            event_list = self.incoming_events_generators.setdefault(base_event_name, [])
+            event_list = self.incoming_events_generators.setdefault(
+                base_event_name, [])
             if not event_class in event_list:
                 event_list.append(event_class)
 
     def unregister_incoming_event(self, event_class):
         for base_event_name in event_class.base_network_events:
             if base_event_name in self.incoming_events_generators:
-                self.incoming_events_generators[base_event_name].remove(event_class)
+                self.incoming_events_generators[base_event_name].remove(
+                    event_class)
 
     def register_outgoing_event(self, event_class):
-        pass
+        for base_event_name in event_class.base_network_events:
+            event_list = self.outgoing_events_generators.setdefault(
+                base_event_name, [])
+            if not event_class in event_list:
+                event_list.append(event_class)
 
     def unregister_outgoing_event(self, event_class):
-        pass
+        for base_event_name in event_class.base_network_events:
+            if base_event_name in self.outgoing_events_generators:
+                self.outgoing_events_generators[base_event_name].remove(
+                    event_class)
 
     def push_incoming_event(self, event_object):
         if event_object.generate():
@@ -62,7 +78,9 @@ class NetworkEventsController(object):
                 self._generate_events_based_on_incoming_event(event_object)
 
     def push_outgoing_event(self, event_object):
-        pass
+        if event_object.generate():
+            if not gajim.ged.raise_event(event_object.name, event_object):
+                self._generate_events_based_on_outgoing_event(event_object)
 
     def _generate_events_based_on_incoming_event(self, event_object):
         '''
@@ -75,11 +93,36 @@ class NetworkEventsController(object):
         '''
         base_event_name = event_object.name
         if base_event_name in self.incoming_events_generators:
-            for new_event_class in self.incoming_events_generators[base_event_name]:
-                new_event_object = new_event_class(None, base_event=event_object)
+            for new_event_class in self.incoming_events_generators[
+            base_event_name]:
+                new_event_object = new_event_class(None,
+                    base_event=event_object)
                 if new_event_object.generate():
-                    if not gajim.ged.raise_event(new_event_object.name, new_event_object):
-                        self._generate_events_based_on_incoming_event(new_event_object)
+                    if not gajim.ged.raise_event(new_event_object.name,
+                    new_event_object):
+                        self._generate_events_based_on_incoming_event(
+                            new_event_object)
+
+    def _generate_events_based_on_outgoing_event(self, event_object):
+        '''
+        :return: True if even_object should be dispatched through Global
+        Events Dispatcher, False otherwise. This can be used to replace
+        base events with those that more data computed (easier to use
+        by handlers).
+        :note: replacing mechanism is not implemented currently, but will be
+        based on attribute in new network events object.
+        '''
+        base_event_name = event_object.name
+        if base_event_name in self.outgoing_events_generators:
+            for new_event_class in self.outgoing_events_generators[
+            base_event_name]:
+                new_event_object = new_event_class(None,
+                    base_event=event_object)
+                if new_event_object.generate():
+                    if not gajim.ged.raise_event(new_event_object.name,
+                    new_event_object):
+                        self._generate_events_based_on_outgoing_event(
+                            new_event_object)
 
 class NetworkEvent(object):
     name = ''
@@ -88,10 +131,10 @@ class NetworkEvent(object):
         if new_name:
             self.name = new_name
 
-        self._set_kwargs_as_attributes(**kwargs)
-
         self.init()
 
+        self._set_kwargs_as_attributes(**kwargs)
+
     def init(self):
         pass
 
@@ -130,5 +173,7 @@ class NetworkIncomingEvent(NetworkEvent):
 
 
 class NetworkOutgoingEvent(NetworkEvent):
-        pass
-
+    base_network_events = []
+    '''
+    Names of base network events that new event is going to be generated on.
+    '''
\ No newline at end of file
diff --git a/src/message_control.py b/src/message_control.py
index 322de94b3e32fc4ab4e4d95367f55ebab6b2e9d4..14efb42dafdf8b1420265f176d3cbadcdf0fd231 100644
--- a/src/message_control.py
+++ b/src/message_control.py
@@ -30,6 +30,7 @@ import gtkgui_helpers
 
 from common import gajim
 from common import helpers
+from common import ged
 from common.stanza_session import EncryptedStanzaSession, ArchivingStanzaSession
 
 # Derived types MUST register their type IDs here if custom behavor is required
@@ -64,6 +65,9 @@ class MessageControl(object):
         self.xml = gtkgui_helpers.get_gtk_builder('%s.ui' % widget_name)
         self.widget = self.xml.get_object('%s_hbox' % widget_name)
 
+        gajim.ged.register_event_handler('message-outgoing', ged.OUT_GUI1,
+            self._nec_message_outgoing)
+
     def get_full_jid(self):
         fjid = self.contact.jid
         if self.resource:
@@ -110,7 +114,8 @@ class MessageControl(object):
         """
         Derived classes MUST implement this
         """
-        pass
+        gajim.ged.remove_event_handler('message-outgoing', ged.OUT_GUI1,
+            self._nec_message_outgoing)
 
     def repaint_themed_widgets(self):
         """
@@ -214,40 +219,35 @@ class MessageControl(object):
         if crypto_changed or archiving_changed:
             self.print_session_details()
 
-    def send_message(self, message, keyID='', type_='chat', chatstate=None,
-                    msg_id=None, composing_xep=None, resource=None, user_nick=None,
-                    xhtml=None, label=None, callback=None, callback_args=[]):
+    def _nec_message_outgoing(self, obj):
         # Send the given message to the active tab.
         # Doesn't return None if error
-        jid = self.contact.jid
+        if obj.account != self.account:
+            return
 
-        message = helpers.remove_invalid_xml_chars(message)
+        obj.jid = self.contact.jid
+        obj.message = helpers.remove_invalid_xml_chars(obj.message)
+        obj.original_message = obj.message
 
-        original_message = message
         conn = gajim.connections[self.account]
 
         if not self.session:
-            if not resource:
+            if not obj.resource:
                 if self.resource:
-                    resource = self.resource
+                    obj.resource = self.resource
                 else:
-                    resource = self.contact.resource
-            sess = conn.find_controlless_session(jid, resource=resource)
+                    obj.resource = self.contact.resource
+            sess = conn.find_controlless_session(obj.jid, resource=obj.resource)
 
             if self.resource:
-                jid += '/' + self.resource
+                obj.jid += '/' + self.resource
 
             if not sess:
                 if self.type_id == TYPE_PM:
-                    sess = conn.make_new_session(jid, type_='pm')
+                    sess = conn.make_new_session(obj.jid, type_='pm')
                 else:
-                    sess = conn.make_new_session(jid)
+                    sess = conn.make_new_session(obj.jid)
 
             self.set_session(sess)
 
-        # Send and update history
-        conn.send_message(jid, message, keyID, type_=type_, chatstate=chatstate,
-                msg_id=msg_id, composing_xep=composing_xep, resource=self.resource,
-                user_nick=user_nick, session=self.session,
-                original_message=original_message, xhtml=xhtml, label=label, callback=callback,
-                callback_args=callback_args)
+        obj.session = self.session