Compare commits

..
Author SHA1 Message Date
milkmakerandMatjaž Tekavec 7c9f374998 [Web] Updated lang.si-si.json
Co-authored-by: Matjaž Tekavec <matjaz@moj-svet.si>
2026-11-12 18:36:50 +00:00
FreddleSpl0it 1a53d8f4c2 Merge pull request #7642 from mailcow/fix/update-self-restart
[Update] Restart update.sh automatically after it updated itself
2026-11-10 19:52:17 +01:00
FreddleSpl0it 18bc6dc98d [Update] Restart update.sh automatically after it updated itself 2026-11-10 19:50:48 +01:00
FreddleSpl0it 9825c8d290 Merge pull request #7641 from mailcow/fix/7436
[Update.sh] Keep ENABLE_IPV6 as set, do not disable IPv6 on hosts with a public IPv6 address
2026-11-10 17:09:56 +01:00
FreddleSpl0it dc880d861c [Update] Keep ENABLE_IPV6 as set, do not disable IPv6 on hosts with a public IPv6 address 2026-11-10 17:04:50 +01:00
FreddleSpl0it a03fd8aaad Merge pull request #7500 from philippderdiedas/fix/update-sh-masquerade-bridge
[Update] Fix update.sh deleting mailcow's own MASQUERADE rule
2026-11-10 15:39:48 +01:00
FreddleSpl0it e3a90718c2 Merge pull request #7516 from wbilalz400/fix/webauthn-forced-enrollment-empty-credential
[Web] Fix forced WebAuthn TFA enrollment storing an empty credential
2026-11-10 15:21:30 +01:00
FreddleSpl0it 54a85ba439 Merge pull request #7540 from pReya/fix/table-ui-polish
[Web] Table UI polish (icon centering, tag heights, sort headers)
2026-11-10 14:07:39 +01:00
FreddleSpl0it 4ced82d554 Merge pull request #7548 from junkerderprovinz/fix/idp-ignore-ssl-error-key
[Web] Fix ignore_ssl_error key in identity provider settings
2026-11-10 13:55:15 +01:00
FreddleSpl0it f83e02b740 Merge pull request #7640 from mailcow/fix/7562
[Rspamd] Remove the URLhaus and MalwareBazaar maps retired by abuse.ch
2026-11-10 13:51:45 +01:00
Junker der Provinzanddiko 5705a48724 [Web] Fix ignore_ssl_error key in identity provider settings
The edit action stores the setting as ignore_ssl_error, but the get
action cast and defaulted ignore_ssl_errors. The stored value was
returned as a string and LDAP setups got an extra ignore_ssl_errors
field that was always false.

Co-authored-by: diko <108140792+admins-little-helper@users.noreply.github.com>
2026-10-24 20:05:10 +02:00
Moritz Stückler 498434ee3d [Web] Even out spacing of the expanded table row
DataTables removes the top padding of the first entry in the expanded
row, but mailcow's 0.5em padding left 7px under the last entry, so the
list had 7px of space above and 15px below and the last entry (often
Tags) looked taller than the others. Drop the last entry's bottom
padding as well.

Signed-off-by: Moritz Stückler <moritz@bitbetter.de>
2026-10-22 13:10:49 +02:00
Moritz Stückler f662af4c50 [Web] Even out badge and tag sizes in tables
- Use the normal cursor on non-orderable headers. The expand column
  header kept a pointer cursor from sorting_asc although clicking it
  does nothing.
- Let icons in badges inherit the badge font size, like .btn .bi, and
  keep their glyph from adding line height. The global 12pt icon size
  made e.g. the "SSO @" badge in Last mail login taller than the IMAP
  and SMTP badges next to it. Tag badges keep their 12px icon.
- Drop the vertical margin of tag badges inside tables. It is meant for
  the tag editor in edit forms and made the Tags entry of the expanded
  row taller than the others.
- Center tag badge captions: the 12px tag icon stretched the 10.5px
  badge line and pushed the caption below center.

Signed-off-by: Moritz Stückler <moritz@bitbetter.de>
2026-10-22 13:06:00 +02:00
Moritz Stückler 8d4895a54d [Web] Align the table expand control and row checkbox
- Center the +/- glyph in the expand control: its line-height (1.25em)
  was larger than the 1em box, pushing the glyph down. Derive the box's
  margin-top from its size so it is centered in the row (desktop and
  the larger mobile variant).
- Hide sort arrows on non-orderable headers. The default initial order
  targets column 0, the expand column, which got a sorting_asc arrow
  and arrow padding although it cannot be sorted.
- Center row checkboxes level with the expand control by using
  Bootstrap's 0.25em margin-top instead of a fixed 7px.

Signed-off-by: Moritz Stückler <moritz@bitbetter.de>
2026-10-22 12:43:18 +02:00
Moritz Stückler 81d6b1f547 [Web] Clearer captions for domain table columns
Caption the "RL" column "Rate limit" using the existing translated
edit.ratelimit string, and shorten "Max. size of a mailbox" to
"Max. mailbox size" (en-gb only; the key is only used for this column).

Signed-off-by: Moritz Stückler <moritz@bitbetter.de>
2026-10-22 12:43:18 +02:00
Bilal Zahid d93f32072e fix(web): post WebAuthn TFA enrollment through the JSON API
The forced TFA enrollment form submitted the raw credential JSON in the
'token' field, which set_tfa()'s webauthn case never reads. It expects the
parsed \['registration'] object that only the JSON API builds, so the
form POST inserted a row with an empty keyHandle and a NULL publicKey while
still reporting success. Every WebAuthn 2FA login then failed, because
webauthn-tfa-get-args sent an empty credential id in allowCredentials.

- base.twig: POST the attestation to /api/v1/add/webauthn-tfa-registration
  like the regular WebAuthn modal does
- functions.inc.php: refuse incomplete WebAuthn registrations
- lang.en-gb.json: message for the new guard
2026-10-13 19:25:17 +05:00
Philipp Harms 7b658fa65c [Update] Fix update.sh deleting mailcow's own MASQUERADE rule
The "Checking for conflicting bridges" step extracts the bridge name with
`cut -d':' -f2`, which yields " br-mailcow" (leading space). Since the
variable got quoted in `grep -v "${MAILCOW_BRIDGE}"`, the leading space is
significant and never matches "!br-mailcow" in the `iptables -L` output, so
the rule `-s <IPV4_NETWORK>.0/24 ! -o br-mailcow -j MASQUERADE` itself gets
deleted. The mailcow network loses outbound NAT, unbound turns unhealthy and
dependent containers stay in "Created" until Docker is restarted.

Strip whitespace/quotes from the bridge name, match the interface as a whole
token, and skip the cleanup if the bridge name could not be determined.
2026-10-02 18:53:12 +02:00
10 changed files with 464 additions and 62 deletions

No files matched your search

+46 -21
View File
@@ -3,6 +3,11 @@
# THIS SCRIPT IS DESIGNED TO BE RUNNING BY MAILCOW SCRIPTS ONLY! # THIS SCRIPT IS DESIGNED TO BE RUNNING BY MAILCOW SCRIPTS ONLY!
# DO NOT, AGAIN, NOT TRY TO RUN THIS SCRIPT STANDALONE!!!!!! # DO NOT, AGAIN, NOT TRY TO RUN THIS SCRIPT STANDALONE!!!!!!
# Global IPv6 address that is no unique local address (fc00::/7, e.g. Docker bridges)
_has_public_ipv6() {
ip -6 -o addr show scope global 2>/dev/null | awk '{print $4}' | grep -qviE '^f[cd]'
}
# 1) Check if the host supports IPv6 # 1) Check if the host supports IPv6
get_ipv6_support() { get_ipv6_support() {
# ---- helper: probe external IPv6 connectivity without DNS ---- # ---- helper: probe external IPv6 connectivity without DNS ----
@@ -37,6 +42,9 @@ get_ipv6_support() {
if _probe_ipv6_connectivity; then if _probe_ipv6_connectivity; then
DETECTED_IPV6=true DETECTED_IPV6=true
echo -e "IPv6 detected on host – ${LIGHT_GREEN}leaving IPv6 support enabled${YELLOW}.${NC}" echo -e "IPv6 detected on host – ${LIGHT_GREEN}leaving IPv6 support enabled${YELLOW}.${NC}"
elif _has_public_ipv6; then
DETECTED_IPV6=true
echo -e "${YELLOW}External IPv6 connectivity test failed, but the host has a public IPv6 address – ${LIGHT_GREEN}leaving IPv6 support enabled${YELLOW}.${NC}"
else else
DETECTED_IPV6=false DETECTED_IPV6=false
echo -e "${YELLOW}Default IPv6 route present but external IPv6 connectivity failed – ${LIGHT_RED}disabling IPv6 support${YELLOW}.${NC}" echo -e "${YELLOW}Default IPv6 route present but external IPv6 connectivity failed – ${LIGHT_RED}disabling IPv6 support${YELLOW}.${NC}"
@@ -192,9 +200,31 @@ EOF
fi fi
} }
_set_enable_ipv6() {
if [[ -n "$MAILCOW_CONF" && -f "$MAILCOW_CONF" ]]; then
if grep -q '^ENABLE_IPV6=' "$MAILCOW_CONF"; then
sed -i "s/^ENABLE_IPV6=.*/ENABLE_IPV6=$1/" "$MAILCOW_CONF"
else
echo "ENABLE_IPV6=$1" >> "$MAILCOW_CONF"
fi
else
export IPV6_BOOL=$1
fi
}
_warn_ipv6_disabled() {
_has_public_ipv6 || return 0
ip -6 route show default 2>/dev/null | grep -qE '^default' || return 0
grep -Eq '"userland-proxy"[[:space:]]*:[[:space:]]*false' /etc/docker/daemon.json 2>/dev/null && return 0
echo -e "${LIGHT_RED}WARNING: ENABLE_IPV6=false, but this host has a public IPv6 address.${NC}"
echo -e "${YELLOW}Docker forwards IPv6 connections to mailcow with an internal source address, which Postfix trusts. This can make your server an open relay over IPv6.${NC}"
echo -e "${YELLOW}Set ENABLE_IPV6=true in mailcow.conf, or set \"userland-proxy\": false in /etc/docker/daemon.json and restart Docker.${NC}"
echo -e "${YELLOW}See https://docs.mailcow.email/post_installation/firststeps-disable_ipv6/${NC}"
sleep 5
}
# 3) Main wrapper for generate_config.sh and update.sh # 3) Main wrapper for generate_config.sh and update.sh
configure_ipv6() { configure_ipv6() {
# detect manual override if mailcow.conf is present
if [[ -n "$MAILCOW_CONF" && -f "$MAILCOW_CONF" ]] && grep -q '^ENABLE_IPV6=' "$MAILCOW_CONF"; then if [[ -n "$MAILCOW_CONF" && -f "$MAILCOW_CONF" ]] && grep -q '^ENABLE_IPV6=' "$MAILCOW_CONF"; then
MANUAL_SETTING=$(grep '^ENABLE_IPV6=' "$MAILCOW_CONF" | cut -d= -f2) MANUAL_SETTING=$(grep '^ENABLE_IPV6=' "$MAILCOW_CONF" | cut -d= -f2)
elif [[ -z "$MAILCOW_CONF" ]] && [[ -n "${ENABLE_IPV6:-}" ]]; then elif [[ -z "$MAILCOW_CONF" ]] && [[ -n "${ENABLE_IPV6:-}" ]]; then
@@ -203,19 +233,23 @@ configure_ipv6() {
MANUAL_SETTING="" MANUAL_SETTING=""
fi fi
if [[ "${MANUAL_SETTING,,}" == "false" ]]; then
_set_enable_ipv6 false
echo "ENABLE_IPV6=false is set, skipping Docker IPv6 configuration."
_warn_ipv6_disabled
echo "IPv6 configuration complete: ENABLE_IPV6=false"
return
fi
get_ipv6_support get_ipv6_support
# if user manually set it, check for mismatch if [[ "$DETECTED_IPV6" != "true" && "${MANUAL_SETTING,,}" == "true" ]] && _has_public_ipv6; then
echo -e "${YELLOW}Keeping ENABLE_IPV6=true, the host has a public IPv6 address.${NC}"
DETECTED_IPV6=true
fi
if [[ "$DETECTED_IPV6" != "true" ]]; then if [[ "$DETECTED_IPV6" != "true" ]]; then
if [[ -n "$MAILCOW_CONF" && -f "$MAILCOW_CONF" ]]; then _set_enable_ipv6 false
if grep -q '^ENABLE_IPV6=' "$MAILCOW_CONF"; then
sed -i 's/^ENABLE_IPV6=.*/ENABLE_IPV6=false/' "$MAILCOW_CONF"
else
echo "ENABLE_IPV6=false" >> "$MAILCOW_CONF"
fi
else
export IPV6_BOOL=false
fi
echo "Skipping Docker IPv6 configuration because host does not support IPv6." echo "Skipping Docker IPv6 configuration because host does not support IPv6."
echo "Make sure to check if your docker daemon.json does not include \"enable_ipv6\": true if you do not want IPv6." echo "Make sure to check if your docker daemon.json does not include \"enable_ipv6\": true if you do not want IPv6."
echo "IPv6 configuration complete: ENABLE_IPV6=false" echo "IPv6 configuration complete: ENABLE_IPV6=false"
@@ -224,16 +258,7 @@ configure_ipv6() {
fi fi
docker_daemon_edit docker_daemon_edit
_set_enable_ipv6 true
if [[ -n "$MAILCOW_CONF" && -f "$MAILCOW_CONF" ]]; then
if grep -q '^ENABLE_IPV6=' "$MAILCOW_CONF"; then
sed -i 's/^ENABLE_IPV6=.*/ENABLE_IPV6=true/' "$MAILCOW_CONF"
else
echo "ENABLE_IPV6=true" >> "$MAILCOW_CONF"
fi
else
export IPV6_BOOL=true
fi
echo "IPv6 configuration complete: ENABLE_IPV6=true" echo "IPv6 configuration complete: ENABLE_IPV6=true"
} }
+25 -2
View File
@@ -15,6 +15,10 @@ table.dataTable>tbody>tr.child ul.dtr-details>li {
border-bottom: 1px solid rgba(0, 0, 0, 0.129); border-bottom: 1px solid rgba(0, 0, 0, 0.129);
padding: 0.5em 0; padding: 0.5em 0;
} }
/* like the first entry has no top padding, the last one needs no bottom padding */
table.dataTable>tbody>tr.child ul.dtr-details>li:last-child {
padding-bottom: 0;
}
table.dataTable.dtr-inline.collapsed>tbody>tr>td.dtr-control:before:hover, table.dataTable.dtr-inline.collapsed>tbody>tr>td.dtr-control:before:hover,
table.dataTable.dtr-inline.collapsed>tbody>tr>th.dtr-control:before:hover { table.dataTable.dtr-inline.collapsed>tbody>tr>th.dtr-control:before:hover {
background-color: var(--mc-dtr-hover-bg); background-color: var(--mc-dtr-hover-bg);
@@ -28,7 +32,8 @@ table.dataTable td.dt-control:before {
color: var(--mc-dtr-color); color: var(--mc-dtr-color);
height: 1em; height: 1em;
width: 1em; width: 1em;
line-height: 1.25em; line-height: 1em;
margin-top: calc(-0.5em - 1.5px);
border-radius: 0px; border-radius: 0px;
box-shadow: none; box-shadow: none;
font-size: 14px; font-size: 14px;
@@ -39,11 +44,29 @@ table.dataTable.dtr-inline.collapsed>tbody>tr.parent>th.dtr-control:before,
table.dataTable td.dt-control:before { table.dataTable td.dt-control:before {
background-color: var(--mc-dtr-active-bg) !important; background-color: var(--mc-dtr-active-bg) !important;
} }
/* The default initial order targets column 0, which is usually the non-orderable expand column */
table.dataTable thead > tr > th.sorting_disabled.sorting_asc,
table.dataTable thead > tr > th.sorting_disabled.sorting_desc {
padding-right: 0.5rem;
cursor: auto;
}
table.dataTable thead > tr > th.sorting_disabled.sorting_asc:before,
table.dataTable thead > tr > th.sorting_disabled.sorting_asc:after,
table.dataTable thead > tr > th.sorting_disabled.sorting_desc:before,
table.dataTable thead > tr > th.sorting_disabled.sorting_desc:after {
display: none;
}
table.dataTable.table-striped>tbody>tr>td { table.dataTable.table-striped>tbody>tr>td {
vertical-align: middle; vertical-align: middle;
} }
table.dataTable.table-striped>tbody>tr>td>input[type="checkbox"] { table.dataTable.table-striped>tbody>tr>td>input[type="checkbox"] {
margin-top: 7px; /* centers the 1em checkbox in the 1.5em line, level with the expand control */
margin-top: 0.25em;
}
/* the vertical margin is meant for the tag editor in edit forms, in tables it only adds height */
table.dataTable .tag-badge {
margin-top: 0;
margin-bottom: 0;
} }
td.dtr-col-lg { td.dtr-col-lg {
min-width: 350px; min-width: 350px;
+8
View File
@@ -139,6 +139,13 @@ body {
display: inline-block; display: inline-block;
font-size: inherit; font-size: inherit;
} }
.badge .bi {
font-size: inherit;
}
/* keeps icons from making a badge taller than one with text only */
.badge .bi::before {
line-height: 0;
}
.btn-group-xs > .btn, .btn-xs { .btn-group-xs > .btn, .btn-xs {
padding: .25rem .4rem; padding: .25rem .4rem;
font-size: .875rem; font-size: .875rem;
@@ -343,6 +350,7 @@ code {
} }
.tag-badge .bi { .tag-badge .bi {
font-size: 12px; font-size: 12px;
line-height: 0;
} }
.tag-badge.btn-badge:hover { .tag-badge.btn-badge:hover {
filter: brightness(0.9); filter: brightness(0.9);
+1 -1
View File
@@ -191,7 +191,7 @@
height: 2rem; height: 2rem;
width: 2rem; width: 2rem;
line-height: 2rem; line-height: 2rem;
margin-top: -15px; margin-top: calc(-1rem - 1.5px);
} }
li .dtr-data { li .dtr-data {
+14 -2
View File
@@ -1394,6 +1394,18 @@ function set_tfa($_data) {
case "webauthn": case "webauthn":
$key_id = (!isset($_data["key_id"])) ? 'unidentified' : $_data["key_id"]; $key_id = (!isset($_data["key_id"])) ? 'unidentified' : $_data["key_id"];
// Refuse incomplete WebAuthn registrations. Without this guard a request
// that does not contain the parsed credential data (e.g. a plain form
// POST) would silently insert an empty keyHandle while reporting success.
if (empty($_data['registration']) || empty($_data['registration']->credentialId)) {
$_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $_data_log),
'msg' => 'webauthn_registration_failed'
);
return false;
}
$stmt = $pdo->prepare("INSERT INTO `tfa` (`username`, `key_id`, `authmech`, `keyHandle`, `publicKey`, `certificate`, `counter`, `active`) $stmt = $pdo->prepare("INSERT INTO `tfa` (`username`, `key_id`, `authmech`, `keyHandle`, `publicKey`, `certificate`, `counter`, `active`)
VALUES (?, ?, 'webauthn', ?, ?, ?, ?, '1')"); VALUES (?, ?, 'webauthn', ?, ?, ?, ?, '1')");
$stmt->execute(array( $stmt->execute(array(
@@ -2420,7 +2432,7 @@ function identity_provider($_action = null, $_data = null, $_extra = null) {
case "use_ssl": case "use_ssl":
case "use_tls": case "use_tls":
case "login_provisioning": case "login_provisioning":
case "ignore_ssl_errors": case "ignore_ssl_error":
$settings[$row["key"]] = boolval($row["value"]); $settings[$row["key"]] = boolval($row["value"]);
break; break;
default: default:
@@ -2444,7 +2456,7 @@ function identity_provider($_action = null, $_data = null, $_extra = null) {
if ($settings["authsource"] == "ldap"){ if ($settings["authsource"] == "ldap"){
$settings['use_ssl'] = !isset($settings['use_ssl']) ? false : $settings['use_ssl']; $settings['use_ssl'] = !isset($settings['use_ssl']) ? false : $settings['use_ssl'];
$settings['use_tls'] = !isset($settings['use_tls']) ? false : $settings['use_tls']; $settings['use_tls'] = !isset($settings['use_tls']) ? false : $settings['use_tls'];
$settings['ignore_ssl_errors'] = !isset($settings['ignore_ssl_errors']) ? false : $settings['ignore_ssl_errors']; $settings['ignore_ssl_error'] = !isset($settings['ignore_ssl_error']) ? false : $settings['ignore_ssl_error'];
} }
return $settings; return $settings;
break; break;
+1 -1
View File
@@ -614,7 +614,7 @@ jQuery(function($){
defaultContent: '' defaultContent: ''
}, },
{ {
title: 'RL', title: lang_edit.ratelimit,
data: 'rl', data: 'rl',
searchable: false, searchable: false,
orderable: false, orderable: false,
+2 -1
View File
@@ -1127,7 +1127,7 @@
"mailbox_defaults_info": "Define default settings for new mailboxes.", "mailbox_defaults_info": "Define default settings for new mailboxes.",
"mailbox_defquota": "Default mailbox size", "mailbox_defquota": "Default mailbox size",
"mailbox_templates": "Mailbox Templates", "mailbox_templates": "Mailbox Templates",
"mailbox_quota": "Max. size of a mailbox", "mailbox_quota": "Max. mailbox size",
"mailboxes": "Mailboxes", "mailboxes": "Mailboxes",
"max_aliases": "Max. aliases", "max_aliases": "Max. aliases",
"max_mailboxes": "Max. possible mailboxes", "max_mailboxes": "Max. possible mailboxes",
@@ -1429,6 +1429,7 @@
"u2f_deprecated": "It seems that your Key was registered using the deprecated U2F method. We will deactivate Two-Factor-Authenticaiton for you and delete your Key.", "u2f_deprecated": "It seems that your Key was registered using the deprecated U2F method. We will deactivate Two-Factor-Authenticaiton for you and delete your Key.",
"u2f_deprecated_important": "Please register your Key in the admin panel with the new WebAuthn method.", "u2f_deprecated_important": "Please register your Key in the admin panel with the new WebAuthn method.",
"webauthn": "WebAuthn authentication", "webauthn": "WebAuthn authentication",
"webauthn_registration_failed": "WebAuthn registration failed. The credential could not be verified, please try again.",
"waiting_usb_auth": "<i>Waiting for USB device...</i><br><br>Please tap the button on your USB device now.", "waiting_usb_auth": "<i>Waiting for USB device...</i><br><br>Please tap the button on your USB device now.",
"waiting_usb_register": "<i>Waiting for USB device...</i><br><br>Please enter your password above and confirm your registration by tapping the button on your USB device.", "waiting_usb_register": "<i>Waiting for USB device...</i><br><br>Please enter your password above and confirm your registration by tapping the button on your USB device.",
"yubi_otp": "Yubico OTP authentication" "yubi_otp": "Yubico OTP authentication"
+327 -11
View File
@@ -30,7 +30,8 @@
"quarantine_category": "Spremeni kategorijo obvestil o karanteni", "quarantine_category": "Spremeni kategorijo obvestil o karanteni",
"syncjobs": "Sinhronizacijska opravila", "syncjobs": "Sinhronizacijska opravila",
"pw_reset": "Dovoli ponastavitev uporabniškega gesla mailcow", "pw_reset": "Dovoli ponastavitev uporabniškega gesla mailcow",
"alias_external_goto": "Dovoli vzdevke z zunanjimi domenami goto" "alias_external_goto": "Dovoli vzdevke z zunanjimi domenami goto",
"mailbox_groups": "Skupine"
}, },
"add": { "add": {
"active": "Aktivno", "active": "Aktivno",
@@ -361,7 +362,7 @@
"iam_default_template": "Privzeta predloga", "iam_default_template": "Privzeta predloga",
"iam_default_template_description": "Če uporabniku ni dodeljena nobena predloga, bo privzeta predloga uporabljena za ustvarjanje nabiralnika, ne pa za posodabljanje nabiralnika.", "iam_default_template_description": "Če uporabniku ni dodeljena nobena predloga, bo privzeta predloga uporabljena za ustvarjanje nabiralnika, ne pa za posodabljanje nabiralnika.",
"iam_description": "Konfigurirajte zunanjega ponudnika za preverjanje pristnosti<br>Uporabnikovi poštni nabiralniki bodo samodejno ustvarjeni ob prvi prijavi, če je nastavljeno preslikavanje atributov.", "iam_description": "Konfigurirajte zunanjega ponudnika za preverjanje pristnosti<br>Uporabnikovi poštni nabiralniki bodo samodejno ustvarjeni ob prvi prijavi, če je nastavljeno preslikavanje atributov.",
"iam_extra_permission": "Za delovanje naslednjih nastavitev potrebuje odjemalec mailcow v Keycloaku <code>Servisni račun</code> in dovoljenje za <code>ogled uporabnikov</code>.", "iam_extra_permission": "Da bi spodnje nastavitve delovale, odjemalec mailcow v sistemu Keycloak potrebuje <code>servisni račun</code> (service account) in dovoljenje za <code>view-users</code> (pri sinhronizaciji skupin tudi <code>query-groups</code>).",
"iam_host": "Gostitelj", "iam_host": "Gostitelj",
"iam_host_info": "Vnesite enega ali več gostiteljev LDAP, ločenih z vejicami.", "iam_host_info": "Vnesite enega ali več gostiteljev LDAP, ločenih z vejicami.",
"iam_import_users": "Uvozi uporabnike", "iam_import_users": "Uvozi uporabnike",
@@ -401,7 +402,104 @@
"ui_theme_dark": "Vključuje različico s temnim načinom", "ui_theme_dark": "Vključuje različico s temnim načinom",
"ui_theme_default": "Privzeto", "ui_theme_default": "Privzeto",
"ui_theme_info": "Teme so mape v <code>data/web/css/themes/&lt;name&gt;/</code>, ki vsebujejo naslednje datoteke:<ul class=\"mb-0\"><li><code>theme.css</code> (obvezna)</li><li><code>dark.css</code> (neobvezna, temni način)</li><li><code>bootstrap.css</code> (neobvezna, nadomesti osnovno temo Bootstrap)</li><li><code>theme.json</code> (neobvezna, <code>name</code> in <code>description</code>)</li></ul>", "ui_theme_info": "Teme so mape v <code>data/web/css/themes/&lt;name&gt;/</code>, ki vsebujejo naslednje datoteke:<ul class=\"mb-0\"><li><code>theme.css</code> (obvezna)</li><li><code>dark.css</code> (neobvezna, temni način)</li><li><code>bootstrap.css</code> (neobvezna, nadomesti osnovno temo Bootstrap)</li><li><code>theme.json</code> (neobvezna, <code>name</code> in <code>description</code>)</li></ul>",
"ui_theme_none": "Tem ni bilo mogoče najti." "ui_theme_none": "Tem ni bilo mogoče najti.",
"api_key_add": "Dodaj API ključ",
"api_keys": "API ključi",
"api_networks": "Dovoljeni naslovi IP/omrežja",
"api_service_key": "Ključ storitve iz datoteke mailcow.conf; spremeniti ga je mogoče le tam.",
"api_service_key_info": "Ta ključ API je določen v datoteki mailcow.conf (API_KEY, API_KEY_READ_ONLY, API_ALLOW_FROM) in ga je mogoče spremeniti le tam.",
"iam_attribute_field_info": "Neobvezno. Atribut LDAP, katerega vrednost izbere predlogo v spodnjem preslikovanju.",
"iam_disabled_filter": "Onemogočen filter",
"iam_disabled_filter_info": "Filter LDAP za onemogočene uporabnike. Računi v imeniku Active Directory, ki imajo v atributu userAccountControl nastavljeno vrednost ACCOUNTDISABLE, se vedno štejejo za onemogočene.",
"iam_encryption": "Šifriranje",
"iam_encryption_info": "StartTLS uporablja običajna vrata (389). SSL (LDAPS) uporablja vrata 636, pri čemer se vrata 389 samodejno spremenijo.",
"iam_encryption_none": "Nič",
"iam_filter_info": "LDAP-filter za uporabnike, ki se lahko prijavijo in so sinhronizirani, npr. <code>(objectClass=person)</code>.",
"iam_group_autocreate": "Ustvari skupine",
"iam_group_autocreate_info": "Za vsako skupino IdP, ki še nima poštnega predala, ustvari skupino s poštnim predalom. Če je naslov skupine prost, postane ta naslov njen naslov.",
"iam_group_basedn": "DN osnove za skupine",
"iam_group_default_domain": "Privzeta domena skupine",
"iam_group_default_domain_info": "Domena novih skupin, katerih e-pošta ni v domeni mailcow.",
"iam_group_filter": "Filter skupin",
"iam_group_member_attribute": "Atribut člana",
"iam_group_member_attribute_info": "Samo za \"Atribut članstva v skupinah\", npr. member ali uniqueMember.",
"iam_group_member_mode": "Članstva",
"iam_group_member_mode_ad_chain": "Active Directory, vključno z ugnezdenimi skupinami",
"iam_group_member_mode_member": "Atribut članstva v skupinah",
"iam_group_member_mode_memberof": "memberOf uporabnikov",
"iam_group_name_attribute": "Atribut imena skupine",
"iam_group_paths": "Pot skupine",
"iam_group_paths_info": "Z vejicami ločene poti do skupin v Keycloaku: <code>/Sales</code> ali <code>/mailcow/*</code> za vse skupine pod <code>/mailcow</code>. Odjemalec mailcow potrebuje dovoljenje <code>query-groups</code>.",
"iam_group_sync": "Sinhronizacija skupin",
"iam_group_sync_info": "Sinhronizira člane skupin iz ponudnika identitete (IdP) s skupinami poštnih predalov (Poštni predali → Skupine). Člani, dodani v sistemu mailcow, ostanejo.",
"iam_id_attribute": "ID atribut",
"iam_id_attribute_info": "Stalen ID uporabnika. Prazno = objectGUID, entryUUID, nsUniqueId ali ipaUniqueID. Sprememba povzroči ponovno povezovanje vseh poštnih predalov na podlagi e-poštnega naslova.",
"iam_import_users_info": "Ustvari poštne predale za vse uporabnike ponudnika identitete (IdP) na podlagi ustrezne predloge, ne da bi bilo treba čakati na njihovo prvo prijavo.",
"iam_login_provisioning_info": "Ob prvi prijavi uporabnika ustvari poštni predal z ustrezno ali privzeto predlogo.",
"iam_mapping_add": "Dodaj preslikavo",
"iam_mapping_info": "Vrednost uporabniškega atributa določa predlogo (Keycloak in OIDC: <code>mailcow_template</code>). Predloge skupin imajo prednost.",
"iam_offboarding": "Zaključek sodelovanja",
"iam_offboarding_info": "Uporabniki, ki so onemogočeni v IdP ali pa so manjkali v dveh popolnih sinhronizacijah, se ne morejo več prijaviti. Njihov poštni nabiralnik še vedno prejema pošto. Ponovno so omogočeni samo poštni nabiralniki, ki jih je sinhronizacija onemogočila.",
"iam_offboarding_limit": "Sprememba meje (%)",
"iam_offboarding_limit_info": "Sinhronizacijski postopki, ki bi onemogočili več nabiralnikov ali odstranili več članstev v skupinah, kot je določeno s to omejitvijo (vsaj 5), so blokirani.",
"iam_periodic_full_sync_info": "Posodobi ime in predlogo obstoječih poštnih predalov na podlagi podatkov iz ponudnika identitete (IdP).",
"iam_redirect_url_add": "Dodaj URL za preusmeritev",
"iam_section_connection": "Povezava",
"iam_section_groups": "Skupine",
"iam_section_login": "Prijava",
"iam_section_sync": "Sinhronizacija",
"iam_section_templates": "Predloge za poštne predale",
"iam_section_users": "Uporabniki",
"iam_sync_accounts": "Poštni predali IdP",
"iam_sync_changes": "Spremembe",
"iam_sync_count_conflicts": "Konflikti",
"iam_sync_count_creates": "Ustvarjeno",
"iam_sync_count_deactivate": "Prijava onemogočena",
"iam_sync_count_errors": "Napake",
"iam_sync_count_found": "Ponovno najdeno",
"iam_sync_count_group_creates": "Ustvarjene skupine",
"iam_sync_count_group_renames": "Skupine preimenovane",
"iam_sync_count_links": "Povezano",
"iam_sync_count_membership_removals": "Članstva odstranjena",
"iam_sync_count_memberships": "Skupine z novimi člani",
"iam_sync_count_missing": "Manjka",
"iam_sync_count_orphaned_groups": "Skupine, ki niso v IdP",
"iam_sync_count_release": "Sproščeno",
"iam_sync_count_restore": "Prijava omogočena",
"iam_sync_count_skipped": "Preskočeno",
"iam_sync_count_updates": "Posodobljeno",
"iam_sync_details": "Podrobnosti",
"iam_sync_force": "Zaženi brez omejitev",
"iam_sync_force_confirm": "Želite zagnati sinhronizacijo brez omejitve števila sprememb? Nabiralniki so lahko onemogočeni, članstva v skupinah pa odstranjena.",
"iam_sync_idp_disabled": "Onemogočeno s strani IdP",
"iam_sync_linked": "Povezano",
"iam_sync_missing": "Manjka v IdP",
"iam_sync_mode": "Način",
"iam_sync_mode_force": "Brez omejitev",
"iam_sync_mode_preview": "Predogled",
"iam_sync_mode_run": "Zaženi",
"iam_sync_no_changes": "Ni sprememb",
"iam_sync_none": "Ni še bilo izvedenih sinhronizacij.",
"iam_sync_off": "Sinhronizacija ni aktivna. Omogočite uvoz, periodično sinhronizacijo, postopek ob zaključku sodelovanja (offboarding) ali sinhronizacijo skupin.",
"iam_sync_preview": "Predogled",
"iam_sync_result": "Rezultat",
"iam_sync_run": "Zaženi zdaj",
"iam_sync_started": "Začeto",
"iam_sync_status": "Stanje sinhronizacije",
"iam_sync_status_blocked": "Blokirano",
"iam_sync_status_error": "Napaka",
"iam_sync_status_info": "Izvajanje se začne v eni minuti. Predogled prikaže spremembe, ne da bi jih uveljavil.",
"iam_sync_status_ok": "OK",
"iam_sync_status_pending": "V čakalni vrsti",
"iam_sync_status_running": "V teku",
"iam_username_field_info": "Atribut z e-poštnim naslovom postane ime poštnega predala. Privzeto: mail.",
"description": "Opis",
"unban_all": "Odblokiraj vse",
"syncjobs": "Opravila sinhronizacije",
"syncjob_max_parallel": "Največje število vzporednih sinhronizacijskih procesov",
"syncjob_max_parallel_info": "Koliko opravil sinhronizacije lahko poteka hkrati (1–32).",
"syncjob_max_kb_per_second": "Omejitev pasovne širine na proces (KB/s)",
"syncjob_max_kb_per_second_info": "0 = neomejeno. Omejuje vsak postopek sinhronizacije (v KB/s); omejitev za posamezno opravilo (v bajtih/s) je navzgor omejena s to vrednostjo. Skupna vrednost ≈ ta vrednost × največje število vzporednih postopkov."
}, },
"danger": { "danger": {
"alias_goto_identical": "Vzdevek in ciljni naslov se ne smeta ujemati", "alias_goto_identical": "Vzdevek in ciljni naslov se ne smeta ujemati",
@@ -550,7 +648,50 @@
"tfa_removal_blocked": "Dvofaktorske avtentikacije ni mogoče odstraniti, ker je obvezna za vaš račun.", "tfa_removal_blocked": "Dvofaktorske avtentikacije ni mogoče odstraniti, ker je obvezna za vaš račun.",
"quarantine_category_invalid": "Kategorija karantene mora biti ena od: add_header, reject, all", "quarantine_category_invalid": "Kategorija karantene mora biti ena od: add_header, reject, all",
"external_goto_denied": "Zunanji naslov goto %s ni dovoljen", "external_goto_denied": "Zunanji naslov goto %s ni dovoljen",
"ui_theme_invalid": "Tema ni najdena" "ui_theme_invalid": "Tema ni najdena",
"alias_group_managed": "Vzdevek %s pripada skupini in ga je mogoče spremeniti le tam.",
"api_key_access_invalid": "Neveljavna vrsta dostopa do API-ja; dovoljene vrednosti so ro in rw",
"api_key_description_invalid": "Opis ključa API ne sme presegati 255 znakov",
"api_key_network_invalid": "Neveljaven naslov IP ali omrežje: %s",
"api_key_service_locked": "Ključ API %s je določen v datoteki mailcow.conf in ga je mogoče spremeniti le tam",
"group_address_invalid": "Skupinski naslov %s je neveljaven ali pa ni v domeni skupine",
"group_description_invalid": "Opis skupine ne sme presegati 255 znakov.",
"group_grant_invalid": "Neveljavna delitev za poštni predal %s",
"group_member_idp": "%s je član prek ponudnika identitete in ga je mogoče odstraniti le tam",
"group_member_invalid": "%s ni poštni predal in ne more biti član skupine",
"group_name_invalid": "Ime skupine ni veljavno (1–100 znakov)",
"group_priority_invalid": "Prednostna naloga mora biti številka",
"group_send_as_invalid": "Naslov za pošiljanje »%s« je neveljaven ali neznan",
"iam_sync_mode_invalid": "Neveljaven način sinhronizacije",
"iam_sync_unavailable": "Ponudnika identitete ni mogoče sinhronizirati (samo Keycloak in LDAP)",
"tfa_login_locked": "Preveč neuspešnih poskusov prijave z dvostopenjskim preverjanjem; poskusite znova pozneje",
"iam_unavailable": "Ponudnik identitete ni dosegljiv; poskusite znova pozneje.",
"refresh_login_failed": "Seje ni bilo mogoče osvežiti. Prosimo, prijavite se znova.",
"imapsync_source_in_use": "Vir sinhronizacije %s še vedno uporablja opravilo sinhronizacije in ga ni mogoče izbrisati",
"imapsync_source_used_by_others": "Strežnika vira sinhronizacije %s ni mogoče spremeniti, saj ga uporabljajo opravila sinhronizacije drugih poštnih predalov",
"imapsync_source_token_refresh_failed": "Osvežitev žetona OAuth za %s ni uspela",
"imapsync_source_scope_empty": "Izberite vsaj eno domeno za izbrano vidnost",
"imapsync_source_unavailable": "Izbrani vir sinhronizacije ni na voljo",
"imapsync_source_oauth_connect_required": "Pred shranjevanjem tega opravila sinhronizacije se prijavite pri ponudniku.",
"imapsync_source_name_invalid": "Neveljavno ime vira sinhronizacije",
"imapsync_source_host_invalid": "Neveljavno ime gostitelja ali naslov IP",
"imapsync_source_port_invalid": "Neveljavna vrata",
"imapsync_source_enc_invalid": "Neveljaven način šifriranja",
"imapsync_source_auth_invalid": "Neveljaven način preverjanja pristnosti",
"imapsync_custom_param_invalid": "Parametri po meri vsebujejo nedovoljeno možnost za imapsync: %s",
"imapsync_source_oauth_required": "OAuth2 zahteva končno točko za žetone, ID odjemalca, skrivnost odjemalca in obseg.",
"imapsync_source_oauth_endpoint_invalid": "Neveljavna končna točka OAuth2: zahtevan je naslov URL s protokolom https:// in veljavnim imenom gostitelja (viri, ki jih ni ustvaril skrbnik, potrebujejo javno dostopnega gostitelja)",
"imapsync_source_oauth_extra_invalid": "Dodatni parametri OAuth2 morajo biti objekt JSON s preprostimi vrednostmi, npr. {\"vir\": \"https://example.com\"}",
"imapsync_source_tenant_missing": "Vnesite najemnika Microsoft 365",
"imapsync_source_oauth_invalid": "Neveljavna konfiguracija OAuth2",
"imapsync_max_parallel_invalid": "Število vzporednih procesov mora biti med 1 in 32",
"imapsync_source_description_invalid": "Opis ne sme presegati 255 znakov.",
"imapsync_source_refresh_unsupported": "Ročno osveževanje žetonov je na voljo samo za vire poverilnic odjemalcev",
"imapsync_custom_params_format": "Prilagojene parametre je treba poslati kot seznam parov možnost/vrednost",
"imapsync_custom_param_value": "Neveljavna vrednost za možnost %s programa imapsync (manjkajoča vrednost, vrednost, podana pri zastavici, ali nedovoljena vrednost)",
"imapsync_job_running": "Opravilo sinhronizacije %s se trenutno izvaja, zato ga ni mogoče načrtovati za naslednji izvedbeni termin",
"imapsync_user1_invalid": "Neveljavno oddaljeno uporabniško ime",
"imapsync_max_kb_per_second_invalid": "Omejitev pasovne širine mora biti med 0 in 10485760 KB/s"
}, },
"debug": { "debug": {
"containers_info": "Informacije o zabojniku", "containers_info": "Informacije o zabojniku",
@@ -764,7 +905,13 @@
"internal_info": "Notranji vzdevki so dostopni samo iz lastne domene ali vzdevkov domen.", "internal_info": "Notranji vzdevki so dostopni samo iz lastne domene ali vzdevkov domen.",
"sender_allowed": "Dovoli pošiljanje kot ta vzdevek", "sender_allowed": "Dovoli pošiljanje kot ta vzdevek",
"sender_allowed_info": "Če je onemogočeno, lahko ta vzdevek samo prejema pošto. Za preglasitev in dodelitev dovoljenja za pošiljanje določenim poštnim predalom uporabite seznam za nadzor dostopa pošiljatelja.", "sender_allowed_info": "Če je onemogočeno, lahko ta vzdevek samo prejema pošto. Za preglasitev in dodelitev dovoljenja za pošiljanje določenim poštnim predalom uporabite seznam za nadzor dostopa pošiljatelja.",
"mta_sts_active_info": "Če ni označeno, pravilnik MTA-STS ne bo objavljen in za poddomeno mta-sts ne bo zahtevano nobeno potrdilo prek ACME." "mta_sts_active_info": "Če ni označeno, pravilnik MTA-STS ne bo objavljen in za poddomeno mta-sts ne bo zahtevano nobeno potrdilo prek ACME.",
"iam_idp_disabled": "Prijava onemogočena zaradi sinhronizacije z IdP",
"iam_link": "Povezava do IdP",
"iam_link_info": "Poštni predal je povezan s tem uporabnikom IdP. Če je bil naslov dodeljen drugemu uporabniku IdP, povezavo odstranite; ponovna povezava se vzpostavi prek e-pošte.",
"iam_missing_since": "Manjka v IdP od",
"iam_not_linked": "Še ni povezano",
"iam_unlink": "Odstrani povezavo"
}, },
"footer": { "footer": {
"restart_container_info": "<b>Pomembno:</b> Eleganten ponovni zagon lahko traja nekaj časa, zato počakajte, da se konča.", "restart_container_info": "<b>Pomembno:</b> Eleganten ponovni zagon lahko traja nekaj časa, zato počakajte, da se konča.",
@@ -896,7 +1043,7 @@
"mailbox_defaults": "Privzete nastavitve", "mailbox_defaults": "Privzete nastavitve",
"mailbox_defquota": "Privzeta velikost poštnega nabiralnika", "mailbox_defquota": "Privzeta velikost poštnega nabiralnika",
"mailbox_templates": "Predloge poštnih nabiralnikov", "mailbox_templates": "Predloge poštnih nabiralnikov",
"mailbox_quota": "Največja velikost poštnega nabiralnika", "mailbox_quota": "Največja velikost poštnega predala",
"mailboxes": "Poštni nabiralniki", "mailboxes": "Poštni nabiralniki",
"max_aliases": "Največje število vzdevkov", "max_aliases": "Največje število vzdevkov",
"max_mailboxes": "Največje možno število poštnih predalov", "max_mailboxes": "Največje možno število poštnih predalov",
@@ -971,7 +1118,9 @@
"sieve_info": "Na uporabnika lahko shranite več filtrov, vendar je lahko hkrati aktiven le en predfilter in en postfilter.<br>\nVsak filter bo obdelan v opisanem vrstnem redu. Niti neuspešen skript niti izdan ukaz »keep;« ne bosta ustavila obdelave nadaljnjih skript. Spremembe globalnih skriptov sita bodo sprožile ponovni zagon Dovecota.<br><br>Globalni predfilter sita &#8226; Predfilter &#8226; Uporabniški skripti &#8226; Postfilter &#8226; Globalni postfilter sita", "sieve_info": "Na uporabnika lahko shranite več filtrov, vendar je lahko hkrati aktiven le en predfilter in en postfilter.<br>\nVsak filter bo obdelan v opisanem vrstnem redu. Niti neuspešen skript niti izdan ukaz »keep;« ne bosta ustavila obdelave nadaljnjih skript. Spremembe globalnih skriptov sita bodo sprožile ponovni zagon Dovecota.<br><br>Globalni predfilter sita &#8226; Predfilter &#8226; Uporabniški skripti &#8226; Postfilter &#8226; Globalni postfilter sita",
"tls_policy_maps_info": "Ta preslikava pravilnikov preglasi pravila odhodnega prenosa TLS neodvisno od uporabnikovih nastavitev pravilnikov TLS.<br>\n Za več informacij preverite <a href=\"http://www.postfix.org/postconf.5.html#smtp_tls_policy_maps\" target=\"_blank\">dokumentacijo »smtp_tls_policy_maps«</a>.", "tls_policy_maps_info": "Ta preslikava pravilnikov preglasi pravila odhodnega prenosa TLS neodvisno od uporabnikovih nastavitev pravilnikov TLS.<br>\n Za več informacij preverite <a href=\"http://www.postfix.org/postconf.5.html#smtp_tls_policy_maps\" target=\"_blank\">dokumentacijo »smtp_tls_policy_maps«</a>.",
"internal": "Notranje", "internal": "Notranje",
"force_tfa": "TFA" "force_tfa": "TFA",
"shared_mailbox": "Skupni poštni predal",
"shared_mailbox_info": "Nima lastne prijave (IMAP, SMTP, SOGo, ActiveSync, gesla za aplikacije, uporabniški vmesnik mailcow). Prejema e-pošto, člani skupin pa do nje dostopajo prek deljenih map. Geslo ni potrebno."
}, },
"fido2": { "fido2": {
"known_ids": "Znani ID-ji", "known_ids": "Znani ID-ji",
@@ -1172,7 +1321,21 @@
"item_released": "Izdan je bil element %s", "item_released": "Izdan je bil element %s",
"saved_settings": "Shranjene nastavitve", "saved_settings": "Shranjene nastavitve",
"learned_ham": "Uspešno naučen ID %s kot zaželjen", "learned_ham": "Uspešno naučen ID %s kot zaželjen",
"ui_theme_modified": "Tema je bila uspešno shranjena" "ui_theme_modified": "Tema je bila uspešno shranjena",
"api_key_added": "Ključ API %s je bil dodan",
"api_key_deleted": "Ključ API %s je bil izbrisan",
"api_key_modified": "Spremembe ključa API %s so bile shranjene",
"group_added": "Skupina %s je bila dodana",
"group_modified": "Spremembe skupine %s so bile shranjene",
"group_removed": "Skupina %s je bila odstranjena",
"iam_link_removed": "Povezava IdP za %s je bila odstranjena",
"iam_sync_requested": "Postopek sinhronizacije je v čakalni vrsti; začel se bo v eni minuti.",
"imapsync_source_added": "Vir sinhronizacije %s je bil dodan",
"imapsync_source_modified": "Vir sinhronizacije %s je bil shranjen",
"imapsync_source_deleted": "Vir sinhronizacije %s je bil izbrisan",
"imapsync_source_token_refreshed": "Žeton OAuth za %s je bil osvežen",
"max_parallel_saved": "Nastavitve opravila sinhronizacije so shranjene",
"imapsync_run_next_done": "%s opravilo(-a) za sinhronizacijo premaknjeno(-a) na začetek čakalne vrste"
}, },
"start": { "start": {
"imap_smtp_server_auth_info": "Prosimo, uporabite svoj celoten e-poštni naslov in mehanizem za preverjanje pristnosti PLAIN.<br>\nVaši podatki za prijavo bodo šifrirani z obveznim šifriranjem na strani strežnika.", "imap_smtp_server_auth_info": "Prosimo, uporabite svoj celoten e-poštni naslov in mehanizem za preverjanje pristnosti PLAIN.<br>\nVaši podatki za prijavo bodo šifrirani z obveznim šifriranjem na strani strežnika.",
@@ -1209,7 +1372,8 @@
"force_tfa_info": "Uporabnik bo moral pred dostopom do nadzorne plošče nastaviti dvofaktorsko overjanje.", "force_tfa_info": "Uporabnik bo moral pred dostopom do nadzorne plošče nastaviti dvofaktorsko overjanje.",
"setup_title": "Zahtevana je dvofaktorska avtentikacija", "setup_title": "Zahtevana je dvofaktorska avtentikacija",
"setup_required": "Vaš račun zahteva dvofaktorsko overjanje. Za nadaljevanje nastavite metodo dvofaktorske overitve.", "setup_required": "Vaš račun zahteva dvofaktorsko overjanje. Za nadaljevanje nastavite metodo dvofaktorske overitve.",
"cancel_setup": "Prekliči in se odjavi" "cancel_setup": "Prekliči in se odjavi",
"webauthn_registration_failed": "Registracija WebAuthn ni uspela. Verodajnice ni bilo mogoče preveriti; poskusite znova."
}, },
"ratelimit": { "ratelimit": {
"disabled": "Onemogočeno", "disabled": "Onemogočeno",
@@ -1247,7 +1411,103 @@
"timeout1": "Časovna omejitev za povezavo do oddaljenega gostitelja", "timeout1": "Časovna omejitev za povezavo do oddaljenega gostitelja",
"timeout2": "Časovna omejitev za povezavo do lokalnega gostitelja", "timeout2": "Časovna omejitev za povezavo do lokalnega gostitelja",
"maxbytespersecond": "Največ bajtov na sekundo <br><small>(0 = neomejeno)</small>", "maxbytespersecond": "Največ bajtov na sekundo <br><small>(0 = neomejeno)</small>",
"custom_params": "Parametri po meri" "custom_params": "Parametri po meri",
"sources_panel": "Viri za sinhronizacijo",
"sources_hint": "Viri sinhronizacije določajo strežnike IMAP (in način njihove overitve), ki jih je mogoče ponovno uporabiti pri opravilih sinhronizacije. Vsak vir določite enkrat, nato pa ga pri ustvarjanju opravil sinhronizacije izberite s spustnega seznama.",
"source_add": "Dodaj vir",
"source": "Vir",
"source_name": "Ime",
"source_description": "Opis",
"source_scope": "Vidljivost",
"source_scope_all": "Vsi uporabniki",
"source_scope_domain": "Specifične domene",
"source_scope_user": "Specifični uporabniki",
"source_domains": "Domene",
"source_users": "Uporabniki",
"source_select": "Izberi vir",
"source_auth_type": "Overjanje",
"source_oauth_block": "Konfiguracija OAuth2",
"source_token_status": "Žeton veljaven do",
"source_token_error": "Napaka pri zadnji osvežitvi",
"source_refresh_now": "Osveži žeton zdaj",
"source_secret_unchanged_hint": "Pustite prazno, da ohranite shranjeno skrivnost.",
"source_oauth_flow": "Postopek OAuth2",
"source_oauth_flow_app": "Aplikacija (poverilnice odjemalca)",
"source_oauth_flow_user": "Prijava uporabnika (koda za avtorizacijo)",
"source_flow_badge_app": "Poverilnice stranke",
"source_flow_badge_user": "Prijava uporabnika",
"token_state_issued": "Žeton izdan",
"token_state_pending": "Žeton v čakanju",
"token_state_failed": "Žeton ni uspel",
"source_authorize_endpoint": "Avtorizacija končne točke",
"source_userinfo_endpoint": "Končna točka za podatke o uporabniku",
"source_redirect_uri": "URI za preusmeritev",
"source_redirect_uri_hint": "Registrirajte ta URI v aplikaciji ponudnika (npr. Azure). Prijava prek ponudnika deluje le, če se mailcow odpre prek tega imena gostitelja.",
"syncjob_oauth_connect": "Prijavite se s ponudnikom",
"syncjob_oauth_connected": "Povezano",
"syncjob_OAUTH_TOKEN_NOT_READY": "Žeton OAuth ni pripravljen (znova se prijavite ali počakajte na osvežitev žetona)",
"custom_params_hint": "V vsako vrstico vnesite eno možnost za imapsync. Sprejete so le možnosti s seznama dovoljenih; vrednost lahko vsebuje poljubne znake (presledke, regularne izraze itd.) in se posreduje kot en sam argument.",
"custom_param_option": "Možnost",
"custom_param_value": "Vrednost",
"custom_param_no_value": "vrednost ni potrebna",
"custom_param_add": "Dodaj parameter",
"prio": "Prednostna naloga",
"prio_hint": "Opravila z višjo prioriteto se izvedejo prva. Znotraj iste prioritete imajo prednost opravila, ki še nikoli niso bila izvedena, sledijo jim tista, ki so bila izvedena najmanj nedavno (0 = običajno).",
"oauth_popup_title": "Prijavite se s ponudnikom",
"oauth_popup_success": "Povezano. To okno lahko zaprete.",
"oauth_popup_failed": "Prijava ni uspela. To okno lahko zaprete.",
"oauth_error_access_denied": "Nimate dovoljenja za upravljanje opravil sinhronizacije",
"oauth_error_mailbox_denied": "Ni dostopa do izbranega lokalnega poštnega predala",
"oauth_error_source_unavailable": "Vir sinhronizacije ni na voljo ali pa ni konfiguriran za prijavo prek ponudnika",
"oauth_error_provider_denied": "Ponudnik je zavrnil prijavo",
"oauth_error_invalid_state": "Seja za prijavo je potekla ali pa ni veljavna; poskusite znova",
"oauth_error_token_failed": "Ponudnik ni izdal žetona (preverite ID odjemalca, skrivnost in URI za preusmeritev)",
"oauth_error_no_identity": "Ponudnik ni vrnil e-poštnega naslova za prijavljeni račun",
"user2_label": "Lokalni poštni predal (cilj)",
"user1_label": "Uporabniško ime na oddaljeni strani (vir)",
"password1_label": "Geslo za oddaljeni dostop (vir)",
"no_sources": "Na voljo ni vira za sinhronizacijo. Najprej dodajte vir za sinhronizacijo.",
"source_list_error": "Virov za sinhronizacijo ni bilo mogoče naložiti",
"source_not_visible": "(ni vidno)",
"oauth_waiting": "Čakanje na ponudnika…",
"oauth_popup_blocked": "Okno za prijavo je bilo blokirano. Za to spletno mesto omogočite pojavna okna in poskusite znova.",
"oauth_select_mailbox": "Najprej izberite lokalni poštni predal",
"oauth_error_unknown": "Prijava ni uspela",
"oauth_hint": "Oddaljeno uporabniško ime se pridobi iz računa, ki je bil uporabljen za prijavo pri ponudniku.",
"token_state_none": "Žeton v čakanju",
"custom_params_legacy": "Podedovani parametri (niso bili preneseni)",
"custom_params_legacy_hint": "Te parametre po meri iz prvotnega opravila sinhronizacije ni bilo mogoče pretvoriti, zato so prezrti. Možnosti, ki jih še vedno potrebujete, dodajte z zgornjim urejevalnikom parametrov.",
"custom_params_legacy_badge": "Podedovani parametri",
"custom_param_remove": "Odstrani parameter",
"never_run": "Nikoli",
"status_inactive": "Neaktivno",
"source_server": "Izvorni strežnik",
"id": "ID",
"source_created_by": "Ustvaril/a",
"source_oauth_token_endpoint": "Končna točka za žetone",
"source_oauth_client_id": "ID odjemalca",
"source_oauth_client_secret": "Skrivnost odjemalca",
"source_oauth_scope": "Obseg",
"source_oauth_extra_params": "Dodatni parametri (JSON)",
"source_oauth_extra_params_hint": "Izbirni objekt JSON. Parametri prompt, access_type, login_hint, domain_hint in hd se pošljejo ob prijavi pri ponudniku, vsi ostali pa ob zahtevku za žeton, npr. {\"vir\": \"https://provider.example.com\"}",
"source_presets": "Prednastavitve",
"source_presets_hint": "Izpolni nastavitve strežnika ponudnika. Številni ponudniki (npr. Gmail, iCloud, Yahoo) zahtevajo uporabo gesla za aplikacijo ali omogočanje dostopa prek protokola IMAP v nastavitvah poštnega predala.",
"source_tenant": "Najemnik Microsoft 365",
"source_tenant_hint": "ID imenika (najemnika) ali domena najemnika, npr. contoso.onmicrosoft.com. Vstavi se v končne točke.",
"source_scope_cc_hint": "Viri, ki uporabljajo tok poverilnic odjemalca, so vedno zasebni za svojega ustvarjalca.",
"source_readonly_hint": "Ta vir sinhronizacije je v skupni rabi z vami in ga je mogoče le ogledati.",
"source_verify_cert": "Preverite potrdilo strežnika",
"source_verify_cert_hint": "Za SSL in STARTTLS. Izklopite za strežnike s samopodpisanim ali poteklim potrdilom oziroma s potrdilom, ki se ne ujema z gostiteljem.",
"source_verify_cert_off": "Potrdilo strežnika ni preverjeno",
"copy": "Kopiraj",
"copied": "Kopirano v odložišče",
"source_view": "Prikaži",
"custom_params_options_error": "Seznama dovoljenih možnosti za imapsync ni bilo mogoče naložiti",
"source_missing": "Temu opravilu ni dodeljen vir za sinhronizacijo. Prosimo, izberite vir.",
"oauth_window_closed": "Okno za prijavo se je zaprlo, še preden je prispel rezultat. Če ste postopek prijave zaključili, ponovno naložite stran ali poskusite znova.",
"custom_params_legacy_badge_title": "Stare parametre po meri, ki jih ni bilo mogoče pretvoriti, se prezre. Za podrobnosti odprite stran za urejanje.",
"status_waiting": "Čakanje",
"status_running": "V teku"
}, },
"user": { "user": {
"open_webmail_sso": "Spletna pošta", "open_webmail_sso": "Spletna pošta",
@@ -1424,6 +1684,62 @@
"no_active_admin": "Zadnjega aktivnega skrbnika ni mogoče deaktivirati", "no_active_admin": "Zadnjega aktivnega skrbnika ni mogoče deaktivirati",
"quota_exceeded_scope": "Kvota domene presežena: V tem obsegu domene je mogoče ustvariti le neomejeno število poštnih predalov.", "quota_exceeded_scope": "Kvota domene presežena: V tem obsegu domene je mogoče ustvariti le neomejeno število poštnih predalov.",
"session_token": "Neveljaven žeton obrazca: Neujemanje žetonov", "session_token": "Neveljaven žeton obrazca: Neujemanje žetonov",
"session_ua": "Neveljaven žeton obrazca: Napaka pri preverjanju uporabniškega agenta" "session_ua": "Neveljaven žeton obrazca: Napaka pri preverjanju uporabniškega agenta",
"group_imap_grant_failed": "Dostopa do poštnega predala %s v sistemu Dovecot še ni bilo mogoče nastaviti; ponovni poskus bo izveden vsakih 15 minut",
"group_sogo_init_failed": "Map SOGo za %s še ni bilo mogoče ustvariti; ponovni poskus bo izveden vsakih 15 minut",
"group_subscription_failed": "Naročnina za %s ni uspela; poskus se samodejno se ponovi",
"group_template_failed": "Predloge %s ni bilo mogoče uporabiti na %s",
"group_too_many_members": "Skupina %s ima več kot %s članov. Postfix dostavi pošto na naslov, ki ima največ toliko prejemnikov."
},
"groups": {
"active": "Aktivno",
"add": "Dodaj skupino",
"address": "Skupinski naslov",
"address_hint": "Neobvezno. Pošta na ta naslov se dostavi vsem članom.",
"description": "Opis",
"domain": "Domena",
"effective_template": "Predloga iz skupin",
"grant_add": "Dodaj",
"grant_folder": "ID mape v SOGo, osebna = privzeta mapa",
"grant_owner": "Poštni nabiralnik",
"grant_state_applied": "Aktivno",
"grant_state_failed": "Neuspešno",
"grant_state_pending": "V čakanju",
"grant_subscribe": "Naroči se",
"grant_subscribe_imap_hint": "V roku ene minute naroči mape poštnega predala za vsakega člana, tako da so te vidne v e-poštnih odjemalcih. Pomembno: če se član odjavi, to stanje ostane nespremenjeno",
"grant_subscribe_sogo_hint": "Mapa se v roku ene minute doda v SOGo vsakega člana – vendar le enkrat: če jo član odstrani, ostane odstranjena.",
"group": "Skupina",
"groups": "Skupine",
"idp": "IdP",
"idp_member": "Sinhronizirano iz ponudnika identitet; spremeniti je mogoče le tam",
"idp_ref": "Skupina IdP",
"imap_grants": "Dostop do poštnega predala",
"imap_grants_hint": "Člani odprejo te poštne nabiralnike v svojem poštnem odjemalcu (mapa V skupni rabi/<poštni nabiralnik>). Branje: branje in označevanje kot prebrano. Pisanje: tudi shranjevanje, premikanje in brisanje e-pošte. Polni dostop: tudi brisanje map. Za poštne nabiralnike ekipe brez lastne prijave označite nabiralnik kot skupni nabiralnik.",
"info": "Skupine združujejo nabiralnike. Skupina ima lahko svoj naslov: vzdevek, ki samodejno dostavlja vsem članom. Člani lahko pošiljajo kot drugi naslovi, dostopajo do skupnih nabiralnikov, koledarjev in imenikov ter dobijo predlogo nabiralnika. Člani, sinhronizirani s ponudnikom identitete, so označeni z IdP.",
"internal": "Sprejemaj pošto samo od pošiljateljev iz domene",
"list_error": "Skupin ni bilo mogoče naložiti",
"managed_alias": "Upravlja skupina %s",
"members": "Člani",
"memberships": "Članstva v skupinah",
"name": "Ime",
"no_memberships": "Ni član nobene skupine",
"priority": "Prednostna naloga",
"reapply_template": "Ponovno uporabite predlogo za vse člane",
"rights_full": "Popoln dostop",
"rights_read": "Beri",
"rights_write": "Piši",
"send_as": "Pošlji kot",
"send_as_groups": "Lahko pošlje kot (prek skupin)",
"send_as_hint": "Naslovi (poštni predal ali vzdevek) ali @domena, v imenu katerih lahko člani pošiljajo sporočila – en naslov v vsaki vrstici.",
"sender_allowed": "Člani lahko pošiljajo prek naslova skupine",
"sogo_grants": "Koledarji in imeniki",
"sogo_grants_hint": "Člani dobijo dostop do mape SOGo v poštnem predalu. Z izbiro možnosti »Naroči se« (Subscribe) se mapa samodejno prikaže v njihovem vmesniku SOGo; v nasprotnem primeru se morajo nanjo naročiti sami. Na čakanju: poštni predal še ni odprl vmesnika SOGo.",
"sogo_visible": "Prikaži naslov skupine kot identiteto v SOGo",
"template": "Predloga poštnega predala",
"template_hint": "Velja za vse člane. Če je poštni predal vključen v več skupin, prevzame predlogo skupine z najvišjo prioriteto.",
"template_none": "Brez predloge",
"type_calendar": "Koledar",
"type_contacts": "Imenik",
"view": "Pogled"
} }
} }
+16 -10
View File
@@ -416,18 +416,24 @@ function recursiveBase64StrToArrayBuffer(obj) {
return navigator.credentials.create(json); return navigator.credentials.create(json);
}).then(function(cred) { }).then(function(cred) {
return { return {
id: cred.id, clientDataJSON: arrayBufferToBase64(cred.response.clientDataJSON),
rawId: arrayBufferToBase64(cred.rawId),
response: {
attestationObject: arrayBufferToBase64(cred.response.attestationObject), attestationObject: arrayBufferToBase64(cred.response.attestationObject),
clientDataJSON: arrayBufferToBase64(cred.response.clientDataJSON) key_id: keyId,
}, tfa_method: 'webauthn',
type: cred.type confirm_password: ''
}; };
}).then(function(credData) { }).then(JSON.stringify).then(function(credentialData) {
$('#setup_webauthn_register_data').val(JSON.stringify(credData)); // send the attestation to the JSON API, like the regular WebAuthn modal does,
$('#setup_webauthn_reg_form input[name=set_tfa]').val('1'); // so that the credential is parsed and stored correctly
$('#setup_webauthn_reg_form').submit(); return window.fetch('/api/v1/add/webauthn-tfa-registration', {method: 'POST', body: credentialData, cache: 'no-cache'});
}).then(function(response) {
return response.json();
}).then(function(json) {
if (json.success) {
window.location = window.location.href.split('#')[0];
} else {
throw new Error(json.msg);
}
}).catch(function(err) { }).catch(function(err) {
$('#setup_webauthn_return_code').show().text(err.message || 'Registration failed'); $('#setup_webauthn_return_code').show().text(err.message || 'Registration failed');
}); });
+24 -13
View File
@@ -18,6 +18,18 @@ if [ ! -f "${PWD}/mailcow.conf" ]; then
fi fi
fi fi
BRANCH="$(cd "${SCRIPT_DIR}" && git rev-parse --abbrev-ref HEAD)" BRANCH="$(cd "${SCRIPT_DIR}" && git rev-parse --abbrev-ref HEAD)"
UPDATE_ARGS=("$@")
SCRIPT_HASH="$(sha256sum "${SCRIPT_DIR}/update.sh" | awk '{print $1}')"
restart_update_script() {
if [[ "${MAILCOW_UPDATE_RESTARTS:-0}" -ge 3 ]]; then
echo -e "\e[31mupdate.sh keeps changing, please run it again.\e[0m"
exit 2
fi
export MAILCOW_UPDATE_RESTARTS=$(( ${MAILCOW_UPDATE_RESTARTS:-0} + 1 ))
echo -e "\e[33m$1, restarting the update script...\e[0m"
exec "${SCRIPT_DIR}/update.sh" "${UPDATE_ARGS[@]}"
}
# Check for --dev flag early to skip _modules update # Check for --dev flag early to skip _modules update
for arg in "$@"; do for arg in "$@"; do
@@ -38,9 +50,9 @@ if [ ! "$DEV" ]; then
MODULES_HASH_BEFORE="EMPTY" MODULES_HASH_BEFORE="EMPTY"
fi fi
echo -e "\e[33mFetching latest _modules from origin/${BRANCH}…\e[0m" echo -e "\e[33mFetching latest _modules and update.sh from origin/${BRANCH}…\e[0m"
git fetch origin "${BRANCH}" git fetch origin "${BRANCH}"
git checkout "origin/${BRANCH}" -- _modules git checkout "origin/${BRANCH}" -- _modules update.sh
if [[ ! -d "${MODULE_DIR}" || -z "$(ls -A "${MODULE_DIR}")" ]]; then if [[ ! -d "${MODULE_DIR}" || -z "$(ls -A "${MODULE_DIR}")" ]]; then
echo -e "\e[31mError: _modules is still missing or empty after fetch!\e[0m" echo -e "\e[31mError: _modules is still missing or empty after fetch!\e[0m"
@@ -50,10 +62,10 @@ if [ ! "$DEV" ]; then
# Calculate hash after fetch # Calculate hash after fetch
MODULES_HASH_AFTER=$(find "${MODULE_DIR}" -type f -exec sha256sum {} \; 2>/dev/null | sort | sha256sum | awk '{print $1}') MODULES_HASH_AFTER=$(find "${MODULE_DIR}" -type f -exec sha256sum {} \; 2>/dev/null | sort | sha256sum | awk '{print $1}')
# Check if modules changed # Check if modules or the script changed
if [[ "${MODULES_HASH_BEFORE}" != "${MODULES_HASH_AFTER}" ]]; then if [[ "${MODULES_HASH_BEFORE}" != "${MODULES_HASH_AFTER}" || "$(sha256sum "${SCRIPT_DIR}/update.sh" | awk '{print $1}')" != "${SCRIPT_HASH}" ]]; then
echo -e "\e[33m_modules have been updated. Please restart the update script.\e[0m" chmod +x "${SCRIPT_DIR}/update.sh"
exit 2 restart_update_script "update.sh or _modules have been updated"
fi fi
else else
echo -e "\e[33mDeveloper mode: Skipping _modules update from git\e[0m" echo -e "\e[33mDeveloper mode: Skipping _modules update from git\e[0m"
@@ -344,15 +356,12 @@ elif [ "$NEW_BRANCH" == "legacy" ] && [ "$CURRENT_BRANCH" != "legacy" ]; then
fi fi
if [ ! "$DEV" ]; then if [ ! "$DEV" ]; then
EXIT_COUNT=0
echo -e "\e[32mChecking for newer update script...\e[0m" echo -e "\e[32mChecking for newer update script...\e[0m"
SHA1_1="$(sha1sum update.sh)"
git fetch origin git fetch origin
git checkout "origin/${BRANCH}" -- update.sh git checkout "origin/${BRANCH}" -- update.sh
SHA1_2="$(sha1sum update.sh)" if [[ "$(sha256sum update.sh | awk '{print $1}')" != "${SCRIPT_HASH}" ]]; then
if [[ "${SHA1_1}" != "${SHA1_2}" ]]; then
chmod +x update.sh chmod +x update.sh
EXIT_COUNT+=1 restart_update_script "update.sh has been updated"
fi fi
fi fi
@@ -374,10 +383,12 @@ if ! $COMPOSE_COMMAND config -q; then
fi fi
echo -e "\e[32mChecking for conflicting bridges...\e[0m" echo -e "\e[32mChecking for conflicting bridges...\e[0m"
MAILCOW_BRIDGE=$($COMPOSE_COMMAND config | grep -i com.docker.network.bridge.name | cut -d':' -f2) MAILCOW_BRIDGE=$($COMPOSE_COMMAND config | grep -i com.docker.network.bridge.name | cut -d':' -f2 | tr -d "[:space:]\"'")
if [[ -n "${MAILCOW_BRIDGE}" ]]; then
while read NAT_ID; do while read NAT_ID; do
iptables -t nat -D POSTROUTING "$NAT_ID" iptables -t nat -D POSTROUTING "$NAT_ID"
done < <(iptables -L -vn -t nat --line-numbers | grep "$IPV4_NETWORK" | grep -E 'MASQUERADE.*all' | grep -v "${MAILCOW_BRIDGE}" | cut -d' ' -f1) done < <(iptables -L -vn -t nat --line-numbers | grep "$IPV4_NETWORK" | grep -E 'MASQUERADE.*all' | grep -vE "[[:space:]]!?${MAILCOW_BRIDGE}[[:space:]]" | cut -d' ' -f1)
fi
DIFF_DIRECTORY=update_diffs DIFF_DIRECTORY=update_diffs
DIFF_FILE=${DIFF_DIRECTORY}/diff_before_update_$(date +"%Y-%m-%d-%H-%M-%S") DIFF_FILE=${DIFF_DIRECTORY}/diff_before_update_$(date +"%Y-%m-%d-%H-%M-%S")