Merge branch 'master' into enforce-tls-admin

master
lub 4 years ago committed by GitHub
commit f3f0a4d86d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

65
.github/stale.yml vendored

@ -0,0 +1,65 @@
# Configuration for probot-stale - https://github.com/probot/stale
# Number of days of inactivity before an Issue or Pull Request becomes stale
daysUntilStale: 21
# Number of days of inactivity before an Issue or Pull Request with the stale label is closed.
# Set to false to disable. If disabled, issues still need to be closed manually, but will remain marked as stale.
daysUntilClose: 14
# Only issues or pull requests with all of these labels are check if stale. Defaults to `[]` (disabled)
onlyLabels: []
# Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable
exemptLabels:
- priority/p0
- priority/p1
- priority/p2
- backlog
- status/wip
- type/bug
- type/discussion
- type/enhancement
- type/feature
- type/security
# Set to true to ignore issues in a project (defaults to false)
exemptProjects: false
# Set to true to ignore issues in a milestone (defaults to false)
exemptMilestones: true
# Set to true to ignore issues with an assignee (defaults to false)
exemptAssignees: true
# Label to use when marking as stale
staleLabel: status/response_needed
# Comment to post when marking as stale. Set to `false` to disable
markComment: >
This issue has been automatically marked as stale because it has not had
recent activity. It will be closed if no further activity occurs. Thank you
for your contributions.
# Comment to post when removing the stale label.
# unmarkComment: >
# Your comment here.
# Comment to post when closing a stale Issue or Pull Request.
closeComment: >
This issue has not seen activity since as it has become stale. It will now be
automatically closed. Please note that this is an automatic action, and not
meant in any offensive way.
# Limit the number of actions per hour, from 1-30. Default is 30
limitPerRun: 30
# Limit to only `issues` or `pulls`
only: issues
# Optionally, specify configuration settings that are specific to just 'issues' or 'pulls':
# pulls:
# <any of above config here>
#
# issues:
# <any of above config here>

@ -27,7 +27,7 @@ pull_request_rules:
- name: Trusted author and 1 approved review; trigger bors r+ - name: Trusted author and 1 approved review; trigger bors r+
conditions: conditions:
- author~=^(kaiyou|muhlemmer|mildred|HorayNarea|adi90x|hoellen|ofthesun9|Nebukadneza|micw)$ - author~=^(mergify|kaiyou|muhlemmer|mildred|HorayNarea|adi90x|hoellen|ofthesun9|Nebukadneza|micw|lub|Diman0)$
- -title~=(WIP|wip) - -title~=(WIP|wip)
- -label~=^(status/wip|status/blocked|review/need2)$ - -label~=^(status/wip|status/blocked|review/need2)$
- "#approved-reviews-by>=1" - "#approved-reviews-by>=1"
@ -35,18 +35,18 @@ pull_request_rules:
comment: comment:
message: bors r+ message: bors r+
- name: Backport to 1.7 branch - name: Backport to 1.8 branch
conditions: conditions:
- base=master - base=master
- label=type/backport - label=type/backport
actions: actions:
backport: backport:
branches: branches:
- '1.7' - '1.8'
- name: remove outdated reviews - name: remove outdated reviews
conditions: conditions:
- base~=^(master|1.7)$ - base~=^(master|1.8)$
actions: actions:
dismiss_reviews: dismiss_reviews:
approved: True approved: True

@ -5,9 +5,10 @@ branches:
- '1.5' - '1.5'
- '1.6' - '1.6'
- '1.7' - '1.7'
- '1.8'
- master - master
# version tags, e.g. 1.7.1 # version tags, e.g. 1.7.1
- /^1\.[567]\.\d+$/ - /^1\.[5678]\.\d+$/
# pre-releases, e.g. 1.8-pre1 # pre-releases, e.g. 1.8-pre1
- /^1\.8-pre\d+$/ - /^1\.8-pre\d+$/
# test branches, e.g. test-debian # test branches, e.g. test-debian
@ -33,6 +34,7 @@ install:
before_script: before_script:
- docker-compose -v - docker-compose -v
- echo "$DOCKER_PW" | docker login --username $DOCKER_UN --password-stdin
- docker-compose -f tests/build.yml build - docker-compose -f tests/build.yml build
- sudo -- sh -c 'mkdir -p /mailu && cp -r tests/certs /mailu && chmod 600 /mailu/certs/*' - sudo -- sh -c 'mkdir -p /mailu && cp -r tests/certs /mailu && chmod 600 /mailu/certs/*'

@ -25,3 +25,6 @@ Other contributors:
- [Tim Mohlmann](https://github.com/muhlemmer) - [Contributions](https://github.com/Mailu/Mailu/commits?author=muhlemmer) - [Tim Mohlmann](https://github.com/muhlemmer) - [Contributions](https://github.com/Mailu/Mailu/commits?author=muhlemmer)
- [Ionut Filip](https://github.com/ionutfilip) - [Contributions](https://github.com/Mailu/Mailu/commits?author=ionutfilip) - [Ionut Filip](https://github.com/ionutfilip) - [Contributions](https://github.com/Mailu/Mailu/commits?author=ionutfilip)
- [Ichikawa Yuriko](https://github.com/IchikawaYukko) - [Contributions](https://github.com/Mailu/Mailu/commits?author=IchikawaYukko) Japanese translation - [Ichikawa Yuriko](https://github.com/IchikawaYukko) - [Contributions](https://github.com/Mailu/Mailu/commits?author=IchikawaYukko) Japanese translation
- [Dimitri Huisman](https://github.com/Diman0) - [Contributions](https://github.com/Mailu/Mailu/commits?author=Diman0)
- [lub](https://github.com/lub) - [Contributions](https://github.com/Mailu/Mailu/commits?author=lub)
- [Dario Ernst](https://github.com/Nebukadneza) - [Contributions](https://github.com/Mailu/Mailu/commits?author=Nebukadneza)

@ -1,11 +1,63 @@
Changelog Changelog
========= =========
Notable changes to this project are documented in the current file. For more Upgrade should run fine as long as you generate a new compose or stack
details about individual changes, see the Git log. You should read this before configuration and upgrade your mailu.env.
upgrading Mailu as some changes will include useful notes.
Please note that the current 1.8 is what we call a "soft release": Its there for everyone to see and use, but to limit possible user-impact of this very big release, its not yet the default in the setup-utility for new users. When upgrading, please treat it with some care, and be sure to always have backups!
There are some changes to the configuration overrides. Override files are now mounted read-only into the containers.
The Dovecot and Postfix overrides are moved in their own sub-directory.
If there are local override files, they will need to be moved from overrides/ to overrides/dovecot and overrides/postfix/.
See https://mailu.io/1.8/faq.html#how-can-i-override-settings for all the mappings.
Please note that the shipped image for PostgreSQL database is deprecated.
We advise to switch to an external database server.
<!-- TOWNCRIER --> <!-- TOWNCRIER -->
v1.8.0 - 2020-09-28
--------------------
- Features: Add support for backward-forwarding using SRS ([#328](https://github.com/Mailu/Mailu/issues/328))
- Features: Add options to support different architectures builds ([#985](https://github.com/Mailu/Mailu/issues/985))
- Features: Add support for Traefik v2 certificate dumping ([#1011](https://github.com/Mailu/Mailu/issues/1011))
- Features: Resolve hosts to IPs if only HOST_* is set. If *_ADDRESS is set, leave it unresolved. ([#1113](https://github.com/Mailu/Mailu/issues/1113))
- Features: - Use nginx as http endpoint on kubernetes to simplify ingress ([#1158](https://github.com/Mailu/Mailu/issues/1158))
- Features: Advertise correct mail capabilities through the front-container, this also enables support for PIPELINING in mail-protocols and IMAP IDLE which is a (potential) performance gain. ([#1160](https://github.com/Mailu/Mailu/issues/1160))
- Features: Change default password scheme to PBKDF2 ([#1194](https://github.com/Mailu/Mailu/issues/1194))
- Features: Enable access log of admin service only for log levels of INFO and finer ([#1197](https://github.com/Mailu/Mailu/issues/1197))
- Features: japanese loca is now available ([#1207](https://github.com/Mailu/Mailu/issues/1207))
- Features: Allow to reject virus mails by setting ANTIVITUS_ACTION=reject ([#1259](https://github.com/Mailu/Mailu/issues/1259))
- Features: Update roundcube to 1.4.0 and enable the new elastic skin ([#1267](https://github.com/Mailu/Mailu/issues/1267))
- Features: The roundcube container does support mysql now (no setup integration yet) ([#1268](https://github.com/Mailu/Mailu/issues/1268))
- Features: Added CardDAV-Plugin for webmail roundcube. ([#1298](https://github.com/Mailu/Mailu/issues/1298))
- Features: Allow users to use server-sided full-text-search again by adding the dovecot fts-xapian plugin ([#1320](https://github.com/Mailu/Mailu/issues/1320))
- Features: Relay a domain to a nonstandard SMTP port by adding ":<port_num>" to the remote hostname or IP address. ([#1357](https://github.com/Mailu/Mailu/issues/1357))
- Features: Allow to enforce TLS for outbound mail by setting OUTBOUND_TLS_LEVEL=encrypt for postfix. ([#1478](https://github.com/Mailu/Mailu/issues/1478))
- Features: Introduce option to disable dovecot full-text-search by an enviroment variable. ([#1538](https://github.com/Mailu/Mailu/issues/1538))
- Features: Add support for AUTH LOGIN authentication mechanism for relaying email via smart hosts. ([#1635](https://github.com/Mailu/Mailu/issues/1635))
- Bugfixes: Fix the password encoding upon authentication ([#1139](https://github.com/Mailu/Mailu/issues/1139))
- Bugfixes: Fix piping mail into rspamd when moving from/to junk-folder ([#1177](https://github.com/Mailu/Mailu/issues/1177))
- Bugfixes: Separate HOST_ANTISPAM in HOST_ANTISPAM_MILTER and HOST_ANTISPAM_WEBUI because of different ports ([#1190](https://github.com/Mailu/Mailu/issues/1190))
- Bugfixes: Make postfix mailqueue persistent ([#1208](https://github.com/Mailu/Mailu/issues/1208))
- Bugfixes: Kubernetes manifests updated to be compatible with Kubernetes 1.16 (breaks compatibility with older k8s versions) ([#1241](https://github.com/Mailu/Mailu/issues/1241))
- Bugfixes: Use pip package for radicale to fix failing builds caused by [alpine]upstream package rebuild against different python version ([#1255](https://github.com/Mailu/Mailu/issues/1255))
- Bugfixes: Ratelimit counts up on failed auth only now ([#1278](https://github.com/Mailu/Mailu/issues/1278))
- Bugfixes: Disable Health checks on swarm mode ([#1289](https://github.com/Mailu/Mailu/issues/1289))
- Bugfixes: Enable the From header for message delivery report in Roundcube and ensure DKIM Signature ([#1381](https://github.com/Mailu/Mailu/issues/1381))
- Bugfixes: Fix alias resolution in regard to case: A specifically matching alias of wrong case is now preferred over a wildcard alias that might have »eaten« it previously. ([#1387](https://github.com/Mailu/Mailu/issues/1387))
- Bugfixes: Show SPF records in accordance with RFC 7208: Previously we instructed admins to create SPF and TXT records, where only TXT records are correct now. !! Attention !! You need to manually remove the SPF-typed records and keep only TXT in your DNS. ([#1394](https://github.com/Mailu/Mailu/issues/1394))
- Bugfixes: Cover relearning messages when moving bewteen Ham and Spam status ([#1438](https://github.com/Mailu/Mailu/issues/1438))
- Bugfixes: Defining POSTMASTER through setup tool apply also to DMARC_RUA and DMARC_RUF settings ([#1463](https://github.com/Mailu/Mailu/issues/1463))
- Bugfixes: Allow IPv6 authenticated connections in PostgreSQL pg_hba.conf ([#1479](https://github.com/Mailu/Mailu/issues/1479))
- Bugfixes: Check postfix mailqueue permissions before start-up ([#1486](https://github.com/Mailu/Mailu/issues/1486))
- Bugfixes: Fixes certbot renewal ([#1564](https://github.com/Mailu/Mailu/issues/1564))
- Improved Documentation: Added documentation that describes how spam filtering works in Mailu. ([#1167](https://github.com/Mailu/Mailu/issues/1167))
- Improved Documentation: Add documentation for the web administration interface. ([#1590](https://github.com/Mailu/Mailu/issues/1590))
- Deprecations and Removals: Dovecot: Delete obsolete data volume ([#1221](https://github.com/Mailu/Mailu/issues/1221))
- Misc: ([#508](https://github.com/Mailu/Mailu/issues/508), [#1098](https://github.com/Mailu/Mailu/issues/1098), [#1214](https://github.com/Mailu/Mailu/issues/1214), [#1308](https://github.com/Mailu/Mailu/issues/1308), [#1444](https://github.com/Mailu/Mailu/issues/1444), [#1512](https://github.com/Mailu/Mailu/issues/1512))
v1.7.0 - 2019-08-22 v1.7.0 - 2019-08-22
------------------- -------------------
@ -14,7 +66,7 @@ configuration and upgrade your mailu.env.
If you run the PostgreSQL server, the database was upgrade, so you will need to If you run the PostgreSQL server, the database was upgrade, so you will need to
dump the database before upgrading and load the dump after the upgrade is dump the database before upgrading and load the dump after the upgrade is
complete. Please not that the shipped image for PostgreSQL database will be complete. Please note that the shipped image for PostgreSQL database will be
deprecated before 1.8.0, you can switch to an external database server by then. deprecated before 1.8.0, you can switch to an external database server by then.
- Deprecation: using the internal postgres image will be deprecated by 1.8.0 - Deprecation: using the internal postgres image will be deprecated by 1.8.0

@ -0,0 +1,44 @@
Thank you for opening an issue with Mailu. Please understand that issues are meant for bugs and enhancement-requests.
For **user-support questions**, reach out to us on [matrix](https://matrix.to/#/#mailu:tedomum.net).
To be able to help you best, we need some more information.
## Before you open your issue
- [ ] Check if no issue or pull-request for this already exists.
- [ ] Check [documentation](https://mailu.io/master/) and [FAQ](https://mailu.io/master/faq.html). (Tip, use the search function on the documentation page)
- [ ] You understand `Mailu` is made by volunteers in their **free time** — be conscise, civil and accept that delays can occur.
- [ ] The title of the issue should be short and simple. It should contain specific terms related to the actual issue. Be specific while writing the title.
## Environment & Versions
### Environment
- [ ] docker-compose
- [ ] kubernetes
- [ ] docker swarm
### Versions
To find your version, get the image name of a mailu container and read the version from the tag (example for version 1.7).
```
$> docker ps -a | grep mailu
140b09d4b09c mailu/roundcube:1.7 "docker-php-entrypoi…" 2 weeks ago Up 2 days (healthy) 80/tcp
$> grep MAILU_VERSION docker-compose.yml mailu.env
```
## Description
Further explain the bug in a few words. It should be clear what the unexpected behaviour is. Share it in an easy-to-understand language.
## Replication Steps
Steps for replicating your issue
## Expected behaviour
Explain what results you expected - be as specific as possible. Just saying "it doesnt work as expected" is not useful. It's also helpful to describe what you actually experienced.
## Logs
Often it is very useful to include log fragments of the involved component. You can get the logs via `docker logs <container name> --tail 1000`. For example for the admin container:
`docker logs mailu_admin_1 --tail 1000`
or using docker-compose `docker-compose -f /mailu/docker-compose.yml logs --tail 1000 admin`
If you can find the relevant section, please share only the parts that seem relevant. If you have any logs, please enclose them in code tags, like so:
````markdown
```
Your logs here!
```
````

@ -24,7 +24,7 @@ DEFAULT_CONFIG = {
'SQLALCHEMY_TRACK_MODIFICATIONS': False, 'SQLALCHEMY_TRACK_MODIFICATIONS': False,
# Statistics management # Statistics management
'INSTANCE_ID_PATH': '/data/instance', 'INSTANCE_ID_PATH': '/data/instance',
'STATS_ENDPOINT': '0.{}.stats.mailu.io', 'STATS_ENDPOINT': '18.{}.stats.mailu.io',
# Common configuration variables # Common configuration variables
'SECRET_KEY': 'changeMe', 'SECRET_KEY': 'changeMe',
'DOMAIN': 'mailu.io', 'DOMAIN': 'mailu.io',
@ -53,8 +53,9 @@ DEFAULT_CONFIG = {
'RECAPTCHA_PUBLIC_KEY': '', 'RECAPTCHA_PUBLIC_KEY': '',
'RECAPTCHA_PRIVATE_KEY': '', 'RECAPTCHA_PRIVATE_KEY': '',
# Advanced settings # Advanced settings
'PASSWORD_SCHEME': 'PBKDF2',
'LOG_LEVEL': 'WARNING', 'LOG_LEVEL': 'WARNING',
'SESSION_COOKIE_SECURE': True,
'CREDENTIAL_ROUNDS': 12,
# Host settings # Host settings
'HOST_IMAP': 'imap', 'HOST_IMAP': 'imap',
'HOST_LMTP': 'imap:2525', 'HOST_LMTP': 'imap:2525',
@ -101,6 +102,15 @@ class ConfigManager(dict):
if self.config["WEBMAIL"] != "none": if self.config["WEBMAIL"] != "none":
self.config["WEBMAIL_ADDRESS"] = self.get_host_address("WEBMAIL") self.config["WEBMAIL_ADDRESS"] = self.get_host_address("WEBMAIL")
def __get_env(self, key, value):
key_file = key + "_FILE"
if key_file in os.environ:
with open(os.environ.get(key_file)) as file:
value_from_file = file.read()
return value_from_file.strip()
else:
return os.environ.get(key, value)
def __coerce_value(self, value): def __coerce_value(self, value):
if isinstance(value, str) and value.lower() in ('true','yes'): if isinstance(value, str) and value.lower() in ('true','yes'):
return True return True
@ -112,7 +122,7 @@ class ConfigManager(dict):
self.config.update(app.config) self.config.update(app.config)
# get environment variables # get environment variables
self.config.update({ self.config.update({
key: self.__coerce_value(os.environ.get(key, value)) key: self.__coerce_value(self.__get_env(key, value))
for key, value in DEFAULT_CONFIG.items() for key, value in DEFAULT_CONFIG.items()
}) })
self.resolve_hosts() self.resolve_hosts()
@ -124,6 +134,8 @@ class ConfigManager(dict):
self.config['RATELIMIT_STORAGE_URL'] = 'redis://{0}/2'.format(self.config['REDIS_ADDRESS']) self.config['RATELIMIT_STORAGE_URL'] = 'redis://{0}/2'.format(self.config['REDIS_ADDRESS'])
self.config['QUOTA_STORAGE_URL'] = 'redis://{0}/1'.format(self.config['REDIS_ADDRESS']) self.config['QUOTA_STORAGE_URL'] = 'redis://{0}/1'.format(self.config['REDIS_ADDRESS'])
self.config['SESSION_COOKIE_SAMESITE'] = 'Strict'
self.config['SESSION_COOKIE_HTTPONLY'] = True
# update the app config itself # update the app config itself
app.config = self app.config = self

@ -22,6 +22,20 @@ STATUSES = {
}), }),
} }
def check_credentials(user, password, ip, protocol=None):
if not user or not user.enabled or (protocol == "imap" and not user.enable_imap) or (protocol == "pop3" and not user.enable_pop):
return False
is_ok = False
# All tokens are 32 characters hex lowercase
if len(password) == 32:
for token in user.tokens:
if (token.check_password(password) and
(not token.ip or token.ip == ip)):
is_ok = True
break
if not is_ok and user.check_password(password):
is_ok = True
return is_ok
def handle_authentication(headers): def handle_authentication(headers):
""" Handle an HTTP nginx authentication request """ Handle an HTTP nginx authentication request
@ -65,20 +79,7 @@ def handle_authentication(headers):
password = raw_password.encode("iso8859-1").decode("utf8") password = raw_password.encode("iso8859-1").decode("utf8")
ip = urllib.parse.unquote(headers["Client-Ip"]) ip = urllib.parse.unquote(headers["Client-Ip"])
user = models.User.query.get(user_email) user = models.User.query.get(user_email)
status = False if check_credentials(user, password, ip, protocol):
if user:
for token in user.tokens:
if (token.check_password(password) and
(not token.ip or token.ip == ip)):
status = True
if user.check_password(password):
status = True
if status:
if protocol == "imap" and not user.enable_imap:
status = False
elif protocol == "pop3" and not user.enable_pop:
status = False
if status and user.enabled:
return { return {
"Auth-Status": "OK", "Auth-Status": "OK",
"Auth-Server": server, "Auth-Server": server,
@ -102,7 +103,7 @@ def get_status(protocol, status):
return status, codes[protocol] return status, codes[protocol]
def extract_host_port(host_and_port, default_port): def extract_host_port(host_and_port, default_port):
host, _, port = re.match('^(.*)(:([0-9]*))?$', host_and_port).groups() host, _, port = re.match('^(.*?)(:([0-9]*))?$', host_and_port).groups()
return host, int(port) if port else default_port return host, int(port) if port else default_port
def get_server(protocol, authenticated=False): def get_server(protocol, authenticated=False):

@ -53,7 +53,7 @@ def basic_authentication():
encoded = authorization.replace("Basic ", "") encoded = authorization.replace("Basic ", "")
user_email, password = base64.b64decode(encoded).split(b":") user_email, password = base64.b64decode(encoded).split(b":")
user = models.User.query.get(user_email.decode("utf8")) user = models.User.query.get(user_email.decode("utf8"))
if user and user.enabled and user.check_password(password.decode("utf8")): if nginx.check_credentials(user, password.decode('utf-8'), flask.request.remote_addr, "web"):
response = flask.Response() response = flask.Response()
response.headers["X-User"] = user.email response.headers["X-User"] = user.email
return response return response

@ -86,13 +86,10 @@ def admin(localpart, domain_name, password, mode='create'):
@click.argument('localpart') @click.argument('localpart')
@click.argument('domain_name') @click.argument('domain_name')
@click.argument('password') @click.argument('password')
@click.argument('hash_scheme', required=False)
@flask_cli.with_appcontext @flask_cli.with_appcontext
def user(localpart, domain_name, password, hash_scheme=None): def user(localpart, domain_name, password):
""" Create a user """ Create a user
""" """
if hash_scheme is None:
hash_scheme = app.config['PASSWORD_SCHEME']
domain = models.Domain.query.get(domain_name) domain = models.Domain.query.get(domain_name)
if not domain: if not domain:
domain = models.Domain(name=domain_name) domain = models.Domain(name=domain_name)
@ -102,7 +99,7 @@ def user(localpart, domain_name, password, hash_scheme=None):
domain=domain, domain=domain,
global_admin=False global_admin=False
) )
user.set_password(password, hash_scheme=hash_scheme) user.set_password(password)
db.session.add(user) db.session.add(user)
db.session.commit() db.session.commit()
@ -111,17 +108,14 @@ def user(localpart, domain_name, password, hash_scheme=None):
@click.argument('localpart') @click.argument('localpart')
@click.argument('domain_name') @click.argument('domain_name')
@click.argument('password') @click.argument('password')
@click.argument('hash_scheme', required=False)
@flask_cli.with_appcontext @flask_cli.with_appcontext
def password(localpart, domain_name, password, hash_scheme=None): def password(localpart, domain_name, password):
""" Change the password of an user """ Change the password of an user
""" """
email = '{0}@{1}'.format(localpart, domain_name) email = '{0}@{1}'.format(localpart, domain_name)
user = models.User.query.get(email) user = models.User.query.get(email)
if hash_scheme is None:
hash_scheme = app.config['PASSWORD_SCHEME']
if user: if user:
user.set_password(password, hash_scheme=hash_scheme) user.set_password(password)
else: else:
print("User " + email + " not found.") print("User " + email + " not found.")
db.session.commit() db.session.commit()
@ -148,13 +142,10 @@ def domain(domain_name, max_users=-1, max_aliases=-1, max_quota_bytes=0):
@click.argument('localpart') @click.argument('localpart')
@click.argument('domain_name') @click.argument('domain_name')
@click.argument('password_hash') @click.argument('password_hash')
@click.argument('hash_scheme')
@flask_cli.with_appcontext @flask_cli.with_appcontext
def user_import(localpart, domain_name, password_hash, hash_scheme = None): def user_import(localpart, domain_name, password_hash):
""" Import a user along with password hash. """ Import a user along with password hash.
""" """
if hash_scheme is None:
hash_scheme = app.config['PASSWORD_SCHEME']
domain = models.Domain.query.get(domain_name) domain = models.Domain.query.get(domain_name)
if not domain: if not domain:
domain = models.Domain(name=domain_name) domain = models.Domain(name=domain_name)
@ -164,7 +155,7 @@ def user_import(localpart, domain_name, password_hash, hash_scheme = None):
domain=domain, domain=domain,
global_admin=False global_admin=False
) )
user.set_password(password_hash, hash_scheme=hash_scheme, raw=True) user.set_password(password_hash, raw=True)
db.session.add(user) db.session.add(user)
db.session.commit() db.session.commit()
@ -217,7 +208,6 @@ def config_update(verbose=False, delete_objects=False):
localpart = user_config['localpart'] localpart = user_config['localpart']
domain_name = user_config['domain'] domain_name = user_config['domain']
password_hash = user_config.get('password_hash', None) password_hash = user_config.get('password_hash', None)
hash_scheme = user_config.get('hash_scheme', None)
domain = models.Domain.query.get(domain_name) domain = models.Domain.query.get(domain_name)
email = '{0}@{1}'.format(localpart, domain_name) email = '{0}@{1}'.format(localpart, domain_name)
optional_params = {} optional_params = {}
@ -239,7 +229,7 @@ def config_update(verbose=False, delete_objects=False):
else: else:
for k in optional_params: for k in optional_params:
setattr(user, k, optional_params[k]) setattr(user, k, optional_params[k])
user.set_password(password_hash, hash_scheme=hash_scheme, raw=True) user.set_password(password_hash, raw=True)
db.session.add(user) db.session.add(user)
aliases = new_config.get('aliases', []) aliases = new_config.get('aliases', [])

@ -1,14 +1,13 @@
from mailu import dkim from mailu import dkim
from sqlalchemy.ext import declarative from sqlalchemy.ext import declarative
from passlib import context, hash from passlib import context, hash, registry
from datetime import datetime, date from datetime import datetime, date
from email.mime import text from email.mime import text
from flask import current_app as app from flask import current_app as app
import flask_sqlalchemy import flask_sqlalchemy
import sqlalchemy import sqlalchemy
import re
import time import time
import os import os
import glob import glob
@ -305,6 +304,7 @@ class User(Base, Email):
""" A user is an email address that has a password to access a mailbox. """ A user is an email address that has a password to access a mailbox.
""" """
__tablename__ = "user" __tablename__ = "user"
_ctx = None
domain = db.relationship(Domain, domain = db.relationship(Domain,
backref=db.backref('users', cascade='all, delete-orphan')) backref=db.backref('users', cascade='all, delete-orphan'))
@ -362,25 +362,38 @@ class User(Base, Email):
self.reply_enddate > now self.reply_enddate > now
) )
scheme_dict = {'PBKDF2': "pbkdf2_sha512", def get_password_context():
'BLF-CRYPT': "bcrypt", if User._ctx:
'SHA512-CRYPT': "sha512_crypt", return User._ctx
'SHA256-CRYPT': "sha256_crypt",
'MD5-CRYPT': "md5_crypt",
'CRYPT': "des_crypt"}
def get_password_context(self): schemes = registry.list_crypt_handlers()
return context.CryptContext( # scrypt throws a warning if the native wheels aren't found
schemes=self.scheme_dict.values(), schemes.remove('scrypt')
default=self.scheme_dict[app.config['PASSWORD_SCHEME']], # we can't leave plaintext schemes as they will be misidentified
for scheme in schemes:
if scheme.endswith('plaintext'):
schemes.remove(scheme)
User._ctx = context.CryptContext(
schemes=schemes,
default='bcrypt_sha256',
bcrypt_sha256__rounds=app.config['CREDENTIAL_ROUNDS'],
deprecated='auto'
) )
return User._ctx
def check_password(self, password): def check_password(self, password):
context = self.get_password_context() reference = self.password
reference = re.match('({[^}]+})?(.*)', self.password).group(2) # strip {scheme} if that's something mailu has added
result = context.verify(password, reference) # passlib will identify *crypt based hashes just fine
if result and context.identify(reference) != context.default_scheme(): # on its own
self.set_password(password) if self.password.startswith("{"):
scheme = self.password.split('}')[0][1:]
if scheme in ['PBKDF2', 'BLF-CRYPT', 'SHA512-CRYPT', 'SHA256-CRYPT', 'MD5-CRYPT', 'CRYPT']:
reference = reference[len(scheme)+2:]
result, new_hash = User.get_password_context().verify_and_update(password, reference)
if new_hash:
self.password = new_hash
db.session.add(self) db.session.add(self)
db.session.commit() db.session.commit()
return result return result
@ -389,13 +402,10 @@ class User(Base, Email):
"""Set password for user with specified encryption scheme """Set password for user with specified encryption scheme
@password: plain text password to encrypt (if raw == True the hash itself) @password: plain text password to encrypt (if raw == True the hash itself)
""" """
if hash_scheme is None:
hash_scheme = app.config['PASSWORD_SCHEME']
# for the list of hash schemes see https://wiki2.dovecot.org/Authentication/PasswordSchemes
if raw: if raw:
self.password = '{'+hash_scheme+'}' + password self.password = password
else: else:
self.password = '{'+hash_scheme+'}' + self.get_password_context().encrypt(password, self.scheme_dict[hash_scheme]) self.password = User.get_password_context().hash(password)
def get_managed_domains(self): def get_managed_domains(self):
if self.global_admin: if self.global_admin:
@ -493,10 +503,18 @@ class Token(Base):
ip = db.Column(db.String(255)) ip = db.Column(db.String(255))
def check_password(self, password): def check_password(self, password):
return hash.sha256_crypt.verify(password, self.password) if self.password.startswith("$5$"):
if hash.sha256_crypt.verify(password, self.password):
self.set_password(password)
db.session.add(self)
db.session.commit()
return True
return False
return hash.pbkdf2_sha256.verify(password, self.password)
def set_password(self, password): def set_password(self, password):
self.password = hash.sha256_crypt.using(rounds=1000).hash(password) # tokens have 128bits of entropy, they are not bruteforceable
self.password = hash.pbkdf2_sha256.using(rounds=1).hash(password)
def __str__(self): def __str__(self):
return self.comment return self.comment

@ -8,7 +8,7 @@ msgstr ""
"Project-Id-Version: PROJECT VERSION\n" "Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2018-04-22 12:10+0200\n" "POT-Creation-Date: 2018-04-22 12:10+0200\n"
"PO-Revision-Date: 2020-04-26 13:09+0000\n" "PO-Revision-Date: 2021-03-04 18:46+0000\n"
"Last-Translator: Jaume Barber <jaumebarber@gmail.com>\n" "Last-Translator: Jaume Barber <jaumebarber@gmail.com>\n"
"Language-Team: Catalan <https://translate.tedomum.net/projects/mailu/admin/" "Language-Team: Catalan <https://translate.tedomum.net/projects/mailu/admin/"
"ca/>\n" "ca/>\n"
@ -139,7 +139,7 @@ msgstr "Nom per mostrar"
#: mailu/ui/forms.py:98 #: mailu/ui/forms.py:98
msgid "Enable spam filter" msgid "Enable spam filter"
msgstr "Activeu filtre d'spam" msgstr "Activeu filtre spam"
#: mailu/ui/forms.py:99 #: mailu/ui/forms.py:99
msgid "Spam filter tolerance" msgid "Spam filter tolerance"
@ -204,7 +204,8 @@ msgstr "Àlies"
#: mailu/ui/forms.py:138 #: mailu/ui/forms.py:138
msgid "Use SQL LIKE Syntax (e.g. for catch-all aliases)" msgid "Use SQL LIKE Syntax (e.g. for catch-all aliases)"
msgstr "Feu servir sintaxi tipus SQL (ex. per a agafar tots els àlies)" msgstr ""
"Feu servir sintaxi tipus SQL (ex. per seleccionar tots els àlies catch-all)"
#: mailu/ui/forms.py:145 #: mailu/ui/forms.py:145
msgid "Admin email" msgid "Admin email"
@ -246,11 +247,11 @@ msgstr "Mantén els correus al servidor"
#: mailu/ui/forms.py:168 #: mailu/ui/forms.py:168
msgid "Announcement subject" msgid "Announcement subject"
msgstr "Tema de l'avís" msgstr "Tema de la notificació"
#: mailu/ui/forms.py:170 #: mailu/ui/forms.py:170
msgid "Announcement body" msgid "Announcement body"
msgstr "Missatge de l'avís" msgstr "Missatge de la notificació"
#: mailu/ui/forms.py:172 #: mailu/ui/forms.py:172
msgid "Send" msgid "Send"
@ -258,7 +259,7 @@ msgstr "Envia"
#: mailu/ui/templates/announcement.html:4 #: mailu/ui/templates/announcement.html:4
msgid "Public announcement" msgid "Public announcement"
msgstr "Avís públic" msgstr "Notificació pública"
#: mailu/ui/templates/client.html:4 mailu/ui/templates/sidebar.html:82 #: mailu/ui/templates/client.html:4 mailu/ui/templates/sidebar.html:82
msgid "Client setup" msgid "Client setup"
@ -304,7 +305,7 @@ msgstr "Resposta automàtica"
#: mailu/ui/templates/fetch/list.html:4 mailu/ui/templates/sidebar.html:26 #: mailu/ui/templates/fetch/list.html:4 mailu/ui/templates/sidebar.html:26
#: mailu/ui/templates/user/list.html:36 #: mailu/ui/templates/user/list.html:36
msgid "Fetched accounts" msgid "Fetched accounts"
msgstr "Comptes trobats" msgstr "Comptes vinculats"
#: mailu/ui/templates/sidebar.html:31 mailu/ui/templates/token/list.html:4 #: mailu/ui/templates/sidebar.html:31 mailu/ui/templates/token/list.html:4
msgid "Authentication tokens" msgid "Authentication tokens"
@ -316,7 +317,7 @@ msgstr "Administració"
#: mailu/ui/templates/sidebar.html:44 #: mailu/ui/templates/sidebar.html:44
msgid "Announcement" msgid "Announcement"
msgstr "Avís" msgstr "Notificació"
#: mailu/ui/templates/sidebar.html:49 #: mailu/ui/templates/sidebar.html:49
msgid "Administrators" msgid "Administrators"
@ -324,7 +325,7 @@ msgstr "Administradors"
#: mailu/ui/templates/sidebar.html:54 #: mailu/ui/templates/sidebar.html:54
msgid "Relayed domains" msgid "Relayed domains"
msgstr "Dominis tramesos" msgstr "Dominis traspassats"
#: mailu/ui/templates/sidebar.html:59 mailu/ui/templates/user/settings.html:15 #: mailu/ui/templates/sidebar.html:59 mailu/ui/templates/user/settings.html:15
msgid "Antispam" msgid "Antispam"
@ -546,18 +547,19 @@ msgid ""
" expires." " expires."
msgstr "" msgstr ""
"Si no sabeu configurar un registre <code>MX</code> a la zona DNS,\n" "Si no sabeu configurar un registre <code>MX</code> a la zona DNS,\n"
"contacteu el vostre proveïdor o administrador de DNS. Per favor, espereu \n" "contacteu amb el vostre proveïdor o administrador de DNS. Per favor, espereu "
"\n"
"uns quants minuts despres d'ajustar el registre <code>MX</code> perquè la " "uns quants minuts despres d'ajustar el registre <code>MX</code> perquè la "
"caixet \n" "caixet \n"
"del servidor local expire." "del servidor local expire."
#: mailu/ui/templates/fetch/create.html:4 #: mailu/ui/templates/fetch/create.html:4
msgid "Add a fetched account" msgid "Add a fetched account"
msgstr "Afegiu un compte (fetched)" msgstr "Afegiu un compte extern"
#: mailu/ui/templates/fetch/edit.html:4 #: mailu/ui/templates/fetch/edit.html:4
msgid "Update a fetched account" msgid "Update a fetched account"
msgstr "Actualitzeu un compte (fetched)" msgstr "Actualitzeu compte extern"
#: mailu/ui/templates/fetch/list.html:12 #: mailu/ui/templates/fetch/list.html:12
msgid "Add an account" msgid "Add an account"
@ -605,11 +607,11 @@ msgstr "Editeu domini llegat (relayed)"
#: mailu/ui/templates/relay/list.html:4 #: mailu/ui/templates/relay/list.html:4
msgid "Relayed domain list" msgid "Relayed domain list"
msgstr "Llista de dominis llegats (relayed)" msgstr "Llista de dominis traspassats"
#: mailu/ui/templates/relay/list.html:9 #: mailu/ui/templates/relay/list.html:9
msgid "New relayed domain" msgid "New relayed domain"
msgstr "Nou domini llegat (relayed)" msgstr "Nou domini traspassat"
#: mailu/ui/templates/token/create.html:4 #: mailu/ui/templates/token/create.html:4
msgid "Create an authentication token" msgid "Create an authentication token"
@ -653,7 +655,7 @@ msgstr "Ajustos d'usuari"
#: mailu/ui/templates/user/list.html:21 #: mailu/ui/templates/user/list.html:21
msgid "Features" msgid "Features"
msgstr "Funcions" msgstr "Característiques"
#: mailu/ui/templates/user/password.html:4 #: mailu/ui/templates/user/password.html:4
msgid "Password update" msgid "Password update"
@ -669,11 +671,11 @@ msgstr "Auto-reenviament"
#: mailu/ui/templates/user/signup_domain.html:8 #: mailu/ui/templates/user/signup_domain.html:8
msgid "pick a domain for the new account" msgid "pick a domain for the new account"
msgstr "tria un domini per al compte nou" msgstr "trieu un domini per al compte nou"
#: mailu/ui/templates/user/signup_domain.html:14 #: mailu/ui/templates/user/signup_domain.html:14
msgid "Domain" msgid "Domain"
msgstr "Domini" msgstr "Nom de domini"
#: mailu/ui/templates/user/signup_domain.html:15 #: mailu/ui/templates/user/signup_domain.html:15
msgid "Available slots" msgid "Available slots"

@ -1,11 +1,16 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Mailu\n"
"PO-Revision-Date: 2021-03-04 18:46+0000\n"
"Last-Translator: Anonymous <noreply@weblate.org>\n"
"Language-Team: German <https://translate.tedomum.net/projects/mailu/admin/de/"
">\n"
"Language: de\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"X-Generator: POEditor.com\n" "Plural-Forms: nplurals=2; plural=n != 1;\n"
"Project-Id-Version: Mailu\n" "X-Generator: Weblate 4.0.1\n"
"Language: de\n"
#: mailu/ui/forms.py:32 #: mailu/ui/forms.py:32
msgid "Invalid email address." msgid "Invalid email address."
@ -64,7 +69,7 @@ msgstr "Passwort bestätigen"
#: mailu/ui/forms.py:80 mailu/ui/templates/user/list.html:22 #: mailu/ui/forms.py:80 mailu/ui/templates/user/list.html:22
#: mailu/ui/templates/user/signup_domain.html:16 #: mailu/ui/templates/user/signup_domain.html:16
msgid "Quota" msgid "Quota"
msgstr "Quota" msgstr "Kontingent"
#: mailu/ui/forms.py:81 #: mailu/ui/forms.py:81
msgid "Allow IMAP access" msgid "Allow IMAP access"
@ -699,4 +704,3 @@ msgstr "Domain"
#: mailu/ui/templates/user/signup_domain.html:15 #: mailu/ui/templates/user/signup_domain.html:15
msgid "Available slots" msgid "Available slots"
msgstr "Verfügbare Plätze" msgstr "Verfügbare Plätze"

@ -8,8 +8,8 @@ msgstr ""
"Project-Id-Version: PROJECT VERSION\n" "Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2018-04-22 12:10+0200\n" "POT-Creation-Date: 2018-04-22 12:10+0200\n"
"PO-Revision-Date: 2020-03-11 23:03+0000\n" "PO-Revision-Date: 2021-03-04 18:46+0000\n"
"Last-Translator: Jae Beojkkoch <jae@jae.moe>\n" "Last-Translator: Jaume Barber <jaumebarber@gmail.com>\n"
"Language-Team: English <https://translate.tedomum.net/projects/mailu/admin/" "Language-Team: English <https://translate.tedomum.net/projects/mailu/admin/"
"en/>\n" "en/>\n"
"Language: en\n" "Language: en\n"
@ -17,7 +17,7 @@ msgstr ""
"Content-Type: text/plain; charset=utf-8\n" "Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n" "Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 3.11.2\n" "X-Generator: Weblate 4.0.1\n"
"Generated-By: Babel 2.5.3\n" "Generated-By: Babel 2.5.3\n"
#: mailu/ui/forms.py:32 #: mailu/ui/forms.py:32
@ -30,13 +30,13 @@ msgstr "Confirm"
#: mailu/ui/forms.py:40 mailu/ui/forms.py:77 #: mailu/ui/forms.py:40 mailu/ui/forms.py:77
msgid "E-mail" msgid "E-mail"
msgstr "" msgstr "E-mail"
#: mailu/ui/forms.py:41 mailu/ui/forms.py:78 mailu/ui/forms.py:90 #: mailu/ui/forms.py:41 mailu/ui/forms.py:78 mailu/ui/forms.py:90
#: mailu/ui/forms.py:109 mailu/ui/forms.py:162 #: mailu/ui/forms.py:109 mailu/ui/forms.py:162
#: mailu/ui/templates/client.html:32 mailu/ui/templates/client.html:59 #: mailu/ui/templates/client.html:32 mailu/ui/templates/client.html:59
msgid "Password" msgid "Password"
msgstr "" msgstr "Password"
#: mailu/ui/forms.py:42 mailu/ui/templates/login.html:4 #: mailu/ui/forms.py:42 mailu/ui/templates/login.html:4
#: mailu/ui/templates/sidebar.html:111 #: mailu/ui/templates/sidebar.html:111
@ -51,7 +51,7 @@ msgstr ""
#: mailu/ui/forms.py:47 #: mailu/ui/forms.py:47
msgid "Maximum user count" msgid "Maximum user count"
msgstr "" msgstr "Maximum user count"
#: mailu/ui/forms.py:48 #: mailu/ui/forms.py:48
msgid "Maximum alias count" msgid "Maximum alias count"
@ -59,11 +59,11 @@ msgstr ""
#: mailu/ui/forms.py:49 #: mailu/ui/forms.py:49
msgid "Maximum user quota" msgid "Maximum user quota"
msgstr "" msgstr "Maximum user quota"
#: mailu/ui/forms.py:50 #: mailu/ui/forms.py:50
msgid "Enable sign-up" msgid "Enable sign-up"
msgstr "" msgstr "Enable sign-up"
#: mailu/ui/forms.py:51 mailu/ui/forms.py:72 mailu/ui/forms.py:83 #: mailu/ui/forms.py:51 mailu/ui/forms.py:72 mailu/ui/forms.py:83
#: mailu/ui/forms.py:128 mailu/ui/forms.py:140 #: mailu/ui/forms.py:128 mailu/ui/forms.py:140
@ -71,28 +71,28 @@ msgstr ""
#: mailu/ui/templates/relay/list.html:19 mailu/ui/templates/token/list.html:19 #: mailu/ui/templates/relay/list.html:19 mailu/ui/templates/token/list.html:19
#: mailu/ui/templates/user/list.html:23 #: mailu/ui/templates/user/list.html:23
msgid "Comment" msgid "Comment"
msgstr "" msgstr "Comment"
#: mailu/ui/forms.py:52 mailu/ui/forms.py:61 mailu/ui/forms.py:66 #: mailu/ui/forms.py:52 mailu/ui/forms.py:61 mailu/ui/forms.py:66
#: mailu/ui/forms.py:73 mailu/ui/forms.py:132 mailu/ui/forms.py:141 #: mailu/ui/forms.py:73 mailu/ui/forms.py:132 mailu/ui/forms.py:141
msgid "Create" msgid "Create"
msgstr "" msgstr "Create"
#: mailu/ui/forms.py:57 #: mailu/ui/forms.py:57
msgid "Initial admin" msgid "Initial admin"
msgstr "" msgstr "Initial admin"
#: mailu/ui/forms.py:58 #: mailu/ui/forms.py:58
msgid "Admin password" msgid "Admin password"
msgstr "" msgstr "Admin password"
#: mailu/ui/forms.py:59 mailu/ui/forms.py:79 mailu/ui/forms.py:91 #: mailu/ui/forms.py:59 mailu/ui/forms.py:79 mailu/ui/forms.py:91
msgid "Confirm password" msgid "Confirm password"
msgstr "" msgstr "Confirm password"
#: mailu/ui/forms.py:65 #: mailu/ui/forms.py:65
msgid "Alternative name" msgid "Alternative name"
msgstr "" msgstr "Alternative name"
#: mailu/ui/forms.py:70 #: mailu/ui/forms.py:70
msgid "Relayed domain name" msgid "Relayed domain name"
@ -105,23 +105,23 @@ msgstr ""
#: mailu/ui/forms.py:80 mailu/ui/templates/user/list.html:22 #: mailu/ui/forms.py:80 mailu/ui/templates/user/list.html:22
#: mailu/ui/templates/user/signup_domain.html:16 #: mailu/ui/templates/user/signup_domain.html:16
msgid "Quota" msgid "Quota"
msgstr "" msgstr "Quota"
#: mailu/ui/forms.py:81 #: mailu/ui/forms.py:81
msgid "Allow IMAP access" msgid "Allow IMAP access"
msgstr "" msgstr "Allow IMAP access"
#: mailu/ui/forms.py:82 #: mailu/ui/forms.py:82
msgid "Allow POP3 access" msgid "Allow POP3 access"
msgstr "" msgstr "Allow POP3 access"
#: mailu/ui/forms.py:84 #: mailu/ui/forms.py:84
msgid "Enabled" msgid "Enabled"
msgstr "" msgstr "Enabled"
#: mailu/ui/forms.py:85 #: mailu/ui/forms.py:85
msgid "Save" msgid "Save"
msgstr "" msgstr "Save"
#: mailu/ui/forms.py:89 #: mailu/ui/forms.py:89
msgid "Email address" msgid "Email address"
@ -131,7 +131,7 @@ msgstr ""
#: mailu/ui/templates/user/signup.html:4 #: mailu/ui/templates/user/signup.html:4
#: mailu/ui/templates/user/signup_domain.html:4 #: mailu/ui/templates/user/signup_domain.html:4
msgid "Sign up" msgid "Sign up"
msgstr "" msgstr "Sign up"
#: mailu/ui/forms.py:97 #: mailu/ui/forms.py:97
msgid "Displayed name" msgid "Displayed name"
@ -139,15 +139,15 @@ msgstr ""
#: mailu/ui/forms.py:98 #: mailu/ui/forms.py:98
msgid "Enable spam filter" msgid "Enable spam filter"
msgstr "" msgstr "Enable spam filter"
#: mailu/ui/forms.py:99 #: mailu/ui/forms.py:99
msgid "Spam filter tolerance" msgid "Spam filter tolerance"
msgstr "" msgstr "Spam filter tolerance"
#: mailu/ui/forms.py:100 #: mailu/ui/forms.py:100
msgid "Enable forwarding" msgid "Enable forwarding"
msgstr "" msgstr "Enable forwarding"
#: mailu/ui/forms.py:101 #: mailu/ui/forms.py:101
msgid "Keep a copy of the emails" msgid "Keep a copy of the emails"
@ -160,7 +160,7 @@ msgstr ""
#: mailu/ui/forms.py:105 #: mailu/ui/forms.py:105
msgid "Save settings" msgid "Save settings"
msgstr "" msgstr "Save settings"
#: mailu/ui/forms.py:110 #: mailu/ui/forms.py:110
msgid "Password check" msgid "Password check"
@ -184,11 +184,11 @@ msgstr ""
#: mailu/ui/forms.py:119 #: mailu/ui/forms.py:119
msgid "End of vacation" msgid "End of vacation"
msgstr "" msgstr "End of vacation"
#: mailu/ui/forms.py:120 #: mailu/ui/forms.py:120
msgid "Update" msgid "Update"
msgstr "" msgstr "Update"
#: mailu/ui/forms.py:125 #: mailu/ui/forms.py:125
msgid "Your token (write it down, as it will never be displayed again)" msgid "Your token (write it down, as it will never be displayed again)"
@ -196,11 +196,11 @@ msgstr ""
#: mailu/ui/forms.py:130 mailu/ui/templates/token/list.html:20 #: mailu/ui/forms.py:130 mailu/ui/templates/token/list.html:20
msgid "Authorized IP" msgid "Authorized IP"
msgstr "" msgstr "Authorized IP"
#: mailu/ui/forms.py:136 #: mailu/ui/forms.py:136
msgid "Alias" msgid "Alias"
msgstr "" msgstr "Alias"
#: mailu/ui/forms.py:138 #: mailu/ui/forms.py:138
msgid "Use SQL LIKE Syntax (e.g. for catch-all aliases)" msgid "Use SQL LIKE Syntax (e.g. for catch-all aliases)"
@ -229,7 +229,7 @@ msgstr ""
#: mailu/ui/forms.py:159 mailu/ui/templates/client.html:20 #: mailu/ui/forms.py:159 mailu/ui/templates/client.html:20
#: mailu/ui/templates/client.html:47 #: mailu/ui/templates/client.html:47
msgid "TCP port" msgid "TCP port"
msgstr "" msgstr "TCP port"
#: mailu/ui/forms.py:160 #: mailu/ui/forms.py:160
msgid "Enable TLS" msgid "Enable TLS"
@ -283,7 +283,7 @@ msgstr ""
#: mailu/ui/templates/docker-error.html:4 #: mailu/ui/templates/docker-error.html:4
msgid "Docker error" msgid "Docker error"
msgstr "" msgstr "Docker error"
#: mailu/ui/templates/docker-error.html:12 #: mailu/ui/templates/docker-error.html:12
msgid "An error occurred while talking to the Docker server." msgid "An error occurred while talking to the Docker server."
@ -328,11 +328,11 @@ msgstr ""
#: mailu/ui/templates/sidebar.html:54 #: mailu/ui/templates/sidebar.html:54
msgid "Relayed domains" msgid "Relayed domains"
msgstr "" msgstr "Relayed domains"
#: mailu/ui/templates/sidebar.html:59 mailu/ui/templates/user/settings.html:15 #: mailu/ui/templates/sidebar.html:59 mailu/ui/templates/user/settings.html:15
msgid "Antispam" msgid "Antispam"
msgstr "" msgstr "Antispam"
#: mailu/ui/templates/sidebar.html:66 #: mailu/ui/templates/sidebar.html:66
msgid "Mail domains" msgid "Mail domains"
@ -593,7 +593,7 @@ msgstr ""
#: mailu/ui/templates/relay/create.html:4 #: mailu/ui/templates/relay/create.html:4
msgid "New relay domain" msgid "New relay domain"
msgstr "" msgstr "New relay domain"
#: mailu/ui/templates/relay/edit.html:4 #: mailu/ui/templates/relay/edit.html:4
msgid "Edit relayd domain" msgid "Edit relayd domain"
@ -601,11 +601,11 @@ msgstr ""
#: mailu/ui/templates/relay/list.html:4 #: mailu/ui/templates/relay/list.html:4
msgid "Relayed domain list" msgid "Relayed domain list"
msgstr "" msgstr "Relayed domain list"
#: mailu/ui/templates/relay/list.html:9 #: mailu/ui/templates/relay/list.html:9
msgid "New relayed domain" msgid "New relayed domain"
msgstr "" msgstr "New relayed domain"
#: mailu/ui/templates/token/create.html:4 #: mailu/ui/templates/token/create.html:4
msgid "Create an authentication token" msgid "Create an authentication token"
@ -669,7 +669,7 @@ msgstr ""
#: mailu/ui/templates/user/signup_domain.html:14 #: mailu/ui/templates/user/signup_domain.html:14
msgid "Domain" msgid "Domain"
msgstr "" msgstr "Domain"
#: mailu/ui/templates/user/signup_domain.html:15 #: mailu/ui/templates/user/signup_domain.html:15
msgid "Available slots" msgid "Available slots"

@ -1,7 +1,7 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Mailu\n" "Project-Id-Version: Mailu\n"
"PO-Revision-Date: 2020-03-11 23:03+0000\n" "PO-Revision-Date: 2021-03-04 18:46+0000\n"
"Last-Translator: Jaume Barber <jaumebarber@gmail.com>\n" "Last-Translator: Jaume Barber <jaumebarber@gmail.com>\n"
"Language-Team: Spanish <https://translate.tedomum.net/projects/mailu/admin/" "Language-Team: Spanish <https://translate.tedomum.net/projects/mailu/admin/"
"es/>\n" "es/>\n"
@ -10,7 +10,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n" "Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 3.11.2\n" "X-Generator: Weblate 4.0.1\n"
#: mailu/ui/forms.py:32 #: mailu/ui/forms.py:32
msgid "Invalid email address." msgid "Invalid email address."
@ -425,7 +425,7 @@ msgstr "Añadir una cuenta"
#: mailu/ui/templates/fetch/list.html:19 #: mailu/ui/templates/fetch/list.html:19
msgid "Endpoint" msgid "Endpoint"
msgstr "Punto final" msgstr "Endpoint"
#: mailu/ui/templates/fetch/list.html:22 #: mailu/ui/templates/fetch/list.html:22
msgid "Last check" msgid "Last check"
@ -437,7 +437,7 @@ msgstr "Añadir un gestor"
#: mailu/ui/templates/manager/list.html:4 #: mailu/ui/templates/manager/list.html:4
msgid "Manager list" msgid "Manager list"
msgstr "Gestor de lista" msgstr "Lista de gestores"
#: mailu/ui/templates/manager/list.html:12 #: mailu/ui/templates/manager/list.html:12
msgid "Add manager" msgid "Add manager"
@ -578,7 +578,7 @@ msgstr "Lista de dominios externos (relayed)"
#: mailu/ui/templates/relay/list.html:9 #: mailu/ui/templates/relay/list.html:9
msgid "New relayed domain" msgid "New relayed domain"
msgstr "Nuevo dominio externo (relayed)" msgstr "Editar dominio externo (relay)"
#: mailu/ui/forms.py:125 #: mailu/ui/forms.py:125
msgid "Your token (write it down, as it will never be displayed again)" msgid "Your token (write it down, as it will never be displayed again)"

@ -0,0 +1,672 @@
# Translations template for PROJECT.
# Copyright (C) 2018 ORGANIZATION
# This file is distributed under the same license as the PROJECT project.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2018.
#
msgid ""
msgstr ""
"Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2018-04-22 12:10+0200\n"
"PO-Revision-Date: 2021-03-04 18:46+0000\n"
"Last-Translator: Jaume Barber <jaumebarber@gmail.com>\n"
"Language-Team: Basque <https://translate.tedomum.net/projects/mailu/admin/eu/"
">\n"
"Language: eu\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 4.0.1\n"
"Generated-By: Babel 2.5.3\n"
#: mailu/ui/forms.py:32
msgid "Invalid email address."
msgstr "baliogabeko helbide elektronikoa."
#: mailu/ui/forms.py:36
msgid "Confirm"
msgstr "Ados"
#: mailu/ui/forms.py:40 mailu/ui/forms.py:77
msgid "E-mail"
msgstr "E-mail"
#: mailu/ui/forms.py:41 mailu/ui/forms.py:78 mailu/ui/forms.py:90
#: mailu/ui/forms.py:109 mailu/ui/forms.py:162
#: mailu/ui/templates/client.html:32 mailu/ui/templates/client.html:59
msgid "Password"
msgstr "Pasahitza"
#: mailu/ui/forms.py:42 mailu/ui/templates/login.html:4
#: mailu/ui/templates/sidebar.html:111
msgid "Sign in"
msgstr ""
#: mailu/ui/forms.py:46 mailu/ui/forms.py:56
#: mailu/ui/templates/domain/details.html:27
#: mailu/ui/templates/domain/list.html:18 mailu/ui/templates/relay/list.html:17
msgid "Domain name"
msgstr ""
#: mailu/ui/forms.py:47
msgid "Maximum user count"
msgstr "Erabiltzaileen gehieneko kopurua"
#: mailu/ui/forms.py:48
msgid "Maximum alias count"
msgstr ""
#: mailu/ui/forms.py:49
msgid "Maximum user quota"
msgstr "Erabiltzaile bakoitzeko gehieneko espazioa"
#: mailu/ui/forms.py:50
msgid "Enable sign-up"
msgstr "Gaitu erregistroa"
#: mailu/ui/forms.py:51 mailu/ui/forms.py:72 mailu/ui/forms.py:83
#: mailu/ui/forms.py:128 mailu/ui/forms.py:140
#: mailu/ui/templates/alias/list.html:21 mailu/ui/templates/domain/list.html:21
#: mailu/ui/templates/relay/list.html:19 mailu/ui/templates/token/list.html:19
#: mailu/ui/templates/user/list.html:23
msgid "Comment"
msgstr "Iruzkindua"
#: mailu/ui/forms.py:52 mailu/ui/forms.py:61 mailu/ui/forms.py:66
#: mailu/ui/forms.py:73 mailu/ui/forms.py:132 mailu/ui/forms.py:141
msgid "Create"
msgstr "Sortu"
#: mailu/ui/forms.py:57
msgid "Initial admin"
msgstr "Administratzailea"
#: mailu/ui/forms.py:58
msgid "Admin password"
msgstr "Administratzaileko pasahitza"
#: mailu/ui/forms.py:59 mailu/ui/forms.py:79 mailu/ui/forms.py:91
msgid "Confirm password"
msgstr "Berretsi pasahitza"
#: mailu/ui/forms.py:65
msgid "Alternative name"
msgstr "Izen alternatiboa"
#: mailu/ui/forms.py:70
msgid "Relayed domain name"
msgstr "Igorritako domeinu izena"
#: mailu/ui/forms.py:71 mailu/ui/templates/relay/list.html:18
msgid "Remote host"
msgstr "Urruneko ostalaria"
#: mailu/ui/forms.py:80 mailu/ui/templates/user/list.html:22
#: mailu/ui/templates/user/signup_domain.html:16
msgid "Quota"
msgstr "Espazioa"
#: mailu/ui/forms.py:81
msgid "Allow IMAP access"
msgstr "Baimendu IMAP sarbidea"
#: mailu/ui/forms.py:82
msgid "Allow POP3 access"
msgstr "Baimendu POP3 sarbidea"
#: mailu/ui/forms.py:84
msgid "Enabled"
msgstr "Gaituta"
#: mailu/ui/forms.py:85
msgid "Save"
msgstr "Gorde"
#: mailu/ui/forms.py:89
msgid "Email address"
msgstr ""
#: mailu/ui/forms.py:93 mailu/ui/templates/sidebar.html:117
#: mailu/ui/templates/user/signup.html:4
#: mailu/ui/templates/user/signup_domain.html:4
msgid "Sign up"
msgstr "Erregistratu"
#: mailu/ui/forms.py:97
msgid "Displayed name"
msgstr ""
#: mailu/ui/forms.py:98
msgid "Enable spam filter"
msgstr "Gaitu spam iragazkia"
#: mailu/ui/forms.py:99
msgid "Spam filter tolerance"
msgstr "Spam iragazkiaren tolerantzia"
#: mailu/ui/forms.py:100
msgid "Enable forwarding"
msgstr "Gaitu birbidaltzea"
#: mailu/ui/forms.py:101
msgid "Keep a copy of the emails"
msgstr ""
#: mailu/ui/forms.py:103 mailu/ui/forms.py:139
#: mailu/ui/templates/alias/list.html:20
msgid "Destination"
msgstr ""
#: mailu/ui/forms.py:105
msgid "Save settings"
msgstr "Gorde ezarpenak"
#: mailu/ui/forms.py:110
msgid "Password check"
msgstr ""
#: mailu/ui/forms.py:111 mailu/ui/templates/sidebar.html:16
msgid "Update password"
msgstr ""
#: mailu/ui/forms.py:115
msgid "Enable automatic reply"
msgstr ""
#: mailu/ui/forms.py:116
msgid "Reply subject"
msgstr ""
#: mailu/ui/forms.py:117
msgid "Reply body"
msgstr ""
#: mailu/ui/forms.py:119
msgid "End of vacation"
msgstr "Oporren amaiera"
#: mailu/ui/forms.py:120
msgid "Update"
msgstr "Eguneratu"
#: mailu/ui/forms.py:125
msgid "Your token (write it down, as it will never be displayed again)"
msgstr ""
#: mailu/ui/forms.py:130 mailu/ui/templates/token/list.html:20
msgid "Authorized IP"
msgstr "Baimendutako IP"
#: mailu/ui/forms.py:136
msgid "Alias"
msgstr "Ezizenza"
#: mailu/ui/forms.py:138
msgid "Use SQL LIKE Syntax (e.g. for catch-all aliases)"
msgstr ""
#: mailu/ui/forms.py:145
msgid "Admin email"
msgstr ""
#: mailu/ui/forms.py:146 mailu/ui/forms.py:151 mailu/ui/forms.py:164
msgid "Submit"
msgstr ""
#: mailu/ui/forms.py:150
msgid "Manager email"
msgstr ""
#: mailu/ui/forms.py:155
msgid "Protocol"
msgstr ""
#: mailu/ui/forms.py:158
msgid "Hostname or IP"
msgstr ""
#: mailu/ui/forms.py:159 mailu/ui/templates/client.html:20
#: mailu/ui/templates/client.html:47
msgid "TCP port"
msgstr "TCP ataka"
#: mailu/ui/forms.py:160
msgid "Enable TLS"
msgstr ""
#: mailu/ui/forms.py:161 mailu/ui/templates/client.html:28
#: mailu/ui/templates/client.html:55 mailu/ui/templates/fetch/list.html:20
msgid "Username"
msgstr ""
#: mailu/ui/forms.py:163
msgid "Keep emails on the server"
msgstr ""
#: mailu/ui/forms.py:168
msgid "Announcement subject"
msgstr ""
#: mailu/ui/forms.py:170
msgid "Announcement body"
msgstr ""
#: mailu/ui/forms.py:172
msgid "Send"
msgstr ""
#: mailu/ui/templates/announcement.html:4
msgid "Public announcement"
msgstr ""
#: mailu/ui/templates/client.html:4 mailu/ui/templates/sidebar.html:82
msgid "Client setup"
msgstr ""
#: mailu/ui/templates/client.html:16 mailu/ui/templates/client.html:43
msgid "Mail protocol"
msgstr ""
#: mailu/ui/templates/client.html:24 mailu/ui/templates/client.html:51
msgid "Server name"
msgstr ""
#: mailu/ui/templates/confirm.html:4
msgid "Confirm action"
msgstr ""
#: mailu/ui/templates/confirm.html:13
#, python-format
msgid "You are about to %(action)s. Please confirm your action."
msgstr "Zu zara %(action)s-etan. Mesedez ekintza honen berretsi."
#: mailu/ui/templates/docker-error.html:4
msgid "Docker error"
msgstr "Docker-en errorea"
#: mailu/ui/templates/docker-error.html:12
msgid "An error occurred while talking to the Docker server."
msgstr ""
#: mailu/ui/templates/login.html:8
msgid "to access the administration tools"
msgstr ""
#: mailu/ui/templates/sidebar.html:11 mailu/ui/templates/user/list.html:34
msgid "Settings"
msgstr ""
#: mailu/ui/templates/sidebar.html:21 mailu/ui/templates/user/list.html:35
msgid "Auto-reply"
msgstr ""
#: mailu/ui/templates/fetch/list.html:4 mailu/ui/templates/sidebar.html:26
#: mailu/ui/templates/user/list.html:36
msgid "Fetched accounts"
msgstr ""
#: mailu/ui/templates/sidebar.html:31 mailu/ui/templates/token/list.html:4
msgid "Authentication tokens"
msgstr ""
#: mailu/ui/templates/sidebar.html:35
msgid "Administration"
msgstr ""
#: mailu/ui/templates/sidebar.html:44
msgid "Announcement"
msgstr ""
#: mailu/ui/templates/sidebar.html:49
msgid "Administrators"
msgstr ""
#: mailu/ui/templates/sidebar.html:54
msgid "Relayed domains"
msgstr "Igorritako domeinuak"
#: mailu/ui/templates/sidebar.html:59 mailu/ui/templates/user/settings.html:15
msgid "Antispam"
msgstr "Antispam"
#: mailu/ui/templates/sidebar.html:66
msgid "Mail domains"
msgstr ""
#: mailu/ui/templates/sidebar.html:72
msgid "Go to"
msgstr ""
#: mailu/ui/templates/sidebar.html:76
msgid "Webmail"
msgstr ""
#: mailu/ui/templates/sidebar.html:87
msgid "Website"
msgstr ""
#: mailu/ui/templates/sidebar.html:92
msgid "Help"
msgstr ""
#: mailu/ui/templates/domain/signup.html:4 mailu/ui/templates/sidebar.html:98
msgid "Register a domain"
msgstr ""
#: mailu/ui/templates/sidebar.html:105
msgid "Sign out"
msgstr ""
#: mailu/ui/templates/working.html:4
msgid "We are still working on this feature!"
msgstr ""
#: mailu/ui/templates/admin/create.html:4
msgid "Add a global administrator"
msgstr ""
#: mailu/ui/templates/admin/list.html:4
msgid "Global administrators"
msgstr ""
#: mailu/ui/templates/admin/list.html:9
msgid "Add administrator"
msgstr ""
#: mailu/ui/templates/admin/list.html:16 mailu/ui/templates/alias/list.html:18
#: mailu/ui/templates/alternative/list.html:18
#: mailu/ui/templates/domain/list.html:16 mailu/ui/templates/fetch/list.html:18
#: mailu/ui/templates/manager/list.html:18
#: mailu/ui/templates/relay/list.html:16 mailu/ui/templates/token/list.html:18
#: mailu/ui/templates/user/list.html:18
msgid "Actions"
msgstr ""
#: mailu/ui/templates/admin/list.html:17 mailu/ui/templates/alias/list.html:19
#: mailu/ui/templates/manager/list.html:19 mailu/ui/templates/user/list.html:20
msgid "Email"
msgstr ""
#: mailu/ui/templates/admin/list.html:22 mailu/ui/templates/alias/list.html:29
#: mailu/ui/templates/alternative/list.html:25
#: mailu/ui/templates/domain/list.html:31 mailu/ui/templates/fetch/list.html:31
#: mailu/ui/templates/manager/list.html:24
#: mailu/ui/templates/relay/list.html:27 mailu/ui/templates/token/list.html:26
#: mailu/ui/templates/user/list.html:31
msgid "Delete"
msgstr ""
#: mailu/ui/templates/alias/create.html:4
msgid "Create alias"
msgstr ""
#: mailu/ui/templates/alias/edit.html:4
msgid "Edit alias"
msgstr ""
#: mailu/ui/templates/alias/list.html:4
msgid "Alias list"
msgstr ""
#: mailu/ui/templates/alias/list.html:12
msgid "Add alias"
msgstr ""
#: mailu/ui/templates/alias/list.html:22
#: mailu/ui/templates/alternative/list.html:20
#: mailu/ui/templates/domain/list.html:22 mailu/ui/templates/fetch/list.html:24
#: mailu/ui/templates/relay/list.html:20 mailu/ui/templates/token/list.html:21
#: mailu/ui/templates/user/list.html:24
msgid "Created"
msgstr ""
#: mailu/ui/templates/alias/list.html:23 mailu/ui/templates/domain/list.html:23
#: mailu/ui/templates/fetch/list.html:25 mailu/ui/templates/relay/list.html:21
#: mailu/ui/templates/user/list.html:25
msgid "Last edit"
msgstr ""
#: mailu/ui/templates/alias/list.html:28 mailu/ui/templates/domain/list.html:30
#: mailu/ui/templates/fetch/list.html:30 mailu/ui/templates/relay/list.html:26
#: mailu/ui/templates/user/list.html:30
msgid "Edit"
msgstr ""
#: mailu/ui/templates/alternative/create.html:4
msgid "Create alternative domain"
msgstr ""
#: mailu/ui/templates/alternative/list.html:4
msgid "Alternative domain list"
msgstr ""
#: mailu/ui/templates/alternative/list.html:12
msgid "Add alternative"
msgstr ""
#: mailu/ui/templates/alternative/list.html:19
msgid "Name"
msgstr ""
#: mailu/ui/templates/domain/create.html:4
#: mailu/ui/templates/domain/list.html:9
msgid "New domain"
msgstr ""
#: mailu/ui/templates/domain/details.html:4
msgid "Domain details"
msgstr ""
#: mailu/ui/templates/domain/details.html:15
msgid "Regenerate keys"
msgstr ""
#: mailu/ui/templates/domain/details.html:17
msgid "Generate keys"
msgstr ""
#: mailu/ui/templates/domain/details.html:31
msgid "DNS MX entry"
msgstr ""
#: mailu/ui/templates/domain/details.html:35
msgid "DNS SPF entries"
msgstr ""
#: mailu/ui/templates/domain/details.html:42
msgid "DKIM public key"
msgstr ""
#: mailu/ui/templates/domain/details.html:46
msgid "DNS DKIM entry"
msgstr ""
#: mailu/ui/templates/domain/details.html:50
msgid "DNS DMARC entry"
msgstr ""
#: mailu/ui/templates/domain/edit.html:4
msgid "Edit domain"
msgstr ""
#: mailu/ui/templates/domain/list.html:4
msgid "Domain list"
msgstr ""
#: mailu/ui/templates/domain/list.html:17
msgid "Manage"
msgstr ""
#: mailu/ui/templates/domain/list.html:19
msgid "Mailbox count"
msgstr ""
#: mailu/ui/templates/domain/list.html:20
msgid "Alias count"
msgstr ""
#: mailu/ui/templates/domain/list.html:28
msgid "Details"
msgstr ""
#: mailu/ui/templates/domain/list.html:35
msgid "Users"
msgstr ""
#: mailu/ui/templates/domain/list.html:36
msgid "Aliases"
msgstr ""
#: mailu/ui/templates/domain/list.html:37
msgid "Managers"
msgstr ""
#: mailu/ui/templates/domain/list.html:39
msgid "Alternatives"
msgstr ""
#: mailu/ui/templates/domain/signup.html:13
msgid ""
"In order to register a new domain, you must first setup the\n"
" domain zone so that the domain <code>MX</code> points to this server"
msgstr ""
#: mailu/ui/templates/domain/signup.html:18
msgid ""
"If you do not know how to setup an <code>MX</code> record for your DNS "
"zone,\n"
" please contact your DNS provider or administrator. Also, please wait "
"a\n"
" couple minutes after the <code>MX</code> is set so the local server "
"cache\n"
" expires."
msgstr ""
#: mailu/ui/templates/fetch/create.html:4
msgid "Add a fetched account"
msgstr ""
#: mailu/ui/templates/fetch/edit.html:4
msgid "Update a fetched account"
msgstr ""
#: mailu/ui/templates/fetch/list.html:12
msgid "Add an account"
msgstr ""
#: mailu/ui/templates/fetch/list.html:19
msgid "Endpoint"
msgstr ""
#: mailu/ui/templates/fetch/list.html:21
msgid "Keep emails"
msgstr ""
#: mailu/ui/templates/fetch/list.html:22
msgid "Last check"
msgstr ""
#: mailu/ui/templates/fetch/list.html:35
msgid "yes"
msgstr ""
#: mailu/ui/templates/fetch/list.html:35
msgid "no"
msgstr ""
#: mailu/ui/templates/manager/create.html:4
msgid "Add a manager"
msgstr ""
#: mailu/ui/templates/manager/list.html:4
msgid "Manager list"
msgstr ""
#: mailu/ui/templates/manager/list.html:12
msgid "Add manager"
msgstr ""
#: mailu/ui/templates/relay/create.html:4
msgid "New relay domain"
msgstr "Igorritako domeinu berria"
#: mailu/ui/templates/relay/edit.html:4
msgid "Edit relayd domain"
msgstr "Editatu igorritako domeinua"
#: mailu/ui/templates/relay/list.html:4
msgid "Relayed domain list"
msgstr "Igorritako domeinuen zerrenda"
#: mailu/ui/templates/relay/list.html:9
msgid "New relayed domain"
msgstr "Igorritako domeinu berria"
#: mailu/ui/templates/token/create.html:4
msgid "Create an authentication token"
msgstr ""
#: mailu/ui/templates/token/list.html:12
msgid "New token"
msgstr ""
#: mailu/ui/templates/user/create.html:4
msgid "New user"
msgstr ""
#: mailu/ui/templates/user/create.html:15
msgid "General"
msgstr ""
#: mailu/ui/templates/user/create.html:22
msgid "Features and quotas"
msgstr ""
#: mailu/ui/templates/user/edit.html:4
msgid "Edit user"
msgstr ""
#: mailu/ui/templates/user/forward.html:4
msgid "Forward emails"
msgstr ""
#: mailu/ui/templates/user/list.html:4
msgid "User list"
msgstr ""
#: mailu/ui/templates/user/list.html:12
msgid "Add user"
msgstr ""
#: mailu/ui/templates/user/list.html:19 mailu/ui/templates/user/settings.html:4
msgid "User settings"
msgstr ""
#: mailu/ui/templates/user/list.html:21
msgid "Features"
msgstr ""
#: mailu/ui/templates/user/password.html:4
msgid "Password update"
msgstr ""
#: mailu/ui/templates/user/reply.html:4
msgid "Automatic reply"
msgstr ""
#: mailu/ui/templates/user/settings.html:22
msgid "Auto-forward"
msgstr ""
#: mailu/ui/templates/user/signup_domain.html:8
msgid "pick a domain for the new account"
msgstr ""
#: mailu/ui/templates/user/signup_domain.html:14
msgid "Domain"
msgstr "Domeinu izena"
#: mailu/ui/templates/user/signup_domain.html:15
msgid "Available slots"
msgstr ""

@ -9,7 +9,7 @@ msgstr ""
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2018-04-22 12:10+0200\n" "POT-Creation-Date: 2018-04-22 12:10+0200\n"
"PO-Revision-Date: 2019-11-27 22:20+0000\n" "PO-Revision-Date: 2019-11-27 22:20+0000\n"
"Last-Translator: Mordi Sacks <mordisacks@gmail.com>\n" "Last-Translator: Mordi Sacks \n"
"Language-Team: Hebrew <https://translate.tedomum.net/projects/mailu/admin/he/" "Language-Team: Hebrew <https://translate.tedomum.net/projects/mailu/admin/he/"
">\n" ">\n"
"Language: he\n" "Language: he\n"

@ -1,7 +1,7 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Mailu\n" "Project-Id-Version: Mailu\n"
"PO-Revision-Date: 2020-03-11 23:03+0000\n" "PO-Revision-Date: 2021-03-04 18:46+0000\n"
"Last-Translator: Jaume Barber <jaumebarber@gmail.com>\n" "Last-Translator: Jaume Barber <jaumebarber@gmail.com>\n"
"Language-Team: Italian <https://translate.tedomum.net/projects/mailu/admin/" "Language-Team: Italian <https://translate.tedomum.net/projects/mailu/admin/"
"it/>\n" "it/>\n"
@ -10,7 +10,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n" "Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 3.11.2\n" "X-Generator: Weblate 4.0.1\n"
#: mailu/ui/forms.py:32 #: mailu/ui/forms.py:32
msgid "Invalid email address." msgid "Invalid email address."

@ -1,11 +1,16 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Mailu\n"
"PO-Revision-Date: 2021-03-04 18:46+0000\n"
"Last-Translator: Jaume Barber <jaumebarber@gmail.com>\n"
"Language-Team: Portuguese <https://translate.tedomum.net/projects/mailu/"
"admin/pt/>\n"
"Language: pt\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"X-Generator: POEditor.com\n" "Plural-Forms: nplurals=2; plural=n > 1;\n"
"Project-Id-Version: Mailu\n" "X-Generator: Weblate 4.0.1\n"
"Language: pt\n"
#: mailu/ui/forms.py:32 #: mailu/ui/forms.py:32
msgid "Invalid email address." msgid "Invalid email address."
@ -183,7 +188,7 @@ msgstr "Erro no docker"
#: mailu/ui/templates/docker-error.html:12 #: mailu/ui/templates/docker-error.html:12
msgid "An error occurred while talking to the Docker server." msgid "An error occurred while talking to the Docker server."
msgstr "Um erro foi encontrado na conexão com o servidor Docker" msgstr "Um erro foi encontrado na conexão com o servidor Docker."
#: mailu/admin/templates/login.html:6 #: mailu/admin/templates/login.html:6
msgid "Your account" msgid "Your account"
@ -700,4 +705,3 @@ msgstr "Domínio"
#: mailu/ui/templates/user/signup_domain.html:15 #: mailu/ui/templates/user/signup_domain.html:15
msgid "Available slots" msgid "Available slots"
msgstr "Slots disponíveis" msgstr "Slots disponíveis"

@ -1,8 +1,8 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Mailu\n" "Project-Id-Version: Mailu\n"
"PO-Revision-Date: 2019-07-22 06:23+0000\n" "PO-Revision-Date: 2021-03-04 18:46+0000\n"
"Last-Translator: kaiyou <pierre@jaury.eu>\n" "Last-Translator: Jaume Barber <jaumebarber@gmail.com>\n"
"Language-Team: Russian <https://translate.tedomum.net/projects/mailu/admin/" "Language-Team: Russian <https://translate.tedomum.net/projects/mailu/admin/"
"ru/>\n" "ru/>\n"
"Language: ru\n" "Language: ru\n"
@ -11,7 +11,7 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=" "Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<="
"4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" "4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
"X-Generator: Weblate 3.3\n" "X-Generator: Weblate 4.0.1\n"
#: mailu/ui/forms.py:32 #: mailu/ui/forms.py:32
msgid "Invalid email address." msgid "Invalid email address."
@ -189,7 +189,7 @@ msgstr "Ошибка Docker"
#: mailu/ui/templates/docker-error.html:12 #: mailu/ui/templates/docker-error.html:12
msgid "An error occurred while talking to the Docker server." msgid "An error occurred while talking to the Docker server."
msgstr "Произошла ошибка при обращении к серверу Docker" msgstr "Произошла ошибка при обращении к серверу Docker."
#: mailu/admin/templates/login.html:6 #: mailu/admin/templates/login.html:6
msgid "Your account" msgid "Your account"

@ -1,11 +1,16 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Mailu\n"
"PO-Revision-Date: 2021-03-04 18:46+0000\n"
"Last-Translator: Jaume Barber <jaumebarber@gmail.com>\n"
"Language-Team: Swedish <https://translate.tedomum.net/projects/mailu/admin/"
"sv/>\n"
"Language: sv\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"X-Generator: POEditor.com\n" "Plural-Forms: nplurals=2; plural=n != 1;\n"
"Project-Id-Version: Mailu\n" "X-Generator: Weblate 4.0.1\n"
"Language: sk\n"
#: mailu/ui/forms.py:32 #: mailu/ui/forms.py:32
msgid "Invalid email address." msgid "Invalid email address."
@ -183,7 +188,7 @@ msgstr "Docker fel"
#: mailu/ui/templates/docker-error.html:12 #: mailu/ui/templates/docker-error.html:12
msgid "An error occurred while talking to the Docker server." msgid "An error occurred while talking to the Docker server."
msgstr "Ett fel inträffade vid kommunikation med Docker" msgstr "Ett fel inträffade vid kommunikation med Docker."
#: mailu/admin/templates/login.html:6 #: mailu/admin/templates/login.html:6
msgid "Your account" msgid "Your account"
@ -699,4 +704,3 @@ msgstr ""
#: mailu/ui/templates/user/signup_domain.html:15 #: mailu/ui/templates/user/signup_domain.html:15
msgid "Available slots" msgid "Available slots"
msgstr "" msgstr ""

@ -1,4 +1,5 @@
{% import "macros.html" as macros %} {% import "macros.html" as macros %}
{% import "bootstrap/utils.html" as utils %}
<!doctype html> <!doctype html>
<html> <html>
<head> <head>
@ -37,6 +38,7 @@
</section> </section>
<section class="content"> <section class="content">
{{ utils.flashed_messages(container=False) }}
{% block content %}{% endblock %} {% block content %}{% endblock %}
</section> </section>
</div> </div>

@ -26,7 +26,7 @@ def token_create(user_email):
form = forms.TokenForm() form = forms.TokenForm()
wtforms_components.read_only(form.displayed_password) wtforms_components.read_only(form.displayed_password)
if not form.raw_password.data: if not form.raw_password.data:
form.raw_password.data = pwd.genword(entropy=128, charset="hex") form.raw_password.data = pwd.genword(entropy=128, length=32, charset="hex")
form.displayed_password.data = form.raw_password.data form.displayed_password.data = form.raw_password.data
if form.validate_on_submit(): if form.validate_on_submit():
token = models.Token(user=user) token = models.Token(user=user)

@ -5,7 +5,7 @@ bcrypt==3.1.6
blinker==1.4 blinker==1.4
cffi==1.12.3 cffi==1.12.3
Click==7.0 Click==7.0
cryptography==2.6.1 cryptography==3.2
decorator==4.4.0 decorator==4.4.0
dnspython==1.16.0 dnspython==1.16.0
dominate==2.3.5 dominate==2.3.5
@ -29,7 +29,7 @@ limits==1.3
Mako==1.0.9 Mako==1.0.9
MarkupSafe==1.1.1 MarkupSafe==1.1.1
mysqlclient==1.4.2.post1 mysqlclient==1.4.2.post1
passlib==1.7.1 passlib==1.7.4
psycopg2==2.8.2 psycopg2==2.8.2
pycparser==2.19 pycparser==2.19
pyOpenSSL==19.0.0 pyOpenSSL==19.0.0

@ -1,4 +1,4 @@
ARG DISTRO=alpine:3.12 ARG DISTRO=alpine:3.13
FROM $DISTRO as builder FROM $DISTRO as builder
WORKDIR /tmp WORKDIR /tmp
RUN apk add git build-base automake autoconf libtool dovecot-dev xapian-core-dev icu-dev RUN apk add git build-base automake autoconf libtool dovecot-dev xapian-core-dev icu-dev

@ -34,6 +34,25 @@ http {
'' $scheme; '' $scheme;
} }
{% if KUBERNETES_INGRESS != 'true' and TLS_FLAVOR in [ 'letsencrypt', 'cert' ] %}
# Enable the proxy for certbot if the flavor is letsencrypt and not on kubernetes
#
server {
# Listen over HTTP
listen 80;
listen [::]:80;
{% if TLS_FLAVOR == 'letsencrypt' %}
location ^~ /.well-known/acme-challenge/ {
proxy_pass http://127.0.0.1:8008;
}
{% endif %}
# redirect to https
location / {
return 301 https://$host$request_uri;
}
}
{% endif %}
# Main HTTP server # Main HTTP server
server { server {
# Favicon stuff # Favicon stuff
@ -48,9 +67,11 @@ http {
set $webdav {{ WEBDAV_ADDRESS }}; set $webdav {{ WEBDAV_ADDRESS }};
{% endif %} {% endif %}
# Always listen over HTTP # Listen on HTTP only in kubernetes or behind reverse proxy
{% if KUBERNETES_INGRESS == 'true' or TLS_FLAVOR in [ 'mail-letsencrypt', 'notls', 'mail' ] %}
listen 80; listen 80;
listen [::]:80; listen [::]:80;
{% endif %}
# Only enable HTTPS if TLS is enabled with no error and not on kubernetes # Only enable HTTPS if TLS is enabled with no error and not on kubernetes
{% if KUBERNETES_INGRESS != 'true' and TLS and not TLS_ERROR %} {% if KUBERNETES_INGRESS != 'true' and TLS and not TLS_ERROR %}
@ -58,6 +79,8 @@ http {
listen [::]:443 ssl http2; listen [::]:443 ssl http2;
include /etc/nginx/tls.conf; include /etc/nginx/tls.conf;
ssl_stapling on;
ssl_stapling_verify on;
ssl_session_cache shared:SSLHTTP:50m; ssl_session_cache shared:SSLHTTP:50m;
add_header Strict-Transport-Security 'max-age=31536000'; add_header Strict-Transport-Security 'max-age=31536000';
@ -78,15 +101,14 @@ http {
add_header X-XSS-Protection '1; mode=block'; add_header X-XSS-Protection '1; mode=block';
add_header Referrer-Policy 'same-origin'; add_header Referrer-Policy 'same-origin';
# In any case, enable the proxy for certbot if the flavor is letsencrypt and not on kubernetes {% if TLS_FLAVOR == 'mail-letsencrypt' %}
{% if KUBERNETES_INGRESS != 'true' and TLS_FLAVOR in [ 'letsencrypt', 'mail-letsencrypt' ] %}
location ^~ /.well-known/acme-challenge/ { location ^~ /.well-known/acme-challenge/ {
proxy_pass http://127.0.0.1:8008; proxy_pass http://127.0.0.1:8008;
} }
{% endif %} {% endif %}
# If TLS is failing, prevent access to anything except certbot # If TLS is failing, prevent access to anything except certbot
{% if KUBERNETES_INGRESS != 'true' and TLS_ERROR and not TLS_FLAVOR == "mail" %} {% if KUBERNETES_INGRESS != 'true' and TLS_ERROR and not (TLS_FLAVOR in [ 'mail-letsencrypt', 'mail' ]) %}
location / { location / {
return 403; return 403;
} }
@ -195,7 +217,7 @@ mail {
{% endif %} {% endif %}
# Advertise real capabilites of backends (postfix/dovecot) # Advertise real capabilites of backends (postfix/dovecot)
smtp_capabilities PIPELINING SIZE {{ MESSAGE_SIZE_LIMIT }} ETRN ENHANCEDSTATUSCODES 8BITMIME DSN CHUNKING; smtp_capabilities PIPELINING SIZE {{ MESSAGE_SIZE_LIMIT }} ETRN ENHANCEDSTATUSCODES 8BITMIME DSN;
pop3_capabilities TOP UIDL RESP-CODES PIPELINING AUTH-RESP-CODE USER; pop3_capabilities TOP UIDL RESP-CODES PIPELINING AUTH-RESP-CODE USER;
imap_capabilities IMAP4 IMAP4rev1 UIDPLUS SASL-IR LOGIN-REFERRALS ID ENABLE IDLE LITERAL+; imap_capabilities IMAP4 IMAP4rev1 UIDPLUS SASL-IR LOGIN-REFERRALS ID ENABLE IDLE LITERAL+;
@ -218,9 +240,9 @@ mail {
listen 25; listen 25;
listen [::]:25; listen [::]:25;
{% if TLS and not TLS_ERROR %} {% if TLS and not TLS_ERROR %}
ssl_protocols TLSv1.2 TLSv1.3; ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384; ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA256:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA;
ssl_prefer_server_ciphers off; ssl_prefer_server_ciphers on;
starttls on; starttls on;
{% endif %} {% endif %}
protocol smtp; protocol smtp;

@ -12,7 +12,7 @@ RUN pip3 install socrate==0.2.0
RUN pip3 install "podop>0.2.5" RUN pip3 install "podop>0.2.5"
# Image specific layers under this line # Image specific layers under this line
RUN apk add --no-cache postfix postfix-pcre cyrus-sasl-plain RUN apk add --no-cache postfix postfix-pcre cyrus-sasl-plain cyrus-sasl-login
COPY conf /conf COPY conf /conf
COPY start.py /start.py COPY start.py /start.py

@ -126,3 +126,5 @@ milter_default_action = tempfail
############### ###############
# Extra Settings # Extra Settings
############### ###############
{# Ensure that the rendered file ends with newline in order to make `postconf` work correctly #}
{{- "\n" }}

@ -1,6 +1,8 @@
Spam filtering Spam filtering
============== ==============
.. _antispam_howto:
How does spam filtering work in Mailu? How does spam filtering work in Mailu?
-------------------------------------- --------------------------------------
@ -68,6 +70,8 @@ Likewise, to learn all messages within the folder ``Spam_Learn`` as spam message
*Issue reference:* `1438`_. *Issue reference:* `1438`_.
.. _antispam_howto_block:
How can I block emails from a domain? How can I block emails from a domain?
------------------------------------- -------------------------------------

Binary file not shown.

Before

Width:  |  Height:  |  Size: 118 KiB

@ -85,7 +85,6 @@ where mail-config.yml looks like:
- localpart: foo - localpart: foo
domain: example.com domain: example.com
password_hash: klkjhumnzxcjkajahsdqweqqwr password_hash: klkjhumnzxcjkajahsdqweqqwr
hash_scheme: MD5-CRYPT
aliases: aliases:
- localpart: alias1 - localpart: alias1

@ -144,9 +144,8 @@ LOG_DRIVER=json-file
# Docker-compose project name, this will prepended to containers names. # Docker-compose project name, this will prepended to containers names.
COMPOSE_PROJECT_NAME=mailu COMPOSE_PROJECT_NAME=mailu
# Default password scheme used for newly created accounts and changed passwords # Number of rounds used by the password hashing scheme
# (value: PBKDF2, BLF-CRYPT, SHA512-CRYPT, SHA256-CRYPT) CREDENTIAL_ROUNDS=12
PASSWORD_SCHEME=PBKDF2
# Header to take the real ip from # Header to take the real ip from
REAL_IP_HEADER= REAL_IP_HEADER=

@ -41,6 +41,7 @@ html_context = {
('1.5', '/1.5/'), ('1.5', '/1.5/'),
('1.6', '/1.6/'), ('1.6', '/1.6/'),
('1.7', '/1.7/'), ('1.7', '/1.7/'),
('1.8', '/1.8/'),
('master', '/master/') ('master', '/master/')
], ],
'conf_py_path': '/docs/' 'conf_py_path': '/docs/'

@ -80,6 +80,8 @@ support or e.g. mismatching TLS versions to deliver emails to Mailu.
.. _`RFC 3207`: https://tools.ietf.org/html/rfc3207 .. _`RFC 3207`: https://tools.ietf.org/html/rfc3207
.. _fetchmail:
The ``FETCHMAIL_DELAY`` is a delay (in seconds) for the fetchmail service to The ``FETCHMAIL_DELAY`` is a delay (in seconds) for the fetchmail service to
go and fetch new email if available. Do not use too short delays if you do not go and fetch new email if available. Do not use too short delays if you do not
want to be blacklisted by external services, but not too long delays if you want to be blacklisted by external services, but not too long delays if you
@ -143,9 +145,9 @@ Depending on your particular deployment you most probably will want to change th
Advanced settings Advanced settings
----------------- -----------------
The ``PASSWORD_SCHEME`` is the password encryption scheme. You should use the The ``CREDENTIAL_ROUNDS`` (default: 12) setting is the number of rounds used by the password hashing scheme. The number of rounds can be reduced in case faster authentication is needed or increased when additional protection is desired. Keep in mind that this is a mitigation against offline attacks on password hashes, aiming to prevent credential stuffing (due to password re-use) on other systems.
default value, unless you are importing password from a separate system and
want to keep using the old password encryption scheme. The ``SESSION_COOKIE_SECURE`` (default: True) setting controls the secure flag on the cookies of the administrative interface. It should only be turned off if you intend to access it over plain HTTP.
The ``LOG_LEVEL`` setting is used by the python start-up scripts as a logging threshold. The ``LOG_LEVEL`` setting is used by the python start-up scripts as a logging threshold.
Log messages equal or higher than this priority will be printed. Log messages equal or higher than this priority will be printed.

@ -129,7 +129,7 @@ So when you have something like this:
- The admin interface generates ``MX`` and ``SPF`` examples which point to the first entry of ``HOSTNAMES`` but these are only examples. - The admin interface generates ``MX`` and ``SPF`` examples which point to the first entry of ``HOSTNAMES`` but these are only examples.
You can modify them to use any other ``HOSTNAMES`` entry. You can modify them to use any other ``HOSTNAMES`` entry.
You're mail service will be reachable for IMAP, POP3, SMTP and Webmail at the addresses: Your mail service will be reachable for IMAP, POP3, SMTP and Webmail at the addresses:
- mail.example.com - mail.example.com
- mail.foo.com - mail.foo.com
@ -170,6 +170,13 @@ Lets start with quoting everything that's wrong:
(`docker/libnetwork#1099 <https://github.com/docker/libnetwork/issues/1099>`_). (`docker/libnetwork#1099 <https://github.com/docker/libnetwork/issues/1099>`_).
-- `Robbert Klarenbeek <https://github.com/robbertkl>`_ (docker-ipv6nat author) -- `Robbert Klarenbeek <https://github.com/robbertkl>`_ (docker-ipv6nat author)
Okay, but I still want to use IPv6! Can I just use the installers IPv6 checkbox? **NO, YOU SHOULD NOT DO THAT!** Why you ask?
Mailu has its own trusted IPv4 network, every container inside this network can use e.g. the SMTP container without further
authentication. If you enabled IPv6 inside the setup assistant (and fixed the ports to also be exposed on IPv6) Docker will
still rewrite any incoming IPv6 requests to an IPv4 address, *which is located inside the trusted network*. Therefore any
incoming connection to the SMTP container will bypass the authentication stage by the front container regardless of your
settings and causes an Open Relay. And you really don't want this!
So, how to make it work? Well, by using `docker-ipv6nat`_! This nifty container will set up ``ip6tables``, So, how to make it work? Well, by using `docker-ipv6nat`_! This nifty container will set up ``ip6tables``,
just as Docker would do for IPv4. We know that nat-ing is not advised in IPv6, just as Docker would do for IPv4. We know that nat-ing is not advised in IPv6,
@ -250,7 +257,10 @@ Postfix, Dovecot, Nginx and Rspamd support overriding configuration files. Overr
``$ROOT/overrides``. Please refer to the official documentation of those programs for the ``$ROOT/overrides``. Please refer to the official documentation of those programs for the
correct syntax. The following file names will be taken as override configuration: correct syntax. The following file names will be taken as override configuration:
- `Postfix`_ - ``postfix.cf`` in postfix sub-directory; - `Postfix`_ :
- ``main.cf`` as ``$ROOT/overrides/postfix/postfix.cf``
- ``master.cf`` as ``$ROOT/overrides/postfix/postfix.master``
- All ``$ROOT/overrides/postfix/*.map`` files
- `Dovecot`_ - ``dovecot.conf`` in dovecot sub-directory; - `Dovecot`_ - ``dovecot.conf`` in dovecot sub-directory;
- `Nginx`_ - All ``*.conf`` files in the ``nginx`` sub-directory; - `Nginx`_ - All ``*.conf`` files in the ``nginx`` sub-directory;
- `Rspamd`_ - All files in the ``rspamd`` sub-directory. - `Rspamd`_ - All files in the ``rspamd`` sub-directory.
@ -320,6 +330,24 @@ After successfull login the domain part will be striped and the rest used as use
*Issue reference:* `575`_. *Issue reference:* `575`_.
How do I use webdav (radicale)?
```````````````````````````````
| For first time set up, the user must access radicale via the url `https://mail.example.com/webdav/.web` and then
| 1. Log in using the user's full email address and password.
| 2. Click 'Create new addressbook or calendar'
| 3. Follow instructions for creating an addressbook (for contact management) and calendar.
|
| Subsequently to use webdav (radicale), you can configure your carddav/caldav client to use the following url:
| `https://mail.example.com/webdav/user@example.com`
| As username you must provide the complete email address (user@example.com).
| As password you must provide the password of the email address.
| The user must be an existing Mailu user.
*issue reference:* `1591`_.
.. _`Postfix`: http://www.postfix.org/postconf.5.html .. _`Postfix`: http://www.postfix.org/postconf.5.html
.. _`Dovecot`: https://doc.dovecot.org/configuration_manual/config_file/config_file_syntax/ .. _`Dovecot`: https://doc.dovecot.org/configuration_manual/config_file/config_file_syntax/
.. _`NGINX`: https://nginx.org/en/docs/ .. _`NGINX`: https://nginx.org/en/docs/
@ -335,6 +363,7 @@ After successfull login the domain part will be striped and the rest used as use
.. _`520`: https://github.com/Mailu/Mailu/issues/520 .. _`520`: https://github.com/Mailu/Mailu/issues/520
.. _`591`: https://github.com/Mailu/Mailu/issues/591 .. _`591`: https://github.com/Mailu/Mailu/issues/591
.. _`575`: https://github.com/Mailu/Mailu/issues/575 .. _`575`: https://github.com/Mailu/Mailu/issues/575
.. _`1591`: https://github.com/Mailu/Mailu/issues/1591
Technical issues Technical issues
---------------- ----------------

@ -16,10 +16,6 @@ Admin interface screenshots
Managing email domains Managing email domains
.. figure:: assets/screenshots/status.png
Displaying service status
.. figure:: assets/screenshots/token.png .. figure:: assets/screenshots/token.png
Creating an authentication token Creating an authentication token

@ -67,6 +67,7 @@ the version of Mailu that you are running.
:caption: Administration :caption: Administration
maintain maintain
webadministration
antispam antispam
cli cli

@ -1,15 +1,54 @@
Release notes Release notes
============= =============
Mailu 1.8 - tbd Mailu 1.8 - 2020-10-02
---------------------- ----------------------
Release 1.8 has come a long way again. Due to corona the project slowed down to a crawl. Fortunately new contributors have joined the team what enabled us to still release Mailu 1.8 this year.
Please note that the current 1.8 is what we call a "soft release": Its there for everyone to see and use, but to limit possible user-impact of this very big release, its not yet the default in the setup-utility for new users. When upgrading, please treat it with some care, and be sure to always have backups!
For a list of all changes refer to `CHANGELOG.md` in the root folder of the Mailu github project. Please read the 'Override location changes' section. It contains important information for the people who use the overrides folder.
New Functionality & Improvements
````````````````````````````````
Heres a short summary of new features:
- Full-text-search is back after having been disabled for a while due to nasty bugs. It can still be disabled via the mailu.env file.
- Tons of documentation improvements, especially geared towards new users.
- (Experimental) support for different architectures, such as ARM.
- Improvements around webmails, such as CardDAV, GPG and a new skin for an updated roundcube, and support for MySQL for it. Updated Rainloop, too.
- Improvements around relaying, such as AUTH LOGIN and non-standard port support.
- Update to alpine:3.12 as baseimage for most containers.
- Setup warns users about compose-IPv6 deployments which have caused open relays in the past.
- Improved handling of upper-vs-lowercase aliases and user-addresses.
- Improved rate-limiting system.
- Support for SRS.
- Japanese localisation is now available.
Upgrading
`````````
Upgrade should run fine as long as you generate a new compose or stack
configuration and upgrade your mailu.env.
Please note that the shipped image for PostgreSQL database is deprecated.
The shipped image for PostgreSQL is not maintained anymore from release 1.8.
We recommend switching to an external PostgreSQL database as soon as possible.
Override location changes Override location changes
````````````````````````` ^^^^^^^^^^^^^^^^^^^^^^^^^
If you have regenerated the Docker compose and environment files, there are some changes to the configuration overrides. If you have regenerated the Docker compose and environment files, there are some changes to the configuration overrides.
Override files are now mounted read-only into the containers. The Dovecot and Postfix overrides are moved in their own sub-directory. If there are local override files, they will need to be moved from ``overrides/`` to ``overrides/dovecot`` and ``overrides/postfix/``. Override files are now mounted read-only into the containers. The Dovecot and Postfix overrides are moved in their own sub-directory. If there are local override files, they will need to be moved from ``overrides/`` to ``overrides/dovecot`` and ``overrides/postfix/``.
Update your DNS SPF Records
^^^^^^^^^^^^^^^^^^^^^^^^^^^
It has become known that the SPF DNS records generated by the admin interface are not completely standard compliant anymore. Please check the DNS records for your domains and compare them to what the new admin-interface instructs you to use. In most cases, this should be a simple copy-paste operation for you ….
Mailu 1.7 - 2019-08-22 Mailu 1.7 - 2019-08-22
---------------------- ----------------------
@ -56,7 +95,7 @@ configuration and upgrade your mailu.env.
If you run the PostgreSQL server, the database was upgrade, so you will need to If you run the PostgreSQL server, the database was upgrade, so you will need to
dump the database before upgrading and load the dump after the upgrade is dump the database before upgrading and load the dump after the upgrade is
complete. Please not that the shipped image for PostgreSQL database will be complete. Please note that the shipped image for PostgreSQL database will be
deprecated before 1.8.0, you can switch to an external database server by then. deprecated before 1.8.0, you can switch to an external database server by then.

@ -225,6 +225,6 @@ You can also download the example configuration files:
Disable completely Mailu reverse proxy Disable completely Mailu reverse proxy
-------------------------------------- --------------------------------------
You can simply disable Mailu reverse proxy by removing the ``front`` section from the ``docker-compose.yml`` and use your own means to reverse proxy requests to the proper containers. You must not disable Mailu reverse proxy by removing the ``front`` section from the ``docker-compose.yml``.
Be careful with this method as resolving container addresses outside the Docker Compose structure is a tricky task: there is no guarantee that addresses will remain after a restart and you are almost certain that addresses will change after every upgrade (and whenever containers are recreated). ``front`` is handling authentication and is also proxying e.g. SMTP and IMAP. A basic HTTP reverse proxy as described in this document is not sufficient for this.

@ -38,7 +38,7 @@ Pick a Mailu version
Mailu is shipped in multiple versions. Mailu is shipped in multiple versions.
- ``1.7`` features the most recent stable version for Mailu. This is the - ``1.8`` features the most recent stable version for Mailu. This is the
recommended build for new setups, old setups should migrate when possible. recommended build for new setups, old setups should migrate when possible.
- ``1.0``, ``1.1``, and other version branches feature old versions of Mailu - ``1.0``, ``1.1``, and other version branches feature old versions of Mailu

@ -106,6 +106,9 @@ As a side effect of this ingress mode "feature", make sure that the ingress subn
- front and webmail are scalable (pending POD_ADDRESS_RANGE is used), although the let's encrypt magic might not like it (race condidtion ? or risk to be banned by let's encrypt server if too many front containers attemps to renew the certs at the same time) - front and webmail are scalable (pending POD_ADDRESS_RANGE is used), although the let's encrypt magic might not like it (race condidtion ? or risk to be banned by let's encrypt server if too many front containers attemps to renew the certs at the same time)
- redis, antispam, antivirus, fetchmail, admin, webdav have not been tested (hence replicas=1 in the following docker-compose.yml file) - redis, antispam, antivirus, fetchmail, admin, webdav have not been tested (hence replicas=1 in the following docker-compose.yml file)
## Docker secrets
There are DB_PW_FILE and SECRET_KEY_FILE environment variables available to specify files for these variables. These can be used to configure Docker secrets instead of writing the values directly into the `docker-compose.yml` or `mailu.env`.
## Variable substitution and docker-compose.yml ## Variable substitution and docker-compose.yml
The docker stack deploy command doesn't support variable substitution in the .yml file itself. The docker stack deploy command doesn't support variable substitution in the .yml file itself.
As a consequence, we cannot simply use ``` docker stack deploy -c docker.compose.yml mailu ``` As a consequence, we cannot simply use ``` docker stack deploy -c docker.compose.yml mailu ```

@ -0,0 +1,436 @@
Web administration interface
============================
The web administration interface is the main website for maintaining your Mailu installation.
For brevity the web administration interface will now be mentioned as admin gui.
It offers the following configuration options:
* change display name.
* change the logged in user's password.
* change user defined spam filter tolerance.
* configure automatic forwarding.
* configure automatic email replies (out of office replies).
* configure fetchmail for automatic email retrieval (from 3rd-party servers).
* configure application passwords.
* send broadcast messages to all users.
* configure global administration users.
* configure relayed domains.
* access Rspamd webui.
* Configure all email domains served by Mailu, including:
* generating dkim and dmarc keys for a domain.
* view email domain information on how to configure your SPF, DMARC, DKIM and MX dns records for an email domain.
* Add new email domains.
* For existing domains, configure users, quotas, aliases, administrators and alternative domain names.
* access the webmail site.
* lookup settings for configuring your email client.
Access the web administration interface
---------------------------------------
The admin GUI is by default accessed via the URL `https://<my domain>/admin`, when it's enabled in the setup utility or by manually setting `ADMIN=true` in `mailu.env`.
To login the admin GUI enter the email address and password of an user.
Only global administrator users have access to all configuration settings and the Rspamd webgui. Other users will be presented with settings for only their account, and domains they are managers of.
To create a user who is a global administrator for a new installation, the Mailu.env file can be adapted.
For more information see the section 'Admin account - automatic creation' in :ref:`the configuration reference <admin_account>`.
The following sections are only accessible for global administrators:
* send broadcast messages to all users (Menu item Broadcasts)
* configure global administration users (Menu item Administrators)
* configure relayed domains (Menu item Relayed domains)
* access Rspamd webui (Menu item Antispam)
* Configure all email domains served by Mailu (Menu item Mail domains)
.. _webadministration_settings:
Settings
--------
After logging in the web administration interface, the settings page is loaded.
On the settings page the settings of the currently logged in user can be changed.
Changes are saved and effective immediately after clicking the Save Settings button at the bottom of the page.
Display name
````````````
On the settings page the displayed name can be changed of the logged in user.
This display name is only used within the web administration interface.
Antispam
````````
Under the section `Antispam` the spam filter can be enabled or disabled for the logged in user. By default the spam filter is enabled.
When the spam filter is disabled, all received email messages will go to the inbox folder of the logged in user.
The exception to this rule, are email messages with an extremely high spam score. These email messages are always rejected by Rspamd.
When the spam filter is enabled, received email messages will be moved to the logged in user's inbox folder or junk folder depending on the user defined spam filter tolerance.
The user defined spam filter tolerance determines when an email is classified as ham (moved to the inbox folder) or spam (moved to the junk folder).
The default value is 80%. The lower the spam filter tolerance, the more false positives (ham classified as spam). The higher the spam filter tolerance, the more false negatives (spam classified as ham).
For more information see the :ref:`antispam documentation <antispam_howto>`.
Auto-forward
`````````````
Under the section `Auto-forward`, the automatic forwarding of received email messages can be enabled. When enabled, all received email messages are forwarded to the specified email address.
The option "Keep a copy of the emails" can be ticked, to keep a copy of the received email message in the inbox folder.
In the destination textbox, the email addresses can be entered for automatic forwarding. When entering multiple email addresses the comma (',') must be used as delimiter.
Update password
---------------
On the `update password` page, the password of the logged in user can be changed. Changes are effective immediately.
.. _webadministration_auto-reply:
Auto-reply
----------
On the `auto-reply` page, automatic replies can be configured. This is also known as out of office (ooo) or out of facility (oof) replies.
To enable automatic replies tick the checkbox 'Enable automatic reply'.
Under Reply subject the email subject for automatic replies can be configured. When a reply subject is entered, this subject will be used for the automatic reply.
When no reply subject is entered, the automatic reply will have the subject `auto: <subject from received email>`.
E.g. if the email subject of the received email message is "how are you?", then the email subject of the automatic reply is `auto: how are you?`.
.. _webadministration_fetched_accounts:
Fetched accounts
----------------
This page is only available when the Fetchmail container is part of your Mailu deployment.
Fetchmail can be enabled when creating the docker-compose.yml file with the setup utility (https://setup.mailu.io).
On the `fetched accounts` page you can configure email accounts from which email messages will be retrieved.
Only unread email messages are retrieved from the specified email account.
By default Fetchmail will retrieve email messages every 10 minutes. This can be changed in the Mailu.env file.
For more information on changing the polling interval see :ref:`the configuration reference <fetchmail>`.
You can add a fetched account by clicking on the `Add an account` button on the top right of the page. To add an fetched account, the following settings must be configured:
* Protocol (IMAP or POP3). The protocol used for accessing the email server.
* Hostname or IP. The hostname or IP address of the email server.
* TCP port. The TCP port the email server listens on. Common ports are 993 (IMAPS with TLS), 143 (IMAP with STARTTLS), 995 (POP3S with TLS) or 110 (POP3 with STARTTLS).
* Enable TLS. Tick this setting if the email server requires TLS/SSL instead of STARTTLS.
* Username. The user name for logging in to the email server. Normally this is the email address or the email address' local-part (the part before @).
* Password. The password for logging in to the email server.
* Keep emails on the server. When ticked, retains the email message in the email account after retrieving it.
Click the submit button to apply settings. With the default polling interval, fetchmail will start polling the email account after 10 minutes.
Authentication tokens
---------------------
On the `authentication tokens` page, authentication tokens can be created. Authentications tokens are also known as application passwords.
The purpose of an authentication token is to create a unique and strong password that can be used by a single application to authenticate as the logged in user's email account.
The application will use this authentication token instead of the logged in user's password for sending/receiving email.
This allows safe access to the logged in user's email account. At any moment, the authentication token can be deleted so that the application has no access to the logged in user's email account anymore.
By clicking on the New token button on the top right of the page, a new authentication token can be created. On this page the generated authentication token will only be displayed once.
After saving the application token it is not possible anymore to view the unique password.
The comment field can be used to enter a description for the authentication token. For example the name of the application the application token is created for.
In the Authorized IP field a white listed IP address can be entered. When an IP address is entered, then the application token can only be used when the IP address of the client matches with this IP address.
When no IP address is entered, there is no restriction on IP address. It is not possible to enter multiple IP addresses.
Announcement
------------
On the `announcement` page, the global administrator can send an email message to all email accounts on the Mailu server. This message will be received as an email message in the inbox folder of each user on the Mailu server.
On the announcement page there are the following options:
* Announcement subject. The subject of the announcement email message.
* Announcement body. The body of the announcement email message.
Click on send to send the announcement email message to all users.
Administrators
--------------
On the `administrators` page, global administrators can be added. A global administrator must be an existing user on the Mailu server.
A global administrator can change `any setting` in the admin GUI. Be careful that you trust the user who you make a global administrator.
Relayed domains
---------------
On the `relayed domains list` page, destination domains can be added that Mailu will relay email messages for without authentication.
This means that for these destination domains, other email clients or email servers can send email via Mailu unauthenticated via port 25 to this destination domain.
For example if the destination domain example.com is added. Any emails to example.com (john@example.com) will be relayed to example.com.
Example scenario's are:
* relay domain from a backup server.
* allow relay for a specific domain for technical reasons.
* relay mails to mailing list servers.
On the new relayed domain page the following options can be entered for a new relayed domain:
* Relayed domain name. The domain name that is relayed. Email messages addressed to this domain (To: John@example.com), will be forwarded to this domain.
No authentication is required.
* Remote host (optional). The SMPT server that will be used for relaying the email message.
When this field is blank, the Mailu server will directly send the email message to the relayed domain.
As value can be entered either a hostname or IP address of the SMPT server.
By default port 25 is used. To use a different port append ":port number" to the Remote Host. For example:
123.45.67.90:2525.
* Comment. A text field where a comment can be entered to describe the entry.
Changes are effective immediately after clicking the Save button.
NOTE: Due to bug `1588`_ email messages fail to be relayed if no Remote Host is configured.
As a workaround the HOSTNAME or IP Address of the SMPT server of the relayed domain can be entered as Remote Host.
Please note that no MX lookup is performed when entering a hostname as Remote Host. You can use the MX lookup on mxtoolbox.com to find the hostname and IP Address of the SMTP server.
.. _`1588`: https://github.com/Mailu/Mailu/issues/1588
Antispam
--------
The menu item Antispam opens the Rspamd webgui. For more information how spam filtering works in Mailu see the :ref:`Spam filtering page <antispam_howto_block>`.
The spam filtering page also contains a section that describes how to create a local blacklist for blocking email messages from specific domains.
The Rspamd webgui offers basic functions for setting metric actions, scores, viewing statistics and learning.
The following settings are not persisent and are *lost* when the Antispam container is recreated or restarted:
* On the configuration tab, any changes to config files that do not reside in /var/lib or /etc/rspamd/override.d. The last location is mapped to the Mailu overrides folder.
* All information on the History tab.
The following settings are persistent and will survive container recreation:
* All information on the Status tab
* All information on the Throughput tab.
* On the Configuration tab, the changes made to action values (greylist, probably spam ....) and config files that reside in /var/lib or /etc/rspamd/override.d. The last location is mapped to the Mailu overrides folder.
* Any changes made on the Symbols tab.
* Any email messages that have been submitted for spam/ham learning on the Scan/Learn tab.
Mail domains
------------
On the `Mail domains` page all the domains served by Mailu are configured. Via the new domain button (top right) a new mail domain can be added. Please note that you may have to add the new domain to `HOSTNAMES` in your :ref:`mailu.env file <common_cfg>`. For existing domains you can access settings via the icons in the Actions column and Manage column. From left to right you have the following options within the Action column and Manage column.
Details
```````
This page is also accessible for domain managers. On the details page all DNS settings are displayed for configuring your DNS server. It contains information on what to configure as MX record and SPF record. On this page it is also possible to (re-)generate the keys for DKIM and DMARC. The option for generating keys for DKIM and DMARC is only available for global administrators. After generating the keys for DKIM and DMARC, this page will also show the DNS records for configuring the DKIM/DMARC records on the DNS server.
Edit
````
This page is only accessible for global administrators. On the edit page, the global settings for the domain can be changed.
* Maximum user count. The maximum amount of users that can be created under this domain. Once this limit is reached it is not possible anymore to add users to the domain; and it is also not possible for users to self-register.
* Maximum alias count. The maximum amount of aliases that can be created for an email account.
* Maximum user quota. The maximum amount of quota that can be assigned to a user. When creating or editing a user, this sets the limit on the maximum amount of quota that can be assigned to the user.
* Enable sign-up. When this option is ticked, self-registration is enabled. When the Admin GUI is accessed, in the menu list the option Signup becomes available.
Obviously this menu item is only visible when signed out. On the Signup page a user can create an email account.
If your Admin GUI is available to the public internet, this means your Mailu installation basically becomes a free email provider.
Use this option with care!
* Comment. Description for the domain. This description is visible on the parent domains list page.
Delete
``````
This page is only accessible for global administrators. This page allows you to delete the domain. The Admin GUI will ask for confirmation if the domain must be really deleted.
Users
`````
This page is also accessible for domain managers. On the users page new users can be added via the Add user button (top right of page). For existing users the following options are available via the columns Actions and User settings (from left to right)
* Edit. For all available options see :ref:`the Add user page <webadministration_add_user>`.
* Delete. Deletes the user. The Admin GUI will ask for confirmation if the user must be really deleted.
* Setting. Access the settings page of the user. See :ref:`the settings page <webadministration_settings>` for more information.
* Auto-reply. Access the auto-reply page of the user. See the :ref:`auto-reply page <webadministration_auto-reply>` for more information.
* Fetched accounts. Access the fetched accounts page of the user. See the :ref:`fetched accounts page <webadministration_fetched_accounts>` for more information.
.. _webadministration_add_user:
Add user
^^^^^^^^
For adding a new user the following options can be configured.
* E-mail. The email address of the new user.
* Password/Confirm password. The password for the new user. The new user can change his password after logging in the Admin GUI.
* Displayed name. The display name of the user within the Admin GUI.
* Comment. A description for the user. This description is shown on the Users page.
* Enabled. Tick this checkbox to enable the user account. When an user is disabled, the user is unable to login to the Admin GUI or webmail or access his email via IMAP/POP3 or send mail.
The email inbox of the user is still retained. This option can be used to temporarily suspend an user account.
* Quota. The maximum quota for the user's email box.
* Allow IMAP access. When ticked, allows email retrieval via the IMAP protocol.
* Allow POP3 access. When ticked, allows email retrieval via the POP3 protocol.
Aliases
```````
This page is also accessible for domain managers. On the aliases page, aliases can be added for email addresses. An alias is a way to disguise another email address.
Everything sent to an alias email address is actually received in the primary email account's inbox of the destination email address.
Aliases can diversify a single email account without having to create multiple email addresses (users).
It is also possible to add multiple email addresses to the destination field. All incoming mails will be sent to each users inbox in this case.
The following options are available when adding an alias:
* Alias. The alias to create for the specified email address. You cannot use an existing email address.
* Use SQL LIKE Syntax (e.g. for catch-all aliases). When this option is ticked, you can use SQL LIKE syntax as alias.
The SQL LIKE syntax is used to match text values against a pattern using wildcards. There are two wildcards that can be used with SQL LIKE syntax:
* % - The percent sign represents zero, one, or multiple characters
* _ - The underscore represents a single character
Examples are:
* a% - Finds any values that start with "a"
* %a - Finds any values that end with "a"
* %or% - Finds any values that have "or" in any position
* _r% - Finds any values that have "r" in the second position
* a_% - Finds any values that start with "a" and are at least 2 characters in length
* a__% - Finds any values that start with "a" and are at least 3 characters in length
* a%o - Finds any values that start with "a" and ends with "o"
* Destination. The destination email address for the alias. Click in the Destination text box to access a drop down list where you can select a destination email address.
* Comment. A description for the alias. This description is visible on the Alias list page.
Managers
````````
This page is also accessible for domain managers. On the `managers list` page, managers can be added for the domain and can be deleted.
Managers have access to configuration settings of the domain.
On the `add manager` page you can click on the manager email text box to access a drop down list of users that can be made a manager of the domain.
Alternatives
````````````
This page is only accessible for global administrators. On the alternatives page, alternative domains can be added for the domain.
An alternative domain acts as a copy of a given domain.
Everything sent to an alternative domain, is actually received in the domain the alternative is created for.
This allows you to receive emails for multiple domains while using a single domain.
For example if the main domain has the email address user@example.com, and the alternative domain is mymail.com,
then email send to user@mymail.com will end up in the email box of user@example.com.
New domain
`````````````````
This page is only accessible for global administrators. Via this page a new domain can be added to Mailu. The following options must be defined for adding a domain:
* domain name. The name of the domain.
* Maximum user count. The maximum amount of users that can be created under this domain. Once this limit is reached it is not possible anymore to add users to the domain; and it is also not possible for users to self-register.
* Maximum alias count. The maximum amount of aliases that can be made for an email account.
* Maximum user quota. The maximum amount of quota that can be assigned to a user. When creating or editing a user, this sets the limit on the maximum amount of quota that can be assigned to the user.
* Enable sign-up. When this option is ticked, self-registration is enabled. When the Admin GUI is accessed, in the menu list the option Signup becomes available.
Obviously this menu item is only visible when signed out. On the Signup page a user can create an email account.
If your Admin GUI is available to the public internet, this means your Mailu installation basically becomes a free email provider.
Use this option with care!
* Comment. Description for the domain. This description is visible on the parent domains list page.
Webmail
-------
The menu item `Webmail` opens the webmail page. This option is only available if the webmail container is running and is enabled in the mailu.env file.
Client setup
------------
The menu item `Client setup` shows all settings for configuring your email client for connecting to Mailu.
Website
-------
The menu item `Website` forwards the user to the URL that is configured in variable WEBSITE=xxxxx in the mailu.env environment file.
Help
----
The menu item `Help` links to the official Mailu documentation website https://mailu.io/
Sign out
--------
The menu item `Sign out` signs out the currently logged in user.

@ -28,7 +28,7 @@ poll "{host}" proto {protocol} port {port}
def extract_host_port(host_and_port, default_port): def extract_host_port(host_and_port, default_port):
host, _, port = re.match('^(.*)(:([0-9]*))?$', host_and_port).groups() host, _, port = re.match('^(.*?)(:([0-9]*))?$', host_and_port).groups()
return host, int(port) if port else default_port return host, int(port) if port else default_port

@ -29,7 +29,7 @@ services:
- "{{ root }}/certs:/certs" - "{{ root }}/certs:/certs"
- "{{ root }}/overrides/nginx:/overrides:ro" - "{{ root }}/overrides/nginx:/overrides:ro"
deploy: deploy:
replicas: {{ front_replicas }} replicas: 1
admin: admin:
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}admin:${MAILU_VERSION:-{{ version }}} image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}admin:${MAILU_VERSION:-{{ version }}}
@ -42,7 +42,7 @@ services:
- "{{ root }}/data:/data" - "{{ root }}/data:/data"
- "{{ root }}/dkim:/dkim" - "{{ root }}/dkim:/dkim"
deploy: deploy:
replicas: {{ admin_replicas }} replicas: 1
healthcheck: healthcheck:
disable: true disable: true
@ -53,7 +53,7 @@ services:
- "{{ root }}/mail:/mail" - "{{ root }}/mail:/mail"
- "{{ root }}/overrides/dovecot:/overrides:ro" - "{{ root }}/overrides/dovecot:/overrides:ro"
deploy: deploy:
replicas: {{ imap_replicas }} replicas: 1
healthcheck: healthcheck:
disable: true disable: true
@ -64,7 +64,7 @@ services:
- "{{ root }}/mailqueue:/queue" - "{{ root }}/mailqueue:/queue"
- "{{ root }}/overrides/postfix:/overrides:ro" - "{{ root }}/overrides/postfix:/overrides:ro"
deploy: deploy:
replicas: {{ smtp_replicas }} replicas: 1
healthcheck: healthcheck:
disable: true disable: true

@ -53,7 +53,10 @@ def build_app(path):
@app.context_processor @app.context_processor
def app_context(): def app_context():
return dict(versions=os.getenv("VERSIONS","master").split(',')) return dict(
versions=os.getenv("VERSIONS","master").split(','),
stable_version = os.getenv("stable_version", "master")
)
prefix_bp = flask.Blueprint(version, __name__) prefix_bp = flask.Blueprint(version, __name__)
prefix_bp.jinja_loader = jinja2.ChoiceLoader([ prefix_bp.jinja_loader = jinja2.ChoiceLoader([

@ -51,7 +51,12 @@ $(document).ready(function() {
} else if (this.value == 'postgresql') { } else if (this.value == 'postgresql') {
$("#postgres_db").show(); $("#postgres_db").show();
$("#external_db").hide(); $("#external_db").hide();
$("#external_db").prop('checked', false); $("#external_psql").prop('checked', true);
$("#external_db").show();
$("#db_user").prop('required',true);
$("#db_pw").prop('required',true);
$("#db_url").prop('required',true);
$("#db_name").prop('required',true);
} else if (this.value == 'mysql') { } else if (this.value == 'mysql') {
$("#postgres_db").hide(); $("#postgres_db").hide();
$("#external_db").show(); $("#external_db").show();

@ -8,13 +8,21 @@
<h1>Mailu configuration</h1> <h1>Mailu configuration</h1>
<p> <p>
Version Version
<select onchange="window.location.href=this.value;" class="btn btn-primary dropdown-toggle"> <select id=version_select onchange="window.location.href=this.value;" class="btn btn-primary dropdown-toggle">
{% for module in versions %} {% for module in versions %}
<option value="/{{ module }}" {% if module == version %}selected{% endif %}>{{ module }}</option> <option value="/{{ module }}" {% if module == version %}selected {% endif %}>{{ module }}</option>
{% endfor %} {% endfor %}
</select> </select>
</p> </p>
{% if version != stable_version %}
{% call macros.panel("danger", "You have not selected the stable version") %}
You have not selected the stable version. The stable version is {{ stable_version }}.
The selected version can be used for testing and reporting bugs.
For production scenarios we recommend to use the stable version.
{% endcall %}
{% endif %}
{% block page %}{% endblock %} {% block page %}{% endblock %}
</div> </div>

@ -12,7 +12,7 @@
{% macro radio(name, value, emph, text, current) %} {% macro radio(name, value, emph, text, current) %}
<div class="radio"> <div class="radio">
<label> <label>
<input type="radio" name="{{ name }}" value="{{ value }}"{% if current == value %} checked="checked"{% endif %}> <input type="radio" name="{{ name }}" value="{{ value }}"{% if current == value %} checked="checked"{% endif %} required="required">
{% if emph %} {% if emph %}
<strong>{{ emph }}</strong>, <strong>{{ emph }}</strong>,
{% endif %} {% endif %}

@ -31,7 +31,7 @@ avoid generic all-interfaces addresses like <code>0.0.0.0</code> or <code>::</co
</div> </div>
<div class="form-group" id="ipv6" style="display: none"> <div class="form-group" id="ipv6" style="display: none">
<p><span class="label label-danger">Read this:</span> Docker currently does not expose the IPv6 ports properly, as it does not interface with <code>ip6tables</code>. Be sure to read our <a href="https://mailu.io/{{ version }}/faq.html#how-to-make-ipv6-work">FAQ section</a>!</p> <p><span class="label label-danger">Read this:</span> Docker currently does not expose the IPv6 ports properly, as it does not interface with <code>ip6tables</code>. Be sure to read our <a href="https://mailu.io/{{ version }}/faq.html#how-to-make-ipv6-work">FAQ section</a> and be <b>very careful</b> if you still wish to enable this!</p>
<label>IPv6 listen address</label> <label>IPv6 listen address</label>
<!-- Validates IPv6 address --> <!-- Validates IPv6 address -->
<input class="form-control" type="text" name="bind6" value="::1" <input class="form-control" type="text" name="bind6" value="::1"

@ -1,9 +1,11 @@
{% if flavor == "stack" %} {% if flavor == "stack" %}
{% call macros.panel("danger", "Docker stack / swarm is experimental") %} {% call macros.panel("danger", "Docker stack / swarm is experimental") %}
Setup is capable of generating a somewhat decent docker-compose.yml, Setup is capable of generating a somewhat decent docker-compose.yml,
for the docker stack flavor. However its usage is for advanced users an is experimental. for the docker stack flavor. However its usage is for advanced users only and is experimental.
Expect many challenges is shared mail storage and fail-over scenarios! Some user experiences Expect many challenges such as shared mail storage and fail-over scenarios! Some user experiences
have been <a href="https://github.com/Mailu/Mailu/blob/master/docs/swarm/master/README.md">shared on GitHub.</a> have been <a href="https://github.com/Mailu/Mailu/blob/master/docs/swarm/master/README.md">shared on GitHub.</a>
For this reason also think very hard about using a replica count higher than 1. This cannot be used with the default config.
Manual post-configuration is required for using a replica count higher than 1.
{% endcall %} {% endcall %}
{% endif %} {% endif %}

@ -11,13 +11,16 @@
<p></p> <p></p>
<div id="postgres_db" style="display: none"> <div id="postgres_db" style="display: none">
<div class="form-check"> <div class="form-check">
<input class="form-check-input" type="radio" name="postgresql" id="internal_psql" value="internal" checked> <input class="form-check-input" type="radio" name="postgresql" id="internal_psql" value="internal">
<label class="form-check-label" for="internal_psql"> <label class="form-check-label" for="internal_psql">
Use the Postgresql from Mailu Use the PostgreSQL image from Mailu. Warning, this image is deprecated.
It will be removed from Mailu 1.9. Existing users can still upgrade to Mailu 1.8 using this image.
With the release of Mailu 1.9,
we will offer a mechanism for migrating your data to another database management system.
</label> </label>
</div> </div>
<div class="form-check"> <div class="form-check">
<input class="form-check-input" type="radio" name="postgresql" value="external" id="external_psql" > <input class="form-check-input" type="radio" name="postgresql" value="external" id="external_psql">
<label class="form-check-label" for="external_psql"> <label class="form-check-label" for="external_psql">
I want to connect to an external database I want to connect to an external database
</label> </label>
@ -37,4 +40,4 @@
</div> </div>
</div> </div>
{% endcall %} {% endcall %}

@ -1,28 +0,0 @@
{% call macros.panel("info", "Step 5 - Number of replicas for containers") %}
<p>Select number of replicas for containers</p>
<div class="form-group">
<input class="form-control" type="number" name="front_replicas" min="1" required value="1"
style="width: 6%; display: inline;">
<label>Front</label>
</div>
<div class="form-group">
<input class="form-control" type="number" name="admin_replicas" min="1" required value="1"
style="width: 6%; display: inline;">
<label>Admin</label>
</div>
<div class="form-group">
<input class="form-control" type="number" name="imap_replicas" min="1" required value="1"
style="width: 6%; display: inline;">
<label>IMAP</label>
</div>
<div class="form-group">
<input class="form-control" type="number" name=smtp_replicas min="1" required value="1"
style="width: 6%; display: inline;">
<label>SMTP</label>
</div>
{% endcall %}

@ -6,6 +6,6 @@ echo "The above error was intended!"
docker-compose -f tests/compose/core/docker-compose.yml exec -T admin flask mailu admin admin mailu.io 'FooBar' --mode=ifmissing || exit 1 docker-compose -f tests/compose/core/docker-compose.yml exec -T admin flask mailu admin admin mailu.io 'FooBar' --mode=ifmissing || exit 1
# Should not fail and update the password; update mode # Should not fail and update the password; update mode
docker-compose -f tests/compose/core/docker-compose.yml exec -T admin flask mailu admin admin mailu.io 'password' --mode=update || exit 1 docker-compose -f tests/compose/core/docker-compose.yml exec -T admin flask mailu admin admin mailu.io 'password' --mode=update || exit 1
docker-compose -f tests/compose/core/docker-compose.yml exec -T admin flask mailu user user mailu.io 'password' 'SHA512-CRYPT' || exit 1 docker-compose -f tests/compose/core/docker-compose.yml exec -T admin flask mailu user user mailu.io 'password' || exit 1
docker-compose -f tests/compose/core/docker-compose.yml exec -T admin flask mailu user 'user/with/slash' mailu.io 'password' 'SHA512-CRYPT' || exit 1 docker-compose -f tests/compose/core/docker-compose.yml exec -T admin flask mailu user 'user/with/slash' mailu.io 'password' || exit 1
echo "User testing succesfull!" echo "User testing succesfull!"

@ -2,7 +2,6 @@ cat << EOF | docker-compose -f tests/compose/core/docker-compose.yml exec -T adm
users: users:
- localpart: forwardinguser - localpart: forwardinguser
password_hash: "\$1\$F2OStvi1\$Q8hBIHkdJpJkJn/TrMIZ9/" password_hash: "\$1\$F2OStvi1\$Q8hBIHkdJpJkJn/TrMIZ9/"
hash_scheme: MD5-CRYPT
domain: mailu.io domain: mailu.io
forward_enabled: true forward_enabled: true
forward_destination: ["user@mailu.io"] forward_destination: ["user@mailu.io"]
@ -14,7 +13,6 @@ cat << EOF | docker-compose -f tests/compose/core/docker-compose.yml exec -T adm
users: users:
- localpart: forwardinguser - localpart: forwardinguser
password_hash: "\$1\$F2OStvi1\$Q8hBIHkdJpJkJn/TrMIZ9/" password_hash: "\$1\$F2OStvi1\$Q8hBIHkdJpJkJn/TrMIZ9/"
hash_scheme: MD5-CRYPT
domain: mailu.io domain: mailu.io
forward_enabled: false forward_enabled: false
forward_destination: [] forward_destination: []

@ -2,7 +2,6 @@ cat << EOF | docker-compose -f tests/compose/core/docker-compose.yml exec -T adm
users: users:
- localpart: replyuser - localpart: replyuser
password_hash: "\$1\$F2OStvi1\$Q8hBIHkdJpJkJn/TrMIZ9/" password_hash: "\$1\$F2OStvi1\$Q8hBIHkdJpJkJn/TrMIZ9/"
hash_scheme: MD5-CRYPT
domain: mailu.io domain: mailu.io
reply_enabled: true reply_enabled: true
reply_subject: This will not reach me reply_subject: This will not reach me
@ -15,7 +14,6 @@ cat << EOF | docker-compose -f tests/compose/core/docker-compose.yml exec -T adm
users: users:
- localpart: replyuser - localpart: replyuser
password_hash: "\$1\$F2OStvi1\$Q8hBIHkdJpJkJn/TrMIZ9/" password_hash: "\$1\$F2OStvi1\$Q8hBIHkdJpJkJn/TrMIZ9/"
hash_scheme: MD5-CRYPT
domain: mailu.io domain: mailu.io
reply_enabled: false reply_enabled: false
EOF EOF

@ -1 +0,0 @@
Allow to enforce TLS for outbound mail by setting OUTBOUND_TLS_LEVEL=encrypt for postfix.

@ -1 +0,0 @@
Add support for Traefik v2 certificate dumping

@ -1 +0,0 @@
Ignore newlines and comment-lines in postfix overrides - this means you can now make your override configfiles much more readable.

@ -1 +0,0 @@
Resolve hosts to IPs if only HOST_* is set. If *_ADDRESS is set, leave it unresolved.

@ -1 +0,0 @@
Fix the password encoding upon authentication

@ -1 +0,0 @@
- Use nginx as http endpoint on kubernetes to simplify ingress

@ -1 +0,0 @@
Advertise correct mail capabilities through the front-container, this also enables support for PIPELINING in mail-protocols and IMAP IDLE which is a (potential) performance gain.

@ -1 +0,0 @@
Added documentation that describes how spam filtering works in Mailu.

@ -1 +0,0 @@
Fix piping mail into rspamd when moving from/to junk-folder

@ -1 +0,0 @@
Separate HOST_ANTISPAM in HOST_ANTISPAM_MILTER and HOST_ANTISPAM_WEBUI because of different ports

@ -1 +0,0 @@
Change default password scheme to PBKDF2

@ -1 +0,0 @@
Enable access log of admin service only for log levels of INFO and finer

@ -1 +0,0 @@
japanese loca is now available

@ -1 +0,0 @@
Make postfix mailqueue persistent

@ -1 +0,0 @@
Move rspamd, fetchmail and unbound services into core and optional

@ -1 +0,0 @@
Dovecot: Delete obsolete data volume

@ -1 +0,0 @@
Kubernetes manifests updated to be compatible with Kubernetes 1.16 (breaks compatibility with older k8s versions)

@ -1 +0,0 @@
Use pip package for radicale to fix failing builds caused by [alpine]upstream package rebuild against different python version

@ -1 +0,0 @@
Allow to reject virus mails by setting ANTIVITUS_ACTION=reject

@ -1 +0,0 @@
Update roundcube to 1.4.0 and enable the new elastic skin

@ -1 +0,0 @@
The roundcube container does support mysql now (no setup integration yet)

@ -1,2 +0,0 @@
Ratelimit counts up on failed auth only now

@ -1 +0,0 @@
Disable Health checks on swarm mode

@ -1 +0,0 @@
Added CardDAV-Plugin for webmail roundcube.

@ -1 +0,0 @@
Use Redis 5.0 in kubernetes manifests

@ -1 +0,0 @@
Allow users to use server-sided full-text-search again by adding the dovecot fts-xapian plugin

@ -1 +0,0 @@
Relay a domain to a nonstandard SMTP port by adding ":<port_num>" to the remote hostname or IP address.

@ -1 +0,0 @@
Enable the From header for message delivery report in Roundcube and ensure DKIM Signature

@ -1 +0,0 @@
Fix alias resolution in regard to case: A specifically matching alias of wrong case is now preferred over a wildcard alias that might have »eaten« it previously.

@ -1 +0,0 @@
Show SPF records in accordance with RFC 7208: Previously we instructed admins to create SPF and TXT records, where only TXT records are correct now. !! Attention !! You need to manually remove the SPF-typed records and keep only TXT in your DNS.

@ -1 +0,0 @@
Cover relearning messages when moving bewteen Ham and Spam status

@ -1 +0,0 @@
Harden security by making certain configuration files read-only. Moves Postfix and Dovecot overrides an independed sub-directories.

@ -1 +0,0 @@
Defining POSTMASTER through setup tool apply also to DMARC_RUA and DMARC_RUF settings

@ -1 +0,0 @@
Allow IPv6 authenticated connections in PostgreSQL pg_hba.conf

@ -1 +0,0 @@
Check postfix mailqueue permissions before start-up

@ -1 +0,0 @@
Use Radicale 3.x for webdav service

@ -1 +0,0 @@
Introduce option to disable dovecot full-text-search by an enviroment variable.

@ -0,0 +1 @@
Implement SECRET_KEY_FILE and DB_PW_FILE variables for usage with Docker secrets.

@ -0,0 +1 @@
Enable OCSP stapling for the http server within nginx.

@ -0,0 +1 @@
Enable support of all hash types passlib supports.

@ -0,0 +1 @@
Fix "extract_host_port" function to support containers with custom / dynamic ports

@ -0,0 +1 @@
Fix letsencrypt access to certbot for the mail-letsencrypt flavour

@ -0,0 +1 @@
Hide x-powered-by PHP-version header from webmails

@ -0,0 +1 @@
This adds more details about the postfix-override possibilities (fixes #1628)

@ -0,0 +1,2 @@
Fix CVE-2020-25275 and CVE-2020-24386 by using alpine 3.13 for
dovecot which contains a fixed dovecot version.

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save