{"id":17470721,"url":"https://github.com/matsumotory/dovecot-mruby-plugin","last_synced_at":"2025-04-30T08:24:45.771Z","repository":{"id":140249468,"uuid":"98559134","full_name":"matsumotory/dovecot-mruby-plugin","owner":"matsumotory","description":"Programmable IMAP Server Scripting with mruby","archived":false,"fork":false,"pushed_at":"2018-02-02T17:03:14.000Z","size":1632,"stargazers_count":30,"open_issues_count":0,"forks_count":1,"subscribers_count":4,"default_branch":"master","last_synced_at":"2024-10-18T18:17:15.030Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/matsumotory.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2017-07-27T16:35:12.000Z","updated_at":"2021-09-08T23:57:36.000Z","dependencies_parsed_at":"2024-02-04T21:19:30.476Z","dependency_job_id":null,"html_url":"https://github.com/matsumotory/dovecot-mruby-plugin","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/matsumotory%2Fdovecot-mruby-plugin","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/matsumotory%2Fdovecot-mruby-plugin/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/matsumotory%2Fdovecot-mruby-plugin/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/matsumotory%2Fdovecot-mruby-plugin/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/matsumotory","download_url":"https://codeload.github.com/matsumotory/dovecot-mruby-plugin/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251667548,"owners_count":21624519,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-18T16:01:48.917Z","updated_at":"2025-04-30T08:24:45.739Z","avatar_url":"https://github.com/matsumotory.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# dovecot-mruby-plugin [![Build Status](https://travis-ci.org/matsumotory/dovecot-mruby-plugin.svg?branch=master)](https://travis-ci.org/matsumotory/dovecot-mruby-plugin)\n\ndovecot included dovecot-mruby-plugin is a programmable IMAP/POP server scripting with mruby like [ngx_mruby](https://github.com/matsumotory/ngx_mruby) for nginx, [mod_mruby](https://github.com/matsumotory/mod_mruby) for apache httpd and [trusterd](https://github.com/matsumotory/trusterd) for HTTP/2 mruby Web server. Also [pmilter](https://github.com/matsumotory/pmilter) is a programmable Milter server scripting with mruby for SMTP server. \n\n## Quick Build and Install\n\n```\nmake setup\nmake\ncp -p dovecot/target/lib/dovecot/lib95_imap_mruby_plugin.so{,1} /path/to/plugin-dir/.\n```\n\n## Test\n\n- dovecot download and install, then test dovecot-mruby-plugin in current directory\n\n```\nmake setup\nmake test\n```\n\n## IMAP command register using mruby\n\n- /path/to/command_register.rb\n\n```ruby\n# Register new commands\n%w(\n\nmatsumotory\ntest\n\n).each do |cmd|\n  Dovecot::IMAP.command_register(cmd) do |args|\n    Dovecot::IMAP.send_line \"Hi, #{Dovecot::IMAP.username}\"\n    if cmd == Dovecot::IMAP.username\n      Dovecot::IMAP.send_line \"You are me.\"\n    else\n      Dovecot::IMAP.send_line \"I am #{cmd}.  Not you with #{args}\"\n    end\n  end\nend\n\n# Register CAP command which run CAPABILITY command\nDovecot::IMAP.alias_command_register(\"CAP\") do\n  Dovecot::IMAP.send_line \"execute CAPABILITY commands\"\n  Dovecot::IMAP.capability\nend\n\nDovecot::IMAP.alias_command_register(\"LIST_ALIAS\") do\n  Dovecot::IMAP.send_line \"alias LIST commands\"\n  Dovecot::IMAP.list\nend\n```\n\n### start dovecot with `DOVECOT_MRUBY_INIT_PATH` env\n\n- dovecot.conf\n\n```\nimport_environment = DOVECOT_MRUBY_INIT_PATH\n```\n\n- start dovecot\n\n```bash\nDOVECOT_MRUBY_INIT_PATH=/path/to/command_register.rb ./dovecot/target/sbin/dovecot \\\n\t-c ./dovecot/configuration/dovecot.conf\n```\n\n- telnet example\n\n```\n$ telnet 127.0.0.1 6070\nTrying 127.0.0.1...\nConnected to 127.0.0.1.\nEscape character is '^]'.\n* OK [CAPABILITY ...] Dovecot ready.\n\n1 login test testPassword\n1 OK [CAPABILITY ...] Logged in\n\n1 matsumotory hoge 1\n* matsumotory Hi, test\n* matsumotory I am matsumotory.  Not you with [\"hoge\", \"1\"]\n1 OK matsumotory completed (0.001 + 0.000 secs).\n\n1 test \n* test Hi, test\n* test You are me.\n1 OK test completed (0.001 + 0.000 secs).\n\n1 matsumotory \n* matsumotory Hi, test\n* matsumotory I am matsumotory.  Not you with []\n1 OK matsumotory completed (0.001 + 0.000 secs).\n\n1 cap\n* cap execute CAPABILITY commands\n* CAPABILITY IMAP4rev1 LITERAL+ SASL-IR ...\n1 OK Capability completed (0.001 + 0.000 secs).\n\n1 list \"\" *\n* LIST (\\HasNoChildren) \"/\" INBOX\n1 OK List completed (0.001 + 0.000 secs).\n\n1 list_alias \"\" *\n* list_alias alias LIST commands\n* LIST (\\HasNoChildren) \"/\" INBOX\n1 OK List completed (0.001 + 0.000 secs).\n\n1 logout\n* BYE Logging out\n1 OK Logout completed (0.001 + 0.000 secs).\n\nConnection closed by foreign host.\n```\n\n## Pre or Post command hook using mruby\n\n- `conf.d/95-mruby.conf`\n\ncallback Ruby scripts on pre and post each IMAP commands.\n\n```\nprotocol imap {\n  mail_plugins = $mail_plugins imap_mruby\n}\n\nplugin {\n  #\n  # mruby_pre_${command name} = '${Ruby code}'\n  # mruby_post_${command name} = '${Ruby code}'\n  # mruby_pre_${command name}_path = /path/to/pre_code.rb\n  # mruby_post_${command name}_path = /path/to/post_code.rb\n  #\n  # support the following commands\n  #\n  # select examine create delete rename subscribe unsubscribe list rlist lsub rlsub\n  # status check close append expunge search fetch store copy uid noop capability idle\n  # namespace getquota setquota getquotaroot\n\n  mruby_pre_capability = '\"pre #{Dovecot::IMAP.command_name}\"'\n  mruby_post_capability = '\"post #{Dovecot::IMAP.command_name}\"'\n\n  # mruby_pre_capability_path = /tmp/a.rb\n  # mruby_post_capability_path = /tmp/a.rb\n}\n```\n\n### dovcot start and watching log\n\n- telnet\n\n```\n$ telnet 127.0.0.1 6070\nTrying 127.0.0.1...\nConnected to 127.0.0.1.\nEscape character is '^]'.\n* OK [CAPABILITY ...] Dovecot ready.\n\n1 login test testPassword\n1 OK [CAPABILITY ...] Logged in\n\n1 capability\n* CAPABILITY IMAP4rev1 ...\n1 OK Capability completed (0.002 + 0.000 + 0.001 secs).\n```\n\n- logging\n\n```\nAug 15 10:14:39 imap-login: Info: Login: user=\u003ctest\u003e, method=PLAIN, rip=127.0.0.1, lip=127.0.0.1, mpid=29724, secured, session=\u003cJZILDMhW1L5/AAAB\u003e\nAug 15 10:14:39 imap(test): Debug: Loading modules from directory: /home/ubuntu/DEV/dovecot-mruby-plugin/dovecot/target/lib/dovecot\nAug 15 10:14:39 imap(test): Debug: Module loaded: /home/ubuntu/DEV/dovecot-mruby-plugin/dovecot/target/lib/dovecot/lib10_quota_plugin.so\nAug 15 10:14:39 imap(test): Debug: Module loaded: /home/ubuntu/DEV/dovecot-mruby-plugin/dovecot/target/lib/dovecot/lib15_notify_plugin.so\nAug 15 10:14:39 imap(test): Debug: Module loaded: /home/ubuntu/DEV/dovecot-mruby-plugin/dovecot/target/lib/dovecot/lib20_fts_plugin.so\nAug 15 10:14:39 imap(test): Debug: Module loaded: /home/ubuntu/DEV/dovecot-mruby-plugin/dovecot/target/lib/dovecot/lib20_mail_log_plugin.so\nAug 15 10:14:39 imap(test): Debug: Module loaded: /home/ubuntu/DEV/dovecot-mruby-plugin/dovecot/target/lib/dovecot/lib20_zlib_plugin.so\nAug 15 10:14:39 imap(test): Debug: Module loaded: /home/ubuntu/DEV/dovecot-mruby-plugin/dovecot/target/lib/dovecot/lib95_imap_mruby_plugin.so\nAug 15 10:14:39 imap(test): Debug: Added userdb setting: plugin/scrambler_plain_password=\u003chidden\u003e\nAug 15 10:14:39 imap(test): Info: code-path: /home/ubuntu/DEV/dovecot-mruby-plugin/dovecot/configuration/mruby_handler/command_register.rb\nAug 15 10:14:39 imap(test): Info: run mruby file at mruby_init, return value: [\"matsumotory\", \"test\"]\nAug 15 10:14:39 imap(test): Debug: Effective uid=1000, gid=1000, home=/home/ubuntu/src/dovecot-2.2.31/build/modules/dovecot/home/test\nAug 15 10:14:39 imap(test): Debug: quota: No quota setting - plugin disabled\nAug 15 10:14:39 imap(test): Debug: Namespace inbox: type=private, prefix=, sep=/, inbox=yes, hidden=no, list=yes, subscriptions=yes location=mdbox:~/mail\nAug 15 10:14:39 imap(test): Debug: fs: root=/home/ubuntu/src/dovecot-2.2.31/build/modules/dovecot/home/test/mail, index=, indexpvt=, control=, inbox=, alt=\nAug 15 10:14:39 imap(test): Debug: fts: No fts setting - plugin disabled\nAug 15 10:14:41 imap(test): Info: mruby_pre_capability inline-code: \"pre #{Dovecot::IMAP.command_name} #{Dovecot::IMAP.username}\"\nAug 15 10:14:41 imap(test): Info: run mruby at mruby_pre_capability, return value: \"pre capability test\"\nAug 15 10:14:41 imap(test): Info: mruby mruby_pre_capability_path hook declined\nAug 15 10:14:41 imap(test): Info: mruby_post_capability inline-code: \"post #{Dovecot::IMAP.command_name} #{Dovecot::IMAP.username}\"\nAug 15 10:14:41 imap(test): Info: run mruby at mruby_post_capability, return value: \"post capability test\"\nAug 15 10:14:41 imap(test): Info: mruby mruby_post_capability_path hook declined\nAug 15 10:14:43 imap(test): Info: Logged out in=22 out=778\n```\n\n## User Case\n\nControl cpu usage of each command with any user.\n\n### limit cpu 30% using mruby-cgroup\n\n- pre.rb\n\n```ruby\nrate = Cgroup::CPU.new \"test\"\n\n# limit cpu 30% usage\nrate.cfs_quota_us = 30000\n\nrate.create\n\nif Dovecot::IMAP.username == \"test\" \u0026\u0026 Dovecot::IMAP.command_name == \"LIST\"\n  rate.attach\nend\n```\n\n- post.rb\n\n```ruby\nrate = Cgroup::CPU.new \"test\"\n\nif Dovecot::IMAP.username == \"test\" \u0026\u0026 Dovecot::IMAP.command_name == \"LIST\"\n  rate.detach\nend\n```\n\n- 95-mruby.conf\n\n```\nprotocol imap {\n  mail_plugins = $mail_plugins imap_mruby\n}\n\nplugin {\n  mruby_pre_list_path = /path/to/pre.rb\n  mruby_post_list_path = /path/to/post.rb\n}\n```\n\n- connect dovecot and run LIST with CPU 100% to 30% limit\n\n```\n29906 ubuntu    20   0   87640   9508   7532 R  29.9  0.1   0:04.46 imap \n```\n\nbuild and test system: special thanks: https://github.com/posteo/scrambler-plugin\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmatsumotory%2Fdovecot-mruby-plugin","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmatsumotory%2Fdovecot-mruby-plugin","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmatsumotory%2Fdovecot-mruby-plugin/lists"}