diff --git a/libpurple/protocols/jabber/message.h b/libpurple/protocols/jabber/message.h
--- a/libpurple/protocols/jabber/message.h
+++ b/libpurple/protocols/jabber/message.h
@@ -43,7 +43,9 @@
 	} type;
 	time_t sent;
 	gboolean delayed;
+	gboolean forwarded;
 	gboolean hasBuzz;
+	gboolean outgoing;
 	char *id;
 	char *from;
 	char *to;
diff --git a/libpurple/protocols/jabber/message.c b/libpurple/protocols/jabber/message.c
--- a/libpurple/protocols/jabber/message.c
+++ b/libpurple/protocols/jabber/message.c
@@ -100,11 +100,12 @@
 
 static void handle_chat(JabberMessage *jm)
 {
-	const gchar *contact = jm->from;
+	const gchar *contact = jm->outgoing ? jm->to : jm->from;
 	JabberID *jid = jabber_id_new(contact);
 
 	PurpleConnection *gc;
 	PurpleAccount *account;
+	PurpleMessageFlags flags = 0;
 	JabberBuddy *jb;
 	JabberBuddyResource *jbr;
 	GString *body;
@@ -199,7 +200,12 @@
 			jbr->thread_id = g_strdup(jm->thread_id);
 		}
 
-		purple_serv_got_im(gc, contact, body->str, 0, jm->sent);
+		if(jm->forwarded) {
+			flags |= PURPLE_MESSAGE_FORWARDED;
+		}
+		flags |= jm->outgoing ? PURPLE_MESSAGE_SEND : PURPLE_MESSAGE_RECV;
+
+		purple_serv_got_im(gc, contact, body->str, flags, jm->sent);
 	}
 
 	jabber_id_free(jid);
@@ -576,16 +582,34 @@
 	const char *id, *from, *to, *type;
 	PurpleXmlNode *child = NULL, *received = NULL;
 	gboolean signal_return;
+	gboolean delayed = FALSE, is_outgoing = FALSE, is_forwarded = FALSE;
+	time_t timestamp = time(NULL);
 
-	/* Check if we have a carbons received element. */
-	received = purple_xmlnode_get_child_with_namespace(packet, "received",
-	                                                   NS_MESSAGE_CARBONS);
-	if(received != NULL) {
+	/* Check if we have a carbons received element from our own account. */
+	from = purple_xmlnode_get_attrib(packet, "from");
+	if(from != NULL && jabber_is_own_account(js, from)) {
 		PurpleXmlNode *forwarded = NULL;
 
-		forwarded = purple_xmlnode_get_child_with_namespace(received,
-		                                                    "forwarded",
-		                                                    NS_FORWARD);
+		/* We check if this is a received carbon first. */
+		received = purple_xmlnode_get_child_with_namespace(packet, "received",
+		                                                   NS_MESSAGE_CARBONS);
+		if(received != NULL) {
+			forwarded = purple_xmlnode_get_child_with_namespace(received,
+			                                                    "forwarded",
+			                                                    NS_FORWARD);
+		} else {
+			PurpleXmlNode *sent = NULL;
+
+			sent = purple_xmlnode_get_child_with_namespace(packet, "sent",
+			                                               NS_MESSAGE_CARBONS);
+			if(sent != NULL) {
+				forwarded = purple_xmlnode_get_child_with_namespace(sent,
+				                                                    "forwarded",
+				                                                    NS_FORWARD);
+				is_outgoing = TRUE;
+			}
+		}
+
 		if(forwarded != NULL) {
 			PurpleXmlNode *fwd_msg = NULL;
 
@@ -593,12 +617,32 @@
 			                                                  "message",
 			                                                  NS_XMPP_CLIENT);
 			if(fwd_msg != NULL) {
+				PurpleXmlNode *delay = NULL;
+
+				/* We have a forwarded message, so update the packet to point
+				 * to it directly.
+				 */
 				packet = fwd_msg;
+				is_forwarded = TRUE;
+
+				/* Now check if it was a delayed message and if so, grab the
+				 * timestamp that the server sent.
+				 */
+				delay = purple_xmlnode_get_child_with_namespace(forwarded,
+				                                                "delay",
+				                                                NS_DELAYED_DELIVERY);
+				if(delay != NULL) {
+					const gchar *ts = purple_xmlnode_get_attrib(delay,
+					                                            "stamp");
+
+					timestamp = purple_str_to_time(ts, TRUE, NULL, NULL, NULL);
+					delayed = TRUE;
+				}
 			}
 		}
 	}
 
-	/* If the message was forward, packet is now pointing to the forwarded
+	/* If the message was forwarded, packet is now pointing to the forwarded
 	 * message.
 	 */
 	from = purple_xmlnode_get_attrib(packet, "from");
@@ -613,9 +657,11 @@
 
 	jm = g_new0(JabberMessage, 1);
 	jm->js = js;
-	jm->sent = time(NULL);
-	jm->delayed = FALSE;
+	jm->sent = timestamp;
+	jm->delayed = delayed;
 	jm->chat_state = JM_STATE_NONE;
+	jm->forwarded = is_forwarded;
+	jm->outgoing = is_outgoing;
 
 	if(type) {
 		if(purple_strequal(type, "normal"))
diff --git a/libpurple/purplemessage.h b/libpurple/purplemessage.h
--- a/libpurple/purplemessage.h
+++ b/libpurple/purplemessage.h
@@ -93,6 +93,7 @@
 	PURPLE_MESSAGE_NO_LINKIFY   = 1 << 12,
 	PURPLE_MESSAGE_INVISIBLE    = 1 << 13,
 	PURPLE_MESSAGE_REMOTE_SEND  = 1 << 14,
+	PURPLE_MESSAGE_FORWARDED    = 1 << 15,
 } PurpleMessageFlags;
 
 /**
