Index: protocols/jabber/iq.c
===================================================================
--- protocols/jabber/iq.c	(revision 3d31618b5f50552b71d8c6f1b3fa733a212ee89c)
+++ protocols/jabber/iq.c	(revision dd43c6256c143e9e6a479e024cb5b7631027efba)
@@ -27,4 +27,5 @@
 static xt_status jabber_parse_roster(struct im_connection *ic, struct xt_node *node, struct xt_node *orig);
 static xt_status jabber_iq_display_vcard(struct im_connection *ic, struct xt_node *node, struct xt_node *orig);
+static xt_status jabber_gmail_handle_new(struct im_connection *ic, struct xt_node *node);
 
 xt_status jabber_pkt_iq(struct xt_node *node, gpointer data)
@@ -141,4 +142,8 @@
 		    (strcmp(s, XMLNS_SI) == 0)) {
 			return jabber_si_handle_request(ic, node, c);
+		} else if ((c = xt_find_node(node->children, "new-mail")) &&
+		           (s = xt_find_attr(c, "xmlns")) &&
+		           (strcmp(s, XMLNS_GMAILNOTIFY) == 0)) {
+			return jabber_gmail_handle_new(ic, node);
 		} else if (!(c = xt_find_node(node->children, "query")) ||
 		           !(s = xt_find_attr(c, "xmlns"))) {
@@ -342,4 +347,7 @@
 			return XT_ABORT;
 		}
+		if (jd->flags & JFLAG_GMAILNOTIFY && node == NULL) {
+			jabber_iq_query_server(ic, jd->server, XMLNS_DISCO_INFO);
+		}
 	} else if ((jd->flags & (JFLAG_WANT_BIND | JFLAG_WANT_SESSION)) == 0) {
 		if (!jabber_get_roster(ic)) {
@@ -369,4 +377,23 @@
 
 	return st;
+}
+
+xt_status jabber_iq_query_gmail(struct im_connection *ic);
+
+static xt_status jabber_gmail_handle_new(struct im_connection *ic, struct xt_node *node)
+{
+	struct xt_node *response;
+	struct jabber_data *jd = ic->proto_data;
+
+	response = jabber_make_packet("iq", "result", g_strdup_printf("%s@%s", jd->username, jd->server), NULL);
+
+	jabber_cache_add(ic, response, NULL);
+	if (!jabber_write_packet(ic, response)) {
+		return XT_ABORT;
+	}
+
+	jabber_iq_query_gmail(ic);
+
+	return XT_HANDLED;
 }
 
@@ -710,4 +737,32 @@
 }
 
+xt_status jabber_iq_parse_gmail(struct im_connection *ic, struct xt_node *node, struct xt_node *orig);
+
+xt_status jabber_iq_query_gmail(struct im_connection *ic)
+{
+	struct xt_node *node, *query;
+	struct jabber_data *jd = ic->proto_data;
+
+	node = xt_new_node("query", NULL, NULL);
+	xt_add_attr(node, "xmlns", XMLNS_GMAILNOTIFY);
+	if (jd->gmail_time) {
+		char *formatted = g_strdup_printf("%" G_GUINT64_FORMAT, (jd->gmail_time + 1));
+		xt_add_attr(node, "newer-than-time", formatted);
+		g_free(formatted);
+	}
+	if (jd->gmail_tid) {
+		xt_add_attr(node, "newer-than-tid", jd->gmail_tid);
+	}
+
+	if (!(query = jabber_make_packet("iq", "get", jd->me, node))) {
+		imcb_log(ic, "WARNING: Couldn't generate server query");
+		xt_free_node(node);
+	}
+
+	jabber_cache_add(ic, query, jabber_iq_parse_gmail);
+
+	return jabber_write_packet(ic, query) ? XT_HANDLED : XT_ABORT;
+}
+
 xt_status jabber_iq_parse_server_features(struct im_connection *ic, struct xt_node *node, struct xt_node *orig);
 
@@ -729,4 +784,71 @@
 
 	return jabber_write_packet(ic, query) ? XT_HANDLED : XT_ABORT;
+}
+
+xt_status jabber_iq_parse_gmail(struct im_connection *ic, struct xt_node *node, struct xt_node *orig)
+{
+	struct xt_node *c;
+	struct jabber_data *jd = ic->proto_data;
+	char *xmlns, *from;
+	guint64 l_time = 0;
+	char *tid = NULL;
+
+	if (!(c = xt_find_node(node->children, "mailbox")) ||
+	    !(from = xt_find_attr(node, "from")) ||
+	    !(xmlns = xt_find_attr(c, "xmlns")) ||
+	    (g_strcmp0(xmlns, XMLNS_GMAILNOTIFY) != 0)) {
+		imcb_log(ic, "WARNING: Received incomplete mailbox packet for gmail notify");
+		return XT_HANDLED;
+	}
+
+	c = c->children;
+
+	while ((c = xt_find_node(c, "mail-thread-info"))) {
+		struct xt_node *thread, *s;
+		char *subject = NULL;
+		char *snippet = NULL;
+		char *msg = NULL;
+		guint64 t_time;
+
+		t_time = g_ascii_strtoull(xt_find_attr(c, "date"), NULL, 10);
+		if (t_time && t_time > l_time) {
+			l_time = t_time;
+			tid = xt_find_attr(c, "tid");
+		}
+
+		thread = c->children;
+
+		if ((s = xt_find_node(thread, "subject"))) {
+			subject = s->text;
+		}
+
+		if ((s = xt_find_node(thread, "snippet"))) {
+			snippet = s->text;
+		}
+
+		if (subject) {
+			msg = g_strdup_printf("New mail for %s. Subj: %s", from, subject);
+		} else {
+			msg = g_strdup_printf("New mail for %s.", from);
+		}
+		imcb_notify_email(ic, set_getstr(&ic->acc->set, "notify_handle"), msg, 0, 0);
+
+		if (snippet) {
+			imcb_notify_email(ic, set_getstr(&ic->acc->set, "notify_handle"), snippet, 0, 0);
+		}
+
+		c = c->next;
+		g_free(msg);
+	}
+
+	if (l_time && (!jd->gmail_time || l_time > jd->gmail_time)) {
+		jd->gmail_time = l_time;
+		if (tid) {
+			g_free(jd->gmail_tid);
+			jd->gmail_tid = g_strdup(tid);
+		}
+	}
+
+	return XT_HANDLED;
 }
 
@@ -781,4 +903,17 @@
 			c = c->next;
 		}
+
+		if (jd->flags & JFLAG_GMAILNOTIFY) {
+			/* search for gmail notification feature */
+			c = xt_find_node(node->children, "query");
+			c = c->children;
+			while ((c = xt_find_node(c, "feature"))) {
+				if (strcmp(xt_find_attr(c, "var"), XMLNS_GMAILNOTIFY) == 0) {
+					jabber_iq_query_gmail(ic);
+				}
+				c = c->next;
+			}
+		}
+
 	} else if (strcmp(xmlns, XMLNS_BYTESTREAMS) == 0) {
 		char *host, *jid, *port_s;
Index: protocols/jabber/jabber.c
===================================================================
--- protocols/jabber/jabber.c	(revision 3d31618b5f50552b71d8c6f1b3fa733a212ee89c)
+++ protocols/jabber/jabber.c	(revision dd43c6256c143e9e6a479e024cb5b7631027efba)
@@ -100,5 +100,10 @@
 
 	s = set_add(&acc->set, "xmlconsole", "false", set_eval_bool, acc);
+
+	s = set_add(&acc->set, "gmail_notifications", "false", set_eval_bool, acc);
 	s->flags |= ACC_SET_OFFLINE_ONLY;
+
+	s = set_add(&acc->set, "notify_handle", NULL, NULL, acc);
+	s->flags |= ACC_SET_OFFLINE_ONLY | SET_NULL_OK;
 
 	acc->flags |= ACC_FLAG_AWAY_MESSAGE | ACC_FLAG_STATUS_MESSAGE |
@@ -259,4 +264,10 @@
 		imcb_add_buddy(ic, JABBER_XMLCONSOLE_HANDLE, NULL);
 	}
+	if (set_getbool(&acc->set, "gmail_notifications")) {
+		jd->flags |= JFLAG_GMAILNOTIFY;
+		if (set_getstr(&acc->set, "notify_handle")) {
+			imcb_add_buddy(ic, set_getstr(&acc->set, "notify_handle"), NULL);
+		}
+	}
 
 	jabber_generate_id_hash(jd);
@@ -334,4 +345,5 @@
 	g_free(jd->away_message);
 	g_free(jd->internal_jid);
+	g_free(jd->gmail_tid);
 	g_free(jd->username);
 	g_free(jd->me);
Index: protocols/jabber/jabber.h
===================================================================
--- protocols/jabber/jabber.h	(revision 3d31618b5f50552b71d8c6f1b3fa733a212ee89c)
+++ protocols/jabber/jabber.h	(revision dd43c6256c143e9e6a479e024cb5b7631027efba)
@@ -46,4 +46,5 @@
 	JFLAG_XMLCONSOLE = 64,          /* If the user added an xmlconsole buddy. */
 	JFLAG_STARTTLS_DONE = 128,      /* If a plaintext session was converted to TLS. */
+	JFLAG_GMAILNOTIFY = 256,        /* If gmail notification is enabled */
 
 	JFLAG_GTALK =  0x100000,        /* Is Google Talk, as confirmed by iq discovery */
@@ -102,4 +103,6 @@
 	const struct jabber_away_state *away_state;
 	char *away_message;
+	guint64 gmail_time;
+	char *gmail_tid;
 
 	md5_state_t cached_id_prefix;
@@ -224,4 +227,5 @@
 #define XMLNS_DELAY        "urn:xmpp:delay"                                      /* XEP-0203 */
 #define XMLNS_XDATA        "jabber:x:data"                                       /* XEP-0004 */
+#define XMLNS_GMAILNOTIFY  "google:mail:notify"                                  /* Not a XEP */
 #define XMLNS_CHATSTATES   "http://jabber.org/protocol/chatstates"               /* XEP-0085 */
 #define XMLNS_DISCO_INFO   "http://jabber.org/protocol/disco#info"               /* XEP-0030 */
