Index: dcc.c
===================================================================
--- dcc.c	(revision c82e4ca037494074398e22273ce2efe4f79e0f79)
+++ dcc.c	(revision f7cc73457c8f1763c31fb8d62a89971b2431d9b9)
@@ -214,5 +214,5 @@
 	                      df->ft->file_name, ipaddr, port, df->ft->file_size);
 
-	irc_send_msg_raw(iu, "PRIVMSG", iu->irc->user->nick, cmd);
+	irc_send_msg_raw(iu, "PRIVMSG", iu->irc->user->nick, cmd, 0);
 
 	g_free(cmd);
Index: irc.h
===================================================================
--- irc.h	(revision c82e4ca037494074398e22273ce2efe4f79e0f79)
+++ irc.h	(revision f7cc73457c8f1763c31fb8d62a89971b2431d9b9)
@@ -76,4 +76,5 @@
 	CAP_AWAY_NOTIFY = (1 << 3),
 	CAP_USERHOST_IN_NAMES = (1 << 4),
+	CAP_SERVER_TIME = (1 << 5),
 } irc_cap_flag_t;
 
@@ -342,6 +343,6 @@
 void irc_send_whois(irc_user_t *iu);
 void irc_send_who(irc_t *irc, GSList *l, const char *channel);
-void irc_send_msg(irc_user_t *iu, const char *type, const char *dst, const char *msg, const char *prefix);
-void irc_send_msg_raw(irc_user_t *iu, const char *type, const char *dst, const char *msg);
+void irc_send_msg(irc_user_t *iu, const char *type, const char *dst, const char *msg, const char *prefix, time_t ts);
+void irc_send_msg_raw(irc_user_t *iu, const char *type, const char *dst, const char* tags, const char *msg);
 void irc_send_msg_f(irc_user_t *iu, const char *type, const char *dst, const char *format, ...) G_GNUC_PRINTF(4, 5);
 void irc_send_nick(irc_user_t *iu, const char *new_nick);
@@ -364,4 +365,5 @@
 char *set_eval_timezone(struct set *set, char *value);
 char *irc_format_timestamp(irc_t *irc, time_t msg_ts);
+char *irc_format_servertime(irc_t *irc, time_t msg_ts);
 char *set_eval_self_messages(struct set *set, char *value);
 
Index: irc_cap.c
===================================================================
--- irc_cap.c	(revision c82e4ca037494074398e22273ce2efe4f79e0f79)
+++ irc_cap.c	(revision f7cc73457c8f1763c31fb8d62a89971b2431d9b9)
@@ -43,4 +43,5 @@
 	{"away-notify", CAP_AWAY_NOTIFY},
 	{"userhost-in-names", CAP_USERHOST_IN_NAMES},
+	{"server-time", CAP_SERVER_TIME},
 	{NULL},
 };
Index: irc_channel.c
===================================================================
--- irc_channel.c	(revision c82e4ca037494074398e22273ce2efe4f79e0f79)
+++ irc_channel.c	(revision f7cc73457c8f1763c31fb8d62a89971b2431d9b9)
@@ -500,5 +500,5 @@
 	va_end(params);
 
-	irc_send_msg(ic->irc->root, "PRIVMSG", ic->name, text, NULL);
+	irc_send_msg(ic->irc->root, "PRIVMSG", ic->name, text, NULL, 0);
 	g_free(text);
 }
Index: irc_commands.c
===================================================================
--- irc_commands.c	(revision c82e4ca037494074398e22273ce2efe4f79e0f79)
+++ irc_commands.c	(revision f7cc73457c8f1763c31fb8d62a89971b2431d9b9)
@@ -524,5 +524,5 @@
 	   for lag checks, so try to support that. */
 	if (nick_cmp(NULL, cmd[1], irc->user->nick) == 0) {
-		irc_send_msg(irc->user, "NOTICE", irc->user->nick, cmd[2], NULL);
+		irc_send_msg(irc->user, "NOTICE", irc->user->nick, cmd[2], NULL, 0);
 	} else if ((iu = irc_user_by_name(irc, cmd[1]))) {
 		iu->f->privmsg(iu, cmd[2]);
@@ -825,5 +825,5 @@
 	int i;
 
-	irc_send_msg_raw(irc->root, "NOTICE", irc->user->nick, "COMPLETIONS OK");
+	irc_send_msg_raw(irc->root, "NOTICE", irc->user->nick, "COMPLETIONS OK", 0);
 
 	for (i = 0; root_commands[i].command; i++) {
@@ -839,5 +839,5 @@
 	}
 
-	irc_send_msg_raw(irc->root, "NOTICE", irc->user->nick, "COMPLETIONS END");
+	irc_send_msg_raw(irc->root, "NOTICE", irc->user->nick, "COMPLETIONS END", 0);
 }
 
Index: irc_im.c
===================================================================
--- irc_im.c	(revision c82e4ca037494074398e22273ce2efe4f79e0f79)
+++ irc_im.c	(revision f7cc73457c8f1763c31fb8d62a89971b2431d9b9)
@@ -305,5 +305,5 @@
 
 	wrapped = word_wrap(msg, IRC_WORD_WRAP);
-	irc_send_msg(src_iu, message_type, dst, wrapped, prefix);
+	irc_send_msg(src_iu, message_type, dst, wrapped, prefix, sent_at);
 	g_free(wrapped);
 
@@ -347,5 +347,5 @@
 	g_string_append_c(msg, '\001');
 
-	irc_send_msg((irc_user_t *) bu->ui_data, "NOTICE", irc->user->nick, msg->str, NULL);
+	irc_send_msg((irc_user_t *) bu->ui_data, "NOTICE", irc->user->nick, msg->str, NULL, 0);
 
 	g_string_free(msg, TRUE);
@@ -707,5 +707,5 @@
 
 	wrapped = word_wrap(msg, IRC_WORD_WRAP);
-	irc_send_msg(iu, "PRIVMSG", ic->name, wrapped, ts);
+	irc_send_msg(iu, "PRIVMSG", ic->name, wrapped, ts, sent_at);
 	g_free(ts);
 	g_free(wrapped);
@@ -819,5 +819,5 @@
 	irc_send_msg_f(iu, "PRIVMSG", irc->user->nick, "<< \002BitlBee\002 - Invitation to chatroom %s >>", name);
 	if (msg) {
-		irc_send_msg(iu, "PRIVMSG", irc->user->nick, msg, NULL);
+		irc_send_msg(iu, "PRIVMSG", irc->user->nick, msg, NULL, 0);
 	}
 	if (chan) {
Index: irc_send.c
===================================================================
--- irc_send.c	(revision c82e4ca037494074398e22273ce2efe4f79e0f79)
+++ irc_send.c	(revision f7cc73457c8f1763c31fb8d62a89971b2431d9b9)
@@ -136,5 +136,5 @@
 
 	dst = irc_user_msgdest(iu);
-	irc_send_msg(iu, cmd, dst, text, NULL);
+	irc_send_msg(iu, cmd, dst, text, NULL, 0);
 }
 
@@ -363,9 +363,14 @@
 }
 
-void irc_send_msg(irc_user_t *iu, const char *type, const char *dst, const char *msg, const char *prefix)
+void irc_send_msg(irc_user_t *iu, const char *type, const char *dst, const char *msg, const char *prefix, time_t ts)
 {
 	char last = 0;
 	const char *s = msg, *line = msg;
+	char *tags = NULL;
 	char raw_msg[strlen(msg) + 1024];
+
+	if (!(iu->irc->caps & CAP_SERVER_TIME)) {
+		ts = 0;
+	}
 
 	while (!last) {
@@ -379,4 +384,6 @@
 		}
 		if (*s == 0 || *s == '\n') {
+			if (ts)
+				tags = irc_format_servertime(iu->irc, ts);
 			if (g_strncasecmp(line, "/me ", 4) == 0 && (!prefix || !*prefix) &&
 			    g_strcasecmp(type, "PRIVMSG") == 0) {
@@ -384,5 +391,5 @@
 				strncat(raw_msg, line + 4, s - line - 4);
 				strcat(raw_msg, "\001");
-				irc_send_msg_raw(iu, type, dst, raw_msg);
+				irc_send_msg_raw(iu, type, dst, tags, raw_msg);
 			} else {
 				*raw_msg = '\0';
@@ -391,6 +398,8 @@
 				}
 				strncat(raw_msg, line, s - line);
-				irc_send_msg_raw(iu, type, dst, raw_msg);
+				irc_send_msg_raw(iu, type, dst, tags, raw_msg);
 			}
+			if (ts)
+				g_free(tags);
 			line = s + 1;
 		}
@@ -399,8 +408,8 @@
 }
 
-void irc_send_msg_raw(irc_user_t *iu, const char *type, const char *dst, const char *msg)
-{
-	irc_write(iu->irc, ":%s!%s@%s %s %s :%s",
-	          iu->nick, iu->user, iu->host, type, dst, msg && *msg ? msg : " ");
+void irc_send_msg_raw(irc_user_t *iu, const char *type, const char *dst, const char* tags, const char *msg)
+{
+	irc_write(iu->irc, "%s%s:%s!%s@%s %s %s :%s",
+	          tags ? tags : "", tags ? " " : "", iu->nick, iu->user, iu->host, type, dst, msg && *msg ? msg : " ");
 }
 
Index: irc_user.c
===================================================================
--- irc_user.c	(revision c82e4ca037494074398e22273ce2efe4f79e0f79)
+++ irc_user.c	(revision f7cc73457c8f1763c31fb8d62a89971b2431d9b9)
@@ -261,5 +261,5 @@
 static gboolean self_privmsg(irc_user_t *iu, const char *msg)
 {
-	irc_send_msg(iu, "PRIVMSG", iu->nick, msg, NULL);
+	irc_send_msg(iu, "PRIVMSG", iu->nick, msg, NULL, 0);
 
 	return TRUE;
Index: irc_util.c
===================================================================
--- irc_util.c	(revision c82e4ca037494074398e22273ce2efe4f79e0f79)
+++ irc_util.c	(revision f7cc73457c8f1763c31fb8d62a89971b2431d9b9)
@@ -120,4 +120,19 @@
 }
 
+char *irc_format_servertime(irc_t *irc, time_t msg_ts)
+{
+	struct tm msg;
+
+	if (msg_ts <= 0) {
+		return NULL;
+	}
+
+	gmtime_r(&msg_ts, &msg);
+
+	return g_strdup_printf("@time=%04d-%02d-%02dT"
+	                       "%02d:%02d:%02d.000Z",
+	                       msg.tm_year + 1900, msg.tm_mon + 1, msg.tm_mday,
+	                       msg.tm_hour, msg.tm_min, msg.tm_sec);
+}
 
 char *set_eval_self_messages(set_t *set, char *value)
