Hi,
I notice that quota domain when using args %d in dictionary isn't honored in mysql during updates and selects when using dovecot 2.3.17+, so I moved my tests to docker environment, because I started using alpine linux and thought it could be musl library problem.
I tested few versions with debian/alpine and after 2.3.17 updates and selects for domain in sql not using domain part, but user@domain.
Maybe I missed some changes in configuration, maybe someone experience this behavior?
User in logs was changed to h.user@example.com.
Configuration
as described in documentation quota = dict:<quota root name>:<username>[:<option>[...]]:<dictionary URI> where username could be %d for supporting domain-wide quotas
quota = dict:user_quota::proxy::sqluserquota quota2 = dict:domain_quota:%d:proxy::sqldomainquota dict { acl = mysql:/etc/dovecot/dovecot-share-folder.conf sqldomainquota = mysql:/etc/dovecot/dovecot-dict-sql-domain.conf sqluserquota = mysql:/etc/dovecot/dovecot-dict-sql-user.conf }
dovecot-dict-sql-domain.conf
map { pattern= priv/quota/storage table= used_domain_quota username_field= domain value_field= bytes } map { pattern= priv/quota/messages table= used_domain_quota username_field= domain value_field= messages }
dovecot-dict-sql-user.conf
map { pattern= priv/quota/storage table= used_quota username_field= username value_field= bytes } map { pattern= priv/quota/messages table= used_quota username_field= username value_field= messages }
Example dump sql table, in real environment with newer dovecot, there was only h.user@example.com and no domain record. *In earlier versions of dovecot there was only domain in this table.*
|//**domain**//|varchar(255)|Nie| |bytes|bigint(20)|Nie|0 |messages|bigint(20)|Nie|0 == Dumping data for table used_domain_quota |h.user@example.com|36000|36000 |example.com|35000|35000
Debug
Doveadm
*In both examples below debug args=example.com seems correct *
Dovecot version 2.3.17+, in this example debian 10 2.3.17 (e2aa53df5b), select with only username.
root@cf801690360c:/# doveadm -D -v quota get -u h.user@example.com Debug: Loading modules from directory: /usr/lib/dovecot/modules/doveadm Debug: Skipping module doveadm_acl_plugin, because dlopen() failed: /usr/lib/dovecot/modules/doveadm/lib10_doveadm_acl_plugin.so: undefined symbol: acl_user_module (this is usually intentional, so just ignore this message) Debug: Skipping module doveadm_quota_plugin, because dlopen() failed: /usr/lib/dovecot/modules/doveadm/lib10_doveadm_quota_plugin.so: undefined symbol: quota_user_module (this is usually intentional, so just ignore this message) Debug: Module loaded: /usr/lib/dovecot/modules/doveadm/lib10_doveadm_sieve_plugin.so Debug: Skipping module doveadm_fts_lucene_plugin, because dlopen() failed: /usr/lib/dovecot/modules/doveadm/lib20_doveadm_fts_lucene_plugin.so: undefined symbol: lucene_index_iter_deinit (this is usually intentional, so just ignore this message) Debug: Skipping module doveadm_fts_plugin, because dlopen() failed: /usr/lib/dovecot/modules/doveadm/lib20_doveadm_fts_plugin.so: undefined symbol: fts_user_get_language_list (this is usually intentional, so just ignore this message) Debug: Skipping module doveadm_mail_crypt_plugin, because dlopen() failed: /usr/lib/dovecot/modules/doveadm/libdoveadm_mail_crypt_plugin.so: undefined symbol: mail_crypt_box_get_pvt_digests (this is usually intentional, so just ignore this message) Nov 27 15:46:31 Debug: Loading modules from directory: /usr/lib/dovecot/modules Nov 27 15:46:31 Debug: Module loaded: /usr/lib/dovecot/modules/lib01_acl_plugin.so Nov 27 15:46:31 Debug: Module loaded: /usr/lib/dovecot/modules/lib10_quota_plugin.so Nov 27 15:46:31 Debug: Module loaded: /usr/lib/dovecot/modules/lib20_mailbox_alias_plugin.so Nov 27 15:46:31 Debug: Loading modules from directory: /usr/lib/dovecot/modules/doveadm Nov 27 15:46:31 Debug: Module loaded: /usr/lib/dovecot/modules/doveadm/lib10_doveadm_acl_plugin.so Nov 27 15:46:31 Debug: Module loaded: /usr/lib/dovecot/modules/doveadm/lib10_doveadm_quota_plugin.so Nov 27 15:46:31 Debug: Skipping module doveadm_fts_lucene_plugin, because dlopen() failed: /usr/lib/dovecot/modules/doveadm/lib20_doveadm_fts_lucene_plugin.so: undefined symbol: lucene_index_iter_deinit (this is usually intentional, so just ignore this message) Nov 27 15:46:31 Debug: Skipping module doveadm_fts_plugin, because dlopen() failed: /usr/lib/dovecot/modules/doveadm/lib20_doveadm_fts_plugin.so: undefined symbol: fts_user_get_language_list (this is usually intentional, so just ignore this message) Nov 27 15:46:31 Debug: Skipping module doveadm_mail_crypt_plugin, because dlopen() failed: /usr/lib/dovecot/modules/doveadm/libdoveadm_mail_crypt_plugin.so: undefined symbol: mail_crypt_box_get_pvt_digests (this is usually intentional, so just ignore this message) Nov 27 15:46:31 doveadm(h.user@example.com)<401><>: Debug: auth-master: userdb lookup(h.user@example.com): Started userdb lookup Nov 27 15:46:31 doveadm(h.user@example.com)<401><>: Debug: auth-master: conn unix:/var/run/dovecot/director-userdb: Connecting Nov 27 15:46:31 doveadm(h.user@example.com)<401><>: Debug: auth-master: conn unix:/var/run/dovecot/director-userdb (pid=1,uid=0): Client connected (fd=9) Nov 27 15:46:31 doveadm(h.user@example.com)<401><>: Debug: auth-master: userdb lookup(h.user@example.com): auth USER input: h.user@example.com home=/home/mail/virtual/data05/example.com/h.user@example.com quota2_rule=*:bytes=10485760000 quota_rule=*:bytes=1048576000 Nov 27 15:46:31 doveadm(h.user@example.com)<401><>: Debug: auth-master: userdb lookup(h.user@example.com): Finished userdb lookup (username=h.user@example.com home=/home/mail/virtual/data05/example.com/h.user@example.com quota2_rule=*:bytes=10485760000 quota_rule=*:bytes=1048576000) Nov 27 15:46:31 doveadm(h.user@example.com)<401><>: Debug: Added userdb setting: plugin/quota2_rule=*:bytes=10485760000 Nov 27 15:46:31 doveadm(h.user@example.com)<401><>: Debug: Added userdb setting: plugin/quota_rule=*:bytes=1048576000 Nov 27 15:46:31 doveadm(h.user@example.com)<401><4l0XONe5ZGWRAQAAQCEzFg>: Debug: Effective uid=101, gid=101, home=/home/mail/virtual/data05/example.com/h.user@example.com Nov 27 15:46:31 doveadm(h.user@example.com)<401><4l0XONe5ZGWRAQAAQCEzFg>: Debug: Home dir not found: /home/mail/virtual/data05/example.com/h.user@example.com Nov 27 15:46:31 doveadm(h.user@example.com)<401><4l0XONe5ZGWRAQAAQCEzFg>: Debug: dict(proxy): dict created (uri=proxy::acl, base_dir=/var/run/dovecot) Nov 27 15:46:31 doveadm(h.user@example.com)<401><4l0XONe5ZGWRAQAAQCEzFg>: Debug: Quota root: name=User Quota backend=dict args=:proxy::sqluserquota Nov 27 15:46:31 doveadm(h.user@example.com)<401><4l0XONe5ZGWRAQAAQCEzFg>: Debug: Quota rule: root=User Quota mailbox=* bytes=1048576000 messages=0 Nov 27 15:46:31 doveadm(h.user@example.com)<401><4l0XONe5ZGWRAQAAQCEzFg>: Debug: Quota warning: bytes=1048576000 (100%) messages=0 reverse=no command=quota-warning 100 h.user@example.com Nov 27 15:46:31 doveadm(h.user@example.com)<401><4l0XONe5ZGWRAQAAQCEzFg>: Debug: Quota warning: bytes=996147200 (95%) messages=0 reverse=no command=quota-warning 95 h.user@example.com Nov 27 15:46:31 doveadm(h.user@example.com)<401><4l0XONe5ZGWRAQAAQCEzFg>: Debug: Quota warning: bytes=943718400 (90%) messages=0 reverse=no command=quota-warning 90 h.user@example.com Nov 27 15:46:31 doveadm(h.user@example.com)<401><4l0XONe5ZGWRAQAAQCEzFg>: Debug: Quota warning: bytes=891289600 (85%) messages=0 reverse=no command=quota-warning 85 h.user@example.com Nov 27 15:46:31 doveadm(h.user@example.com)<401><4l0XONe5ZGWRAQAAQCEzFg>: Debug: Quota grace: root=User Quota bytes=104857600 (10%) Nov 27 15:46:31 doveadm(h.user@example.com)<401><4l0XONe5ZGWRAQAAQCEzFg>: Debug: Quota root: name=Domain Quota backend=dict args=example.com:proxy::sqldomainquota Nov 27 15:46:31 doveadm(h.user@example.com)<401><4l0XONe5ZGWRAQAAQCEzFg>: Debug: Quota rule: root=Domain Quota mailbox=* bytes=10485760000 messages=0 Nov 27 15:46:31 doveadm(h.user@example.com)<401><4l0XONe5ZGWRAQAAQCEzFg>: Debug: Quota grace: root=Domain Quota bytes=1048576000 (10%) Nov 27 15:46:31 doveadm(h.user@example.com)<401><4l0XONe5ZGWRAQAAQCEzFg>: Debug: quota-dict: user=h.user@example.com, uri=proxy::sqluserquota, noenforcing=0 Nov 27 15:46:31 doveadm(h.user@example.com)<401><4l0XONe5ZGWRAQAAQCEzFg>: Debug: dict(proxy): dict created (uri=proxy::sqluserquota, base_dir=/var/run/dovecot) Nov 27 15:46:31 doveadm(h.user@example.com)<401><4l0XONe5ZGWRAQAAQCEzFg>: Debug: quota-dict: user=example.com, uri=proxy::sqldomainquota, noenforcing=0 Nov 27 15:46:31 doveadm(h.user@example.com)<401><4l0XONe5ZGWRAQAAQCEzFg>: Debug: dict(proxy): dict created (uri=proxy::sqldomainquota, base_dir=/var/run/dovecot) Nov 27 15:46:31 doveadm(h.user@example.com)<401><4l0XONe5ZGWRAQAAQCEzFg>: Debug: Namespace : type=private, prefix=, sep=/, inbox=yes, hidden=no, list=yes, subscriptions=yes location=maildir://home/mail/virtual/data05/example.com/h.user@example.com/Maildir/:INDEX=//home/mail/virtual/data05/example.com/h.user@example.com/Maildir/ Nov 27 15:46:31 doveadm(h.user@example.com)<401><4l0XONe5ZGWRAQAAQCEzFg>: Debug: maildir++: root=//home/mail/virtual/data05/example.com/h.user@example.com/Maildir, index=, indexpvt=, control=, inbox=//home/mail/virtual/data05/example.com/h.user@example.com/Maildir, alt= Nov 27 15:46:31 doveadm(h.user@example.com)<401><4l0XONe5ZGWRAQAAQCEzFg>: Debug: acl: initializing backend with data: vfile Nov 27 15:46:31 doveadm(h.user@example.com)<401><4l0XONe5ZGWRAQAAQCEzFg>: Debug: acl: acl username= h.user@example.com Nov 27 15:46:31 doveadm(h.user@example.com)<401><4l0XONe5ZGWRAQAAQCEzFg>: Debug: acl: owner= 1 Nov 27 15:46:31 doveadm(h.user@example.com)<401><4l0XONe5ZGWRAQAAQCEzFg>: Debug: acl vfile: Global ACLs disabled Nov 27 15:46:31 doveadm(h.user@example.com)<401><4l0XONe5ZGWRAQAAQCEzFg>: Debug: Namespace : type=shared, prefix=Shared/%u/, sep=/, inbox=no, hidden=no, list=children, subscriptions=yes location=maildir:%Lh/Maildir/:INDEX=%Lh/Maildir/Shared/%u Nov 27 15:46:31 doveadm(h.user@example.com)<401><4l0XONe5ZGWRAQAAQCEzFg>: Debug: shared: root=/var/run/dovecot, index=, indexpvt=, control=, inbox=, alt= Nov 27 15:46:31 doveadm(h.user@example.com)<401><4l0XONe5ZGWRAQAAQCEzFg>: Debug: acl: initializing backend with data: vfile Nov 27 15:46:31 doveadm(h.user@example.com)<401><4l0XONe5ZGWRAQAAQCEzFg>: Debug: acl: acl username= h.user@example.com Nov 27 15:46:31 doveadm(h.user@example.com)<401><4l0XONe5ZGWRAQAAQCEzFg>: Debug: acl: owner= 0 Nov 27 15:46:31 doveadm(h.user@example.com)<401><4l0XONe5ZGWRAQAAQCEzFg>: Debug: acl vfile: Global ACLs disabled Nov 27 15:46:31 doveadm(h.user@example.com)<401><4l0XONe5ZGWRAQAAQCEzFg>: Debug: quota: quota_over_flag check: quota_over_script unset - skipping Nov 27 15:46:31 doveadm(h.user@example.com)<401><4l0XONe5ZGWRAQAAQCEzFg>: Debug: quota: quota_over_flag check: quota2_over_script unset - skipping Nov 27 15:46:31 doveadm(h.user@example.com): Debug: dict(proxy): Looking up 'priv/quota/storage' Nov 27 15:46:31 doveadm(h.user@example.com): Debug: dict(proxy): Looking up (async) 'priv/quota/storage' Nov 27 15:46:31 doveadm(h.user@example.com): Debug: dict(proxy): conn unix:/var/run/dovecot/dict: Connecting Nov 27 15:46:31 doveadm(h.user@example.com): Debug: dict(proxy): conn unix:/var/run/dovecot/dict (pid=1,uid=0): Client connected (fd=10) Nov 27 15:46:31 doveadm(h.user@example.com): Debug: dict(proxy): Lookup finished for 'priv/quota/storage': found Nov 27 15:46:31 doveadm(h.user@example.com): Debug: dict(proxy): Lookup finished for 'priv/quota/storage': found Nov 27 15:46:31 doveadm(h.user@example.com): Debug: dict(proxy): Looking up 'priv/quota/messages' Nov 27 15:46:31 doveadm(h.user@example.com): Debug: dict(proxy): Looking up (async) 'priv/quota/messages' Nov 27 15:46:31 doveadm(h.user@example.com): Debug: dict(proxy): Lookup finished for 'priv/quota/messages': found Nov 27 15:46:31 doveadm(h.user@example.com): Debug: dict(proxy): Lookup finished for 'priv/quota/messages': found Nov 27 15:46:31 doveadm(h.user@example.com): Debug: dict(proxy): Looking up 'priv/quota/storage' Nov 27 15:46:31 doveadm(h.user@example.com): Debug: dict(proxy): Looking up (async) 'priv/quota/storage' Nov 27 15:46:31 doveadm(h.user@example.com): Debug: dict(proxy): conn unix:/var/run/dovecot/dict: Connecting Nov 27 15:46:31 doveadm(h.user@example.com): Debug: dict(proxy): conn unix:/var/run/dovecot/dict (pid=1,uid=0): Client connected (fd=12) Nov 27 15:46:31 doveadm(h.user@example.com): Debug: dict(proxy): Lookup finished for 'priv/quota/storage': found Nov 27 15:46:31 doveadm(h.user@example.com): Debug: dict(proxy): Lookup finished for 'priv/quota/storage': found Nov 27 15:46:31 doveadm(h.user@example.com): Debug: dict(proxy): Looking up 'priv/quota/messages' Nov 27 15:46:31 doveadm(h.user@example.com): Debug: dict(proxy): Looking up (async) 'priv/quota/messages' Nov 27 15:46:31 doveadm(h.user@example.com): Debug: dict(proxy): Lookup finished for 'priv/quota/messages': found Nov 27 15:46:31 doveadm(h.user@example.com): Debug: dict(proxy): Lookup finished for 'priv/quota/messages': found Nov 27 15:46:31 doveadm(h.user@example.com): Debug: dict(proxy): dict destroyed Nov 27 15:46:31 doveadm(h.user@example.com): Debug: dict(proxy): Waiting for dict to finish pending operations Nov 27 15:46:31 doveadm(h.user@example.com): Debug: dict(proxy): conn unix:/var/run/dovecot/dict (pid=1,uid=0): Disconnected: Connection closed (fd=10) Nov 27 15:46:31 doveadm(h.user@example.com): Debug: dict(proxy): dict destroyed Nov 27 15:46:31 doveadm(h.user@example.com): Debug: dict(proxy): Waiting for dict to finish pending operations Nov 27 15:46:31 doveadm(h.user@example.com): Debug: dict(proxy): conn unix:/var/run/dovecot/dict (pid=1,uid=0): Disconnected: Connection closed (fd=12) Nov 27 15:46:31 doveadm(h.user@example.com): Debug: dict(proxy): dict destroyed Quota name Type Value Limit % User Quota STORAGE 25 1024000 0 User Quota MESSAGE 25000 - 0 Domain Quota STORAGE 36 10240000 0 Domain Quota MESSAGE 36000 - 0 Nov 27 15:46:31 doveadm(401): Debug: auth-master: conn unix:/var/run/dovecot/director-userdb (pid=1,uid=0): Disconnected: Connection closed (fd=9)
Dovecot version 2.3.16, 2.3.15, 2.3.13. in this example 2.3.13 (89f716dc2) bullseye - *correct behavior, select*
Debug: Loading modules from directory: /usr/lib/dovecot/modules Debug: Module loaded: /usr/lib/dovecot/modules/lib01_acl_plugin.so Debug: Module loaded: /usr/lib/dovecot/modules/lib10_quota_plugin.so Debug: Module loaded: /usr/lib/dovecot/modules/lib20_mailbox_alias_plugin.so Debug: Loading modules from directory: /usr/lib/dovecot/modules/doveadm Debug: Module loaded: /usr/lib/dovecot/modules/doveadm/lib10_doveadm_acl_plugin.so Debug: Skipping module doveadm_expire_plugin, because dlopen() failed: /usr/lib/dovecot/modules/doveadm/lib10_doveadm_expire_plugin.so: undefined symbol: expire_set_deinit (this is usually intentional, so just ignore this message) Debug: Module loaded: /usr/lib/dovecot/modules/doveadm/lib10_doveadm_quota_plugin.so Debug: Module loaded: /usr/lib/dovecot/modules/doveadm/lib10_doveadm_sieve_plugin.so Debug: Skipping module doveadm_fts_lucene_plugin, because dlopen() failed: /usr/lib/dovecot/modules/doveadm/lib20_doveadm_fts_lucene_plugin.so: undefined symbol: lucene_index_iter_deinit (this is usually intentional, so just ignore this message) Debug: Skipping module doveadm_fts_plugin, because dlopen() failed: /usr/lib/dovecot/modules/doveadm/lib20_doveadm_fts_plugin.so: undefined symbol: fts_user_get_language_list (this is usually intentional, so just ignore this message) Debug: Skipping module doveadm_mail_crypt_plugin, because dlopen() failed: /usr/lib/dovecot/modules/doveadm/libdoveadm_mail_crypt_plugin.so: undefined symbol: mail_crypt_box_get_pvt_digests (this is usually intentional, so just ignore this message) doveadm(h.gorska@example.com)<93><>: Debug: auth-master: userdb lookup(h.user@example.com): Started userdb lookup doveadm(h.user@example.com)<93><>: Debug: auth-master: conn unix:/run/dovecot/director-userdb: Connecting doveadm(h.user@example.com)<93><>: Debug: auth-master: conn unix:/run/dovecot/director-userdb (pid=1,uid=0): Client connected (fd=9) doveadm(h.user@example.com)<93><>: Debug: auth-master: userdb lookup(h.user@example.com): auth USER input: h.user@example.com home=/home/mail/virtual/data05/example.com/h.user@example.com quota2_rule=*:bytes=10485760000 quota_rule=*:bytes=1048576000 doveadm(h.user@example.com)<93><>: Debug: auth-master: userdb lookup(h.user@example.com): Finished userdb lookup (username=h.user@example.com home=/home/mail/virtual/data05/example.com/h.user@example.com quota2_rule=*:bytes=10485760000 quota_rule=*:bytes=1048576000) doveadm(h.user@example.com)<93><>: Debug: Added userdb setting: plugin/quota2_rule=*:bytes=10485760000 doveadm(h.user@example.com)<93><>: Debug: Added userdb setting: plugin/quota_rule=*:bytes=1048576000 doveadm(h.user@example.com): Debug: Effective uid=101, gid=102, home=/home/mail/virtual/data05/example.com/h.user@example.com doveadm(h.user@example.com): Debug: Home dir not found: /home/mail/virtual/data05/example.com/h.user@example.com doveadm(h.user@example.com): Debug: Quota root: name=User Quota backend=dict args=:proxy::sqluserquota doveadm(h.user@example.com): Debug: Quota rule: root=User Quota mailbox=* bytes=1048576000 messages=0 doveadm(h.user@example.com): Debug: Quota warning: bytes=1048576000 (100%) messages=0 reverse=no command=quota-warning 100 h.user@example.com doveadm(h.user@example.com): Debug: Quota warning: bytes=996147200 (95%) messages=0 reverse=no command=quota-warning 95 h.user@example.com doveadm(h.user@example.com): Debug: Quota warning: bytes=943718400 (90%) messages=0 reverse=no command=quota-warning 90 h.user@example.com doveadm(h.user@example.com): Debug: Quota warning: bytes=891289600 (85%) messages=0 reverse=no command=quota-warning 85 h.user@example.com doveadm(h.user@example.com): Debug: Quota grace: root=User Quota bytes=104857600 (10%) doveadm(h.user@example.com): Debug: Quota root: name=Domain Quota backend=dict args=example.com:proxy::sqldomainquota doveadm(h.user@example.com): Debug: Quota rule: root=Domain Quota mailbox=* bytes=10485760000 messages=0 doveadm(h.user@example.com): Debug: Quota grace: root=Domain Quota bytes=1048576000 (10%) doveadm(h.user@example.com): Debug: quota-dict: user=h.user@example.com, uri=proxy::sqluserquota, noenforcing=0 doveadm(h.user@example.com): Debug: quota-dict: user=example.com, uri=proxy::sqldomainquota, noenforcing=0 doveadm(h.user@example.com): Debug: Namespace : type=private, prefix=, sep=/, inbox=yes, hidden=no, list=yes, subscriptions=yes location=maildir://home/mail/virtual/data05/example.com/h.user@example.com/Maildir/:INDEX=//home/mail/virtual/data05/example.com/h.user@example.com/Maildir/ doveadm(h.user@example.com): Debug: maildir++: root=//home/mail/virtual/data05/example.com/h.user@example.com/Maildir, index=, indexpvt=, control=, inbox=//home/mail/virtual/data05/example.com/h.user@example.com/Maildir, alt= doveadm(h.user@example.com): Debug: acl: initiali|//**domain**//|varchar(255)|Nie| |bytes|bigint(20)|Nie|0 |messages|bigint(20)|Nie|0 == Dumping data for table used_domain_quota |h.user@example.com|36000|36000 |example.com|35000|35000zing backend with data: vfile doveadm(h.user@example.com): Debug: acl: acl username= h.user@example.com doveadm(h.user@example.com): Debug: acl: owner= 1 doveadm(h.user@example.com): Debug: acl vfile: Global ACLs disabled doveadm(h.user@example.com): Debug: Namespace : type=shared, prefix=Shared/%u/, sep=/, inbox=no, hidden=no, list=children, subscriptions=yes location=maildir:%Lh/Maildir/:INDEX=%Lh/Maildir/Shared/%u doveadm(h.user@example.com): Debug: shared: root=/run/dovecot, index=, indexpvt=, control=, inbox=, alt= doveadm(h.user@example.com): Debug: acl: initializing backend with data: vfile doveadm(h.user@example.com): Debug: acl: acl username= h.user@example.com doveadm(h.user@example.com): Debug: acl: owner= 0 doveadm(h.user@example.com): Debug: acl vfile: Global ACLs disabled doveadm(h.user@example.com): Debug: quota: quota_over_flag check: quota_over_script unset - skipping doveadm(h.user@example.com): Debug: quota: quota_over_flag check: quota2_over_script unset - skipping Quota name Type Value Limit % User Quota STORAGE 25 1024000 0 User Quota MESSAGE 25000 - 0 Domain Quota STORAGE 35 10240000 0 Domain Quota MESSAGE 35000 - 0 doveadm(h.user@example.com): Debug: auth-master: conn unix:/run/dovecot/director-userdb (pid=1,uid=0): Disconnected: Connection closed (fd=9)
MYSQL catch logs
Mysql catch log during doveadm quota get -u h.user@example.com, version 2.3.17+
592 Query SELECT username AS user,
CONCAT('/home/mail/virtual/',mailbox.storagenode,mailbox.maildir,username)
AS home, CONCAT('*:bytes=', domain.maxquota*1048576) AS quota2_rule,
CONCAT('*:bytes=', mailbox.quota*1048576) AS quota_rule FROM
mailbox,domain WHERE username = 'h.user@example.com'AND
mailbox.domain=domain.domain AND domain.active=1 AND
mailbox.enabledoveadm
=1 AND mailbox.active=1
593 Connect root@10.15.1.40 on postfix using TCP/IP
593 Query SELECT bytes FROM used_quota WHERE username = 'h.user@example.com'
593 Query SELECT messages FROM used_quota WHERE username =
'h.user@example.com'
594 Connect root@10.15.1.40 on postfix using TCP/IP
594 Query SELECT bytes FROM used_domain_quota WHERE domain =
'h.user@example.com'
594 Query SELECT messages FROM used_domain_quota WHERE domain =
'h.user@example.com'
example SQL UPDATE, dovecot version 2.3.20 (80a5ac675d) alpine 3.18.4 - bad behavior
# User@Host: user[user @ [192.168.254.176] # Thread_id: 58405753 Schema: postfix QC_hit: No # Query_time: 0.000294 Lock_time: 0.000104 Rows_sent: 0 Rows_examined: 1 # Rows_affected: 1 Bytes_sent: 52 # # explain: id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra # explain: 1 SIMPLE used_domain_quota range PRIMARY PRIMARY 767 NULL 1 1.00 100.00 100.00 Using where # SET timestamp=1701103297; UPDATE used_domain_quota SET bytes=bytes+4359,messages=messages+1 WHERE domain = 'h.user@example.com';
example SQL UPDATE domain and user quota - *good behavior*, dovecot version 2.3.4.1 (f79e8e7e4), debian 10
# User@Host: postfix[postfix] @ [192.168.254.175] # Thread_id: 58406279 Schema: postfix QC_hit: No # Query_time: 0.000252 Lock_time: 0.000080 Rows_sent: 0 Rows_examined: 1 # Rows_affected: 1 Bytes_sent: 52 # # explain: id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra # explain: 1 SIMPLE used_domain_quota range PRIMARY PRIMARY 767 NULL 1 1.00 100.00 100.00 Using where # SET timestamp=1701103048; UPDATE used_domain_quota SET bytes=bytes+11597,messages=messages+1 WHERE domain = 'example.com'; # User@Host: user[user] @ [192.168.254.175] # Thread_id: 58406274 Schema: postfix QC_hit: No # Query_time: 0.000247 Lock_time: 0.000076 Rows_sent: 0 Rows_examined: 1 # Rows_affected: 1 Bytes_sent: 52 # # explain: id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra # explain: 1 SIMPLE used_quota range PRIMARY PRIMARY 767 NULL 1 1.00 100.00 100.00 Using where # SET timestamp=1701103048; UPDATE used_quota SET bytes=bytes+11597,messages=messages+1 WHERE username = 'h.user@example.com';
Hi, I notice that quota domain when using args %d in dictionary isn't honored in mysql during updates and selects when using dovecot 2.3.17+, so I moved my tests to docker environment, because I started using alpine linux and thought it could be musl library problem. I tested few versions with debian/alpine and after 2.3.17 updates and selects for domain in sql not using domain part, but user@domain. Maybe I missed some changes in configuration, maybe someone experience this behavior? User in logs was changed to h.user@example.com.
***** Configuration ***** as described in documentation quota = dict:<quota root name>:<username>[:
<option>[...]]:<dictionary URI> where username could be %d for supporting domain-wide quotas quota = dict:user_quota::proxy::sqluserquota quota2 = dict:domain_quota:%d:proxy::sqldomainquota dict { acl = mysql:/etc/dovecot/dovecot-share-folder.conf sqldomainquota = mysql:/etc/dovecot/dovecot-dict-sql-domain.conf sqluserquota = mysql:/etc/dovecot/dovecot-dict-sql-user.conf } dovecot-dict-sql-domain.conf map { pattern = priv/quota/storage table = used_domain_quota username_field = domain value_field = bytes } map { pattern = priv/quota/messages table = used_domain_quota username_field = domain value_field = messages } dovecot-dict-sql-user.conf map { pattern = priv/quota/storage table = used_quota username_field = username value_field = bytes } map { pattern = priv/quota/messages table = used_quota username_field = username value_field = messages }
Example dump sql table, in real environment with newer dovecot, there was only h.user@example.com and no domain record. In earlier versions of dovecot there was only domain in this table. |//**domain**//|varchar(255)|Nie| |bytes|bigint(20)|Nie|0 |messages|bigint(20)|Nie|0 == Dumping data for table used_domain_quota |h.user@example.com|36000|36000 |example.com|35000|35000 ***** Debug ***** **** Doveadm
In both examples below debug args=example.com seems correct Dovecot version 2.3.17+, in this example debian 10 2.3.17 (e2aa53df5b), select with only username. root@cf801690360c:/# doveadm -D -v quota get -u h.user@example.com Debug: Loading modules from directory: /usr/lib/dovecot/modules/doveadm Debug: Skipping module doveadm_acl_plugin, because dlopen() failed: /usr/lib/ dovecot/modules/doveadm/lib10_doveadm_acl_plugin.so: undefined symbol: acl_user_module (this is usually intentional, so just ignore this message) Debug: Skipping module doveadm_quota_plugin, because dlopen() failed: /usr/lib/ dovecot/modules/doveadm/lib10_doveadm_quota_plugin.so: undefined symbol: quota_user_module (this is usually intentional, so just ignore this message) Debug: Module loaded: /usr/lib/dovecot/modules/doveadm/ lib10_doveadm_sieve_plugin.so Debug: Skipping module doveadm_fts_lucene_plugin, because dlopen() failed: / usr/lib/dovecot/modules/doveadm/lib20_doveadm_fts_lucene_plugin.so: undefined symbol: lucene_index_iter_deinit (this is usually intentional, so just ignore this message) Debug: Skipping module doveadm_fts_plugin, because dlopen() failed: /usr/lib/ dovecot/modules/doveadm/lib20_doveadm_fts_plugin.so: undefined symbol: fts_user_get_language_list (this is usually intentional, so just ignore this message) Debug: Skipping module doveadm_mail_crypt_plugin, because dlopen() failed: / usr/lib/dovecot/modules/doveadm/libdoveadm_mail_crypt_plugin.so: undefined symbol: mail_crypt_box_get_pvt_digests (this is usually intentional, so just ignore this message) Nov 27 15:46:31 Debug: Loading modules from directory: /usr/lib/dovecot/modules Nov 27 15:46:31 Debug: Module loaded: /usr/lib/dovecot/modules/ lib01_acl_plugin.so Nov 27 15:46:31 Debug: Module loaded: /usr/lib/dovecot/modules/ lib10_quota_plugin.so Nov 27 15:46:31 Debug: Module loaded: /usr/lib/dovecot/modules/ lib20_mailbox_alias_plugin.so Nov 27 15:46:31 Debug: Loading modules from directory: /usr/lib/dovecot/ modules/doveadm Nov 27 15:46:31 Debug: Module loaded: /usr/lib/dovecot/modules/doveadm/ lib10_doveadm_acl_plugin.so Nov 27 15:46:31 Debug: Module loaded: /usr/lib/dovecot/modules/doveadm/ lib10_doveadm_quota_plugin.so Nov 27 15:46:31 Debug: Skipping module doveadm_fts_lucene_plugin, because dlopen() failed: /usr/lib/dovecot/modules/doveadm/ lib20_doveadm_fts_lucene_plugin.so: undefined symbol: lucene_index_iter_deinit (this is usually intentional, so just ignore this message) Nov 27 15:46:31 Debug: Skipping module doveadm_fts_plugin, because dlopen() failed: /usr/lib/dovecot/modules/doveadm/lib20_doveadm_fts_plugin.so: undefined symbol: fts_user_get_language_list (this is usually intentional, so just ignore this message) Nov 27 15:46:31 Debug: Skipping module doveadm_mail_crypt_plugin, because dlopen() failed: /usr/lib/dovecot/modules/doveadm/ libdoveadm_mail_crypt_plugin.so: undefined symbol: mail_crypt_box_get_pvt_digests (this is usually intentional, so just ignore this message) Nov 27 15:46:31 doveadm(h.user@example.com)<401><>: Debug: auth-master: userdb lookup(h.user@example.com): Started userdb lookup Nov 27 15:46:31 doveadm(h.user@example.com)<401><>: Debug: auth-master: conn unix:/var/run/dovecot/director-userdb: Connecting Nov 27 15:46:31 doveadm(h.user@example.com)<401><>: Debug: auth-master: conn unix:/var/run/dovecot/director-userdb (pid=1,uid=0): Client connected (fd=9) Nov 27 15:46:31 doveadm(h.user@example.com)<401><>: Debug: auth-master: userdb lookup(h.user@example.com): auth USER input: h.user@example.com home=/home/ mail/virtual/data05/example.com/h.user@example.com quota2_rule=*: bytes=10485760000 quota_rule=*:bytes=1048576000 Nov 27 15:46:31 doveadm(h.user@example.com)<401><>: Debug: auth-master: userdb lookup(h.user@example.com): Finished userdb lookup (username=h.user@example.com home=/home/mail/virtual/data05/example.com/h.user@example.com quota2_rule=*: bytes=10485760000 quota_rule=*:bytes=1048576000) Nov 27 15:46:31 doveadm(h.user@example.com)<401><>: Debug: Added userdb setting: plugin/quota2_rule=*:bytes=10485760000 Nov 27 15:46:31 doveadm(h.user@example.com)<401><>: Debug: Added userdb setting: plugin/quota_rule=*:bytes=1048576000 Nov 27 15:46:31 doveadm(h.user@example.com)<401><4l0XONe5ZGWRAQAAQCEzFg>: Debug: Effective uid=101, gid=101, home=/home/mail/virtual/data05/example.com/ h.user@example.com Nov 27 15:46:31 doveadm(h.user@example.com)<401><4l0XONe5ZGWRAQAAQCEzFg>: Debug: Home dir not found: /home/mail/virtual/data05/example.com/ h.user@example.com Nov 27 15:46:31 doveadm(h.user@example.com)<401><4l0XONe5ZGWRAQAAQCEzFg>: Debug: dict(proxy): dict created (uri=proxy::acl, base_dir=/var/run/dovecot) Nov 27 15:46:31 doveadm(h.user@example.com)<401><4l0XONe5ZGWRAQAAQCEzFg>: Debug: Quota root: name=User Quota backend=dict args=:proxy::sqluserquota Nov 27 15:46:31 doveadm(h.user@example.com)<401><4l0XONe5ZGWRAQAAQCEzFg>: Debug: Quota rule: root=User Quota mailbox=* bytes=1048576000 messages=0 Nov 27 15:46:31 doveadm(h.user@example.com)<401><4l0XONe5ZGWRAQAAQCEzFg>: Debug: Quota warning: bytes=1048576000 (100%) messages=0 reverse=no command=quota-warning 100 h.user@example.com Nov 27 15:46:31 doveadm(h.user@example.com)<401><4l0XONe5ZGWRAQAAQCEzFg>: Debug: Quota warning: bytes=996147200 (95%) messages=0 reverse=no command=quota-warning 95 h.user@example.com Nov 27 15:46:31 doveadm(h.user@example.com)<401><4l0XONe5ZGWRAQAAQCEzFg>: Debug: Quota warning: bytes=943718400 (90%) messages=0 reverse=no command=quota-warning 90 h.user@example.com Nov 27 15:46:31 doveadm(h.user@example.com)<401><4l0XONe5ZGWRAQAAQCEzFg>: Debug: Quota warning: bytes=891289600 (85%) messages=0 reverse=no command=quota-warning 85 h.user@example.com Nov 27 15:46:31 doveadm(h.user@example.com)<401><4l0XONe5ZGWRAQAAQCEzFg>: Debug: Quota grace: root=User Quota bytes=104857600 (10%) Nov 27 15:46:31 doveadm(h.user@example.com)<401><4l0XONe5ZGWRAQAAQCEzFg>: Debug: Quota root: name=Domain Quota backend=dict args=example.com:proxy:: sqldomainquota Nov 27 15:46:31 doveadm(h.user@example.com)<401><4l0XONe5ZGWRAQAAQCEzFg>: Debug: Quota rule: root=Domain Quota mailbox=* bytes=10485760000 messages=0 Nov 27 15:46:31 doveadm(h.user@example.com)<401><4l0XONe5ZGWRAQAAQCEzFg>: Debug: Quota grace: root=Domain Quota bytes=1048576000 (10%) Nov 27 15:46:31 doveadm(h.user@example.com)<401><4l0XONe5ZGWRAQAAQCEzFg>: Debug: quota-dict: user=h.user@example.com, uri=proxy::sqluserquota, noenforcing=0 Nov 27 15:46:31 doveadm(h.user@example.com)<401><4l0XONe5ZGWRAQAAQCEzFg>: Debug: dict(proxy): dict created (uri=proxy::sqluserquota, base_dir=/var/run/ dovecot) Nov 27 15:46:31 doveadm(h.user@example.com)<401><4l0XONe5ZGWRAQAAQCEzFg>: Debug: quota-dict: user=example.com, uri=proxy::sqldomainquota, noenforcing=0 Nov 27 15:46:31 doveadm(h.user@example.com)<401><4l0XONe5ZGWRAQAAQCEzFg>: Debug: dict(proxy): dict created (uri=proxy::sqldomainquota, base_dir=/var/run/ dovecot) Nov 27 15:46:31 doveadm(h.user@example.com)<401><4l0XONe5ZGWRAQAAQCEzFg>: Debug: Namespace : type=private, prefix=, sep=/, inbox=yes, hidden=no, list=yes, subscriptions=yes location=maildir://home/mail/virtual/data05/ example.com/h.user@example.com/Maildir/:INDEX=//home/mail/virtual/data05/ example.com/h.user@example.com/Maildir/ Nov 27 15:46:31 doveadm(h.user@example.com)<401><4l0XONe5ZGWRAQAAQCEzFg>: Debug: maildir++: root=//home/mail/virtual/data05/example.com/ h.user@example.com/Maildir, index=, indexpvt=, control=, inbox=//home/mail/ virtual/data05/example.com/h.user@example.com/Maildir, alt= Nov 27 15:46:31 doveadm(h.user@example.com)<401><4l0XONe5ZGWRAQAAQCEzFg>: Debug: acl: initializing backend with data: vfile Nov 27 15:46:31 doveadm(h.user@example.com)<401><4l0XONe5ZGWRAQAAQCEzFg>: Debug: acl: acl username = h.user@example.com Nov 27 15:46:31 doveadm(h.user@example.com)<401><4l0XONe5ZGWRAQAAQCEzFg>: Debug: acl: owner = 1 Nov 27 15:46:31 doveadm(h.user@example.com)<401><4l0XONe5ZGWRAQAAQCEzFg>: Debug: acl vfile: Global ACLs disabled Nov 27 15:46:31 doveadm(h.user@example.com)<401><4l0XONe5ZGWRAQAAQCEzFg>: Debug: Namespace : type=shared, prefix=Shared/%u/, sep=/, inbox=no, hidden=no, list=children, subscriptions=yes location=maildir:%Lh/Maildir/:INDEX=%Lh/ Maildir/Shared/%u Nov 27 15:46:31 doveadm(h.user@example.com)<401><4l0XONe5ZGWRAQAAQCEzFg>: Debug: shared: root=/var/run/dovecot, index=, indexpvt=, control=, inbox=, alt= Nov 27 15:46:31 doveadm(h.user@example.com)<401><4l0XONe5ZGWRAQAAQCEzFg>: Debug: acl: initializing backend with data: vfile Nov 27 15:46:31 doveadm(h.user@example.com)<401><4l0XONe5ZGWRAQAAQCEzFg>: Debug: acl: acl username = h.user@example.com Nov 27 15:46:31 doveadm(h.user@example.com)<401><4l0XONe5ZGWRAQAAQCEzFg>: Debug: acl: owner = 0 Nov 27 15:46:31 doveadm(h.user@example.com)<401><4l0XONe5ZGWRAQAAQCEzFg>: Debug: acl vfile: Global ACLs disabled Nov 27 15:46:31 doveadm(h.user@example.com)<401><4l0XONe5ZGWRAQAAQCEzFg>: Debug: quota: quota_over_flag check: quota_over_script unset - skipping Nov 27 15:46:31 doveadm(h.user@example.com)<401><4l0XONe5ZGWRAQAAQCEzFg>: Debug: quota: quota_over_flag check: quota2_over_script unset - skipping Nov 27 15:46:31 doveadm(h.user@example.com): Debug: dict(proxy): Looking up 'priv/quota/storage' Nov 27 15:46:31 doveadm(h.user@example.com): Debug: dict(proxy): Looking up (async) 'priv/quota/storage' Nov 27 15:46:31 doveadm(h.user@example.com): Debug: dict(proxy): conn unix:/ var/run/dovecot/dict: Connecting Nov 27 15:46:31 doveadm(h.user@example.com): Debug: dict(proxy): conn unix:/ var/run/dovecot/dict (pid=1,uid=0): Client connected (fd=10) Nov 27 15:46:31 doveadm(h.user@example.com): Debug: dict(proxy): Lookup finished for 'priv/quota/storage': found Nov 27 15:46:31 doveadm(h.user@example.com): Debug: dict(proxy): Lookup finished for 'priv/quota/storage': found Nov 27 15:46:31 doveadm(h.user@example.com): Debug: dict(proxy): Looking up 'priv/quota/messages' Nov 27 15:46:31 doveadm(h.user@example.com): Debug: dict(proxy): Looking up (async) 'priv/quota/messages' Nov 27 15:46:31 doveadm(h.user@example.com): Debug: dict(proxy): Lookup finished for 'priv/quota/messages': found Nov 27 15:46:31 doveadm(h.user@example.com): Debug: dict(proxy): Lookup finished for 'priv/quota/messages': found Nov 27 15:46:31 doveadm(h.user@example.com): Debug: dict(proxy): Looking up 'priv/quota/storage' Nov 27 15:46:31 doveadm(h.user@example.com): Debug: dict(proxy): Looking up (async) 'priv/quota/storage' Nov 27 15:46:31 doveadm(h.user@example.com): Debug: dict(proxy): conn unix:/ var/run/dovecot/dict: Connecting Nov 27 15:46:31 doveadm(h.user@example.com): Debug: dict(proxy): conn unix:/ var/run/dovecot/dict (pid=1,uid=0): Client connected (fd=12) Nov 27 15:46:31 doveadm(h.user@example.com): Debug: dict(proxy): Lookup finished for 'priv/quota/storage': found Nov 27 15:46:31 doveadm(h.user@example.com): Debug: dict(proxy): Lookup finished for 'priv/quota/storage': found Nov 27 15:46:31 doveadm(h.user@example.com): Debug: dict(proxy): Looking up 'priv/quota/messages' Nov 27 15:46:31 doveadm(h.user@example.com): Debug: dict(proxy): Looking up (async) 'priv/quota/messages' Nov 27 15:46:31 doveadm(h.user@example.com): Debug: dict(proxy): Lookup finished for 'priv/quota/messages': found Nov 27 15:46:31 doveadm(h.user@example.com): Debug: dict(proxy): Lookup finished for 'priv/quota/messages': found Nov 27 15:46:31 doveadm(h.user@example.com): Debug: dict(proxy): dict destroyed Nov 27 15:46:31 doveadm(h.user@example.com): Debug: dict(proxy): Waiting for dict to finish pending operations Nov 27 15:46:31 doveadm(h.user@example.com): Debug: dict(proxy): conn unix:/ var/run/dovecot/dict (pid=1,uid=0): Disconnected: Connection closed (fd=10) Nov 27 15:46:31 doveadm(h.user@example.com): Debug: dict(proxy): dict destroyed Nov 27 15:46:31 doveadm(h.user@example.com): Debug: dict(proxy): Waiting for dict to finish pending operations Nov 27 15:46:31 doveadm(h.user@example.com): Debug: dict(proxy): conn unix:/ var/run/dovecot/dict (pid=1,uid=0): Disconnected: Connection closed (fd=12) Nov 27 15:46:31 doveadm(h.user@example.com): Debug: dict(proxy): dict destroyed Quota name Type Value Limit % User Quota STORAGE 25 1024000 0 User Quota MESSAGE 25000 - 0 Domain Quota STORAGE 36 10240000 0 Domain Quota MESSAGE 36000 - 0 Nov 27 15:46:31 doveadm(401): Debug: auth-master: conn unix:/var/run/dovecot/ director-userdb (pid=1,uid=0): Disconnected: Connection closed (fd=9)
Dovecot version 2.3.16, 2.3.15, 2.3.13. in this example 2.3.13 (89f716dc2) bullseye - correct behavior, select Debug: Loading modules from directory: /usr/lib/dovecot/modules Debug: Module loaded: /usr/lib/dovecot/modules/lib01_acl_plugin.so Debug: Module loaded: /usr/lib/dovecot/modules/lib10_quota_plugin.so Debug: Module loaded: /usr/lib/dovecot/modules/lib20_mailbox_alias_plugin.so Debug: Loading modules from directory: /usr/lib/dovecot/modules/doveadm Debug: Module loaded: /usr/lib/dovecot/modules/doveadm/ lib10_doveadm_acl_plugin.so Debug: Skipping module doveadm_expire_plugin, because dlopen() failed: /usr/ lib/dovecot/modules/doveadm/lib10_doveadm_expire_plugin.so: undefined symbol: expire_set_deinit (this is usually intentional, so just ignore this message) Debug: Module loaded: /usr/lib/dovecot/modules/doveadm/ lib10_doveadm_quota_plugin.so Debug: Module loaded: /usr/lib/dovecot/modules/doveadm/ lib10_doveadm_sieve_plugin.so Debug: Skipping module doveadm_fts_lucene_plugin, because dlopen() failed: / usr/lib/dovecot/modules/doveadm/lib20_doveadm_fts_lucene_plugin.so: undefined symbol: lucene_index_iter_deinit (this is usually intentional, so just ignore this message) Debug: Skipping module doveadm_fts_plugin, because dlopen() failed: /usr/lib/ dovecot/modules/doveadm/lib20_doveadm_fts_plugin.so: undefined symbol: fts_user_get_language_list (this is usually intentional, so just ignore this message) Debug: Skipping module doveadm_mail_crypt_plugin, because dlopen() failed: / usr/lib/dovecot/modules/doveadm/libdoveadm_mail_crypt_plugin.so: undefined symbol: mail_crypt_box_get_pvt_digests (this is usually intentional, so just ignore this message) doveadm(h.gorska@example.com)<93><>: Debug: auth-master: userdb lookup (h.user@example.com): Started userdb lookup doveadm(h.user@example.com)<93><>: Debug: auth-master: conn unix:/run/dovecot/ director-userdb: Connecting doveadm(h.user@example.com)<93><>: Debug: auth-master: conn unix:/run/dovecot/ director-userdb (pid=1,uid=0): Client connected (fd=9) doveadm(h.user@example.com)<93><>: Debug: auth-master: userdb lookup (h.user@example.com): auth USER input: h.user@example.com home=/home/mail/ virtual/data05/example.com/h.user@example.com quota2_rule=*:bytes=10485760000 quota_rule=*:bytes=1048576000 doveadm(h.user@example.com)<93><>: Debug: auth-master: userdb lookup (h.user@example.com): Finished userdb lookup (username=h.user@example.com home=/home/mail/virtual/data05/example.com/h.user@example.com quota2_rule=*: bytes=10485760000 quota_rule=*:bytes=1048576000) doveadm(h.user@example.com)<93><>: Debug: Added userdb setting: plugin/ quota2_rule=*:bytes=10485760000 doveadm(h.user@example.com)<93><>: Debug: Added userdb setting: plugin/ quota_rule=*:bytes=1048576000 doveadm(h.user@example.com): Debug: Effective uid=101, gid=102, home=/home/ mail/virtual/data05/example.com/h.user@example.com doveadm(h.user@example.com): Debug: Home dir not found: /home/mail/virtual/ data05/example.com/h.user@example.com doveadm(h.user@example.com): Debug: Quota root: name=User Quota backend=dict args=:proxy::sqluserquota doveadm(h.user@example.com): Debug: Quota rule: root=User Quota mailbox=* bytes=1048576000 messages=0 doveadm(h.user@example.com): Debug: Quota warning: bytes=1048576000 (100%) messages=0 reverse=no command=quota-warning 100 h.user@example.com doveadm(h.user@example.com): Debug: Quota warning: bytes=996147200 (95%) messages=0 reverse=no command=quota-warning 95 h.user@example.com doveadm(h.user@example.com): Debug: Quota warning: bytes=943718400 (90%) messages=0 reverse=no command=quota-warning 90 h.user@example.com doveadm(h.user@example.com): Debug: Quota warning: bytes=891289600 (85%) messages=0 reverse=no command=quota-warning 85 h.user@example.com doveadm(h.user@example.com): Debug: Quota grace: root=User Quota bytes=104857600 (10%) doveadm(h.user@example.com): Debug: Quota root: name=Domain Quota backend=dict args=example.com:proxy::sqldomainquota doveadm(h.user@example.com): Debug: Quota rule: root=Domain Quota mailbox=* bytes=10485760000 messages=0 doveadm(h.user@example.com): Debug: Quota grace: root=Domain Quota bytes=1048576000 (10%) doveadm(h.user@example.com): Debug: quota-dict: user=h.user@example.com, uri=proxy::sqluserquota, noenforcing=0 doveadm(h.user@example.com): Debug: quota-dict: user=example.com, uri=proxy:: sqldomainquota, noenforcing=0 doveadm(h.user@example.com): Debug: Namespace : type=private, prefix=, sep=/, inbox=yes, hidden=no, list=yes, subscriptions=yes location=maildir://home/mail/ virtual/data05/example.com/h.user@example.com/Maildir/:INDEX=//home/mail/ virtual/data05/example.com/h.user@example.com/Maildir/ doveadm(h.user@example.com): Debug: maildir++: root=//home/mail/virtual/data05/ example.com/h.user@example.com/Maildir, index=, indexpvt=, control=, inbox=// home/mail/virtual/data05/example.com/h.user@example.com/Maildir, alt= doveadm(h.user@example.com): Debug: acl: initiali|//**domain**//|varchar (255)|Nie| |bytes|bigint(20)|Nie|0 |messages|bigint(20)|Nie|0 == Dumping data for table used_domain_quota |h.user@example.com|36000|36000 |example.com|35000|35000zing backend with data: vfile doveadm(h.user@example.com): Debug: acl: acl username = h.user@example.com doveadm(h.user@example.com): Debug: acl: owner = 1 doveadm(h.user@example.com): Debug: acl vfile: Global ACLs disabled doveadm(h.user@example.com): Debug: Namespace : type=shared, prefix=Shared/%u/, sep=/, inbox=no, hidden=no, list=children, subscriptions=yes location=maildir: %Lh/Maildir/:INDEX=%Lh/Maildir/Shared/%u doveadm(h.user@example.com): Debug: shared: root=/run/dovecot, index=, indexpvt=, control=, inbox=, alt= doveadm(h.user@example.com): Debug: acl: initializing backend with data: vfile doveadm(h.user@example.com): Debug: acl: acl username = h.user@example.com doveadm(h.user@example.com): Debug: acl: owner = 0 doveadm(h.user@example.com): Debug: acl vfile: Global ACLs disabled doveadm(h.user@example.com): Debug: quota: quota_over_flag check: quota_over_script unset - skipping doveadm(h.user@example.com): Debug: quota: quota_over_flag check: quota2_over_script unset - skipping Quota name Type Value Limit % User Quota STORAGE 25 1024000 0 User Quota MESSAGE 25000 - 0 Domain Quota STORAGE 35 10240000 0 Domain Quota MESSAGE 35000 - 0 doveadm(h.user@example.com): Debug: auth-master: conn unix:/run/dovecot/ director-userdb (pid=1,uid=0): Disconnected: Connection closed (fd=9)
**** MYSQL catch logs
Mysql catch log during doveadm quota get -u h.user@example.com, version 2.3.17+
592 Query SELECT username AS user, CONCAT('/home/mail/virtual/
',mailbox.storagenode,mailbox.maildir,username) AS home, CONCAT('*:bytes=',
domain.maxquota*1048576) AS quota2_rule, CONCAT('*:bytes=',
mailbox.quota*1048576) AS quota_rule FROM mailbox,domain WHERE username =
'h.user@example.com' AND mailbox.domain=domain.domain AND domain.active=1 AND
mailbox.enabledoveadm
=1 AND mailbox.active=1
593 Connect root@10.15.1.40 on postfix using TCP/IP
593 Query SELECT bytes FROM used_quota WHERE username = 'h.user@example.com'
593 Query SELECT messages FROM used_quota WHERE username = 'h.user@example.com'
594 Connect root@10.15.1.40 on postfix using TCP/IP
594 Query SELECT bytes FROM used_domain_quota WHERE domain =
'h.user@example.com'
594 Query SELECT messages FROM used_domain_quota WHERE domain =
'h.user@example.com'
example SQL UPDATE, dovecot version 2.3.20 (80a5ac675d) alpine 3.18.4 - bad
behavior
# User@Host: user[user @ [192.168.254.176]
# Thread_id: 58405753 Schema: postfix QC_hit: No
# Query_time: 0.000294 Lock_time: 0.000104 Rows_sent: 0 Rows_examined: 1
# Rows_affected: 1 Bytes_sent: 52
#
# explain: id select_type table type possible_keys key key_len ref rows r_rows
filtered r_filtered Extra
# explain: 1 SIMPLE used_domain_quota range PRIMARY PRIMARY 767 NULL 1 1.00
100.00 100.00 Using where
#
SET timestamp=1701103297;
UPDATE used_domain_quota SET bytes=bytes+4359,messages=messages+1 WHERE domain
= 'h.user@example.com';
example SQL UPDATE domain and user quota - good behavior, dovecot version
2.3.4.1 (f79e8e7e4), debian 10
# User@Host: postfix[postfix] @ [192.168.254.175]
# Thread_id: 58406279 Schema: postfix QC_hit: No
# Query_time: 0.000252 Lock_time: 0.000080 Rows_sent: 0 Rows_examined: 1
# Rows_affected: 1 Bytes_sent: 52
#
# explain: id select_type table type possible_keys key key_len ref rows r_rows
filtered r_filtered Extra
# explain: 1 SIMPLE used_domain_quota range PRIMARY PRIMARY 767 NULL 1 1.00
100.00 100.00 Using where
#
SET timestamp=1701103048;
UPDATE used_domain_quota SET bytes=bytes+11597,messages=messages+1 WHERE domain
= 'example.com';
# User@Host: user[user] @ [192.168.254.175]
# Thread_id: 58406274 Schema: postfix QC_hit: No
# Query_time: 0.000247 Lock_time: 0.000076 Rows_sent: 0 Rows_examined: 1
# Rows_affected: 1 Bytes_sent: 52
#
# explain: id select_type table type possible_keys key key_len ref rows r_rows
filtered r_filtered Extra
# explain: 1 SIMPLE used_quota range PRIMARY PRIMARY 767 NULL 1 1.00 100.00
100.00 Using where
#
SET timestamp=1701103048;
UPDATE used_quota SET bytes=bytes+11597,messages=messages+1 WHERE username =
'h.user@example.com';