diff --git a/core/admin/mailu/configuration.py b/core/admin/mailu/configuration.py
index d2d34d88..50733d52 100644
--- a/core/admin/mailu/configuration.py
+++ b/core/admin/mailu/configuration.py
@@ -46,6 +46,7 @@ DEFAULT_CONFIG = {
'DKIM_SELECTOR': 'dkim',
'DKIM_PATH': '/dkim/{domain}.{selector}.key',
'DEFAULT_QUOTA': 1000000000,
+ 'MESSAGE_RATELIMIT': '100/hour',
# Web settings
'SITENAME': 'Mailu',
'WEBSITE': 'https://mailu.io',
diff --git a/core/admin/mailu/internal/views/postfix.py b/core/admin/mailu/internal/views/postfix.py
index c358c37f..06918c61 100644
--- a/core/admin/mailu/internal/views/postfix.py
+++ b/core/admin/mailu/internal/views/postfix.py
@@ -1,5 +1,6 @@
-from mailu import models
+from mailu import models, utils
from mailu.internal import internal
+from flask import current_app as app
import flask
import idna
@@ -31,7 +32,6 @@ def postfix_alias_map(alias):
destination = models.Email.resolve_destination(localpart, domain_name)
return flask.jsonify(",".join(destination)) if destination else flask.abort(404)
-
@internal.route("/postfix/transport/{% trans %}User settings{% endtrans %}
{% trans %}Email{% endtrans %}
{% trans %}Features{% endtrans %}
- {% trans %}Quota{% endtrans %}
+ {% trans %}Storage Quota{% endtrans %}
+ {% trans %}Sending Quota{% endtrans %}
{% trans %}Comment{% endtrans %}
{% trans %}Created{% endtrans %}
{% trans %}Last edit{% endtrans %}
@@ -41,6 +42,8 @@
{% if user.enable_pop %}pop3{% endif %}
{{ user.quota_bytes_used | filesizeformat }} / {{ (user.quota_bytes | filesizeformat) if user.quota_bytes else '∞' }}
+ {% set limiter = user.sender_limiter %}
+ {{ limiter.get_window_stats()[1] }} / {{ limiter.limit }}
{{ user.comment or '-' }}
{{ user.created_at }}
{{ user.updated_at or '' }}
diff --git a/core/postfix/conf/main.cf b/core/postfix/conf/main.cf
index 8f35f609..6f5a20b8 100644
--- a/core/postfix/conf/main.cf
+++ b/core/postfix/conf/main.cf
@@ -100,6 +100,7 @@ smtpd_sender_login_maps = ${podop}senderlogin
smtpd_helo_required = yes
smtpd_client_restrictions =
+ check_sasl_access ${podop}senderrate,
permit_mynetworks,
check_sender_access ${podop}senderaccess,
reject_non_fqdn_sender,
diff --git a/core/postfix/start.py b/core/postfix/start.py
index e0c781b7..139616b2 100755
--- a/core/postfix/start.py
+++ b/core/postfix/start.py
@@ -25,7 +25,8 @@ def start_podop():
("recipientmap", "url", url + "recipient/map/§"),
("sendermap", "url", url + "sender/map/§"),
("senderaccess", "url", url + "sender/access/§"),
- ("senderlogin", "url", url + "sender/login/§")
+ ("senderlogin", "url", url + "sender/login/§"),
+ ("senderrate", "url", url + "sender/rate/§")
])
def is_valid_postconf_line(line):
diff --git a/setup/flavors/compose/mailu.env b/setup/flavors/compose/mailu.env
index d45f5517..52f4ee04 100644
--- a/setup/flavors/compose/mailu.env
+++ b/setup/flavors/compose/mailu.env
@@ -62,6 +62,11 @@ ANTIVIRUS={{ antivirus_enabled or 'none' }}
# Max attachment size will be 33% smaller
MESSAGE_SIZE_LIMIT={{ message_size_limit or '50000000' }}
+# Message rate limit (per user)
+{% if message_ratelimit_pd > '0' %}
+MESSAGE_RATELIMIT={{ message_ratelimit_pd }}/day
+{% endif %}
+
# Networks granted relay permissions
# Use this with care, all hosts in this networks will be able to send mail without authentication!
RELAYNETS=
diff --git a/setup/templates/steps/config.html b/setup/templates/steps/config.html
index 72b83915..87410fca 100644
--- a/setup/templates/steps/config.html
+++ b/setup/templates/steps/config.html
@@ -55,6 +55,13 @@ Or in plain english: if receivers start to classify your mail as spam, this post
/ day +
+