diff --git a/deploy-chatmail/src/deploy_chatmail/dovecot/dovecot.conf.j2 b/deploy-chatmail/src/deploy_chatmail/dovecot/dovecot.conf.j2 index 0e2a7ca1..5834e717 100644 --- a/deploy-chatmail/src/deploy_chatmail/dovecot/dovecot.conf.j2 +++ b/deploy-chatmail/src/deploy_chatmail/dovecot/dovecot.conf.j2 @@ -79,7 +79,7 @@ plugin { quota_rule = *:storage=100M quota_max_mail_size=30M quota_grace = 0 - quota_over_flag_value = TRUE + # quota_over_flag_value = TRUE } diff --git a/deploy-chatmail/src/deploy_chatmail/postfix/main.cf.j2 b/deploy-chatmail/src/deploy_chatmail/postfix/main.cf.j2 index 7508e460..303aed13 100644 --- a/deploy-chatmail/src/deploy_chatmail/postfix/main.cf.j2 +++ b/deploy-chatmail/src/deploy_chatmail/postfix/main.cf.j2 @@ -37,6 +37,8 @@ mydestination = relayhost = mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128 mailbox_size_limit = 0 +# maximum 30MB sized messages +message_size_limit = 31457280 recipient_delimiter = + inet_interfaces = all inet_protocols = all diff --git a/deploy-chatmail/src/deploy_chatmail/postfix/master.cf b/deploy-chatmail/src/deploy_chatmail/postfix/master.cf index 310542a3..e071acf0 100644 --- a/deploy-chatmail/src/deploy_chatmail/postfix/master.cf +++ b/deploy-chatmail/src/deploy_chatmail/postfix/master.cf @@ -9,7 +9,7 @@ # service type private unpriv chroot wakeup maxproc command + args # (yes) (yes) (no) (never) (100) # ========================================================================== -smtp inet n - y - - smtpd +smtp inet n - y - - smtpd -v #smtp inet n - y - 1 postscreen #smtpd pass - - y - - smtpd #dnsblog unix - - y - 0 dnsblog diff --git a/online-tests/conftest.py b/online-tests/conftest.py index ef9688e1..86d99d29 100644 --- a/online-tests/conftest.py +++ b/online-tests/conftest.py @@ -1,5 +1,6 @@ import os import io +import random import imaplib import smtplib import itertools @@ -50,13 +51,15 @@ class SmtpConn: @pytest.fixture def gencreds(maildomain): - prefix = str(time.time()) count = itertools.count() def gen(): while 1: num = next(count) - yield f"user{prefix}_{num}@{maildomain}", f"password{prefix}_{num}" + alphanumeric = "abcdefghijklmnopqrstuvwxyz1234567890" + user = "".join(random.choices(alphanumeric, k=10)) + password = "".join(random.choices(alphanumeric, k=10)) + yield f"{user}@{maildomain}", f"{password}" return lambda: next(gen()) @@ -99,7 +102,7 @@ def cmfactory(request, maildomain, gencreds, tmpdir, data): am = ACFactory(request=request, tmpdir=tmpdir, testprocess=testproc, data=data) yield am if hasattr(request.node, "rep_call") and request.node.rep_call.failed: - if testprocess.pytestconfig.getoption("--extra-info"): + if testproc.pytestconfig.getoption("--extra-info"): logfile = io.StringIO() am.dump_imap_summary(logfile=logfile) print(logfile.getvalue()) diff --git a/online-tests/test_1_deltachat.py b/online-tests/test_1_deltachat.py index 1439898b..86e0d5d7 100644 --- a/online-tests/test_1_deltachat.py +++ b/online-tests/test_1_deltachat.py @@ -1,3 +1,7 @@ +import random +import pytest + + class TestMailSending: def test_one_on_one(self, cmfactory, lp): ac1, ac2 = cmfactory.get_online_accounts(2) @@ -9,3 +13,41 @@ class TestMailSending: lp.sec("wait for ac2 to receive message") msg2 = ac2._evtracker.wait_next_incoming_message() assert msg2.text == "message0" + + def test_exceed_quota(self, cmfactory, lp, tmpdir): + ac1, ac2 = cmfactory.get_online_accounts(2) + chat = cmfactory.get_accepted_chat(ac1, ac2) + + quota = 1024 * 1024 * 100 + attachsize = 1 * 1024 * 1024 + num_to_send = quota // attachsize + 2 + lp.sec(f"ac1: send {num_to_send} large files to ac2") + lp.indent(f"per-user quota is assumed to be: {quota/(1024*1024)}MB") + alphanumeric = "abcdefghijklmnopqrstuvwxyz1234567890" + msgs = [] + for i in range(num_to_send): + attachment = tmpdir / f"attachment{i}" + data = "".join(random.choice(alphanumeric) for i in range(1024)) + with open(attachment, "w+") as f: + for j in range(attachsize // len(data)): + f.write(data) + + msg = chat.send_file(str(attachment)) + msgs.append(msg) + lp.indent(f"Sent out msg {i}, size {attachsize/(1024*1024)}MB") + + lp.sec("ac2: check that at least one message failed due to quota") + bytes_sent = 0 + for i, msg in enumerate(msgs): + # wait for the message to be received + msg_received = ac2.wait_next_incoming_message() + if msg.is_out_failed(): + assert bytes_sent + 10 * 1024*1024 > quota, "quota kicked in too early" + lp.indent("good, message sending failed because quota was exceeded") + lp.indent(chat.get_messages()[i].get_message_info()) + return + assert msg.is_out_delivered(), msg.get_message_info() + bytes_sent += attachsize + mb = bytes_sent // (1024*1024) + lp.indent(f"message {i} success, bytes transmitted so far {mb}MB") + pytest.fail("sending succeeded although messages should exceed quota")