quota-status fails when size=0 from Postfix

Christoph Haas email at christoph-haas.de
Thu Jul 29 03:14:20 EEST 2021


Dear list,

I've been pulling my hair out today and kindly ask you for help. I'm on 
Debian Bullseye with Dovecot 2.3.13 and Postfix 3.5.6. Users are stored 
in SQL and I want to use quotas. Basically I followed 
https://doc.dovecot.org/configuration_manual/quota_plugin/#quota-service

With mail_debug enabled I see that the information from SQL is fetched 
correctly:

dovecot: quota-status(test at bullseye.example.org)<45148><>: Debug: 
auth-master: userdb lookup(test at bullseye.example.org): auth USER input: 
test at bullseye.example.org quota_rule=*:bytes=1000 
home=/var/vmail/bullseye.example.org/test uid=5000 gid=5000

So the quota rule "*:bytes=1000" is loaded as intended for testing.
Before handing the email over to Dovecot through LMTP Postfix should 
call the quota-service (policy daemon) to determine if the user is over 
quota:

smtpd_recipient_restrictions = \
   reject_unauth_destination \
   check_policy_service inet:localhost:12340

This is still by the book.

What I found:
- sending a test mail with Thunderbird properly returns a 5xx status
   (over quota)
- sending a test mail with SWAKS returns DUNNO
   (swaks is an SMTP test tool)

I have used tcpdump to look into the communication on port 12340 and the 
difference appears to be the "size=0" line that Postfix sends if I use 
SWAKS. Output from SWAKS:
  -> RCPT TO:<test at bullseye.example.org>
<-  250 2.1.5 Ok

However if Thunderbird sends an email it uses something like

  -> RCPT TO:<test at bullseye.example.org> SIZE=12345

If I understand the situation correctly then Postfix extracts the SIZE=… 
value and uses that to send it to the quota-status policy daemon.

The user however is definitely over quota:

$> doveadm quota get -u test at bullseye.example.org
Quota name Type        Value Limit %
User quota STORAGE     1     1     100
User quota MESSAGE     1     -     0

So whatever the size of the incoming email is, it should be rejected.
As quota-status returns DUNNO, Postfix will send the email to Dovecot 
through LMTP. And LMTP in turn does another quota check and correctly 
rejects the email:

postfix/lmtp[45153]: 573419D6A3: to=<test at bullseye.example.org>, 
relay=iredmail-test[private/dovecot-lmtp], delay=0.08, 
delays=0.05/0.01/0.01/0.01, dsn=5.2.2, status=bounced (host 
iredmail-test[private/dovecot-lmtp] said: 552 5.2.2 
<test at bullseye.example.org> Quota exceeded (mailbox for user is full) 
(in reply to end of DATA command))

Problem here is that a bounce is created and Postfix is sending 
backscatter. Had "quota-service" indicated that the mailbox is over 
quota then Postfix had instantly rejected the email without any bounce.

I can also reproduce this effect by talking to the quota-status daemon:

printf "recipient=test at bullseye.example.org\nsize=0\n\n" | nc localhost 
12340
action=DUNNO

printf "recipient=test at bullseye.example.org\nsize=10000\n\n" | nc 
localhost 12340
action=554 5.2.2 Quota exceeded (mailbox for user is full)

Is this a feature? A bug? An evil coincidence?

Thanks for reading this far. I know that this matter seems a bit 
complicated. But it feels like Dovecot's behavior leads to backscatter 
and of course I'd like to avoid that.

Kindly… Christoph


More information about the dovecot mailing list