Merge remote-tracking branch 'upstream/master' into update_deps

master
Alexander Graf 3 years ago
commit 0315ed78d9
No known key found for this signature in database
GPG Key ID: B8A9DC143E075629

@ -54,6 +54,7 @@ DEFAULT_CONFIG = {
'DKIM_PATH': '/dkim/{domain}.{selector}.key', 'DKIM_PATH': '/dkim/{domain}.{selector}.key',
'DEFAULT_QUOTA': 1000000000, 'DEFAULT_QUOTA': 1000000000,
'MESSAGE_RATELIMIT': '200/day', 'MESSAGE_RATELIMIT': '200/day',
'MESSAGE_RATELIMIT_EXEMPTION': '',
'RECIPIENT_DELIMITER': '', 'RECIPIENT_DELIMITER': '',
# Web settings # Web settings
'SITENAME': 'Mailu', 'SITENAME': 'Mailu',
@ -154,6 +155,7 @@ class ConfigManager:
self.config['PERMANENT_SESSION_LIFETIME'] = timedelta(hours=int(self.config['SESSION_LIFETIME'])) self.config['PERMANENT_SESSION_LIFETIME'] = timedelta(hours=int(self.config['SESSION_LIFETIME']))
hostnames = [host.strip() for host in self.config['HOSTNAMES'].split(',')] hostnames = [host.strip() for host in self.config['HOSTNAMES'].split(',')]
self.config['AUTH_RATELIMIT_EXEMPTION'] = set(ipaddress.ip_network(cidr, False) for cidr in (cidr.strip() for cidr in self.config['AUTH_RATELIMIT_EXEMPTION'].split(',')) if cidr) self.config['AUTH_RATELIMIT_EXEMPTION'] = set(ipaddress.ip_network(cidr, False) for cidr in (cidr.strip() for cidr in self.config['AUTH_RATELIMIT_EXEMPTION'].split(',')) if cidr)
self.config['MESSAGE_RATELIMIT_EXEMPTION'] = set([s for s in self.config['MESSAGE_RATELIMIT_EXEMPTION'].lower().replace(' ', '').split(',') if s])
self.config['HOSTNAMES'] = ','.join(hostnames) self.config['HOSTNAMES'] = ','.join(hostnames)
self.config['HOSTNAME'] = hostnames[0] self.config['HOSTNAME'] = hostnames[0]

@ -149,6 +149,8 @@ def postfix_sender_login(sender):
def postfix_sender_rate(sender): def postfix_sender_rate(sender):
""" Rate limit outbound emails per sender login """ Rate limit outbound emails per sender login
""" """
if sender in flask.current_app.config['MESSAGE_RATELIMIT_EXEMPTION']:
flask.abort(404)
user = models.User.get(sender) or flask.abort(404) user = models.User.get(sender) or flask.abort(404)
return flask.abort(404) if user.sender_limiter.hit() else flask.jsonify("450 4.2.1 You are sending too many emails too fast.") return flask.abort(404) if user.sender_limiter.hit() else flask.jsonify("450 4.2.1 You are sending too many emails too fast.")

@ -14,17 +14,14 @@ def vault_error(*messages, status=404):
@internal.route("/rspamd/vault/v1/dkim/<domain_name>", methods=['GET']) @internal.route("/rspamd/vault/v1/dkim/<domain_name>", methods=['GET'])
def rspamd_dkim_key(domain_name): def rspamd_dkim_key(domain_name):
domain = models.Domain.query.get(domain_name) or flask.abort(vault_error('unknown domain')) selectors = []
key = domain.dkim_key or flask.abort(vault_error('no dkim key', status=400)) if domain := models.Domain.query.get(domain_name):
return flask.jsonify({ if key := domain.dkim_key:
'data': { selectors.append(
'selectors': [
{ {
'domain' : domain.name, 'domain' : domain.name,
'key' : key.decode('utf8'), 'key' : key.decode('utf8'),
'selector': flask.current_app.config.get('DKIM_SELECTOR', 'dkim'), 'selector': flask.current_app.config.get('DKIM_SELECTOR', 'dkim'),
} }
] )
} return flask.jsonify({'data': {'selectors': selectors}})
})

@ -39,7 +39,7 @@ def login():
flask.session.regenerate() flask.session.regenerate()
flask_login.login_user(user) flask_login.login_user(user)
response = flask.redirect(destination) response = flask.redirect(destination)
response.set_cookie('rate_limit', utils.limiter.device_cookie(username), max_age=31536000, path=flask.url_for('sso.login')) response.set_cookie('rate_limit', utils.limiter.device_cookie(username), max_age=31536000, path=flask.url_for('sso.login'), secure=app.config['SESSION_COOKIE_SECURE'], httponly=True)
flask.current_app.logger.info(f'Login succeeded for {username} from {client_ip}.') flask.current_app.logger.info(f'Login succeeded for {username} from {client_ip}.')
return response return response
else: else:

@ -17,7 +17,7 @@ queue_directory = /queue
message_size_limit = {{ MESSAGE_SIZE_LIMIT }} message_size_limit = {{ MESSAGE_SIZE_LIMIT }}
# Relayed networks # Relayed networks
mynetworks = 127.0.0.1/32 [::1]/128 {{ SUBNET }} {{ RELAYNETS.split(",") | join(' ') }} mynetworks = 127.0.0.1/32 [::1]/128 {{ SUBNET }} {% if RELAYNETS %}{{ RELAYNETS.split(",") | join(' ') }}{% endif %}
# Empty alias list to override the configuration variable and disable NIS # Empty alias list to override the configuration variable and disable NIS
alias_maps = alias_maps =

@ -69,9 +69,11 @@ The ``MESSAGE_SIZE_LIMIT`` is the maximum size of a single email. It should not
be too low to avoid dropping legitimate emails and should not be too high to be too low to avoid dropping legitimate emails and should not be too high to
avoid filling the disks with large junk emails. avoid filling the disks with large junk emails.
The ``MESSAGE_RATELIMIT`` is the limit of messages a single user can send. This is The ``MESSAGE_RATELIMIT`` (default: 200/day) is the maximum number of messages
meant to fight outbound spam in case of compromised or malicious account on the a single user can send. ``MESSAGE_RATELIMIT_EXEMPTION`` contains a comma delimited
server. list of user email addresses that are exempted from any restriction. Those
settings are meant to reduce outbound spam in case of compromised or malicious
account on the server.
The ``RELAYNETS`` (default: unset) is a comma delimited list of network addresses The ``RELAYNETS`` (default: unset) is a comma delimited list of network addresses
for which mail is relayed for with no authentication required. This should be for which mail is relayed for with no authentication required. This should be

Loading…
Cancel
Save