user icon

Dovecotのpush_notificationを使ってイベントログを取る

前回はDovecotをソースからビルドしてLuaが動くまでをやりました。 今回Luaが大体動く感じになったので、イベントごとのデータを送ります。

Dovecot

10-mail.confは前回のままです。
  • /usr/local/etc/dovecot/conf.d/10-mail.conf
mail_plugins = $mail_plugins quota mail_lua notify push_notification push_notification_lua
  • /usr/local/etc/dovecot/conf.d/90-plugin.conf
plugin {
  push_notification_driver = lua:file=/home/vmb/dovecot-push.lua
  push_lua_url = http://localhost/push.php
}
  • /home/vmb/dovecot-push.lua
#!/usr/bin/lua
local client = nil
local json = require "json"

function script_init()
  client = dovecot.http.client({debug=True, timeout=10000})
  return 0
end

local function table_get(t, k, d)
  return t[k] or d
end

function datapost(url, ctx, data)
  local user = ctx.user
  data.username = table_get(user, "username", "")
  data.home = table_get(user, "home", "")
  data.service = table_get(user, "service", "")
  data.session_id = table_get(user, "session_id", "")
  --
  local rq = client:request({url=url, method="POST"})
  rq:add_header("content-type", "application/json")
  rq:set_payload(json.encode(data))
  local code = rq:submit():status()
  return code
end

-- start
function dovecot_lua_notify_begin_txn(user)
  return {user=user, event=dovecot.event(), ep=user:plugin_getenv("push_lua_url"), states={}, messages={}}
end

-- mailbox
function dovecot_lua_notify_event_mailbox_create(ctx, data)
  datapost(ctx.ep, ctx, data)
end
function dovecot_lua_notify_event_mailbox_delete(ctx, data)
  datapost(ctx.ep, ctx, data)
end
function dovecot_lua_notify_event_mailbox_rename(ctx, data)
  datapost(ctx.ep, ctx, data)
end
function dovecot_lua_notify_event_mailbox_subscribe(ctx, data)
  datapost(ctx.ep, ctx, data)
end
function dovecot_lua_notify_event_mailbox_unsubscribe(ctx, data)
  datapost(ctx.ep, ctx, data)
end

-- message
function dovecot_lua_notify_event_message_new(ctx, data)
  datapost(ctx.ep, ctx, data)
end
function dovecot_lua_notify_event_message_append(ctx, data)
  datapost(ctx.ep, ctx, data)
end
function dovecot_lua_notify_event_message_read(ctx, data)
  datapost(ctx.ep, ctx, data)
end
function dovecot_lua_notify_event_message_trash(ctx, data)
  datapost(ctx.ep, ctx, data)
end
function dovecot_lua_notify_event_message_expunge(ctx, data)
  datapost(ctx.ep, ctx, data)
end

-- flags
function dovecot_lua_notify_event_flags_set(ctx, data)
  datapost(ctx.ep, ctx, data)
end
function dovecot_lua_notify_event_flags_clear(ctx, data)
  datapost(ctx.ep, ctx, data)
end

-- end
function dovecot_lua_notify_end_txn(ctx)
  -- nothing
end
各function(mailbox, message, flags)を定義する事で、イベントごとに実行されるようです。イベントごとの差異を気にせずに済むよう、全部送ってしまいます。
最初はjson.encode()でなくhttp_util.dict_to_query()を使っていたんですが、string型以外を受け付けない(numberでさえ駄目)事と、一次元配列に加工し直す必要が有って、一応動きはしたもののどこかで引っかかりそうなので、諦めて捨てました。

Web側

DocumentRoot下にpush.phpを作ります。
  • http://localhost/push.php
<?php
// data
$content = file_get_contents('php://input');
if($_SERVER["CONTENT_TYPE"] == "application/json"){
    $Data = json_decode($content, true);
    $json = $content;
}else{
    $Data = $_GET + $_POST;
    $json = json_encode($Data);
}
// log
$res = false;
if(isset($Data["name"], $Data["username"], $Data["mailbox"])){
    $con = @pg_connect("user=mail dbname=mail password=testpass");
    if($con){
        $INSQL = array("eventname"=>$Data["name"], "username"=>$Data["username"], "mailbox"=>$Data["mailbox"], "data"=>$json);
        $res = pg_insert($con, "notifications", $INSQL);
    }
}
Luaから送るのはJSON形式のデータのため、php://inputで受けてjson_decodeしています。
(CONTENT_TYPEで分ける必要は無いですが、どちらでも受けられるようにはしています)

PostgreSQL

イベント保存用のテーブルを作成します。
CREATE TABLE notifications (
    id bigserial PRIMARY KEY,
    eventname text NOT NULL,
    mailbox text,
    username text,
    data text,
    created timestamp without time zone DEFAULT now()
);
RoundCubeでログインして、適当にフラグを外したりメールを移動させたりして、psqlコマンドでデータを見てみます。
mail=> select eventname,username,mailbox,created from notifications ORDER BY created;
   eventname    |          username          | mailbox |          created           
----------------+----------------------------+---------+----------------------------
 FlagsClear     | aikawa@virtual.localdomain | INBOX   | 2023-01-26 14:21:23.636366
 MessageAppend  | aikawa@virtual.localdomain | INBOX   | 2023-01-26 14:21:37.172475
 MessageExpunge | aikawa@virtual.localdomain | Test    | 2023-01-26 14:21:37.182596
これでデータをDBに記録出来る事が確認出来ました。
メールを移動させると、MessageAppend、次にMessageExpungeが発生していました。一つの動作で複数の通知が飛ぶ事も有るようです。
Facebooktwitterlinkedintumblrmail
名前
E-mail
URL
コメント

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)