From bcffb869724b628104eb2ab9e1da5937a73fa174 Mon Sep 17 00:00:00 2001 From: Christoph Haas Date: Tue, 30 Dec 2025 14:53:44 +0100 Subject: [PATCH 1/7] link typo --- src/content/docs/ispmail-trixie/330-quotas.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/content/docs/ispmail-trixie/330-quotas.mdx b/src/content/docs/ispmail-trixie/330-quotas.mdx index b561243..5c948cc 100644 --- a/src/content/docs/ispmail-trixie/330-quotas.mdx +++ b/src/content/docs/ispmail-trixie/330-quotas.mdx @@ -264,8 +264,8 @@ After a few emails you will see the rejection message: These are things you should consider if quotas do not seem to work properly: -- Check that your `/etc/dovecot/conf.d/99-ispmail-sql.conf` file looks as [described] - (/ispmail-trixie/dovecot#99-ispmail-sqlconf). Earlier version of this Trixie guide did not contain the +- Check that your `/etc/dovecot/conf.d/99-ispmail-sql.conf` file looks as + [described](/ispmail-trixie/dovecot#99-ispmail-sqlconf). Earlier version of this Trixie guide did not contain the `quota_storage_size` field in the `userdb sql` query. - Run `tcpdump -Ai lo port 13373` on the server to see if Postfix talks to the `quota-status` service. - Your users may complain that they have deleted many emails but are still over quota. Let them check if they actually From 87fab8c3e7bf9187946c17e4073872604568408f Mon Sep 17 00:00:00 2001 From: Christoph Haas Date: Tue, 30 Dec 2025 17:09:08 +0100 Subject: [PATCH 2/7] deprecated hint removed --- src/content/docs/ispmail-trixie/330-quotas.mdx | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/content/docs/ispmail-trixie/330-quotas.mdx b/src/content/docs/ispmail-trixie/330-quotas.mdx index 5c948cc..19cf6da 100644 --- a/src/content/docs/ispmail-trixie/330-quotas.mdx +++ b/src/content/docs/ispmail-trixie/330-quotas.mdx @@ -148,8 +148,6 @@ chmod u=rwx,g=rx,o= /usr/local/bin/ispmail-quota-warning.sh chown vmail:vmail /usr/local/bin/ispmail-quota-warning.sh ``` -Please change `@domain.com` to your main domain. - ### Global versus local By default you will probably allow all users to use a certain amount of disk space for their emails. That would be the From 8e2a0d0c88fdf463e150c7ab6cfb028c18820262 Mon Sep 17 00:00:00 2001 From: Christoph Haas Date: Tue, 30 Dec 2025 18:50:38 +0100 Subject: [PATCH 3/7] fix thresholds in quota warnings --- src/content/docs/ispmail-trixie/330-quotas.mdx | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/content/docs/ispmail-trixie/330-quotas.mdx b/src/content/docs/ispmail-trixie/330-quotas.mdx index 19cf6da..503f9ca 100644 --- a/src/content/docs/ispmail-trixie/330-quotas.mdx +++ b/src/content/docs/ispmail-trixie/330-quotas.mdx @@ -54,11 +54,20 @@ quota "User quota" { } } - # Set one warning level to 95% - warning warn-95 { - quota_storage_percentage = 95 + # Set one warning level to 100% + warning warn-100 { + quota_storage_percentage = 100 execute quota-warning { - args = 95 %{user} + args = 100 %{user} + } + } + + # User is no longer over quota + warning warn-under { + quota_storage_percentage = 100 + threshold = under + execute quota-warning { + args = below %{user} } } } From d97875ed389c66f1be20a0446e4494d38b7e07c6 Mon Sep 17 00:00:00 2001 From: Christoph Haas Date: Tue, 30 Dec 2025 18:59:50 +0100 Subject: [PATCH 4/7] move 100% alert before the 80% alert --- src/content/docs/ispmail-trixie/330-quotas.mdx | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/content/docs/ispmail-trixie/330-quotas.mdx b/src/content/docs/ispmail-trixie/330-quotas.mdx index 503f9ca..6562e61 100644 --- a/src/content/docs/ispmail-trixie/330-quotas.mdx +++ b/src/content/docs/ispmail-trixie/330-quotas.mdx @@ -46,14 +46,6 @@ quota_storage_grace = 50M # Define two warnings at 80% and 95% of quota usage. quota "User quota" { - # Set another warning level to 80% for early warnings - warning warn-80 { - quota_storage_percentage = 80 - execute quota-warning { - args = 80 %{user} - } - } - # Set one warning level to 100% warning warn-100 { quota_storage_percentage = 100 @@ -62,6 +54,14 @@ quota "User quota" { } } + # Set another warning level to 80% for early warnings + warning warn-80 { + quota_storage_percentage = 80 + execute quota-warning { + args = 80 %{user} + } + } + # User is no longer over quota warning warn-under { quota_storage_percentage = 100 From c69571740b15375684eb8fc1caba8f3139b80c81 Mon Sep 17 00:00:00 2001 From: Christoph Haas Date: Tue, 30 Dec 2025 19:10:08 +0100 Subject: [PATCH 5/7] add quota configuration --- public/ispmail.sh | 165 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 164 insertions(+), 1 deletion(-) diff --git a/public/ispmail.sh b/public/ispmail.sh index 5a4d19c..75b6efa 100755 --- a/public/ispmail.sh +++ b/public/ispmail.sh @@ -5,12 +5,17 @@ # # License: Creative Commons BY-NC-SA license # +# Please report bugs at https://github.com/Signum/ispmail-workaround-org/issues +# # Version 0.1 / 2025-12-14 # First release. # # Version 0.2 / 2025-12-28 # Enable plugins (managesieve, password) in Roundcube # +# Version 0.3 / 2025-12-30 +# Add quota setup +# usage() { echo "Usage: $0 -f fqdn" @@ -296,7 +301,9 @@ mysql /var/run/mysqld/mysqld.sock { } userdb sql { - query = SELECT email as user FROM virtual_users WHERE email='%{user}' + query = SELECT email as user, \ + IF(quota > 0, CONCAT(quota, 'B'), NULL) AS quota_storage_size \ + FROM virtual_users WHERE email='%{user}' iterate_query = SELECT email as user FROM virtual_users } @@ -885,6 +892,159 @@ EOF echo "✅ Catch-all aliases ready to use." } +############ Quota config ############# + +quota_config() { + cat > /etc/dovecot/conf.d/99-ispmail-quota.conf << 'EOF' +# Enable the quota plugin +mail_plugins { + quota = yes +} + +# Set global defaults. Keep this outside of a "quota {}" section so that it +# can be overriden with data from the virtual_users table. +# Allow 5 GB of space per default. +quota_storage_size = 5G + +# It is important to allow it so that Postfix can deliver an email to +# bring the user above 100% of quota usage. Otherwise you risk that the user +# is at 99.99% of quota but the last email cannot be delivered and gets stuck +# between Postfix and Dovecot. No email should be larger than this. +quota_storage_grace = 50M + +# Define two warnings at 80% and 95% of quota usage. +quota "User quota" { + # Set one warning level to 100% + warning warn-100 { + quota_storage_percentage = 100 + execute quota-warning { + args = 100 %{user} + } + } + + # Set another warning level to 80% for early warnings + warning warn-80 { + quota_storage_percentage = 80 + execute quota-warning { + args = 80 %{user} + } + } + + # User is no longer over quota + warning warn-under { + quota_storage_percentage = 100 + threshold = under + execute quota-warning { + args = below %{user} + } + } +} + +# Define what happens if the user goes over quota. Point to a script that +# creates a warning email to the user. The name "quota-warning" corresponds +# to the "execute" statement in the warning definitions. +service quota-warning { + executable = script /usr/local/bin/ispmail-quota-warning.sh + unix_listener quota-warning { + mode = 0660 + user = vmail + group = vmail + } +} + +# Add a new service so that Postfix can check if a user is over quota. +# It listens on TCP port 13373. +service quota-status { + executable = quota-status -p postfix + inet_listener quota-status { + listen = 127.0.0.1 + port = 13373 + } + client_limit = 1 +} + +# Enable the IMAP QUOTA extension, allowing IMAP clients to ask for the +# current quota usage. Roundcube displays the current space usage in +# the lower left corner. +protocol imap { + mail_plugins { + imap_quota = yes + } +} +EOF + +# Apply the configuration +systemctl reload dovecot + +cat > /usr/local/bin/ispmail-quota-warning.sh << 'EOF' +#!/bin/bash +# +# This script is part of the ISPmail configuration. +# It is called from /etc/dovecot/conf.d/99-ispmail-quota.conf +# and sends an email to the user if the quota is at 80%, over 100% +# or back below 100%. +# +# Christoph Haas +# Version 1.0 – 2025-12-30 + +LEVEL=$1 +USER=$2 +MAIL="From: postmaster@${USER#*@}" +MAIL+="\nSubject: Quota information" +MAIL+="\nX-Priority: 1" +MAIL+="\n\nThis is an automatic email from your friendly mail server.\n\n" + +if [ $LEVEL = "below" ]; then + MAIL+="Thanks for making some space. You will now be able to receive emails again." +elif [ $LEVEL -eq 80 ]; then + MAIL+="Your mailbox is currently using up 80% of the maximum space." + MAIL+="\nPlease consider deleting some emails. If your used space reached" + MAIL+="\n100% then you would not be able to receive further emails. I will" + MAIL+="\nhowever send you another email in that case." + MAIL+="\n" + MAIL+="\nThanks for your attention." +elif [ $LEVEL -eq 100 ]; then + MAIL+="I am afraid to tell you that your mailbox is now 100% full." + MAIL+="\nNew emails to your address will be rejected by the server." + MAIL+="\nPlease delete some emails immediately. I will send you another" + MAIL+="\nemail once you have made some space." + MAIL+="\n" + MAIL+="\nThanks for your attention." +fi + +echo -e $MAIL | /usr/lib/dovecot/dovecot-lda -d $USER -o quota_enforce=no +EOF + + chmod u=rwx,g=rx,o= /usr/local/bin/ispmail-quota-warning.sh + chown vmail:vmail /usr/local/bin/ispmail-quota-warning.sh + + # Apply the configuration + systemctl reload dovecot + + # Check if Dovecot tells us quota information + lines=$(doveadm quota get -A | grep -c john@example.org) + if [ $lines -ne 2 ]; then + echo "❌ The quota setup is not working. Check 'doveadm quota get -A'." + exit 1 + fi + + mariadb mailserver -Bse 'update virtual_users set quota=0 where email="john@example.org";' + quota_storage_check=$(dovecot quota get -u john@example.org | grep STORAGE | awk '{print $5}') + if [ $quota_storage_check -ne 5242880 ]; then + echo "❌ The quota storage value for John should be 5 GB. But it's not." + exit 1 + fi + + mariadb mailserver -Bse 'update virtual_users set quota=1024000 where email="john@example.org";' + quota_storage_check=$(dovecot quota get -u john@example.org | grep STORAGE | awk '{print $5}') + if [ $quota_storage_check -ne 1000 ]; then + echo "❌ The overriden quota storage value for John should be 1000 KB. But it's not." + exit 1 + fi + + echo "✅ Quotas are ready to use." +} + ############ Going-live ############# going_live() { @@ -994,6 +1154,9 @@ dkim_config banner "Setting up catch-all aliases" catchall_config +banner "Configuring quotas" +quota_config + banner "Final steps – changing dummy passwords" going_live From 030f528ea7fbf47d4f96e7cc960cf72cead1dcba Mon Sep 17 00:00:00 2001 From: Christoph Haas Date: Tue, 30 Dec 2025 19:15:41 +0100 Subject: [PATCH 6/7] link to installation script --- src/content/docs/ispmail-trixie/100-start.md | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/content/docs/ispmail-trixie/100-start.md b/src/content/docs/ispmail-trixie/100-start.md index 3ab3144..0f14a33 100644 --- a/src/content/docs/ispmail-trixie/100-start.md +++ b/src/content/docs/ispmail-trixie/100-start.md @@ -59,13 +59,19 @@ server. ## What this is not about -If you just want to have a working mail server and do not care how it works then this guide is not for you. Check out -ready solutions like [mailinabox](https://mailinabox.email/) or [iRedMail](http://www.iredmail.org/) or -[Mailcow](https://mailcow.email/). Be aware that running a mail server requires some technical understanding. And that’s -what the ISPmail guide is for. Experience from giving support to other sysadmins shows that most problems appear because -some detail in a complex setup goes wrong and they have no idea how to fix it. Email has evolved a lot over the past 40 -years. Go with ready solutions if you like. But I have a feeling that we meet again. And you will probably not save time -either taking the supposedly easy route. +If you just want to have a working mail server and do not care how it works then this guide may not be for you. There is +an [automated installation script](/ispmail-trixie/automated-installation/) that does all the steps of this guide +automatically for you. But that is no replacement for reading this guide and understanding how the server works. It is +merely meant to help you save time if you want to set up multiple servers. + +Be aware that running a mail server requires some technical understanding. And that’s what the ISPmail guide is for. +Experience from giving support to other sysadmins shows that most problems appear because some detail in a complex setup +goes wrong and they have no idea how to fix it. Email has evolved a lot over the past 40 years. Go with ready solutions +if you like. But I have a feeling that we meet again. And you will probably not save time either taking the supposedly +easy route. + +There are also other projects that give you a ready solution like [mailinabox](https://mailinabox.email/), +[iRedMail](http://www.iredmail.org/) or [Mailcow](https://mailcow.email/). ## What's new From 2186d0af02f31828824d6786045840a56cd51bae Mon Sep 17 00:00:00 2001 From: Christoph Haas Date: Wed, 31 Dec 2025 11:46:00 +0100 Subject: [PATCH 7/7] add warning about potential breakage --- src/content/docs/ispmail-trixie/330-quotas.mdx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/content/docs/ispmail-trixie/330-quotas.mdx b/src/content/docs/ispmail-trixie/330-quotas.mdx index 6562e61..038107a 100644 --- a/src/content/docs/ispmail-trixie/330-quotas.mdx +++ b/src/content/docs/ispmail-trixie/330-quotas.mdx @@ -12,6 +12,12 @@ import { Aside } from "@astrojs/starlight/components"; This feature is completely optional. If you are eager to get finished then skip this page and maybe come back later. + + Quotas are size limits for users. You can make sure that users do not waste arbitrary amounts of disk space but are forced to clean up old emails every now and then.