mirror of
https://github.com/Mailu/Mailu.git
synced 2025-04-23 12:08:54 +02:00
Merge remote-tracking branch 'upstream/master' into webmail-sso
This commit is contained in:
commit
dd3d03f06d
@ -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|lub|Diman0)$
|
- 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"
|
||||||
|
@ -34,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/*'
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ 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/.
|
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.
|
See https://mailu.io/1.8/faq.html#how-can-i-override-settings for all the mappings.
|
||||||
|
|
||||||
Please not that the shipped image for PostgreSQL database is deprecated.
|
Please note that the shipped image for PostgreSQL database is deprecated.
|
||||||
We advise to switch to an external database server.
|
We advise to switch to an external database server.
|
||||||
|
|
||||||
<!-- TOWNCRIER -->
|
<!-- TOWNCRIER -->
|
||||||
@ -66,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
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
import flask
|
import flask
|
||||||
import flask_bootstrap
|
import flask_bootstrap
|
||||||
|
import redis
|
||||||
|
from flask_kvsession import KVSessionExtension
|
||||||
|
from simplekv.memory.redisstore import RedisStore
|
||||||
|
|
||||||
from mailu import utils, debug, models, manage, configuration
|
from mailu import utils, debug, models, manage, configuration
|
||||||
|
|
||||||
@ -18,6 +21,7 @@ def create_app_from_config(config):
|
|||||||
# Initialize application extensions
|
# Initialize application extensions
|
||||||
config.init_app(app)
|
config.init_app(app)
|
||||||
models.db.init_app(app)
|
models.db.init_app(app)
|
||||||
|
KVSessionExtension(RedisStore(redis.StrictRedis().from_url('redis://{0}/3'.format(config['REDIS_ADDRESS']))), app).cleanup_sessions(app)
|
||||||
utils.limiter.init_app(app)
|
utils.limiter.init_app(app)
|
||||||
utils.babel.init_app(app)
|
utils.babel.init_app(app)
|
||||||
utils.login.init_app(app)
|
utils.login.init_app(app)
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import os
|
import os
|
||||||
|
|
||||||
|
from datetime import timedelta
|
||||||
from socrate import system
|
from socrate import system
|
||||||
|
|
||||||
DEFAULT_CONFIG = {
|
DEFAULT_CONFIG = {
|
||||||
@ -31,6 +32,7 @@ DEFAULT_CONFIG = {
|
|||||||
'HOSTNAMES': 'mail.mailu.io,alternative.mailu.io,yetanother.mailu.io',
|
'HOSTNAMES': 'mail.mailu.io,alternative.mailu.io,yetanother.mailu.io',
|
||||||
'POSTMASTER': 'postmaster',
|
'POSTMASTER': 'postmaster',
|
||||||
'TLS_FLAVOR': 'cert',
|
'TLS_FLAVOR': 'cert',
|
||||||
|
'INBOUND_TLS_ENFORCE': False,
|
||||||
'AUTH_RATELIMIT': '10/minute;1000/hour',
|
'AUTH_RATELIMIT': '10/minute;1000/hour',
|
||||||
'AUTH_RATELIMIT_SUBNET': True,
|
'AUTH_RATELIMIT_SUBNET': True,
|
||||||
'DISABLE_STATISTICS': False,
|
'DISABLE_STATISTICS': False,
|
||||||
@ -52,8 +54,10 @@ 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_LIFETIME': 24,
|
||||||
|
'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',
|
||||||
@ -100,6 +104,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
|
||||||
@ -111,7 +124,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()
|
||||||
@ -123,6 +136,10 @@ 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
|
||||||
|
self.config['SESSION_KEY_BITS'] = 128
|
||||||
|
self.config['PERMANENT_SESSION_LIFETIME'] = timedelta(hours=int(self.config['SESSION_LIFETIME']))
|
||||||
# update the app config itself
|
# update the app config itself
|
||||||
app.config = self
|
app.config = self
|
||||||
|
|
||||||
|
@ -16,8 +16,29 @@ STATUSES = {
|
|||||||
"smtp": "535 5.7.8",
|
"smtp": "535 5.7.8",
|
||||||
"pop3": "-ERR Authentication failed"
|
"pop3": "-ERR Authentication failed"
|
||||||
}),
|
}),
|
||||||
|
"encryption": ("Must issue a STARTTLS command first", {
|
||||||
|
"smtp": "530 5.7.0"
|
||||||
|
}),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
# webmails
|
||||||
|
if len(password) == 64 and ip == app.config['WEBMAIL_ADDRESS']:
|
||||||
|
if user.verify_temp_token(password):
|
||||||
|
is_ok = True
|
||||||
|
# All tokens are 32 characters hex lowercase
|
||||||
|
if not is_ok and 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
|
||||||
@ -27,12 +48,27 @@ def handle_authentication(headers):
|
|||||||
protocol = headers["Auth-Protocol"]
|
protocol = headers["Auth-Protocol"]
|
||||||
# Incoming mail, no authentication
|
# Incoming mail, no authentication
|
||||||
if method == "none" and protocol == "smtp":
|
if method == "none" and protocol == "smtp":
|
||||||
server, port = get_server(headers["Auth-Protocol"], False)
|
server, port = get_server(protocol, False)
|
||||||
return {
|
if app.config["INBOUND_TLS_ENFORCE"]:
|
||||||
"Auth-Status": "OK",
|
if "Auth-SSL" in headers and headers["Auth-SSL"] == "on":
|
||||||
"Auth-Server": server,
|
return {
|
||||||
"Auth-Port": port
|
"Auth-Status": "OK",
|
||||||
}
|
"Auth-Server": server,
|
||||||
|
"Auth-Port": port
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
status, code = get_status(protocol, "encryption")
|
||||||
|
return {
|
||||||
|
"Auth-Status": status,
|
||||||
|
"Auth-Error-Code" : code,
|
||||||
|
"Auth-Wait": 0
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
return {
|
||||||
|
"Auth-Status": "OK",
|
||||||
|
"Auth-Server": server,
|
||||||
|
"Auth-Port": port
|
||||||
|
}
|
||||||
# Authenticated user
|
# Authenticated user
|
||||||
elif method == "plain":
|
elif method == "plain":
|
||||||
server, port = get_server(headers["Auth-Protocol"], True)
|
server, port = get_server(headers["Auth-Protocol"], True)
|
||||||
@ -46,28 +82,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:
|
|
||||||
# webmails
|
|
||||||
if len(password) == 64 and ip == app.config['WEBMAIL_ADDRESS']:
|
|
||||||
if user.verify_temp_token(password):
|
|
||||||
status = True
|
|
||||||
|
|
||||||
# All tokens are 32 characters hex lowercase
|
|
||||||
if not status and len(password) == 32:
|
|
||||||
for token in user.tokens:
|
|
||||||
if (token.check_password(password) and
|
|
||||||
(not token.ip or token.ip == ip)):
|
|
||||||
status = True
|
|
||||||
break
|
|
||||||
if not status and 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,
|
||||||
|
@ -65,7 +65,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
|
||||||
@ -306,6 +305,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'))
|
||||||
@ -363,25 +363,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
|
||||||
@ -390,13 +403,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:
|
||||||
@ -503,10 +513,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)"
|
||||||
|
672
core/admin/mailu/translations/eu/LC_MESSAGES/messages.po
Normal file
672
core/admin/mailu/translations/eu/LC_MESSAGES/messages.po
Normal file
@ -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 ""
|
||||||
|
|
||||||
|
@ -46,6 +46,8 @@ class ConfirmationForm(flask_wtf.FlaskForm):
|
|||||||
|
|
||||||
|
|
||||||
class LoginForm(flask_wtf.FlaskForm):
|
class LoginForm(flask_wtf.FlaskForm):
|
||||||
|
class Meta:
|
||||||
|
csrf = False
|
||||||
email = fields.StringField(_('E-mail'), [validators.Email()])
|
email = fields.StringField(_('E-mail'), [validators.Email()])
|
||||||
pw = fields.PasswordField(_('Password'), [validators.DataRequired()])
|
pw = fields.PasswordField(_('Password'), [validators.DataRequired()])
|
||||||
submit = fields.SubmitField(_('Sign in'))
|
submit = fields.SubmitField(_('Sign in'))
|
||||||
|
@ -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>
|
||||||
|
@ -18,6 +18,7 @@ def login():
|
|||||||
if form.validate_on_submit():
|
if form.validate_on_submit():
|
||||||
user = models.User.login(form.email.data, form.pw.data)
|
user = models.User.login(form.email.data, form.pw.data)
|
||||||
if user:
|
if user:
|
||||||
|
flask.session.regenerate()
|
||||||
flask_login.login_user(user)
|
flask_login.login_user(user)
|
||||||
endpoint = flask.request.args.get('next', '.index')
|
endpoint = flask.request.args.get('next', '.index')
|
||||||
return flask.redirect(flask.url_for(endpoint)
|
return flask.redirect(flask.url_for(endpoint)
|
||||||
@ -31,6 +32,7 @@ def login():
|
|||||||
@access.authenticated
|
@access.authenticated
|
||||||
def logout():
|
def logout():
|
||||||
flask_login.logout_user()
|
flask_login.logout_user()
|
||||||
|
flask.session.destroy()
|
||||||
return flask.redirect(flask.url_for('.index'))
|
return flask.redirect(flask.url_for('.index'))
|
||||||
|
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
@ -119,6 +119,7 @@ def user_password(user_email):
|
|||||||
if form.pw.data != form.pw2.data:
|
if form.pw.data != form.pw2.data:
|
||||||
flask.flash('Passwords do not match', 'error')
|
flask.flash('Passwords do not match', 'error')
|
||||||
else:
|
else:
|
||||||
|
flask.session.regenerate()
|
||||||
user.set_password(form.pw.data)
|
user.set_password(form.pw.data)
|
||||||
models.db.session.commit()
|
models.db.session.commit()
|
||||||
flask.flash('Password updated for %s' % user)
|
flask.flash('Password updated for %s' % user)
|
||||||
@ -186,6 +187,7 @@ def user_signup(domain_name=None):
|
|||||||
if domain.has_email(form.localpart.data):
|
if domain.has_email(form.localpart.data):
|
||||||
flask.flash('Email is already used', 'error')
|
flask.flash('Email is already used', 'error')
|
||||||
else:
|
else:
|
||||||
|
flask.session.regenerate()
|
||||||
user = models.User(domain=domain)
|
user = models.User(domain=domain)
|
||||||
form.populate_obj(user)
|
form.populate_obj(user)
|
||||||
user.set_password(form.pw.data)
|
user.set_password(form.pw.data)
|
||||||
|
@ -13,6 +13,7 @@ Flask==1.0.2
|
|||||||
Flask-Babel==0.12.2
|
Flask-Babel==0.12.2
|
||||||
Flask-Bootstrap==3.3.7.1
|
Flask-Bootstrap==3.3.7.1
|
||||||
Flask-DebugToolbar==0.10.1
|
Flask-DebugToolbar==0.10.1
|
||||||
|
Flask-KVSession==0.6.2
|
||||||
Flask-Limiter==1.0.1
|
Flask-Limiter==1.0.1
|
||||||
Flask-Login==0.4.1
|
Flask-Login==0.4.1
|
||||||
Flask-Migrate==2.4.0
|
Flask-Migrate==2.4.0
|
||||||
@ -29,7 +30,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
|
||||||
|
@ -3,6 +3,7 @@ Flask-Login
|
|||||||
Flask-SQLAlchemy
|
Flask-SQLAlchemy
|
||||||
Flask-bootstrap
|
Flask-bootstrap
|
||||||
Flask-Babel
|
Flask-Babel
|
||||||
|
Flask-KVSession
|
||||||
Flask-migrate
|
Flask-migrate
|
||||||
Flask-script
|
Flask-script
|
||||||
Flask-wtf
|
Flask-wtf
|
||||||
|
@ -79,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';
|
||||||
|
|
||||||
@ -239,7 +241,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+;
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ smtp inet n - n - - smtpd
|
|||||||
-o cleanup_service_name=outclean
|
-o cleanup_service_name=outclean
|
||||||
outclean unix n - n - 0 cleanup
|
outclean unix n - n - 0 cleanup
|
||||||
-o header_checks=pcre:/etc/postfix/outclean_header_filter.cf
|
-o header_checks=pcre:/etc/postfix/outclean_header_filter.cf
|
||||||
|
-o nested_header_checks=
|
||||||
|
|
||||||
# Internal postfix services
|
# Internal postfix services
|
||||||
pickup unix n - n 60 1 pickup
|
pickup unix n - n 60 1 pickup
|
||||||
|
@ -5,6 +5,9 @@ skip_authenticated = false;
|
|||||||
use = ["x-spamd-bar", "x-spam-level", "x-virus", "authentication-results"];
|
use = ["x-spamd-bar", "x-spam-level", "x-virus", "authentication-results"];
|
||||||
|
|
||||||
routines {
|
routines {
|
||||||
|
authentication-results {
|
||||||
|
add_smtp_user = false;
|
||||||
|
}
|
||||||
x-virus {
|
x-virus {
|
||||||
symbols = ["CLAM_VIRUS", "FPROT_VIRUS", "JUST_EICAR"];
|
symbols = ["CLAM_VIRUS", "FPROT_VIRUS", "JUST_EICAR"];
|
||||||
}
|
}
|
||||||
|
@ -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=
|
||||||
|
@ -73,6 +73,13 @@ By default postfix uses "opportunistic TLS" for outbound mail. This can be chang
|
|||||||
by setting ``OUTBOUND_TLS_LEVEL`` to ``encrypt``. This setting is highly recommended
|
by setting ``OUTBOUND_TLS_LEVEL`` to ``encrypt``. This setting is highly recommended
|
||||||
if you are a relayhost that supports TLS.
|
if you are a relayhost that supports TLS.
|
||||||
|
|
||||||
|
Similarily by default nginx uses "opportunistic TLS" for inbound mail. This can be changed
|
||||||
|
by setting ``INBOUND_TLS_ENFORCE`` to ``True``. Please note that this is forbidden for
|
||||||
|
internet facing hosts according to e.g. `RFC 3207`_ , because this prevents MTAs without STARTTLS
|
||||||
|
support or e.g. mismatching TLS versions to deliver emails to Mailu.
|
||||||
|
|
||||||
|
.. _`RFC 3207`: https://tools.ietf.org/html/rfc3207
|
||||||
|
|
||||||
.. _fetchmail:
|
.. _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
|
||||||
@ -138,9 +145,11 @@ 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.
|
||||||
|
|
||||||
|
``SESSION_LIFETIME`` (default: 24) is the length in hours a session is valid for on the administrative interface.
|
||||||
|
|
||||||
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
|
||||||
@ -257,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.
|
||||||
|
@ -33,9 +33,9 @@ Upgrading
|
|||||||
Upgrade should run fine as long as you generate a new compose or stack
|
Upgrade should run fine as long as you generate a new compose or stack
|
||||||
configuration and upgrade your mailu.env.
|
configuration and upgrade your mailu.env.
|
||||||
|
|
||||||
Please not that the shipped image for PostgreSQL database is deprecated.
|
Please note that the shipped image for PostgreSQL database is deprecated.
|
||||||
The shipped image for PostgreSQL is not maintained anymore from release 1.8.
|
The shipped image for PostgreSQL is not maintained anymore from release 1.8.
|
||||||
We recommend switching to an external database as soon as possible.
|
We recommend switching to an external PostgreSQL database as soon as possible.
|
||||||
|
|
||||||
Override location changes
|
Override location changes
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
@ -95,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.
|
||||||
|
|
||||||
|
|
||||||
|
@ -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 ```
|
||||||
|
@ -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
towncrier/newsfragments/1607.feature
Normal file
1
towncrier/newsfragments/1607.feature
Normal file
@ -0,0 +1 @@
|
|||||||
|
Implement SECRET_KEY_FILE and DB_PW_FILE variables for usage with Docker secrets.
|
1
towncrier/newsfragments/1610.feature
Normal file
1
towncrier/newsfragments/1610.feature
Normal file
@ -0,0 +1 @@
|
|||||||
|
Add possibility to enforce inbound STARTTLS via INBOUND_TLS_LEVEL=true
|
1
towncrier/newsfragments/1618.feature
Normal file
1
towncrier/newsfragments/1618.feature
Normal file
@ -0,0 +1 @@
|
|||||||
|
Enable OCSP stapling for the http server within nginx.
|
1
towncrier/newsfragments/1638.fix
Normal file
1
towncrier/newsfragments/1638.fix
Normal file
@ -0,0 +1 @@
|
|||||||
|
Hide the login of the user in sent emails
|
1
towncrier/newsfragments/1660.bugfix
Normal file
1
towncrier/newsfragments/1660.bugfix
Normal file
@ -0,0 +1 @@
|
|||||||
|
Don't replace nested headers (typically in attached emails)
|
1
towncrier/newsfragments/1662.feature
Normal file
1
towncrier/newsfragments/1662.feature
Normal file
@ -0,0 +1 @@
|
|||||||
|
Enable support of all hash types passlib supports.
|
1
towncrier/newsfragments/1712.misc
Normal file
1
towncrier/newsfragments/1712.misc
Normal file
@ -0,0 +1 @@
|
|||||||
|
This adds more details about the postfix-override possibilities (fixes #1628)
|
1
towncrier/newsfragments/1753.feature
Normal file
1
towncrier/newsfragments/1753.feature
Normal file
@ -0,0 +1 @@
|
|||||||
|
Switch to bcrypt_sha256, replace PASSWORD_SCHEME with CREDENTIAL_ROUNDS and dynamically update existing hashes on first login
|
1
towncrier/newsfragments/1783.misc
Normal file
1
towncrier/newsfragments/1783.misc
Normal file
@ -0,0 +1 @@
|
|||||||
|
Switch from client side sessions (cookies) to server-side sessions (Redis). This simplies the security model a lot and allows for an easier recovery should a cookie ever land in the hands of an attacker.
|
@ -2,10 +2,10 @@ ARG ARCH=""
|
|||||||
ARG QEMU=other
|
ARG QEMU=other
|
||||||
|
|
||||||
# NOTE: only add file if building for arm
|
# NOTE: only add file if building for arm
|
||||||
FROM ${ARCH}php:7.3-apache as build_arm
|
FROM ${ARCH}php:7.4-apache as build_arm
|
||||||
ONBUILD COPY --from=balenalib/rpi-alpine:3.10 /usr/bin/qemu-arm-static /usr/bin/qemu-arm-static
|
ONBUILD COPY --from=balenalib/rpi-alpine:3.10 /usr/bin/qemu-arm-static /usr/bin/qemu-arm-static
|
||||||
|
|
||||||
FROM ${ARCH}php:7.3-apache as build_other
|
FROM ${ARCH}php:7.4-apache as build_other
|
||||||
|
|
||||||
FROM build_${QEMU}
|
FROM build_${QEMU}
|
||||||
#Shared layer between rainloop and roundcube
|
#Shared layer between rainloop and roundcube
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
# NOTE: only add file if building for arm
|
# NOTE: only add file if building for arm
|
||||||
ARG ARCH=""
|
ARG ARCH=""
|
||||||
ARG QEMU=other
|
ARG QEMU=other
|
||||||
FROM ${ARCH}php:7.3-apache as build_arm
|
FROM ${ARCH}php:7.4-apache as build_arm
|
||||||
ONBUILD COPY --from=balenalib/rpi-alpine:3.10 /usr/bin/qemu-arm-static /usr/bin/qemu-arm-static
|
ONBUILD COPY --from=balenalib/rpi-alpine:3.10 /usr/bin/qemu-arm-static /usr/bin/qemu-arm-static
|
||||||
|
|
||||||
FROM ${ARCH}php:7.3-apache as build_other
|
FROM ${ARCH}php:7.4-apache as build_other
|
||||||
|
|
||||||
FROM build_${QEMU}
|
FROM build_${QEMU}
|
||||||
#Shared layer between rainloop and roundcube
|
#Shared layer between rainloop and roundcube
|
||||||
|
@ -5,7 +5,7 @@ $config = array();
|
|||||||
// Generals
|
// Generals
|
||||||
$config['db_dsnw'] = getenv('DB_DSNW');;
|
$config['db_dsnw'] = getenv('DB_DSNW');;
|
||||||
$config['temp_dir'] = '/tmp/';
|
$config['temp_dir'] = '/tmp/';
|
||||||
$config['des_key'] = getenv('SECRET_KEY');
|
$config['des_key'] = getenv('SECRET_KEY') ? getenv('SECRET_KEY') : trim(file_get_contents(getenv('SECRET_KEY_FILE')));
|
||||||
$config['cipher_method'] = 'AES-256-CBC';
|
$config['cipher_method'] = 'AES-256-CBC';
|
||||||
$config['identities_level'] = 0;
|
$config['identities_level'] = 0;
|
||||||
$config['reply_all_mode'] = 1;
|
$config['reply_all_mode'] = 1;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user