diff --git a/PULL_REQUEST_TEMPLATE.md b/PULL_REQUEST_TEMPLATE.md index 8fb3265d..fc3b6b61 100644 --- a/PULL_REQUEST_TEMPLATE.md +++ b/PULL_REQUEST_TEMPLATE.md @@ -8,7 +8,7 @@ - Mention an issue like: #001 - Auto close an issue like: closes #001 -## Prerequistes +## Prerequisites Before we can consider review and merge, please make sure the following list is done and checked. If an entry in not applicable, you can check it or remove it from the list. diff --git a/README.md b/README.md index c4354b28..4c19ad78 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ Main features include: - **Web access**, multiple Webmails and administration interface - **User features**, aliases, auto-reply, auto-forward, fetched accounts - **Admin features**, global admins, announcements, per-domain delegation, quotas -- **Security**, enforced TLS, Letsencrypt!, outgoing DKIM, anti-virus scanner +- **Security**, enforced TLS, DANE, MTA-STS, Letsencrypt!, outgoing DKIM, anti-virus scanner - **Antispam**, auto-learn, greylisting, DMARC and SPF - **Freedom**, all FOSS components, no tracker included diff --git a/core/admin/Dockerfile b/core/admin/Dockerfile index a7ca45c7..1a8ef695 100644 --- a/core/admin/Dockerfile +++ b/core/admin/Dockerfile @@ -1,35 +1,42 @@ # First stage to build assets -ARG DISTRO=alpine:3.14 +ARG DISTRO=alpine:3.14.2 ARG ARCH="" FROM ${ARCH}node:16 as assets -COPY --from=balenalib/rpi-alpine:3.14 /usr/bin/qemu-arm-static /usr/bin/qemu-arm-static COPY package.json ./ -RUN npm install +RUN set -eu \ + && npm config set update-notifier false \ + && npm install --no-fund -COPY ./webpack.config.js ./ -COPY ./assets ./assets -RUN mkdir static \ - && ./node_modules/.bin/webpack-cli +COPY webpack.config.js ./ +COPY assets ./assets +RUN set -eu \ + && sed -i 's/#007bff/#55a5d9/' node_modules/admin-lte/build/scss/_bootstrap-variables.scss \ + && for l in ca da de:de_de en:en-gb es:es_es eu fr:fr_fr he hu is it:it_it ja nb_NO:no_nb nl:nl_nl pl pt:pt_pt ru sv:sv_se zh_CN:zh; do \ + cp node_modules/datatables.net-plugins/i18n/${l#*:}.json assets/${l%:*}.json; \ + done \ + && node_modules/.bin/webpack-cli --color # Actual application FROM $DISTRO +COPY --from=balenalib/rpi-alpine:3.14 /usr/bin/qemu-arm-static /usr/bin/qemu-arm-static + # python3 shared with most images -RUN apk add --no-cache \ - python3 py3-pip git bash \ - && pip3 install --upgrade pip +RUN set -eu \ + && apk add --no-cache python3 py3-pip git bash \ + && pip3 install --upgrade pip RUN mkdir -p /app WORKDIR /app COPY requirements-prod.txt requirements.txt -RUN apk add --no-cache openssl curl postgresql-libs mariadb-connector-c \ - && apk add --no-cache --virtual build-dep \ - openssl-dev libffi-dev python3-dev build-base postgresql-dev mariadb-connector-c-dev cargo \ - && pip3 install -r requirements.txt \ - && apk del --no-cache build-dep +RUN set -eu \ + && apk add --no-cache libressl curl postgresql-libs mariadb-connector-c \ + && apk add --no-cache --virtual build-dep libressl-dev libffi-dev python3-dev build-base postgresql-dev mariadb-connector-c-dev cargo \ + && pip3 install -r requirements.txt \ + && apk del --no-cache build-dep COPY --from=assets static ./mailu/ui/static COPY --from=assets static ./mailu/sso/static diff --git a/core/admin/assets/app.css b/core/admin/assets/app.css index 8351eed8..3886b5c1 100644 --- a/core/admin/assets/app.css +++ b/core/admin/assets/app.css @@ -1,23 +1,54 @@ -.select2-search--inline .select2-search__field:focus { - border: none; +/* mailu logo */ +.mailu-logo { + opacity: .8; +} +.bg-mailu-logo { + background-color: #2980b9!important; } -.sidebar h4 { - padding-left: 5px; - padding-right: 5px; - overflow: hidden; - text-overflow: ellipsis; +/* user image */ +.div-circle { + position: relative; + width: 2.1rem; + height: 2.1rem; + opacity: .8; + background-color: white; + border-radius: 50%; +} +.div-circle > i { + display: block; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%) } -.sidebar-collapse .sidebar h4 { - display: none !important; +/* nice round preformatted configuration display */ +.pre-config { + padding: 9px; + margin: 0; + white-space: pre-wrap; + word-wrap: anywhere; + border-radius: 4px; } -.logo a { - color: #fff; +/* fieldset */ +legend { + font-size: inherit; +} +fieldset:disabled :not(legend) label { + opacity: .5; +} +fieldset:disabled .form-control:disabled { + color: gray; } -.sidebar-toggle { - padding: unset !important; +/* fix animation for icons in menu text */ +.sidebar .nav-link p i { + transition: margin-left .3s linear,opacity .3s ease,visibility .3s ease; } +/* fix select2 text color */ +.select2-container--default .select2-selection--multiple .select2-selection__choice { + color: black; +} diff --git a/core/admin/assets/app.js b/core/admin/assets/app.js index 364f8429..dc3414f2 100644 --- a/core/admin/assets/app.js +++ b/core/admin/assets/app.js @@ -1,17 +1,70 @@ require('./app.css'); -import 'admin-lte/plugins/select2/js/select2.js'; -import 'admin-lte/plugins/datatables/jquery.dataTables.js'; -import 'admin-lte/plugins/datatables-bs4/js/dataTables.bootstrap4.js'; -import 'admin-lte/plugins/datatables-responsive/js/dataTables.responsive.js'; -import 'admin-lte/plugins/datatables-responsive/js/responsive.bootstrap4.js'; +import logo from './mailu.png'; +import modules from "./*.json"; -jQuery("document").ready(function() { - jQuery(".mailselect").select2({ +// TODO: conditionally (or lazy) load select2 and dataTable +$('document').ready(function() { + + // intercept anchors with data-clicked attribute and open alternate location instead + $('[data-clicked]').click(function(e) { + e.preventDefault(); + window.location.href = $(this).data('clicked'); + }); + + // use post for language selection + $('#mailu-languages > a').click(function(e) { + e.preventDefault(); + $.post({ + url: $(this).attr('href'), + success: function() { + location.reload(); + }, + }); + }); + + // allow en-/disabling of inputs in fieldset with checkbox in legend + $('fieldset legend input[type=checkbox]').change(function() { + var fieldset = $(this).parents('fieldset'); + if (this.checked) { + fieldset.removeAttr('disabled'); + fieldset.find('input').not(this).removeAttr('disabled'); + } else { + fieldset.attr('disabled', ''); + fieldset.find('input').not(this).attr('disabled', ''); + } + }); + + // display of range input value + $('input[type=range]').each(function() { + var value_element = $('#'+this.id+'_value'); + if (value_element.length) { + value_element = $(value_element[0]); + var infinity = $(this).data('infinity'); + var step = $(this).attr('step'); + $(this).on('input', function() { + value_element.text((infinity && this.value == 0) ? '∞' : this.value/step); + }).trigger('input'); + } + }); + + // init select2 + $('.mailselect').select2({ tags: true, - tokenSeparators: [',', ' '] + tokenSeparators: [',', ' '], }); - jQuery(".dataTable").DataTable({ - "responsive": true, + + // init dataTable + var d = $(document.documentElement); + $('.dataTable').DataTable({ + 'responsive': true, + language: { + url: d.data('static') + d.attr('lang') + '.json', + }, }); + + // init clipboard.js + new ClipboardJS('.btn-clip'); + }); + diff --git a/core/admin/assets/mailu.png b/core/admin/assets/mailu.png new file mode 100644 index 00000000..e4f5021f Binary files /dev/null and b/core/admin/assets/mailu.png differ diff --git a/core/admin/assets/vendor.js b/core/admin/assets/vendor.js index fd43d918..906448cf 100644 --- a/core/admin/assets/vendor.js +++ b/core/admin/assets/vendor.js @@ -1,22 +1,24 @@ -// jQuery -import jQuery from 'jquery'; -import 'admin-lte/plugins/select2/css/select2.css'; - -// bootstrap -// import 'bootstrap/less/bootstrap.less'; -// import 'bootstrap'; - -// FontAwesome -import 'admin-lte/plugins/fontawesome-free/css/fontawesome.css'; -import 'admin-lte/plugins/fontawesome-free/css/regular.css'; -import 'admin-lte/plugins/fontawesome-free/css/solid.css'; - // AdminLTE +import 'admin-lte/plugins/jquery/jquery.min.js'; +import 'admin-lte/plugins/bootstrap/js/bootstrap.bundle.min.js'; import 'admin-lte/build/scss/adminlte.scss'; -import 'admin-lte/plugins/datatables-bs4/css/dataTables.bootstrap4.css'; -import 'admin-lte/plugins/datatables-responsive/css/responsive.bootstrap4.css'; -import 'admin-lte/plugins/bootstrap/js/bootstrap.js'; import 'admin-lte/build/js/AdminLTE.js'; -import 'admin-lte/build/js/Layout.js'; -import 'admin-lte/build/js/ControlSidebar.js'; -import 'admin-lte/build/js/PushMenu.js'; + +// fontawesome plugin +import 'admin-lte/plugins/fontawesome-free/css/all.min.css'; + +// select2 plugin +import 'admin-lte/plugins/select2/css/select2.min.css'; +import 'admin-lte/plugins/select2/js/select2.min.js'; + +// dataTables plugin +import 'admin-lte/plugins/datatables-bs4/css/dataTables.bootstrap4.min.css'; +import 'admin-lte/plugins/datatables-responsive/css/responsive.bootstrap4.min.css'; +import 'admin-lte/plugins/datatables/jquery.dataTables.min.js'; +import 'admin-lte/plugins/datatables-bs4/js/dataTables.bootstrap4.min.js'; +import 'admin-lte/plugins/datatables-responsive/js/dataTables.responsive.min.js'; +import 'admin-lte/plugins/datatables-responsive/js/responsive.bootstrap4.min.js'; + +// clipboard.js +import 'clipboard/dist/clipboard.min.js'; + diff --git a/core/admin/mailu/__init__.py b/core/admin/mailu/__init__.py index f80533fe..34761ec3 100644 --- a/core/admin/mailu/__init__.py +++ b/core/admin/mailu/__init__.py @@ -14,8 +14,7 @@ def create_app_from_config(config): app = flask.Flask(__name__) app.cli.add_command(manage.mailu) - # Bootstrap is used for basic JS and CSS loading - # TODO: remove this and use statically generated assets instead + # Bootstrap is used for error display and flash messages app.bootstrap = flask_bootstrap.Bootstrap(app) # Initialize application extensions @@ -31,6 +30,15 @@ def create_app_from_config(config): app.temp_token_key = hmac.new(bytearray(app.secret_key, 'utf-8'), bytearray('WEBMAIL_TEMP_TOKEN_KEY', 'utf-8'), 'sha256').digest() + # Initialize list of translations + config.translations = { + str(locale): locale + for locale in sorted( + utils.babel.list_translations(), + key=lambda l: l.get_language_name().title() + ) + } + # Initialize debugging tools if app.config.get("DEBUG"): debug.toolbar.init_app(app) @@ -43,8 +51,8 @@ def create_app_from_config(config): def inject_defaults(): signup_domains = models.Domain.query.filter_by(signup_enabled=True).all() return dict( - signup_domains=signup_domains, - config=app.config + signup_domains= signup_domains, + config = app.config, ) # Import views diff --git a/core/admin/mailu/configuration.py b/core/admin/mailu/configuration.py index 025a173c..1c63c5c3 100644 --- a/core/admin/mailu/configuration.py +++ b/core/admin/mailu/configuration.py @@ -35,6 +35,7 @@ DEFAULT_CONFIG = { 'WILDCARD_SENDERS': '', 'TLS_FLAVOR': 'cert', 'INBOUND_TLS_ENFORCE': False, + 'DEFER_ON_TLS_ERROR': True, 'AUTH_RATELIMIT': '1000/minute;10000/hour', 'AUTH_RATELIMIT_SUBNET': False, 'DISABLE_STATISTICS': False, @@ -57,6 +58,8 @@ DEFAULT_CONFIG = { 'WEBMAIL': 'none', 'RECAPTCHA_PUBLIC_KEY': '', 'RECAPTCHA_PRIVATE_KEY': '', + 'LOGO_URL': None, + 'LOGO_BACKGROUND': None, # Advanced settings 'LOG_LEVEL': 'WARNING', 'SESSION_KEY_BITS': 128, @@ -144,6 +147,9 @@ class ConfigManager(dict): self.config['SESSION_COOKIE_SAMESITE'] = 'Strict' self.config['SESSION_COOKIE_HTTPONLY'] = True self.config['PERMANENT_SESSION_LIFETIME'] = timedelta(hours=int(self.config['SESSION_LIFETIME'])) + hostnames = [host.strip() for host in self.config['HOSTNAMES'].split(',')] + self.config['HOSTNAMES'] = ','.join(hostnames) + self.config['HOSTNAME'] = hostnames[0] # update the app config itself app.config = self diff --git a/core/admin/mailu/internal/nginx.py b/core/admin/mailu/internal/nginx.py index 5e60cd0c..167341e2 100644 --- a/core/admin/mailu/internal/nginx.py +++ b/core/admin/mailu/internal/nginx.py @@ -71,16 +71,6 @@ def handle_authentication(headers): } # Authenticated user elif method == "plain": - server, port = get_server(headers["Auth-Protocol"], True) - # According to RFC2616 section 3.7.1 and PEP 3333, HTTP headers should - # be ASCII and are generally considered ISO8859-1. However when passing - # the password, nginx does not transcode the input UTF string, thus - # we need to manually decode. - raw_user_email = urllib.parse.unquote(headers["Auth-User"]) - user_email = raw_user_email.encode("iso8859-1").decode("utf8") - raw_password = urllib.parse.unquote(headers["Auth-Pass"]) - password = raw_password.encode("iso8859-1").decode("utf8") - ip = urllib.parse.unquote(headers["Client-Ip"]) service_port = int(urllib.parse.unquote(headers["Auth-Port"])) if service_port == 25: return { @@ -88,20 +78,33 @@ def handle_authentication(headers): "Auth-Error-Code": "502 5.5.1", "Auth-Wait": 0 } - user = models.User.query.get(user_email) - if check_credentials(user, password, ip, protocol): - return { - "Auth-Status": "OK", - "Auth-Server": server, - "Auth-Port": port - } + # According to RFC2616 section 3.7.1 and PEP 3333, HTTP headers should + # be ASCII and are generally considered ISO8859-1. However when passing + # the password, nginx does not transcode the input UTF string, thus + # we need to manually decode. + raw_user_email = urllib.parse.unquote(headers["Auth-User"]) + raw_password = urllib.parse.unquote(headers["Auth-Pass"]) + try: + user_email = raw_user_email.encode("iso8859-1").decode("utf8") + password = raw_password.encode("iso8859-1").decode("utf8") + except: + app.logger.warn(f'Received undecodable user/password from nginx: {raw_user_email!r}/{raw_password!r}') else: - status, code = get_status(protocol, "authentication") - return { - "Auth-Status": status, - "Auth-Error-Code": code, - "Auth-Wait": 0 - } + user = models.User.query.get(user_email) + ip = urllib.parse.unquote(headers["Client-Ip"]) + if check_credentials(user, password, ip, protocol): + server, port = get_server(headers["Auth-Protocol"], True) + return { + "Auth-Status": "OK", + "Auth-Server": server, + "Auth-Port": port + } + status, code = get_status(protocol, "authentication") + return { + "Auth-Status": status, + "Auth-Error-Code": code, + "Auth-Wait": 0 + } # Unexpected return {} diff --git a/core/admin/mailu/internal/views/postfix.py b/core/admin/mailu/internal/views/postfix.py index 2e7d0b9b..330fed5b 100644 --- a/core/admin/mailu/internal/views/postfix.py +++ b/core/admin/mailu/internal/views/postfix.py @@ -7,6 +7,9 @@ import idna import re import srslib +@internal.route("/postfix/dane/") +def postfix_dane_map(domain_name): + return flask.jsonify('dane-only') if utils.has_dane_record(domain_name) else flask.abort(404) @internal.route("/postfix/domain/") def postfix_mailbox_domain(domain_name): diff --git a/core/admin/mailu/manage.py b/core/admin/mailu/manage.py index 5708327e..54f4b826 100644 --- a/core/admin/mailu/manage.py +++ b/core/admin/mailu/manage.py @@ -48,44 +48,44 @@ def advertise(): @click.argument('localpart') @click.argument('domain_name') @click.argument('password') -@click.option('-m', '--mode') +@click.option('-m', '--mode', default='create', metavar='MODE', help='''\b'create' (default): create user. it's an error if user already exists +'ifmissing': only update password if user is missing +'update': create user or update password if user exists +''') @with_appcontext -def admin(localpart, domain_name, password, mode='create'): +def admin(localpart, domain_name, password, mode): """ Create an admin user - 'mode' can be: - - 'create' (default) Will try to create user and will raise an exception if present - - 'ifmissing': if user exists, nothing happens, else it will be created - - 'update': user is created or, if it exists, its password gets updated """ + + if not mode in ('create', 'update', 'ifmissing'): + raise click.ClickException(f'invalid mode: {mode!r}') + domain = models.Domain.query.get(domain_name) if not domain: domain = models.Domain(name=domain_name) db.session.add(domain) - user = None - if mode == 'ifmissing' or mode == 'update': - email = f'{localpart}@{domain_name}' - user = models.User.query.get(email) - - if user and mode == 'ifmissing': - print('user %s exists, not updating' % email) + email = f'{localpart}@{domain_name}' + if user := models.User.query.get(email): + if mode == 'ifmissing': + print(f'user {email!r} exists, not updating') return - - if not user: + elif mode == 'update': + user.set_password(password) + db.session.commit() + print("updated admin password") + else: + raise click.ClickException(f'user {email!r} exists, not created') + else: user = models.User( localpart=localpart, domain=domain, global_admin=True ) - user.set_password(password) db.session.add(user) + user.set_password(password) db.session.commit() print("created admin user") - elif mode == 'update': - user.set_password(password) - db.session.commit() - print("updated admin password") - @mailu.command() diff --git a/core/admin/mailu/models.py b/core/admin/mailu/models.py index 5760c27f..f93b158f 100644 --- a/core/admin/mailu/models.py +++ b/core/admin/mailu/models.py @@ -209,16 +209,16 @@ class Domain(Base): os.unlink(file_path) self._dkim_key_on_disk = self._dkim_key - @property + @cached_property def dns_mx(self): """ return MX record for domain """ - hostname = app.config['HOSTNAMES'].split(',', 1)[0] + hostname = app.config['HOSTNAME'] return f'{self.name}. 600 IN MX 10 {hostname}.' - @property + @cached_property def dns_spf(self): """ return SPF record for domain """ - hostname = app.config['HOSTNAMES'].split(',', 1)[0] + hostname = app.config['HOSTNAME'] return f'{self.name}. 600 IN TXT "v=spf1 mx a:{hostname} ~all"' @property @@ -226,12 +226,11 @@ class Domain(Base): """ return DKIM record for domain """ if self.dkim_key: selector = app.config['DKIM_SELECTOR'] - return ( - f'{selector}._domainkey.{self.name}. 600 IN TXT' - f'"v=DKIM1; k=rsa; p={self.dkim_publickey}"' - ) + txt = f'v=DKIM1; k=rsa; p={self.dkim_publickey}' + record = ' '.join(f'"{txt[p:p+250]}"' for p in range(0, len(txt), 250)) + return f'{selector}._domainkey.{self.name}. 600 IN TXT {record}' - @property + @cached_property def dns_dmarc(self): """ return DMARC record for domain """ if self.dkim_key: @@ -242,6 +241,34 @@ class Domain(Base): ruf = f' ruf=mailto:{ruf}@{domain};' if ruf else '' return f'_dmarc.{self.name}. 600 IN TXT "v=DMARC1; p=reject;{rua}{ruf} adkim=s; aspf=s"' + @cached_property + def dns_autoconfig(self): + """ return list of auto configuration records (RFC6186) """ + hostname = app.config['HOSTNAME'] + protocols = [ + ('submission', 587), + ('imap', 143), + ('pop3', 110), + ] + if app.config['TLS_FLAVOR'] != 'notls': + protocols.extend([ + ('imaps', 993), + ('pop3s', 995), + ]) + return list([ + f'_{proto}._tcp.{self.name}. 600 IN SRV 1 1 {port} {hostname}.' + for proto, port + in protocols + ]) + + @cached_property + def dns_tlsa(self): + """ return TLSA record for domain when using letsencrypt """ + hostname = app.config['HOSTNAME'] + if app.config['TLS_FLAVOR'] in ('letsencrypt', 'mail-letsencrypt'): + # current ISRG Root X1 (RSA 4096, O = Internet Security Research Group, CN = ISRG Root X1) @20210902 + return f'_25._tcp.{hostname}. 600 IN TLSA 2 1 1 0b9fa5a59eed715c26c1020c711b4f6ec42d58b0015e14337a39dad301c5afc3' + @property def dkim_key(self): """ return private DKIM key """ diff --git a/core/admin/mailu/translations/pl/LC_MESSAGES/messages.po b/core/admin/mailu/translations/pl/LC_MESSAGES/messages.po index cec7a4a0..664ff571 100644 --- a/core/admin/mailu/translations/pl/LC_MESSAGES/messages.po +++ b/core/admin/mailu/translations/pl/LC_MESSAGES/messages.po @@ -1,188 +1,287 @@ msgid "" msgstr "" -"Project-Id-Version: Mailu\n" +"Project-Id-Version: Mailu\n" +"POT-Creation-Date: 2021-02-05 16:34+0100\n" "PO-Revision-Date: 2020-02-17 20:23+0000\n" -"Last-Translator: NeroPcStation \n" -"Language-Team: Polish \n" +"Last-Translator: Marcin Siennicki \n" "Language: pl\n" +"Language-Team: Polish " +"\n" +"Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && " +"(n%100<10 || n%100>=20) ? 1 : 2\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" -"Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 " -"|| n%100>=20) ? 1 : 2;\n" -"X-Generator: Weblate 3.3\n" +"Generated-By: Babel 2.9.0\n" -#: mailu/ui/forms.py:32 +#: mailu/ui/forms.py:33 mailu/ui/forms.py:36 msgid "Invalid email address." msgstr "Nieprawidłowy adres e-mail." -#: mailu/ui/forms.py:36 +#: mailu/ui/forms.py:45 msgid "Confirm" msgstr "Zatwierdź" -#: mailu/ui/forms.py:40 mailu/ui/forms.py:77 +#: mailu/ui/forms.py:49 mailu/ui/forms.py:86 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/forms.py:50 mailu/ui/forms.py:87 mailu/ui/forms.py:100 +#: mailu/ui/forms.py:118 mailu/ui/forms.py:172 #: mailu/ui/templates/client.html:32 mailu/ui/templates/client.html:59 msgid "Password" msgstr "Hasło" -#: mailu/ui/forms.py:42 mailu/ui/templates/login.html:4 -#: mailu/ui/templates/sidebar.html:111 +#: mailu/ui/forms.py:51 mailu/ui/templates/login.html:4 +#: mailu/ui/templates/sidebar.html:108 msgid "Sign in" msgstr "Zaloguj" -#: mailu/ui/forms.py:46 mailu/ui/forms.py:56 +#: mailu/ui/forms.py:55 mailu/ui/forms.py:65 #: 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 "Nazwa domeny" -#: mailu/ui/forms.py:47 +#: mailu/ui/forms.py:56 msgid "Maximum user count" msgstr "Maksymalna liczba użytkowników" -#: mailu/ui/forms.py:48 +#: mailu/ui/forms.py:57 msgid "Maximum alias count" msgstr "Maksymalna liczba aliasów" -#. Needs more context - is that a verb or a noun? -#: 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:58 +msgid "Maximum user quota" +msgstr "Maksymalny przydział użytkownika" + +#: mailu/ui/forms.py:59 +msgid "Enable sign-up" +msgstr "Włącz rejestrację" + +#: mailu/ui/forms.py:60 mailu/ui/forms.py:81 mailu/ui/forms.py:93 +#: mailu/ui/forms.py:138 mailu/ui/forms.py:150 #: 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 "Komentarz" -#: 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 "Utwórz" +#: mailu/ui/forms.py:61 mailu/ui/forms.py:75 mailu/ui/forms.py:82 +#: mailu/ui/forms.py:95 mailu/ui/forms.py:142 mailu/ui/forms.py:151 +msgid "Save" +msgstr "Zapisz" -#: mailu/ui/forms.py:59 mailu/ui/forms.py:79 mailu/ui/forms.py:91 +#: mailu/ui/forms.py:66 +msgid "Initial admin" +msgstr "Początkowy administrator" + +#: mailu/ui/forms.py:67 +msgid "Admin password" +msgstr "Hasło administratora" + +#: mailu/ui/forms.py:68 mailu/ui/forms.py:88 mailu/ui/forms.py:101 msgid "Confirm password" msgstr "Potwierdź hasło" -#: mailu/ui/forms.py:80 mailu/ui/templates/user/list.html:22 +#: mailu/ui/forms.py:70 +msgid "Create" +msgstr "Utwórz" + +#: mailu/ui/forms.py:74 +msgid "Alternative name" +msgstr "Alternatywna nazwa" + +#: mailu/ui/forms.py:79 +msgid "Relayed domain name" +msgstr "Domeny przekierowywane" + +#: mailu/ui/forms.py:80 mailu/ui/templates/relay/list.html:18 +msgid "Remote host" +msgstr "Zdalny host" + +#: mailu/ui/forms.py:89 mailu/ui/templates/user/list.html:22 #: mailu/ui/templates/user/signup_domain.html:16 msgid "Quota" msgstr "Maksymalna przestrzeń na dysku" -#: mailu/ui/forms.py:81 +#: mailu/ui/forms.py:90 msgid "Allow IMAP access" msgstr "Zezwalaj na dostęp przez protokół IMAP" -#: mailu/ui/forms.py:82 +#: mailu/ui/forms.py:91 msgid "Allow POP3 access" msgstr "Zezwalaj na dostęp przez protokół POP3" -#: mailu/ui/forms.py:85 -msgid "Save" -msgstr "Zapisz" - -#: mailu/ui/forms.py:97 +#: mailu/ui/forms.py:92 mailu/ui/forms.py:108 +#: mailu/ui/templates/user/settings.html:15 msgid "Displayed name" msgstr "Nazwa wyświetlana" -#: mailu/ui/forms.py:98 +#: mailu/ui/forms.py:94 +msgid "Enabled" +msgstr "Włączone" + +#: mailu/ui/forms.py:99 +msgid "Email address" +msgstr "Adres e-mail" + +#: mailu/ui/forms.py:102 mailu/ui/templates/sidebar.html:114 +#: mailu/ui/templates/user/signup.html:4 +#: mailu/ui/templates/user/signup_domain.html:4 +msgid "Sign up" +msgstr "Utwórz konto" + +#: mailu/ui/forms.py:109 msgid "Enable spam filter" msgstr "Włącz filtr antyspamowy" -#: mailu/ui/forms.py:80 -msgid "Spam filter threshold" -msgstr "Próg filtra antyspamowego" - -#: mailu/ui/forms.py:105 -msgid "Save settings" -msgstr "Zapisz ustawienia" - #: mailu/ui/forms.py:110 -msgid "Password check" -msgstr "" +msgid "Spam filter tolerance" +msgstr "Tolerancja filtra spamu" -#: mailu/ui/forms.py:111 mailu/ui/templates/sidebar.html:16 -msgid "Update password" -msgstr "Zaktualizuj hasło" - -#: mailu/ui/forms.py:100 +#: mailu/ui/forms.py:111 msgid "Enable forwarding" msgstr "Włącz przekierowanie poczty" -#: mailu/ui/forms.py:103 mailu/ui/forms.py:139 +#: mailu/ui/forms.py:112 +msgid "Keep a copy of the emails" +msgstr "Przechowuj kopię wiadomości" + +#: mailu/ui/forms.py:113 mailu/ui/forms.py:149 #: mailu/ui/templates/alias/list.html:20 msgid "Destination" msgstr "Adres docelowy" -#: mailu/ui/forms.py:120 -msgid "Update" -msgstr "Aktualizuj" +#: mailu/ui/forms.py:114 +msgid "Save settings" +msgstr "Zapisz ustawienia" -#: mailu/ui/forms.py:115 +#: mailu/ui/forms.py:119 +msgid "Password check" +msgstr "Powtórz hasło" + +#: mailu/ui/forms.py:120 mailu/ui/templates/sidebar.html:16 +msgid "Update password" +msgstr "Zaktualizuj hasło" + +#: mailu/ui/forms.py:124 msgid "Enable automatic reply" msgstr "Włącz automatyczną odpowiedź" -#: mailu/ui/forms.py:116 +#: mailu/ui/forms.py:125 msgid "Reply subject" msgstr "Temat odpowiedzi" -#: mailu/ui/forms.py:117 +#: mailu/ui/forms.py:126 msgid "Reply body" msgstr "Treść odpowiedzi" -#: mailu/ui/forms.py:136 +#: mailu/ui/forms.py:128 +#, fuzzy +msgid "Start of vacation" +msgstr "Rozpoczęcie nieobecności" + +#: mailu/ui/forms.py:129 +msgid "End of vacation" +msgstr "Koniec nieobecności" + +#: mailu/ui/forms.py:130 +msgid "Update" +msgstr "Aktualizuj" + +#: mailu/ui/forms.py:135 +msgid "Your token (write it down, as it will never be displayed again)" +msgstr "Twój token (zapisz go, ponieważ nigdy więcej nie będzie wyświetlany)" + +#: mailu/ui/forms.py:140 mailu/ui/templates/token/list.html:20 +msgid "Authorized IP" +msgstr "Autoryzowany adres IP" + +#: mailu/ui/forms.py:146 msgid "Alias" msgstr "Alias" -#: mailu/ui/forms.py:138 +#: mailu/ui/forms.py:148 msgid "Use SQL LIKE Syntax (e.g. for catch-all aliases)" msgstr "Używaj składni SQL LIKE (np. do adresów catch-all)" -#: mailu/ui/forms.py:145 +#: mailu/ui/forms.py:155 msgid "Admin email" msgstr "E-mail administratora" -#: mailu/ui/forms.py:146 mailu/ui/forms.py:151 mailu/ui/forms.py:164 +#: mailu/ui/forms.py:156 mailu/ui/forms.py:161 mailu/ui/forms.py:174 msgid "Submit" msgstr "Prześlij" -#: mailu/ui/forms.py:150 +#: mailu/ui/forms.py:160 msgid "Manager email" msgstr "E-mail menedżera" -#: mailu/ui/forms.py:155 +#: mailu/ui/forms.py:165 msgid "Protocol" msgstr "Protokół" -#: mailu/ui/forms.py:158 +#: mailu/ui/forms.py:168 msgid "Hostname or IP" msgstr "Nazwa hosta lub adres IP" -#: mailu/ui/forms.py:159 mailu/ui/templates/client.html:20 +#: mailu/ui/forms.py:169 mailu/ui/templates/client.html:20 #: mailu/ui/templates/client.html:47 msgid "TCP port" msgstr "Port TCP" -#: mailu/ui/forms.py:160 +#: mailu/ui/forms.py:170 msgid "Enable TLS" msgstr "Włącz TLS" -#: mailu/ui/forms.py:161 mailu/ui/templates/client.html:28 +#: mailu/ui/forms.py:171 mailu/ui/templates/client.html:28 #: mailu/ui/templates/client.html:55 mailu/ui/templates/fetch/list.html:20 msgid "Username" msgstr "Nazwa użytkownika" +#: mailu/ui/forms.py:173 +msgid "Keep emails on the server" +msgstr "Przechowuj wiadomości na serwerze" + +#: mailu/ui/forms.py:178 +msgid "Announcement subject" +msgstr "Temat ogłoszenia" + +#: mailu/ui/forms.py:180 +msgid "Announcement body" +msgstr "Treść ogłoszenia" + +#: mailu/ui/forms.py:182 +msgid "Send" +msgstr "Wyślij" + +#: mailu/ui/templates/announcement.html:4 +msgid "Public announcement" +msgstr "Publiczne ogłoszenie" + +#: mailu/ui/templates/client.html:4 mailu/ui/templates/sidebar.html:79 +msgid "Client setup" +msgstr "Konfiguracja klienta" + +#: mailu/ui/templates/client.html:16 mailu/ui/templates/client.html:43 +msgid "Mail protocol" +msgstr "Protokół poczty" + +#: mailu/ui/templates/client.html:24 mailu/ui/templates/client.html:51 +msgid "Server name" +msgstr "Nazwa serwera" + #: mailu/ui/templates/confirm.html:4 msgid "Confirm action" msgstr "Potwierdź wykonanie czynności" #: mailu/ui/templates/confirm.html:13 +#, python-format msgid "You are about to %(action)s. Please confirm your action." -msgstr "Zamierzasz wykonać następujące czynności: %(action)s. Potwierdź wykonanie czynności." +msgstr "" +"Zamierzasz wykonać następujące czynności: %(action)s. Potwierdź wykonanie" +" czynności." #: mailu/ui/templates/docker-error.html:4 msgid "Docker error" @@ -192,54 +291,19 @@ msgstr "Błąd Dockera" msgid "An error occurred while talking to the Docker server." msgstr "Wystąpił błąd komunikacji z serwerem Dockera." -#: mailu/admin/templates/login.html:6 -msgid "Your account" -msgstr "Twoje konto" - #: mailu/ui/templates/login.html:8 msgid "to access the administration tools" msgstr "aby uzyskać dostęp do narzędzi administracyjnych" -#: mailu/ui/templates/services.html:4 mailu/ui/templates/sidebar.html:39 -msgid "Services status" -msgstr "Status usług" - -#: mailu/ui/templates/services.html:10 -msgid "Service" -msgstr "Usługa" - -#: mailu/ui/templates/fetch/list.html:23 mailu/ui/templates/services.html:11 -msgid "Status" -msgstr "Status" - -#: mailu/ui/templates/services.html:12 -msgid "PID" -msgstr "PID" - -#: mailu/ui/templates/services.html:13 -msgid "Image" -msgstr "Obraz" - -#: mailu/ui/templates/services.html:14 -msgid "Started" -msgstr "" - -#: mailu/ui/templates/services.html:15 -msgid "Last update" -msgstr "Ostatnia aktualizacja" - #: mailu/ui/templates/sidebar.html:8 +#, fuzzy msgid "My account" -msgstr "Moje konto" +msgstr "Dodaj konto" #: mailu/ui/templates/sidebar.html:11 mailu/ui/templates/user/list.html:34 msgid "Settings" msgstr "Ustawienia" -#: mailu/ui/templates/user/settings.html:22 -msgid "Auto-forward" -msgstr "Automatyczne przekierowanie" - #: mailu/ui/templates/sidebar.html:21 mailu/ui/templates/user/list.html:35 msgid "Auto-reply" msgstr "Automatyczna odpowiedź" @@ -247,28 +311,60 @@ msgstr "Automatyczna odpowiedź" #: mailu/ui/templates/fetch/list.html:4 mailu/ui/templates/sidebar.html:26 #: mailu/ui/templates/user/list.html:36 msgid "Fetched accounts" -msgstr "" +msgstr "Zewnętrzne konta e-mail" -#: mailu/ui/templates/sidebar.html:105 -msgid "Sign out" -msgstr "Wyloguj" +#: mailu/ui/templates/sidebar.html:31 mailu/ui/templates/token/list.html:4 +msgid "Authentication tokens" +msgstr "Tokeny uwierzytelnienia" -#: mailu/ui/templates/sidebar.html:35 +#: mailu/ui/templates/sidebar.html:36 msgid "Administration" msgstr "Administracja" -#: mailu/ui/templates/sidebar.html:49 +#: mailu/ui/templates/sidebar.html:41 +msgid "Announcement" +msgstr "Ogłoszenie" + +#: mailu/ui/templates/sidebar.html:46 msgid "Administrators" msgstr "Administratorzy" -#: mailu/ui/templates/sidebar.html:66 +#: mailu/ui/templates/sidebar.html:51 +msgid "Relayed domains" +msgstr "Domeny przekierowywane" + +#: mailu/ui/templates/sidebar.html:56 mailu/ui/templates/user/settings.html:19 +msgid "Antispam" +msgstr "Filtr antyspamowy" + +#: mailu/ui/templates/sidebar.html:63 msgid "Mail domains" msgstr "Domeny pocztowe" -#: mailu/ui/templates/sidebar.html:92 +#: mailu/ui/templates/sidebar.html:69 +msgid "Go to" +msgstr "Przejdź do" + +#: mailu/ui/templates/sidebar.html:73 +msgid "Webmail" +msgstr "Twoja poczta" + +#: mailu/ui/templates/sidebar.html:84 +msgid "Website" +msgstr "Strona internetowa" + +#: mailu/ui/templates/sidebar.html:89 msgid "Help" msgstr "Pomoc" +#: mailu/ui/templates/domain/signup.html:4 mailu/ui/templates/sidebar.html:95 +msgid "Register a domain" +msgstr "Zarejestruj domenę" + +#: mailu/ui/templates/sidebar.html:102 +msgid "Sign out" +msgstr "Wyloguj" + #: mailu/ui/templates/working.html:4 msgid "We are still working on this feature!" msgstr "Nadal pracujemy nad tą funkcją!" @@ -344,6 +440,22 @@ msgstr "Ostatnia edycja" msgid "Edit" msgstr "Edytuj" +#: mailu/ui/templates/alternative/create.html:4 +msgid "Create alternative domain" +msgstr "Utwórz alternatywną domenę" + +#: mailu/ui/templates/alternative/list.html:4 +msgid "Alternative domain list" +msgstr "Alternatywna lista domen" + +#: mailu/ui/templates/alternative/list.html:12 +msgid "Add alternative" +msgstr "Dodaj alternatywę" + +#: mailu/ui/templates/alternative/list.html:19 +msgid "Name" +msgstr "Nazwa" + #: mailu/ui/templates/domain/create.html:4 #: mailu/ui/templates/domain/list.html:9 msgid "New domain" @@ -357,6 +469,10 @@ msgstr "Szczegóły domeny" msgid "Regenerate keys" msgstr "Wygeneruj ponownie klucze" +#: mailu/ui/templates/domain/details.html:17 +msgid "Generate keys" +msgstr "Wygeneruj klucze" + #: mailu/ui/templates/domain/details.html:31 msgid "DNS MX entry" msgstr "Wpis MX DNS" @@ -365,15 +481,15 @@ msgstr "Wpis MX DNS" msgid "DNS SPF entries" msgstr "Wpisy SPF DNS" -#: mailu/ui/templates/domain/details.html:42 +#: mailu/ui/templates/domain/details.html:41 msgid "DKIM public key" msgstr "Publiczny klucz DKIM" -#: mailu/ui/templates/domain/details.html:46 +#: mailu/ui/templates/domain/details.html:45 msgid "DNS DKIM entry" msgstr "Wpis DKIM DNS" -#: mailu/ui/templates/domain/details.html:50 +#: mailu/ui/templates/domain/details.html:49 msgid "DNS DMARC entry" msgstr "Wpis DMARC DNS" @@ -413,13 +529,42 @@ msgstr "Aliasy" msgid "Managers" msgstr "Menedżerowie" +#: mailu/ui/templates/domain/list.html:39 +msgid "Alternatives" +msgstr "Alternatywy" + +#: 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 MX points to this server" +msgstr "" +"Aby zarejestrować nową domenę, musisz najpierw skonfigurować strefę " +"domeny, aby domena MX wskazywała na ten serwer" + +#: mailu/ui/templates/domain/signup.html:18 +msgid "" +"If you do not know how to setup an MX record for your DNS " +"zone,\n" +" please contact your DNS provider or administrator. Also, please wait " +"a\n" +" couple minutes after the MX is set so the local server " +"cache\n" +" expires." +msgstr "" +"Jeśli nie wiesz, jak skonfigurować rekord MX dla swojej " +"strefy DNS,\n" +"skontaktuj się z dostawcą DNS lub administratorem. Proszę również " +"poczekać\n" +"kilka minut po ustawieniu MX , żeby pamięć podręczna " +"serwera lokalnego wygasła." + #: mailu/ui/templates/fetch/create.html:4 msgid "Add a fetched account" -msgstr "" +msgstr "Dodaj zewnętrzne konto pocztowe" #: mailu/ui/templates/fetch/edit.html:4 msgid "Update a fetched account" -msgstr "" +msgstr "Zaktualizuj konto" #: mailu/ui/templates/fetch/list.html:12 msgid "Add an account" @@ -427,12 +572,28 @@ msgstr "Dodaj konto" #: mailu/ui/templates/fetch/list.html:19 msgid "Endpoint" -msgstr "" +msgstr "Serwer" + +#: mailu/ui/templates/fetch/list.html:21 +msgid "Keep emails" +msgstr "Przechowuj wiadomości" #: mailu/ui/templates/fetch/list.html:22 msgid "Last check" msgstr "Ostatnie sprawdzenie" +#: mailu/ui/templates/fetch/list.html:23 +msgid "Status" +msgstr "Stan" + +#: mailu/ui/templates/fetch/list.html:35 +msgid "yes" +msgstr "Tak" + +#: mailu/ui/templates/fetch/list.html:35 +msgid "no" +msgstr "Nie" + #: mailu/ui/templates/manager/create.html:4 msgid "Add a manager" msgstr "Dodaj menedżera" @@ -445,34 +606,43 @@ msgstr "Lista menedżerów" msgid "Add manager" msgstr "Dodaj menedżera" -#: mailu/ui/forms.py:168 -msgid "Announcement subject" -msgstr "Temat ogłoszenia" +#: mailu/ui/templates/relay/create.html:4 +msgid "New relay domain" +msgstr "Nowa domena do przekierowania" -#: mailu/ui/forms.py:170 -msgid "Announcement body" -msgstr "Treść ogłoszenia" +#: mailu/ui/templates/relay/edit.html:4 +#, fuzzy +msgid "Edit relayd domain" +msgstr "Edycja domeny" -#: mailu/ui/forms.py:172 -msgid "Send" -msgstr "Wyślij" +#: mailu/ui/templates/relay/list.html:4 +msgid "Relayed domain list" +msgstr "Lista domen przekierowywanych" -#: mailu/ui/templates/announcement.html:4 -msgid "Public announcement" -msgstr "Publiczne ogłoszenie" +#: mailu/ui/templates/relay/list.html:9 +msgid "New relayed domain" +msgstr "Nowa domena do przekierowania" -#: mailu/ui/templates/announcement.html:8 -msgid "from" -msgstr "od" +#: mailu/ui/templates/token/create.html:4 +msgid "Create an authentication token" +msgstr "Utwórz token uwierzytelniający" -#: mailu/ui/templates/sidebar.html:44 -msgid "Announcement" -msgstr "Ogłoszenie" +#: mailu/ui/templates/token/list.html:12 +msgid "New token" +msgstr "Nowy token" #: mailu/ui/templates/user/create.html:4 msgid "New user" msgstr "Nowy użytkownik" +#: mailu/ui/templates/user/create.html:15 +msgid "General" +msgstr "Ogólne" + +#: mailu/ui/templates/user/create.html:23 +msgid "Features and quotas" +msgstr "Funkcje i limity" + #: mailu/ui/templates/user/edit.html:4 msgid "Edit user" msgstr "Edytuj użytkownika" @@ -505,202 +675,9 @@ msgstr "Zmiana hasła" msgid "Automatic reply" msgstr "Automatyczna odpowiedź" -#: mailu/ui/forms.py:49 -msgid "Maximum user quota" -msgstr "Maksymalny przydział użytkownika" - -#: mailu/ui/forms.py:101 -msgid "Keep a copy of the emails" -msgstr "Przechowuj kopię wiadomości" - -#: mailu/ui/forms.py:163 -msgid "Keep emails on the server" -msgstr "Przechowuj wiadomości na serwerze" - -#: mailu/ui/templates/fetch/list.html:21 -msgid "Keep emails" -msgstr "Przechowuj wiadomości" - -#: mailu/ui/templates/fetch/list.html:35 -msgid "yes" -msgstr "Tak" - -#: mailu/ui/templates/fetch/list.html:35 -msgid "no" -msgstr "Nie" - -#: mailu/ui/forms.py:65 -msgid "Alternative name" -msgstr "Alternatywna nazwa" - -#: mailu/ui/forms.py:70 -msgid "Relayed domain name" -msgstr "" - -#: mailu/ui/forms.py:71 mailu/ui/templates/relay/list.html:18 -msgid "Remote host" -msgstr "Zdalny host" - -#: mailu/ui/templates/sidebar.html:54 -msgid "Relayed domains" -msgstr "" - -#: mailu/ui/templates/alternative/create.html:4 -msgid "Create alternative domain" -msgstr "Utwórz alternatywną domenę" - -#: mailu/ui/templates/alternative/list.html:4 -msgid "Alternative domain list" -msgstr "Alternatywna lista domen" - -#: mailu/ui/templates/alternative/list.html:12 -msgid "Add alternative" -msgstr "Dodaj alternatywę" - -#: mailu/ui/templates/alternative/list.html:19 -msgid "Name" -msgstr "Nazwa" - -#: mailu/ui/templates/domain/list.html:39 -msgid "Alternatives" -msgstr "Alternatywy" - -#: mailu/ui/templates/relay/create.html:4 -msgid "New relay domain" -msgstr "" - -#: mailu/ui/templates/relay/edit.html:4 -msgid "Edit relayd domain" -msgstr "" - -#: mailu/ui/templates/relay/list.html:4 -msgid "Relayed domain list" -msgstr "" - -#: mailu/ui/templates/relay/list.html:9 -msgid "New relayed domain" -msgstr "" - -#: mailu/ui/forms.py:125 -msgid "Your token (write it down, as it will never be displayed again)" -msgstr "Twój token (zapisz go, ponieważ nigdy więcej nie będzie wyświetlany)" - -#: mailu/ui/forms.py:130 mailu/ui/templates/token/list.html:20 -msgid "Authorized IP" -msgstr "Autoryzowany adres IP" - -#: mailu/ui/templates/sidebar.html:31 mailu/ui/templates/token/list.html:4 -msgid "Authentication tokens" -msgstr "Tokeny uwierzytelnienia" - -#: mailu/ui/templates/sidebar.html:72 -msgid "Go to" -msgstr "Przejdź do" - -#: mailu/ui/templates/sidebar.html:76 -msgid "Webmail" -msgstr "" - -#: mailu/ui/templates/sidebar.html:87 -msgid "Website" -msgstr "Strona internetowa" - -#: mailu/ui/templates/token/create.html:4 -msgid "Create an authentication token" -msgstr "Utwórz token uwierzytelniający" - -#: mailu/ui/templates/token/list.html:12 -msgid "New token" -msgstr "Nowy token" - -#: 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/settings.html:14 -msgid "General settings" -msgstr "Ustawienia ogólne" - -#: mailu/ui/templates/sidebar.html:59 mailu/ui/templates/user/settings.html:15 -msgid "Antispam" -msgstr "Filtr antyspamowy" - -#: mailu/ui/forms.py:99 -msgid "Spam filter tolerance" -msgstr "Tolerancja filtra spamu" - -#: mailu/ui/forms.py:50 -msgid "Enable sign-up" -msgstr "Włącz rejestrację" - -#: mailu/ui/forms.py:57 -msgid "Initial admin" -msgstr "Początkowy administrator" - -#: mailu/ui/forms.py:58 -msgid "Admin password" -msgstr "hasło administratora" - -#: mailu/ui/forms.py:84 -msgid "Enabled" -msgstr "Włączone" - -#: mailu/ui/forms.py:89 -msgid "Email address" -msgstr "Adres e-mail" - -#: 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 "" - -#: mailu/ui/forms.py:119 -msgid "End of vacation" -msgstr "Koniec wakacji" - -#: mailu/ui/templates/client.html:4 mailu/ui/templates/sidebar.html:82 -msgid "Client setup" -msgstr "Konfiguracja klienta" - -#: mailu/ui/templates/client.html:16 mailu/ui/templates/client.html:43 -msgid "Mail protocol" -msgstr "Protokół poczty" - -#: mailu/ui/templates/client.html:24 mailu/ui/templates/client.html:51 -msgid "Server name" -msgstr "Nazwa serwera" - -#: mailu/ui/templates/domain/signup.html:4 mailu/ui/templates/sidebar.html:98 -msgid "Register a domain" -msgstr "Zarejestruj domenę" - -#: mailu/ui/templates/domain/details.html:17 -msgid "Generate keys" -msgstr "Wygeneruj klucze" - -#: 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 MX points to this server" -msgstr "" -"Aby zarejestrować nową domenę, musisz najpierw skonfigurować strefę domeny, " -"aby domena MX wskazywała na ten serwer" - -#: mailu/ui/templates/domain/signup.html:18 -msgid "If you do not know how to setup an MX record for your DNS zone,\n" -" please contact your DNS provider or administrator. Also, please wait a\n" -" couple minutes after the MX is set so the local server cache\n" -" expires." -msgstr "" -"Jeśli nie wiesz, jak skonfigurować rekord MX dla swojej " -"strefy DNS,\n" -"skontaktuj się z dostawcą DNS lub administratorem. Proszę również poczekać\n" -"kilka minut po ustawieniu MX , żeby pamięć podręczna serwera " -"lokalnego wygasła." +#: mailu/ui/templates/user/settings.html:26 +msgid "Auto-forward" +msgstr "Automatyczne przekierowanie" #: mailu/ui/templates/user/signup_domain.html:8 msgid "pick a domain for the new account" @@ -713,3 +690,40 @@ msgstr "Domena" #: mailu/ui/templates/user/signup_domain.html:15 msgid "Available slots" msgstr "Dostępne miejsca" + +#~ msgid "Spam filter threshold" +#~ msgstr "Próg filtra antyspamowego" + +#~ msgid "Your account" +#~ msgstr "Twoje konto" + +#~ msgid "Services status" +#~ msgstr "Status usług" + +#~ msgid "Service" +#~ msgstr "Usługa" + +#~ msgid "Status" +#~ msgstr "Status" + +#~ msgid "PID" +#~ msgstr "PID" + +#~ msgid "Image" +#~ msgstr "Obraz" + +#~ msgid "Started" +#~ msgstr "Uruchomione" + +#~ msgid "Last update" +#~ msgstr "Ostatnia aktualizacja" + +#~ msgid "My account" +#~ msgstr "Moje konto" + +#~ msgid "from" +#~ msgstr "od" + +#~ msgid "General settings" +#~ msgstr "Ustawienia ogólne" + diff --git a/core/admin/mailu/ui/forms.py b/core/admin/mailu/ui/forms.py index 640408e3..24d6f899 100644 --- a/core/admin/mailu/ui/forms.py +++ b/core/admin/mailu/ui/forms.py @@ -79,7 +79,7 @@ class UserForm(flask_wtf.FlaskForm): localpart = fields.StringField(_('E-mail'), [validators.DataRequired(), validators.Regexp(LOCALPART_REGEX)]) pw = fields.PasswordField(_('Password')) pw2 = fields.PasswordField(_('Confirm password'), [validators.EqualTo('pw')]) - quota_bytes = fields_.IntegerSliderField(_('Quota'), default=1000000000) + quota_bytes = fields_.IntegerSliderField(_('Quota'), default=10**9) enable_imap = fields.BooleanField(_('Allow IMAP access'), default=True) enable_pop = fields.BooleanField(_('Allow POP3 access'), default=True) displayed_name = fields.StringField(_('Displayed name')) diff --git a/core/admin/mailu/ui/templates/admin/create.html b/core/admin/mailu/ui/templates/admin/create.html index 6c2413bc..071cb77f 100644 --- a/core/admin/mailu/ui/templates/admin/create.html +++ b/core/admin/mailu/ui/templates/admin/create.html @@ -1,15 +1,15 @@ -{% extends "base.html" %} +{%- extends "base.html" %} -{% block title %} +{%- block title %} {% trans %}Add a global administrator{% endtrans %} -{% endblock %} +{%- endblock %} -{% block content %} -{% call macros.card() %} +{%- block content %} +{%- call macros.card() %}
{{ form.hidden_tag() }} {{ macros.form_field(form.admin, class_='mailselect') }} {{ macros.form_field(form.submit) }}
-{% endcall %} -{% endblock %} +{%- endcall %} +{%- endblock %} diff --git a/core/admin/mailu/ui/templates/admin/list.html b/core/admin/mailu/ui/templates/admin/list.html index f2f5d229..84d954a0 100644 --- a/core/admin/mailu/ui/templates/admin/list.html +++ b/core/admin/mailu/ui/templates/admin/list.html @@ -1,17 +1,17 @@ -{% extends "base.html" %} +{%- extends "base.html" %} -{% block title %} +{%- block title %} {% trans %}Global administrators{% endtrans %} -{% endblock %} +{%- endblock %} -{% block main_action %} +{%- block main_action %} {% trans %}Add administrator{% endtrans %} -{% endblock %} +{%- endblock %} -{% block content %} -{% call macros.table() %} +{%- block content %} +{%- call macros.table() %} {% trans %}Actions{% endtrans %} @@ -19,14 +19,14 @@ - {% for admin in admins %} + {%- for admin in admins %} {{ admin }} - {% endfor %} + {%- endfor %} -{% endcall %} -{% endblock %} +{%- endcall %} +{%- endblock %} diff --git a/core/admin/mailu/ui/templates/alias/create.html b/core/admin/mailu/ui/templates/alias/create.html index 2079d191..ce9f8167 100644 --- a/core/admin/mailu/ui/templates/alias/create.html +++ b/core/admin/mailu/ui/templates/alias/create.html @@ -1,15 +1,15 @@ -{% extends "base.html" %} +{%- extends "base.html" %} -{% block title %} +{%- block title %} {% trans %}Create alias{% endtrans %} -{% endblock %} +{%- endblock %} -{% block subtitle %} +{%- block subtitle %} {{ domain }} -{% endblock %} +{%- endblock %} -{% block content %} -{% call macros.card() %} +{%- block content %} +{%- call macros.card() %}
{{ form.hidden_tag() }} {{ macros.form_field(form.localpart, append='@'+domain.name+'') }} @@ -18,5 +18,5 @@ {{ macros.form_field(form.comment) }} {{ macros.form_field(form.submit) }}
-{% endcall %} -{% endblock %} +{%- endcall %} +{%- endblock %} diff --git a/core/admin/mailu/ui/templates/alias/edit.html b/core/admin/mailu/ui/templates/alias/edit.html index b28ea170..4dc13cce 100644 --- a/core/admin/mailu/ui/templates/alias/edit.html +++ b/core/admin/mailu/ui/templates/alias/edit.html @@ -1,9 +1,9 @@ -{% extends "alias/create.html" %} +{%- extends "alias/create.html" %} -{% block title %} +{%- block title %} {% trans %}Edit alias{% endtrans %} -{% endblock %} +{%- endblock %} -{% block subtitle %} +{%- block subtitle %} {{ alias }} -{% endblock %} +{%- endblock %} diff --git a/core/admin/mailu/ui/templates/alias/list.html b/core/admin/mailu/ui/templates/alias/list.html index e8ddc862..0b784d52 100644 --- a/core/admin/mailu/ui/templates/alias/list.html +++ b/core/admin/mailu/ui/templates/alias/list.html @@ -1,19 +1,19 @@ -{% extends "base.html" %} +{%- extends "base.html" %} -{% block title %} +{%- block title %} {% trans %}Alias list{% endtrans %} -{% endblock %} +{%- endblock %} -{% block subtitle %} +{%- block subtitle %} {{ domain.name }} -{% endblock %} +{%- endblock %} -{% block main_action %} +{%- block main_action %} {% trans %}Add alias{% endtrans %} -{% endblock %} +{%- endblock %} -{% block content %} -{% call macros.table() %} +{%- block content %} +{%- call macros.table() %} {% trans %}Actions{% endtrans %} @@ -25,7 +25,7 @@ - {% for alias in domain.aliases %} + {%- for alias in domain.aliases %}   @@ -37,7 +37,7 @@ {{ alias.created_at }} {{ alias.updated_at or '' }} - {% endfor %} + {%- endfor %} -{% endcall %} -{% endblock %} +{%- endcall %} +{%- endblock %} diff --git a/core/admin/mailu/ui/templates/alternative/create.html b/core/admin/mailu/ui/templates/alternative/create.html index 75461c67..f10cb718 100644 --- a/core/admin/mailu/ui/templates/alternative/create.html +++ b/core/admin/mailu/ui/templates/alternative/create.html @@ -1,9 +1,9 @@ -{% extends "form.html" %} +{%- extends "form.html" %} -{% block title %} +{%- block title %} {% trans %}Create alternative domain{% endtrans %} -{% endblock %} +{%- endblock %} -{% block subtitle %} +{%- block subtitle %} {{ domain }} -{% endblock %} +{%- endblock %} diff --git a/core/admin/mailu/ui/templates/alternative/list.html b/core/admin/mailu/ui/templates/alternative/list.html index f123eb9f..b56cd751 100644 --- a/core/admin/mailu/ui/templates/alternative/list.html +++ b/core/admin/mailu/ui/templates/alternative/list.html @@ -1,19 +1,19 @@ -{% extends "base.html" %} +{%- extends "base.html" %} -{% block title %} +{%- block title %} {% trans %}Alternative domain list{% endtrans %} -{% endblock %} +{%- endblock %} -{% block subtitle %} +{%- block subtitle %} {{ domain.name }} -{% endblock %} +{%- endblock %} -{% block main_action %} +{%- block main_action %} {% trans %}Add alternative{% endtrans %} -{% endblock %} +{%- endblock %} -{% block content %} -{% call macros.table() %} +{%- block content %} +{%- call macros.table() %} {% trans %}Actions{% endtrans %} @@ -22,7 +22,7 @@ - {% for alternative in domain.alternatives %} + {%- for alternative in domain.alternatives %} @@ -30,7 +30,7 @@ {{ alternative }} {{ alternative.created_at }} - {% endfor %} + {%- endfor %} -{% endcall %} -{% endblock %} +{%- endcall %} +{%- endblock %} diff --git a/core/admin/mailu/ui/templates/announcement.html b/core/admin/mailu/ui/templates/announcement.html index acdbde1a..ed7fe772 100644 --- a/core/admin/mailu/ui/templates/announcement.html +++ b/core/admin/mailu/ui/templates/announcement.html @@ -1,16 +1,16 @@ -{% extends "base.html" %} +{%- extends "base.html" %} -{% block title %} +{%- block title %} {% trans %}Public announcement{% endtrans %} -{% endblock %} +{%- endblock %} -{% block content %} -{% call macros.card() %} +{%- block content %} +{%- call macros.card() %}
{{ form.hidden_tag() }} {{ macros.form_field(form.announcement_subject) }} {{ macros.form_field(form.announcement_body, rows=10) }} {{ macros.form_field(form.submit) }}
-{% endcall %} -{% endblock %} +{%- endcall %} +{%- endblock %} diff --git a/core/admin/mailu/ui/templates/antispam.html b/core/admin/mailu/ui/templates/antispam.html new file mode 100644 index 00000000..0b2713b9 --- /dev/null +++ b/core/admin/mailu/ui/templates/antispam.html @@ -0,0 +1,15 @@ +{%- extends "base.html" %} + +{%- block title %} +{% trans %}Antispam{% endtrans %} +{%- endblock %} + +{%- block subtitle %} +{% trans %}RSPAMD status page{% endtrans %} +{%- endblock %} + +{%- block content %} +
+ +
+{%- endblock %} diff --git a/core/admin/mailu/ui/templates/base.html b/core/admin/mailu/ui/templates/base.html index 89695e50..fc27d12b 100644 --- a/core/admin/mailu/ui/templates/base.html +++ b/core/admin/mailu/ui/templates/base.html @@ -1,65 +1,83 @@ -{% import "macros.html" as macros %} -{% import "bootstrap/utils.html" as utils %} +{%- import "macros.html" as macros %} +{%- import "bootstrap/utils.html" as utils %} - + - + + + + + Mailu-Admin | {{ config["SITENAME"] }} - Mailu-Admin - {{ config["SITENAME"] }}
-