<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  </head>
  <body>
    <p>Some answers to my questions, a first version of my script and
      more questions ;)<br>
    </p>
    <p>Am 03.08.20 um 18:15 schrieb Ralf Becker:</p>
    <blockquote type="cite"
      cite="mid:e251229e-9e14-9ac4-a6cd-c17257887368@egroupware.org">
      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
      Currently looking into the following questions:
      <div class="moz-cite-prefix"><br>
      </div>
      <div class="moz-cite-prefix">- can I get the rfc 5423 type of
        event somehow (obviously I can set it on the event myself
        depending of the function called)</div>
    </blockquote>
    event.name<br>
    <blockquote type="cite"
      cite="mid:e251229e-9e14-9ac4-a6cd-c17257887368@egroupware.org">
      <div class="moz-cite-prefix">- looking at the example code, it
        looks like it can be called for multiple messages, when does
        that happen (LMTP send more then one)<br>
      </div>
    </blockquote>
    <p>still no idea, maybe Ake?</p>
    <p>I noticed that some events have the same uid-validity, are the
      from a single transaction, eg. I delete my Trash?<br>
    </p>
    <blockquote type="cite"
      cite="mid:e251229e-9e14-9ac4-a6cd-c17257887368@egroupware.org">
      <div class="moz-cite-prefix"> </div>
      <div class="moz-cite-prefix">- why is the mailbox status put into
        an other structure and send with a different notifiction</div>
      <div class="moz-cite-prefix">- does anyone have a code snippet to
        send a JSON encoded message (probably easy to figure out looking
        at Lua docu)</div>
    </blockquote>
    <p>these two I managed to solve im my current version of the script,
      which also support now all message event types:</p>
    <pre style="background-color:#ffffff;color:#000000;font-family:'JetBrains Mono',monospace;font-size:9,8pt;"><span style="color:#808080;font-style:italic;">-- To use
</span><span style="color:#808080;font-style:italic;">--
</span><span style="color:#808080;font-style:italic;">-- plugin {
</span><span style="color:#808080;font-style:italic;">--  push_notification_driver = lua:file=/etc/dovecot/dovecot-push.lua
</span><span style="color:#808080;font-style:italic;">--  push_lua_url = <a class="moz-txt-link-freetext" href="http://push.notification.server/handler">http://push.notification.server/handler</a>
</span><span style="color:#808080;font-style:italic;">-- }
</span><span style="color:#808080;font-style:italic;">--
</span><span style="color:#808080;font-style:italic;">-- server is sent a PUT message with JSON body like push_notification_driver = ox:url=<push_lua_url> user_from_metadata
</span><span style="color:#808080;font-style:italic;">--
</span><span style="color:#808080;font-style:italic;">
</span><span style="color:#000080;font-weight:bold;">local </span>http = <span style="color:#cc542e;">require </span><span style="color:#008000;font-weight:bold;">"socket.http"
</span><span style="color:#000080;font-weight:bold;">local </span>ltn12 = <span style="color:#cc542e;">require </span><span style="color:#008000;font-weight:bold;">"ltn12"
</span><span style="color:#808080;font-style:italic;">-- luarocks install json-lua
</span><span style="color:#000080;font-weight:bold;">local </span>json = <span style="color:#cc542e;">require </span><span style="color:#008000;font-weight:bold;">"JSON"
</span><span style="color:#008000;font-weight:bold;">
</span><span style="color:#000080;font-weight:bold;">function </span><span style="color:#660e7a;font-style:italic;">table_get</span>(<span style="color:#006666;font-weight:bold;">t</span>, <span style="color:#006666;font-weight:bold;">k</span>, <span style="color:#006666;font-weight:bold;">d</span>)
  <span style="color:#000080;font-weight:bold;">return </span><span style="color:#006666;font-weight:bold;">t</span>[<span style="color:#006666;font-weight:bold;">k</span>] <span style="color:#000080;font-weight:bold;">or </span><span style="color:#006666;font-weight:bold;">d
</span><span style="color:#000080;font-weight:bold;">end
</span><span style="color:#000080;font-weight:bold;">
</span><span style="color:#000080;font-weight:bold;">function </span><span style="color:#660e7a;font-style:italic;">script_init</span>()
  <span style="color:#000080;font-weight:bold;">return </span><span style="color:#0000ff;">0
</span><span style="color:#000080;font-weight:bold;">end
</span><span style="color:#000080;font-weight:bold;">
</span><span style="color:#000080;font-weight:bold;">function </span><span style="color:#660e7a;font-style:italic;">dovecot_lua_notify_begin_txn</span>(<span style="color:#006666;font-weight:bold;">user</span>)
    <span style="color:#000080;font-weight:bold;">local </span>meta = <span style="color:#006666;font-weight:bold;">user</span>:metadata_get(<span style="color:#008000;font-weight:bold;">"/private/vendor/vendor.dovecot/http-notify"</span>)
    <span style="color:#000080;font-weight:bold;">return </span>{user=<span style="color:#006666;font-weight:bold;">user</span>, event=<span style="color:#660e7a;font-style:italic;">dovecot</span>.<span style="font-style:italic;">event</span>(), ep=<span style="color:#006666;font-weight:bold;">user</span>:plugin_getenv(<span style="color:#008000;font-weight:bold;">"push_lua_url"</span>), messages={}, meta=meta}
<span style="color:#000080;font-weight:bold;">end
</span><span style="color:#000080;font-weight:bold;">
</span><span style="color:#000080;font-weight:bold;">function </span><span style="color:#660e7a;font-style:italic;">dovecot_lua_notify_event_message_new</span>(<span style="color:#006666;font-weight:bold;">ctx</span>, <span style="color:#006666;font-weight:bold;">event</span>)
    <span style="color:#808080;font-style:italic;">-- check if there is a push token registered
</span><span style="color:#808080;font-style:italic;">    </span><span style="color:#000080;font-weight:bold;">if </span>(<span style="color:#006666;font-weight:bold;">ctx</span>.meta == <span style="color:#d700ff;">nil </span><span style="color:#000080;font-weight:bold;">or </span><span style="color:#006666;font-weight:bold;">ctx</span>.meta == <span style="color:#008000;font-weight:bold;">''</span>) <span style="color:#000080;font-weight:bold;">then
</span><span style="color:#000080;font-weight:bold;">    return
</span><span style="color:#000080;font-weight:bold;">    end
</span><span style="color:#000080;font-weight:bold;">    </span><span style="color:#808080;font-style:italic;">-- get mailbox status
</span><span style="color:#808080;font-style:italic;">    </span><span style="color:#000080;font-weight:bold;">local </span>mbox = <span style="color:#006666;font-weight:bold;">ctx</span>.user:mailbox(<span style="color:#006666;font-weight:bold;">event</span>.mailbox)
    mbox:sync()
    <span style="color:#000080;font-weight:bold;">local </span>status = mbox:status(<span style="color:#660e7a;font-style:italic;">dovecot</span>.storage.STATUS_RECENT, <span style="color:#660e7a;font-style:italic;">dovecot</span>.storage.STATUS_UNSEEN, <span style="color:#660e7a;font-style:italic;">dovecot</span>.storage.STATUS_MESSAGES)
    mbox:free()
    <span style="color:#cc542e;">table</span>.insert(<span style="color:#006666;font-weight:bold;">ctx</span>.messages, {
      user = <span style="color:#006666;font-weight:bold;">ctx</span>.meta,
      [<span style="color:#008000;font-weight:bold;">"imap-uidvalidity"</span>] = <span style="color:#006666;font-weight:bold;">event</span>.uid_validity,
      [<span style="color:#008000;font-weight:bold;">"imap-uid"</span>] = <span style="color:#006666;font-weight:bold;">event</span>.uid,
      folder = <span style="color:#006666;font-weight:bold;">event</span>.mailbox,
      event = <span style="color:#006666;font-weight:bold;">event</span>.name,
      from = <span style="color:#006666;font-weight:bold;">event</span>.from,
      subject = <span style="color:#006666;font-weight:bold;">event</span>.subject,
      snippet = <span style="color:#006666;font-weight:bold;">event</span>.snippet,
      unseen = status.unseen
    })
<span style="color:#000080;font-weight:bold;">end
</span><span style="color:#000080;font-weight:bold;">
</span><span style="color:#000080;font-weight:bold;">function </span><span style="color:#660e7a;font-style:italic;">dovecot_lua_notify_event_message_append</span>(<span style="color:#006666;font-weight:bold;">ctx</span>, <span style="color:#006666;font-weight:bold;">event</span>)
  <span style="color:#660e7a;font-style:italic;">dovecot_lua_notify_event_message_new</span>(<span style="color:#006666;font-weight:bold;">ctx</span>, <span style="color:#006666;font-weight:bold;">event</span>)
<span style="color:#000080;font-weight:bold;">end
</span><span style="color:#000080;font-weight:bold;">
</span><span style="color:#000080;font-weight:bold;">function </span><span style="color:#660e7a;font-style:italic;">dovecot_lua_notify_event_message_read</span>(<span style="color:#006666;font-weight:bold;">ctx</span>, <span style="color:#006666;font-weight:bold;">event</span>)
    <span style="color:#808080;font-style:italic;">-- check if there is a push token registered
</span><span style="color:#808080;font-style:italic;">    </span><span style="color:#000080;font-weight:bold;">if </span>(<span style="color:#006666;font-weight:bold;">ctx</span>.meta == <span style="color:#d700ff;">nil </span><span style="color:#000080;font-weight:bold;">or </span><span style="color:#006666;font-weight:bold;">ctx</span>.meta == <span style="color:#008000;font-weight:bold;">''</span>) <span style="color:#000080;font-weight:bold;">then
</span><span style="color:#000080;font-weight:bold;">        return
</span><span style="color:#000080;font-weight:bold;">    end
</span><span style="color:#000080;font-weight:bold;">    </span><span style="color:#808080;font-style:italic;">-- get mailbox status
</span><span style="color:#808080;font-style:italic;">    </span><span style="color:#000080;font-weight:bold;">local </span>mbox = <span style="color:#006666;font-weight:bold;">ctx</span>.user:mailbox(<span style="color:#006666;font-weight:bold;">event</span>.mailbox)
    mbox:sync()
    <span style="color:#000080;font-weight:bold;">local </span>status = mbox:status(<span style="color:#660e7a;font-style:italic;">dovecot</span>.storage.STATUS_RECENT, <span style="color:#660e7a;font-style:italic;">dovecot</span>.storage.STATUS_UNSEEN, <span style="color:#660e7a;font-style:italic;">dovecot</span>.storage.STATUS_MESSAGES)
    mbox:free()
    <span style="color:#cc542e;">table</span>.insert(<span style="color:#006666;font-weight:bold;">ctx</span>.messages, {
        user = <span style="color:#006666;font-weight:bold;">ctx</span>.meta,
        [<span style="color:#008000;font-weight:bold;">"imap-uidvalidity"</span>] = <span style="color:#006666;font-weight:bold;">event</span>.uid_validity,
        [<span style="color:#008000;font-weight:bold;">"imap-uid"</span>] = <span style="color:#006666;font-weight:bold;">event</span>.uid,
        folder = <span style="color:#006666;font-weight:bold;">event</span>.mailbox,
        event = <span style="color:#006666;font-weight:bold;">event</span>.name,
        unseen = status.unseen
    })
<span style="color:#000080;font-weight:bold;">end
</span><span style="color:#000080;font-weight:bold;">
</span><span style="color:#000080;font-weight:bold;">function </span><span style="color:#660e7a;font-style:italic;">dovecot_lua_notify_event_message_trash</span>(<span style="color:#006666;font-weight:bold;">ctx</span>, <span style="color:#006666;font-weight:bold;">event</span>)
    <span style="color:#660e7a;font-style:italic;">dovecot_lua_notify_event_message_read</span>(<span style="color:#006666;font-weight:bold;">ctx</span>, <span style="color:#006666;font-weight:bold;">event</span>)
<span style="color:#000080;font-weight:bold;">end
</span><span style="color:#000080;font-weight:bold;">
</span><span style="color:#000080;font-weight:bold;">function </span><span style="color:#660e7a;font-style:italic;">dovecot_lua_notify_event_message_expunge</span>(<span style="color:#006666;font-weight:bold;">ctx</span>, <span style="color:#006666;font-weight:bold;">event</span>)
    <span style="color:#660e7a;font-style:italic;">dovecot_lua_notify_event_message_read</span>(<span style="color:#006666;font-weight:bold;">ctx</span>, <span style="color:#006666;font-weight:bold;">event</span>)
<span style="color:#000080;font-weight:bold;">end
</span><span style="color:#000080;font-weight:bold;">
</span><span style="color:#000080;font-weight:bold;">function </span><span style="color:#660e7a;font-style:italic;">dovecot_lua_notify_event_flags_set</span>(<span style="color:#006666;font-weight:bold;">ctx</span>, <span style="color:#006666;font-weight:bold;">event</span>)
    <span style="color:#808080;font-style:italic;">-- check if there is a push token registered
</span><span style="color:#808080;font-style:italic;">    </span><span style="color:#000080;font-weight:bold;">if </span>(<span style="color:#006666;font-weight:bold;">ctx</span>.meta == <span style="color:#d700ff;">nil </span><span style="color:#000080;font-weight:bold;">or </span><span style="color:#006666;font-weight:bold;">ctx</span>.meta == <span style="color:#008000;font-weight:bold;">''</span>) <span style="color:#000080;font-weight:bold;">then
</span><span style="color:#000080;font-weight:bold;">        return
</span><span style="color:#000080;font-weight:bold;">    end
</span><span style="color:#000080;font-weight:bold;">    </span><span style="color:#cc542e;">table</span>.insert(<span style="color:#006666;font-weight:bold;">ctx</span>.messages, {
        user = <span style="color:#006666;font-weight:bold;">ctx</span>.meta,
        [<span style="color:#008000;font-weight:bold;">"imap-uidvalidity"</span>] = <span style="color:#006666;font-weight:bold;">event</span>.uid_validity,
        [<span style="color:#008000;font-weight:bold;">"imap-uid"</span>] = <span style="color:#006666;font-weight:bold;">event</span>.uid,
        folder = <span style="color:#006666;font-weight:bold;">event</span>.mailbox,
        event = <span style="color:#006666;font-weight:bold;">event</span>.name,
        flags = <span style="color:#006666;font-weight:bold;">event</span>.flags,
        [<span style="color:#008000;font-weight:bold;">"keywords-set"</span>] = <span style="color:#006666;font-weight:bold;">event</span>.keywords_set
    })
<span style="color:#000080;font-weight:bold;">end
</span><span style="color:#000080;font-weight:bold;">
</span><span style="color:#000080;font-weight:bold;">function </span><span style="color:#660e7a;font-style:italic;">dovecot_lua_notify_event_flags_clear</span>(<span style="color:#006666;font-weight:bold;">ctx</span>, <span style="color:#006666;font-weight:bold;">event</span>)
    <span style="color:#808080;font-style:italic;">-- check if there is a push token registered
</span><span style="color:#808080;font-style:italic;">    </span><span style="color:#000080;font-weight:bold;">if </span>(<span style="color:#006666;font-weight:bold;">ctx</span>.meta == <span style="color:#d700ff;">nil </span><span style="color:#000080;font-weight:bold;">or </span><span style="color:#006666;font-weight:bold;">ctx</span>.meta == <span style="color:#008000;font-weight:bold;">''</span>) <span style="color:#000080;font-weight:bold;">then
</span><span style="color:#000080;font-weight:bold;">        return
</span><span style="color:#000080;font-weight:bold;">    end
</span><span style="color:#000080;font-weight:bold;">    </span><span style="color:#cc542e;">table</span>.insert(<span style="color:#006666;font-weight:bold;">ctx</span>.messages, {
        user = <span style="color:#006666;font-weight:bold;">ctx</span>.meta,
        [<span style="color:#008000;font-weight:bold;">"imap-uidvalidity"</span>] = <span style="color:#006666;font-weight:bold;">event</span>.uid_validity,
        [<span style="color:#008000;font-weight:bold;">"imap-uid"</span>] = <span style="color:#006666;font-weight:bold;">event</span>.uid,
        folder = <span style="color:#006666;font-weight:bold;">event</span>.mailbox,
        event = <span style="color:#006666;font-weight:bold;">event</span>.name,
        flags = <span style="color:#006666;font-weight:bold;">event</span>.flags,
        [<span style="color:#008000;font-weight:bold;">"keywords-clear"</span>] = <span style="color:#006666;font-weight:bold;">event</span>.keywords_clear,
        [<span style="color:#008000;font-weight:bold;">"keywords-old"</span>] = <span style="color:#006666;font-weight:bold;">event</span>.keywords_old
    })
<span style="color:#000080;font-weight:bold;">end
</span><span style="color:#000080;font-weight:bold;">
</span><span style="color:#000080;font-weight:bold;">function </span><span style="color:#660e7a;font-style:italic;">dovecot_lua_notify_end_txn</span>(<span style="color:#006666;font-weight:bold;">ctx</span>)
    <span style="color:#808080;font-style:italic;">-- report all states
</span><span style="color:#808080;font-style:italic;">    </span><span style="color:#000080;font-weight:bold;">for </span><span style="color:#006666;font-weight:bold;">i</span>,<span style="color:#006666;font-weight:bold;">msg </span><span style="color:#000080;font-weight:bold;">in </span><span style="color:#cc542e;">ipairs</span>(<span style="color:#006666;font-weight:bold;">ctx</span>.messages) <span style="color:#000080;font-weight:bold;">do
</span><span style="color:#000080;font-weight:bold;">    local </span>e = <span style="color:#660e7a;font-style:italic;">dovecot</span>.<span style="font-style:italic;">event</span>(<span style="color:#006666;font-weight:bold;">ctx</span>.event)
    e:set_name(<span style="color:#008000;font-weight:bold;">"lua_notify_mail_finished"</span>)
    <span style="color:#660e7a;font-style:italic;">reqbody </span>= <span style="font-weight:bold;font-style:italic;">json</span>:encode(<span style="color:#006666;font-weight:bold;">msg</span>)
    e:log_debug(<span style="color:#006666;font-weight:bold;">ctx</span>.ep .. <span style="color:#008000;font-weight:bold;">" - sending " </span>.. <span style="color:#660e7a;font-style:italic;">reqbody</span>)
    <span style="color:#660e7a;font-style:italic;">res</span>, <span style="color:#660e7a;font-style:italic;">code </span>= <span style="font-weight:bold;font-style:italic;">http</span>.<span style="font-style:italic;">request</span>({
        method = <span style="color:#008000;font-weight:bold;">"PUT"</span>,
        url = <span style="color:#006666;font-weight:bold;">ctx</span>.ep,
        source = <span style="font-weight:bold;font-style:italic;">ltn12</span>.source.<span style="font-style:italic;">string</span>(<span style="color:#660e7a;font-style:italic;">reqbody</span>),
        headers={
            [<span style="color:#008000;font-weight:bold;">"content-type"</span>] = <span style="color:#008000;font-weight:bold;">"application/json; charset=utf-8"</span>,
            [<span style="color:#008000;font-weight:bold;">"content-length"</span>] = <span style="color:#cc542e;">tostring</span>(#<span style="color:#660e7a;font-style:italic;">reqbody</span>)
        }
    })
    e:add_int(<span style="color:#008000;font-weight:bold;">"result_code"</span>, <span style="color:#660e7a;font-style:italic;">code</span>)
    e:log_info(<span style="color:#008000;font-weight:bold;">"Mail notify status " </span>.. <span style="color:#cc542e;">tostring</span>(<span style="color:#660e7a;font-style:italic;">code</span>))
    <span style="color:#000080;font-weight:bold;">end
</span><span style="color:#000080;font-weight:bold;">end</span></pre>
    <p><br>
    </p>
    <p>This leads to a couple more questions ;)</p>
    <p>- is there a way (eg. return value) to stop event processing
      already in <span style="color:#660e7a;font-style:italic;">dovecot_lua_notify_begin_txn</span></p>
    <p>- sometimes multiple events are generated, eg. when I read an
      email:</p>
    <p>{"event":"FlagsClear","flags":[],"folder":"INBOX/eGroupWare/calconnect","imap-uid":2275,"imap-uidvalidity":1499767470,"keywords-old":[],"user":"user=5::42;***"}<br>
{"event":"FlagsSet","flags":["\\Seen"],"folder":"INBOX/eGroupWare/calconnect","imap-uid":2275,"imap-uidvalidity":1499767470,"user":"user=5::42;***"}<br>
{"event":"MessageRead","folder":"INBOX/eGroupWare/calconnect","imap-uid":2275,"imap-uidvalidity":1499767470,"unseen":0,"user":"user=5::42;***"}<br>
    </p>
    Ralf<br>
    <br>
    <pre class="moz-signature" cols="72">-- 
Ralf Becker
EGroupware GmbH [<a class="moz-txt-link-abbreviated" href="http://www.egroupware.org">www.egroupware.org</a>]
Handelsregister HRB Kaiserslautern 3587
Geschäftsführer Birgit und Ralf Becker
Leibnizstr. 17, 67663 Kaiserslautern, Germany
Telefon +49 631 31657-0
</pre>
  </body>
</html>