imap-notify.c revision 2ac5f36aa7c2e7a07ba8815d43a6d7483f62e74c
02c335c23bf5fa225a467c19f2c063fb0dc7b8c3Timo Sirainen/* Copyright (c) 2013-2016 Dovecot authors, see the included COPYING file */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenstatic int imap_notify_list(struct imap_notify_namespace *notify_ns,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen char ns_sep = mail_namespace_get_sep(notify_ns->ns);
09801f106cd531a28b4e03ec665e44c421264560Timo Sirainen return client_send_line_next(notify_ns->ctx->client, str_c(str));
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenstatic int imap_notify_status(struct imap_notify_namespace *notify_ns,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen struct client *client = notify_ns->ctx->client;
09801f106cd531a28b4e03ec665e44c421264560Timo Sirainen if ((client->enabled_features & MAILBOX_FEATURE_CONDSTORE) != 0)
5024c4799b324ea15270152b775c67ccfc72d5bcTimo Sirainen box = mailbox_alloc(notify_ns->ns->list, rec->vname, 0);
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen if ((rec->events & MAILBOX_LIST_NOTIFY_UIDVALIDITY) != 0) {
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen items.status |= STATUS_UIDVALIDITY | STATUS_UIDNEXT |
8edc373587d75f8040e3c4416e50638aa2a32188Timo Sirainen if ((rec->events & (MAILBOX_LIST_NOTIFY_APPENDS |
8edc373587d75f8040e3c4416e50638aa2a32188Timo Sirainen items.status |= STATUS_UIDNEXT | STATUS_MESSAGES | STATUS_UNSEEN;
8edc373587d75f8040e3c4416e50638aa2a32188Timo Sirainen if ((rec->events & MAILBOX_LIST_NOTIFY_SEEN_CHANGES) != 0)
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen if ((rec->events & MAILBOX_LIST_NOTIFY_MODSEQ_CHANGES) != 0) {
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen /* if HIGHESTMODSEQ isn't being sent, don't send anything */
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen /* don't send anything */
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen } else if (mailbox_get_status(box, items.status, &result.status) < 0) {
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen /* hide permission errors from client. we don't want to leak
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen information about existence of mailboxes where user doesn't
9e095dd6a77097356aca8216356d4d71ef1bea45Timo Sirainen have access to */
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen ret = imap_status_send(client, rec->vname, &items, &result);
9f131c8b6d88ffc65d94eae63e0b3c11d7c24cb9Timo Sirainenimap_notify_next(struct imap_notify_namespace *notify_ns,
5024c4799b324ea15270152b775c67ccfc72d5bcTimo Sirainen if ((rec->events & MAILBOX_LIST_NOTIFY_CREATE) != 0) {
5024c4799b324ea15270152b775c67ccfc72d5bcTimo Sirainen if (mailbox_list_mailbox(notify_ns->ns->list, rec->storage_name,
5024c4799b324ea15270152b775c67ccfc72d5bcTimo Sirainen if ((ret = imap_notify_list(notify_ns, rec, mailbox_flags)) <= 0)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if ((rec->events & MAILBOX_LIST_NOTIFY_DELETE) != 0) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if ((ret = imap_notify_list(notify_ns, rec, MAILBOX_NONEXISTENT)) < 0)
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen if ((rec->events & MAILBOX_LIST_NOTIFY_RENAME) != 0) {
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen if (mailbox_list_mailbox(notify_ns->ns->list, rec->storage_name,
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen if ((ret = imap_notify_list(notify_ns, rec, mailbox_flags)) < 0)
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen if ((rec->events & MAILBOX_LIST_NOTIFY_SUBSCRIBE) != 0) {
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen if (mailbox_list_mailbox(notify_ns->ns->list, rec->storage_name,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if ((rec->events & MAILBOX_LIST_NOTIFY_UNSUBSCRIBE) != 0) {
1060afdc2fcdf647dbb3bc11647401f1b44a3a8aTimo Sirainen if (mailbox_list_mailbox(notify_ns->ns->list, rec->storage_name,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if ((ret = imap_notify_list(notify_ns, rec, mailbox_flags)) < 0)
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen if ((rec->events & (MAILBOX_LIST_NOTIFY_UIDVALIDITY |
4ae354df6e08998137b527f495bfaaf3daf9eddcTimo Sirainen if ((ret = imap_notify_status(notify_ns, rec)) < 0)
8edc373587d75f8040e3c4416e50638aa2a32188Timo Sirainenimap_notify_match_event(struct imap_notify_namespace *notify_ns,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen const struct imap_notify_mailboxes *notify_boxes,
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen enum imap_notify_event wanted_events = notify_boxes->events;
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen /* check for mailbox list events first */
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen if ((wanted_events & IMAP_NOTIFY_EVENT_MAILBOX_NAME) != 0) {
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen if ((rec->events & (MAILBOX_LIST_NOTIFY_CREATE |
01f4ee4a0243f3fe9af763e1a540cd5cff0d63f5Timo Sirainen if ((wanted_events & IMAP_NOTIFY_EVENT_SUBSCRIPTION_CHANGE) != 0) {
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen if ((rec->events & (MAILBOX_LIST_NOTIFY_SUBSCRIBE |
09801f106cd531a28b4e03ec665e44c421264560Timo Sirainen /* if this is an event for the selected mailbox, ignore it */
09801f106cd531a28b4e03ec665e44c421264560Timo Sirainen if (box != NULL && mailbox_equals(box, notify_ns->ns, rec->vname))
e17d72cec1c75554483d692edd687b411526f312Timo Sirainen if ((wanted_events & (IMAP_NOTIFY_EVENT_MESSAGE_NEW |
01f4ee4a0243f3fe9af763e1a540cd5cff0d63f5Timo Sirainen if ((rec->events & MAILBOX_LIST_NOTIFY_UIDVALIDITY) != 0)
09801f106cd531a28b4e03ec665e44c421264560Timo Sirainen if ((wanted_events & IMAP_NOTIFY_EVENT_MESSAGE_NEW) != 0) {
e17d72cec1c75554483d692edd687b411526f312Timo Sirainen if ((rec->events & MAILBOX_LIST_NOTIFY_APPENDS) != 0)
e17d72cec1c75554483d692edd687b411526f312Timo Sirainen if ((wanted_events & IMAP_NOTIFY_EVENT_MESSAGE_EXPUNGE) != 0) {
01f4ee4a0243f3fe9af763e1a540cd5cff0d63f5Timo Sirainen if ((rec->events & MAILBOX_LIST_NOTIFY_EXPUNGES) != 0)
01f4ee4a0243f3fe9af763e1a540cd5cff0d63f5Timo Sirainen if ((wanted_events & IMAP_NOTIFY_EVENT_FLAG_CHANGE) != 0) {
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen if ((rec->events & (MAILBOX_LIST_NOTIFY_SEEN_CHANGES |
9a755930537f13e9746c4fc8c1bc42a83e52275eTimo Sirainenbool imap_notify_match_mailbox(struct imap_notify_namespace *notify_ns,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen const struct imap_notify_mailboxes *notify_boxes,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen const char *const *namep;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen box = mailbox_alloc(notify_ns->ns->list, vname, 0);
331b4805d76c0b3a5a38a560276f3cf110f55ba0Timo Sirainen ns_sep = mail_namespace_get_sep(notify_ns->ns);
331b4805d76c0b3a5a38a560276f3cf110f55ba0Timo Sirainen /* everything under root. NOTIFY spec itself
331b4805d76c0b3a5a38a560276f3cf110f55ba0Timo Sirainen doesn't define this, but we use it for
331b4805d76c0b3a5a38a560276f3cf110f55ba0Timo Sirainen implementing "personal" */
e93184a9055c2530366dfe617e07199603c399ddMartti Rannanjärviimap_notify_match(struct imap_notify_namespace *notify_ns,
bf132be3fe1c9e8de84f10d0b05c0b46ca542ac4Timo Sirainen const struct imap_notify_mailboxes *notify_boxes;
09801f106cd531a28b4e03ec665e44c421264560Timo Sirainen array_foreach(¬ify_ns->mailboxes, notify_boxes) {
bf132be3fe1c9e8de84f10d0b05c0b46ca542ac4Timo Sirainen if (imap_notify_match_event(notify_ns, notify_boxes, rec) &&
bf132be3fe1c9e8de84f10d0b05c0b46ca542ac4Timo Sirainen imap_notify_match_mailbox(notify_ns, notify_boxes, rec->vname))
43834f87bf431198f986e86052a4f6e558fdb07dTimo Sirainenstatic int imap_client_notify_ns(struct imap_notify_namespace *notify_ns)
e93184a9055c2530366dfe617e07199603c399ddMartti Rannanjärvi const struct mailbox_list_notify_rec *rec;
e93184a9055c2530366dfe617e07199603c399ddMartti Rannanjärvi return 0; /* notifications not supported in this namespace */
43834f87bf431198f986e86052a4f6e558fdb07dTimo Sirainen while ((ret = mailbox_list_notify_next(notify_ns->notify, &rec)) > 0) {
43834f87bf431198f986e86052a4f6e558fdb07dTimo Sirainen if (imap_notify_match(notify_ns, rec)) T_BEGIN {
09801f106cd531a28b4e03ec665e44c421264560Timo Sirainen /* failed to get some notifications */
int ret;
return ret;
if (ret == 0)
if (ret < 0) {
return ret;
static enum mailbox_list_notify_event
return ret;
i_unreached();
if (!notify_hook_registered) {
notify_events = 0;
ret = 0;
return ret;