tallence / push-notification-kafka-plugin

A driver for Dovecot's Push Notification Framework for publishing push notification events to a Kafka broker.
Other
6 stars 4 forks source link

Set Keywords for several mails at once- #12

Open jrse opened 5 years ago

jrse commented 5 years ago

if user selects multiple mails at one "e.g. via thunderbird" and sets / deletes a keyword. the notification plugin sends the following msg.

{"user":"sm@sm.test","mailbox":"INBOX","event":"FlagsClear","uidvalidity":1556548880,"uid":1,"keywords":["x.travel",".travel","x.travel","x.travel","x.travel","x.travel","x.travel","x.travel","x.travel","travel","x.travel","x.travel","x.travel","x.travel","x.travel"]}

jrse commented 5 years ago

dlog notification plugin

pr 30 00:34:47 imap(t1): Debug: Called process_msg push_notification plugin hook. Apr 30 00:34:47 imap(t1): Debug: Message data: Mailbox [INBOX], UID [1], UIDVALIDITY [1556552541] Apr 30 00:34:47 imap(t1): Debug: FlagsSet: Keyword set [smf.abcdfffff] Apr 30 00:34:47 imap(t1): Debug: FlagsSet: Keyword set [smf.abcdfffff] Apr 30 00:34:47 imap(t1): Debug: FlagsSet: Keyword set [smf.abcdfffff] Apr 30 00:34:47 imap(t1): Debug: Called end_txn push_notification plugin hook.

jrse commented 5 years ago

keywords are set in: src/plugins/push-notification/push-notification-event-flagsset.c

./src/plugins/push-notification/push-notification-triggers.c

jrse commented 5 years ago

static void push_notification_event_flagsset_keywords_event( struct push_notification_txn ptxn, struct push_notification_event_config ec, struct push_notification_txn_msg msg, struct mail mail, const char const old_keywords) { struct push_notification_event_flagsset_data data; const char k, const keywords, const op;

data = push_notification_event_flagsset_get_data(ptxn, msg, ec);
keywords = mail_get_keywords(mail);

for (; *keywords != NULL; keywords++) {
    for (op = old_keywords; *op != NULL; op++) {
        if (strcmp(*keywords, *op) == 0) {
            break;
        }
    }

    if (*op == NULL) {
        k = p_strdup(ptxn->pool, *keywords);
        array_append(&data->keywords_set, &k, 1);
    }
}

}

jrse commented 5 years ago

/src/plugins/push-notification/push-notification-txn-msg.c: push_notification_txn_msg_end(struct push_notification_txn ptxn, struct mail_transaction_commit_changes changes)

triggers the process_event notification hook, but only once!

jrse commented 5 years ago

struct push_notification_txn_msg push_notification_txn_msg_create(struct push_notification_txn txn, struct mail *mail)
-> adds the push_notification msg to the hash_table used in (push_notification_txn_msg_end)

=> this function is only called once to create the message. the other calls deliver the created message.

jrse commented 5 years ago

looks like a bug in dovecot:

the function assumes that each message has a different txn->t->save_count, but this is not the case. txn->t->save_count stays equal for each message. using e.g. mail->seq as hash_table key to insert and lookup the msg, we create and process separate message for each msg.


struct push_notification_txn_msg *
push_notification_txn_msg_create(struct push_notification_txn *txn,
                                 struct mail *mail)
{
    struct push_notification_txn_msg *msg = NULL;

    if (hash_table_is_created(txn->messages)) {
        msg = hash_table_lookup(txn->messages,
                                POINTER_CAST(txn->t->save_count + 1));
        i_debug("hash table lookup called msg is %lu msg_seq = %d, uid = %d",msg,txn->t->save_count+1, mail->uid);
    } else {
        hash_table_create_direct(&txn->messages, txn->pool, 4);
    }

    if (msg == NULL) {
        msg = p_new(txn->pool, struct push_notification_txn_msg, 1);
        msg->mailbox = mailbox_get_vname(mail->box);
        /* Save sequence number - used to determine UID later. */
        msg->seq = txn->t->save_count;
        msg->uid = mail->uid;
        i_debug("adding msg uid(%d) to hash_table msg_seq = %d, mail->uid %d",msg->uid,txn->t->save_count +1, mail->uid);
        hash_table_insert(txn->messages, POINTER_CAST(txn->t->save_count + 1),
                          msg);
    }

    return msg;
}
jrse commented 5 years ago

This bug seems to be fixed in 2.3.5