aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/user-guide/commands.xml22
-rw-r--r--protocols/bee.h2
-rw-r--r--protocols/bee_user.c9
-rw-r--r--protocols/jabber/iq.c135
-rw-r--r--protocols/jabber/jabber.c12
-rw-r--r--protocols/jabber/jabber.h4
-rw-r--r--protocols/msn/msn.c10
-rw-r--r--protocols/msn/ns.c14
-rw-r--r--protocols/purple/purple.c11
-rw-r--r--protocols/yahoo/yahoo.c28
10 files changed, 233 insertions, 14 deletions
diff --git a/doc/user-guide/commands.xml b/doc/user-guide/commands.xml
index 4d6e7659..40387585 100644
--- a/doc/user-guide/commands.xml
+++ b/doc/user-guide/commands.xml
@@ -1022,6 +1022,28 @@
</bitlbee-setting>
+ <bitlbee-setting name="notify_handle" type="string" scope="account">
+ <default>empty</default>
+
+ <description>
+ <para>
+ This setting is available for protocols with e-mail notification functionality. If set to empty all e-mail notifications will go to control channel, if set to some string - this will be the name of a contact who will PRIVMSG you on every new notification.
+ </para>
+ </description>
+
+ </bitlbee-setting>
+
+ <bitlbee-setting name="gmail_notifications" type="boolean" scope="account">
+ <default>false</default>
+
+ <description>
+ <para>
+ Same as "mail_notifications" but GMail specific.
+ </para>
+ </description>
+
+ </bitlbee-setting>
+
<bitlbee-setting name="message_length" type="integer" scope="account">
<default>140</default>
diff --git a/protocols/bee.h b/protocols/bee.h
index 36ff2889..1d87f743 100644
--- a/protocols/bee.h
+++ b/protocols/bee.h
@@ -155,6 +155,8 @@ G_MODULE_EXPORT void imcb_buddy_times(struct im_connection *ic, const char *hand
/* Call when a handle says something. 'flags' and 'sent_at may be just 0. */
G_MODULE_EXPORT void imcb_buddy_msg(struct im_connection *ic, const char *handle, const char *msg, guint32 flags,
time_t sent_at);
+G_MODULE_EXPORT void imcb_notify_email(struct im_connection *ic, const char *handle, char *msg, guint32 flags,
+ time_t sent_at);
/* bee_chat.c */
/* These two functions are to create a group chat.
diff --git a/protocols/bee_user.c b/protocols/bee_user.c
index 2eb24997..562b31b3 100644
--- a/protocols/bee_user.c
+++ b/protocols/bee_user.c
@@ -270,6 +270,15 @@ void imcb_buddy_msg(struct im_connection *ic, const char *handle, const char *ms
}
}
+void imcb_notify_email(struct im_connection *ic, const char *handle, char *msg, uint32_t flags, time_t sent_at)
+{
+ if (handle != NULL) {
+ imcb_buddy_msg(ic, handle, msg, flags, sent_at);
+ } else {
+ imcb_log(ic, "%s", msg);
+ }
+}
+
void imcb_buddy_typing(struct im_connection *ic, const char *handle, uint32_t flags)
{
bee_user_t *bu;
diff --git a/protocols/jabber/iq.c b/protocols/jabber/iq.c
index 33889d32..4eef6925 100644
--- a/protocols/jabber/iq.c
+++ b/protocols/jabber/iq.c
@@ -26,6 +26,7 @@
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)
{
@@ -140,6 +141,10 @@ xt_status jabber_pkt_iq(struct xt_node *node, gpointer data)
(s = xt_find_attr(c, "xmlns")) &&
(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"))) {
return XT_HANDLED;
@@ -341,6 +346,9 @@ xt_status jabber_pkt_bind_sess(struct im_connection *ic, struct xt_node *node, s
if (!jabber_write_packet(ic, reply)) {
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)) {
return XT_ABORT;
@@ -370,6 +378,25 @@ int jabber_get_roster(struct im_connection *ic)
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;
+}
+
static xt_status jabber_parse_roster(struct im_connection *ic, struct xt_node *node, struct xt_node *orig)
{
struct jabber_data *jd = ic->proto_data;
@@ -709,6 +736,34 @@ xt_status jabber_iq_parse_features(struct im_connection *ic, struct xt_node *nod
return XT_HANDLED;
}
+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);
xt_status jabber_iq_query_server(struct im_connection *ic, char *jid, char *xmlns)
@@ -730,6 +785,73 @@ xt_status jabber_iq_query_server(struct im_connection *ic, char *jid, char *xmln
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;
+}
+
/*
* Query the server for "items", query each "item" for identities, query each "item" that's a proxy for it's bytestream info
*/
@@ -780,6 +902,19 @@ xt_status jabber_iq_parse_server_features(struct im_connection *ic, struct xt_no
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;
int port;
diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c
index 04db365e..184021dd 100644
--- a/protocols/jabber/jabber.c
+++ b/protocols/jabber/jabber.c
@@ -99,8 +99,13 @@ static void jabber_init(account_t *acc)
s = set_add(&acc->set, "user_agent", "BitlBee", NULL, acc);
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 |
ACC_FLAG_HANDLE_DOMAINS;
}
@@ -258,6 +263,12 @@ void jabber_connect(struct im_connection *ic)
I think this shouldn't break anything. */
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);
}
@@ -333,6 +344,7 @@ static void jabber_logout(struct im_connection *ic)
g_free(jd->oauth2_access_token);
g_free(jd->away_message);
g_free(jd->internal_jid);
+ g_free(jd->gmail_tid);
g_free(jd->username);
g_free(jd->me);
g_free(jd);
diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h
index b8ef8b08..37c99ff0 100644
--- a/protocols/jabber/jabber.h
+++ b/protocols/jabber/jabber.h
@@ -45,6 +45,7 @@ typedef enum {
activates all XEP-85 related code. */
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 */
JFLAG_HIPCHAT = 0x200000, /* Is hipchat, because prpl->name says so */
@@ -101,6 +102,8 @@ struct jabber_data {
presence_send_update() to inform the server about the changes. */
const struct jabber_away_state *away_state;
char *away_message;
+ guint64 gmail_time;
+ char *gmail_tid;
md5_state_t cached_id_prefix;
GHashTable *node_cache;
@@ -223,6 +226,7 @@ struct jabber_transfer {
#define XMLNS_DELAY_OLD "jabber:x:delay" /* XEP-0091 */
#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 */
#define XMLNS_DISCO_ITEMS "http://jabber.org/protocol/disco#items" /* XEP-0030 */
diff --git a/protocols/msn/msn.c b/protocols/msn/msn.c
index 4acff23a..c5567a14 100644
--- a/protocols/msn/msn.c
+++ b/protocols/msn/msn.c
@@ -45,7 +45,11 @@ static void msn_init(account_t *acc)
s = set_add(&acc->set, "port", MSN_NS_PORT, set_eval_int, acc);
s->flags |= ACC_SET_OFFLINE_ONLY;
- set_add(&acc->set, "mail_notifications", "false", set_eval_bool, acc);
+ s = set_add(&acc->set, "mail_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 |
ACC_FLAG_HANDLE_DOMAINS;
@@ -81,6 +85,10 @@ static void msn_login(account_t *acc)
imcb_log(ic, "Connecting");
msn_ns_connect(ic, server,
set_getint(&ic->acc->set, "port"));
+
+ if (set_getbool(&acc->set, "mail_notifications") && set_getstr(&acc->set, "notify_handle")) {
+ imcb_add_buddy(ic, set_getstr(&acc->set, "notify_handle"), NULL);
+ }
}
static void msn_logout(struct im_connection *ic)
diff --git a/protocols/msn/ns.c b/protocols/msn/ns.c
index ab92f30d..130f1c91 100644
--- a/protocols/msn/ns.c
+++ b/protocols/msn/ns.c
@@ -393,9 +393,11 @@ int msn_ns_message(struct msn_data *md, char *msg, int msglen, char **cmd, int n
char *folders = get_rfc822_header(body, "Folders-Unread:", blen);
if (inbox && folders) {
- imcb_log(ic,
- "INBOX contains %s new messages, plus %s messages in other folders.", inbox,
- folders);
+ char *msg = g_strdup_printf(
+ "INBOX contains %s new messages, plus %s messages in other folders.", inbox,
+ folders);
+ imcb_notify_email(ic, set_getstr(&ic->acc->set, "notify_handle"), msg, 0, 0);
+ g_free(msg);
}
g_free(inbox);
@@ -407,8 +409,10 @@ int msn_ns_message(struct msn_data *md, char *msg, int msglen, char **cmd, int n
char *fromname = get_rfc822_header(body, "From:", blen);
if (from && fromname) {
- imcb_log(ic, "Received an e-mail message from %s <%s>.", fromname,
- from);
+ char *msg = g_strdup_printf("Received an e-mail message from %s <%s>.",
+ fromname, from);
+ imcb_notify_email(ic, set_getstr(&ic->acc->set, "notify_handle"), msg, 0, 0);
+ g_free(msg);
}
g_free(from);
diff --git a/protocols/purple/purple.c b/protocols/purple/purple.c
index 6d8cff56..42a5448c 100644
--- a/protocols/purple/purple.c
+++ b/protocols/purple/purple.c
@@ -237,6 +237,9 @@ static void purple_init(account_t *acc)
if (pi->options & OPT_PROTO_MAIL_CHECK) {
s = set_add(&acc->set, "mail_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;
}
if (strcmp(prpl->info->name, "Gadu-Gadu") == 0) {
@@ -331,6 +334,10 @@ static void purple_login(account_t *acc)
purple_sync_settings(acc, pd->account);
purple_account_set_enabled(pd->account, "BitlBee", TRUE);
+
+ if (set_getbool(&acc->set, "mail_notifications") && set_getstr(&acc->set, "notify_handle")) {
+ imcb_add_buddy(ic, set_getstr(&acc->set, "notify_handle"), NULL);
+ }
}
static void purple_logout(struct im_connection *ic)
@@ -1253,8 +1260,10 @@ static void *prplcb_notify_email(PurpleConnection *gc, const char *subject, cons
const char *to, const char *url)
{
struct im_connection *ic = purple_ic_by_gc(gc);
+ char *msg = g_strdup_printf("Received e-mail from %s for %s: %s <%s>", from, to, subject, url);
- imcb_log(ic, "Received e-mail from %s for %s: %s <%s>", from, to, subject, url);
+ imcb_notify_email(ic, set_getstr(&ic->acc->set, "notify_handle"), msg, 0, 0);
+ g_free(msg);
return NULL;
}
diff --git a/protocols/yahoo/yahoo.c b/protocols/yahoo/yahoo.c
index 728803fb..2e7c4831 100644
--- a/protocols/yahoo/yahoo.c
+++ b/protocols/yahoo/yahoo.c
@@ -122,7 +122,13 @@ static char *byahoo_strip(const char *in)
static void byahoo_init(account_t *acc)
{
- set_add(&acc->set, "mail_notifications", "false", set_eval_bool, acc);
+ set_t *s;
+
+ s = set_add(&acc->set, "mail_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;
}
@@ -144,6 +150,10 @@ static void byahoo_login(account_t *acc)
imcb_log(ic, "Connecting");
yd->y2_id = yahoo_init(acc->user, acc->pass);
yahoo_login(yd->y2_id, yd->current_status);
+
+ if (set_getbool(&acc->set, "mail_notifications") && set_getstr(&acc->set, "notify_handle")) {
+ imcb_add_buddy(ic, set_getstr(&acc->set, "notify_handle"), NULL);
+ }
}
static void byahoo_logout(struct im_connection *ic)
@@ -948,13 +958,17 @@ void ext_yahoo_game_notify(int id, const char *me, const char *who, int stat, co
void ext_yahoo_mail_notify(int id, const char *from, const char *subj, int cnt)
{
struct im_connection *ic = byahoo_get_ic_by_id(id);
+ char *msg;
+
+ if (set_getbool(&ic->acc->set, "mail_notifications")) {
+ if (from && subj) {
+ msg = g_strdup_printf("Received e-mail message from %s with subject `%s'", from, subj);
+ } else if (cnt > 0) {
+ msg = g_strdup_printf("Received %d new e-mails", cnt);
+ }
- if (!set_getbool(&ic->acc->set, "mail_notifications")) {
- ; /* The user doesn't care. */
- } else if (from && subj) {
- imcb_log(ic, "Received e-mail message from %s with subject `%s'", from, subj);
- } else if (cnt > 0) {
- imcb_log(ic, "Received %d new e-mails", cnt);
+ imcb_notify_email(ic, set_getstr(&ic->acc->set, "notify_handle"), msg, 0, 0);
+ g_free(msg);
}
}