I have configured a shared private namespace in dovecot so that, via ACLs, users can access other users' mailboxes.
I set up a quota for each user and this also works well. The quota is monitored and new messages are denied if the quota is exceeded.
There is one problem though: apparently dovecot treats shared mailboxes in relation to the current user's quota, it does not consider (as would be appropriate) the shared mailbox owner's quota.
I will try to explain better with a couple of examples.
==============
Consider the following case:
user1 has a quota of 1MB, totally available
user2 has a quota of 10MB, totally available
user1 shares the "Sales" mailbox with user2
user2 copies a 500KB message to the shared "Sales" mailbox
user1's quota will be correctly deducted by 500KB, thus resulting in 0.5MB available
At this point, however, let's try another operation:
user2 copies an 800KB message to the shared "Sales" mailbox.
The server should return error because this way user1 exceeds the allocated quota of 1MB (500KB + 800KB), but instead the copy operation succeeds.
This happens because at the time of the copy operation, dovecot considers the quota limit of user2 instead of considering the quota limit of user1.
==============
Let us consider another case, performing the same operations but where the user quota limits are reversed (user1 has a larger quota than user2):
user1 has a quota of 10MB, totally available
user2 has a quota of 1MB, totally available
user1 shares the "Sales" mailbox with user2
user2 copies a 500KB message to the shared mailbox "Sales"
The operation fails by overquota, because again dovecot considers user2's quota limit instead of considering user1's quota limit. Therefore, it is as if user2, with a 1MB limit, tries to write to a "larger" area (10MB).
As a counterevidence, setting user1 and user2 with the same quota limit, the operation succeeds perfectly.
==============
Can anyone help me solve the problem? Is this a problem that is related to my configuration?
Below I attach the output of dovecot -n
===============
# 2.3.19.1 (9b53102964): /etc/dovecot/dovecot.conf
# Pigeonhole version 0.5.19 (4eae2f79)
# OS: Linux 6.1.0-16-cloud-arm64 aarch64 Debian 12.4
auth_master_user_separator = *
auth_mechanisms = PLAIN LOGIN
default_client_limit = 7168
default_process_limit = 1024
deliver_log_format = from=%{from}, envelope_sender=%{from_envelope}, subject=%{subject}, msgid=%m, size=%{size}, delivery_time=%{delivery_time}ms, %$
dict {
acl = mysql:/etc/dovecot/dovecot-dict-acl-sql.conf.ext
}
first_valid_uid = 2000
last_valid_uid = 2000
listen = * [::]
login_log_format_elements = user=<%u> method=%m rip=%r lip=%l mpid=%e %c %k session=<%{session}>
mail_gid = 2000
mail_location = maildir:%Lh:INDEX=%Lh
mail_plugins = quota mailbox_alias acl mail_log notify
mail_uid = 2000
managesieve_notify_capability = mailto
managesieve_sieve_capability = fileinto reject envelope encoded-character vacation subaddress comparator-i;ascii-numeric relational regex imap4flags copy include variables body enotify environment mailbox date index ihave duplicate mime foreverypart extracttext editheader
metric {
filter = event=imap_command_finished
metric_name = imap_command
}
namespace {
inbox = yes
location =
mailbox {
auto = no
special_use = \Archive
name = Archive
}
mailbox {
auto = no
special_use = \Archive
name = Archives
}
mailbox {
auto = no
special_use = \Trash
name = Deleted Messages
}
mailbox {
auto = subscribe
special_use = \Drafts
name = Drafts
}
mailbox {
auto = subscribe
special_use = \Junk
name = Junk
}
mailbox {
auto = no
special_use = \Junk
name = Junk E-mail
}
mailbox {
auto = subscribe
special_use = \Sent
name = Sent
}
mailbox {
auto = no
special_use = \Sent
name = Sent Items
}
mailbox {
auto = no
special_use = \Sent
name = Sent Messages
}
mailbox {
auto = no
special_use = \Junk
name = Spam
}
mailbox {
auto = subscribe
special_use = \Trash
name = Trash
}
prefix =
separator = /
type = private
name =
}
namespace {
list = children
location = maildir:%%Lh:INDEXPVT=%%Lh/Shared/%{auth_user}
prefix = Shared/%%u/
separator = /
subscriptions = yes
type = shared
name =
}
passdb {
args = /etc/dovecot/dovecot-sql.conf.ext
driver = sql
}
passdb {
args = /etc/dovecot/master-users
driver = passwd-file
master = yes
result_success = continue
}
plugin {
acl = vfile:/etc/dovecot/dovecot-acl
acl_shared_dict = proxy::acl
mail_log_events = delete undelete expunge copy mailbox_create mailbox_delete mailbox_rename
mail_log_fields = uid box msgid size from subject flags
quota = maildir:User quota
quota_rule = *:storage=1G
quota_rule2 = Trash:storage=+100M
quota_status_nouser = DUNNO
quota_status_overquota = 552 5.2.2 Mailbox is full
quota_status_success = DUNNO
quota_warning = storage=95%% quota-warning 95 %u
quota_warning2 = storage=80%% quota-warning 80 %u
sieve = file:/home/vmail/%d/sieve/%n/;active=/home/vmail/%d/sieve/%n/.dovecot.sieve
sieve_before = /home/vmail/sieve/sievebefore1
sieve_editheader_forbid_add = X-Verified
sieve_editheader_forbid_delete = X-Verified X-Seen
sieve_editheader_max_header_size = 1k
sieve_extensions = +editheader
sieve_global_dir = /home/vmail/sieve
sieve_max_redirects = 30
sieve_vacation_default_period = 1d
sieve_vacation_min_period = 0
sieve_vacation_send_from_recipient = yes
}
protocols = pop3 imap sieve lmtp
service replication-notify-fifo {
name = aggregator
}
service anvil-auth-penalty {
name = anvil
}
service auth-worker {
name = auth-worker
}
service {
unix_listener {
group = postfix
mode = 0666
user = postfix
path = /var/spool/postfix/private/auth
}
unix_listener {
group = vmail
mode = 0660
user = vmail
path = auth-userdb
}
name = auth
}
service config {
name = config
}
service dict-async {
name = dict-async
}
service {
unix_listener {
group = vmail
mode = 0660
user = vmail
path = dict
}
name = dict
}
service login/proxy-notify {
name = director
}
service dns-client {
name = dns-client
}
service doveadm-server {
name = doveadm
}
service imap-hibernate {
name = imap-hibernate
}
service imap {
process_min_avail = 8
service_count = 0
vsz_limit = 1 G
name = imap-login
}
service imap-urlauth {
name = imap-urlauth-login
}
service imap-urlauth-worker {
name = imap-urlauth-worker
}
service token-login/imap-urlauth {
name = imap-urlauth
}
service {
process_limit = 2048
name = imap
}
service indexer-worker {
name = indexer-worker
}
service indexer {
name = indexer
}
service ipc {
name = ipc
}
service {
unix_listener {
group = postfix
mode = 0666
user = postfix
path = /var/spool/postfix/private/dovecot-lmtp
}
name = lmtp
}
service log-errors {
name = log
}
service {
inet_listener {
port = 4190
name = sieve
}
name = managesieve-login
}
service login/sieve {
name = managesieve
}
service old-stats-mail {
name = old-stats
}
service pop3 {
service_count = 0
name = pop3-login
}
service login/pop3 {
name = pop3
}
service {
executable = script /opt/scripts/dovecot/quota-warning.sh
unix_listener {
group = vmail
mode = 0660
user = vmail
path = quota-warning
}
name = quota-warning
}
service replicator-doveadm {
name = replicator
}
service login/stats-writer {
unix_listener {
group = vmail
mode = 0660
user = vmail
path = stats-reader
}
unix_listener {
group = vmail
mode = 0660
user = vmail
path = stats-writer
}
name = stats
}
service submission {
name = submission-login
}
service login/submission {
name = submission
}
ssl = required
ssl_cert = </etc/letsencrypt/live/mydomain.com/fullchain.pem
ssl_cipher_list = EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH
ssl_dh = # hidden, use -P to show it
ssl_key = # hidden, use -P to show it
ssl_prefer_server_ciphers = yes
userdb {
args = /etc/dovecot/dovecot-sql.conf.ext
driver = sql
}
protocol lda {
lda_mailbox_autocreate = yes
lda_mailbox_autosubscribe = yes
mail_plugins = quota mailbox_alias acl mail_log notify sieve
service replication-notify-fifo {
name = aggregator
}
service anvil-auth-penalty {
name = anvil
}
service auth-worker {
name = auth-worker
}
service auth-client {
name = auth
}
service config {
name = config
}
service dict-async {
name = dict-async
}
service dict {
name = dict
}
service login/proxy-notify {
name = director
}
service dns-client {
name = dns-client
}
service doveadm-server {
name = doveadm
}
service imap-hibernate {
name = imap-hibernate
}
service imap {
name = imap-login
}
service imap-urlauth {
name = imap-urlauth-login
}
service imap-urlauth-worker {
name = imap-urlauth-worker
}
service token-login/imap-urlauth {
name = imap-urlauth
}
service imap-master {
name = imap
}
service indexer-worker {
name = indexer-worker
}
service indexer {
name = indexer
}
service ipc {
name = ipc
}
service lmtp {
name = lmtp
}
service log-errors {
name = log
}
service sieve {
name = managesieve-login
}
service login/sieve {
name = managesieve
}
service old-stats-mail {
name = old-stats
}
service pop3 {
name = pop3-login
}
service login/pop3 {
name = pop3
}
service replicator-doveadm {
name = replicator
}
service login/stats-writer {
name = stats
}
service submission {
name = submission-login
}
service login/submission {
name = submission
}
}
protocol lmtp {
mail_plugins = quota mailbox_alias acl mail_log notify sieve
postmaster_address = postmaster(a)mydomain.com
recipient_delimiter = +
service replication-notify-fifo {
name = aggregator
}
service anvil-auth-penalty {
name = anvil
}
service auth-worker {
name = auth-worker
}
service auth-client {
name = auth
}
service config {
name = config
}
service dict-async {
name = dict-async
}
service dict {
name = dict
}
service login/proxy-notify {
name = director
}
service dns-client {
name = dns-client
}
service doveadm-server {
name = doveadm
}
service imap-hibernate {
name = imap-hibernate
}
service imap {
name = imap-login
}
service imap-urlauth {
name = imap-urlauth-login
}
service imap-urlauth-worker {
name = imap-urlauth-worker
}
service token-login/imap-urlauth {
name = imap-urlauth
}
service imap-master {
name = imap
}
service indexer-worker {
name = indexer-worker
}
service indexer {
name = indexer
}
service ipc {
name = ipc
}
service lmtp {
name = lmtp
}
service log-errors {
name = log
}
service sieve {
name = managesieve-login
}
service login/sieve {
name = managesieve
}
service old-stats-mail {
name = old-stats
}
service pop3 {
name = pop3-login
}
service login/pop3 {
name = pop3
}
service replicator-doveadm {
name = replicator
}
service login/stats-writer {
name = stats
}
service submission {
name = submission-login
}
service login/submission {
name = submission
}
}
protocol imap {
imap_client_workarounds = tb-extra-mailbox-sep
mail_max_userip_connections = 256
mail_plugins = quota mailbox_alias acl mail_log notify imap_quota imap_acl
service replication-notify-fifo {
name = aggregator
}
service anvil-auth-penalty {
name = anvil
}
service auth-worker {
name = auth-worker
}
service auth-client {
name = auth
}
service config {
name = config
}
service dict-async {
name = dict-async
}
service dict {
name = dict
}
service login/proxy-notify {
name = director
}
service dns-client {
name = dns-client
}
service doveadm-server {
name = doveadm
}
service imap-hibernate {
name = imap-hibernate
}
service imap {
name = imap-login
}
service imap-urlauth {
name = imap-urlauth-login
}
service imap-urlauth-worker {
name = imap-urlauth-worker
}
service token-login/imap-urlauth {
name = imap-urlauth
}
service imap-master {
name = imap
}
service indexer-worker {
name = indexer-worker
}
service indexer {
name = indexer
}
service ipc {
name = ipc
}
service lmtp {
name = lmtp
}
service log-errors {
name = log
}
service sieve {
name = managesieve-login
}
service login/sieve {
name = managesieve
}
service old-stats-mail {
name = old-stats
}
service pop3 {
name = pop3-login
}
service login/pop3 {
name = pop3
}
service replicator-doveadm {
name = replicator
}
service login/stats-writer {
name = stats
}
service submission {
name = submission-login
}
service login/submission {
name = submission
}
}
protocol pop3 {
mail_max_userip_connections = 30
mail_plugins = quota mailbox_alias acl mail_log notify
pop3_client_workarounds = outlook-no-nuls oe-ns-eoh
pop3_uidl_format = %08Xu%08Xv
service replication-notify-fifo {
name = aggregator
}
service anvil-auth-penalty {
name = anvil
}
service auth-worker {
name = auth-worker
}
service auth-client {
name = auth
}
service config {
name = config
}
service dict-async {
name = dict-async
}
service dict {
name = dict
}
service login/proxy-notify {
name = director
}
service dns-client {
name = dns-client
}
service doveadm-server {
name = doveadm
}
service imap-hibernate {
name = imap-hibernate
}
service imap {
name = imap-login
}
service imap-urlauth {
name = imap-urlauth-login
}
service imap-urlauth-worker {
name = imap-urlauth-worker
}
service token-login/imap-urlauth {
name = imap-urlauth
}
service imap-master {
name = imap
}
service indexer-worker {
name = indexer-worker
}
service indexer {
name = indexer
}
service ipc {
name = ipc
}
service lmtp {
name = lmtp
}
service log-errors {
name = log
}
service sieve {
name = managesieve-login
}
service login/sieve {
name = managesieve
}
service old-stats-mail {
name = old-stats
}
service pop3 {
name = pop3-login
}
service login/pop3 {
name = pop3
}
service replicator-doveadm {
name = replicator
}
service login/stats-writer {
name = stats
}
service submission {
name = submission-login
}
service login/submission {
name = submission
}
}