mirror of
https://github.com/mailcow/mailcow-dockerized.git
synced 2026-02-19 15:46:23 +00:00
Compare commits
138 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9a729d89bf | ||
|
|
74b4097ee0 | ||
|
|
e00d0d5f8d | ||
|
|
c5e399ebc2 | ||
|
|
cb9ca772b1 | ||
|
|
162f05ccda | ||
|
|
6c97c4f372 | ||
|
|
6d4fcacd83 | ||
|
|
1994f706c0 | ||
|
|
e34afd3fdd | ||
|
|
a6f71faf46 | ||
|
|
b26ccc2019 | ||
|
|
b1c1e403d2 | ||
|
|
8753ea2be6 | ||
|
|
9fee568082 | ||
|
|
294a406b91 | ||
|
|
8b933f1967 | ||
|
|
824a473fea | ||
|
|
7f790c5360 | ||
|
|
52431a3942 | ||
|
|
8017394e9d | ||
|
|
76194be7dd | ||
|
|
3b23afa0ff | ||
|
|
6e00d653ce | ||
|
|
b6c036496d | ||
|
|
5d7c9b20bc | ||
|
|
4b400eadb1 | ||
|
|
ab2abda8cc | ||
|
|
2fe21e9641 | ||
|
|
b7ed6982d8 | ||
|
|
fd927853cb | ||
|
|
c48f4f4ab8 | ||
|
|
a4c006828e | ||
|
|
b56291f62b | ||
|
|
0cdf7647c4 | ||
|
|
8fe1cc4961 | ||
|
|
bf050f17c4 | ||
|
|
edd85dea8d | ||
|
|
3bf90c1f73 | ||
|
|
292306b191 | ||
|
|
b3e0a66222 | ||
|
|
e994cf4d05 | ||
|
|
cc0dc2eae0 | ||
|
|
a001a0584f | ||
|
|
926af87cfb | ||
|
|
b0339372b5 | ||
|
|
e398cb91e9 | ||
|
|
6ee0303b0f | ||
|
|
68616c2d57 | ||
|
|
f8de520d29 | ||
|
|
10077ece31 | ||
|
|
c918726143 | ||
|
|
3885b07a99 | ||
|
|
fcf27d640d | ||
|
|
82fde23cc1 | ||
|
|
cbca306fc1 | ||
|
|
6a8986fe4f | ||
|
|
ff34eb12e2 | ||
|
|
fbecd60e56 | ||
|
|
c37bf0bb32 | ||
|
|
2208d7e6fb | ||
|
|
e426c3a7e7 | ||
|
|
03fccb28e9 | ||
|
|
8fbfd99dd6 | ||
|
|
7f7a869678 | ||
|
|
73257151c4 | ||
|
|
efb2572f0f | ||
|
|
66aa28b5de | ||
|
|
987a027339 | ||
|
|
eea81e21f6 | ||
|
|
a689109f44 | ||
|
|
58c0a46459 | ||
|
|
2dbe8bf4ca | ||
|
|
ef7ec06947 | ||
|
|
fc7ea7a247 | ||
|
|
9b478b3859 | ||
|
|
384e5a2e64 | ||
|
|
aadeeb0df3 | ||
|
|
f33d82ffc1 | ||
|
|
ffeeb179e1 | ||
|
|
8e2d3a6db5 | ||
|
|
70126e1f0c | ||
|
|
b9ae174a6a | ||
|
|
9715c57314 | ||
|
|
b9f8959d92 | ||
|
|
9c814cc182 | ||
|
|
cf6594220c | ||
|
|
2cf952eb36 | ||
|
|
6fc86dd7d3 | ||
|
|
bf13af9691 | ||
|
|
1af9c21a50 | ||
|
|
443941e687 | ||
|
|
527577b438 | ||
|
|
9daf2d80c0 | ||
|
|
38b0641742 | ||
|
|
f675af5bb0 | ||
|
|
533c4e7956 | ||
|
|
1b2c2c0037 | ||
|
|
97768494e1 | ||
|
|
4a052da289 | ||
|
|
18d7a55b15 | ||
|
|
9ca2fb7ccf | ||
|
|
b4e8355827 | ||
|
|
e0bde1c459 | ||
|
|
27c007ebd3 | ||
|
|
8f3ea09732 | ||
|
|
af626d98d3 | ||
|
|
34b0574e56 | ||
|
|
49d738809b | ||
|
|
2fa3a22eca | ||
|
|
dc5eb6f92e | ||
|
|
ba8902f0b1 | ||
|
|
11e9a77840 | ||
|
|
64cd7e74c5 | ||
|
|
cac65d081e | ||
|
|
e5ada994be | ||
|
|
6ba2459645 | ||
|
|
58f63aad08 | ||
|
|
8a8687a63c | ||
|
|
f7f93c360d | ||
|
|
c160e1f68e | ||
|
|
47c08ab8d2 | ||
|
|
cd83ffbaa2 | ||
|
|
e12981a821 | ||
|
|
47fd1bb894 | ||
|
|
20582b6353 | ||
|
|
c8ff5387c0 | ||
|
|
7cb138d515 | ||
|
|
3dd4c45fab | ||
|
|
549539bec9 | ||
|
|
e449cac464 | ||
|
|
62e458f39b | ||
|
|
b37caaf9e5 | ||
|
|
7660ca89ae | ||
|
|
5c851f2935 | ||
|
|
914a8204d4 | ||
|
|
02a55ce9db | ||
|
|
6dc0bdbfa3 |
12
.github/ISSUE_TEMPLATE/pr_to_nighty_template.yml
vendored
12
.github/ISSUE_TEMPLATE/pr_to_nighty_template.yml
vendored
@@ -1,13 +1,3 @@
|
||||
## :memo: Brief description
|
||||
<!-- Diff summary - START -->
|
||||
<!-- Diff summary - END -->
|
||||
|
||||
|
||||
## :computer: Commits
|
||||
<!-- Diff commits - START -->
|
||||
<!-- Diff commits - END -->
|
||||
|
||||
|
||||
## :file_folder: Modified files
|
||||
<!-- Diff files - START -->
|
||||
<!-- Diff files - END -->
|
||||
<!-- Diff files - END -->
|
||||
38
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
38
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
<!-- _Please make sure to review and check all of these items, otherwise we might refuse your PR:_ -->
|
||||
|
||||
## Contribution Guidelines
|
||||
|
||||
* [ ] I've read the [contribution guidelines](https://github.com/mailcow/mailcow-dockerized/blob/master/CONTRIBUTING.md) and wholeheartedly agree them
|
||||
|
||||
<!-- _NOTE: this tickbox is needed to fullfil on order to get your PR reviewed._ -->
|
||||
|
||||
## What does this PR include?
|
||||
|
||||
### Short Description
|
||||
|
||||
<!-- Please write a short description, what your PR does here. -->
|
||||
|
||||
### Affected Containers
|
||||
|
||||
<!-- Please list all affected Docker containers here, which you commited changes to -->
|
||||
|
||||
<!--
|
||||
|
||||
Please list them like this:
|
||||
|
||||
- container1
|
||||
- container2
|
||||
- container3
|
||||
etc.
|
||||
|
||||
-->
|
||||
|
||||
## Did you run tests?
|
||||
|
||||
### What did you tested?
|
||||
|
||||
<!-- Please write shortly, what you've tested (which components etc.). -->
|
||||
|
||||
### What were the final results? (Awaited, got)
|
||||
|
||||
<!-- Please write shortly, what your final tests results were. What did you awaited? Was the outcome the awaited one? -->
|
||||
2
.github/workflows/rebuild_backup_image.yml
vendored
2
.github/workflows/rebuild_backup_image.yml
vendored
@@ -26,7 +26,7 @@ jobs:
|
||||
password: ${{ secrets.BACKUPIMAGEBUILD_ACTION_DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v5
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
|
||||
@@ -1,33 +1,52 @@
|
||||
# Contribution Guidelines (Last modified on 18th December 2023)
|
||||
# Contribution Guidelines
|
||||
**_Last modified on 15th August 2024_**
|
||||
|
||||
First of all, thank you for wanting to provide a bugfix or a new feature for the mailcow community, it's because of your help that the project can continue to grow!
|
||||
|
||||
## Pull Requests (Last modified on 18th December 2023)
|
||||
As we want to keep mailcow's development structured we setup these Guidelines which helps you to create your issue/pull request accordingly.
|
||||
|
||||
**PLEASE NOTE, THAT WE MIGHT CLOSE ISSUES/PULL REQUESTS IF THEY DON'T FULLFIL OUR WRITTEN GUIDELINES WRITTEN INSIDE THIS DOCUMENT**. So please check this guidelines before you propose a Issue/Pull Request.
|
||||
|
||||
## Topics
|
||||
|
||||
- [Pull Requests](#pull-requests)
|
||||
- [Issue Reporting](#issue-reporting)
|
||||
- [Guidelines](#issue-reporting-guidelines)
|
||||
- [Issue Report Guide](#issue-report-guide)
|
||||
|
||||
## Pull Requests
|
||||
**_Last modified on 15th August 2024_**
|
||||
|
||||
However, please note the following regarding pull requests:
|
||||
|
||||
1. **ALWAYS** create your PR using the staging branch of your locally cloned mailcow instance, as the pull request will end up in said staging branch of mailcow once approved. Ideally, you should simply create a new branch for your pull request that is named after the type of your PR (e.g. `feat/` for function updates or `fix/` for bug fixes) and the actual content (e.g. `sogo-6.0.0` for an update from SOGo to version 6 or `html-escape` for a fix that includes escaping HTML in mailcow).
|
||||
2. Please **keep** this pull request branch **clean** and free of commits that have nothing to do with the changes you have made (e.g. commits from other users from other branches). *If you make changes to the `update.sh` script or other scripts that trigger a commit, there is usually a developer mode for clean working in this case.
|
||||
3. **Test your changes before you commit them as a pull request.** <ins>If possible</ins>, write a small **test log** or demonstrate the functionality with a **screenshot or GIF**. *We will of course also test your pull request ourselves, but proof from you will save us the question of whether you have tested your own changes yourself.*
|
||||
4. Please **ALWAYS** create the actual pull request against the staging branch and **NEVER** directly against the master branch. *If you forget to do this, our moobot will remind you to switch the branch to staging.*
|
||||
5. Wait for a merge commit: It may happen that we do not accept your pull request immediately or sometimes not at all for various reasons. Please do not be disappointed if this is the case. We always endeavor to incorporate any meaningful changes from the community into the mailcow project.
|
||||
6. If you are planning larger and therefore more complex pull requests, it would be advisable to first announce this in a separate issue and then start implementing it after the idea has been accepted in order to avoid unnecessary frustration and effort!
|
||||
2. **ALWAYS** report/request issues/features in the english language, even though mailcow is a german based company. This is done to allow other GitHub users to reply to your issues/requests too which did not speak german or other languages besides english.
|
||||
3. Please **keep** this pull request branch **clean** and free of commits that have nothing to do with the changes you have made (e.g. commits from other users from other branches). *If you make changes to the `update.sh` script or other scripts that trigger a commit, there is usually a developer mode for clean working in this case.*
|
||||
4. **Test your changes before you commit them as a pull request.** <ins>If possible</ins>, write a small **test log** or demonstrate the functionality with a **screenshot or GIF**. *We will of course also test your pull request ourselves, but proof from you will save us the question of whether you have tested your own changes yourself.*
|
||||
5. **Please use** the pull request template we provide once creating a pull request. *HINT: During editing you encounter comments which looks like: `<!-- CONTENT -->`. These can be removed or kept, as they will not rendered later on GitHub! Please only create actual content without the said comments.*
|
||||
6. Please **ALWAYS** create the actual pull request against the staging branch and **NEVER** directly against the master branch. *If you forget to do this, our moobot will remind you to switch the branch to staging.*
|
||||
7. Wait for a merge commit: It may happen that we do not accept your pull request immediately or sometimes not at all for various reasons. Please do not be disappointed if this is the case. We always endeavor to incorporate any meaningful changes from the community into the mailcow project.
|
||||
8. If you are planning larger and therefore more complex pull requests, it would be advisable to first announce this in a separate issue and then start implementing it after the idea has been accepted in order to avoid unnecessary frustration and effort!
|
||||
|
||||
---
|
||||
|
||||
## Issue Reporting (Last modified on 18th December 2023)
|
||||
## Issue Reporting
|
||||
**_Last modified on 15th August 2024_**
|
||||
|
||||
If you plan to report a issue within mailcow please read and understand the following rules:
|
||||
|
||||
### Issue Reporting Guidelines
|
||||
|
||||
1. **ONLY** use the issue tracker for bug reports or improvement requests and NOT for support questions. For support questions you can either contact the [mailcow community on Telegram](https://docs.mailcow.email/#community-support-and-chat) or the mailcow team directly in exchange for a [support fee](https://docs.mailcow.email/#commercial-support).
|
||||
2. **ONLY** report an error if you have the **necessary know-how (at least the basics)** for the administration of an e-mail server and the usage of Docker. mailcow is a complex and fully-fledged e-mail server including groupware components on a Docker basement and it requires a bit of technical know-how for debugging and operating.
|
||||
3. **ONLY** report bugs that are contained in the latest mailcow release series. *The definition of the latest release series includes the last major patch (e.g. 2023-12) and all minor patches (revisions) below it (e.g. 2023-12a, b, c etc.).* New issue reports published starting from January 1, 2024 must meet this criterion, as versions below the latest releases are no longer supported by us.
|
||||
4. When reporting a problem, please be as detailed as possible and include even the smallest changes to your mailcow installation. Simply fill out the corresponding bug report form in detail and accurately to minimize possible questions.
|
||||
5. **Before you open an issue/feature request**, please first check whether a similar request already exists in the mailcow tracker on GitHub. If so, please include yourself in this request.
|
||||
6. When you create a issue/feature request: Please note that the creation does <ins>**not guarantee an instant implementation or fix by the mailcow team or the community**</ins>.
|
||||
7. Please **ALWAYS** anonymize any sensitive information in your bug report or feature request before submitting it.
|
||||
3. **ALWAYS** report/request issues/features in the english language, even though mailcow is a german based company. This is done to allow other GitHub users to reply to your issues/requests too which did not speak german or other languages besides english.
|
||||
4. **ONLY** report bugs that are contained in the latest mailcow release series. *The definition of the latest release series includes the last major patch (e.g. 2023-12) and all minor patches (revisions) below it (e.g. 2023-12a, b, c etc.).* New issue reports published starting from January 1, 2024 must meet this criterion, as versions below the latest releases are no longer supported by us.
|
||||
5. When reporting a problem, please be as detailed as possible and include even the smallest changes to your mailcow installation. Simply fill out the corresponding bug report form in detail and accurately to minimize possible questions.
|
||||
6. **Before you open an issue/feature request**, please first check whether a similar request already exists in the mailcow tracker on GitHub. If so, please include yourself in this request.
|
||||
7. When you create a issue/feature request: Please note that the creation does <ins>**not guarantee an instant implementation or fix by the mailcow team or the community**</ins>.
|
||||
8. Please **ALWAYS** anonymize any sensitive information in your bug report or feature request before submitting it.
|
||||
|
||||
### Quick guide to reporting problems:
|
||||
### Issue Report Guide
|
||||
1. Read your logs; follow them to see what the reason for your problem is.
|
||||
2. Follow the leads given to you in your logfiles and start investigating.
|
||||
3. Restarting the troubled service or the whole stack to see if the problem persists.
|
||||
@@ -36,4 +55,4 @@ If you plan to report a issue within mailcow please read and understand the foll
|
||||
6. [Create an issue](https://github.com/mailcow/mailcow-dockerized/issues/new/choose) over at our GitHub repository if you think your problem might be a bug or a missing feature you badly need. But please make sure, that you include **all the logs** and a full description to your problem.
|
||||
7. Ask your questions in our community-driven [support channels](https://docs.mailcow.email/#community-support-and-chat).
|
||||
|
||||
## When creating an issue/feature request or a pull request, you will be asked to confirm these guidelines.
|
||||
## When creating an issue/feature request or a pull request, you will be asked to confirm these guidelines.
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
FROM alpine:3.18
|
||||
FROM alpine:3.20
|
||||
|
||||
LABEL maintainer = "The Infrastructure Company GmbH <info@servercow.de>"
|
||||
|
||||
LABEL maintainer "The Infrastructure Company GmbH <info@servercow.de>"
|
||||
|
||||
ARG PIP_BREAK_SYSTEM_PACKAGES=1
|
||||
RUN apk upgrade --no-cache \
|
||||
&& apk add --update --no-cache \
|
||||
bash \
|
||||
@@ -15,9 +15,7 @@ RUN apk upgrade --no-cache \
|
||||
tini \
|
||||
tzdata \
|
||||
python3 \
|
||||
py3-pip \
|
||||
&& pip3 install --upgrade pip \
|
||||
&& pip3 install acme-tiny
|
||||
acme-tiny --repository=http://dl-cdn.alpinelinux.org/alpine/edge/community/
|
||||
|
||||
COPY acme.sh /srv/acme.sh
|
||||
COPY functions.sh /srv/functions.sh
|
||||
|
||||
@@ -33,6 +33,10 @@ if [[ "${ONLY_MAILCOW_HOSTNAME}" =~ ^([yY][eE][sS]|[yY])+$ ]]; then
|
||||
ONLY_MAILCOW_HOSTNAME=y
|
||||
fi
|
||||
|
||||
if [[ "${AUTODISCOVER_SAN}" =~ ^([yY][eE][sS]|[yY])+$ ]]; then
|
||||
AUTODISCOVER_SAN=y
|
||||
fi
|
||||
|
||||
# Request individual certificate for every domain
|
||||
if [[ "${ENABLE_SSL_SNI}" =~ ^([yY][eE][sS]|[yY])+$ ]]; then
|
||||
ENABLE_SSL_SNI=y
|
||||
@@ -119,7 +123,7 @@ done
|
||||
log_f "Database OK"
|
||||
|
||||
log_f "Waiting for Nginx..."
|
||||
until $(curl --output /dev/null --silent --head --fail http://nginx:8081); do
|
||||
until $(curl --output /dev/null --silent --head --fail http://nginx.${COMPOSE_PROJECT_NAME}_mailcow-network:8081); do
|
||||
sleep 2
|
||||
done
|
||||
log_f "Nginx OK"
|
||||
@@ -133,7 +137,7 @@ log_f "Resolver OK"
|
||||
# Waiting for domain table
|
||||
log_f "Waiting for domain table..."
|
||||
while [[ -z ${DOMAIN_TABLE} ]]; do
|
||||
curl --silent http://nginx/ >/dev/null 2>&1
|
||||
curl --silent http://nginx.${COMPOSE_PROJECT_NAME}_mailcow-network/ >/dev/null 2>&1
|
||||
DOMAIN_TABLE=$(mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "SHOW TABLES LIKE 'domain'" -Bs)
|
||||
[[ -z ${DOMAIN_TABLE} ]] && sleep 10
|
||||
done
|
||||
@@ -211,7 +215,11 @@ while true; do
|
||||
ADDITIONAL_SAN_ARR+=($i)
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ ${AUTODISCOVER_SAN} == "y" ]]; then
|
||||
# Fetch certs for autoconfig and autodiscover subdomains
|
||||
ADDITIONAL_WC_ARR+=('autodiscover' 'autoconfig')
|
||||
fi
|
||||
|
||||
if [[ ${SKIP_IP_CHECK} != "y" ]]; then
|
||||
# Start IP detection
|
||||
|
||||
@@ -2,32 +2,32 @@
|
||||
|
||||
# Reading container IDs
|
||||
# Wrapping as array to ensure trimmed content when calling $NGINX etc.
|
||||
NGINX=($(curl --silent --insecure https://dockerapi/containers/json | jq -r ".[] | {name: .Config.Labels[\"com.docker.compose.service\"], project: .Config.Labels[\"com.docker.compose.project\"], id: .Id}" | jq -rc "select( .name | tostring | contains(\"nginx-mailcow\")) | select( .project | tostring | contains(\"${COMPOSE_PROJECT_NAME,,}\")) | .id" | tr "\n" " "))
|
||||
DOVECOT=($(curl --silent --insecure https://dockerapi/containers/json | jq -r ".[] | {name: .Config.Labels[\"com.docker.compose.service\"], project: .Config.Labels[\"com.docker.compose.project\"], id: .Id}" | jq -rc "select( .name | tostring | contains(\"dovecot-mailcow\")) | select( .project | tostring | contains(\"${COMPOSE_PROJECT_NAME,,}\")) | .id" | tr "\n" " "))
|
||||
POSTFIX=($(curl --silent --insecure https://dockerapi/containers/json | jq -r ".[] | {name: .Config.Labels[\"com.docker.compose.service\"], project: .Config.Labels[\"com.docker.compose.project\"], id: .Id}" | jq -rc "select( .name | tostring | contains(\"postfix-mailcow\")) | select( .project | tostring | contains(\"${COMPOSE_PROJECT_NAME,,}\")) | .id" | tr "\n" " "))
|
||||
NGINX=($(curl --silent --insecure https://dockerapi.${COMPOSE_PROJECT_NAME}_mailcow-network/containers/json | jq -r ".[] | {name: .Config.Labels[\"com.docker.compose.service\"], project: .Config.Labels[\"com.docker.compose.project\"], id: .Id}" | jq -rc "select( .name | tostring | contains(\"nginx-mailcow\")) | select( .project | tostring | contains(\"${COMPOSE_PROJECT_NAME,,}\")) | .id" | tr "\n" " "))
|
||||
DOVECOT=($(curl --silent --insecure https://dockerapi.${COMPOSE_PROJECT_NAME}_mailcow-network/containers/json | jq -r ".[] | {name: .Config.Labels[\"com.docker.compose.service\"], project: .Config.Labels[\"com.docker.compose.project\"], id: .Id}" | jq -rc "select( .name | tostring | contains(\"dovecot-mailcow\")) | select( .project | tostring | contains(\"${COMPOSE_PROJECT_NAME,,}\")) | .id" | tr "\n" " "))
|
||||
POSTFIX=($(curl --silent --insecure https://dockerapi.${COMPOSE_PROJECT_NAME}_mailcow-network/containers/json | jq -r ".[] | {name: .Config.Labels[\"com.docker.compose.service\"], project: .Config.Labels[\"com.docker.compose.project\"], id: .Id}" | jq -rc "select( .name | tostring | contains(\"postfix-mailcow\")) | select( .project | tostring | contains(\"${COMPOSE_PROJECT_NAME,,}\")) | .id" | tr "\n" " "))
|
||||
|
||||
reload_nginx(){
|
||||
echo "Reloading Nginx..."
|
||||
NGINX_RELOAD_RET=$(curl -X POST --insecure https://dockerapi/containers/${NGINX}/exec -d '{"cmd":"reload", "task":"nginx"}' --silent -H 'Content-type: application/json' | jq -r .type)
|
||||
NGINX_RELOAD_RET=$(curl -X POST --insecure https://dockerapi.${COMPOSE_PROJECT_NAME}_mailcow-network/containers/${NGINX}/exec -d '{"cmd":"reload", "task":"nginx"}' --silent -H 'Content-type: application/json' | jq -r .type)
|
||||
[[ ${NGINX_RELOAD_RET} != 'success' ]] && { echo "Could not reload Nginx, restarting container..."; restart_container ${NGINX} ; }
|
||||
}
|
||||
|
||||
reload_dovecot(){
|
||||
echo "Reloading Dovecot..."
|
||||
DOVECOT_RELOAD_RET=$(curl -X POST --insecure https://dockerapi/containers/${DOVECOT}/exec -d '{"cmd":"reload", "task":"dovecot"}' --silent -H 'Content-type: application/json' | jq -r .type)
|
||||
DOVECOT_RELOAD_RET=$(curl -X POST --insecure https://dockerapi.${COMPOSE_PROJECT_NAME}_mailcow-network/containers/${DOVECOT}/exec -d '{"cmd":"reload", "task":"dovecot"}' --silent -H 'Content-type: application/json' | jq -r .type)
|
||||
[[ ${DOVECOT_RELOAD_RET} != 'success' ]] && { echo "Could not reload Dovecot, restarting container..."; restart_container ${DOVECOT} ; }
|
||||
}
|
||||
|
||||
reload_postfix(){
|
||||
echo "Reloading Postfix..."
|
||||
POSTFIX_RELOAD_RET=$(curl -X POST --insecure https://dockerapi/containers/${POSTFIX}/exec -d '{"cmd":"reload", "task":"postfix"}' --silent -H 'Content-type: application/json' | jq -r .type)
|
||||
POSTFIX_RELOAD_RET=$(curl -X POST --insecure https://dockerapi.${COMPOSE_PROJECT_NAME}_mailcow-network/containers/${POSTFIX}/exec -d '{"cmd":"reload", "task":"postfix"}' --silent -H 'Content-type: application/json' | jq -r .type)
|
||||
[[ ${POSTFIX_RELOAD_RET} != 'success' ]] && { echo "Could not reload Postfix, restarting container..."; restart_container ${POSTFIX} ; }
|
||||
}
|
||||
|
||||
restart_container(){
|
||||
for container in $*; do
|
||||
echo "Restarting ${container}..."
|
||||
C_REST_OUT=$(curl -X POST --insecure https://dockerapi/containers/${container}/restart --silent | jq -r '.msg')
|
||||
C_REST_OUT=$(curl -X POST --insecure https://dockerapi.${COMPOSE_PROJECT_NAME}_mailcow-network/containers/${container}/restart --silent | jq -r '.msg')
|
||||
echo "${C_REST_OUT}"
|
||||
done
|
||||
}
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
FROM debian:bullseye-slim
|
||||
FROM debian:bookworm-slim
|
||||
|
||||
RUN apt update && apt install pigz
|
||||
@@ -1,6 +1,6 @@
|
||||
FROM alpine:3.19
|
||||
FROM alpine:3.20
|
||||
|
||||
LABEL maintainer "The Infrastructure Company GmbH <info@servercow.de>"
|
||||
LABEL maintainer = "The Infrastructure Company GmbH <info@servercow.de>"
|
||||
|
||||
RUN apk upgrade --no-cache \
|
||||
&& apk add --update --no-cache \
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
FROM alpine:3.19
|
||||
FROM alpine:3.20
|
||||
|
||||
LABEL maintainer "The Infrastructure Company GmbH <info@servercow.de>"
|
||||
LABEL maintainer = "The Infrastructure Company GmbH <info@servercow.de>"
|
||||
|
||||
ARG PIP_BREAK_SYSTEM_PACKAGES=1
|
||||
WORKDIR /app
|
||||
|
||||
@@ -358,8 +358,8 @@ class DockerApi:
|
||||
for line in cmd_response.split("\n"):
|
||||
if '$2$' in line:
|
||||
hash = line.strip()
|
||||
hash_out = re.search('\$2\$.+$', hash).group(0)
|
||||
rspamd_passphrase_hash = re.sub('[^0-9a-zA-Z\$]+', '', hash_out.rstrip())
|
||||
hash_out = re.search(r'\$2\$.+$', hash).group(0)
|
||||
rspamd_passphrase_hash = re.sub(r'[^0-9a-zA-Z\$]+', '', hash_out.rstrip())
|
||||
rspamd_password_filename = "/etc/rspamd/override.d/worker-controller-password.inc"
|
||||
cmd = '''/bin/echo 'enable_password = "%s";' > %s && cat %s''' % (rspamd_passphrase_hash, rspamd_password_filename, rspamd_password_filename)
|
||||
cmd_response = self.exec_cmd_container(container, cmd, user="_rspamd")
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
FROM alpine:3.19
|
||||
LABEL maintainer "The Infrastructure Company GmbH <info@servercow.de>"
|
||||
FROM alpine:3.20
|
||||
|
||||
LABEL maintainer="The Infrastructure Company GmbH <info@servercow.de>"
|
||||
|
||||
# renovate: datasource=github-releases depName=tianon/gosu versioning=semver-coerced extractVersion=^(?<version>.*)$
|
||||
ARG GOSU_VERSION=1.16
|
||||
|
||||
ENV LANG C.UTF-8
|
||||
ENV LC_ALL C.UTF-8
|
||||
ENV LANG=C.UTF-8
|
||||
ENV LC_ALL=C.UTF-8
|
||||
|
||||
# Add groups and users before installing Dovecot to not break compatibility
|
||||
RUN addgroup -g 5000 vmail \
|
||||
@@ -24,6 +25,7 @@ RUN addgroup -g 5000 vmail \
|
||||
envsubst \
|
||||
ca-certificates \
|
||||
curl \
|
||||
coreutils \
|
||||
jq \
|
||||
lua \
|
||||
lua-cjson \
|
||||
@@ -62,7 +64,7 @@ RUN addgroup -g 5000 vmail \
|
||||
perl-package-stash-xs \
|
||||
perl-par-packer \
|
||||
perl-parse-recdescent \
|
||||
perl-lockfile-simple --repository=http://dl-cdn.alpinelinux.org/alpine/edge/community/ \
|
||||
perl-lockfile-simple \
|
||||
libproc \
|
||||
perl-readonly \
|
||||
perl-regexp-common \
|
||||
@@ -104,13 +106,12 @@ RUN addgroup -g 5000 vmail \
|
||||
dovecot-pigeonhole-plugin \
|
||||
dovecot-pop3d \
|
||||
dovecot-fts-solr \
|
||||
dovecot-fts-flatcurve \
|
||||
&& arch=$(arch | sed s/aarch64/arm64/ | sed s/x86_64/amd64/) \
|
||||
&& wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$arch" \
|
||||
&& chmod +x /usr/local/bin/gosu \
|
||||
&& gosu nobody true
|
||||
|
||||
# RUN cpan LockFile::Simple
|
||||
|
||||
COPY trim_logs.sh /usr/local/bin/trim_logs.sh
|
||||
COPY clean_q_aged.sh /usr/local/bin/clean_q_aged.sh
|
||||
COPY syslog-ng.conf /etc/syslog-ng/syslog-ng.conf
|
||||
@@ -129,6 +130,7 @@ COPY stop-supervisor.sh /usr/local/sbin/stop-supervisor.sh
|
||||
COPY quarantine_notify.py /usr/local/bin/quarantine_notify.py
|
||||
COPY quota_notify.py /usr/local/bin/quota_notify.py
|
||||
COPY repl_health.sh /usr/local/bin/repl_health.sh
|
||||
COPY optimize-fts.sh /usr/local/bin/optimize-fts.sh
|
||||
|
||||
ENTRYPOINT ["/docker-entrypoint.sh"]
|
||||
CMD exec /usr/bin/supervisord -c /etc/supervisor/supervisord.conf
|
||||
CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/supervisord.conf"]
|
||||
|
||||
@@ -29,6 +29,7 @@ ${REDIS_CMDLINE} SET DOVECOT_REPL_HEALTH 1 > /dev/null
|
||||
# Create missing directories
|
||||
[[ ! -d /etc/dovecot/sql/ ]] && mkdir -p /etc/dovecot/sql/
|
||||
[[ ! -d /etc/dovecot/lua/ ]] && mkdir -p /etc/dovecot/lua/
|
||||
[[ ! -d /etc/dovecot/conf.d/ ]] && mkdir -p /etc/dovecot/conf.d/
|
||||
[[ ! -d /var/vmail/_garbage ]] && mkdir -p /var/vmail/_garbage
|
||||
[[ ! -d /var/vmail/sieve ]] && mkdir -p /var/vmail/sieve
|
||||
[[ ! -d /etc/sogo ]] && mkdir -p /etc/sogo
|
||||
@@ -109,7 +110,14 @@ EOF
|
||||
|
||||
echo -n ${ACL_ANYONE} > /etc/dovecot/acl_anyone
|
||||
|
||||
if [[ "${SKIP_SOLR}" =~ ^([yY][eE][sS]|[yY])+$ ]]; then
|
||||
if [[ "${FLATCURVE_EXPERIMENTAL}" =~ ^([yY][eE][sS]|[yY]) ]]; then
|
||||
echo -e "\e[33mActivating Flatcurve as FTS Backend...\e[0m"
|
||||
echo -e "\e[33mDepending on your previous setup a full reindex might be needed... \e[0m"
|
||||
echo -e "\e[34mVisit https://docs.mailcow.email/manual-guides/Dovecot/u_e-dovecot-fts/#fts-related-dovecot-commands to learn how to reindex\e[0m"
|
||||
echo -n 'quota acl zlib mail_crypt mail_crypt_acl mail_log notify fts fts_flatcurve listescape replication' > /etc/dovecot/mail_plugins
|
||||
echo -n 'quota imap_quota imap_acl acl zlib imap_zlib imap_sieve mail_crypt mail_crypt_acl notify mail_log fts fts_flatcurve listescape replication' > /etc/dovecot/mail_plugins_imap
|
||||
echo -n 'quota sieve acl zlib mail_crypt mail_crypt_acl fts fts_flatcurve notify listescape replication' > /etc/dovecot/mail_plugins_lmtp
|
||||
elif [[ "${SKIP_SOLR}" =~ ^([yY][eE][sS]|[yY])+$ ]]; then
|
||||
echo -n 'quota acl zlib mail_crypt mail_crypt_acl mail_log notify listescape replication' > /etc/dovecot/mail_plugins
|
||||
echo -n 'quota imap_quota imap_acl acl zlib imap_zlib imap_sieve mail_crypt mail_crypt_acl notify listescape replication mail_log' > /etc/dovecot/mail_plugins_imap
|
||||
echo -n 'quota sieve acl zlib mail_crypt mail_crypt_acl notify listescape replication' > /etc/dovecot/mail_plugins_lmtp
|
||||
@@ -239,6 +247,51 @@ function script_deinit()
|
||||
end
|
||||
EOF
|
||||
|
||||
# Temporarily set FTS depending on user choice inside mailcow.conf. Will be removed as soon as Solr is dropped
|
||||
if [[ "${FLATCURVE_EXPERIMENTAL}" =~ ^([yY][eE][sS]|[yY])$ ]]; then
|
||||
cat <<EOF > /etc/dovecot/conf.d/fts.conf
|
||||
# Autogenerated by mailcow
|
||||
plugin {
|
||||
fts_autoindex = yes
|
||||
fts_autoindex_exclude = \Junk
|
||||
fts_autoindex_exclude2 = \Trash
|
||||
fts = flatcurve
|
||||
|
||||
# Maximum term length can be set via the 'maxlen' argument (maxlen is
|
||||
# specified in bytes, not number of UTF-8 characters)
|
||||
fts_tokenizer_email_address = maxlen=100
|
||||
fts_tokenizer_generic = algorithm=simple maxlen=30
|
||||
|
||||
# These are not flatcurve settings, but required for Dovecot FTS. See
|
||||
# Dovecot FTS Configuration link above for further information.
|
||||
fts_languages = en es de
|
||||
fts_tokenizers = generic email-address
|
||||
|
||||
# OPTIONAL: Recommended default FTS core configuration
|
||||
fts_filters = normalizer-icu snowball stopwords
|
||||
fts_filters_en = lowercase snowball english-possessive stopwords
|
||||
}
|
||||
EOF
|
||||
elif [[ ! "${SKIP_SOLR}" =~ ^([yY][eE][sS]|[yY])$ ]]; then
|
||||
cat <<EOF > /etc/dovecot/conf.d/fts.conf
|
||||
# Autogenerated by mailcow
|
||||
plugin {
|
||||
fts = solr
|
||||
fts_autoindex = yes
|
||||
fts_autoindex_exclude = \Junk
|
||||
fts_autoindex_exclude2 = \Trash
|
||||
fts_solr = url=http://solr:8983/solr/dovecot-fts/
|
||||
|
||||
fts_tokenizers = generic email-address
|
||||
fts_tokenizer_generic = algorithm=simple
|
||||
|
||||
fts_filters = normalizer-icu snowball stopwords
|
||||
fts_filters_en = lowercase snowball english-possessive stopwords
|
||||
}
|
||||
EOF
|
||||
fi
|
||||
|
||||
|
||||
# Replace patterns in app-passdb.lua
|
||||
sed -i "s/__DBUSER__/${DBUSER}/g" /etc/dovecot/lua/passwd-verify.lua
|
||||
sed -i "s/__DBPASS__/${DBPASS}/g" /etc/dovecot/lua/passwd-verify.lua
|
||||
@@ -343,7 +396,6 @@ mail_replica = tcp:${MAILCOW_REPLICA_IP}:${DOVEADM_REPLICA_PORT}
|
||||
EOF
|
||||
fi
|
||||
|
||||
|
||||
# 401 is user dovecot
|
||||
if [[ ! -s /mail_crypt/ecprivkey.pem || ! -s /mail_crypt/ecpubkey.pem ]]; then
|
||||
openssl ecparam -name prime256v1 -genkey | openssl pkey -out /mail_crypt/ecprivkey.pem
|
||||
@@ -359,14 +411,6 @@ sievec /var/vmail/sieve/global_sieve_after.sieve
|
||||
sievec /usr/lib/dovecot/sieve/report-spam.sieve
|
||||
sievec /usr/lib/dovecot/sieve/report-ham.sieve
|
||||
|
||||
for file in /var/vmail/*/*/sieve/*.sieve ; do
|
||||
if [[ "$file" == "/var/vmail/*/*/sieve/*.sieve" ]]; then
|
||||
continue
|
||||
fi
|
||||
sievec "$file" "$(dirname "$file")/../.dovecot.svbin"
|
||||
chown vmail:vmail "$(dirname "$file")/../.dovecot.svbin"
|
||||
done
|
||||
|
||||
# Fix permissions
|
||||
chown root:root /etc/dovecot/sql/*.conf
|
||||
chown root:dovecot /etc/dovecot/sql/dovecot-dict-sql-sieve* /etc/dovecot/sql/dovecot-dict-sql-quota* /etc/dovecot/lua/passwd-verify.lua
|
||||
@@ -387,7 +431,8 @@ chmod +x /usr/lib/dovecot/sieve/rspamd-pipe-ham \
|
||||
/usr/local/bin/maildir_gc.sh \
|
||||
/usr/local/sbin/stop-supervisor.sh \
|
||||
/usr/local/bin/quota_notify.py \
|
||||
/usr/local/bin/repl_health.sh
|
||||
/usr/local/bin/repl_health.sh \
|
||||
/usr/local/bin/optimize-fts.sh
|
||||
|
||||
# Prepare environment file for cronjobs
|
||||
printenv | sed 's/^\(.*\)$/export \1/g' > /source_env.sh
|
||||
|
||||
7
data/Dockerfiles/dovecot/optimize-fts.sh
Normal file
7
data/Dockerfiles/dovecot/optimize-fts.sh
Normal file
@@ -0,0 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [[ "${SKIP_SOLR}" =~ ^([yY][eE][sS]|[yY])+$ && ! "${FLATCURVE_EXPERIMENTAL}" =~ ^([yY][eE][sS]|[yY])+$ ]]; then
|
||||
exit 0
|
||||
else
|
||||
doveadm fts optimize -A
|
||||
fi
|
||||
@@ -3,8 +3,8 @@ FILE=/tmp/mail$$
|
||||
cat > $FILE
|
||||
trap "/bin/rm -f $FILE" 0 1 2 3 13 15
|
||||
|
||||
cat ${FILE} | /usr/bin/curl -H "Flag: 11" -s --data-binary @- --unix-socket /var/lib/rspamd/rspamd.sock http://rspamd/fuzzydel
|
||||
cat ${FILE} | /usr/bin/curl -s --data-binary @- --unix-socket /var/lib/rspamd/rspamd.sock http://rspamd/learnham
|
||||
cat ${FILE} | /usr/bin/curl -H "Flag: 13" -s --data-binary @- --unix-socket /var/lib/rspamd/rspamd.sock http://rspamd/fuzzyadd
|
||||
cat ${FILE} | /usr/bin/curl -H "Flag: 11" -s --data-binary @- --unix-socket /var/lib/rspamd/rspamd.sock http://rspamd.${COMPOSE_PROJECT_NAME}_mailcow-network/fuzzydel
|
||||
cat ${FILE} | /usr/bin/curl -s --data-binary @- --unix-socket /var/lib/rspamd/rspamd.sock http://rspamd.${COMPOSE_PROJECT_NAME}_mailcow-network/learnham
|
||||
cat ${FILE} | /usr/bin/curl -H "Flag: 13" -s --data-binary @- --unix-socket /var/lib/rspamd/rspamd.sock http://rspamd.${COMPOSE_PROJECT_NAME}_mailcow-network/fuzzyadd
|
||||
|
||||
exit 0
|
||||
|
||||
@@ -3,8 +3,8 @@ FILE=/tmp/mail$$
|
||||
cat > $FILE
|
||||
trap "/bin/rm -f $FILE" 0 1 2 3 13 15
|
||||
|
||||
cat ${FILE} | /usr/bin/curl -H "Flag: 13" -s --data-binary @- --unix-socket /var/lib/rspamd/rspamd.sock http://rspamd/fuzzydel
|
||||
cat ${FILE} | /usr/bin/curl -s --data-binary @- --unix-socket /var/lib/rspamd/rspamd.sock http://rspamd/learnspam
|
||||
cat ${FILE} | /usr/bin/curl -H "Flag: 11" -s --data-binary @- --unix-socket /var/lib/rspamd/rspamd.sock http://rspamd/fuzzyadd
|
||||
cat ${FILE} | /usr/bin/curl -H "Flag: 13" -s --data-binary @- --unix-socket /var/lib/rspamd/rspamd.sock http://rspamd.${COMPOSE_PROJECT_NAME}_mailcow-network/fuzzydel
|
||||
cat ${FILE} | /usr/bin/curl -s --data-binary @- --unix-socket /var/lib/rspamd/rspamd.sock http://rspamd.${COMPOSE_PROJECT_NAME}_mailcow-network/learnspam
|
||||
cat ${FILE} | /usr/bin/curl -H "Flag: 11" -s --data-binary @- --unix-socket /var/lib/rspamd/rspamd.sock http://rspamd.${COMPOSE_PROJECT_NAME}_mailcow-network/fuzzyadd
|
||||
|
||||
exit 0
|
||||
|
||||
@@ -11,7 +11,7 @@ else
|
||||
fi
|
||||
|
||||
# Deploy
|
||||
curl --connect-timeout 15 --retry 10 --max-time 30 http://www.spamassassin.heinlein-support.de/$(dig txt 1.4.3.spamassassin.heinlein-support.de +short | tr -d '"' | tr -dc '0-9').tar.gz --output /tmp/sa-rules-heinlein.tar.gz
|
||||
curl --connect-timeout 15 --retry 10 --max-time 30 https://www.spamassassin.heinlein-support.de/$(dig txt 1.4.3.spamassassin.heinlein-support.de +short | tr -d '"' | tr -dc '0-9').tar.gz --output /tmp/sa-rules-heinlein.tar.gz
|
||||
if gzip -t /tmp/sa-rules-heinlein.tar.gz; then
|
||||
tar xfvz /tmp/sa-rules-heinlein.tar.gz -C /tmp/sa-rules-heinlein
|
||||
cat /tmp/sa-rules-heinlein/*cf > /etc/rspamd/custom/sa-rules
|
||||
@@ -21,11 +21,11 @@ sed -i -e 's/\([^\\]\)\$\([^\/]\)/\1\\$\2/g' /etc/rspamd/custom/sa-rules
|
||||
|
||||
if [[ "$(cat /etc/rspamd/custom/sa-rules | md5sum | cut -d' ' -f1)" != "${HASH_SA_RULES}" ]]; then
|
||||
CONTAINER_NAME=rspamd-mailcow
|
||||
CONTAINER_ID=$(curl --silent --insecure https://dockerapi/containers/json | \
|
||||
CONTAINER_ID=$(curl --silent --insecure https://dockerapi.${COMPOSE_PROJECT_NAME}_mailcow-network/containers/json | \
|
||||
jq -r ".[] | {name: .Config.Labels[\"com.docker.compose.service\"], project: .Config.Labels[\"com.docker.compose.project\"], id: .Id}" | \
|
||||
jq -rc "select( .name | tostring | contains(\"${CONTAINER_NAME}\")) | select( .project | tostring | contains(\"${COMPOSE_PROJECT_NAME,,}\")) | .id")
|
||||
if [[ ! -z ${CONTAINER_ID} ]]; then
|
||||
curl --silent --insecure -XPOST --connect-timeout 15 --max-time 120 https://dockerapi/containers/${CONTAINER_ID}/restart
|
||||
curl --silent --insecure -XPOST --connect-timeout 15 --max-time 120 https://dockerapi.${COMPOSE_PROJECT_NAME}_mailcow-network/containers/${CONTAINER_ID}/restart
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
FROM alpine:3.19
|
||||
LABEL maintainer "The Infrastructure Company GmbH <info@servercow.de>"
|
||||
FROM alpine:3.20
|
||||
|
||||
LABEL maintainer = "The Infrastructure Company GmbH <info@servercow.de>"
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
|
||||
@@ -80,16 +80,16 @@ def refreshF2bregex():
|
||||
global exit_code
|
||||
if not r.get('F2B_REGEX'):
|
||||
f2bregex = {}
|
||||
f2bregex[1] = 'mailcow UI: Invalid password for .+ by ([0-9a-f\.:]+)'
|
||||
f2bregex[2] = 'Rspamd UI: Invalid password by ([0-9a-f\.:]+)'
|
||||
f2bregex[3] = 'warning: .*\[([0-9a-f\.:]+)\]: SASL .+ authentication failed: (?!.*Connection lost to authentication server).+'
|
||||
f2bregex[4] = 'warning: non-SMTP command from .*\[([0-9a-f\.:]+)]:.+'
|
||||
f2bregex[5] = 'NOQUEUE: reject: RCPT from \[([0-9a-f\.:]+)].+Protocol error.+'
|
||||
f2bregex[6] = '-login: Disconnected.+ \(auth failed, .+\): user=.*, method=.+, rip=([0-9a-f\.:]+),'
|
||||
f2bregex[7] = '-login: Aborted login.+ \(auth failed .+\): user=.+, rip=([0-9a-f\.:]+), lip.+'
|
||||
f2bregex[8] = '-login: Aborted login.+ \(tried to use disallowed .+\): user=.+, rip=([0-9a-f\.:]+), lip.+'
|
||||
f2bregex[9] = 'SOGo.+ Login from \'([0-9a-f\.:]+)\' for user .+ might not have worked'
|
||||
f2bregex[10] = '([0-9a-f\.:]+) \"GET \/SOGo\/.* HTTP.+\" 403 .+'
|
||||
f2bregex[1] = r'mailcow UI: Invalid password for .+ by ([0-9a-f\.:]+)'
|
||||
f2bregex[2] = r'Rspamd UI: Invalid password by ([0-9a-f\.:]+)'
|
||||
f2bregex[3] = r'warning: .*\[([0-9a-f\.:]+)\]: SASL .+ authentication failed: (?!.*Connection lost to authentication server).+'
|
||||
f2bregex[4] = r'warning: non-SMTP command from .*\[([0-9a-f\.:]+)]:.+'
|
||||
f2bregex[5] = r'NOQUEUE: reject: RCPT from \[([0-9a-f\.:]+)].+Protocol error.+'
|
||||
f2bregex[6] = r'-login: Disconnected.+ \(auth failed, .+\): user=.*, method=.+, rip=([0-9a-f\.:]+),'
|
||||
f2bregex[7] = r'-login: Aborted login.+ \(auth failed .+\): user=.+, rip=([0-9a-f\.:]+), lip.+'
|
||||
f2bregex[8] = r'-login: Aborted login.+ \(tried to use disallowed .+\): user=.+, rip=([0-9a-f\.:]+), lip.+'
|
||||
f2bregex[9] = r'SOGo.+ Login from \'([0-9a-f\.:]+)\' for user .+ might not have worked'
|
||||
f2bregex[10] = r'([0-9a-f\.:]+) \"GET \/SOGo\/.* HTTP.+\" 403 .+'
|
||||
r.set('F2B_REGEX', json.dumps(f2bregex, ensure_ascii=False))
|
||||
else:
|
||||
try:
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
FROM alpine:3.19
|
||||
LABEL maintainer "The Infrastructure Company GmbH <info@servercow.de>"
|
||||
FROM alpine:3.20
|
||||
|
||||
LABEL maintainer = "The Infrastructure Company GmbH <info@servercow.de>"
|
||||
|
||||
ARG PIP_BREAK_SYSTEM_PACKAGES=1
|
||||
WORKDIR /app
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
FROM php:8.2-fpm-alpine3.18
|
||||
LABEL maintainer "The Infrastructure Company GmbH <info@servercow.de>"
|
||||
|
||||
LABEL maintainer = "The Infrastructure Company GmbH <info@servercow.de>"
|
||||
|
||||
# renovate: datasource=github-tags depName=krakjoe/apcu versioning=semver-coerced extractVersion=^v(?<version>.*)$
|
||||
ARG APCU_PECL_VERSION=5.1.23
|
||||
|
||||
@@ -23,7 +23,8 @@ done
|
||||
# Check mysql_upgrade (master and slave)
|
||||
CONTAINER_ID=
|
||||
until [[ ! -z "${CONTAINER_ID}" ]] && [[ "${CONTAINER_ID}" =~ ^[[:alnum:]]*$ ]]; do
|
||||
CONTAINER_ID=$(curl --silent --insecure https://dockerapi/containers/json | jq -r ".[] | {name: .Config.Labels[\"com.docker.compose.service\"], project: .Config.Labels[\"com.docker.compose.project\"], id: .Id}" 2> /dev/null | jq -rc "select( .name | tostring | contains(\"mysql-mailcow\")) | select( .project | tostring | contains(\"${COMPOSE_PROJECT_NAME,,}\")) | .id" 2> /dev/null)
|
||||
CONTAINER_ID=$(curl --silent --insecure https://dockerapi.${COMPOSE_PROJECT_NAME}_mailcow-network/containers/json | jq -r ".[] | {name: .Config.Labels[\"com.docker.compose.service\"], project: .Config.Labels[\"com.docker.compose.project\"], id: .Id}" 2> /dev/null | jq -rc "select( .name | tostring | contains(\"mysql-mailcow\")) | select( .project | tostring | contains(\"${COMPOSE_PROJECT_NAME,,}\")) | .id" 2> /dev/null)
|
||||
echo "Could not get mysql-mailcow container id... trying again"
|
||||
sleep 2
|
||||
done
|
||||
echo "MySQL @ ${CONTAINER_ID}"
|
||||
@@ -34,7 +35,7 @@ until [[ ${SQL_UPGRADE_STATUS} == 'success' ]]; do
|
||||
echo "Tried to upgrade MySQL and failed, giving up after ${SQL_LOOP_C} retries and starting container (oops, not good)"
|
||||
break
|
||||
fi
|
||||
SQL_FULL_UPGRADE_RETURN=$(curl --silent --insecure -XPOST https://dockerapi/containers/${CONTAINER_ID}/exec -d '{"cmd":"system", "task":"mysql_upgrade"}' --silent -H 'Content-type: application/json')
|
||||
SQL_FULL_UPGRADE_RETURN=$(curl --silent --insecure -XPOST https://dockerapi.${COMPOSE_PROJECT_NAME}_mailcow-network/containers/${CONTAINER_ID}/exec -d '{"cmd":"system", "task":"mysql_upgrade"}' --silent -H 'Content-type: application/json')
|
||||
SQL_UPGRADE_STATUS=$(echo ${SQL_FULL_UPGRADE_RETURN} | jq -r .type)
|
||||
SQL_LOOP_C=$((SQL_LOOP_C+1))
|
||||
echo "SQL upgrade iteration #${SQL_LOOP_C}"
|
||||
@@ -59,12 +60,12 @@ done
|
||||
|
||||
# doing post-installation stuff, if SQL was upgraded (master and slave)
|
||||
if [ ${SQL_CHANGED} -eq 1 ]; then
|
||||
POSTFIX=$(curl --silent --insecure https://dockerapi/containers/json | jq -r ".[] | {name: .Config.Labels[\"com.docker.compose.service\"], project: .Config.Labels[\"com.docker.compose.project\"], id: .Id}" 2> /dev/null | jq -rc "select( .name | tostring | contains(\"postfix-mailcow\")) | select( .project | tostring | contains(\"${COMPOSE_PROJECT_NAME,,}\")) | .id" 2> /dev/null)
|
||||
POSTFIX=$(curl --silent --insecure https://dockerapi.${COMPOSE_PROJECT_NAME}_mailcow-network/containers/json | jq -r ".[] | {name: .Config.Labels[\"com.docker.compose.service\"], project: .Config.Labels[\"com.docker.compose.project\"], id: .Id}" 2> /dev/null | jq -rc "select( .name | tostring | contains(\"postfix-mailcow\")) | select( .project | tostring | contains(\"${COMPOSE_PROJECT_NAME,,}\")) | .id" 2> /dev/null)
|
||||
if [[ -z "${POSTFIX}" ]] || ! [[ "${POSTFIX}" =~ ^[[:alnum:]]*$ ]]; then
|
||||
echo "Could not determine Postfix container ID, skipping Postfix restart."
|
||||
else
|
||||
echo "Restarting Postfix"
|
||||
curl -X POST --silent --insecure https://dockerapi/containers/${POSTFIX}/restart | jq -r '.msg'
|
||||
curl -X POST --silent --insecure https://dockerapi.${COMPOSE_PROJECT_NAME}_mailcow-network/containers/${POSTFIX}/restart | jq -r '.msg'
|
||||
echo "Sleeping 5 seconds..."
|
||||
sleep 5
|
||||
fi
|
||||
@@ -73,7 +74,7 @@ fi
|
||||
# Check mysql tz import (master and slave)
|
||||
TZ_CHECK=$(mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "SELECT CONVERT_TZ('2019-11-02 23:33:00','Europe/Berlin','UTC') AS time;" -BN 2> /dev/null)
|
||||
if [[ -z ${TZ_CHECK} ]] || [[ "${TZ_CHECK}" == "NULL" ]]; then
|
||||
SQL_FULL_TZINFO_IMPORT_RETURN=$(curl --silent --insecure -XPOST https://dockerapi/containers/${CONTAINER_ID}/exec -d '{"cmd":"system", "task":"mysql_tzinfo_to_sql"}' --silent -H 'Content-type: application/json')
|
||||
SQL_FULL_TZINFO_IMPORT_RETURN=$(curl --silent --insecure -XPOST https://dockerapi.${COMPOSE_PROJECT_NAME}_mailcow-network/containers/${CONTAINER_ID}/exec -d '{"cmd":"system", "task":"mysql_tzinfo_to_sql"}' --silent -H 'Content-type: application/json')
|
||||
echo "MySQL mysql_tzinfo_to_sql - debug output:"
|
||||
echo ${SQL_FULL_TZINFO_IMPORT_RETURN}
|
||||
fi
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
FROM debian:bullseye-slim
|
||||
LABEL maintainer "The Infrastructure Company GmbH <info@servercow.de>"
|
||||
FROM debian:bookworm-slim
|
||||
|
||||
LABEL maintainer = "The Infrastructure Company GmbH <info@servercow.de>"
|
||||
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
ENV LC_ALL C
|
||||
|
||||
@@ -415,12 +415,6 @@ postscreen_dnsbl_sites = wl.mailspike.net=127.0.0.[18;19;20]*-2
|
||||
b.barracudacentral.org=127.0.0.2*7
|
||||
bl.mailspike.net=127.0.0.2*5
|
||||
bl.mailspike.net=127.0.0.[10;11;12]*4
|
||||
dnsbl.sorbs.net=127.0.0.10*8
|
||||
dnsbl.sorbs.net=127.0.0.5*6
|
||||
dnsbl.sorbs.net=127.0.0.7*3
|
||||
dnsbl.sorbs.net=127.0.0.8*2
|
||||
dnsbl.sorbs.net=127.0.0.6*2
|
||||
dnsbl.sorbs.net=127.0.0.9*2
|
||||
EOF
|
||||
fi
|
||||
DNSBL_CONFIG=$(grep -v '^#' /opt/postfix/conf/dns_blocklists.cf | grep '\S')
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@version: 3.28
|
||||
@version: 3.38
|
||||
@include "scl.conf"
|
||||
options {
|
||||
chain_hostnames(off);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@version: 3.28
|
||||
@version: 3.38
|
||||
@include "scl.conf"
|
||||
options {
|
||||
chain_hostnames(off);
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
FROM debian:bullseye-slim
|
||||
LABEL maintainer "The Infrastructure Company GmbH <info@servercow.de>"
|
||||
FROM debian:bookworm-slim
|
||||
LABEL maintainer = "The Infrastructure Company GmbH <info@servercow.de>"
|
||||
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
ARG CODENAME=bullseye
|
||||
ENV LC_ALL C
|
||||
ARG RSPAMD_VER=rspamd_3.9.1-1~82f43560f
|
||||
ARG CODENAME=bookworm
|
||||
ENV LC_ALL=C
|
||||
|
||||
RUN apt-get update && apt-get install -y \
|
||||
tzdata \
|
||||
@@ -11,12 +12,16 @@ RUN apt-get update && apt-get install -y \
|
||||
gnupg2 \
|
||||
apt-transport-https \
|
||||
dnsutils \
|
||||
netcat \
|
||||
&& apt-key adv --fetch-keys https://rspamd.com/apt-stable/gpg.key \
|
||||
&& echo "deb https://rspamd.com/apt-stable/ $CODENAME main" > /etc/apt/sources.list.d/rspamd.list \
|
||||
&& apt-get update \
|
||||
&& apt-get --no-install-recommends -y install rspamd redis-tools procps nano \
|
||||
&& rm -rf /var/lib/apt/lists/* \
|
||||
netcat-traditional \
|
||||
wget \
|
||||
redis-tools \
|
||||
procps \
|
||||
nano \
|
||||
lua-cjson \
|
||||
&& arch=$(arch | sed s/aarch64/arm64/ | sed s/x86_64/amd64/) \
|
||||
&& wget -P /tmp https://rspamd.com/apt-stable/pool/main/r/rspamd/${RSPAMD_VER}~${CODENAME}_${arch}.deb\
|
||||
&& apt install -y /tmp/${RSPAMD_VER}~${CODENAME}_${arch}.deb \
|
||||
&& rm -rf /var/lib/apt/lists/* /tmp/*\
|
||||
&& apt-get autoremove --purge \
|
||||
&& apt-get clean \
|
||||
&& mkdir -p /run/rspamd \
|
||||
@@ -25,7 +30,6 @@ RUN apt-get update && apt-get install -y \
|
||||
&& sed -i 's/#analysis_keyword_table > 0/analysis_cat_table.macro_exist == "M"/g' /usr/share/rspamd/lualib/lua_scanners/oletools.lua
|
||||
|
||||
COPY settings.conf /etc/rspamd/settings.conf
|
||||
COPY metadata_exporter.lua /usr/share/rspamd/plugins/metadata_exporter.lua
|
||||
COPY set_worker_password.sh /set_worker_password.sh
|
||||
COPY docker-entrypoint.sh /docker-entrypoint.sh
|
||||
|
||||
|
||||
@@ -124,4 +124,190 @@ for file in /hooks/*; do
|
||||
fi
|
||||
done
|
||||
|
||||
# If DQS KEY is set in mailcow.conf add Spamhaus DQS RBLs
|
||||
if [[ ! -z ${SPAMHAUS_DQS_KEY} ]]; then
|
||||
cat <<EOF > /etc/rspamd/custom/dqs-rbl.conf
|
||||
# Autogenerated by mailcow. DO NOT TOUCH!
|
||||
spamhaus {
|
||||
rbl = "${SPAMHAUS_DQS_KEY}.zen.dq.spamhaus.net";
|
||||
from = false;
|
||||
}
|
||||
spamhaus_from {
|
||||
from = true;
|
||||
received = false;
|
||||
rbl = "${SPAMHAUS_DQS_KEY}.zen.dq.spamhaus.net";
|
||||
returncodes {
|
||||
SPAMHAUS_ZEN = [ "127.0.0.2", "127.0.0.3", "127.0.0.4", "127.0.0.5", "127.0.0.6", "127.0.0.7", "127.0.0.9", "127.0.0.10", "127.0.0.11" ];
|
||||
}
|
||||
}
|
||||
spamhaus_authbl_received {
|
||||
# Check if the sender client is listed in AuthBL (AuthBL is *not* part of ZEN)
|
||||
rbl = "${SPAMHAUS_DQS_KEY}.authbl.dq.spamhaus.net";
|
||||
from = false;
|
||||
received = true;
|
||||
ipv6 = true;
|
||||
returncodes {
|
||||
SH_AUTHBL_RECEIVED = "127.0.0.20"
|
||||
}
|
||||
}
|
||||
spamhaus_dbl {
|
||||
# Add checks on the HELO string
|
||||
rbl = "${SPAMHAUS_DQS_KEY}.dbl.dq.spamhaus.net";
|
||||
helo = true;
|
||||
rdns = true;
|
||||
dkim = true;
|
||||
disable_monitoring = true;
|
||||
returncodes {
|
||||
RBL_DBL_SPAM = "127.0.1.2";
|
||||
RBL_DBL_PHISH = "127.0.1.4";
|
||||
RBL_DBL_MALWARE = "127.0.1.5";
|
||||
RBL_DBL_BOTNET = "127.0.1.6";
|
||||
RBL_DBL_ABUSED_SPAM = "127.0.1.102";
|
||||
RBL_DBL_ABUSED_PHISH = "127.0.1.104";
|
||||
RBL_DBL_ABUSED_MALWARE = "127.0.1.105";
|
||||
RBL_DBL_ABUSED_BOTNET = "127.0.1.106";
|
||||
RBL_DBL_DONT_QUERY_IPS = "127.0.1.255";
|
||||
}
|
||||
}
|
||||
spamhaus_dbl_fullurls {
|
||||
ignore_defaults = true;
|
||||
no_ip = true;
|
||||
rbl = "${SPAMHAUS_DQS_KEY}.dbl.dq.spamhaus.net";
|
||||
selector = 'urls:get_host'
|
||||
disable_monitoring = true;
|
||||
returncodes {
|
||||
DBLABUSED_SPAM_FULLURLS = "127.0.1.102";
|
||||
DBLABUSED_PHISH_FULLURLS = "127.0.1.104";
|
||||
DBLABUSED_MALWARE_FULLURLS = "127.0.1.105";
|
||||
DBLABUSED_BOTNET_FULLURLS = "127.0.1.106";
|
||||
}
|
||||
}
|
||||
spamhaus_zrd {
|
||||
# Add checks on the HELO string also for DQS
|
||||
rbl = "${SPAMHAUS_DQS_KEY}.zrd.dq.spamhaus.net";
|
||||
helo = true;
|
||||
rdns = true;
|
||||
dkim = true;
|
||||
disable_monitoring = true;
|
||||
returncodes {
|
||||
RBL_ZRD_VERY_FRESH_DOMAIN = ["127.0.2.2", "127.0.2.3", "127.0.2.4"];
|
||||
RBL_ZRD_FRESH_DOMAIN = [
|
||||
"127.0.2.5", "127.0.2.6", "127.0.2.7", "127.0.2.8", "127.0.2.9", "127.0.2.10", "127.0.2.11", "127.0.2.12", "127.0.2.13", "127.0.2.14", "127.0.2.15", "127.0.2.16", "127.0.2.17", "127.0.2.18", "127.0.2.19", "127.0.2.20", "127.0.2.21", "127.0.2.22", "127.0.2.23", "127.0.2.24"
|
||||
];
|
||||
RBL_ZRD_DONT_QUERY_IPS = "127.0.2.255";
|
||||
}
|
||||
}
|
||||
"SPAMHAUS_ZEN_URIBL" {
|
||||
enabled = true;
|
||||
rbl = "${SPAMHAUS_DQS_KEY}.zen.dq.spamhaus.net";
|
||||
resolve_ip = true;
|
||||
checks = ['urls'];
|
||||
replyto = true;
|
||||
emails = true;
|
||||
ipv4 = true;
|
||||
ipv6 = true;
|
||||
emails_domainonly = true;
|
||||
returncodes {
|
||||
URIBL_SBL = "127.0.0.2";
|
||||
URIBL_SBL_CSS = "127.0.0.3";
|
||||
URIBL_XBL = ["127.0.0.4", "127.0.0.5", "127.0.0.6", "127.0.0.7"];
|
||||
URIBL_PBL = ["127.0.0.10", "127.0.0.11"];
|
||||
URIBL_DROP = "127.0.0.9";
|
||||
}
|
||||
}
|
||||
SH_EMAIL_DBL {
|
||||
ignore_defaults = true;
|
||||
replyto = true;
|
||||
emails_domainonly = true;
|
||||
disable_monitoring = true;
|
||||
rbl = "${SPAMHAUS_DQS_KEY}.dbl.dq.spamhaus.net";
|
||||
returncodes = {
|
||||
SH_EMAIL_DBL = [
|
||||
"127.0.1.2",
|
||||
"127.0.1.4",
|
||||
"127.0.1.5",
|
||||
"127.0.1.6"
|
||||
];
|
||||
SH_EMAIL_DBL_ABUSED = [
|
||||
"127.0.1.102",
|
||||
"127.0.1.104",
|
||||
"127.0.1.105",
|
||||
"127.0.1.106"
|
||||
];
|
||||
SH_EMAIL_DBL_DONT_QUERY_IPS = [ "127.0.1.255" ];
|
||||
}
|
||||
}
|
||||
SH_EMAIL_ZRD {
|
||||
ignore_defaults = true;
|
||||
replyto = true;
|
||||
emails_domainonly = true;
|
||||
disable_monitoring = true;
|
||||
rbl = "${SPAMHAUS_DQS_KEY}.zrd.dq.spamhaus.net";
|
||||
returncodes = {
|
||||
SH_EMAIL_ZRD_VERY_FRESH_DOMAIN = ["127.0.2.2", "127.0.2.3", "127.0.2.4"];
|
||||
SH_EMAIL_ZRD_FRESH_DOMAIN = [
|
||||
"127.0.2.5", "127.0.2.6", "127.0.2.7", "127.0.2.8", "127.0.2.9", "127.0.2.10", "127.0.2.11", "127.0.2.12", "127.0.2.13", "127.0.2.14", "127.0.2.15", "127.0.2.16", "127.0.2.17", "127.0.2.18", "127.0.2.19", "127.0.2.20", "127.0.2.21", "127.0.2.22", "127.0.2.23", "127.0.2.24"
|
||||
];
|
||||
SH_EMAIL_ZRD_DONT_QUERY_IPS = [ "127.0.2.255" ];
|
||||
}
|
||||
}
|
||||
"DBL" {
|
||||
# override the defaults for DBL defined in modules.d/rbl.conf
|
||||
rbl = "${SPAMHAUS_DQS_KEY}.dbl.dq.spamhaus.net";
|
||||
disable_monitoring = true;
|
||||
}
|
||||
"ZRD" {
|
||||
ignore_defaults = true;
|
||||
rbl = "${SPAMHAUS_DQS_KEY}.zrd.dq.spamhaus.net";
|
||||
no_ip = true;
|
||||
dkim = true;
|
||||
emails = true;
|
||||
emails_domainonly = true;
|
||||
urls = true;
|
||||
returncodes = {
|
||||
ZRD_VERY_FRESH_DOMAIN = ["127.0.2.2", "127.0.2.3", "127.0.2.4"];
|
||||
ZRD_FRESH_DOMAIN = ["127.0.2.5", "127.0.2.6", "127.0.2.7", "127.0.2.8", "127.0.2.9", "127.0.2.10", "127.0.2.11", "127.0.2.12", "127.0.2.13", "127.0.2.14", "127.0.2.15", "127.0.2.16", "127.0.2.17", "127.0.2.18", "127.0.2.19", "127.0.2.20", "127.0.2.21", "127.0.2.22", "127.0.2.23", "127.0.2.24"];
|
||||
}
|
||||
}
|
||||
spamhaus_sbl_url {
|
||||
ignore_defaults = true
|
||||
rbl = "${SPAMHAUS_DQS_KEY}.sbl.dq.spamhaus.net";
|
||||
checks = ['urls'];
|
||||
disable_monitoring = true;
|
||||
returncodes {
|
||||
SPAMHAUS_SBL_URL = "127.0.0.2";
|
||||
}
|
||||
}
|
||||
|
||||
SH_HBL_EMAIL {
|
||||
ignore_defaults = true;
|
||||
rbl = "_email.${SPAMHAUS_DQS_KEY}.hbl.dq.spamhaus.net";
|
||||
emails_domainonly = false;
|
||||
selector = "from('smtp').lower;from('mime').lower";
|
||||
ignore_whitelist = true;
|
||||
checks = ['emails', 'replyto'];
|
||||
hash = "sha1";
|
||||
returncodes = {
|
||||
SH_HBL_EMAIL = [
|
||||
"127.0.3.2"
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
spamhaus_dqs_hbl {
|
||||
symbol = "HBL_FILE_UNKNOWN";
|
||||
rbl = "_file.${SPAMHAUS_DQS_KEY}.hbl.dq.spamhaus.net.";
|
||||
selector = "attachments('rbase32', 'sha256')";
|
||||
ignore_whitelist = true;
|
||||
ignore_defaults = true;
|
||||
returncodes {
|
||||
SH_HBL_FILE_MALICIOUS = "127.0.3.10";
|
||||
SH_HBL_FILE_SUSPICIOUS = "127.0.3.15";
|
||||
}
|
||||
}
|
||||
EOF
|
||||
else
|
||||
rm -rf /etc/rspamd/custom/dqs-rbl.conf
|
||||
fi
|
||||
|
||||
exec "$@"
|
||||
|
||||
@@ -1,632 +0,0 @@
|
||||
--[[
|
||||
Copyright (c) 2016, Andrew Lewis <nerf@judo.za.org>
|
||||
Copyright (c) 2016, Vsevolod Stakhov <vsevolod@highsecure.ru>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
]]--
|
||||
|
||||
if confighelp then
|
||||
return
|
||||
end
|
||||
|
||||
-- A plugin that pushes metadata (or whole messages) to external services
|
||||
|
||||
local redis_params
|
||||
local lua_util = require "lua_util"
|
||||
local rspamd_http = require "rspamd_http"
|
||||
local rspamd_util = require "rspamd_util"
|
||||
local rspamd_logger = require "rspamd_logger"
|
||||
local ucl = require "ucl"
|
||||
local E = {}
|
||||
local N = 'metadata_exporter'
|
||||
|
||||
local settings = {
|
||||
pusher_enabled = {},
|
||||
pusher_format = {},
|
||||
pusher_select = {},
|
||||
mime_type = 'text/plain',
|
||||
defer = false,
|
||||
mail_from = '',
|
||||
mail_to = 'postmaster@localhost',
|
||||
helo = 'rspamd',
|
||||
email_template = [[From: "Rspamd" <$mail_from>
|
||||
To: $mail_to
|
||||
Subject: Spam alert
|
||||
Date: $date
|
||||
MIME-Version: 1.0
|
||||
Message-ID: <$our_message_id>
|
||||
Content-type: text/plain; charset=utf-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Authenticated username: $user
|
||||
IP: $ip
|
||||
Queue ID: $qid
|
||||
SMTP FROM: $from
|
||||
SMTP RCPT: $rcpt
|
||||
MIME From: $header_from
|
||||
MIME To: $header_to
|
||||
MIME Date: $header_date
|
||||
Subject: $header_subject
|
||||
Message-ID: $message_id
|
||||
Action: $action
|
||||
Score: $score
|
||||
Symbols: $symbols]],
|
||||
}
|
||||
|
||||
local function get_general_metadata(task, flatten, no_content)
|
||||
local r = {}
|
||||
local ip = task:get_from_ip()
|
||||
if ip and ip:is_valid() then
|
||||
r.ip = tostring(ip)
|
||||
else
|
||||
r.ip = 'unknown'
|
||||
end
|
||||
r.user = task:get_user() or 'unknown'
|
||||
r.qid = task:get_queue_id() or 'unknown'
|
||||
r.subject = task:get_subject() or 'unknown'
|
||||
r.action = task:get_metric_action('default')
|
||||
|
||||
local s = task:get_metric_score('default')[1]
|
||||
r.score = flatten and string.format('%.2f', s) or s
|
||||
|
||||
local fuzzy = task:get_mempool():get_variable("fuzzy_hashes", "fstrings")
|
||||
if fuzzy and #fuzzy > 0 then
|
||||
local fz = {}
|
||||
for _,h in ipairs(fuzzy) do
|
||||
table.insert(fz, h)
|
||||
end
|
||||
if not flatten then
|
||||
r.fuzzy = fz
|
||||
else
|
||||
r.fuzzy = table.concat(fz, ', ')
|
||||
end
|
||||
else
|
||||
r.fuzzy = 'unknown'
|
||||
end
|
||||
|
||||
local rcpt = task:get_recipients('smtp')
|
||||
if rcpt then
|
||||
local l = {}
|
||||
for _, a in ipairs(rcpt) do
|
||||
table.insert(l, a['addr'])
|
||||
end
|
||||
if not flatten then
|
||||
r.rcpt = l
|
||||
else
|
||||
r.rcpt = table.concat(l, ', ')
|
||||
end
|
||||
else
|
||||
r.rcpt = 'unknown'
|
||||
end
|
||||
local from = task:get_from('smtp')
|
||||
if ((from or E)[1] or E).addr then
|
||||
r.from = from[1].addr
|
||||
else
|
||||
r.from = 'unknown'
|
||||
end
|
||||
local syminf = task:get_symbols_all()
|
||||
if flatten then
|
||||
local l = {}
|
||||
for _, sym in ipairs(syminf) do
|
||||
local txt
|
||||
if sym.options then
|
||||
local topt = table.concat(sym.options, ', ')
|
||||
txt = sym.name .. '(' .. string.format('%.2f', sym.score) .. ')' .. ' [' .. topt .. ']'
|
||||
else
|
||||
txt = sym.name .. '(' .. string.format('%.2f', sym.score) .. ')'
|
||||
end
|
||||
table.insert(l, txt)
|
||||
end
|
||||
r.symbols = table.concat(l, '\n\t')
|
||||
else
|
||||
r.symbols = syminf
|
||||
end
|
||||
local function process_header(name)
|
||||
local hdr = task:get_header_full(name)
|
||||
if hdr then
|
||||
local l = {}
|
||||
for _, h in ipairs(hdr) do
|
||||
table.insert(l, h.decoded)
|
||||
end
|
||||
if not flatten then
|
||||
return l
|
||||
else
|
||||
return table.concat(l, '\n')
|
||||
end
|
||||
else
|
||||
return 'unknown'
|
||||
end
|
||||
end
|
||||
if not no_content then
|
||||
r.header_from = process_header('from')
|
||||
r.header_to = process_header('to')
|
||||
r.header_subject = process_header('subject')
|
||||
r.header_date = process_header('date')
|
||||
r.message_id = task:get_message_id()
|
||||
end
|
||||
return r
|
||||
end
|
||||
|
||||
local formatters = {
|
||||
default = function(task)
|
||||
return task:get_content(), {}
|
||||
end,
|
||||
email_alert = function(task, rule, extra)
|
||||
local meta = get_general_metadata(task, true)
|
||||
local display_emails = {}
|
||||
local mail_targets = {}
|
||||
meta.mail_from = rule.mail_from or settings.mail_from
|
||||
local mail_rcpt = rule.mail_to or settings.mail_to
|
||||
if type(mail_rcpt) ~= 'table' then
|
||||
table.insert(display_emails, string.format('<%s>', mail_rcpt))
|
||||
table.insert(mail_targets, mail_rcpt)
|
||||
else
|
||||
for _, e in ipairs(mail_rcpt) do
|
||||
table.insert(display_emails, string.format('<%s>', e))
|
||||
table.insert(mail_targets, mail_rcpt)
|
||||
end
|
||||
end
|
||||
if rule.email_alert_sender then
|
||||
local x = task:get_from('smtp')
|
||||
if x and string.len(x[1].addr) > 0 then
|
||||
table.insert(mail_targets, x)
|
||||
table.insert(display_emails, string.format('<%s>', x[1].addr))
|
||||
end
|
||||
end
|
||||
if rule.email_alert_user then
|
||||
local x = task:get_user()
|
||||
if x then
|
||||
table.insert(mail_targets, x)
|
||||
table.insert(display_emails, string.format('<%s>', x))
|
||||
end
|
||||
end
|
||||
if rule.email_alert_recipients then
|
||||
local x = task:get_recipients('smtp')
|
||||
if x then
|
||||
for _, e in ipairs(x) do
|
||||
if string.len(e.addr) > 0 then
|
||||
table.insert(mail_targets, e.addr)
|
||||
table.insert(display_emails, string.format('<%s>', e.addr))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
meta.mail_to = table.concat(display_emails, ', ')
|
||||
meta.our_message_id = rspamd_util.random_hex(12) .. '@rspamd'
|
||||
meta.date = rspamd_util.time_to_string(rspamd_util.get_time())
|
||||
return lua_util.template(rule.email_template or settings.email_template, meta), { mail_targets = mail_targets}
|
||||
end,
|
||||
json = function(task)
|
||||
return ucl.to_format(get_general_metadata(task), 'json-compact')
|
||||
end
|
||||
}
|
||||
|
||||
local function is_spam(action)
|
||||
return (action == 'reject' or action == 'add header' or action == 'rewrite subject')
|
||||
end
|
||||
|
||||
local selectors = {
|
||||
default = function(task)
|
||||
return true
|
||||
end,
|
||||
is_spam = function(task)
|
||||
local action = task:get_metric_action('default')
|
||||
return is_spam(action)
|
||||
end,
|
||||
is_spam_authed = function(task)
|
||||
if not task:get_user() then
|
||||
return false
|
||||
end
|
||||
local action = task:get_metric_action('default')
|
||||
return is_spam(action)
|
||||
end,
|
||||
is_reject = function(task)
|
||||
local action = task:get_metric_action('default')
|
||||
return (action == 'reject')
|
||||
end,
|
||||
is_reject_authed = function(task)
|
||||
if not task:get_user() then
|
||||
return false
|
||||
end
|
||||
local action = task:get_metric_action('default')
|
||||
return (action == 'reject')
|
||||
end,
|
||||
}
|
||||
|
||||
local function maybe_defer(task, rule)
|
||||
if rule.defer then
|
||||
rspamd_logger.warnx(task, 'deferring message')
|
||||
task:set_pre_result('soft reject', 'deferred', N)
|
||||
end
|
||||
end
|
||||
|
||||
local pushers = {
|
||||
redis_pubsub = function(task, formatted, rule)
|
||||
local _,ret,upstream
|
||||
local function redis_pub_cb(err)
|
||||
if err then
|
||||
rspamd_logger.errx(task, 'got error %s when publishing on server %s',
|
||||
err, upstream:get_addr())
|
||||
return maybe_defer(task, rule)
|
||||
end
|
||||
return true
|
||||
end
|
||||
ret,_,upstream = rspamd_redis_make_request(task,
|
||||
redis_params, -- connect params
|
||||
nil, -- hash key
|
||||
true, -- is write
|
||||
redis_pub_cb, --callback
|
||||
'PUBLISH', -- command
|
||||
{rule.channel, formatted} -- arguments
|
||||
)
|
||||
if not ret then
|
||||
rspamd_logger.errx(task, 'error connecting to redis')
|
||||
maybe_defer(task, rule)
|
||||
end
|
||||
end,
|
||||
http = function(task, formatted, rule)
|
||||
local function http_callback(err, code)
|
||||
if err then
|
||||
rspamd_logger.errx(task, 'got error %s in http callback', err)
|
||||
return maybe_defer(task, rule)
|
||||
end
|
||||
if code ~= 200 then
|
||||
rspamd_logger.errx(task, 'got unexpected http status: %s', code)
|
||||
return maybe_defer(task, rule)
|
||||
end
|
||||
return true
|
||||
end
|
||||
local hdrs = {}
|
||||
if rule.meta_headers then
|
||||
local gm = get_general_metadata(task, false, true)
|
||||
local pfx = rule.meta_header_prefix or 'X-Rspamd-'
|
||||
for k, v in pairs(gm) do
|
||||
if type(v) == 'table' then
|
||||
hdrs[pfx .. k] = ucl.to_format(v, 'json-compact')
|
||||
else
|
||||
hdrs[pfx .. k] = v
|
||||
end
|
||||
end
|
||||
end
|
||||
rspamd_http.request({
|
||||
task=task,
|
||||
url=rule.url,
|
||||
body=formatted,
|
||||
callback=http_callback,
|
||||
mime_type=rule.mime_type or settings.mime_type,
|
||||
headers=hdrs,
|
||||
})
|
||||
end,
|
||||
send_mail = function(task, formatted, rule, extra)
|
||||
local lua_smtp = require "lua_smtp"
|
||||
local function sendmail_cb(ret, err)
|
||||
if not ret then
|
||||
rspamd_logger.errx(task, 'SMTP export error: %s', err)
|
||||
maybe_defer(task, rule)
|
||||
end
|
||||
end
|
||||
|
||||
lua_smtp.sendmail({
|
||||
task = task,
|
||||
host = rule.smtp,
|
||||
port = rule.smtp_port or settings.smtp_port or 25,
|
||||
from = rule.mail_from or settings.mail_from,
|
||||
recipients = extra.mail_targets or rule.mail_to or settings.mail_to,
|
||||
helo = rule.helo or settings.helo,
|
||||
timeout = rule.timeout or settings.timeout,
|
||||
}, formatted, sendmail_cb)
|
||||
end,
|
||||
}
|
||||
|
||||
local opts = rspamd_config:get_all_opt(N)
|
||||
if not opts then return end
|
||||
local process_settings = {
|
||||
select = function(val)
|
||||
selectors.custom = assert(load(val))()
|
||||
end,
|
||||
format = function(val)
|
||||
formatters.custom = assert(load(val))()
|
||||
end,
|
||||
push = function(val)
|
||||
pushers.custom = assert(load(val))()
|
||||
end,
|
||||
custom_push = function(val)
|
||||
if type(val) == 'table' then
|
||||
for k, v in pairs(val) do
|
||||
pushers[k] = assert(load(v))()
|
||||
end
|
||||
end
|
||||
end,
|
||||
custom_select = function(val)
|
||||
if type(val) == 'table' then
|
||||
for k, v in pairs(val) do
|
||||
selectors[k] = assert(load(v))()
|
||||
end
|
||||
end
|
||||
end,
|
||||
custom_format = function(val)
|
||||
if type(val) == 'table' then
|
||||
for k, v in pairs(val) do
|
||||
formatters[k] = assert(load(v))()
|
||||
end
|
||||
end
|
||||
end,
|
||||
pusher_enabled = function(val)
|
||||
if type(val) == 'string' then
|
||||
if pushers[val] then
|
||||
settings.pusher_enabled[val] = true
|
||||
else
|
||||
rspamd_logger.errx(rspamd_config, 'Pusher type: %s is invalid', val)
|
||||
end
|
||||
elseif type(val) == 'table' then
|
||||
for _, v in ipairs(val) do
|
||||
if pushers[v] then
|
||||
settings.pusher_enabled[v] = true
|
||||
else
|
||||
rspamd_logger.errx(rspamd_config, 'Pusher type: %s is invalid', val)
|
||||
end
|
||||
end
|
||||
end
|
||||
end,
|
||||
}
|
||||
for k, v in pairs(opts) do
|
||||
local f = process_settings[k]
|
||||
if f then
|
||||
f(opts[k])
|
||||
else
|
||||
settings[k] = v
|
||||
end
|
||||
end
|
||||
if type(settings.rules) ~= 'table' then
|
||||
-- Legacy config
|
||||
settings.rules = {}
|
||||
if not next(settings.pusher_enabled) then
|
||||
if pushers.custom then
|
||||
rspamd_logger.infox(rspamd_config, 'Custom pusher implicitly enabled')
|
||||
settings.pusher_enabled.custom = true
|
||||
else
|
||||
-- Check legacy options
|
||||
if settings.url then
|
||||
rspamd_logger.warnx(rspamd_config, 'HTTP pusher implicitly enabled')
|
||||
settings.pusher_enabled.http = true
|
||||
end
|
||||
if settings.channel then
|
||||
rspamd_logger.warnx(rspamd_config, 'Redis Pubsub pusher implicitly enabled')
|
||||
settings.pusher_enabled.redis_pubsub = true
|
||||
end
|
||||
if settings.smtp and settings.mail_to then
|
||||
rspamd_logger.warnx(rspamd_config, 'SMTP pusher implicitly enabled')
|
||||
settings.pusher_enabled.send_mail = true
|
||||
end
|
||||
end
|
||||
end
|
||||
if not next(settings.pusher_enabled) then
|
||||
rspamd_logger.errx(rspamd_config, 'No push backend enabled')
|
||||
return
|
||||
end
|
||||
if settings.formatter then
|
||||
settings.format = formatters[settings.formatter]
|
||||
if not settings.format then
|
||||
rspamd_logger.errx(rspamd_config, 'No such formatter: %s', settings.formatter)
|
||||
return
|
||||
end
|
||||
end
|
||||
if settings.selector then
|
||||
settings.select = selectors[settings.selector]
|
||||
if not settings.select then
|
||||
rspamd_logger.errx(rspamd_config, 'No such selector: %s', settings.selector)
|
||||
return
|
||||
end
|
||||
end
|
||||
for k in pairs(settings.pusher_enabled) do
|
||||
local formatter = settings.pusher_format[k]
|
||||
local selector = settings.pusher_select[k]
|
||||
if not formatter then
|
||||
settings.pusher_format[k] = settings.formatter or 'default'
|
||||
rspamd_logger.infox(rspamd_config, 'Using default formatter for %s pusher', k)
|
||||
else
|
||||
if not formatters[formatter] then
|
||||
rspamd_logger.errx(rspamd_config, 'No such formatter: %s - disabling %s', formatter, k)
|
||||
settings.pusher_enabled.k = nil
|
||||
end
|
||||
end
|
||||
if not selector then
|
||||
settings.pusher_select[k] = settings.selector or 'default'
|
||||
rspamd_logger.infox(rspamd_config, 'Using default selector for %s pusher', k)
|
||||
else
|
||||
if not selectors[selector] then
|
||||
rspamd_logger.errx(rspamd_config, 'No such selector: %s - disabling %s', selector, k)
|
||||
settings.pusher_enabled.k = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
if settings.pusher_enabled.redis_pubsub then
|
||||
redis_params = rspamd_parse_redis_server(N)
|
||||
if not redis_params then
|
||||
rspamd_logger.errx(rspamd_config, 'No redis servers are specified')
|
||||
settings.pusher_enabled.redis_pubsub = nil
|
||||
else
|
||||
local r = {}
|
||||
r.backend = 'redis_pubsub'
|
||||
r.channel = settings.channel
|
||||
r.defer = settings.defer
|
||||
r.selector = settings.pusher_select.redis_pubsub
|
||||
r.formatter = settings.pusher_format.redis_pubsub
|
||||
settings.rules[r.backend:upper()] = r
|
||||
end
|
||||
end
|
||||
if settings.pusher_enabled.http then
|
||||
if not settings.url then
|
||||
rspamd_logger.errx(rspamd_config, 'No URL is specified')
|
||||
settings.pusher_enabled.http = nil
|
||||
else
|
||||
local r = {}
|
||||
r.backend = 'http'
|
||||
r.url = settings.url
|
||||
r.mime_type = settings.mime_type
|
||||
r.defer = settings.defer
|
||||
r.selector = settings.pusher_select.http
|
||||
r.formatter = settings.pusher_format.http
|
||||
settings.rules[r.backend:upper()] = r
|
||||
end
|
||||
end
|
||||
if settings.pusher_enabled.send_mail then
|
||||
if not (settings.mail_to and settings.smtp) then
|
||||
rspamd_logger.errx(rspamd_config, 'No mail_to and/or smtp setting is specified')
|
||||
settings.pusher_enabled.send_mail = nil
|
||||
else
|
||||
local r = {}
|
||||
r.backend = 'send_mail'
|
||||
r.mail_to = settings.mail_to
|
||||
r.mail_from = settings.mail_from
|
||||
r.helo = settings.hello
|
||||
r.smtp = settings.smtp
|
||||
r.smtp_port = settings.smtp_port
|
||||
r.email_template = settings.email_template
|
||||
r.defer = settings.defer
|
||||
r.selector = settings.pusher_select.send_mail
|
||||
r.formatter = settings.pusher_format.send_mail
|
||||
settings.rules[r.backend:upper()] = r
|
||||
end
|
||||
end
|
||||
if not next(settings.pusher_enabled) then
|
||||
rspamd_logger.errx(rspamd_config, 'No push backend enabled')
|
||||
return
|
||||
end
|
||||
elseif not next(settings.rules) then
|
||||
lua_util.debugm(N, rspamd_config, 'No rules enabled')
|
||||
return
|
||||
end
|
||||
if not settings.rules or not next(settings.rules) then
|
||||
rspamd_logger.errx(rspamd_config, 'No rules enabled')
|
||||
return
|
||||
end
|
||||
local backend_required_elements = {
|
||||
http = {
|
||||
'url',
|
||||
},
|
||||
smtp = {
|
||||
'mail_to',
|
||||
'smtp',
|
||||
},
|
||||
redis_pubsub = {
|
||||
'channel',
|
||||
},
|
||||
}
|
||||
local check_element = {
|
||||
selector = function(k, v)
|
||||
if not selectors[v] then
|
||||
rspamd_logger.errx(rspamd_config, 'Rule %s has invalid selector %s', k, v)
|
||||
return false
|
||||
else
|
||||
return true
|
||||
end
|
||||
end,
|
||||
formatter = function(k, v)
|
||||
if not formatters[v] then
|
||||
rspamd_logger.errx(rspamd_config, 'Rule %s has invalid formatter %s', k, v)
|
||||
return false
|
||||
else
|
||||
return true
|
||||
end
|
||||
end,
|
||||
}
|
||||
local backend_check = {
|
||||
default = function(k, rule)
|
||||
local reqset = backend_required_elements[rule.backend]
|
||||
if reqset then
|
||||
for _, e in ipairs(reqset) do
|
||||
if not rule[e] then
|
||||
rspamd_logger.errx(rspamd_config, 'Rule %s misses required setting %s', k, e)
|
||||
settings.rules[k] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
for sett, v in pairs(rule) do
|
||||
local f = check_element[sett]
|
||||
if f then
|
||||
if not f(sett, v) then
|
||||
settings.rules[k] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end,
|
||||
}
|
||||
backend_check.redis_pubsub = function(k, rule)
|
||||
if not redis_params then
|
||||
redis_params = rspamd_parse_redis_server(N)
|
||||
end
|
||||
if not redis_params then
|
||||
rspamd_logger.errx(rspamd_config, 'No redis servers are specified')
|
||||
settings.rules[k] = nil
|
||||
else
|
||||
backend_check.default(k, rule)
|
||||
end
|
||||
end
|
||||
setmetatable(backend_check, {
|
||||
__index = function()
|
||||
return backend_check.default
|
||||
end,
|
||||
})
|
||||
for k, v in pairs(settings.rules) do
|
||||
if type(v) == 'table' then
|
||||
local backend = v.backend
|
||||
if not backend then
|
||||
rspamd_logger.errx(rspamd_config, 'Rule %s has no backend', k)
|
||||
settings.rules[k] = nil
|
||||
elseif not pushers[backend] then
|
||||
rspamd_logger.errx(rspamd_config, 'Rule %s has invalid backend %s', k, backend)
|
||||
settings.rules[k] = nil
|
||||
else
|
||||
local f = backend_check[backend]
|
||||
f(k, v)
|
||||
end
|
||||
else
|
||||
rspamd_logger.errx(rspamd_config, 'Rule %s has bad type: %s', k, type(v))
|
||||
settings.rules[k] = nil
|
||||
end
|
||||
end
|
||||
|
||||
local function gen_exporter(rule)
|
||||
return function (task)
|
||||
if task:has_flag('skip') then return end
|
||||
local selector = rule.selector or 'default'
|
||||
local selected = selectors[selector](task)
|
||||
if selected then
|
||||
lua_util.debugm(N, task, 'Message selected for processing')
|
||||
local formatter = rule.formatter or 'default'
|
||||
local formatted, extra = formatters[formatter](task, rule)
|
||||
if formatted then
|
||||
pushers[rule.backend](task, formatted, rule, extra)
|
||||
else
|
||||
lua_util.debugm(N, task, 'Formatter [%s] returned non-truthy value [%s]', formatter, formatted)
|
||||
end
|
||||
else
|
||||
lua_util.debugm(N, task, 'Selector [%s] returned non-truthy value [%s]', selector, selected)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if not next(settings.rules) then
|
||||
rspamd_logger.errx(rspamd_config, 'No rules enabled')
|
||||
lua_util.disable_module(N, "config")
|
||||
end
|
||||
for k, r in pairs(settings.rules) do
|
||||
rspamd_config:register_symbol({
|
||||
name = 'EXPORT_METADATA_' .. k,
|
||||
type = 'idempotent',
|
||||
callback = gen_exporter(r),
|
||||
priority = 10,
|
||||
flags = 'empty,explicit_disable,ignore_passthrough',
|
||||
})
|
||||
end
|
||||
@@ -1,12 +1,13 @@
|
||||
FROM debian:bullseye-slim
|
||||
LABEL maintainer "The Infrastructure Company GmbH <info@servercow.de>"
|
||||
FROM debian:bookworm-slim
|
||||
|
||||
LABEL maintainer="The Infrastructure Company GmbH <info@servercow.de>"
|
||||
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
ARG DEBIAN_VERSION=bullseye
|
||||
ARG DEBIAN_VERSION=bookworm
|
||||
ARG SOGO_DEBIAN_REPOSITORY=http://www.axis.cz/linux/debian
|
||||
# renovate: datasource=github-releases depName=tianon/gosu versioning=semver-coerced extractVersion=^(?<version>.*)$
|
||||
ARG GOSU_VERSION=1.17
|
||||
ENV LC_ALL C
|
||||
ENV LC_ALL=C
|
||||
|
||||
# Prerequisites
|
||||
RUN echo "Building from repository $SOGO_DEBIAN_REPOSITORY" \
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@version: 3.28
|
||||
@version: 3.38
|
||||
@include "scl.conf"
|
||||
options {
|
||||
chain_hostnames(off);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@version: 3.28
|
||||
@version: 3.38
|
||||
@include "scl.conf"
|
||||
options {
|
||||
chain_hostnames(off);
|
||||
|
||||
@@ -1,7 +1,15 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [[ "${SKIP_SOLR}" =~ ^([yY][eE][sS]|[yY])+$ ]]; then
|
||||
if [[ "${FLATCURVE_EXPERIMENTAL}" =~ ^([yY][eE][sS]|[yY])+$ ]]; then
|
||||
echo "FLATCURVE_EXPERIMENTAL=y, skipping Solr but enabling Flatcurve as FTS for Dovecot!"
|
||||
echo "Solr will be removed in the future!"
|
||||
sleep 365d
|
||||
exit 0
|
||||
elif [[ "${SKIP_SOLR}" =~ ^([yY][eE][sS]|[yY])+$ ]]; then
|
||||
echo "SKIP_SOLR=y, skipping Solr..."
|
||||
echo "HINT: You could try the newer FTS Backend Flatcurve, which is currently in experimental state..."
|
||||
echo "Simply set FLATCURVE_EXPERIMENTAL=y inside your mailcow.conf and restart the stack afterwards!"
|
||||
echo "Solr will be removed in the future!"
|
||||
sleep 365d
|
||||
exit 0
|
||||
fi
|
||||
@@ -57,5 +65,11 @@ if [[ "${1}" == "--bootstrap" ]]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "Starting up Solr..."
|
||||
echo -e "\e[31mSolr is deprecated! You can try the new FTS System now by enabling FLATCURVE_EXPERIMENTAL=y inside mailcow.conf and restarting the stack\e[0m"
|
||||
echo -e "\e[31mSolr will be removed completely soon!\e[0m"
|
||||
|
||||
sleep 15
|
||||
|
||||
exec gosu solr solr-foreground
|
||||
|
||||
|
||||
@@ -1,18 +1,21 @@
|
||||
FROM alpine:3.18
|
||||
FROM alpine:3.20
|
||||
|
||||
LABEL maintainer "The Infrastructure Company GmbH <info@servercow.de>"
|
||||
LABEL maintainer = "The Infrastructure Company GmbH <info@servercow.de>"
|
||||
|
||||
RUN apk add --update --no-cache \
|
||||
curl \
|
||||
bind-tools \
|
||||
coreutils \
|
||||
unbound \
|
||||
bash \
|
||||
openssl \
|
||||
drill \
|
||||
tzdata \
|
||||
syslog-ng \
|
||||
supervisor \
|
||||
&& curl -o /etc/unbound/root.hints https://www.internic.net/domain/named.cache \
|
||||
&& chown root:unbound /etc/unbound \
|
||||
&& adduser unbound tty \
|
||||
&& adduser unbound tty \
|
||||
&& chmod 775 /etc/unbound
|
||||
|
||||
EXPOSE 53/udp 53/tcp
|
||||
@@ -21,9 +24,13 @@ COPY docker-entrypoint.sh /docker-entrypoint.sh
|
||||
|
||||
# healthcheck (dig, ping)
|
||||
COPY healthcheck.sh /healthcheck.sh
|
||||
COPY syslog-ng.conf /etc/syslog-ng/syslog-ng.conf
|
||||
COPY supervisord.conf /etc/supervisor/supervisord.conf
|
||||
COPY stop-supervisor.sh /usr/local/sbin/stop-supervisor.sh
|
||||
|
||||
RUN chmod +x /healthcheck.sh
|
||||
HEALTHCHECK --interval=30s --timeout=30s CMD [ "/healthcheck.sh" ]
|
||||
HEALTHCHECK --interval=30s --timeout=10s \
|
||||
CMD sh -c '[ -f /tmp/healthcheck_status ] && [ "$(cat /tmp/healthcheck_status)" -eq 0 ] || exit 1'
|
||||
|
||||
ENTRYPOINT ["/docker-entrypoint.sh"]
|
||||
|
||||
CMD ["/usr/sbin/unbound"]
|
||||
CMD exec /usr/bin/supervisord -c /etc/supervisor/supervisord.conf
|
||||
|
||||
@@ -1,72 +1,102 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Skip Unbound (DNS Resolver) Healthchecks (NOT Recommended!)
|
||||
if [[ "${SKIP_UNBOUND_HEALTHCHECK}" =~ ^([yY][eE][sS]|[yY])+$ ]]; then
|
||||
SKIP_UNBOUND_HEALTHCHECK=y
|
||||
fi
|
||||
STATUS_FILE="/tmp/healthcheck_status"
|
||||
RUNS=0
|
||||
|
||||
# Declare log function for logfile inside container
|
||||
function log_to_file() {
|
||||
echo "$(date +"%Y-%m-%d %H:%M:%S"): $1" > /var/log/healthcheck.log
|
||||
# Declare log function for logfile to stdout
|
||||
function log_to_stdout() {
|
||||
echo "$(date +"%Y-%m-%d %H:%M:%S"): $1"
|
||||
}
|
||||
|
||||
# General Ping function to check general pingability
|
||||
function check_ping() {
|
||||
declare -a ipstoping=("1.1.1.1" "8.8.8.8" "9.9.9.9")
|
||||
declare -a ipstoping=("1.1.1.1" "8.8.8.8" "9.9.9.9")
|
||||
local fail_tolerance=1
|
||||
local failures=0
|
||||
|
||||
for ip in "${ipstoping[@]}" ; do
|
||||
ping -q -c 3 -w 5 "$ip"
|
||||
if [ $? -ne 0 ]; then
|
||||
log_to_file "Healthcheck: Couldn't ping $ip for 5 seconds... Gave up!"
|
||||
log_to_file "Please check your internet connection or firewall rules to fix this error, because a simple ping test should always go through from the unbound container!"
|
||||
return 1
|
||||
fi
|
||||
for ip in "${ipstoping[@]}" ; do
|
||||
success=false
|
||||
for ((i=1; i<=3; i++)); do
|
||||
ping -q -c 3 -w 5 "$ip" > /dev/null
|
||||
if [ $? -eq 0 ]; then
|
||||
success=true
|
||||
break
|
||||
else
|
||||
log_to_stdout "Healthcheck: Failed to ping $ip on attempt $i. Trying again..."
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$success" = false ]; then
|
||||
log_to_stdout "Healthcheck: Couldn't ping $ip after 3 attempts. Marking this IP as failed."
|
||||
((failures++))
|
||||
fi
|
||||
done
|
||||
|
||||
if [ $failures -gt $fail_tolerance ]; then
|
||||
log_to_stdout "Healthcheck: Too many ping failures ($fail_tolerance failures allowed, you got $failures failures), marking Healthcheck as unhealthy..."
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
|
||||
log_to_file "Healthcheck: Ping Checks WORKING properly!"
|
||||
return 0
|
||||
}
|
||||
|
||||
# General DNS Resolve Check against Unbound Resolver himself
|
||||
function check_dns() {
|
||||
declare -a domains=("mailcow.email" "github.com" "hub.docker.com")
|
||||
declare -a domains=("fuzzy.mailcow.email" "github.com" "hub.docker.com")
|
||||
local fail_tolerance=1
|
||||
local failures=0
|
||||
|
||||
for domain in "${domains[@]}" ; do
|
||||
for ((i=1; i<=3; i++)); do
|
||||
dig +short +timeout=2 +tries=1 "$domain" @127.0.0.1 > /dev/null
|
||||
if [ $? -ne 0 ]; then
|
||||
log_to_file "Healthcheck: DNS Resolution Failed on $i attempt! Trying again..."
|
||||
if [ $i -eq 3 ]; then
|
||||
log_to_file "Healthcheck: DNS Resolution not possible after $i attempts... Gave up!"
|
||||
log_to_file "Maybe check your outbound firewall, as it needs to resolve DNS over TCP AND UDP!"
|
||||
return 1
|
||||
fi
|
||||
for domain in "${domains[@]}" ; do
|
||||
success=false
|
||||
for ((i=1; i<=3; i++)); do
|
||||
dig_output=$(dig +short +timeout=2 +tries=1 "$domain" @127.0.0.1 2>/dev/null)
|
||||
dig_rc=$?
|
||||
|
||||
if [ $dig_rc -ne 0 ] || [ -z "$dig_output" ]; then
|
||||
log_to_stdout "Healthcheck: DNS Resolution Failed on attempt $i for $domain! Trying again..."
|
||||
else
|
||||
success=true
|
||||
break
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
||||
log_to_file "Healthcheck: DNS Resolver WORKING properly!"
|
||||
return 0
|
||||
|
||||
if [ "$success" = false ]; then
|
||||
log_to_stdout "Healthcheck: DNS Resolution not possible after 3 attempts for $domain... Gave up!"
|
||||
((failures++))
|
||||
fi
|
||||
done
|
||||
|
||||
if [ $failures -gt $fail_tolerance ]; then
|
||||
log_to_stdout "Healthcheck: Too many DNS failures ($fail_tolerance failures allowed, you got $failures failures), marking Healthcheck as unhealthy..."
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
if [[ ${SKIP_UNBOUND_HEALTHCHECK} == "y" ]]; then
|
||||
log_to_file "Healthcheck: ALL CHECKS WERE SKIPPED! Unbound is healthy!"
|
||||
exit 0
|
||||
fi
|
||||
while true; do
|
||||
|
||||
# run checks, if check is not returning 0 (return value if check is ok), healthcheck will exit with 1 (marked in docker as unhealthy)
|
||||
check_ping
|
||||
if [[ ${SKIP_UNBOUND_HEALTHCHECK} == "y" ]]; then
|
||||
log_to_stdout "Healthcheck: ALL CHECKS WERE SKIPPED! Unbound is healthy!"
|
||||
echo "0" > $STATUS_FILE
|
||||
sleep 365d
|
||||
fi
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
exit 1
|
||||
fi
|
||||
# run checks, if check is not returning 0 (return value if check is ok), healthcheck will exit with 1 (marked in docker as unhealthy)
|
||||
check_ping
|
||||
PING_STATUS=$?
|
||||
|
||||
check_dns
|
||||
check_dns
|
||||
DNS_STATUS=$?
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
exit 1
|
||||
fi
|
||||
if [ $PING_STATUS -ne 0 ] || [ $DNS_STATUS -ne 0 ]; then
|
||||
echo "1" > $STATUS_FILE
|
||||
|
||||
log_to_file "Healthcheck: ALL CHECKS WERE SUCCESSFUL! Unbound is healthy!"
|
||||
exit 0
|
||||
else
|
||||
echo "0" > $STATUS_FILE
|
||||
fi
|
||||
|
||||
sleep 30
|
||||
|
||||
done
|
||||
10
data/Dockerfiles/unbound/stop-supervisor.sh
Executable file
10
data/Dockerfiles/unbound/stop-supervisor.sh
Executable file
@@ -0,0 +1,10 @@
|
||||
#!/bin/bash
|
||||
|
||||
printf "READY\n";
|
||||
|
||||
while read line; do
|
||||
echo "Processing Event: $line" >&2;
|
||||
kill -3 $(cat "/var/run/supervisord.pid")
|
||||
done < /dev/stdin
|
||||
|
||||
rm -rf /tmp/healthcheck_status
|
||||
32
data/Dockerfiles/unbound/supervisord.conf
Normal file
32
data/Dockerfiles/unbound/supervisord.conf
Normal file
@@ -0,0 +1,32 @@
|
||||
[supervisord]
|
||||
nodaemon=true
|
||||
user=root
|
||||
pidfile=/var/run/supervisord.pid
|
||||
|
||||
[program:syslog-ng]
|
||||
command=/usr/sbin/syslog-ng --foreground --no-caps
|
||||
stdout_logfile=/dev/stdout
|
||||
stdout_logfile_maxbytes=0
|
||||
stderr_logfile=/dev/stderr
|
||||
stderr_logfile_maxbytes=0
|
||||
autostart=true
|
||||
|
||||
[program:unbound]
|
||||
command=/usr/sbin/unbound
|
||||
stdout_logfile=/dev/stdout
|
||||
stdout_logfile_maxbytes=0
|
||||
stderr_logfile=/dev/stderr
|
||||
stderr_logfile_maxbytes=0
|
||||
autorestart=true
|
||||
|
||||
[program:unbound-healthcheck]
|
||||
command=/bin/bash /healthcheck.sh
|
||||
stdout_logfile=/dev/stdout
|
||||
stdout_logfile_maxbytes=0
|
||||
stderr_logfile=/dev/stderr
|
||||
stderr_logfile_maxbytes=0
|
||||
autorestart=true
|
||||
|
||||
[eventlistener:processes]
|
||||
command=/usr/local/sbin/stop-supervisor.sh
|
||||
events=PROCESS_STATE_STOPPED, PROCESS_STATE_EXITED, PROCESS_STATE_FATAL
|
||||
21
data/Dockerfiles/unbound/syslog-ng.conf
Normal file
21
data/Dockerfiles/unbound/syslog-ng.conf
Normal file
@@ -0,0 +1,21 @@
|
||||
@version: 4.5
|
||||
@include "scl.conf"
|
||||
options {
|
||||
chain_hostnames(off);
|
||||
flush_lines(0);
|
||||
use_dns(no);
|
||||
use_fqdn(no);
|
||||
owner("root"); group("adm"); perm(0640);
|
||||
stats(freq(0));
|
||||
keep_timestamp(no);
|
||||
bad_hostname("^gconfd$");
|
||||
};
|
||||
source s_dgram {
|
||||
unix-dgram("/dev/log");
|
||||
internal();
|
||||
};
|
||||
destination d_stdout { pipe("/dev/stdout"); };
|
||||
log {
|
||||
source(s_dgram);
|
||||
destination(d_stdout);
|
||||
};
|
||||
@@ -1,5 +1,6 @@
|
||||
FROM alpine:3.18
|
||||
LABEL maintainer "The Infrastructure Company GmbH <info@servercow.de>"
|
||||
FROM alpine:3.20
|
||||
|
||||
LABEL maintainer = "The Infrastructure Company GmbH <info@servercow.de>"
|
||||
|
||||
# Installation
|
||||
RUN apk add --update \
|
||||
|
||||
@@ -169,9 +169,13 @@ function notify_error() {
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Escape subject and body (https://stackoverflow.com/a/2705678)
|
||||
ESCAPED_SUBJECT=$(echo ${SUBJECT} | sed -e 's/[\/&]/\\&/g')
|
||||
ESCAPED_BODY=$(echo ${BODY} | sed -e 's/[\/&]/\\&/g')
|
||||
|
||||
# Replace subject and body placeholders
|
||||
WEBHOOK_BODY=$(echo ${WATCHDOG_NOTIFY_WEBHOOK_BODY} | sed "s/\$SUBJECT\|\${SUBJECT}/$SUBJECT/g" | sed "s/\$BODY\|\${BODY}/$BODY/g")
|
||||
|
||||
WEBHOOK_BODY=$(echo ${WATCHDOG_NOTIFY_WEBHOOK_BODY} | sed -e "s/\$SUBJECT\|\${SUBJECT}/$ESCAPED_SUBJECT/g" -e "s/\$BODY\|\${BODY}/$ESCAPED_BODY/g")
|
||||
|
||||
# POST to webhook
|
||||
curl -X POST -H "Content-Type: application/json" ${CURL_VERBOSE} -d "${WEBHOOK_BODY}" ${WATCHDOG_NOTIFY_WEBHOOK}
|
||||
|
||||
@@ -191,12 +195,12 @@ get_container_ip() {
|
||||
else
|
||||
sleep 0.5
|
||||
# get long container id for exact match
|
||||
CONTAINER_ID=($(curl --silent --insecure https://dockerapi/containers/json | jq -r ".[] | {name: .Config.Labels[\"com.docker.compose.service\"], project: .Config.Labels[\"com.docker.compose.project\"], id: .Id}" | jq -rc "select( .name | tostring == \"${1}\") | select( .project | tostring | contains(\"${COMPOSE_PROJECT_NAME,,}\")) | .id"))
|
||||
CONTAINER_ID=($(curl --silent --insecure https://dockerapi.${COMPOSE_PROJECT_NAME}_mailcow-network/containers/json | jq -r ".[] | {name: .Config.Labels[\"com.docker.compose.service\"], project: .Config.Labels[\"com.docker.compose.project\"], id: .Id}" | jq -rc "select( .name | tostring == \"${1}\") | select( .project | tostring | contains(\"${COMPOSE_PROJECT_NAME,,}\")) | .id"))
|
||||
# returned id can have multiple elements (if scaled), shuffle for random test
|
||||
CONTAINER_ID=($(printf "%s\n" "${CONTAINER_ID[@]}" | shuf))
|
||||
if [[ ! -z ${CONTAINER_ID} ]]; then
|
||||
for matched_container in "${CONTAINER_ID[@]}"; do
|
||||
CONTAINER_IPS=($(curl --silent --insecure https://dockerapi/containers/${matched_container}/json | jq -r '.NetworkSettings.Networks[].IPAddress'))
|
||||
CONTAINER_IPS=($(curl --silent --insecure https://dockerapi.${COMPOSE_PROJECT_NAME}_mailcow-network/containers/${matched_container}/json | jq -r '.NetworkSettings.Networks[].IPAddress'))
|
||||
for ip_match in "${CONTAINER_IPS[@]}"; do
|
||||
# grep will do nothing if one of these vars is empty
|
||||
[[ -z ${ip_match} ]] && continue
|
||||
@@ -716,7 +720,7 @@ rspamd_checks() {
|
||||
From: watchdog@localhost
|
||||
|
||||
Empty
|
||||
' | usr/bin/curl --max-time 10 -s --data-binary @- --unix-socket /var/lib/rspamd/rspamd.sock http://rspamd/scan | jq -rc .default.required_score | sed 's/\..*//' )
|
||||
' | usr/bin/curl --max-time 10 -s --data-binary @- --unix-socket /var/lib/rspamd/rspamd.sock http://rspamd.${COMPOSE_PROJECT_NAME}_mailcow-network/scan | jq -rc .default.required_score | sed 's/\..*//' )
|
||||
if [[ ${SCORE} -ne 9999 ]]; then
|
||||
echo "Rspamd settings check failed, score returned: ${SCORE}" 2>> /tmp/rspamd-mailcow 1>&2
|
||||
err_count=$(( ${err_count} + 1))
|
||||
@@ -1095,12 +1099,12 @@ while true; do
|
||||
elif [[ ${com_pipe_answer} =~ .+-mailcow ]]; then
|
||||
kill -STOP ${BACKGROUND_TASKS[*]}
|
||||
sleep 10
|
||||
CONTAINER_ID=$(curl --silent --insecure https://dockerapi/containers/json | jq -r ".[] | {name: .Config.Labels[\"com.docker.compose.service\"], project: .Config.Labels[\"com.docker.compose.project\"], id: .Id}" | jq -rc "select( .name | tostring | contains(\"${com_pipe_answer}\")) | select( .project | tostring | contains(\"${COMPOSE_PROJECT_NAME,,}\")) | .id")
|
||||
CONTAINER_ID=$(curl --silent --insecure https://dockerapi.${COMPOSE_PROJECT_NAME}_mailcow-network/containers/json | jq -r ".[] | {name: .Config.Labels[\"com.docker.compose.service\"], project: .Config.Labels[\"com.docker.compose.project\"], id: .Id}" | jq -rc "select( .name | tostring | contains(\"${com_pipe_answer}\")) | select( .project | tostring | contains(\"${COMPOSE_PROJECT_NAME,,}\")) | .id")
|
||||
if [[ ! -z ${CONTAINER_ID} ]]; then
|
||||
if [[ "${com_pipe_answer}" == "php-fpm-mailcow" ]]; then
|
||||
HAS_INITDB=$(curl --silent --insecure -XPOST https://dockerapi/containers/${CONTAINER_ID}/top | jq '.msg.Processes[] | contains(["php -c /usr/local/etc/php -f /web/inc/init_db.inc.php"])' | grep true)
|
||||
HAS_INITDB=$(curl --silent --insecure -XPOST https://dockerapi.${COMPOSE_PROJECT_NAME}_mailcow-network/containers/${CONTAINER_ID}/top | jq '.msg.Processes[] | contains(["php -c /usr/local/etc/php -f /web/inc/init_db.inc.php"])' | grep true)
|
||||
fi
|
||||
S_RUNNING=$(($(date +%s) - $(curl --silent --insecure https://dockerapi/containers/${CONTAINER_ID}/json | jq .State.StartedAt | xargs -n1 date +%s -d)))
|
||||
S_RUNNING=$(($(date +%s) - $(curl --silent --insecure https://dockerapi.${COMPOSE_PROJECT_NAME}_mailcow-network/containers/${CONTAINER_ID}/json | jq .State.StartedAt | xargs -n1 date +%s -d)))
|
||||
if [ ${S_RUNNING} -lt 360 ]; then
|
||||
log_msg "Container is running for less than 360 seconds, skipping action..."
|
||||
elif [[ ! -z ${HAS_INITDB} ]]; then
|
||||
@@ -1108,7 +1112,7 @@ while true; do
|
||||
sleep 60
|
||||
else
|
||||
log_msg "Sending restart command to ${CONTAINER_ID}..."
|
||||
curl --silent --insecure -XPOST https://dockerapi/containers/${CONTAINER_ID}/restart
|
||||
curl --silent --insecure -XPOST https://dockerapi.${COMPOSE_PROJECT_NAME}_mailcow-network/containers/${CONTAINER_ID}/restart
|
||||
notify_error "${com_pipe_answer}"
|
||||
log_msg "Wait for restarted container to settle and continue watching..."
|
||||
sleep 35
|
||||
|
||||
29
data/assets/templates/pw_reset_html.tpl
Normal file
29
data/assets/templates/pw_reset_html.tpl
Normal file
@@ -0,0 +1,29 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta name="x-apple-disable-message-reformatting" />
|
||||
<style>
|
||||
body {
|
||||
font-family: Helvetica, Arial, Sans-Serif;
|
||||
}
|
||||
/* mobile devices */
|
||||
@media all and (max-width: 480px) {
|
||||
.mob {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
Hello {{username2}},<br><br>
|
||||
|
||||
Somebody requested a new password for the {{hostname}} account associated with {{username}}.<br>
|
||||
<small>Date of the password reset request: {{date}}</small><br><br>
|
||||
|
||||
You can reset your password by clicking the link below:<br>
|
||||
<a href="{{link}}">{{link}}</a><br><br>
|
||||
|
||||
The link will be valid for the next {{token_lifetime}} minutes.<br><br>
|
||||
|
||||
If you did not request a new password, please ignore this email.<br>
|
||||
</body>
|
||||
</html>
|
||||
11
data/assets/templates/pw_reset_text.tpl
Normal file
11
data/assets/templates/pw_reset_text.tpl
Normal file
@@ -0,0 +1,11 @@
|
||||
Hello {{username2}},
|
||||
|
||||
Somebody requested a new password for the {{hostname}} account associated with {{username}}.
|
||||
Date of the password reset request: {{date}}
|
||||
|
||||
You can reset your password by clicking the link below:
|
||||
{{link}}
|
||||
|
||||
The link will be valid for the next {{token_lifetime}} minutes.
|
||||
|
||||
If you did not request a new password, please ignore this email.
|
||||
@@ -10,6 +10,7 @@
|
||||
auth_mechanisms = plain login
|
||||
#mail_debug = yes
|
||||
#auth_debug = yes
|
||||
#log_debug = category=fts-flatcurve # Activate Logging for Flatcurve FTS Searchings
|
||||
log_path = syslog
|
||||
disable_plaintext_auth = yes
|
||||
# Uncomment on NFS share
|
||||
@@ -194,9 +195,6 @@ plugin {
|
||||
acl_shared_dict = file:/var/vmail/shared-mailboxes.db
|
||||
acl = vfile
|
||||
acl_user = %u
|
||||
fts = solr
|
||||
fts_autoindex = yes
|
||||
fts_solr = url=http://solr:8983/solr/dovecot-fts/
|
||||
quota = dict:Userquota::proxy::sqlquota
|
||||
quota_rule2 = Trash:storage=+100%%
|
||||
sieve = /var/vmail/sieve/%u.sieve
|
||||
@@ -305,6 +303,7 @@ replication_dsync_parameters = -d -l 30 -U -n INBOX
|
||||
!include_try /etc/dovecot/extra.conf
|
||||
!include_try /etc/dovecot/sogo-sso.conf
|
||||
!include_try /etc/dovecot/shared_namespace.conf
|
||||
!include_try /etc/dovecot/conf.d/fts.conf
|
||||
# </Includes>
|
||||
default_client_limit = 10400
|
||||
default_vsz_limit = 1024 M
|
||||
|
||||
@@ -289,5 +289,20 @@ namespace inbox {
|
||||
mailbox "Kladde" {
|
||||
special_use = \Drafts
|
||||
}
|
||||
mailbox "Πρόχειρα" {
|
||||
special_use = \Drafts
|
||||
}
|
||||
mailbox "Απεσταλμένα" {
|
||||
special_use = \Sent
|
||||
}
|
||||
mailbox "Κάδος απορριμάτων" {
|
||||
special_use = \Trash
|
||||
}
|
||||
mailbox "Ανεπιθύμητα" {
|
||||
special_use = \Junk
|
||||
}
|
||||
mailbox "Αρχειοθετημένα" {
|
||||
special_use = \Archive
|
||||
}
|
||||
prefix =
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
if /^\s*Received:.*Authenticated sender.*\(Postcow\)/
|
||||
#/^Received: from .*? \([\w-.]* \[.*?\]\)\s+\(Authenticated sender: (.+)\)\s+by.+\(Postcow\) with (E?SMTPS?A?) id ([A-F0-9]+).+;.*?/
|
||||
/^Received: from .*? \([\w-.]* \[.*?\]\)(.*|\n.*)\(Authenticated sender: (.+)\)\s+by.+\(Postcow\) with (.*)/
|
||||
/^Received: from .*? \([\w\-.]* \[.*?\]\)(.*|\n.*)\(Authenticated sender: (.+)\)\s+by.+\(Postcow\) with (.*)/
|
||||
REPLACE Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with $3
|
||||
endif
|
||||
if /^\s*Received: from.* \(.*dovecot-mailcow.*mailcow-network.*\).*\(Postcow\)/
|
||||
|
||||
@@ -114,14 +114,14 @@ smtpd_tls_loglevel = 1
|
||||
|
||||
# Mandatory protocols and ciphers are used when a connections is enforced to use TLS
|
||||
# Does _not_ apply to enforced incoming TLS settings per mailbox
|
||||
smtp_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
|
||||
lmtp_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
|
||||
smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
|
||||
smtp_tls_mandatory_protocols = >=TLSv1.2
|
||||
lmtp_tls_mandatory_protocols = >=TLSv1.2
|
||||
smtpd_tls_mandatory_protocols = >=TLSv1.2
|
||||
smtpd_tls_mandatory_ciphers = high
|
||||
|
||||
smtp_tls_protocols = !SSLv2, !SSLv3
|
||||
lmtp_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
|
||||
smtpd_tls_protocols = !SSLv2, !SSLv3
|
||||
smtp_tls_protocols = >=TLSv1.2
|
||||
lmtp_tls_protocols = >=TLSv1.2
|
||||
smtpd_tls_protocols = >=TLSv1.2
|
||||
|
||||
smtpd_tls_security_level = may
|
||||
tls_preempt_cipherlist = yes
|
||||
@@ -163,12 +163,12 @@ transport_maps = pcre:/opt/postfix/conf/custom_transport.pcre,
|
||||
proxy:mysql:/opt/postfix/conf/sql/mysql_transport_maps.cf
|
||||
smtp_sasl_auth_soft_bounce = no
|
||||
postscreen_discard_ehlo_keywords = silent-discard, dsn, chunking
|
||||
smtpd_discard_ehlo_keywords = chunking
|
||||
compatibility_level = 2
|
||||
smtpd_discard_ehlo_keywords = chunking, silent-discard
|
||||
compatibility_level = 3.7
|
||||
smtputf8_enable = no
|
||||
# Define protocols for SMTPS and submission service
|
||||
submission_smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
|
||||
smtps_smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
|
||||
submission_smtpd_tls_mandatory_protocols = >=TLSv1.2
|
||||
smtps_smtpd_tls_mandatory_protocols = >=TLSv1.2
|
||||
parent_domain_matches_subdomains = debug_peer_list,fast_flush_domains,mynetworks,qmqpd_authorized_clients
|
||||
|
||||
# DO NOT EDIT ANYTHING BELOW #
|
||||
|
||||
@@ -4,7 +4,6 @@ smtp inet n - n - 1 postscreen
|
||||
-o postscreen_upstream_proxy_protocol=haproxy
|
||||
-o syslog_name=haproxy
|
||||
smtpd pass - - n - - smtpd
|
||||
-o smtpd_helo_restrictions=permit_mynetworks,reject_non_fqdn_helo_hostname
|
||||
-o smtpd_sasl_auth_enable=no
|
||||
-o smtpd_sender_restrictions=permit_mynetworks,reject_unlisted_sender,reject_unknown_sender_domain
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Whitelist generated by Postwhite v3.4 on Mon Apr 1 00:15:02 UTC 2024
|
||||
# Whitelist generated by Postwhite v3.4 on Thu Aug 1 00:16:45 UTC 2024
|
||||
# https://github.com/stevejenkins/postwhite/
|
||||
# 2009 total rules
|
||||
# 1954 total rules
|
||||
2a00:1450:4000::/36 permit
|
||||
2a01:111:f400::/48 permit
|
||||
2a01:111:f403:8000::/50 permit
|
||||
@@ -13,37 +13,35 @@
|
||||
2.207.151.53 permit
|
||||
3.70.123.177 permit
|
||||
3.93.157.0/24 permit
|
||||
3.94.40.108 permit
|
||||
3.129.120.190 permit
|
||||
3.137.16.58 permit
|
||||
3.210.190.0/24 permit
|
||||
8.20.114.31 permit
|
||||
8.25.194.0/23 permit
|
||||
8.25.196.0/23 permit
|
||||
8.39.54.0/23 permit
|
||||
8.40.222.0/23 permit
|
||||
10.162.0.0/16 permit
|
||||
12.130.86.238 permit
|
||||
13.70.32.43 permit
|
||||
13.72.50.45 permit
|
||||
13.74.143.28 permit
|
||||
13.78.233.182 permit
|
||||
13.92.31.129 permit
|
||||
13.110.208.0/21 permit
|
||||
13.110.209.0/24 permit
|
||||
13.110.216.0/22 permit
|
||||
13.110.224.0/20 permit
|
||||
13.111.0.0/16 permit
|
||||
13.111.191.0/24 permit
|
||||
15.200.21.50 permit
|
||||
15.200.44.248 permit
|
||||
15.200.201.185 permit
|
||||
17.41.0.0/16 permit
|
||||
17.57.155.0/24 permit
|
||||
17.57.156.0/24 permit
|
||||
17.58.0.0/16 permit
|
||||
17.142.0.0/15 permit
|
||||
18.156.89.250 permit
|
||||
18.157.243.190 permit
|
||||
18.194.95.56 permit
|
||||
18.198.96.88 permit
|
||||
18.208.124.128/25 permit
|
||||
18.216.232.154 permit
|
||||
18.235.27.253 permit
|
||||
18.236.40.242 permit
|
||||
18.236.56.161 permit
|
||||
20.51.6.32/30 permit
|
||||
@@ -65,10 +63,8 @@
|
||||
20.107.239.64/30 permit
|
||||
20.112.250.133 permit
|
||||
20.118.139.208/30 permit
|
||||
20.185.213.160/27 permit
|
||||
20.185.213.224/27 permit
|
||||
20.141.10.196 permit
|
||||
20.185.214.0/27 permit
|
||||
20.185.214.2 permit
|
||||
20.185.214.32/27 permit
|
||||
20.185.214.64/27 permit
|
||||
20.231.239.246 permit
|
||||
@@ -107,21 +103,21 @@
|
||||
35.176.132.251 permit
|
||||
35.190.247.0/24 permit
|
||||
35.191.0.0/16 permit
|
||||
35.205.92.9 permit
|
||||
35.242.169.159 permit
|
||||
37.218.248.47 permit
|
||||
37.218.249.47 permit
|
||||
37.218.251.62 permit
|
||||
39.156.163.64/29 permit
|
||||
40.71.187.0/24 permit
|
||||
40.92.0.0/15 permit
|
||||
40.92.0.0/16 permit
|
||||
40.107.0.0/16 permit
|
||||
40.112.65.63 permit
|
||||
43.228.184.0/22 permit
|
||||
44.206.138.57 permit
|
||||
44.217.45.156 permit
|
||||
44.236.56.93 permit
|
||||
44.238.220.251 permit
|
||||
46.19.168.0/23 permit
|
||||
46.19.170.16 permit
|
||||
46.226.48.0/21 permit
|
||||
46.228.36.37 permit
|
||||
@@ -182,11 +178,8 @@
|
||||
50.18.125.237 permit
|
||||
50.18.126.162 permit
|
||||
50.31.32.0/19 permit
|
||||
50.56.130.220 permit
|
||||
50.56.130.221 permit
|
||||
51.137.58.21 permit
|
||||
51.140.75.55 permit
|
||||
51.144.100.179 permit
|
||||
50.31.36.205 permit
|
||||
50.56.130.220/30 permit
|
||||
52.1.14.157 permit
|
||||
52.5.230.59 permit
|
||||
52.27.5.72 permit
|
||||
@@ -194,19 +187,19 @@
|
||||
52.28.63.81 permit
|
||||
52.36.138.31 permit
|
||||
52.37.142.146 permit
|
||||
52.50.24.208 permit
|
||||
52.58.216.183 permit
|
||||
52.59.143.3 permit
|
||||
52.60.41.5 permit
|
||||
52.60.115.116 permit
|
||||
52.61.91.9 permit
|
||||
52.71.0.205 permit
|
||||
52.82.172.0/22 permit
|
||||
52.94.124.0/28 permit
|
||||
52.95.48.152/29 permit
|
||||
52.95.49.88/29 permit
|
||||
52.96.91.34 permit
|
||||
52.96.111.82 permit
|
||||
52.96.214.50 permit
|
||||
52.96.172.98 permit
|
||||
52.96.222.194 permit
|
||||
52.96.222.226 permit
|
||||
52.96.223.2 permit
|
||||
@@ -215,8 +208,6 @@
|
||||
52.100.0.0/14 permit
|
||||
52.103.0.0/17 permit
|
||||
52.119.213.144/28 permit
|
||||
52.160.39.140 permit
|
||||
52.165.175.144 permit
|
||||
52.185.106.240/28 permit
|
||||
52.200.59.0/24 permit
|
||||
52.205.61.79 permit
|
||||
@@ -227,15 +218,12 @@
|
||||
52.222.75.85 permit
|
||||
52.222.89.228 permit
|
||||
52.234.172.96/28 permit
|
||||
52.235.253.128 permit
|
||||
52.236.28.240/28 permit
|
||||
52.244.206.214 permit
|
||||
52.247.53.144 permit
|
||||
52.250.107.196 permit
|
||||
52.250.126.174 permit
|
||||
54.90.148.255 permit
|
||||
54.165.19.38 permit
|
||||
54.172.97.247 permit
|
||||
54.174.52.0/24 permit
|
||||
54.174.53.128/30 permit
|
||||
54.174.57.0/24 permit
|
||||
54.174.59.0/24 permit
|
||||
54.174.60.0/23 permit
|
||||
@@ -267,7 +255,6 @@
|
||||
62.201.172.32/27 permit
|
||||
62.253.227.114 permit
|
||||
63.80.14.0/23 permit
|
||||
63.111.28.137 permit
|
||||
63.128.21.0/24 permit
|
||||
63.143.57.128/25 permit
|
||||
63.143.59.128/25 permit
|
||||
@@ -283,17 +270,6 @@
|
||||
64.127.115.252 permit
|
||||
64.132.88.0/23 permit
|
||||
64.132.92.0/24 permit
|
||||
64.147.123.17 permit
|
||||
64.147.123.18 permit
|
||||
64.147.123.19 permit
|
||||
64.147.123.20 permit
|
||||
64.147.123.21 permit
|
||||
64.147.123.24 permit
|
||||
64.147.123.25 permit
|
||||
64.147.123.26 permit
|
||||
64.147.123.27 permit
|
||||
64.147.123.28 permit
|
||||
64.147.123.29 permit
|
||||
64.147.123.128/27 permit
|
||||
64.207.219.7 permit
|
||||
64.207.219.8 permit
|
||||
@@ -348,24 +324,9 @@
|
||||
65.110.161.77 permit
|
||||
65.123.29.213 permit
|
||||
65.123.29.220 permit
|
||||
65.154.166.0/24 permit
|
||||
65.212.180.36 permit
|
||||
66.102.0.0/20 permit
|
||||
66.111.4.25 permit
|
||||
66.111.4.26 permit
|
||||
66.111.4.27 permit
|
||||
66.111.4.28 permit
|
||||
66.111.4.29 permit
|
||||
66.111.4.221 permit
|
||||
66.111.4.222 permit
|
||||
66.111.4.224 permit
|
||||
66.111.4.225 permit
|
||||
66.111.4.229 permit
|
||||
66.111.4.230 permit
|
||||
66.119.150.192/26 permit
|
||||
66.135.202.0/27 permit
|
||||
66.135.215.0/24 permit
|
||||
66.135.222.1 permit
|
||||
66.162.193.226/31 permit
|
||||
66.163.184.0/24 permit
|
||||
66.163.185.0/24 permit
|
||||
@@ -471,15 +432,17 @@
|
||||
69.65.42.195 permit
|
||||
69.65.49.192/29 permit
|
||||
69.72.32.0/20 permit
|
||||
69.72.40.93 permit
|
||||
69.72.40.94/31 permit
|
||||
69.72.40.96/30 permit
|
||||
69.72.47.205 permit
|
||||
69.147.84.227 permit
|
||||
69.162.98.0/24 permit
|
||||
69.169.224.0/20 permit
|
||||
69.171.232.0/24 permit
|
||||
69.171.244.0/23 permit
|
||||
70.37.151.128/25 permit
|
||||
70.42.149.0/24 permit
|
||||
70.42.149.35 permit
|
||||
72.3.237.64/28 permit
|
||||
72.14.192.0/18 permit
|
||||
72.21.192.0/19 permit
|
||||
72.21.217.142 permit
|
||||
@@ -595,7 +558,6 @@
|
||||
77.238.189.142 permit
|
||||
77.238.189.146/31 permit
|
||||
77.238.189.148/30 permit
|
||||
81.7.169.128/25 permit
|
||||
81.223.46.0/27 permit
|
||||
82.165.159.2 permit
|
||||
82.165.159.3 permit
|
||||
@@ -1164,7 +1126,6 @@
|
||||
104.47.108.0/23 permit
|
||||
104.130.96.0/28 permit
|
||||
104.130.122.0/23 permit
|
||||
104.214.25.77 permit
|
||||
106.10.144.64/27 permit
|
||||
106.10.144.100/31 permit
|
||||
106.10.144.103 permit
|
||||
@@ -1286,6 +1247,7 @@
|
||||
106.10.244.0/24 permit
|
||||
106.39.212.64/29 permit
|
||||
106.50.16.0/28 permit
|
||||
107.20.18.111 permit
|
||||
107.20.210.250 permit
|
||||
108.174.0.0/24 permit
|
||||
108.174.0.215 permit
|
||||
@@ -1297,6 +1259,7 @@
|
||||
108.175.30.45 permit
|
||||
108.177.8.0/21 permit
|
||||
108.177.96.0/19 permit
|
||||
108.179.144.0/20 permit
|
||||
109.237.142.0/24 permit
|
||||
111.221.23.128/25 permit
|
||||
111.221.26.0/27 permit
|
||||
@@ -1320,8 +1283,6 @@
|
||||
117.120.16.0/21 permit
|
||||
119.42.242.52/31 permit
|
||||
119.42.242.156 permit
|
||||
121.244.91.48 permit
|
||||
122.15.156.182 permit
|
||||
123.126.78.64/29 permit
|
||||
124.108.96.24/31 permit
|
||||
124.108.96.28/31 permit
|
||||
@@ -1377,25 +1338,14 @@
|
||||
134.170.141.64/26 permit
|
||||
134.170.143.0/24 permit
|
||||
134.170.174.0/24 permit
|
||||
135.84.80.0/24 permit
|
||||
135.84.81.0/24 permit
|
||||
135.84.82.0/24 permit
|
||||
135.84.83.0/24 permit
|
||||
135.84.216.0/22 permit
|
||||
136.143.160.0/24 permit
|
||||
136.143.161.0/24 permit
|
||||
136.143.178.49 permit
|
||||
136.143.182.0/23 permit
|
||||
136.143.184.0/24 permit
|
||||
136.143.188.0/24 permit
|
||||
136.143.190.0/23 permit
|
||||
136.147.128.0/20 permit
|
||||
136.147.135.0/24 permit
|
||||
136.147.176.0/20 permit
|
||||
136.147.176.0/24 permit
|
||||
136.147.182.0/24 permit
|
||||
136.147.224.0/20 permit
|
||||
136.179.50.206 permit
|
||||
138.91.172.26 permit
|
||||
139.60.152.0/22 permit
|
||||
139.138.35.44 permit
|
||||
139.138.46.121 permit
|
||||
@@ -1406,6 +1356,12 @@
|
||||
139.180.17.0/24 permit
|
||||
141.148.159.229 permit
|
||||
141.193.32.0/23 permit
|
||||
141.193.184.32/27 permit
|
||||
141.193.184.64/26 permit
|
||||
141.193.184.128/25 permit
|
||||
141.193.185.32/27 permit
|
||||
141.193.185.64/26 permit
|
||||
141.193.185.128/25 permit
|
||||
143.55.224.0/21 permit
|
||||
143.55.232.0/22 permit
|
||||
143.55.236.0/22 permit
|
||||
@@ -1419,8 +1375,7 @@
|
||||
144.178.38.0/24 permit
|
||||
145.253.228.160/29 permit
|
||||
145.253.239.128/29 permit
|
||||
146.20.14.105 permit
|
||||
146.20.14.107 permit
|
||||
146.20.14.104/30 permit
|
||||
146.20.112.0/26 permit
|
||||
146.20.113.0/24 permit
|
||||
146.20.191.0/24 permit
|
||||
@@ -1441,6 +1396,7 @@
|
||||
150.230.98.160 permit
|
||||
152.67.105.195 permit
|
||||
152.69.200.236 permit
|
||||
152.70.155.126 permit
|
||||
155.248.208.51 permit
|
||||
157.55.0.192/26 permit
|
||||
157.55.1.128/26 permit
|
||||
@@ -1451,7 +1407,6 @@
|
||||
157.55.61.0/24 permit
|
||||
157.55.157.128/25 permit
|
||||
157.55.225.0/25 permit
|
||||
157.55.254.216 permit
|
||||
157.56.24.0/25 permit
|
||||
157.56.120.128/26 permit
|
||||
157.56.232.0/21 permit
|
||||
@@ -1495,11 +1450,9 @@
|
||||
163.47.180.0/22 permit
|
||||
163.114.130.16 permit
|
||||
163.114.132.120 permit
|
||||
164.177.132.168 permit
|
||||
164.177.132.169 permit
|
||||
164.177.132.170 permit
|
||||
164.177.132.171 permit
|
||||
165.173.128.0/24 permit
|
||||
163.114.134.16 permit
|
||||
163.114.135.16 permit
|
||||
164.177.132.168/30 permit
|
||||
166.78.68.0/22 permit
|
||||
166.78.68.221 permit
|
||||
166.78.69.169 permit
|
||||
@@ -1508,6 +1461,7 @@
|
||||
167.89.0.0/17 permit
|
||||
167.89.46.159 permit
|
||||
167.89.54.103 permit
|
||||
167.89.60.95 permit
|
||||
167.89.64.9 permit
|
||||
167.89.65.0 permit
|
||||
167.89.65.53 permit
|
||||
@@ -1526,11 +1480,6 @@
|
||||
168.245.12.252 permit
|
||||
168.245.46.9 permit
|
||||
168.245.127.231 permit
|
||||
169.148.129.0/24 permit
|
||||
169.148.131.0/24 permit
|
||||
169.148.142.10 permit
|
||||
169.148.144.0/25 permit
|
||||
169.148.144.10 permit
|
||||
170.10.68.0/22 permit
|
||||
170.10.128.0/24 permit
|
||||
170.10.129.0/24 permit
|
||||
@@ -1575,9 +1524,13 @@
|
||||
185.80.93.227 permit
|
||||
185.80.95.31 permit
|
||||
185.90.20.0/22 permit
|
||||
185.138.56.128/25 permit
|
||||
185.189.236.0/22 permit
|
||||
185.211.120.0/22 permit
|
||||
185.250.236.0/22 permit
|
||||
185.250.239.148 permit
|
||||
185.250.239.168 permit
|
||||
185.250.239.190 permit
|
||||
188.125.68.132 permit
|
||||
188.125.68.152/31 permit
|
||||
188.125.68.156 permit
|
||||
@@ -1645,7 +1598,6 @@
|
||||
193.122.128.100 permit
|
||||
193.123.56.63 permit
|
||||
194.19.134.0/25 permit
|
||||
194.64.234.128/27 permit
|
||||
194.64.234.129 permit
|
||||
194.106.220.0/23 permit
|
||||
194.113.24.0/22 permit
|
||||
@@ -1667,9 +1619,13 @@
|
||||
198.37.144.0/20 permit
|
||||
198.37.152.186 permit
|
||||
198.61.254.0/23 permit
|
||||
198.61.254.21 permit
|
||||
198.61.254.231 permit
|
||||
198.178.234.57 permit
|
||||
198.244.48.0/20 permit
|
||||
198.244.59.30 permit
|
||||
198.244.59.33 permit
|
||||
198.244.59.35 permit
|
||||
198.244.60.0/22 permit
|
||||
198.245.80.0/20 permit
|
||||
198.245.81.0/24 permit
|
||||
@@ -1678,13 +1634,7 @@
|
||||
199.16.156.0/22 permit
|
||||
199.33.145.1 permit
|
||||
199.33.145.32 permit
|
||||
199.34.22.36 permit
|
||||
199.59.148.0/22 permit
|
||||
199.67.80.2 permit
|
||||
199.67.82.2 permit
|
||||
199.67.84.0/24 permit
|
||||
199.67.86.0/24 permit
|
||||
199.67.88.0/24 permit
|
||||
199.101.161.130 permit
|
||||
199.101.162.0/25 permit
|
||||
199.122.120.0/21 permit
|
||||
@@ -1733,7 +1683,6 @@
|
||||
203.209.230.76/31 permit
|
||||
204.11.168.0/21 permit
|
||||
204.13.11.48/29 permit
|
||||
204.13.11.48/30 permit
|
||||
204.14.232.0/21 permit
|
||||
204.14.232.64/28 permit
|
||||
204.14.234.64/28 permit
|
||||
@@ -1742,9 +1691,6 @@
|
||||
204.92.114.187 permit
|
||||
204.92.114.203 permit
|
||||
204.92.114.204/31 permit
|
||||
204.132.224.66 permit
|
||||
204.141.32.0/23 permit
|
||||
204.141.42.0/23 permit
|
||||
204.220.160.0/20 permit
|
||||
204.232.168.0/24 permit
|
||||
205.139.110.0/24 permit
|
||||
@@ -1763,6 +1709,7 @@
|
||||
205.251.233.36 permit
|
||||
206.25.247.143 permit
|
||||
206.25.247.155 permit
|
||||
206.55.144.0/20 permit
|
||||
206.165.246.80/29 permit
|
||||
206.191.224.0/19 permit
|
||||
206.246.157.1 permit
|
||||
@@ -1780,14 +1727,12 @@
|
||||
207.46.132.128/27 permit
|
||||
207.46.198.0/25 permit
|
||||
207.46.200.0/27 permit
|
||||
207.46.225.107 permit
|
||||
207.58.147.64/28 permit
|
||||
207.67.38.0/24 permit
|
||||
207.67.98.192/27 permit
|
||||
207.68.176.0/26 permit
|
||||
207.68.176.96/27 permit
|
||||
207.97.204.96 permit
|
||||
207.97.204.97 permit
|
||||
207.97.204.96/29 permit
|
||||
207.126.144.0/20 permit
|
||||
207.171.160.0/19 permit
|
||||
207.211.30.64/26 permit
|
||||
@@ -1826,7 +1771,6 @@
|
||||
208.71.42.212/31 permit
|
||||
208.71.42.214 permit
|
||||
208.72.249.240/29 permit
|
||||
208.74.204.0/22 permit
|
||||
208.74.204.5 permit
|
||||
208.74.204.9 permit
|
||||
208.75.120.0/22 permit
|
||||
@@ -1842,6 +1786,9 @@
|
||||
209.46.117.168 permit
|
||||
209.46.117.179 permit
|
||||
209.61.151.0/24 permit
|
||||
209.61.151.236 permit
|
||||
209.61.151.249 permit
|
||||
209.61.151.251 permit
|
||||
209.67.98.46 permit
|
||||
209.67.98.59 permit
|
||||
209.85.128.0/17 permit
|
||||
@@ -1951,7 +1898,6 @@
|
||||
216.39.62.60/31 permit
|
||||
216.39.62.136/29 permit
|
||||
216.39.62.144/31 permit
|
||||
216.46.168.0/24 permit
|
||||
216.58.192.0/19 permit
|
||||
216.66.217.240/29 permit
|
||||
216.71.138.33 permit
|
||||
@@ -1966,9 +1912,6 @@
|
||||
216.99.5.68 permit
|
||||
216.109.114.32/27 permit
|
||||
216.109.114.64/29 permit
|
||||
216.113.160.0/24 permit
|
||||
216.113.172.0/25 permit
|
||||
216.113.175.0/24 permit
|
||||
216.128.126.97 permit
|
||||
216.136.162.65 permit
|
||||
216.136.162.120/29 permit
|
||||
@@ -2007,6 +1950,8 @@
|
||||
2620:109:c00d:104::/64 permit
|
||||
2620:10d:c090:400::8:1 permit
|
||||
2620:10d:c091:400::8:1 permit
|
||||
2620:10d:c09b:400::8:1 permit
|
||||
2620:10d:c09c:400::8:1 permit
|
||||
2620:119:50c0:207::/64 permit
|
||||
2620:119:50c0:207::215 permit
|
||||
2800:3f0:4000::/36 permit
|
||||
|
||||
@@ -21,6 +21,10 @@ FREEMAIL_TO_UNDISC_RCPT {
|
||||
SOGO_CONTACT_EXCLUDE {
|
||||
expression = "(-WHITELISTED_FWD_HOST | -g+:policies) & ^SOGO_CONTACT & !DMARC_POLICY_ALLOW";
|
||||
}
|
||||
# Remove MAILCOW_WHITE symbol for senders with broken policy recieved not from fwd hosts
|
||||
MAILCOW_WHITE_EXCLUDE {
|
||||
expression = "^MAILCOW_WHITE & (-DMARC_POLICY_REJECT | -DMARC_POLICY_QUARANTINE | -R_SPF_PERMFAIL) & !WHITELISTED_FWD_HOST";
|
||||
}
|
||||
# Spoofed header from and broken policy (excluding sieve host, rspamd host, whitelisted senders, authenticated senders and forward hosts)
|
||||
SPOOFED_UNAUTH {
|
||||
expression = "!MAILCOW_AUTH & !MAILCOW_WHITE & !RSPAMD_HOST & !SIEVE_HOST & MAILCOW_DOMAIN_HEADER_FROM & !WHITELISTED_FWD_HOST & -g+:policies";
|
||||
@@ -103,4 +107,4 @@ CLAMD_JS_MALWARE {
|
||||
expression = "CLAM_SECI_JS & !MAILCOW_WHITE";
|
||||
description = "JS malware found, Securite JS malware Flag set through ClamAV";
|
||||
score = 8;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,23 +1,8 @@
|
||||
rbls {
|
||||
sorbs {
|
||||
symbol = "RBL_SORBS";
|
||||
rbl = "dnsbl.sorbs.net";
|
||||
returncodes {
|
||||
# http:// www.sorbs.net/general/using.shtml
|
||||
RBL_SORBS_HTTP = "127.0.0.2";
|
||||
RBL_SORBS_SOCKS = "127.0.0.3";
|
||||
RBL_SORBS_MISC = "127.0.0.4";
|
||||
RBL_SORBS_SMTP = "127.0.0.5";
|
||||
RBL_SORBS_RECENT = "127.0.0.6";
|
||||
RBL_SORBS_WEB = "127.0.0.7";
|
||||
RBL_SORBS_DUL = "127.0.0.10";
|
||||
RBL_SORBS_BLOCK = "127.0.0.8";
|
||||
RBL_SORBS_ZOMBIE = "127.0.0.9";
|
||||
}
|
||||
}
|
||||
interserver_ip {
|
||||
symbol = "RBL_INTERSERVER_IP";
|
||||
rbl = "rbl.interserver.net";
|
||||
from = true;
|
||||
ipv6 = false;
|
||||
returncodes {
|
||||
RBL_INTERSERVER_BAD_IP = "127.0.0.2";
|
||||
@@ -35,4 +20,7 @@ rbls {
|
||||
RBL_INTERSERVER_BAD_URI = "127.0.0.2";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.include(try=true,override=true,priority=5) "$LOCAL_CONFDIR/custom/dqs-rbl.conf"
|
||||
|
||||
}
|
||||
@@ -5,46 +5,6 @@ symbols = {
|
||||
"RBL_UCEPROTECT_LEVEL2" {
|
||||
score = 1.5;
|
||||
}
|
||||
"RBL_SORBS" {
|
||||
score = 0.0;
|
||||
description = "Unrecognised result from SORBS RBL";
|
||||
}
|
||||
"RBL_SORBS_HTTP" {
|
||||
score = 2.5;
|
||||
description = "List of Open HTTP Proxy Servers.";
|
||||
}
|
||||
"RBL_SORBS_SOCKS" {
|
||||
score = 2.5;
|
||||
description = "List of Open SOCKS Proxy Servers.";
|
||||
}
|
||||
"RBL_SORBS_MISC" {
|
||||
score = 1.0;
|
||||
description = "List of open Proxy Servers not listed in the SOCKS or HTTP lists.";
|
||||
}
|
||||
"RBL_SORBS_SMTP" {
|
||||
score = 4.0;
|
||||
description = "List of Open SMTP relay servers.";
|
||||
}
|
||||
"RBL_SORBS_RECENT" {
|
||||
score = 2.0;
|
||||
description = "List of hosts that have been noted as sending spam/UCE/UBE to the admins of SORBS within the last 28 days (includes new.spam.dnsbl.sorbs.net).";
|
||||
}
|
||||
"RBL_SORBS_WEB" {
|
||||
score = 2.0;
|
||||
description = "List of web (WWW) servers which have spammer abusable vulnerabilities (e.g. FormMail scripts)";
|
||||
}
|
||||
"RBL_SORBS_DUL" {
|
||||
score = 2.0;
|
||||
description = "Dynamic IP Address ranges (NOT a Dial Up list!)";
|
||||
}
|
||||
"RBL_SORBS_BLOCK" {
|
||||
score = 0.5;
|
||||
description = "List of hosts demanding that they never be tested by SORBS.";
|
||||
}
|
||||
"RBL_SORBS_ZOMBIE" {
|
||||
score = 2.0;
|
||||
description = "List of networks hijacked from their original owners, some of which have already used for spamming.";
|
||||
}
|
||||
"RECEIVED_SPAMHAUS_XBL" {
|
||||
weight = 0.0;
|
||||
description = "Received address is listed in ZEN XBL";
|
||||
@@ -57,4 +17,261 @@ symbols = {
|
||||
score = 4.0;
|
||||
description = "Listed on Interserver RBL";
|
||||
}
|
||||
|
||||
"SPAMHAUS_ZEN" {
|
||||
weight = 7.0;
|
||||
}
|
||||
"SH_AUTHBL_RECEIVED" {
|
||||
weight = 4.0;
|
||||
}
|
||||
"RBL_DBL_SPAM" {
|
||||
weight = 7.0;
|
||||
}
|
||||
"RBL_DBL_PHISH" {
|
||||
weight = 7.0;
|
||||
}
|
||||
"RBL_DBL_MALWARE" {
|
||||
weight = 7.0;
|
||||
}
|
||||
"RBL_DBL_BOTNET" {
|
||||
weight = 7.0;
|
||||
}
|
||||
"RBL_DBL_ABUSED_SPAM" {
|
||||
weight = 3.0;
|
||||
}
|
||||
"RBL_DBL_ABUSED_PHISH" {
|
||||
weight = 3.0;
|
||||
}
|
||||
"RBL_DBL_ABUSED_MALWARE" {
|
||||
weight = 3.0;
|
||||
}
|
||||
"RBL_DBL_ABUSED_BOTNET" {
|
||||
weight = 3.0;
|
||||
}
|
||||
"RBL_ZRD_VERY_FRESH_DOMAIN" {
|
||||
weight = 7.0;
|
||||
}
|
||||
"RBL_ZRD_FRESH_DOMAIN" {
|
||||
weight = 4.0;
|
||||
}
|
||||
"ZRD_VERY_FRESH_DOMAIN" {
|
||||
weight = 7.0;
|
||||
}
|
||||
"ZRD_FRESH_DOMAIN" {
|
||||
weight = 4.0;
|
||||
}
|
||||
"SH_EMAIL_DBL" {
|
||||
weight = 7.0;
|
||||
}
|
||||
"SH_EMAIL_DBL_ABUSED" {
|
||||
weight = 7.0;
|
||||
}
|
||||
"SH_EMAIL_ZRD_VERY_FRESH_DOMAIN" {
|
||||
weight = 7.0;
|
||||
}
|
||||
"SH_EMAIL_ZRD_FRESH_DOMAIN" {
|
||||
weight = 4.0;
|
||||
}
|
||||
"RBL_DBL_DONT_QUERY_IPS" {
|
||||
weight = 0.0;
|
||||
}
|
||||
"RBL_ZRD_DONT_QUERY_IPS" {
|
||||
weight = 0.0;
|
||||
}
|
||||
"SH_EMAIL_ZRD_DONT_QUERY_IPS" {
|
||||
weight = 0.0;
|
||||
}
|
||||
"SH_EMAIL_DBL_DONT_QUERY_IPS" {
|
||||
weight = 0.0;
|
||||
}
|
||||
"DBL" {
|
||||
weight = 0.0;
|
||||
description = "DBL unknown result";
|
||||
groups = ["spamhaus"];
|
||||
}
|
||||
"DBL_SPAM" {
|
||||
weight = 7;
|
||||
description = "DBL uribl spam";
|
||||
groups = ["spamhaus"];
|
||||
}
|
||||
"DBL_PHISH" {
|
||||
weight = 7;
|
||||
description = "DBL uribl phishing";
|
||||
groups = ["spamhaus"];
|
||||
}
|
||||
"DBL_MALWARE" {
|
||||
weight = 7;
|
||||
description = "DBL uribl malware";
|
||||
groups = ["spamhaus"];
|
||||
}
|
||||
"DBL_BOTNET" {
|
||||
weight = 7;
|
||||
description = "DBL uribl botnet C&C domain";
|
||||
groups = ["spamhaus"];
|
||||
}
|
||||
|
||||
|
||||
"DBLABUSED_SPAM_FULLURLS" {
|
||||
weight = 5.5;
|
||||
description = "DBL uribl abused legit spam";
|
||||
groups = ["spamhaus"];
|
||||
}
|
||||
"DBLABUSED_PHISH_FULLURLS" {
|
||||
weight = 5.5;
|
||||
description = "DBL uribl abused legit phish";
|
||||
groups = ["spamhaus"];
|
||||
}
|
||||
"DBLABUSED_MALWARE_FULLURLS" {
|
||||
weight = 5.5;
|
||||
description = "DBL uribl abused legit malware";
|
||||
groups = ["spamhaus"];
|
||||
}
|
||||
"DBLABUSED_BOTNET_FULLURLS" {
|
||||
weight = 5.5;
|
||||
description = "DBL uribl abused legit botnet";
|
||||
groups = ["spamhaus"];
|
||||
}
|
||||
|
||||
"DBL_ABUSE" {
|
||||
weight = 5.5;
|
||||
description = "DBL uribl abused legit spam";
|
||||
groups = ["spamhaus"];
|
||||
}
|
||||
"DBL_ABUSE_REDIR" {
|
||||
weight = 1.5;
|
||||
description = "DBL uribl abused spammed redirector domain";
|
||||
groups = ["spamhaus"];
|
||||
}
|
||||
"DBL_ABUSE_PHISH" {
|
||||
weight = 5.5;
|
||||
description = "DBL uribl abused legit phish";
|
||||
groups = ["spamhaus"];
|
||||
}
|
||||
"DBL_ABUSE_MALWARE" {
|
||||
weight = 5.5;
|
||||
description = "DBL uribl abused legit malware";
|
||||
groups = ["spamhaus"];
|
||||
}
|
||||
"DBL_ABUSE_BOTNET" {
|
||||
weight = 5.5;
|
||||
description = "DBL uribl abused legit botnet C&C";
|
||||
groups = ["spamhaus"];
|
||||
}
|
||||
"DBL_PROHIBIT" {
|
||||
weight = 0.0;
|
||||
description = "DBL uribl IP queries prohibited!";
|
||||
groups = ["spamhaus"];
|
||||
}
|
||||
"DBL_BLOCKED_OPENRESOLVER" {
|
||||
weight = 0.0;
|
||||
description = "You are querying Spamhaus from an open resolver, please see https://www.spamhaus.org/returnc/pub/";
|
||||
groups = ["spamhaus"];
|
||||
}
|
||||
"DBL_BLOCKED" {
|
||||
weight = 0.0;
|
||||
description = "You are exceeding the query limit, please see https://www.spamhaus.org/returnc/vol/";
|
||||
groups = ["spamhaus"];
|
||||
}
|
||||
"SPAMHAUS_ZEN_URIBL" {
|
||||
weight = 0.0;
|
||||
description = "Spamhaus ZEN URIBL: Filtered result";
|
||||
groups = ["spamhaus"];
|
||||
}
|
||||
"URIBL_SBL" {
|
||||
weight = 6.5;
|
||||
description = "A domain in the message body resolves to an IP listed in Spamhaus SBL";
|
||||
one_shot = true;
|
||||
groups = ["spamhaus"];
|
||||
}
|
||||
"URIBL_SBL_CSS" {
|
||||
weight = 6.5;
|
||||
description = "A domain in the message body resolves to an IP listed in Spamhaus SBL CSS";
|
||||
one_shot = true;
|
||||
groups = ["spamhaus"];
|
||||
}
|
||||
"URIBL_PBL" {
|
||||
weight = 0.01;
|
||||
description = "A domain in the message body resolves to an IP listed in Spamhaus PBL";
|
||||
one_shot = true;
|
||||
groups = ["spamhaus"];
|
||||
}
|
||||
"URIBL_DROP" {
|
||||
weight = 6.5;
|
||||
description = "A domain in the message body resolves to an IP listed in Spamhaus DROP";
|
||||
one_shot = true;
|
||||
groups = ["spamhaus"];
|
||||
}
|
||||
"URIBL_XBL" {
|
||||
weight = 5.0;
|
||||
description = "A domain in the message body resolves to an IP listed in Spamhaus XBL";
|
||||
one_shot = true;
|
||||
groups = ["spamhaus"];
|
||||
}
|
||||
"SPAMHAUS_SBL_URL" {
|
||||
weight = 6.5;
|
||||
description = "A numeric URL in the message body is listed in Spamhaus SBL";
|
||||
one_shot = true;
|
||||
groups = ["spamhaus"];
|
||||
}
|
||||
|
||||
"SH_HBL_EMAIL" {
|
||||
weight = 7;
|
||||
description = "Email listed in HBL";
|
||||
groups = ["spamhaus"];
|
||||
}
|
||||
|
||||
"SH_HBL_FILE_MALICIOUS" {
|
||||
weight = 7;
|
||||
description = "An attachment hash is listed in Spamhaus HBL as malicious";
|
||||
groups = ["spamhaus"];
|
||||
}
|
||||
|
||||
"SH_HBL_FILE_SUSPICIOUS" {
|
||||
weight = 5;
|
||||
description = "An attachment hash is listed in Spamhaus HBL as suspicious";
|
||||
groups = ["spamhaus"];
|
||||
}
|
||||
|
||||
"RBL_SPAMHAUS_CW_BTC" {
|
||||
score = 7;
|
||||
description = "Bitcoin found in Spamhaus cryptowallet list";
|
||||
groups = ["spamhaus"];
|
||||
}
|
||||
|
||||
"RBL_SPAMHAUS_CW_ETH" {
|
||||
score = 7;
|
||||
description = "Ethereum found in Spamhaus cryptowallet list";
|
||||
groups = ["spamhaus"];
|
||||
}
|
||||
|
||||
"RBL_SPAMHAUS_CW_BCH" {
|
||||
score = 7;
|
||||
description = "Bitcoinhash found in Spamhaus cryptowallet list";
|
||||
groups = ["spamhaus"];
|
||||
}
|
||||
|
||||
"RBL_SPAMHAUS_CW_XMR" {
|
||||
score = 7;
|
||||
description = "Monero found in Spamhaus cryptowallet list";
|
||||
groups = ["spamhaus"];
|
||||
}
|
||||
|
||||
"RBL_SPAMHAUS_CW_LTC" {
|
||||
score = 7;
|
||||
description = "Litecoin found in Spamhaus cryptowallet list";
|
||||
groups = ["spamhaus"];
|
||||
}
|
||||
|
||||
"RBL_SPAMHAUS_CW_XRP" {
|
||||
score = 7;
|
||||
description = "Ripple found in Spamhaus cryptowallet list";
|
||||
groups = ["spamhaus"];
|
||||
}
|
||||
|
||||
"RBL_SPAMHAUS_HBL_URL" {
|
||||
score = 7;
|
||||
description = "URL found in spamhaus HBL blocklist";
|
||||
groups = ["spamhaus"];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
classifier "bayes" {
|
||||
# name = "custom"; # 'name' parameter must be set if multiple classifiers are defined
|
||||
learn_condition = 'return require("lua_bayes_learn").can_learn';
|
||||
new_schema = true;
|
||||
tokenizer {
|
||||
name = "osb";
|
||||
}
|
||||
backend = "redis";
|
||||
min_tokens = 11;
|
||||
min_learns = 5;
|
||||
new_schema = true;
|
||||
expire = 2592000;
|
||||
expire = 7776000;
|
||||
statfile {
|
||||
symbol = "BAYES_HAM";
|
||||
spam = false;
|
||||
|
||||
@@ -107,6 +107,7 @@ $template_data = [
|
||||
'f2b_banlist_url' => getBaseUrl() . "/api/v1/get/fail2ban/banlist/" . $f2b_data['banlist_id'],
|
||||
'q_data' => quarantine('settings'),
|
||||
'qn_data' => quota_notification('get'),
|
||||
'pw_reset_data' => reset_password('get_notification'),
|
||||
'rsettings_map' => file_get_contents('http://nginx:8081/settings.php'),
|
||||
'rsettings' => $rsettings,
|
||||
'rspamd_regex_maps' => $rspamd_regex_maps,
|
||||
|
||||
@@ -1,4 +1,11 @@
|
||||
<?php
|
||||
|
||||
// Block requests by checking the 'Sec-Fetch-Dest' header.
|
||||
if (isset($_SERVER['HTTP_SEC_FETCH_DEST']) && $_SERVER['HTTP_SEC_FETCH_DEST'] !== 'empty') {
|
||||
header('HTTP/1.1 403 Forbidden');
|
||||
exit;
|
||||
}
|
||||
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/prerequisites.inc.php';
|
||||
if (!isset($_SESSION['mailcow_cc_role']) || $_SESSION['mailcow_cc_role'] != 'admin') {
|
||||
exit();
|
||||
|
||||
@@ -284,17 +284,17 @@ function last_login($action, $username, $sasl_limit_days = 7, $ui_offset = 1) {
|
||||
}
|
||||
if (!$sasl[$k]['location']) {
|
||||
$curl = curl_init();
|
||||
curl_setopt($curl, CURLOPT_URL,"https://dfdata.bella.network/lookup/" . $sasl[$k]['real_rip']);
|
||||
curl_setopt($curl, CURLOPT_URL,"https://dfdata.bella.network/country/" . $sasl[$k]['real_rip']);
|
||||
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($curl, CURLOPT_USERAGENT, 'Moocow');
|
||||
curl_setopt($curl, CURLOPT_TIMEOUT, 5);
|
||||
$ip_data = curl_exec($curl);
|
||||
if (!curl_errno($curl)) {
|
||||
$ip_data_array = json_decode($ip_data, true);
|
||||
if ($ip_data_array !== false and !empty($ip_data_array['location']['shortcountry'])) {
|
||||
$sasl[$k]['location'] = $ip_data_array['location']['shortcountry'];
|
||||
if ($ip_data_array !== false and !empty($ip_data_array['shortcountry'])) {
|
||||
$sasl[$k]['location'] = $ip_data_array['shortcountry'];
|
||||
try {
|
||||
$redis->hSet('IP_SHORTCOUNTRY', $sasl[$k]['real_rip'], $ip_data_array['location']['shortcountry']);
|
||||
$redis->hSet('IP_SHORTCOUNTRY', $sasl[$k]['real_rip'], $ip_data_array['shortcountry']);
|
||||
}
|
||||
catch (RedisException $e) {
|
||||
$_SESSION['return'][] = array(
|
||||
@@ -1073,13 +1073,17 @@ function update_sogo_static_view($mailbox = null) {
|
||||
function edit_user_account($_data) {
|
||||
global $lang;
|
||||
global $pdo;
|
||||
|
||||
$_data_log = $_data;
|
||||
!isset($_data_log['user_new_pass']) ?: $_data_log['user_new_pass'] = '*';
|
||||
!isset($_data_log['user_new_pass2']) ?: $_data_log['user_new_pass2'] = '*';
|
||||
!isset($_data_log['user_old_pass']) ?: $_data_log['user_old_pass'] = '*';
|
||||
|
||||
$username = $_SESSION['mailcow_cc_username'];
|
||||
$role = $_SESSION['mailcow_cc_role'];
|
||||
$password_old = $_data['user_old_pass'];
|
||||
$pw_recovery_email = $_data['pw_recovery_email'];
|
||||
|
||||
if (filter_var($username, FILTER_VALIDATE_EMAIL === false) || $role != 'user') {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
@@ -1088,20 +1092,24 @@ function edit_user_account($_data) {
|
||||
);
|
||||
return false;
|
||||
}
|
||||
$stmt = $pdo->prepare("SELECT `password` FROM `mailbox`
|
||||
WHERE `kind` NOT REGEXP 'location|thing|group'
|
||||
AND `username` = :user");
|
||||
$stmt->execute(array(':user' => $username));
|
||||
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
if (!verify_hash($row['password'], $password_old)) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_data_log),
|
||||
'msg' => 'access_denied'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
if (!empty($_data['user_new_pass']) && !empty($_data['user_new_pass2'])) {
|
||||
|
||||
// edit password
|
||||
if (!empty($password_old) && !empty($_data['user_new_pass']) && !empty($_data['user_new_pass2'])) {
|
||||
$stmt = $pdo->prepare("SELECT `password` FROM `mailbox`
|
||||
WHERE `kind` NOT REGEXP 'location|thing|group'
|
||||
AND `username` = :user");
|
||||
$stmt->execute(array(':user' => $username));
|
||||
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if (!verify_hash($row['password'], $password_old)) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_data_log),
|
||||
'msg' => 'access_denied'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
$password_new = $_data['user_new_pass'];
|
||||
$password_new2 = $_data['user_new_pass2'];
|
||||
if (password_check($password_new, $password_new2) !== true) {
|
||||
@@ -1116,8 +1124,29 @@ function edit_user_account($_data) {
|
||||
':password_hashed' => $password_hashed,
|
||||
':username' => $username
|
||||
));
|
||||
|
||||
update_sogo_static_view();
|
||||
}
|
||||
update_sogo_static_view();
|
||||
// edit password recovery email
|
||||
elseif (isset($pw_recovery_email)) {
|
||||
if (!isset($_SESSION['acl']['pw_reset']) || $_SESSION['acl']['pw_reset'] != "1" ) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
|
||||
'msg' => 'access_denied'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
$pw_recovery_email = (!filter_var($pw_recovery_email, FILTER_VALIDATE_EMAIL)) ? '' : $pw_recovery_email;
|
||||
$stmt = $pdo->prepare("UPDATE `mailbox` SET `attributes` = JSON_SET(`attributes`, '$.recovery_email', :recovery_email)
|
||||
WHERE `username` = :username");
|
||||
$stmt->execute(array(
|
||||
':recovery_email' => $pw_recovery_email,
|
||||
':username' => $username
|
||||
));
|
||||
}
|
||||
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'success',
|
||||
'log' => array(__FUNCTION__, $_data_log),
|
||||
@@ -1560,7 +1589,7 @@ function unset_tfa_key($_data) {
|
||||
}
|
||||
function get_tfa($username = null, $id = null) {
|
||||
global $pdo;
|
||||
if (isset($_SESSION['mailcow_cc_username'])) {
|
||||
if (empty($username) && isset($_SESSION['mailcow_cc_username'])) {
|
||||
$username = $_SESSION['mailcow_cc_username'];
|
||||
}
|
||||
elseif (empty($username)) {
|
||||
@@ -2261,6 +2290,386 @@ function uuid4() {
|
||||
|
||||
return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4));
|
||||
}
|
||||
function reset_password($action, $data = null) {
|
||||
global $pdo;
|
||||
global $redis;
|
||||
global $mailcow_hostname;
|
||||
global $PW_RESET_TOKEN_LIMIT;
|
||||
global $PW_RESET_TOKEN_LIFETIME;
|
||||
|
||||
$_data_log = $data;
|
||||
if (isset($_data_log['new_password'])) $_data_log['new_password'] = '*';
|
||||
if (isset($_data_log['new_password2'])) $_data_log['new_password2'] = '*';
|
||||
|
||||
switch ($action) {
|
||||
case 'check':
|
||||
$token = $data;
|
||||
|
||||
$stmt = $pdo->prepare("SELECT `t1`.`username` FROM `reset_password` AS `t1` JOIN `mailbox` AS `t2` ON `t1`.`username` = `t2`.`username` WHERE `t1`.`token` = :token AND `t1`.`created` > DATE_SUB(NOW(), INTERVAL :lifetime MINUTE) AND `t2`.`active` = 1;");
|
||||
$stmt->execute(array(
|
||||
':token' => preg_replace('/[^a-zA-Z0-9-]/', '', $token),
|
||||
':lifetime' => $PW_RESET_TOKEN_LIFETIME
|
||||
));
|
||||
$return = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
return empty($return['username']) ? false : $return['username'];
|
||||
break;
|
||||
case 'issue':
|
||||
$username = $data;
|
||||
|
||||
// perform cleanup
|
||||
$stmt = $pdo->prepare("DELETE FROM `reset_password` WHERE created < DATE_SUB(NOW(), INTERVAL :lifetime MINUTE);");
|
||||
$stmt->execute(array(':lifetime' => $PW_RESET_TOKEN_LIFETIME));
|
||||
|
||||
if (filter_var($username, FILTER_VALIDATE_EMAIL) === false) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $action, $_data_log),
|
||||
'msg' => 'access_denied'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
$pw_reset_notification = reset_password('get_notification', 'raw');
|
||||
if (!$pw_reset_notification) return false;
|
||||
if (empty($pw_reset_notification['from']) || empty($pw_reset_notification['subject'])) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $action, $_data_log),
|
||||
'msg' => 'password_reset_na'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
$stmt = $pdo->prepare("SELECT * FROM `mailbox`
|
||||
WHERE `username` = :username");
|
||||
$stmt->execute(array(':username' => $username));
|
||||
$mailbox_data = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if (empty($mailbox_data)) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $action, $_data_log),
|
||||
'msg' => 'password_reset_invalid_user'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
$mailbox_attr = json_decode($mailbox_data['attributes'], true);
|
||||
if (empty($mailbox_attr['recovery_email']) || filter_var($mailbox_attr['recovery_email'], FILTER_VALIDATE_EMAIL) === false) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $action, $_data_log),
|
||||
'msg' => "password_reset_invalid_user"
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
$stmt = $pdo->prepare("SELECT * FROM `reset_password`
|
||||
WHERE `username` = :username");
|
||||
$stmt->execute(array(':username' => $username));
|
||||
$generated_token_count = count($stmt->fetchAll(PDO::FETCH_ASSOC));
|
||||
if ($generated_token_count >= $PW_RESET_TOKEN_LIMIT) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $action, $_data_log),
|
||||
'msg' => "reset_token_limit_exceeded"
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
$token = implode('-', array(
|
||||
strtoupper(bin2hex(random_bytes(3))),
|
||||
strtoupper(bin2hex(random_bytes(3))),
|
||||
strtoupper(bin2hex(random_bytes(3))),
|
||||
strtoupper(bin2hex(random_bytes(3))),
|
||||
strtoupper(bin2hex(random_bytes(3)))
|
||||
));
|
||||
|
||||
$stmt = $pdo->prepare("INSERT INTO `reset_password` (`username`, `token`)
|
||||
VALUES (:username, :token)");
|
||||
$stmt->execute(array(
|
||||
':username' => $username,
|
||||
':token' => $token
|
||||
));
|
||||
|
||||
$reset_link = getBaseURL() . "/reset-password?token=" . $token;
|
||||
|
||||
$request_date = new DateTime();
|
||||
$locale_date = locale_get_default();
|
||||
$date_formatter = new IntlDateFormatter(
|
||||
$locale_date,
|
||||
IntlDateFormatter::FULL,
|
||||
IntlDateFormatter::FULL
|
||||
);
|
||||
$formatted_request_date = $date_formatter->format($request_date);
|
||||
|
||||
// set template vars
|
||||
// subject
|
||||
$pw_reset_notification['subject'] = str_replace('{{hostname}}', $mailcow_hostname, $pw_reset_notification['subject']);
|
||||
$pw_reset_notification['subject'] = str_replace('{{link}}', $reset_link, $pw_reset_notification['subject']);
|
||||
$pw_reset_notification['subject'] = str_replace('{{username}}', $username, $pw_reset_notification['subject']);
|
||||
$pw_reset_notification['subject'] = str_replace('{{username2}}', $mailbox_attr['recovery_email'], $pw_reset_notification['subject']);
|
||||
$pw_reset_notification['subject'] = str_replace('{{date}}', $formatted_request_date, $pw_reset_notification['subject']);
|
||||
$pw_reset_notification['subject'] = str_replace('{{token_lifetime}}', $PW_RESET_TOKEN_LIFETIME, $pw_reset_notification['subject']);
|
||||
// text
|
||||
$pw_reset_notification['text_tmpl'] = str_replace('{{hostname}}', $mailcow_hostname, $pw_reset_notification['text_tmpl']);
|
||||
$pw_reset_notification['text_tmpl'] = str_replace('{{link}}', $reset_link, $pw_reset_notification['text_tmpl']);
|
||||
$pw_reset_notification['text_tmpl'] = str_replace('{{username}}', $username, $pw_reset_notification['text_tmpl']);
|
||||
$pw_reset_notification['text_tmpl'] = str_replace('{{username2}}', $mailbox_attr['recovery_email'], $pw_reset_notification['text_tmpl']);
|
||||
$pw_reset_notification['text_tmpl'] = str_replace('{{date}}', $formatted_request_date, $pw_reset_notification['text_tmpl']);
|
||||
$pw_reset_notification['text_tmpl'] = str_replace('{{token_lifetime}}', $PW_RESET_TOKEN_LIFETIME, $pw_reset_notification['text_tmpl']);
|
||||
// html
|
||||
$pw_reset_notification['html_tmpl'] = str_replace('{{hostname}}', $mailcow_hostname, $pw_reset_notification['html_tmpl']);
|
||||
$pw_reset_notification['html_tmpl'] = str_replace('{{link}}', $reset_link, $pw_reset_notification['html_tmpl']);
|
||||
$pw_reset_notification['html_tmpl'] = str_replace('{{username}}', $username, $pw_reset_notification['html_tmpl']);
|
||||
$pw_reset_notification['html_tmpl'] = str_replace('{{username2}}', $mailbox_attr['recovery_email'], $pw_reset_notification['html_tmpl']);
|
||||
$pw_reset_notification['html_tmpl'] = str_replace('{{date}}', $formatted_request_date, $pw_reset_notification['html_tmpl']);
|
||||
$pw_reset_notification['html_tmpl'] = str_replace('{{token_lifetime}}', $PW_RESET_TOKEN_LIFETIME, $pw_reset_notification['html_tmpl']);
|
||||
|
||||
|
||||
$email_sent = reset_password('send_mail', array(
|
||||
"from" => $pw_reset_notification['from'],
|
||||
"to" => $mailbox_attr['recovery_email'],
|
||||
"subject" => $pw_reset_notification['subject'],
|
||||
"text" => $pw_reset_notification['text_tmpl'],
|
||||
"html" => $pw_reset_notification['html_tmpl']
|
||||
));
|
||||
|
||||
if (!$email_sent){
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $action, $_data_log),
|
||||
'msg' => "recovery_email_failed"
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
list($localPart, $domainPart) = explode('@', $mailbox_attr['recovery_email']);
|
||||
if (strlen($localPart) > 1) {
|
||||
$maskedLocalPart = $localPart[0] . str_repeat('*', strlen($localPart) - 1);
|
||||
} else {
|
||||
$maskedLocalPart = "*";
|
||||
}
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'success',
|
||||
'log' => array(__FUNCTION__, $action, $_data_log),
|
||||
'msg' => array("recovery_email_sent", $maskedLocalPart . '@' . $domainPart)
|
||||
);
|
||||
return array(
|
||||
"username" => $username,
|
||||
"issue" => "success"
|
||||
);
|
||||
break;
|
||||
case 'reset':
|
||||
$token = $data['token'];
|
||||
$new_password = $data['new_password'];
|
||||
$new_password2 = $data['new_password2'];
|
||||
$username = $data['username'];
|
||||
$check_tfa = $data['check_tfa'];
|
||||
|
||||
if (!$username || !$token) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $action, $_data_log),
|
||||
'msg' => 'invalid_reset_token'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
# check new password
|
||||
if (!password_check($new_password, $new_password2)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($check_tfa){
|
||||
// check for tfa authenticators
|
||||
$authenticators = get_tfa($username);
|
||||
if (isset($authenticators['additional']) && is_array($authenticators['additional']) && count($authenticators['additional']) > 0) {
|
||||
$_SESSION['pending_mailcow_cc_username'] = $username;
|
||||
$_SESSION['pending_pw_reset_token'] = $token;
|
||||
$_SESSION['pending_pw_new_password'] = $new_password;
|
||||
$_SESSION['pending_tfa_methods'] = $authenticators['additional'];
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'info',
|
||||
'log' => array(__FUNCTION__, $user, '*'),
|
||||
'msg' => 'awaiting_tfa_confirmation'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
# set new password
|
||||
$password_hashed = hash_password($new_password);
|
||||
$stmt = $pdo->prepare("UPDATE `mailbox` SET
|
||||
`password` = :password_hashed,
|
||||
`attributes` = JSON_SET(`attributes`, '$.passwd_update', NOW())
|
||||
WHERE `username` = :username");
|
||||
$stmt->execute(array(
|
||||
':password_hashed' => $password_hashed,
|
||||
':username' => $username
|
||||
));
|
||||
|
||||
// perform cleanup
|
||||
$stmt = $pdo->prepare("DELETE FROM `reset_password` WHERE `username` = :username;");
|
||||
$stmt->execute(array(
|
||||
':username' => $username
|
||||
));
|
||||
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'success',
|
||||
'log' => array(__FUNCTION__, $action, $_data_log),
|
||||
'msg' => 'password_changed_success'
|
||||
);
|
||||
return true;
|
||||
break;
|
||||
case 'get_notification':
|
||||
$type = $data;
|
||||
|
||||
try {
|
||||
$settings['from'] = $redis->Get('PW_RESET_FROM');
|
||||
$settings['subject'] = $redis->Get('PW_RESET_SUBJ');
|
||||
$settings['html_tmpl'] = $redis->Get('PW_RESET_HTML');
|
||||
$settings['text_tmpl'] = $redis->Get('PW_RESET_TEXT');
|
||||
if (empty($settings['html_tmpl']) && empty($settings['text_tmpl'])) {
|
||||
$settings['html_tmpl'] = file_get_contents("/tpls/pw_reset_html.tpl");
|
||||
$settings['text_tmpl'] = file_get_contents("/tpls/pw_reset_text.tpl");
|
||||
}
|
||||
|
||||
if ($type != "raw") {
|
||||
$settings['html_tmpl'] = htmlspecialchars($settings['html_tmpl']);
|
||||
$settings['text_tmpl'] = htmlspecialchars($settings['text_tmpl']);
|
||||
}
|
||||
}
|
||||
catch (RedisException $e) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $action, $_data_log),
|
||||
'msg' => array('redis_error', $e)
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
return $settings;
|
||||
break;
|
||||
case 'send_mail':
|
||||
$from = $data['from'];
|
||||
$to = $data['to'];
|
||||
$text = $data['text'];
|
||||
$html = $data['html'];
|
||||
$subject = $data['subject'];
|
||||
|
||||
if (!filter_var($from, FILTER_VALIDATE_EMAIL)) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $action, $_data_log),
|
||||
'msg' => 'from_invalid'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
if (!filter_var($to, FILTER_VALIDATE_EMAIL)) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $action, $_data_log),
|
||||
'msg' => 'to_invalid'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
if (empty($subject)) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $action, $_data_log),
|
||||
'msg' => 'subject_empty'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
if (empty($text)) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $action, $_data_log),
|
||||
'msg' => 'text_empty'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
ini_set('max_execution_time', 0);
|
||||
ini_set('max_input_time', 0);
|
||||
$mail = new PHPMailer;
|
||||
$mail->Timeout = 10;
|
||||
$mail->SMTPOptions = array(
|
||||
'ssl' => array(
|
||||
'verify_peer' => false,
|
||||
'verify_peer_name' => false,
|
||||
'allow_self_signed' => true
|
||||
)
|
||||
);
|
||||
$mail->isSMTP();
|
||||
$mail->Host = 'postfix-mailcow';
|
||||
$mail->SMTPAuth = false;
|
||||
$mail->Port = 25;
|
||||
$mail->setFrom($from);
|
||||
$mail->Subject = $subject;
|
||||
$mail->CharSet ="UTF-8";
|
||||
if (!empty($html)) {
|
||||
$mail->Body = $html;
|
||||
$mail->AltBody = $text;
|
||||
}
|
||||
else {
|
||||
$mail->Body = $text;
|
||||
}
|
||||
$mail->XMailer = 'MooMail';
|
||||
$mail->AddAddress($to);
|
||||
if (!$mail->send()) {
|
||||
return false;
|
||||
}
|
||||
$mail->ClearAllRecipients();
|
||||
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
|
||||
if ($_SESSION['mailcow_cc_role'] != "admin") {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $action, $_data_log),
|
||||
'msg' => 'access_denied'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
switch ($action) {
|
||||
case 'edit_notification':
|
||||
$subject = $data['subject'];
|
||||
$from = preg_replace('/[\x00-\x1F\x80-\xFF]/', '', $data['from']);
|
||||
|
||||
$from = (!filter_var($from, FILTER_VALIDATE_EMAIL)) ? "" : $from;
|
||||
$subject = (empty($subject)) ? "" : $subject;
|
||||
$text = (empty($data['text_tmpl'])) ? "" : $data['text_tmpl'];
|
||||
$html = (empty($data['html_tmpl'])) ? "" : $data['html_tmpl'];
|
||||
|
||||
try {
|
||||
$redis->Set('PW_RESET_FROM', $from);
|
||||
$redis->Set('PW_RESET_SUBJ', $subject);
|
||||
$redis->Set('PW_RESET_HTML', $html);
|
||||
$redis->Set('PW_RESET_TEXT', $text);
|
||||
}
|
||||
catch (RedisException $e) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $action, $_data_log),
|
||||
'msg' => array('redis_error', $e)
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'success',
|
||||
'log' => array(__FUNCTION__, $action, $_data_log),
|
||||
'msg' => 'saved_settings'
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function get_logs($application, $lines = false) {
|
||||
if ($lines === false) {
|
||||
|
||||
@@ -184,6 +184,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
||||
'msg' => 'global_filter_written'
|
||||
);
|
||||
return true;
|
||||
break;
|
||||
case 'filter':
|
||||
$sieve = new Sieve\SieveParser();
|
||||
if (!isset($_SESSION['acl']['filters']) || $_SESSION['acl']['filters'] != "1" ) {
|
||||
@@ -1249,6 +1250,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
||||
$_data['quarantine_notification'] = (in_array('quarantine_notification', $_data['acl'])) ? 1 : 0;
|
||||
$_data['quarantine_category'] = (in_array('quarantine_category', $_data['acl'])) ? 1 : 0;
|
||||
$_data['app_passwds'] = (in_array('app_passwds', $_data['acl'])) ? 1 : 0;
|
||||
$_data['pw_reset'] = (in_array('pw_reset', $_data['acl'])) ? 1 : 0;
|
||||
} else {
|
||||
$_data['spam_alias'] = intval($MAILBOX_DEFAULT_ATTRIBUTES['acl_spam_alias']);
|
||||
$_data['tls_policy'] = intval($MAILBOX_DEFAULT_ATTRIBUTES['acl_tls_policy']);
|
||||
@@ -1264,14 +1266,15 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
||||
$_data['quarantine_notification'] = intval($MAILBOX_DEFAULT_ATTRIBUTES['acl_quarantine_notification']);
|
||||
$_data['quarantine_category'] = intval($MAILBOX_DEFAULT_ATTRIBUTES['acl_quarantine_category']);
|
||||
$_data['app_passwds'] = intval($MAILBOX_DEFAULT_ATTRIBUTES['acl_app_passwds']);
|
||||
$_data['pw_reset'] = intval($MAILBOX_DEFAULT_ATTRIBUTES['acl_pw_reset']);
|
||||
}
|
||||
|
||||
try {
|
||||
$stmt = $pdo->prepare("INSERT INTO `user_acl`
|
||||
(`username`, `spam_alias`, `tls_policy`, `spam_score`, `spam_policy`, `delimiter_action`, `syncjobs`, `eas_reset`, `sogo_profile_reset`,
|
||||
`pushover`, `quarantine`, `quarantine_attachments`, `quarantine_notification`, `quarantine_category`, `app_passwds`)
|
||||
`pushover`, `quarantine`, `quarantine_attachments`, `quarantine_notification`, `quarantine_category`, `app_passwds`, `pw_reset`)
|
||||
VALUES (:username, :spam_alias, :tls_policy, :spam_score, :spam_policy, :delimiter_action, :syncjobs, :eas_reset, :sogo_profile_reset,
|
||||
:pushover, :quarantine, :quarantine_attachments, :quarantine_notification, :quarantine_category, :app_passwds) ");
|
||||
:pushover, :quarantine, :quarantine_attachments, :quarantine_notification, :quarantine_category, :app_passwds, :pw_reset) ");
|
||||
$stmt->execute(array(
|
||||
':username' => $username,
|
||||
':spam_alias' => $_data['spam_alias'],
|
||||
@@ -1287,7 +1290,8 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
||||
':quarantine_attachments' => $_data['quarantine_attachments'],
|
||||
':quarantine_notification' => $_data['quarantine_notification'],
|
||||
':quarantine_category' => $_data['quarantine_category'],
|
||||
':app_passwds' => $_data['app_passwds']
|
||||
':app_passwds' => $_data['app_passwds'],
|
||||
':pw_reset' => $_data['pw_reset']
|
||||
));
|
||||
}
|
||||
catch (PDOException $e) {
|
||||
@@ -1576,6 +1580,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
||||
$attr['acl_quarantine_notification'] = (in_array('quarantine_notification', $_data['acl'])) ? 1 : 0;
|
||||
$attr['acl_quarantine_category'] = (in_array('quarantine_category', $_data['acl'])) ? 1 : 0;
|
||||
$attr['acl_app_passwds'] = (in_array('app_passwds', $_data['acl'])) ? 1 : 0;
|
||||
$attr['acl_pw_reset'] = (in_array('pw_reset', $_data['acl'])) ? 1 : 0;
|
||||
} else {
|
||||
$_data['acl'] = (array)$_data['acl'];
|
||||
$attr['acl_spam_alias'] = 0;
|
||||
@@ -2865,21 +2870,22 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
||||
$_data['sieve_access'] = (in_array('sieve', $_data['protocol_access'])) ? 1 : 0;
|
||||
}
|
||||
if (!empty($is_now)) {
|
||||
$active = (isset($_data['active'])) ? intval($_data['active']) : $is_now['active'];
|
||||
$active = (isset($_data['active'])) ? intval($_data['active']) : $is_now['active'];
|
||||
(int)$force_pw_update = (isset($_data['force_pw_update'])) ? intval($_data['force_pw_update']) : intval($is_now['attributes']['force_pw_update']);
|
||||
(int)$sogo_access = (isset($_data['sogo_access']) && isset($_SESSION['acl']['sogo_access']) && $_SESSION['acl']['sogo_access'] == "1") ? intval($_data['sogo_access']) : intval($is_now['attributes']['sogo_access']);
|
||||
(int)$imap_access = (isset($_data['imap_access']) && isset($_SESSION['acl']['protocol_access']) && $_SESSION['acl']['protocol_access'] == "1") ? intval($_data['imap_access']) : intval($is_now['attributes']['imap_access']);
|
||||
(int)$pop3_access = (isset($_data['pop3_access']) && isset($_SESSION['acl']['protocol_access']) && $_SESSION['acl']['protocol_access'] == "1") ? intval($_data['pop3_access']) : intval($is_now['attributes']['pop3_access']);
|
||||
(int)$smtp_access = (isset($_data['smtp_access']) && isset($_SESSION['acl']['protocol_access']) && $_SESSION['acl']['protocol_access'] == "1") ? intval($_data['smtp_access']) : intval($is_now['attributes']['smtp_access']);
|
||||
(int)$sieve_access = (isset($_data['sieve_access']) && isset($_SESSION['acl']['protocol_access']) && $_SESSION['acl']['protocol_access'] == "1") ? intval($_data['sieve_access']) : intval($is_now['attributes']['sieve_access']);
|
||||
(int)$relayhost = (isset($_data['relayhost']) && isset($_SESSION['acl']['mailbox_relayhost']) && $_SESSION['acl']['mailbox_relayhost'] == "1") ? intval($_data['relayhost']) : intval($is_now['attributes']['relayhost']);
|
||||
(int)$quota_m = (isset_has_content($_data['quota'])) ? intval($_data['quota']) : ($is_now['quota'] / 1048576);
|
||||
$name = (!empty($_data['name'])) ? ltrim(rtrim($_data['name'], '>'), '<') : $is_now['name'];
|
||||
$domain = $is_now['domain'];
|
||||
$quota_b = $quota_m * 1048576;
|
||||
$password = (!empty($_data['password'])) ? $_data['password'] : null;
|
||||
$password2 = (!empty($_data['password2'])) ? $_data['password2'] : null;
|
||||
$tags = (is_array($_data['tags']) ? $_data['tags'] : array());
|
||||
(int)$sogo_access = (isset($_data['sogo_access']) && isset($_SESSION['acl']['sogo_access']) && $_SESSION['acl']['sogo_access'] == "1") ? intval($_data['sogo_access']) : intval($is_now['attributes']['sogo_access']);
|
||||
(int)$imap_access = (isset($_data['imap_access']) && isset($_SESSION['acl']['protocol_access']) && $_SESSION['acl']['protocol_access'] == "1") ? intval($_data['imap_access']) : intval($is_now['attributes']['imap_access']);
|
||||
(int)$pop3_access = (isset($_data['pop3_access']) && isset($_SESSION['acl']['protocol_access']) && $_SESSION['acl']['protocol_access'] == "1") ? intval($_data['pop3_access']) : intval($is_now['attributes']['pop3_access']);
|
||||
(int)$smtp_access = (isset($_data['smtp_access']) && isset($_SESSION['acl']['protocol_access']) && $_SESSION['acl']['protocol_access'] == "1") ? intval($_data['smtp_access']) : intval($is_now['attributes']['smtp_access']);
|
||||
(int)$sieve_access = (isset($_data['sieve_access']) && isset($_SESSION['acl']['protocol_access']) && $_SESSION['acl']['protocol_access'] == "1") ? intval($_data['sieve_access']) : intval($is_now['attributes']['sieve_access']);
|
||||
(int)$relayhost = (isset($_data['relayhost']) && isset($_SESSION['acl']['mailbox_relayhost']) && $_SESSION['acl']['mailbox_relayhost'] == "1") ? intval($_data['relayhost']) : intval($is_now['attributes']['relayhost']);
|
||||
(int)$quota_m = (isset_has_content($_data['quota'])) ? intval($_data['quota']) : ($is_now['quota'] / 1048576);
|
||||
$name = (!empty($_data['name'])) ? ltrim(rtrim($_data['name'], '>'), '<') : $is_now['name'];
|
||||
$domain = $is_now['domain'];
|
||||
$quota_b = $quota_m * 1048576;
|
||||
$password = (!empty($_data['password'])) ? $_data['password'] : null;
|
||||
$password2 = (!empty($_data['password2'])) ? $_data['password2'] : null;
|
||||
$pw_recovery_email = (isset($_data['pw_recovery_email'])) ? $_data['pw_recovery_email'] : $is_now['attributes']['recovery_email'];
|
||||
$tags = (is_array($_data['tags']) ? $_data['tags'] : array());
|
||||
}
|
||||
else {
|
||||
$_SESSION['return'][] = array(
|
||||
@@ -3132,31 +3138,43 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
||||
':address' => $username,
|
||||
':active' => $active
|
||||
));
|
||||
$stmt = $pdo->prepare("UPDATE `mailbox` SET
|
||||
`active` = :active,
|
||||
`name`= :name,
|
||||
`quota` = :quota_b,
|
||||
`attributes` = JSON_SET(`attributes`, '$.force_pw_update', :force_pw_update),
|
||||
`attributes` = JSON_SET(`attributes`, '$.sogo_access', :sogo_access),
|
||||
`attributes` = JSON_SET(`attributes`, '$.imap_access', :imap_access),
|
||||
`attributes` = JSON_SET(`attributes`, '$.sieve_access', :sieve_access),
|
||||
`attributes` = JSON_SET(`attributes`, '$.pop3_access', :pop3_access),
|
||||
`attributes` = JSON_SET(`attributes`, '$.relayhost', :relayhost),
|
||||
`attributes` = JSON_SET(`attributes`, '$.smtp_access', :smtp_access)
|
||||
WHERE `username` = :username");
|
||||
$stmt->execute(array(
|
||||
':active' => $active,
|
||||
':name' => $name,
|
||||
':quota_b' => $quota_b,
|
||||
':force_pw_update' => $force_pw_update,
|
||||
':sogo_access' => $sogo_access,
|
||||
':imap_access' => $imap_access,
|
||||
':pop3_access' => $pop3_access,
|
||||
':sieve_access' => $sieve_access,
|
||||
':smtp_access' => $smtp_access,
|
||||
':relayhost' => $relayhost,
|
||||
':username' => $username
|
||||
));
|
||||
try {
|
||||
$stmt = $pdo->prepare("UPDATE `mailbox` SET
|
||||
`active` = :active,
|
||||
`name`= :name,
|
||||
`quota` = :quota_b,
|
||||
`attributes` = JSON_SET(`attributes`, '$.force_pw_update', :force_pw_update),
|
||||
`attributes` = JSON_SET(`attributes`, '$.sogo_access', :sogo_access),
|
||||
`attributes` = JSON_SET(`attributes`, '$.imap_access', :imap_access),
|
||||
`attributes` = JSON_SET(`attributes`, '$.sieve_access', :sieve_access),
|
||||
`attributes` = JSON_SET(`attributes`, '$.pop3_access', :pop3_access),
|
||||
`attributes` = JSON_SET(`attributes`, '$.relayhost', :relayhost),
|
||||
`attributes` = JSON_SET(`attributes`, '$.smtp_access', :smtp_access),
|
||||
`attributes` = JSON_SET(`attributes`, '$.recovery_email', :recovery_email)
|
||||
WHERE `username` = :username");
|
||||
$stmt->execute(array(
|
||||
':active' => $active,
|
||||
':name' => $name,
|
||||
':quota_b' => $quota_b,
|
||||
':force_pw_update' => $force_pw_update,
|
||||
':sogo_access' => $sogo_access,
|
||||
':imap_access' => $imap_access,
|
||||
':pop3_access' => $pop3_access,
|
||||
':sieve_access' => $sieve_access,
|
||||
':smtp_access' => $smtp_access,
|
||||
':recovery_email' => $pw_recovery_email,
|
||||
':relayhost' => $relayhost,
|
||||
':username' => $username
|
||||
));
|
||||
}
|
||||
catch (PDOException $e) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
|
||||
'msg' => $e->getMessage()
|
||||
);
|
||||
return false;
|
||||
}
|
||||
// save tags
|
||||
foreach($tags as $index => $tag){
|
||||
if (empty($tag)) continue;
|
||||
@@ -3263,6 +3281,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
||||
$attr['acl_quarantine_notification'] = (in_array('quarantine_notification', $_data['acl'])) ? 1 : 0;
|
||||
$attr['acl_quarantine_category'] = (in_array('quarantine_category', $_data['acl'])) ? 1 : 0;
|
||||
$attr['acl_app_passwds'] = (in_array('app_passwds', $_data['acl'])) ? 1 : 0;
|
||||
$attr['acl_pw_reset'] = (in_array('pw_reset', $_data['acl'])) ? 1 : 0;
|
||||
} else {
|
||||
foreach ($is_now as $key => $value){
|
||||
$attr[$key] = $is_now[$key];
|
||||
@@ -5212,7 +5231,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
||||
'msg' => 'Could not move maildir to garbage collector: variables local_part and/or domain empty'
|
||||
);
|
||||
}
|
||||
if (strtolower(getenv('SKIP_SOLR')) == 'n') {
|
||||
if (strtolower(getenv('SKIP_SOLR')) == 'n' && strtolower(getenv('FLATCURVE_EXPERIMENTAL')) != 'y') {
|
||||
$curl = curl_init();
|
||||
curl_setopt($curl, CURLOPT_URL, 'http://solr:8983/solr/dovecot-fts/update?commit=true');
|
||||
curl_setopt($curl, CURLOPT_HTTPHEADER,array('Content-Type: text/xml'));
|
||||
|
||||
@@ -145,17 +145,22 @@ function rspamd_maps($_action, $_data = null) {
|
||||
$maps = (array)$_data['map'];
|
||||
$valid_maps = array();
|
||||
foreach ($maps as $map) {
|
||||
$is_valid = false;
|
||||
foreach ($RSPAMD_MAPS as $rspamd_map_type) {
|
||||
if (!in_array($map, $rspamd_map_type)) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, '-'),
|
||||
'msg' => array('global_map_invalid', $map)
|
||||
);
|
||||
} else {
|
||||
array_push($valid_maps, $map);
|
||||
if (in_array($map, $rspamd_map_type)) {
|
||||
$is_valid = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($is_valid) {
|
||||
array_push($valid_maps, $map);
|
||||
} else {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, '-'),
|
||||
'msg' => array('global_map_invalid', $map)
|
||||
);
|
||||
}
|
||||
}
|
||||
foreach ($valid_maps as $map) {
|
||||
try {
|
||||
|
||||
@@ -49,7 +49,6 @@ $globalVariables = [
|
||||
'app_links' => customize('get', 'app_links'),
|
||||
'is_root_uri' => (parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH) == '/'),
|
||||
'uri' => $_SERVER['REQUEST_URI'],
|
||||
'last_login' => last_login('get', $_SESSION['mailcow_cc_username'], 7, 0)['ui']['time']
|
||||
];
|
||||
|
||||
foreach ($globalVariables as $globalVariableName => $globalVariableValue) {
|
||||
|
||||
@@ -3,7 +3,7 @@ function init_db_schema() {
|
||||
try {
|
||||
global $pdo;
|
||||
|
||||
$db_version = "26022024_1433";
|
||||
$db_version = "29072024_1000";
|
||||
|
||||
$stmt = $pdo->query("SHOW TABLES LIKE 'versions'");
|
||||
$num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
|
||||
@@ -483,6 +483,7 @@ function init_db_schema() {
|
||||
"quarantine_notification" => "TINYINT(1) NOT NULL DEFAULT '1'",
|
||||
"quarantine_category" => "TINYINT(1) NOT NULL DEFAULT '1'",
|
||||
"app_passwds" => "TINYINT(1) NOT NULL DEFAULT '1'",
|
||||
"pw_reset" => "TINYINT(1) NOT NULL DEFAULT '1'",
|
||||
),
|
||||
"keys" => array(
|
||||
"primary" => array(
|
||||
@@ -694,6 +695,19 @@ function init_db_schema() {
|
||||
),
|
||||
"attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC"
|
||||
),
|
||||
"reset_password" => array(
|
||||
"cols" => array(
|
||||
"username" => "VARCHAR(255) NOT NULL",
|
||||
"token" => "VARCHAR(255) NOT NULL",
|
||||
"created" => "DATETIME(0) NOT NULL DEFAULT NOW(0)",
|
||||
),
|
||||
"keys" => array(
|
||||
"primary" => array(
|
||||
"" => array("token", "created")
|
||||
),
|
||||
),
|
||||
"attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC"
|
||||
),
|
||||
"imapsync" => array(
|
||||
"cols" => array(
|
||||
"id" => "INT NOT NULL AUTO_INCREMENT",
|
||||
|
||||
33
data/web/inc/lib/sieve/extensions/enotify.xml
Normal file
33
data/web/inc/lib/sieve/extensions/enotify.xml
Normal file
@@ -0,0 +1,33 @@
|
||||
<?xml version='1.0' standalone='yes'?>
|
||||
|
||||
<extension name="enotify">
|
||||
<command name="notify">
|
||||
<parameter type="tag" name="from" occurrence="optional">
|
||||
<parameter type="string" name="from-address" />
|
||||
</parameter>
|
||||
|
||||
<parameter type="tag" name="importance" regex="(1|2|3)" occurrence="optional" />
|
||||
|
||||
<parameter type="tag" name="options" occurrence="optional">
|
||||
<parameter type="stringlist" name="option-strings" />
|
||||
</parameter>
|
||||
|
||||
<parameter type="tag" name="message" occurrence="optional">
|
||||
<parameter type="string" name="message-text" />
|
||||
</parameter>
|
||||
|
||||
<parameter type="string" name="method" />
|
||||
</command>
|
||||
|
||||
<test name="valid_notify_method">
|
||||
<parameter type="stringlist" name="notification-uris" />
|
||||
</test>
|
||||
|
||||
<test name="notify_method_capability">
|
||||
<parameter type="string" name="notification-uri" />
|
||||
<parameter type="string" name="notification-capability" />
|
||||
<parameter type="stringlist" name="key-list" />
|
||||
</test>
|
||||
|
||||
<modifier name="encodeurl" />
|
||||
</extension>
|
||||
58
data/web/inc/lib/sieve/extensions/mime.xml
Normal file
58
data/web/inc/lib/sieve/extensions/mime.xml
Normal file
@@ -0,0 +1,58 @@
|
||||
<?xml version='1.0' standalone='yes'?>
|
||||
|
||||
<extension name="mime">
|
||||
<command name="foreverypart">
|
||||
<parameter type="string" name="name" occurrence="optional" />
|
||||
<block />
|
||||
</command>
|
||||
|
||||
<command name="break">
|
||||
<parameter type="string" name="name" occurrence="optional" />
|
||||
</command>
|
||||
|
||||
<tagged-argument extends="(header|address|exists)">
|
||||
<parameter type="tag" name="mime" regex="mime" occurrence="optional" />
|
||||
</tagged-argument>
|
||||
<tagged-argument extends="(header|address|exists)">
|
||||
<parameter type="tag" name="anychild" regex="anychild" occurrence="optional" />
|
||||
</tagged-argument>
|
||||
<tagged-argument extends="(header)">
|
||||
<parameter type="tag" name="type" occurrence="optional" />
|
||||
</tagged-argument>
|
||||
<tagged-argument extends="(header)">
|
||||
<parameter type="tag" name="subtype" occurrence="optional" />
|
||||
</tagged-argument>
|
||||
<tagged-argument extends="(header)">
|
||||
<parameter type="tag" name="contenttype" occurrence="optional" />
|
||||
</tagged-argument>
|
||||
<tagged-argument extends="(header)">
|
||||
<parameter type="tag" name="param" regex="param" occurrence="optional">
|
||||
<parameter type="stringlist" name="param-list" />
|
||||
</parameter>
|
||||
</tagged-argument>
|
||||
<tagged-argument extends="(header|address|exists)">
|
||||
<parameter type="stringlist" name="header-names" />
|
||||
</tagged-argument>
|
||||
<tagged-argument extends="(header)">
|
||||
<parameter type="stringlist" name="key-list" />
|
||||
</tagged-argument>
|
||||
|
||||
<action name="replace">
|
||||
<parameter type="tag" name="mime" regex="mime" occurrence="optional" />
|
||||
<parameter type="string" name="subject" occurrence="optional" />
|
||||
<parameter type="string" name="from" occurrence="optional" />
|
||||
<parameter type="string" name="replacement" />
|
||||
</action>
|
||||
|
||||
<action name="enclose">
|
||||
<parameter type="string" name="subject" occurrence="optional" />
|
||||
<parameter type="stringlist" name="headers" occurrence="optional" />
|
||||
<parameter type="string" name="text" />
|
||||
</action>
|
||||
|
||||
<action name="extracttext">
|
||||
<parameter type="tag" name="first" regex="first" occurrence="optional" />
|
||||
<parameter type="number" name="number" occurrence="optional" />
|
||||
<parameter type="string" name="varname" />
|
||||
</action>
|
||||
</extension>
|
||||
@@ -1,7 +1,7 @@
|
||||
headline: lang.sieve_preset_1
|
||||
content: |
|
||||
require ["reject","body","regex"];
|
||||
if anyof (body :raw :regex ["filename=.*\.doc","filename=.*\.exe","filename=.*\.moo"]) {
|
||||
if anyof (body :raw :regex ["filename=\".*\\.(doc|exe|moo)\""]) {
|
||||
reject text:
|
||||
doc, exe and moo are dangerous file extensions.
|
||||
Why would you do that? I am a sad cow.
|
||||
|
||||
@@ -10,16 +10,54 @@ if (!empty($_GET['sso_token'])) {
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($_POST["pw_reset_request"]) && !empty($_POST['username'])) {
|
||||
reset_password("issue", $_POST['username']);
|
||||
header("Location: /");
|
||||
exit;
|
||||
}
|
||||
if (isset($_POST["pw_reset"])) {
|
||||
$username = reset_password("check", $_POST['token']);
|
||||
$reset_result = reset_password("reset", array(
|
||||
'new_password' => $_POST['new_password'],
|
||||
'new_password2' => $_POST['new_password2'],
|
||||
'token' => $_POST['token'],
|
||||
'username' => $username,
|
||||
'check_tfa' => True
|
||||
));
|
||||
|
||||
if ($reset_result){
|
||||
header("Location: /");
|
||||
exit;
|
||||
}
|
||||
}
|
||||
if (isset($_POST["verify_tfa_login"])) {
|
||||
if (verify_tfa_login($_SESSION['pending_mailcow_cc_username'], $_POST)) {
|
||||
$_SESSION['mailcow_cc_username'] = $_SESSION['pending_mailcow_cc_username'];
|
||||
$_SESSION['mailcow_cc_role'] = $_SESSION['pending_mailcow_cc_role'];
|
||||
unset($_SESSION['pending_mailcow_cc_username']);
|
||||
unset($_SESSION['pending_mailcow_cc_role']);
|
||||
unset($_SESSION['pending_tfa_methods']);
|
||||
if (isset($_SESSION['pending_mailcow_cc_username']) && isset($_SESSION['pending_pw_reset_token']) && isset($_SESSION['pending_pw_new_password'])) {
|
||||
reset_password("reset", array(
|
||||
'new_password' => $_SESSION['pending_pw_new_password'],
|
||||
'new_password2' => $_SESSION['pending_pw_new_password'],
|
||||
'token' => $_SESSION['pending_pw_reset_token'],
|
||||
'username' => $_SESSION['pending_mailcow_cc_username']
|
||||
));
|
||||
unset($_SESSION['pending_pw_reset_token']);
|
||||
unset($_SESSION['pending_pw_new_password']);
|
||||
unset($_SESSION['pending_mailcow_cc_username']);
|
||||
unset($_SESSION['pending_tfa_methods']);
|
||||
|
||||
header("Location: /user");
|
||||
header("Location: /");
|
||||
exit;
|
||||
} else {
|
||||
$_SESSION['mailcow_cc_username'] = $_SESSION['pending_mailcow_cc_username'];
|
||||
$_SESSION['mailcow_cc_role'] = $_SESSION['pending_mailcow_cc_role'];
|
||||
unset($_SESSION['pending_mailcow_cc_username']);
|
||||
unset($_SESSION['pending_mailcow_cc_role']);
|
||||
unset($_SESSION['pending_tfa_methods']);
|
||||
|
||||
header("Location: /user");
|
||||
}
|
||||
} else {
|
||||
unset($_SESSION['pending_pw_reset_token']);
|
||||
unset($_SESSION['pending_pw_new_password']);
|
||||
unset($_SESSION['pending_mailcow_cc_username']);
|
||||
unset($_SESSION['pending_mailcow_cc_role']);
|
||||
unset($_SESSION['pending_tfa_methods']);
|
||||
@@ -27,11 +65,13 @@ if (isset($_POST["verify_tfa_login"])) {
|
||||
}
|
||||
|
||||
if (isset($_GET["cancel_tfa_login"])) {
|
||||
unset($_SESSION['pending_mailcow_cc_username']);
|
||||
unset($_SESSION['pending_mailcow_cc_role']);
|
||||
unset($_SESSION['pending_tfa_methods']);
|
||||
unset($_SESSION['pending_pw_reset_token']);
|
||||
unset($_SESSION['pending_pw_new_password']);
|
||||
unset($_SESSION['pending_mailcow_cc_username']);
|
||||
unset($_SESSION['pending_mailcow_cc_role']);
|
||||
unset($_SESSION['pending_tfa_methods']);
|
||||
|
||||
header("Location: /");
|
||||
header("Location: /");
|
||||
}
|
||||
|
||||
if (isset($_POST["quick_release"])) {
|
||||
|
||||
@@ -210,6 +210,12 @@ $MAILBOX_DEFAULT_ATTRIBUTES['mailbox_format'] = 'maildir:';
|
||||
// Show last IMAP and POP3 logins
|
||||
$SHOW_LAST_LOGIN = true;
|
||||
|
||||
// Maximum number of password reset tokens that can be generated at once per user
|
||||
$PW_RESET_TOKEN_LIMIT = 3;
|
||||
|
||||
// Maximum time in minutes a password reset token is valid
|
||||
$PW_RESET_TOKEN_LIFETIME = 15;
|
||||
|
||||
// UV flag handling in FIDO2/WebAuthn - defaults to false to allow iOS logins
|
||||
// true = required
|
||||
// false = preferred
|
||||
|
||||
@@ -397,7 +397,10 @@ jQuery(function($){
|
||||
{
|
||||
title: lang.host,
|
||||
data: 'hostname',
|
||||
defaultContent: ''
|
||||
defaultContent: '',
|
||||
render: function (data, type) {
|
||||
return escapeHtml(data);
|
||||
}
|
||||
},
|
||||
{
|
||||
title: lang.username,
|
||||
|
||||
@@ -325,7 +325,10 @@ jQuery(function($){
|
||||
title: 'URI',
|
||||
data: 'uri',
|
||||
defaultContent: '',
|
||||
className: 'dtr-col-md dtr-break-all'
|
||||
className: 'dtr-col-md dtr-break-all',
|
||||
render: function (data, type) {
|
||||
return escapeHtml(data);
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Method',
|
||||
@@ -1294,13 +1297,7 @@ function update_stats(timeout=5){
|
||||
$("#host_cpu_usage").text(parseInt(data.cpu.usage).toString() + "%");
|
||||
$("#host_memory_total").text((data.memory.total / (1024 ** 3)).toFixed(2).toString() + "GB");
|
||||
$("#host_memory_usage").text(parseInt(data.memory.usage).toString() + "%");
|
||||
if (data.architecture == "aarch64"){
|
||||
$("#host_architecture").html('<span data-bs-toggle="tooltip" data-bs-placement="top" title="' + lang_debug.wip +'">' + data.architecture + ' ⚠️</span>');
|
||||
}
|
||||
else {
|
||||
$("#host_architecture").html(data.architecture);
|
||||
}
|
||||
|
||||
$("#host_architecture").html(data.architecture);
|
||||
// update cpu and mem chart
|
||||
var cpu_chart = Chart.getChart("host_cpu_chart");
|
||||
var mem_chart = Chart.getChart("host_mem_chart");
|
||||
|
||||
@@ -380,6 +380,9 @@ $(document).ready(function() {
|
||||
if (template.acl_app_passwds == 1){
|
||||
acl.push("app_passwds");
|
||||
}
|
||||
if (template.acl_pw_reset == 1){
|
||||
acl.push("pw_reset");
|
||||
}
|
||||
$('#user_acl').selectpicker('val', acl);
|
||||
|
||||
$('#rl_value').val(template.rl_value);
|
||||
|
||||
@@ -676,5 +676,5 @@ jQuery(function($){
|
||||
onVisible("[id^=wl_policy_mailbox_table]", () => draw_wl_policy_mailbox_table());
|
||||
onVisible("[id^=sync_job_table]", () => draw_sync_job_table());
|
||||
onVisible("[id^=app_passwd_table]", () => draw_app_passwd_table());
|
||||
last_logins('get');
|
||||
onVisible("[id^=recent-logins]", () => last_logins('get'));
|
||||
});
|
||||
|
||||
@@ -1973,7 +1973,6 @@ if (isset($_GET['query'])) {
|
||||
case "quota_notification_bcc":
|
||||
process_edit_return(quota_notification_bcc('edit', $attr));
|
||||
break;
|
||||
break;
|
||||
case "mailq":
|
||||
process_edit_return(mailq('edit', array_merge(array('qid' => $items), $attr)));
|
||||
break;
|
||||
@@ -2069,6 +2068,9 @@ if (isset($_GET['query'])) {
|
||||
case "cors":
|
||||
process_edit_return(cors('edit', $attr));
|
||||
break;
|
||||
case "reset-password-notification":
|
||||
process_edit_return(reset_password('edit_notification', $attr));
|
||||
break;
|
||||
// return no route found if no case is matched
|
||||
default:
|
||||
http_response_code(404);
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
"prohibited": "Untersagt durch Richtlinie",
|
||||
"protocol_access": "Ändern der erlaubten Protokolle",
|
||||
"pushover": "Pushover",
|
||||
"pw_reset": "Verwalten der E-Mail zur Passwortwiederherstellung erlauben",
|
||||
"quarantine": "Quarantäne-Aktionen",
|
||||
"quarantine_attachments": "Anhänge aus Quarantäne",
|
||||
"quarantine_category": "Ändern der Quarantäne-Benachrichtigungskategorie",
|
||||
@@ -248,6 +249,11 @@
|
||||
"password_policy_numbers": "Muss eine Ziffer enthalten",
|
||||
"password_policy_special_chars": "Muss Sonderzeichen enthalten",
|
||||
"password_repeat": "Passwort wiederholen",
|
||||
"password_reset_info": "Wenn keine E-Mail zur Passwortwiederherstellung hinterlegt ist, kann diese Funktion nicht genutzt werden.",
|
||||
"password_reset_settings": "Einstellungen zur Passwortwiederherstellung",
|
||||
"password_reset_tmpl_html": "HTML Vorlage",
|
||||
"password_reset_tmpl_text": "Text Vorlage",
|
||||
"password_settings": "Passwort Einstellungen",
|
||||
"priority": "Gewichtung",
|
||||
"private_key": "Private Key",
|
||||
"quarantine": "Quarantäne",
|
||||
@@ -287,6 +293,8 @@
|
||||
"remove_row": "Entfernen",
|
||||
"reset_default": "Zurücksetzen auf Standard",
|
||||
"reset_limit": "Hash entfernen",
|
||||
"reset_password_vars": "<code>{{link}}</code> Der generierte Passwort-Reset-Link<br><code>{{username}}</code> Die E-Mail-Adresse des Benutzers, der die Passwortzurücksetzung angefordert hat<br><code>{{username2}}</code> Die E-Mail-Adresse zur Wiederherstellung<br><code>{{date}}</code> Das Datum, an dem die Passwort-Reset-Anfrage gestellt wurde<br><code>{{token_lifetime}}</code> Die Gültigkeitsdauer des Tokens in Minuten<br><code>{{hostname}}</code> Der mailcow Hostname",
|
||||
"restore_template": "Leer lassen, um Standard-Template wiederherzustellen.",
|
||||
"routing": "Routing",
|
||||
"rsetting_add_rule": "Regel hinzufügen",
|
||||
"rsetting_content": "Regelinhalt",
|
||||
@@ -407,6 +415,7 @@
|
||||
"invalid_nexthop_authenticated": "Dieser Next Hop existiert bereits mit abweichenden Authentifizierungsdaten. Die bestehenden Authentifizierungsdaten dieses \"Next Hops\" müssen vorab angepasst werden.",
|
||||
"invalid_recipient_map_new": "Neuer Empfänger \"%s\" ist ungültig",
|
||||
"invalid_recipient_map_old": "Originaler Empfänger \"%s\" ist ungültig",
|
||||
"invalid_reset_token": "Ungültiger Rücksetz-Token",
|
||||
"ip_list_empty": "Liste erlaubter IPs darf nicht leer sein",
|
||||
"is_alias": "%s lautet bereits eine Alias-Adresse",
|
||||
"is_alias_or_mailbox": "Eine Mailbox, ein Alias oder eine sich aus einer Alias-Domain ergebende Adresse mit dem Namen %s ist bereits vorhanden",
|
||||
@@ -436,6 +445,8 @@
|
||||
"password_complexity": "Passwort entspricht nicht den Richtlinien",
|
||||
"password_empty": "Passwort darf nicht leer sein",
|
||||
"password_mismatch": "Passwort-Wiederholung stimmt nicht überein",
|
||||
"password_reset_invalid_user": "Benutzer nicht gefunden oder keine E-Mail-Adresse zur Wiederherstellung eingerichtet",
|
||||
"password_reset_na": "Die Passwortwiederherstellung ist momentan nicht verfügbar. Bitte wenden Sie sich an Ihren Administrator.",
|
||||
"policy_list_from_exists": "Ein Eintrag mit diesem Wert existiert bereits",
|
||||
"policy_list_from_invalid": "Eintrag hat ein ungültiges Format",
|
||||
"private_key_error": "Schlüsselfehler: %s",
|
||||
@@ -444,10 +455,12 @@
|
||||
"pushover_token": "Pushover Token hat das falsche Format",
|
||||
"quota_not_0_not_numeric": "Speicherplatz muss numerisch und >= 0 sein",
|
||||
"recipient_map_entry_exists": "Eine Empfängerumschreibung für Objekt \"%s\" existiert bereits",
|
||||
"recovery_email_failed": "E-Mail zur Wiederherstellung konnte nicht gesendet werden. Bitte wenden Sie sich an Ihren Administrator.",
|
||||
"redis_error": "Redis Fehler: %s",
|
||||
"relayhost_invalid": "Map-Eintrag %s ist ungültig",
|
||||
"release_send_failed": "Die Nachricht konnte nicht versendet werden: %s",
|
||||
"reset_f2b_regex": "Regex-Filter konnten nicht in vorgegebener Zeit zurückgesetzt werden, bitte erneut versuchen oder die Webseite neu laden.",
|
||||
"reset_token_limit_exceeded": "Das Limit für Rücksetz-Tokens wurde überschritten. Bitte versuchen Sie es später erneut.",
|
||||
"resource_invalid": "Ressourcenname %s ist ungültig",
|
||||
"rl_timeframe": "Ratelimit-Zeitraum ist inkorrekt",
|
||||
"rspamd_ui_pw_length": "Rspamd UI-Passwort muss mindestens 6 Zeichen lang sein",
|
||||
@@ -467,6 +480,7 @@
|
||||
"tls_policy_map_dest_invalid": "Ziel ist ungültig",
|
||||
"tls_policy_map_entry_exists": "Eine TLS-Richtlinie \"%s\" existiert bereits",
|
||||
"tls_policy_map_parameter_invalid": "Parameter ist ungültig",
|
||||
"to_invalid": "Empfänger darf nicht leer sein",
|
||||
"totp_verification_failed": "TOTP-Verifizierung fehlgeschlagen",
|
||||
"transport_dest_exists": "Transport-Maps-Ziel \"%s\" existiert bereits",
|
||||
"webauthn_verification_failed": "WebAuthn-Verifizierung fehlgeschlagen: %s",
|
||||
@@ -638,6 +652,7 @@
|
||||
"nexthop": "Next Hop",
|
||||
"none_inherit": "Keine Auswahl / Erben",
|
||||
"password": "Passwort",
|
||||
"password_recovery_email": "E-Mail zur Passwortwiederherstellung",
|
||||
"password_repeat": "Passwort wiederholen",
|
||||
"previous": "Vorherige Seite",
|
||||
"private_comment": "Privater Kommentar",
|
||||
@@ -741,12 +756,19 @@
|
||||
"session_expires": "Die Sitzung wird in etwa 15 Sekunden beendet."
|
||||
},
|
||||
"login": {
|
||||
"back_to_mailcow": "Zurück zu mailcow",
|
||||
"delayed": "Login wurde zur Sicherheit um %s Sekunde/n verzögert.",
|
||||
"fido2_webauthn": "FIDO2/WebAuthn Login",
|
||||
"forgot_password": "> Passwort vergessen?",
|
||||
"invalid_pass_reset_token": "Der Rücksetz-Token für das Passwort ist ungültig oder abgelaufen.<br>Bitte fordern Sie einen neuen Link zur Passwortwiederherstellung an.",
|
||||
"login": "Anmelden",
|
||||
"mobileconfig_info": "Bitte als Mailbox-Benutzer einloggen, um das Verbindungsprofil herunterzuladen.",
|
||||
"new_password": "Neues Passwort",
|
||||
"new_password_confirm": "Neues Passwort bestätigen",
|
||||
"other_logins": "Key Login",
|
||||
"password": "Passwort",
|
||||
"reset_password": "Passwort zurücksetzen",
|
||||
"request_reset_password": "Passwortänderung anfordern",
|
||||
"username": "Benutzername"
|
||||
},
|
||||
"mailbox": {
|
||||
@@ -1065,11 +1087,13 @@
|
||||
"nginx_reloaded": "Nginx wurde neu geladen",
|
||||
"object_modified": "Änderungen an Objekt %s wurden gespeichert",
|
||||
"password_policy_saved": "Passwortrichtlinie wurde erfolgreich gespeichert",
|
||||
"password_changed_success": "Das Passwort wurde erfolgreich geändert",
|
||||
"pushover_settings_edited": "Pushover-Konfiguration gespeichert, bitte den Zugang im Anschluss verifizieren.",
|
||||
"qlearn_spam": "Nachricht-ID %s wurde als Spam gelernt und gelöscht",
|
||||
"queue_command_success": "Queue-Aufgabe erfolgreich ausgeführt",
|
||||
"recipient_map_entry_deleted": "Empfängerumschreibung mit der ID %s wurde gelöscht",
|
||||
"recipient_map_entry_saved": "Empfängerumschreibung für Objekt \"%s\" wurde gespeichert",
|
||||
"recovery_email_sent": "Wiederherstellungs-E-Mail an %s gesendet",
|
||||
"relayhost_added": "Map-Eintrag %s wurde hinzugefügt",
|
||||
"relayhost_removed": "Map-Eintrag %s wurde entfernt",
|
||||
"reset_main_logo": "Standardgrafik wurde wiederhergestellt",
|
||||
@@ -1202,6 +1226,7 @@
|
||||
"password": "Passwort",
|
||||
"password_now": "Aktuelles Passwort (Änderungen bestätigen)",
|
||||
"password_repeat": "Passwort (Wiederholung)",
|
||||
"password_reset_info": "Wenn keine E-Mail zur Passwortwiederherstellung hinterlegt ist, kann diese Funktion nicht genutzt werden.",
|
||||
"pushover_evaluate_x_prio": "Hohe Priorität eskalieren [<code>X-Priority: 1</code>]",
|
||||
"pushover_info": "Push-Benachrichtungen werden angewendet auf alle nicht-Spam Nachrichten zugestellt an <b>%s</b>, einschließlich Alias-Adressen (shared, non-shared, tagged).",
|
||||
"pushover_only_x_prio": "Nur Mail mit hoher Priorität berücksichtigen [<code>X-Priority: 1</code>]",
|
||||
@@ -1211,6 +1236,7 @@
|
||||
"pushover_title": "Notification Titel",
|
||||
"pushover_vars": "Wenn kein Sender-Filter definiert ist, werden alle E-Mails berücksichtigt.<br>Die direkte Absenderprüfung und reguläre Ausdrücke werden unabhängig voneinander geprüft, sie <b>hängen nicht voneinander ab</b> und werden der Reihe nach ausgeführt. <br>Verwendbare Variablen für Titel und Text (Datenschutzrichtlinien beachten)",
|
||||
"pushover_verify": "Verbindung verifizieren",
|
||||
"pw_recovery_email": "E-Mail zur Passwortwiederherstellung",
|
||||
"q_add_header": "Junk-Ordner",
|
||||
"q_all": "Alle Kategorien",
|
||||
"q_reject": "Abgelehnt",
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
"prohibited": "Prohibited by ACL",
|
||||
"protocol_access": "Change protocol access",
|
||||
"pushover": "Pushover",
|
||||
"pw_reset": "Allow to reset mailcow user password",
|
||||
"quarantine": "Quarantine actions",
|
||||
"quarantine_attachments": "Quarantine attachments",
|
||||
"quarantine_category": "Change quarantine notification category",
|
||||
@@ -256,6 +257,11 @@
|
||||
"password_policy_numbers": "Must contain at least one number",
|
||||
"password_policy_special_chars": "Must contain special characters",
|
||||
"password_repeat": "Confirmation password (repeat)",
|
||||
"password_reset_info": "If no recovery email is provided, this function cannot be used.",
|
||||
"password_reset_settings": "Password Recovery Settings",
|
||||
"password_reset_tmpl_html": "HTML Template",
|
||||
"password_reset_tmpl_text": "Text Template",
|
||||
"password_settings": "Password Settings",
|
||||
"priority": "Priority",
|
||||
"private_key": "Private key",
|
||||
"quarantine": "Quarantine",
|
||||
@@ -296,6 +302,8 @@
|
||||
"remove_row": "Remove row",
|
||||
"reset_default": "Reset to default",
|
||||
"reset_limit": "Remove hash",
|
||||
"reset_password_vars": "<code>{{link}}</code> The generated password reset link<br><code>{{username}}</code> The mailbox name of the user who requested the password reset<br><code>{{username2}}</code> The recovery mailbox name<br><code>{{date}}</code> The date the password reset request was made<br><code>{{token_lifetime}}</code> The token lifetime in minutes<br><code>{{hostname}}</code> The mailcow hostname",
|
||||
"restore_template": "Leave empty to restore default template.",
|
||||
"routing": "Routing",
|
||||
"rsetting_add_rule": "Add rule",
|
||||
"rsetting_content": "Rule content",
|
||||
@@ -407,6 +415,7 @@
|
||||
"invalid_nexthop_authenticated": "Next hop exists with different credentials, please update the existing credentials for this next hop first.",
|
||||
"invalid_recipient_map_new": "Invalid new recipient specified: %s",
|
||||
"invalid_recipient_map_old": "Invalid original recipient specified: %s",
|
||||
"invalid_reset_token": "Invalid reset token",
|
||||
"ip_list_empty": "List of allowed IPs cannot be empty",
|
||||
"is_alias": "%s is already known as an alias address",
|
||||
"is_alias_or_mailbox": "%s is already known as an alias, a mailbox or an alias address expanded from an alias domain.",
|
||||
@@ -436,6 +445,8 @@
|
||||
"password_complexity": "Password does not meet the policy",
|
||||
"password_empty": "Password must not be empty",
|
||||
"password_mismatch": "Confirmation password does not match",
|
||||
"password_reset_invalid_user": "Mailbox not found or no recovery email is set",
|
||||
"password_reset_na": "The password recovery is currently unavailable. Please contact your administrator.",
|
||||
"policy_list_from_exists": "A record with given name exists",
|
||||
"policy_list_from_invalid": "Record has invalid format",
|
||||
"private_key_error": "Private key error: %s",
|
||||
@@ -444,10 +455,12 @@
|
||||
"pushover_token": "Pushover token has a wrong format",
|
||||
"quota_not_0_not_numeric": "Quota must be numeric and >= 0",
|
||||
"recipient_map_entry_exists": "A Recipient map entry \"%s\" exists",
|
||||
"recovery_email_failed": "Could not send a recovery email. Please contact your administrator.",
|
||||
"redis_error": "Redis error: %s",
|
||||
"relayhost_invalid": "Map entry %s is invalid",
|
||||
"release_send_failed": "Message could not be released: %s",
|
||||
"reset_f2b_regex": "Regex filter could not be reset in time, please try again or wait a few more seconds and reload the website.",
|
||||
"reset_token_limit_exceeded": "Reset token limit has been exceeded. Please try again later.",
|
||||
"resource_invalid": "Resource name %s is invalid",
|
||||
"rl_timeframe": "Rate limit time frame is incorrect",
|
||||
"rspamd_ui_pw_length": "Rspamd UI password should be at least 6 chars long",
|
||||
@@ -470,6 +483,7 @@
|
||||
"tls_policy_map_dest_invalid": "Policy destination is invalid",
|
||||
"tls_policy_map_entry_exists": "A TLS policy map entry \"%s\" exists",
|
||||
"tls_policy_map_parameter_invalid": "Policy parameter is invalid",
|
||||
"to_invalid": "Recipient must not be empty",
|
||||
"totp_verification_failed": "TOTP verification failed",
|
||||
"transport_dest_exists": "Transport destination \"%s\" exists",
|
||||
"webauthn_verification_failed": "WebAuthn verification failed: %s",
|
||||
@@ -638,6 +652,7 @@
|
||||
"none_inherit": "None / Inherit",
|
||||
"nexthop": "Next hop",
|
||||
"password": "Password",
|
||||
"password_recovery_email": "Password recovery email",
|
||||
"password_repeat": "Confirmation password (repeat)",
|
||||
"previous": "Previous page",
|
||||
"private_comment": "Private comment",
|
||||
@@ -741,12 +756,19 @@
|
||||
"session_expires": "Your session will expire in about 15 seconds"
|
||||
},
|
||||
"login": {
|
||||
"back_to_mailcow": "Back to mailcow",
|
||||
"delayed": "Login was delayed by %s seconds.",
|
||||
"fido2_webauthn": "FIDO2/WebAuthn Login",
|
||||
"forgot_password": "> Forgot Password?",
|
||||
"invalid_pass_reset_token": "The reset password token is invalid or has expired.<br>Please request a new password reset link.",
|
||||
"login": "Login",
|
||||
"mobileconfig_info": "Please login as mailbox user to download the requested Apple connection profile.",
|
||||
"new_password": "New Password",
|
||||
"new_password_confirm": "Confirm new password",
|
||||
"other_logins": "Key login",
|
||||
"password": "Password",
|
||||
"reset_password": "Reset Password",
|
||||
"request_reset_password": "Request password change",
|
||||
"username": "Username"
|
||||
},
|
||||
"mailbox": {
|
||||
@@ -1072,11 +1094,13 @@
|
||||
"nginx_reloaded": "Nginx was reloaded",
|
||||
"object_modified": "Changes to object %s have been saved",
|
||||
"password_policy_saved": "Password policy was saved successfully",
|
||||
"password_changed_success": "Password was successfully changed",
|
||||
"pushover_settings_edited": "Pushover settings successfully set, please verify credentials.",
|
||||
"qlearn_spam": "Message ID %s was learned as spam and deleted",
|
||||
"queue_command_success": "Queue command completed successfully",
|
||||
"recipient_map_entry_deleted": "Recipient map ID %s has been deleted",
|
||||
"recipient_map_entry_saved": "Recipient map entry \"%s\" has been saved",
|
||||
"recovery_email_sent": "Recovery email sent to %s",
|
||||
"relayhost_added": "Map entry %s has been added",
|
||||
"relayhost_removed": "Map entry %s has been removed",
|
||||
"reset_main_logo": "Reset to default logo",
|
||||
@@ -1210,6 +1234,7 @@
|
||||
"password": "Password",
|
||||
"password_now": "Current password (confirm changes)",
|
||||
"password_repeat": "Password (repeat)",
|
||||
"password_reset_info": "If no email for password recovery is provided, this function cannot be used.",
|
||||
"pushover_evaluate_x_prio": "Escalate high priority mail [<code>X-Priority: 1</code>]",
|
||||
"pushover_info": "Push notification settings will apply to all clean (non-spam) mail delivered to <b>%s</b> including aliases (shared, non-shared, tagged).",
|
||||
"pushover_only_x_prio": "Only consider high priority mail [<code>X-Priority: 1</code>]",
|
||||
@@ -1220,6 +1245,7 @@
|
||||
"pushover_sound": "Sound",
|
||||
"pushover_vars": "When no sender filter is defined, all mails will be considered.<br>Regex filters as well as exact sender checks can be defined individually and will be considered sequentially. They do not depend on each other.<br>Useable variables for text and title (please take note of data protection policies)",
|
||||
"pushover_verify": "Verify credentials",
|
||||
"pw_recovery_email": "Password recovery email",
|
||||
"q_add_header": "Junk folder",
|
||||
"q_all": "All categories",
|
||||
"q_reject": "Rejected",
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
"spam_score": "Score SPAM",
|
||||
"syncjobs": "Tâches de synchronisation",
|
||||
"tls_policy": "Politique TLS",
|
||||
"unlimited_quota": "Quota illimité pour les boites de courriel",
|
||||
"unlimited_quota": "Quota illimité pour les boîtes de réception",
|
||||
"domain_desc": "Modifier la description du domaine",
|
||||
"domain_relayhost": "Changer le relais pour un domaine",
|
||||
"mailbox_relayhost": "Changer le relais d’une boîte de réception"
|
||||
@@ -52,7 +52,7 @@
|
||||
"delete2duplicates": "Supprimer les doubles à destination",
|
||||
"description": "Description",
|
||||
"destination": "Destination",
|
||||
"disable_login": "Désactiver l'authentification (les e-mails entrants resteront acceptés)",
|
||||
"disable_login": "Désactiver l'authentification (les courriels entrants resteront acceptés)",
|
||||
"domain": "domaine",
|
||||
"domain_matches_hostname": "Le domaine %s correspond à la machine (hostname)",
|
||||
"domain_quota_m": "Quota total du domaine (Mo)",
|
||||
@@ -68,11 +68,11 @@
|
||||
"hostname": "Nom d'hôte",
|
||||
"inactive": "Inactif",
|
||||
"kind": "Type",
|
||||
"mailbox_quota_def": "Quota boîte mail par défaut",
|
||||
"mailbox_quota_m": "Quota max par boîte (Mo)",
|
||||
"mailbox_quota_def": "Quota boîte de réception par défaut",
|
||||
"mailbox_quota_m": "Quota max par boîte de réception (Mo)",
|
||||
"mailbox_username": "Identifiant (partie gauche d'une adresse de courriel)",
|
||||
"max_aliases": "Nombre maximal d'alias",
|
||||
"max_mailboxes": "Nombre maximal de boîtes",
|
||||
"max_mailboxes": "Nombre maximal de boîtes de réception",
|
||||
"mins_interval": "Période de relève (minutes)",
|
||||
"multiple_bookings": "Inscriptions multiples",
|
||||
"nexthop": "Suivant",
|
||||
@@ -84,10 +84,10 @@
|
||||
"public_comment": "Commentaire public",
|
||||
"quota_mb": "Quota (Mo)",
|
||||
"relay_all": "Relayer tous les destinataires",
|
||||
"relay_all_info": "↪ Si vous choissisez <b>de ne pas</b> relayer tous les destinataires, vous devez ajouter une boîte (\"aveugle\") pour chaque destinataire simple qui doit être relayé.",
|
||||
"relay_all_info": "↪ Si vous choissisez <b>de ne pas</b> relayer tous les destinataires, vous devez ajouter une boîte de réception (\"aveugle\") pour chaque destinataire simple qui doit être relayé.",
|
||||
"relay_domain": "Relayer ce domaine",
|
||||
"relay_transport_info": "<div class=\"badge fs-6 bg-info\">Info</div> Vous pouvez définir des cartes de transport vers une destination personnalisée pour ce domaine. sinon, une recherche MX sera effectuée.",
|
||||
"relay_unknown_only": "Relayer uniquement les boîtes inexistantes. Les boîtes existantes seront livrées localement.",
|
||||
"relay_unknown_only": "Relayer uniquement les boîtes de réception inexistantes. Les boîtes de réception existantes seront livrées localement.",
|
||||
"relayhost_wrapped_tls_info": "Veuillez <b>ne pas</b> utiliser des ports TLS wrappés (généralement utilisés sur le port 465).<br>\r\nUtilisez n'importe quel port non encapsulé et lancez STARTTLS. Une politique TLS pour appliquer TLS peut être créée dans \"Cartes de politique TLS\".",
|
||||
"select": "Veuillez sélectionner…",
|
||||
"select_domain": "Sélectionner d'abord un domaine",
|
||||
@@ -96,7 +96,7 @@
|
||||
"skipcrossduplicates": "Ignorer les messages en double dans les dossiers (premier arrivé, premier servi)",
|
||||
"subscribeall": "S'abonner à tous les dossiers",
|
||||
"syncjob": "Ajouter une tâche de synchronisation",
|
||||
"syncjob_hint": "Sachez que les mots de passe seront sauvegardés en clair !",
|
||||
"syncjob_hint": "Sachez que les mots de passe seront enregistrés en clair !",
|
||||
"target_address": "Aller à l'adresse",
|
||||
"target_address_info": "<small>Adresse(s) de courriel complète(s) (séparées par des virgules).</small>",
|
||||
"target_domain": "Domaine cible",
|
||||
@@ -105,7 +105,7 @@
|
||||
"username": "Nom d'utilisateur",
|
||||
"validate": "Valider",
|
||||
"validation_success": "Validation réussie",
|
||||
"bcc_dest_format": "La destination Cci doit être une seule adresse e-mail valide.<br>Si vous avez besoin d'envoyer une copie à plusieurs adresses, créez un alias et utilisez-le ici.",
|
||||
"bcc_dest_format": "La destination Cci doit être une seule adresse de courriel valide.<br>Si vous avez besoin d'envoyer une copie à plusieurs adresses, créez un alias et utilisez-le ici.",
|
||||
"tags": "Etiquettes",
|
||||
"app_passwd_protocols": "Protocoles autorisés pour le mot de passe de l'application",
|
||||
"dry": "Simuler la synchronisation"
|
||||
@@ -194,7 +194,7 @@
|
||||
"generate": "générer",
|
||||
"guid": "GUID - Identifiant de l'instance",
|
||||
"guid_and_license": "GUID & Licence",
|
||||
"hash_remove_info": "La suppression d'un hachage ratelimit (s'il existe toujours) réinitialisera complètement son compteur.<br>\r\n Chaque hachage est indiqué par une couleur individuelle.",
|
||||
"hash_remove_info": "La suppression d'un hachage limite d'envoi (s'il existe toujours) réinitialisera complètement son compteur.<br>\n Chaque hachage est indiqué par une couleur individuelle.",
|
||||
"help_text": "Remplacer le texte d'aide sous le masque de connexion (HTML autorisé)",
|
||||
"host": "Hôte",
|
||||
"html": "HTML",
|
||||
@@ -203,7 +203,7 @@
|
||||
"in_use_by": "Utilisé par",
|
||||
"inactive": "Inactif",
|
||||
"include_exclude": "Inclure/Exclure",
|
||||
"include_exclude_info": "Par défaut - sans sélection - <b>toutes les boîtes</b> sont adressées",
|
||||
"include_exclude_info": "Par défaut - sans sélection - <b>toutes les boîte de réception</b> sont adressées",
|
||||
"includes": "Inclure ces destinataires",
|
||||
"last_applied": "Dernière application",
|
||||
"license_info": "Une licence n’est pas requise, mais contribue au développement.<br><a href=\"https://www.servercow.de/mailcow?lang=en#sal\" target=\"_blank\" alt=\"SAL order\">Enregistrer votre GUID ici</a> or <a href=\"https://www.servercow.de/mailcow?lang=en#support\" target=\"_blank\" alt=\"Support order\">acheter le support pour votre intallation Mailcow.</a>",
|
||||
@@ -222,7 +222,7 @@
|
||||
"no_record": "Aucun enregistrement",
|
||||
"oauth2_client_id": "Client ID",
|
||||
"oauth2_client_secret": "Secret client",
|
||||
"oauth2_info": "L'implémentation OAuth2 prend en charge le type d'autorisation \"Authorization Code\" et émet des jetons d'actualisation.<br>\nLe serveur émet également automatiquement de nouveaux jetons d'actualisation, après qu'un jeton d'actualisation a été utilisé.<br><br>\n→ La portée par défaut est <i>profile</i>. Seuls les utilisateurs d'une boîte peuvent être authentifiés par rapport à OAuth2. Si le paramètre scope est omis, il revient au <i>profile</i>.<br>\n→ Le paramètre <i>state</i> doit être envoyé par le client dans le cadre de la demande d'autorisation.<br><br>\nChemins d'accès aux requêtes vers l'API OAuth <br>\n<ul>\n <li>Point de terminaison d'autorisation : <code>/oauth/authorize</code></li>\n <li>Point de terminaison du jeton : <code>/oauth/token</code></li>\n <li>Page de ressource : <code>/oauth/profile</code></li>\n</ul>\nLa régénération du secret client ne fera pas expirer les codes d'autorisation existants, mais ils ne pourront pas renouveler leur jeton.<br><br>\nLa révocation des jetons clients entraînera la fin immédiate de toutes les sessions actives. Tous les clients doivent se ré-authentifier.",
|
||||
"oauth2_info": "L'implémentation OAuth2 prend en charge le type d'autorisation \"Authorization Code\" et émet des jetons d'actualisation.<br>\nLe serveur émet également automatiquement de nouveaux jetons d'actualisation, après qu'un jeton d'actualisation a été utilisé.<br><br>\n→ La portée par défaut est <i>profile</i>. Seuls les utilisateurs d'une boîte de réception peuvent être authentifiés par rapport à OAuth2. Si le paramètre scope est omis, il revient au <i>profile</i>.<br>\n→ Le paramètre <i>state</i> doit être envoyé par le client dans le cadre de la demande d'autorisation.<br><br>\nChemins d'accès aux requêtes vers l'API OAuth <br>\n<ul>\n <li>Point de terminaison d'autorisation : <code>/oauth/authorize</code></li>\n <li>Point de terminaison du jeton : <code>/oauth/token</code></li>\n <li>Page de ressource : <code>/oauth/profile</code></li>\n</ul>\nLa régénération du secret client ne fera pas expirer les codes d'autorisation existants, mais ils ne pourront pas renouveler leur jeton.<br><br>\nLa révocation des jetons clients entraînera la fin immédiate de toutes les sessions actives. Tous les clients doivent se ré-authentifier.",
|
||||
"oauth2_redirect_uri": "URI de redirection",
|
||||
"oauth2_renew_secret": "Générer un nouveau secret client",
|
||||
"oauth2_revoke_tokens": "Révoquer tous les jetons",
|
||||
@@ -237,24 +237,24 @@
|
||||
"quarantine_max_age": "Âge maximun en jour(s)<br><small>La valeur doit être égale ou supérieure à 1 jour.</small>",
|
||||
"quarantine_max_size": "Taille maximum en Mo (les éléments plus grands sont mis au rebut):<br><small>0 ne signifie <b>pas</b> illimité.</small>",
|
||||
"quarantine_max_score": "Ignorer la notification si le score de spam est au dessus de cette valeur :<br><small>Par défaut : 9999.0</small>",
|
||||
"quarantine_notification_html": "Modèle de courriel de notification:<br><small>Laisser vide pour restaurer le modèle par défaut.</small>",
|
||||
"quarantine_notification_sender": "Notification par e-mail de l’expéditeur",
|
||||
"quarantine_notification_html": "Modèle de courriel de notification :<br><small>Laisser vide pour restaurer le modèle par défaut.</small>",
|
||||
"quarantine_notification_sender": "Notification par courriel de l’expéditeur",
|
||||
"quarantine_notification_subject": "Objet du courriel de notification",
|
||||
"quarantine_redirect": "<b>Rediriger toutes les notifications</b> vers ce destinataire:<br><small>Laisser vide pour désactiver. <b>Courrier non signé et non coché. Doit être livré en interne seulement.</b></small>",
|
||||
"quarantine_release_format": "Format des éléments diffusés",
|
||||
"quarantine_release_format_att": "En pièce jointe",
|
||||
"quarantine_release_format_raw": "Original non modifié",
|
||||
"quarantine_retention_size": "Rétentions par boîte:<br><small>0 indique <b>inactive</b>.</small>",
|
||||
"quota_notification_html": "Modèle de courriel de notification:<br><small>Laisser vide pour restaurer le modèle par défaut.</small>",
|
||||
"quota_notification_sender": "Notification par e-mail de l’expéditeur",
|
||||
"quarantine_retention_size": "Rétentions par boîte de réception:<br><small>0 indique <b>inactive</b>.</small>",
|
||||
"quota_notification_html": "Modèle de courriel de notification :<br><small>Laisser vide pour restaurer le modèle par défaut.</small>",
|
||||
"quota_notification_sender": "Notification par courriel de l’expéditeur",
|
||||
"quota_notification_subject": "Objet du courriel de notification",
|
||||
"quota_notifications": "Notifications de quotas",
|
||||
"quota_notifications_info": "Les notications de quota sont envoyées aux utilisateurs une fois lors du passage à 80 % et une fois lors du passage à 95 % d’utilisation.",
|
||||
"quota_notifications_vars": "{{percent}} égale le quota actuel de l’utilisateur<br>{{username}} est le nom de la boîte",
|
||||
"quota_notifications_vars": "{{percent}} égale le quota actuel de l’utilisateur<br>{{username}} est le nom de la boîte de réception",
|
||||
"r_active": "Restrictions actives",
|
||||
"r_inactive": "Restrictions inactives",
|
||||
"r_info": "Les éléments grisés/désactivés sur la liste des restrictions actives ne sont pas considérés comme des restrictions valides pour Mailcow et ne peuvent pas être déplacés. Des restrictions inconnues seront établies par ordre d’apparition de toute façon. <br>Vous pouvez ajouter de nouveaux éléments dans le code <code>inc/vars.local.inc.php</code> pour pouvoir les basculer.",
|
||||
"rate_name": "Nom du taux",
|
||||
"rate_name": "Nom de la limite",
|
||||
"recipients": "Destinataires",
|
||||
"refresh": "Rafraîchir",
|
||||
"regen_api_key": "Regénérer la clé API",
|
||||
@@ -274,9 +274,9 @@
|
||||
"rsetting_no_selection": "Veuillez sélectionner une règle",
|
||||
"rsetting_none": "Pas de règles disponibles",
|
||||
"rsettings_insert_preset": "Insérer un exemple de préréglage \"%s\"",
|
||||
"rsettings_preset_1": "Désactiver tout sauf DKIM et la limite tarifaire pour les utilisateurs authentifiés",
|
||||
"rsettings_preset_1": "Désactiver tout sauf DKIM et la limite d'envoi pour les utilisateurs authentifiés",
|
||||
"rsettings_preset_2": "Les postmasters veulent du spam",
|
||||
"rsettings_preset_3": "Autoriser uniquement des expéditeurs particuliers pour une boîte (c.-à-d. utilisation comme boîte interne seulement)",
|
||||
"rsettings_preset_3": "Autoriser uniquement des expéditeurs particuliers pour une boîte de réception (c.-à-d. utilisation comme boîte de réception interne seulement)",
|
||||
"rspamd_com_settings": "Un nom de paramètre sera généré automatiquement, voir l’exemple de préréglages ci-dessous. Pour plus de détails voir : <a href=\"https://rspamd.com/doc/configuration/settings.html#settings-structure\" target=\"_blank\">Docs Rspamd</a>",
|
||||
"rspamd_global_filters": "Cartes des filtres globaux",
|
||||
"rspamd_global_filters_agree": "Je serai prudent !",
|
||||
@@ -312,7 +312,7 @@
|
||||
"ui_header_announcement_type_warning": "Important",
|
||||
"ui_header_announcement_type_danger": "Très important",
|
||||
"ui_texts": "Textes et étiquettes de l'interface utilisateur",
|
||||
"unban_pending": "unban en attente",
|
||||
"unban_pending": "Débanissement en attente",
|
||||
"unchanged_if_empty": "Si non modifié, laisser en blanc",
|
||||
"upload": "Charger",
|
||||
"username": "Nom d'utilisateur",
|
||||
@@ -338,7 +338,12 @@
|
||||
"oauth2_apps": "Applications OAuth2",
|
||||
"password_length": "Longueur des mots de passe",
|
||||
"password_policy_chars": "Doit contenir au moins une lettre",
|
||||
"password_policy_length": "La longueur minimale du mot de passe est de %d"
|
||||
"password_policy_length": "La longueur minimale du mot de passe est de %d",
|
||||
"f2b_manage_external_info": "Fail2ban maintiendra la liste de bannissement, mais ne définira pas activement de règles pour bloquer le trafic. Utilisez la liste de bannissement générée ci-dessous pour bloquer le trafic de manière externe.",
|
||||
"f2b_manage_external": "Gérer Fail2Ban en externe",
|
||||
"transport_test_rcpt_info": "• ; Utilisez null@hosted.mailcow.de pour tester le relais vers une destination étrangère.",
|
||||
"relay_rcpt": "Adresse \"À :\"",
|
||||
"is_mx_based": "Basé sur MX"
|
||||
},
|
||||
"danger": {
|
||||
"access_denied": "Accès refusé ou données de formulaire non valides",
|
||||
@@ -352,9 +357,9 @@
|
||||
"app_passwd_id_invalid": "Le mot de passe ID %s de l'application est non valide",
|
||||
"bcc_empty": "La destination BCC destination ne peut pas être vide",
|
||||
"bcc_exists": "Une carte de transport BCC %s existe pour le type %s",
|
||||
"bcc_must_be_email": "Le destination BCC %s n'est pas une adresse e-mail valide",
|
||||
"bcc_must_be_email": "La destination BCC %s n'est pas une adresse de courriel valide",
|
||||
"comment_too_long": "Le commentaire est trop long, 160 caractère max sont permis",
|
||||
"defquota_empty": "Le quota par défaut par boîte ne doit pas être 0.",
|
||||
"defquota_empty": "Le quota par défaut par boîte de réception doit pas être 0.",
|
||||
"description_invalid": "La description des ressources pour %s est non valide",
|
||||
"dkim_domain_or_sel_exists": "Une clé DKIM pour \"%s\" existe et ne sera pas écrasée",
|
||||
"dkim_domain_or_sel_invalid": "Domaine ou sélection DKIM non valide : %s",
|
||||
@@ -389,22 +394,22 @@
|
||||
"invalid_recipient_map_old": "Destinataire original spécifié non valide : %s",
|
||||
"ip_list_empty": "La liste des adresses IP autorisées ne peut pas être vide",
|
||||
"is_alias": "%s est déjà connu comme une adresse alias",
|
||||
"is_alias_or_mailbox": "%s est déjà connu comme un alias, une boîte ou une adresse alias développée à partir d’un domaine alias.",
|
||||
"is_alias_or_mailbox": "%s est déjà connu comme un alias, une boîte de réception ou une adresse alias développée à partir d’un domaine alias.",
|
||||
"is_spam_alias": "%s est déjà connu comme une adresse alias temporaire (alias d'adresse spam)",
|
||||
"last_key": "La dernière clé ne peut pas être supprimée, veuillez désactiver TFA à la place.",
|
||||
"login_failed": "La connexion a échoué",
|
||||
"mailbox_defquota_exceeds_mailbox_maxquota": "Le quota par défaut dépasse la limite maximale du quota",
|
||||
"mailbox_invalid": "Le nom de la boîte n'est pas valide",
|
||||
"mailbox_invalid": "Le nom de la boîte de réception n'est pas valide",
|
||||
"mailbox_quota_exceeded": "Le quota dépasse la limite du domaine (max. %d Mo)",
|
||||
"mailbox_quota_exceeds_domain_quota": "Le quota maximum dépasse la limite du quota de domaine",
|
||||
"mailbox_quota_exceeds_domain_quota": "Le quota maximal dépasse la limite du quota de domaine",
|
||||
"mailbox_quota_left_exceeded": "Espace libre insuffisant (espace libre : %d Mio)",
|
||||
"mailboxes_in_use": "Le max. des boîtes doit être supérieur ou égal à %d",
|
||||
"mailboxes_in_use": "Le max. des boîtes de réception doit être supérieur ou égal à %d",
|
||||
"malformed_username": "Nom d’utilisateur malformé",
|
||||
"map_content_empty": "Le contenu de la carte ne peut pas être vide",
|
||||
"max_alias_exceeded": "Le nombre max. d'aliases est dépassé",
|
||||
"max_mailbox_exceeded": "Le nombre max. de boîte est dépassé (%d of %d)",
|
||||
"max_quota_in_use": "Le quota de la boîte doit être supérieur ou égal à %d Mo",
|
||||
"maxquota_empty": "Le quota maximum par boîte ne doit pas être de 0.",
|
||||
"max_mailbox_exceeded": "Le nombre max. de boîte de réception est dépassé (%d of %d)",
|
||||
"max_quota_in_use": "Le quota de la boîte de réception doit être supérieur ou égal à %d Mo",
|
||||
"maxquota_empty": "Le quota maximum par boîte de réception ne doit pas être de 0.",
|
||||
"mysql_error": "Erreur MySQL : %s",
|
||||
"nginx_reload_failed": "Le rechargement de Nginx a échoué : %s",
|
||||
"network_host_invalid": "Réseau ou hôte non valide : %s",
|
||||
@@ -429,15 +434,15 @@
|
||||
"release_send_failed": "Le message n’a pas pu être diffusé : %s",
|
||||
"reset_f2b_regex": "Le filtre regex n'a pas pu être réinitialisé à temps, veuillez réessayer ou attendre quelques secondes de plus et recharger le site web.",
|
||||
"resource_invalid": "Le nom de la resource %s n'est pas valide",
|
||||
"rl_timeframe": "Le délai limite du taux est incorrect",
|
||||
"rspamd_ui_pw_length": "Le mot de passe de l'interface Rspamd doit être de 6 caratères au minimum",
|
||||
"rl_timeframe": "Le délai de la limite d'envoi est incorrect",
|
||||
"rspamd_ui_pw_length": "Le mot de passe de l'interface Rspamd doit être de 6 caractères au minimum",
|
||||
"script_empty": "Le script ne peut pas être vide",
|
||||
"sender_acl_invalid": "La valeur ACL de l’expéditeur %s est invalide",
|
||||
"set_acl_failed": "Impossible de définir ACL",
|
||||
"set_acl_failed": "Impossible de définir l'ACL",
|
||||
"settings_map_invalid": "La carte des paramètres %s est invalide",
|
||||
"sieve_error": "Erreur d'analyse syntaxique Sieve : %s",
|
||||
"spam_learn_error": "Erreur d'apprentissage du spam : %s",
|
||||
"subject_empty": "Le sujet ne peut^pas être vide",
|
||||
"subject_empty": "Le sujet ne peut pas être vide",
|
||||
"target_domain_invalid": "Le domaine cible %s n'est pas valide",
|
||||
"targetd_not_found": "Le domaine cible %s est introuvable",
|
||||
"targetd_relay_domain": "Le domaine cible %s est un domaine de relais",
|
||||
@@ -449,7 +454,7 @@
|
||||
"tls_policy_map_parameter_invalid": "Le paramètre Policy est invalide",
|
||||
"totp_verification_failed": "Echec de la vérification TOTP",
|
||||
"transport_dest_exists": "La destination de transport \"%s\" existe",
|
||||
"webauthn_verification_failed": "Echec de la vérification WebAuthn : %s",
|
||||
"webauthn_verification_failed": "Échec de la vérification WebAuthn : %s",
|
||||
"fido2_verification_failed": "La vérification FIDO2 a échoué : %s",
|
||||
"unknown": "Une erreur inconnue est survenue",
|
||||
"unknown_tfa_method": "Methode TFA inconnue",
|
||||
@@ -458,13 +463,18 @@
|
||||
"validity_missing": "Veuillez attribuer une période de validité",
|
||||
"value_missing": "Veuillez fournir toutes les valeurs",
|
||||
"yotp_verification_failed": "La vérification Yubico OTP a échoué : %s",
|
||||
"webauthn_authenticator_failed": "L'authentificateur selectionné est introuvable",
|
||||
"webauthn_authenticator_failed": "L'authentificateur sélectionné est introuvable",
|
||||
"demo_mode_enabled": "Le mode de démonstration est activé",
|
||||
"template_exists": "La template %s existe déja",
|
||||
"template_id_invalid": "Le numéro de template %s est invalide",
|
||||
"template_name_invalid": "Le nom de la template est invalide",
|
||||
"template_exists": "Le modèle %s existe déjà",
|
||||
"template_id_invalid": "Le numéro de modèle %s est invalide",
|
||||
"template_name_invalid": "Le nom du modèle est invalide",
|
||||
"img_dimensions_exceeded": "L'image dépasse les dimensions maximales",
|
||||
"img_size_exceeded": "L'image dépasse la taille maximale de fichier"
|
||||
"img_size_exceeded": "L'image dépasse la taille maximale de fichier",
|
||||
"webauthn_publickey_failed": "Aucune clé publique n'a été stockée pour l'authentificateur sélectionné.",
|
||||
"cors_invalid_method": "Allow-Method specifiée invalide",
|
||||
"cors_invalid_origin": "Allow-Origin spécifiée invalide",
|
||||
"extended_sender_acl_denied": "ACL manquante pour définir les adresses des expéditeurs externes",
|
||||
"webauthn_username_failed": "L'authentificateur sélectionné appartient à un autre compte"
|
||||
},
|
||||
"debug": {
|
||||
"chart_this_server": "Graphique (ce serveur)",
|
||||
@@ -474,7 +484,7 @@
|
||||
"history_all_servers": "Historique (tous les serveurs)",
|
||||
"in_memory_logs": "Logs En-mémoire",
|
||||
"jvm_memory_solr": "Utilisation mémoire JVM",
|
||||
"log_info": "<p>Les logs <b>En-mémoire</b> Mailcow sont collectés dans des listes Redis et découpées en LOG_LINES (%d) chaque minute pour réduire la charge.\r\n <br>Les logs En-mémoire ne sont pas destinés à être persistants. Toutes les applications qui se connectent en mémoire, se connectent également au démon Docker et donc au pilote de journalisation par défaut.\r\n <br>Le type de journal en mémoire doit être utilisé pour déboguer les problèmes mineurs avec les conteneurs.</p>\r\n <p><b>Les logs externes</b> sont collectés via l'API de l'application concernée.</p>\r\n <p>Les journaux <b>statiques</b> sont principalement des journaux d’activité, qui ne sont pas enregistrés dans Dockerd, mais qui doivent toujours être persistants (sauf pour les logs API).</p>",
|
||||
"log_info": "<p>Les logs <b>En-mémoire</b> Mailcow sont collectés dans des listes Redis et découpées en LOG_LINES (%d) chaque minute pour réduire la charge.\n <br>Les logs En-mémoire ne sont pas destinés à être persistants. Toutes les applications qui se connectent en mémoire, se connectent également au démon Docker, et donc au pilote de journalisation par défaut.\n <br>Le type de journal en mémoire doit être utilisé pour déboguer les problèmes mineurs avec les conteneurs.</p>\n <p><b>Les logs externes</b> sont collectés via l'API de l'application concernée.</p>\n <p>Les journaux <b>statiques</b> sont principalement des journaux d’activité, qui ne sont pas enregistrés dans Dockerd, mais qui doivent toujours être persistants (sauf pour les logs API).</p>",
|
||||
"logs": "Logs",
|
||||
"restart_container": "Redémarrer",
|
||||
"solr_dead": "Solr est en cours de démarrage, désactivé ou mort.",
|
||||
@@ -487,7 +497,13 @@
|
||||
"uptime": "Disponibilité",
|
||||
"started_on": "Démarré à",
|
||||
"static_logs": "Logs statiques",
|
||||
"system_containers": "Système & Conteneurs"
|
||||
"system_containers": "Système & Conteneurs",
|
||||
"timezone": "Fuseau horaire",
|
||||
"username": "Nom d'utilisateur",
|
||||
"wip": "En cours de réalisation",
|
||||
"architecture": "Architecture",
|
||||
"cores": "Cœurs",
|
||||
"current_time": "Heure du système"
|
||||
},
|
||||
"diagnostics": {
|
||||
"cname_from_a": "Valeur dérivée de l’enregistrement A/AAAA. Ceci est supporté tant que l’enregistrement indique la bonne ressource.",
|
||||
@@ -496,7 +512,7 @@
|
||||
"dns_records_docs": "Veuillez également consulter <a target=\"_blank\" href=\"https://docs.mailcow.email/getstarted/prerequisite-dns\">la documentation</a>.",
|
||||
"dns_records_data": "Données correcte",
|
||||
"dns_records_name": "Nom",
|
||||
"dns_records_status": "Etat courant",
|
||||
"dns_records_status": "État courant",
|
||||
"dns_records_type": "Type",
|
||||
"optional": "Cet enregistrement est optionel."
|
||||
},
|
||||
@@ -511,7 +527,7 @@
|
||||
"app_passwd": "Mot de passe de l'application",
|
||||
"automap": "Essayer d’automatiser les dossiers (\"Sent items\", \"Sent\" => \"Sent\" etc.)",
|
||||
"backup_mx_options": "Options Backup MX",
|
||||
"bcc_dest_format": "La destination BCC doit être une seule adresse e-mail valide.",
|
||||
"bcc_dest_format": "La destination BCC doit être une seule adresse de courriel valide.",
|
||||
"client_id": "ID client",
|
||||
"client_secret": "Secret client",
|
||||
"comment_info": "Un commentaire privé n’est pas visible pour l’utilisateur, tandis qu’un commentaire public est affiché comme infobulle lorsque vous le placez dans un aperçu des utilisateurs",
|
||||
@@ -527,7 +543,7 @@
|
||||
"domains": "Domaines",
|
||||
"dont_check_sender_acl": "Désactiver la vérification de l’expéditeur pour le domaine %s (+ alias de domaines)",
|
||||
"edit_alias_domain": "Édition des alias de domaine",
|
||||
"encryption": "Cryptage",
|
||||
"encryption": "Chiffrement",
|
||||
"exclude": "Exclure des objets (regex)",
|
||||
"extended_sender_acl": "Adresses de l’expéditeur externe",
|
||||
"extended_sender_acl_info": "Une clé de domaine DKIM doit être importée, si disponible.<br>\r\n N’oubliez pas d’ajouter ce serveur à l’enregistrement TXT SPF correspondant.<br>\r\n Chaque fois qu’un domaine ou un alias de domaine est ajouté à ce serveur, et qui chevauche une adresse externe, l’adresse externe est supprimée.<br>\r\n Utiliser @domain.tld pour permettre l'envoi comme *@domain.tld.",
|
||||
@@ -542,14 +558,14 @@
|
||||
"inactive": "Inactif",
|
||||
"kind": "Type",
|
||||
"last_modified": "Dernière modification",
|
||||
"mailbox": "Édition de la boîte mail",
|
||||
"mailbox_quota_def": "Quota par défaut de la boîte",
|
||||
"mailbox": "Édition de la boîte de réception",
|
||||
"mailbox_quota_def": "Quota par défaut de la boîte de réception",
|
||||
"max_aliases": "Nombre max. d'alias",
|
||||
"max_mailboxes": "Nombre max. de boîtes possibles",
|
||||
"max_quota": "Quota max. par boîte mail (Mo)",
|
||||
"max_mailboxes": "Nombre max. de boîte de réception possibles",
|
||||
"max_quota": "Quota max. par boîte de réception (Mo)",
|
||||
"maxage": "Âge maximal en jours des messages qui seront consultés à distance<br><small>(0 = ignorer la durée)</small>",
|
||||
"maxbytespersecond": "Octets max. par seconde <br><small>(0 = pas de limite)</small>",
|
||||
"mbox_rl_info": "Cette limite de taux est appliquée au nom de connexion SASL, elle correspond à toute adresse \"from\" utilisée par l’utilisateur connecté. Une limite tarifaire pour les boîtes remplace une limite tarifaire pour l’ensemble du domaine.",
|
||||
"mbox_rl_info": "Cette limite d'envoi est appliquée au nom de connexion SASL, elle correspond à toute adresse \"from\" utilisée par l’utilisateur connecté. Une limite d'envoi pour les boîtes de réception remplace une limite d'envoi pour l’ensemble du domaine.",
|
||||
"mins_interval": "Intervalle (min)",
|
||||
"multiple_bookings": "Réservations multiples",
|
||||
"nexthop": "Saut suivant",
|
||||
@@ -559,22 +575,22 @@
|
||||
"private_comment": "Commentaire privé",
|
||||
"public_comment": "Commentaire public",
|
||||
"pushover_evaluate_x_prio": "Acheminement du courrier hautement prioritaire [<code>X-Priority: 1</code>]",
|
||||
"pushover_info": "Les paramètres de notification push s’appliqueront à tout le courrier propre (non spam) livré à <b>%s</b> y compris les alias (partagés, non partagés, étiquetés).",
|
||||
"pushover_info": "Les paramètres de notification push s’appliqueront à tout le courrier propre (non-spam) livré à <b>%s</b> y compris les alias (partagés, non partagés, étiquetés).",
|
||||
"pushover_only_x_prio": "Ne tenir compte que du courrier hautement prioritaire [<code>X-Priority: 1</code>]",
|
||||
"pushover_sender_array": "Ne tenir compte que des adresses électroniques suivantes de l’expéditeur : <small>(séparées par des virgules)</small>",
|
||||
"pushover_sender_array": "Ne tenir compte que des adresses de courriel suivantes de l’expéditeur : <small>(séparées par des virgules)</small>",
|
||||
"pushover_sender_regex": "Tenir compte de l’expéditeur regex suivant",
|
||||
"pushover_text": "Texte de la notification",
|
||||
"pushover_title": "Titre de la notification",
|
||||
"pushover_vars": "Lorsque aucun filtre d’expéditeur n’est défini, tous les messages seront considérés.<br>Les filtres Regex ainsi que les vérifications exactes de l’expéditeur peuvent être définis individuellement et seront considérés de façon séquentielle. Ils ne dépendent pas les uns des autres.<br>Variables utilisables pour le texte et le titre (veuillez prendre note des politiques de protection des données)",
|
||||
"pushover_verify": "Vérifier les justificatifs",
|
||||
"pushover_verify": "Vérifier les informations d'identification",
|
||||
"quota_mb": "Quota (Mo)",
|
||||
"ratelimit": "Limite de taux",
|
||||
"redirect_uri": "Redirection/rappel URL",
|
||||
"ratelimit": "Limite d'envoi",
|
||||
"redirect_uri": "URL de redirection/callback",
|
||||
"relay_all": "Relayer tous les destinataires",
|
||||
"relay_all_info": "↪ Si vous <b>ne choissisez pas</b> de relayer tous les destinataires, vous devrez ajouter une boîte (\"aveugle\") pour chaque destinataire qui devrait être relayé.",
|
||||
"relay_all_info": "↪ Si vous <b>ne choisissez pas</b> de relayer tous les destinataires, vous devrez ajouter une boîte de réception (\"aveugle\") pour chaque destinataire qui devrait être relayé.",
|
||||
"relay_domain": "Relayer ce domaine",
|
||||
"relay_transport_info": "<div class=\"badge fs-6 bg-info\">Info</div> Vous pouvez définir des cartes de transport vers une destination personnalisée pour ce domaine. Si elle n’est pas configurée, une recherche MX sera effectuée.",
|
||||
"relay_unknown_only": "Relais des boîtes non existantes seulement. Les boîtes existantes seront livrées localement..",
|
||||
"relay_unknown_only": "Relais des boîtes de réception non existantes seulement. Les boîtes de réception existantes seront livrées localement.",
|
||||
"relayhost": "Transports dépendant de l’expéditeur",
|
||||
"remove": "Enlever",
|
||||
"resource": "Ressource",
|
||||
@@ -582,12 +598,12 @@
|
||||
"scope": "Portée",
|
||||
"sender_acl": "Permettre d’envoyer comme",
|
||||
"sender_acl_disabled": "<span class=\"badge fs-6 bg-danger\">Le contrôle de l’expéditeur est désactivé</span>",
|
||||
"sender_acl_info": "Si l’utilisateur de la boîte A est autorisé à envoyer en tant qu’utilisateur de la boîte B, l’adresse de l’expéditeur n’est pas automatiquement affichée comme sélectionnable du champ \"from\" dans SOGo.<br>\r\n L’utilisateur B de la boîte doit créer une délégation dans Sogo pour permettre à l’utilisateur A de la boîte de sélectionner son adresse comme expéditeur. Pour déléguer une boîte dans Sogo, utilisez le menu (trois points) à droite du nom de votre boîte dans le coin supérieur gauche dans la vue de courrier. Ce comportement ne s’applique pas aux adresses alias.",
|
||||
"sender_acl_info": "Si l’utilisateur de la boîte de réception A est autorisé à envoyer en tant qu’utilisateur de la boîte de réception B, l’adresse de l’expéditeur n’est pas automatiquement affichée comme sélectionnable du champ \"de\" dans SOGo.<br>\n L’utilisateur B de la boîte de réception doit créer une délégation dans Sogo pour permettre à l’utilisateur A de la boîte de réception de sélectionner son adresse comme expéditeur. Pour déléguer une boîte de réception dans Sogo, utilisez le menu (trois points) à droite du nom de votre boîte dans le coin supérieur gauche dans la vue de courrier. Ce comportement ne s’applique pas aux adresses alias.",
|
||||
"sieve_desc": "Description courte",
|
||||
"sieve_type": "Type de filtre",
|
||||
"skipcrossduplicates": "Ignorer les messages en double dans les dossiers (premier arrivé, premier servi)",
|
||||
"sogo_visible": "Alias visible dans SOGo",
|
||||
"sogo_visible_info": "Cette option affecte uniquement les objets qui peuvent être affichés dans SOGo (adresses alias partagées ou non partagées pointant vers au moins une boîte mail locale). Si caché, un alias n’apparaîtra pas comme expéditeur sélectionnable dans SOGo.",
|
||||
"sogo_visible_info": "Cette option affecte uniquement les objets qui peuvent être affichés dans SOGo (adresses alias partagées ou non partagées pointant vers au moins une boîte de réception locale). Si caché, un alias n’apparaîtra pas comme expéditeur sélectionnable dans SOGo.",
|
||||
"spam_alias": "Créer ou modifier des adresses alias limitées dans le temps",
|
||||
"spam_filter": "Filtre spam",
|
||||
"spam_policy": "Ajouter ou supprimer des éléments à la liste blanche/noire",
|
||||
@@ -601,9 +617,32 @@
|
||||
"title": "Éditer l'objet",
|
||||
"unchanged_if_empty": "Si non modifié, laisser en blanc",
|
||||
"username": "Nom d'utilisateur",
|
||||
"validate_save": "Valider et sauver",
|
||||
"validate_save": "Valider et enregistrer",
|
||||
"lookup_mx": "La destination est une expression régulière qui doit correspondre avec le nom du MX (<code>.*\\.google\\.com</code> pour acheminer tout le courrier destiné à un MX se terminant par google.com via ce saut)",
|
||||
"mailbox_relayhost_info": "S'applique uniquement à la boîte aux lettres et aux alias directs, remplace le relayhost du domaine."
|
||||
"mailbox_relayhost_info": "S'applique uniquement à la boîte de réception et aux alias directs, remplace le relayhost du domaine.",
|
||||
"acl": "ACL (Permission)",
|
||||
"footer_exclude": "Exclure du pied de page",
|
||||
"custom_attributes": "Attributs personnalisés",
|
||||
"domain_footer_info_vars": {
|
||||
"from_addr": "{= from_addr =} - Partie de l'enveloppe relative à l'adresse de provenance",
|
||||
"from_domain": "{= from_domain =} - Partie de l'enveloppe provenant du domaine",
|
||||
"custom": "{= foo =} - Si la boîte de réception possède l'attribut personnalisé \"foo\" avec la valeur \"bar\", elle renvoie \"bar\"",
|
||||
"auth_user": "{= auth_user =} - Nom d'utilisateur authentifié spécifié par un MTA",
|
||||
"from_user": "{= from_user =} -La partie utilisateur de l'enveloppe, par exemple, pour \"moo@mailcow.tld\", renvoie \"moo\"",
|
||||
"from_name": "{= from_name =} - À partir du nom de l'enveloppe, par exemple, pour \"Mailcow <moo@mailcow.tld> ;\" on obtient \"Mailcow\""
|
||||
},
|
||||
"domain_footer_skip_replies": "Ignorer le pied de page des courriels de réponse",
|
||||
"domain_footer": "Pied de page du domaine",
|
||||
"domain_footer_html": "Pied de page HTML",
|
||||
"domain_footer_info": "Les pieds de page du domaine sont ajoutés à tous les courriels sortants associés à une adresse au sein de ce domaine. <br> Les variables suivantes peuvent être utilisées pour le pied de page :",
|
||||
"domain_footer_plain": "Pied de page",
|
||||
"app_passwd_protocols": "Protocoles autorisés pour le mot de passe d'application",
|
||||
"created_on": "Créé le",
|
||||
"none_inherit": "Aucun / Héritage",
|
||||
"quota_warning_bcc": "Avertissement sur les quotas BCC",
|
||||
"quota_warning_bcc_info": "Les avertissements seront envoyés en copies séparées aux destinataires suivants. Le sujet sera précédé du nom d'utilisateur correspondant entre parenthèses, par exemple : <code>Avertissement sur les quotas (user@example.com)</code>.",
|
||||
"sogo_access_info": "L'authentification unique à partir de l'interface de messagerie reste opérationnelle. Ce paramètre n'affecte pas l'accès à tous les autres services et ne supprime ni ne modifie le profil SOGo existant d'un utilisateur.",
|
||||
"admin": "Modifier l'administrateur"
|
||||
},
|
||||
"footer": {
|
||||
"cancel": "Annuler",
|
||||
@@ -614,15 +653,16 @@
|
||||
"hibp_ok": "Aucune correspondance trouvée.",
|
||||
"loading": "Veuillez patienter…",
|
||||
"restart_container": "Redémarrer le conteneur",
|
||||
"restart_container_info": "<b>Important:</b> Un redémarrage en douceur peut prendre un certain temps, veuillez attendre qu’il soit terminé.",
|
||||
"restart_container_info": "<b>Important :</b> Un redémarrage en douceur peut prendre un certain temps, veuillez attendre qu’il soit terminé.",
|
||||
"restart_now": "Redémarrer maintenant",
|
||||
"restarting_container": "Redémarrage du conteneur, cela peut prendre un certain temps"
|
||||
"restarting_container": "Redémarrage du conteneur, cela peut prendre un certain temps",
|
||||
"nothing_selected": "Rien n'est sélectionné"
|
||||
},
|
||||
"header": {
|
||||
"administration": "Configuration & détails",
|
||||
"apps": "Applications",
|
||||
"debug": "Information Système",
|
||||
"email": "E-Mail",
|
||||
"email": "Courriel",
|
||||
"mailcow_config": "Configuration",
|
||||
"quarantine": "Quarantaine",
|
||||
"restart_netfilter": "Redémarrer Netfilter",
|
||||
@@ -638,7 +678,7 @@
|
||||
"delayed": "La connexion a été retardée de %s secondes.",
|
||||
"fido2_webauthn": "FIDO2/WebAuthn Login",
|
||||
"login": "Connexion",
|
||||
"mobileconfig_info": "Veuillez vous connecter en tant qu’utilisateur de la boîte pour télécharger le profil de connexion Apple demandé.",
|
||||
"mobileconfig_info": "Veuillez vous connecter en tant qu’utilisateur de la boîte de réception pour télécharger le profil de connexion Apple demandé.",
|
||||
"other_logins": "Clé d'authentification",
|
||||
"password": "Mot de passe",
|
||||
"username": "Nom d'utilisateur"
|
||||
@@ -646,7 +686,7 @@
|
||||
"mailbox": {
|
||||
"action": "Action",
|
||||
"activate": "Activer",
|
||||
"active": "Active",
|
||||
"active": "Actif",
|
||||
"add": "Ajouter",
|
||||
"add_alias": "Ajouter un alias",
|
||||
"add_bcc_entry": "Ajouter une carte BCC",
|
||||
@@ -654,19 +694,19 @@
|
||||
"add_domain_alias": "Ajouter un alias de domaine",
|
||||
"add_domain_record_first": "Veuillez d’abord ajouter un domaine",
|
||||
"add_filter": "Ajouter un filtre",
|
||||
"add_mailbox": "Ajouter une boîte",
|
||||
"add_mailbox": "Ajouter une boîte de réception",
|
||||
"add_recipient_map_entry": "Ajouter la carte du destinataire",
|
||||
"add_resource": "Ajouter une ressource",
|
||||
"add_tls_policy_map": "Ajouter la carte de la politique des TLS",
|
||||
"address_rewriting": "Réécriture de l’adresse",
|
||||
"alias": "Alias",
|
||||
"alias_domain_alias_hint": "Les alias <b>ne sont pas</b> appliqués automatiquement sur les alias de domaine. Un alias d'adresse <code>my-alias@domain</code> <b>ne couvre pas</b> l'adresse <code>my-alias@alias-domain</code> (où \"alias-domain\" est un alias imaginaire pour \"domain\").<br>Veuillez utiliser un filtre à tamis pour rediriger le courrier vers une boîte externe (voir l'onglet \"Filtres\" ou utilisez SOGo -> Forwarder).",
|
||||
"alias_domain_alias_hint": "Les alias <b>ne sont pas</b> appliqués automatiquement sur les alias de domaine. Un alias d'adresse <code>my-alias@domain</code> <b>ne couvre pas</b> l'adresse <code>my-alias@alias-domain</code> (où \"alias-domain\" est un alias imaginaire pour \"domain\").<br>Veuillez utiliser un filtre à tamis pour rediriger le courrier vers une boîte de réception externe (voir l'onglet « Filtres » ou utilisez SOGo → Transférer).",
|
||||
"alias_domain_backupmx": "Alias de domaine inactif pour le domaine relais",
|
||||
"aliases": "Aliases",
|
||||
"allow_from_smtp": "Restreindre l'utilisation de <b>SMTP</b> à ces adresses IP",
|
||||
"allow_from_smtp_info": "Laissez vide pour autoriser tous les expéditeurs.<br>Adresses IPv4/IPv6 et réseaux.",
|
||||
"allowed_protocols": "Protocoles autorisés",
|
||||
"backup_mx": "Sauvegarde MX",
|
||||
"backup_mx": "Domaine de relais",
|
||||
"bcc": "BCC",
|
||||
"bcc_destination": "Destination BCC",
|
||||
"bcc_destinations": "Destinations BCC",
|
||||
@@ -682,9 +722,9 @@
|
||||
"bcc_type": "Type de BCC",
|
||||
"booking_null": "Toujours montrer comme libre",
|
||||
"booking_0_short": "Toujours libre",
|
||||
"booking_custom": "Limite rigide à un nombre de réservations personnalisé",
|
||||
"booking_custom_short": "Limite rigide",
|
||||
"booking_ltnull": "Illimité, mais afficher aussi occupé lorsque réservé",
|
||||
"booking_custom": "Limitation stricte à un nombre personnalisé de réservations",
|
||||
"booking_custom_short": "Limite stricte",
|
||||
"booking_ltnull": "Illimité, mais indiqué comme occupé lors de la réservation",
|
||||
"booking_lt0_short": "Limite souple",
|
||||
"daily": "Quotidiennement",
|
||||
"deactivate": "Désactiver",
|
||||
@@ -700,32 +740,32 @@
|
||||
"domain_quota_total": "Quota total du domaine",
|
||||
"domains": "Domaines",
|
||||
"edit": "Éditer",
|
||||
"empty": "Pas de résulats",
|
||||
"empty": "Pas de résultats",
|
||||
"enable_x": "Activer",
|
||||
"excludes": "Exclut",
|
||||
"filter_table": "Table de filtre",
|
||||
"excludes": "Exclus",
|
||||
"filter_table": "Table de filtrage",
|
||||
"filters": "Filtres",
|
||||
"fname": "Nom complet",
|
||||
"force_pw_update": "Forcer la mise à jour du mot de passe à la prochaine ouverture de session",
|
||||
"gal": "Carnet d'Adresses Global (GAL)",
|
||||
"hourly": "Horaire",
|
||||
"hourly": "Toutes les heures",
|
||||
"in_use": "Utilisé (%)",
|
||||
"inactive": "Inactif",
|
||||
"insert_preset": "Insérer un exemple de préréglage \"%s\"",
|
||||
"kind": "Type",
|
||||
"last_mail_login": "Dernière connexion mail",
|
||||
"last_modified": "Dernière modification",
|
||||
"last_run": "Dernière éxécution",
|
||||
"last_run": "Dernière exécution",
|
||||
"last_run_reset": "Calendrier suivant",
|
||||
"mailbox": "Mailbox",
|
||||
"mailbox_defquota": "Taille de boîte par défaut",
|
||||
"mailbox_quota": "Taille max. d’une boîte",
|
||||
"mailboxes": "Boîtes mail",
|
||||
"mailbox": "Boîte de réception",
|
||||
"mailbox_defquota": "Taille de boîte de réception par défaut",
|
||||
"mailbox_quota": "Taille max. d’une boîte de réception",
|
||||
"mailboxes": "Boîtes de réception",
|
||||
"mailbox_defaults": "Paramètres par défaut",
|
||||
"mailbox_defaults_info": "Définir les paramètres par défaut pour les nouvelles boîtes aux lettres.",
|
||||
"mailbox_defaults_info": "Définir les paramètres par défaut pour les nouvelles boîtes de réception.",
|
||||
"max_aliases": "Nombre maximal d'alias",
|
||||
"max_mailboxes": "Nombre maximal de boîtes",
|
||||
"max_quota": "Quota max. par boîte mail",
|
||||
"max_mailboxes": "Nombre maximal de boîte de réception",
|
||||
"max_quota": "Quota max. par boîte de réception",
|
||||
"mins_interval": "Intervalle (min)",
|
||||
"msg_num": "Message #",
|
||||
"multiple_bookings": "Réservations multiples",
|
||||
@@ -736,18 +776,18 @@
|
||||
"owner": "Propriétaire",
|
||||
"private_comment": "Commentaire privé",
|
||||
"public_comment": "Commentaire public",
|
||||
"q_add_header": "Courriers indésirables",
|
||||
"q_all": " quand déplacé dans le dossier spam ou rejeté",
|
||||
"q_reject": "Rejecté",
|
||||
"q_add_header": "lorsqu'il est déplacé dans le dossier Indésirables",
|
||||
"q_all": " quand déplacé dans le dossier indésirables ou rejeté",
|
||||
"q_reject": "en cas de refus",
|
||||
"quarantine_notification": "Avis de quarantaine",
|
||||
"quarantine_category": "Catégorie de la notification de quarantaine",
|
||||
"quick_actions": "Actions",
|
||||
"recipient_map": "Carte du destinataire",
|
||||
"recipient_map_info": "Les cartes des destinataires sont utilisées pour remplacer l’adresse de destination d’un message avant sa livraison.",
|
||||
"recipient_map_new": "Nouveau destinataire",
|
||||
"recipient_map_new_info": "La destination de la carte du destinataire doit être une adresse électronique valide.",
|
||||
"recipient_map_new_info": "La destination de la carte du destinataire doit être une adresse de courriel valide.",
|
||||
"recipient_map_old": "Destinataire original",
|
||||
"recipient_map_old_info": "Une carte de destination originale doit être une adresse e-mail valide ou un nom de domaine.",
|
||||
"recipient_map_old_info": "Une carte de destination originale doit être une adresse de courriel valide ou un nom de domaine.",
|
||||
"recipient_maps": "Cartes des bénéficiaires",
|
||||
"relay_all": "Relayer tous les destinataires",
|
||||
"remove": "Supprimer",
|
||||
@@ -755,16 +795,16 @@
|
||||
"running": "En fonctionnement",
|
||||
"set_postfilter": "Marquer comme postfiltre",
|
||||
"set_prefilter": "Marquer comme préfiltre",
|
||||
"sieve_info": "Vous pouvez stocker plusieurs filtres par utilisateur, mais un seul préfiltre et un seul postfiltre peuvent être actifs en même temps.<br>\r\nChaque filtre sera traité dans l’ordre décrit. Ni un script \"rejeter\" ni un \"garder\" n’arrêtera le traitement des autres scripts. Les modifications apportées aux scripts de tamis globaux déclencheront un redémarrage de Dovecot.<br><br>Préfiltre de tamis global → Préfiltre → Scripts utilisateur → Postfiltre → Postfiltre du tamis global",
|
||||
"sieve_info": "Vous pouvez stocker plusieurs filtres par utilisateur, mais un seul préfiltre et un seul postfiltre peuvent être actifs simultanément.<br>\nChaque filtre sera traité dans l’ordre décrit. Ni un script « rejeter » ni un « garder » n’arrêtera le traitement des autres scripts. Les modifications apportées aux scripts de tamis globaux déclencheront un redémarrage de Dovecot.<br><br>Préfiltre de tamis global → Préfiltre → Scripts utilisateur → Postfiltre → Postfiltre du tamis global",
|
||||
"sieve_preset_1": "Jeter le courrier avec les types de fichiers dangereux probables",
|
||||
"sieve_preset_2": "Toujours marquer l’e-mail d’un expéditeur spécifique comme vu",
|
||||
"sieve_preset_3": "Jeter en silence, arrêter tout traitement supplémentaire du tamis",
|
||||
"sieve_preset_4": "Fichier dans INBOX, éviter le traitement ultérieur par filtres à tamis",
|
||||
"sieve_preset_2": "Toujours marquer l'adresse de courriel d’un expéditeur spécifique comme vu",
|
||||
"sieve_preset_3": "Jeter en silence, arrêter tout traitement supplémentaire par filtre sieve",
|
||||
"sieve_preset_4": "Fichier dans INBOX, éviter le traitement ultérieur par filtres sieve",
|
||||
"sieve_preset_5": "Répondeur auto (vacances)",
|
||||
"sieve_preset_6": "Rejeter le courrier avec réponse",
|
||||
"sieve_preset_7": "Rediriger et garder/déposer",
|
||||
"sieve_preset_8": "Supprimer le message envoyé à une adresse alias dont fait partie l’expéditeur",
|
||||
"sieve_preset_header": "Voir les exemples de préréglages ci-dessous. Pour plus de détails voir <a href=\"https://en.wikipedia.org/wiki/Sieve_(mail_filtering_language)\" target=\"_blank\">Wikipedia</a>.",
|
||||
"sieve_preset_8": "Rediriger les courriels d'un expéditeur spécifique, les marquer comme lus et les classer dans des sous-dossiers.",
|
||||
"sieve_preset_header": "Voir les exemples de préréglages ci-dessous. Pour plus de détails, voir <a href=\"https://en.wikipedia.org/wiki/Sieve_(mail_filtering_language)\" target=\"_blank\">Wikipédia</a>.",
|
||||
"sogo_visible": "Alias visible dans SOGo",
|
||||
"sogo_visible_n": "Masquer alias dans SOGo",
|
||||
"sogo_visible_y": "Afficher alias dans SOGo",
|
||||
@@ -785,19 +825,29 @@
|
||||
"tls_map_policy": "Politique",
|
||||
"tls_policy_maps": "Cartes des politiques des TLS",
|
||||
"tls_policy_maps_info": "Cette carte de politique remplace les règles de transport TLS sortantes indépendamment des paramètres de politique TLS des utilisateurs.<br>\r\n Veuillez vérifier <a href=\"http://www.postfix.org/postconf.5.html#smtp_tls_policy_maps\" target=\"_blank\">la doc \"smtp_tls_policy_maps\" </a> pour plus d'informations.",
|
||||
"tls_policy_maps_enforced_tls": "Ces politiques remplaceront également le comportement des utilisateurs de boîtes qui appliquent les connexions TLS sortantes. Si aucune politique n’existe ci-dessous, ces utilisateurs appliqueront les valeurs par défaut spécifiées comme <code>smtp_tls_mandatory_protocols</code> et <code>smtp_tls_mandatory_ciphers</code>.",
|
||||
"tls_policy_maps_enforced_tls": "Ces politiques remplaceront également le comportement des utilisateurs de boîtes de réception qui appliquent les connexions TLS sortantes. Si aucune politique n’existe ci-dessous, ces utilisateurs appliqueront les valeurs par défaut spécifiées comme <code>smtp_tls_mandatory_protocols</code> et <code>smtp_tls_mandatory_ciphers</code>.",
|
||||
"tls_policy_maps_long": "Contournement de la carte de politique TLS sortante",
|
||||
"toggle_all": "Tout basculer",
|
||||
"username": "Nom d'utilisateur",
|
||||
"waiting": "En attente",
|
||||
"weekly": "Hebdomadaire",
|
||||
"yes": "✓"
|
||||
"yes": "✓",
|
||||
"add_alias_expand": "Étendre l'alias aux alias de domaine",
|
||||
"catch_all": "Catch-All",
|
||||
"created_on": "Créé le",
|
||||
"goto_ham": "Apprendre comme <b>ham</b>",
|
||||
"goto_spam": "Apprendre comme <b>pourriel</b>",
|
||||
"last_pw_change": "Dernier changement de mot de passe",
|
||||
"mailbox_templates": "Modèle de boîte de réception",
|
||||
"relay_unknown": "Relayer les boîtes de réception inconnues",
|
||||
"all_domains": "Tous les domaines",
|
||||
"syncjob_EXIT_OVERQUOTA": "Quota dépassé de la boîte de réception cible"
|
||||
},
|
||||
"oauth2": {
|
||||
"access_denied": "Veuillez vous connecter en tant que propriétaire de la boîte pour accorder l’accès via Oauth2.",
|
||||
"access_denied": "Veuillez vous connecter en tant que propriétaire de la boîte de réception pour accorder l’accès via Oauth2.",
|
||||
"authorize_app": "Autoriser l'application",
|
||||
"deny": "Refuser",
|
||||
"permit": "Autorise l'application",
|
||||
"permit": "Autoriser l'application",
|
||||
"profile": "Profil",
|
||||
"profile_desc": "Afficher les informations personnelles : nom d’utilisateur, nom complet, créé, modifié, actif",
|
||||
"scope_ask_permission": "Une application demande les permissions suivantes"
|
||||
@@ -810,8 +860,8 @@
|
||||
"confirm_delete": "Confirmer la suppression de cet élément.",
|
||||
"danger": "Danger",
|
||||
"deliver_inbox": "Envoyer dans la boîte de reception",
|
||||
"disabled_by_config": "La configuration actuelle du système désactive la fonctionnalité de quarantaine. Veuillez définir \"retentions par boîte\" et une \"taille maximum\" pour les éléments en quarantaine.",
|
||||
"settings_info": "Quantité maximum d'éléments à mettre en quarantaine : %s<br>Taille maximale des e-mails : %s MiB",
|
||||
"disabled_by_config": "La configuration actuelle du système désactive la fonctionnalité de quarantaine. Veuillez définir « retentions par boîte » et une « taille maximale » pour les éléments en quarantaine.",
|
||||
"settings_info": "Quantité maximale d'éléments à mettre en quarantaine : %s<br>Taille maximale des courriels : %s MiB",
|
||||
"download_eml": "Télécharger (.eml)",
|
||||
"empty": "Pas de résultat",
|
||||
"high_danger": "Haut",
|
||||
@@ -824,7 +874,7 @@
|
||||
"notified": "Notifié",
|
||||
"qhandler_success": "Demande envoyée avec succès au système. Vous pouvez maintenant fermer la fenêtre.",
|
||||
"qid": "Rspamd QID",
|
||||
"qinfo": "Le système de quarantaine enregistrera le courrier rejeté dans la base de données (l'expéditeur n'aura <em> pas </em> l'impression d'un courrier remis) ainsi que le courrier, qui est remis sous forme de copie dans le dossier indésirable d'une boîte aux lettres.\r\n <br>\"Apprendre comme spam et supprimer\" apprendra un message comme spam via le théorème Bayesianet calculera également des hachages flous pour refuser des messages similaires à l'avenir.\r\n <br>Veuillez noter que l'apprentissage de plusieurs messages peut prendre du temps, selon votre système. <br> Les éléments figurant sur la liste noire sont exclus de la quarantaine.",
|
||||
"qinfo": "Le système de quarantaine enregistrera le courrier rejeté dans la base de données (l'expéditeur n'aura <em> pas </em> l'impression d'un courrier remis) ainsi que le courrier, remis sous forme de copie dans le dossier indésirable d'une boîte de réception.\n <br>« Apprendre comme spam et supprimer » apprendra un message comme spam via le théorème Bayésien calculera également des hachages flous pour refuser des messages similaires à l'avenir.\n <br>Veuillez noter que l'apprentissage de plusieurs messages peut prendre du temps, selon votre système. <br> Les éléments figurant sur la liste noire sont exclus de la quarantaine.",
|
||||
"qitem": "Élément de quarantaine",
|
||||
"quarantine": "Quarantaine",
|
||||
"quick_actions": "Actions",
|
||||
@@ -856,26 +906,34 @@
|
||||
"toggle_all": "Tout basculer"
|
||||
},
|
||||
"queue": {
|
||||
"queue_manager": "Gestion de la file d'attente"
|
||||
"queue_manager": "Gestion de la file d'attente",
|
||||
"hold_mail": "Garder",
|
||||
"legend": "Fonctions d'action de la file d'attente du courrier :",
|
||||
"info": "La file d'attente contient tous les courriels en attente de livraison. Si un courriel reste longtemps dans la file d'attente, il est automatiquement supprimé par le système.<br>Le message d'erreur du courriel concerné indique pourquoi le courriel n'a pas pu être distribué.",
|
||||
"deliver_mail_legend": "Tentatives de réexpédition des courriers sélectionnés.",
|
||||
"hold_mail_legend": "Met en attente les courriers sélectionnés. (Empêche les tentatives de distribution ultérieures)",
|
||||
"unban": "file d'attente d'unban",
|
||||
"unhold_mail": "Libérer",
|
||||
"unhold_mail_legend": "Libère les courriers sélectionnés pour la distribution. (Nécessite une mise en attente préalable)"
|
||||
},
|
||||
"start": {
|
||||
"help": "Afficher/masquer le panneau d’aide",
|
||||
"imap_smtp_server_auth_info": "Veuillez utiliser votre adresse e-mail complète et le mécanisme d’authentification PLAIN.<br>\r\nVos données de connexion seront cryptées par le cryptage obligatoire côté serveur.",
|
||||
"mailcow_apps_detail": "Utiliser une application mailcow pour accéder à vos messages, calendrier, contacts et plus.",
|
||||
"mailcow_panel_detail": "<b>Les administrateurs de domaines</b> peuvent créer, modifier or supprimer des boîtes et alias, changer de domaines et lire de plus amples renseignements sur les domaines qui leurs sont attribués.<br>\r\n<b>Les utilisateurs de boîtes</b> sont en mesure de créer des alias limités dans le temps (alias spam), de modifier leurs mots de passe et les paramètres du filtre anti-spam."
|
||||
"imap_smtp_server_auth_info": "Veuillez utiliser votre adresse courriel complète et le mécanisme d’authentification PLAIN.<br>\nVos données de connexion seront cryptées par le cryptage obligatoire côté serveur.",
|
||||
"mailcow_apps_detail": "Utiliser une application mailcow pour accéder à vos messages, vos calendriers, vos contacts et plus.",
|
||||
"mailcow_panel_detail": "<b>Les administrateurs de domaines</b> peuvent créer, modifier, ou supprimer des boîtes de réception et alias, changer de domaines et lire de plus amples renseignements sur les domaines qui leur sont attribués.<br>\n<b>Les utilisateurs de boîtes de réception</b> sont en mesure de créer des alias limités dans le temps (alias spam), de modifier leurs mots de passe et les paramètres du filtre anti-spam."
|
||||
},
|
||||
"success": {
|
||||
"acl_saved": "ACL (Access Control List) pour l'objet %s sauvé",
|
||||
"admin_added": "Administrateur %s a été ajoutées",
|
||||
"acl_saved": "ACL (Access Control List) pour l'objet %s enregistré",
|
||||
"admin_added": "Administrateur %s a été ajouté",
|
||||
"admin_api_modified": "Les modifications apportées à l’API ont été enregistrées",
|
||||
"admin_modified": "Les modifications apportées à l’administrateur ont été enregistrées",
|
||||
"admin_removed": "Administrateur %s a été effacé",
|
||||
"alias_added": "L'adresse alias %s (%d) a été ajoutée",
|
||||
"alias_domain_removed": "L'alias de domaine %s a été effacé",
|
||||
"alias_modified": "Le changement de l'adresse alias %s a été sauvegardée",
|
||||
"alias_modified": "Le changement de l'adresse alias %s a été enregistré",
|
||||
"alias_removed": "L'alias %s a été effacé",
|
||||
"aliasd_added": "Alias de domaine %s ajouté",
|
||||
"aliasd_modified": "Les changements de l'alias de domaine %s ont été sauvegardés",
|
||||
"aliasd_modified": "Les changements de l'alias de domaine %s ont été enregistrés",
|
||||
"app_links": "Modifications enregistrées dans les liens d’application",
|
||||
"app_passwd_added": "Ajout d’un nouveau mot de passe d’application",
|
||||
"app_passwd_removed": "Suppression de l’identifiant du mot de passe de l’application %s",
|
||||
@@ -887,14 +945,14 @@
|
||||
"delete_filters": "Filtres supprimés : %s",
|
||||
"deleted_syncjob": "ID du travail de synchronisation supprimé : %s",
|
||||
"deleted_syncjobs": "Travail de synchronisation supprimé : %s",
|
||||
"dkim_added": "La clé DKIM %s a été sauvegardée",
|
||||
"dkim_duplicated": "La clé DKIM pour e domaine %s a été copiée vers %s",
|
||||
"dkim_added": "La clé DKIM %s a été enregistrée",
|
||||
"dkim_duplicated": "La clé DKIM pour le domaine %s a été copiée vers %s",
|
||||
"dkim_removed": "La clé DKIM %s a été supprimée",
|
||||
"domain_added": "Domaine ajouté %s",
|
||||
"domain_admin_added": "L'administrateur de domaine %s a été ajouté",
|
||||
"domain_admin_modified": "Les modifications de l'administrateur de domaine %s ont été sauvées",
|
||||
"domain_admin_modified": "Les modifications de l'administrateur de domaine %s ont été enregistrées",
|
||||
"domain_admin_removed": "L'administrateur de domaine %s a été supprimé",
|
||||
"domain_modified": "Les modification du domaine %s ont été sauvées",
|
||||
"domain_modified": "Les modifications du domaine %s ont été enregistrées",
|
||||
"domain_removed": "Le domaine %s a été supprimé",
|
||||
"dovecot_restart_success": "Dovecot a été relancé avec succès",
|
||||
"eas_reset": "Les périphériques Activesync pour l’utilisateur %s ont été réinitialisés",
|
||||
@@ -910,40 +968,47 @@
|
||||
"learned_ham": "ID %s acquis avec succès comme ham",
|
||||
"license_modified": "Les modifications apportées à la licence ont été enregistrées",
|
||||
"logged_in_as": "Connecté en tant que %s",
|
||||
"mailbox_added": "La boîte mail %s a été ajoutée",
|
||||
"mailbox_modified": "Les modifications de la boîte %s ont été sauvées",
|
||||
"mailbox_removed": "La boîte %s a été supprimée",
|
||||
"mailbox_added": "La boîte de réception %s a été ajoutée",
|
||||
"mailbox_modified": "Les modifications de la boîte de réception %s ont été enregistrées",
|
||||
"mailbox_removed": "La boîte de réception %s a été supprimée",
|
||||
"nginx_reloaded": "Nginx a été rechargé",
|
||||
"object_modified": "Les changements de %s ont été sauvés",
|
||||
"object_modified": "Les changements de %s ont été enregistrés",
|
||||
"pushover_settings_edited": "Paramètres Pushover réglés avec succès, veuillez vérifier les informations d’identification.",
|
||||
"qlearn_spam": "Le message ID %s a été appris comme spam et supprimé",
|
||||
"queue_command_success": "Queue de commande terminée avec succès",
|
||||
"recipient_map_entry_deleted": "La carte du destinataire ID %s a été effacée",
|
||||
"recipient_map_entry_saved": "L'entrée de la carte du bénéficiaire \"%s\" a été sauvée",
|
||||
"recipient_map_entry_saved": "L'entrée de la carte du bénéficiaire \"%s\" a été enregistrée",
|
||||
"relayhost_added": "L'entrée de la carte %s a été ajoutée",
|
||||
"relayhost_removed": "L'entrée de la carte %s a été supprimée",
|
||||
"reset_main_logo": "Réinitialisation du logo par défaut",
|
||||
"resource_added": "La ressource %s a été ajoutée",
|
||||
"resource_modified": "Les modifications apportées à la boîte %s ont été enregistrées",
|
||||
"resource_modified": "Les modifications apportées à la boîte de réception %s ont été enregistrées",
|
||||
"resource_removed": "La ressource %s a été supprimée",
|
||||
"rl_saved": "Limite de taux pour l’objet %s enregistrée",
|
||||
"rl_saved": "Limite d'envoi pour l’objet %s enregistrée",
|
||||
"rspamd_ui_pw_set": "Mot de passe de l'interface Rspamd sauvegardé avec succès",
|
||||
"saved_settings": "Paramètres enregistrés",
|
||||
"settings_map_added": "Ajout de l’entrée de la carte des paramètres",
|
||||
"settings_map_removed": "Suppression de la carte des paramètres ID %s",
|
||||
"sogo_profile_reset": "Le profil SOGo profile pour l'utilisateur %s est remis à zéro",
|
||||
"tls_policy_map_entry_deleted": "La carte de stratégie TLS ID %s a été supprimé",
|
||||
"tls_policy_map_entry_saved": "La carte de stratégie TLS ID \"%s\" a été sauvée",
|
||||
"tls_policy_map_entry_deleted": "La carte de stratégie TLS ID %s a été supprimée",
|
||||
"tls_policy_map_entry_saved": "La carte de stratégie TLS ID \"%s\" a été enregistrée",
|
||||
"ui_texts": "Enregistrement des modifications apportées aux textes de l’interface utilisateur",
|
||||
"upload_success": "Fichier téléchargé avec succès",
|
||||
"verified_totp_login": "Authentification TOTP vérifiée",
|
||||
"verified_webauthn_login": "Authentification WebAuthn vérifiée",
|
||||
"verified_fido2_login": "Authentification FIDO2 vérifiée",
|
||||
"verified_yotp_login": "Authentification Yubico OTP vérifiée"
|
||||
"verified_yotp_login": "Authentification Yubico OTP vérifiée",
|
||||
"cors_headers_edited": "Les paramètres CORS ont été enregistrés",
|
||||
"domain_footer_modified": "Les modifications apportées au pied de page du domaine %s ont été enregistrées",
|
||||
"f2b_banlist_refreshed": "L'ID de la liste de ban a été actualisé avec succès.",
|
||||
"template_added": "Modèles ajoutés %s",
|
||||
"template_removed": "Le modèle ayant l'ID %s a été supprimé",
|
||||
"domain_add_dkim_available": "A DKIM key did already exist",
|
||||
"ip_check_opt_in_modified": "Le contrôle de l'IP a été enregistré avec succès"
|
||||
},
|
||||
"tfa": {
|
||||
"api_register": "%s utilise l'API Yubico Cloud. Veuillez obtenir une clé API pour votre clé <a href=\"https://upgrade.yubico.com/getapikey/\" target=\"_blank\">here</a>",
|
||||
"confirm": "confirmer",
|
||||
"api_register": "%s utilise l'API Yubico Cloud. Veuillez obtenir une clé API pour votre clé <a href=\"https://upgrade.yubico.com/getapikey/\" target=\"_blank\">ici</a>",
|
||||
"confirm": "Confirmer",
|
||||
"confirm_totp_token": "Veuillez confirmer vos modifications en saisissant le jeton généré",
|
||||
"delete_tfa": "Désactiver TFA",
|
||||
"disable_tfa": "Désactiver TFA jusqu’à la prochaine ouverture de session réussie",
|
||||
@@ -964,21 +1029,25 @@
|
||||
"webauthn": "Authentification WebAuthn",
|
||||
"waiting_usb_auth": "<i>En attente d’un périphérique USB…</i><br><br>S’il vous plaît appuyez maintenant sur le bouton de votre périphérique USB WebAuthn.",
|
||||
"waiting_usb_register": "<i>En attente d’un périphérique USB…</i><br><br>Veuillez entrer votre mot de passe ci-dessus et confirmer votre inscription WebAuthn en appuyant sur le bouton de votre périphérique USB WebAuthn.",
|
||||
"yubi_otp": "Authentification OTP Yubico"
|
||||
"yubi_otp": "Authentification OTP Yubico",
|
||||
"authenticators": "Authentificateurs",
|
||||
"u2f_deprecated_important": "Veuillez enregistrer votre clé dans le panneau d'administration avec la nouvelle méthode WebAuthn.",
|
||||
"u2f_deprecated": "Il semble que votre clé ait été enregistrée à l'aide de la méthode U2F obsolète. Nous allons désactiver l'authentification à deux facteurs pour vous et supprimer votre clé."
|
||||
},
|
||||
"fido2": {
|
||||
"set_fn": "Définir un nom",
|
||||
"fn": "Nom",
|
||||
"rename": "renommer",
|
||||
"rename": "Renommer",
|
||||
"confirm": "Confirmer",
|
||||
"register_status": "Etat de l'enregistrement",
|
||||
"register_status": "État de l'enregistrement",
|
||||
"known_ids": "Identifiant(s) connu(s)",
|
||||
"none": "Désactivé",
|
||||
"set_fido2": "Enregistrer un nouvel appareil FIDO2",
|
||||
"start_fido2_validation": "Tester la validation FIDO2",
|
||||
"fido2_auth": "Se connecter avec FIDO2",
|
||||
"fido2_success": "L'appareil est enregistré avec succès",
|
||||
"fido2_validation_failed": "La validation a échoué"
|
||||
"fido2_validation_failed": "La validation a échoué",
|
||||
"set_fido2_touchid": "Enregistrer Touch ID sur Apple M1"
|
||||
},
|
||||
"user": {
|
||||
"action": "Action",
|
||||
@@ -995,9 +1064,9 @@
|
||||
"alias_valid_until": "Valide jusque",
|
||||
"aliases_also_send_as": "Aussi autorisé à envoyer en tant qu’utilisateur",
|
||||
"aliases_send_as_all": "Ne pas vérifier l’accès de l’expéditeur pour les domaines suivants et leurs alias",
|
||||
"app_hint": "Les mots de passe d’application sont des mots de passe alternatifs pour votre connexion IMAP, SMTP, Caldav, Carddav et EAS. Le nom d’utilisateur reste inchangé.<br>SOGo n'est pas disponible au travers de mots de passe.",
|
||||
"app_hint": "Les mots de passe d’application sont des mots de passe alternatifs pour votre connexion IMAP, SMTP, Caldav, Carddav et EAS. Le nom d’utilisateur reste inchangé.<br>SOGo n'est pas disponible au travers des mots de passe d'application.",
|
||||
"app_name": "Nom d'application",
|
||||
"app_passwds": "Mots de passe de l'application",
|
||||
"app_passwds": "Mots de passe d'applications",
|
||||
"apple_connection_profile": "Profil de connexion Apple",
|
||||
"apple_connection_profile_complete": "Ce profil de connexion inclut les paramètres IMAP et SMTP ainsi que les chemins Caldav (calendriers) et Carddav (contacts) pour un appareil Apple.",
|
||||
"apple_connection_profile_mailonly": "Ce profil de connexion inclut les paramètres de configuration IMAP et SMTP pour un périphérique Apple.",
|
||||
@@ -1010,14 +1079,14 @@
|
||||
"delete_ays": "Veuillez confirmer le processus de suppression.",
|
||||
"direct_aliases": "Adresses alias directes",
|
||||
"direct_aliases_desc": "Les adresses d’alias directes sont affectées par le filtre anti-spam et les paramètres de politique TLS.",
|
||||
"eas_reset": "Réinitialiser le cache de l’appareil Activesync",
|
||||
"eas_reset_help": "Dans de nombreux cas, une réinitialisation du cache de l’appareil aidera à récupérer un profil Activesync cassé.<br><b>Attention :</b> Tous les éléments seront à nouveau téléchargés !",
|
||||
"eas_reset": "Réinitialiser le cache de l’appareil ActiveSync",
|
||||
"eas_reset_help": "Dans de nombreux cas, une réinitialisation du cache de l’appareil aidera à récupérer un profil ActiveSync cassé.<br><b>Attention :</b> Tous les éléments seront de nouveau téléchargés !",
|
||||
"eas_reset_now": "Réinitialiser maintenant",
|
||||
"edit": "Éditer",
|
||||
"email": "E-mail",
|
||||
"email_and_dav": "E-mail, calendriers et contacts",
|
||||
"encryption": "Cryptage",
|
||||
"excludes": "Exclut",
|
||||
"email": "Courriel",
|
||||
"email_and_dav": "Courriel, calendriers et contacts",
|
||||
"encryption": "Chiffrement",
|
||||
"excludes": "Exclus",
|
||||
"expire_in": "Expire dans",
|
||||
"force_pw_update": "Vous <b>devez</b> définir un nouveau mot de passe pour pouvoir accéder aux services liés aux logiciels de groupe.",
|
||||
"generate": "générer",
|
||||
@@ -1030,7 +1099,7 @@
|
||||
"last_mail_login": "Dernière connexion mail",
|
||||
"last_run": "Dernière exécution",
|
||||
"loading": "Chargement…",
|
||||
"mailbox_details": "Détails de la boîte",
|
||||
"mailbox_details": "Détails",
|
||||
"messages": "messages",
|
||||
"never": "jamais",
|
||||
"new_password": "Nouveau mot de passe",
|
||||
@@ -1044,27 +1113,27 @@
|
||||
"pushover_evaluate_x_prio": "Acheminement du courrier hautement prioritaire [<code>X-Priority: 1</code>]",
|
||||
"pushover_info": "Les paramètres de notification push s’appliqueront à tout le courrier propre (non spam) livré à <b>%s</b> y compris les alias (partagés, non partagés, étiquetés).",
|
||||
"pushover_only_x_prio": "Ne tenir compte que du courrier hautement prioritaire [<code>X-Priority: 1</code>]",
|
||||
"pushover_sender_array": "Tenez compte des adresses courriel suivantes de l’expéditeur : <small>(comma-separated)</small>",
|
||||
"pushover_sender_array": "Tenir compte des adresses de courriel suivantes de l’expéditeur : <small>(comma-separated)</small>",
|
||||
"pushover_sender_regex": "Apparier les expéditeurs par le regex suivant",
|
||||
"pushover_text": "Texte de notification",
|
||||
"pushover_title": "Titre de la notification",
|
||||
"pushover_vars": "Lorsqu’aucun filtre d’expéditeur n’est défini, tous les messages seront considérés.<br>Les filtres Regex ainsi que les vérifications exactes de l’expéditeur peuvent être définis individuellement et seront considérés de façon séquentielle. Ils ne dépendent pas les uns des autres.<br>Variables utilisables pour le texte et le titre (veuillez prendre note des politiques de protection des données)",
|
||||
"pushover_verify": "Vérifier les justificatifs",
|
||||
"pushover_vars": "Lorsque aucun filtre d’expéditeur n’est défini, tous les messages seront considérés.<br>Les filtres Regex ainsi que les vérifications exactes de l’expéditeur peuvent être définis individuellement et seront considérés de façon séquentielle. Ils ne dépendent pas les uns des autres.<br>Variables utilisables pour le texte et le titre (veuillez prendre note des politiques de protection des données)",
|
||||
"pushover_verify": "Vérifier les identifiants",
|
||||
"q_add_header": "Courrier indésirable",
|
||||
"q_all": "Toutes les catégories",
|
||||
"q_reject": "Rejeté",
|
||||
"quarantine_notification": "Avis de quarantaine",
|
||||
"quarantine_category": "Catégorie de la notification de quarantaine",
|
||||
"quarantine_notification_info": "Une fois qu’un avis a été envoyé, les articles seront marqués comme \"notified\" et aucune autre notification ne sera envoyée pour ce point particulier.",
|
||||
"quarantine_category_info": "La catégorie de notification \"Rejeté\" inclut le courrier qui a été rejeté, tandis que \"Dossier indésirable\" informera un utilisateur des e-mails qui ont été placés dans le dossier indésirable.",
|
||||
"quarantine_notification_info": "Une fois qu’un avis a été envoyé, les articles seront marqués comme « notifiés » et aucune autre notification ne sera envoyée pour ce point particulier.",
|
||||
"quarantine_category_info": "La catégorie de notification « Rejeté » inclut le courrier rejeté, tandis que « Dossier indésirable » informera un utilisateur des courriels placés dans le dossier indésirable.",
|
||||
"remove": "Enlever",
|
||||
"running": "En fonction",
|
||||
"save": "Sauvegarder les changements",
|
||||
"save_changes": "Sauvegarder les changements",
|
||||
"running": "En fonctionnement",
|
||||
"save": "Enregistrer les changements",
|
||||
"save_changes": "Enregistrer les changements",
|
||||
"sender_acl_disabled": "<span class=\"badge fs-6 bg-danger\">Le contrôle de l’expéditeur est désactivé</span>",
|
||||
"shared_aliases": "Adresses alias partagées",
|
||||
"shared_aliases_desc": "Les alias partagés ne sont pas affectés par les paramètres spécifiques à l’utilisateur tels que le filtre anti-spam ou la politique de chiffrement. Les filtres anti-spam correspondants ne peuvent être effectués que par un administrateur en tant que politique de domaine.",
|
||||
"show_sieve_filters": "Afficher le filtre de tamis actif de l’utilisateur",
|
||||
"show_sieve_filters": "Afficher le filtre sieve actif de l’utilisateur",
|
||||
"sogo_profile_reset": "Remise à zéro du profil SOGo",
|
||||
"sogo_profile_reset_help": "Ceci détruira un profil Sogo des utilisateurs et <b>supprimera toutes les données de contact et de calendrier irrécupérables</b>.",
|
||||
"sogo_profile_reset_now": "Remise à zéro du profil maintenant",
|
||||
@@ -1073,10 +1142,10 @@
|
||||
"spamfilter": "Filtre de spam",
|
||||
"spamfilter_behavior": "Note",
|
||||
"spamfilter_bl": "Liste noire (BlackList)",
|
||||
"spamfilter_bl_desc": "Les adresses de courriel sur la liste noire de <b>always (toujours)</b> peuvent être classées comme des pourriels et rejetées. Des caractères génériques peuvent être utilisés. Un filtre n’est appliqué qu’aux alias directs (alias avec une seule boîte cible), à l’exclusion des alias tous azimuts et d’une boîte elle-même.",
|
||||
"spamfilter_bl_desc": "Les adresses de courriel sur la liste noire de <b>toujours</b> peuvent être classées comme des pourriels et rejetées. Des caractères génériques peuvent être utilisés. Un filtre n’est appliqué qu’aux alias directs (alias avec une seule boîte de réception cible), à l’exclusion des alias tous azimuts et d’une boîte de réception elle-même.",
|
||||
"spamfilter_default_score": "Valeurs par défaut",
|
||||
"spamfilter_green": "Vert : ce message n'est pas un spam",
|
||||
"spamfilter_hint": "La première valeur indique un \"faible score de spam\", la seconde représente un \"haut score de spam\".",
|
||||
"spamfilter_hint": "La première valeur indique un « faible score de spam », la seconde représente un « haut score de spam ».",
|
||||
"spamfilter_red": "Rouge : Ce message est un spam et sera rejeté par le serveur",
|
||||
"spamfilter_table_action": "Action",
|
||||
"spamfilter_table_add": "Ajouter un élément",
|
||||
@@ -1085,12 +1154,12 @@
|
||||
"spamfilter_table_remove": "supprimer",
|
||||
"spamfilter_table_rule": "Règle",
|
||||
"spamfilter_wl": "Liste blanche (WhiteList)",
|
||||
"spamfilter_wl_desc": "La liste blanche est programmé pour <b> ne jamais</b> classer comme spam les adresses e-mail qu'elle contient. Des caractères génériques peuvent être utilisés. Un filtre n’est appliqué qu’aux alias directs (alias avec une seule boîte cible), à l’exclusion des alias catch-all et d’une boîte mail.",
|
||||
"spamfilter_wl_desc": "La liste blanche est programmée pour <b> ne jamais</b> classer comme spam les adresses de courriel qu'elle contient. Des caractères génériques peuvent être utilisés. Un filtre n’est appliqué qu’aux alias directs (alias avec une seule boîte de réception cible), à l’exclusion des alias catch-all et d’une boîte de réception.",
|
||||
"spamfilter_yellow": "Jaune : ce message est peut être un spam, il sera étiqueté comme spam et déplacé vers votre dossier Pourriel",
|
||||
"status": "Statut",
|
||||
"sync_jobs": "Jobs de synchronisation",
|
||||
"tag_handling": "Régler la manipulation du courrier étiqueté",
|
||||
"tag_help_example": "Exemple pour une adresse e-mail étiquetée : me<b>+Facebook</b>@example.org",
|
||||
"tag_help_example": "Exemple pour une adresse de courriel étiquetée : me<b>+Facebook</b>@example.org",
|
||||
"tag_help_explain": "Dans un sous-dossier : un nouveau sous-dossier nommé selon l'étiquette sera créé sous INBOX (\"INBOX/Facebook\").<br>\nDans le sujet : le nom des balises sera ajouté au début du sujet de l'e-mail, exemple : \"[Facebook] My News\".",
|
||||
"tag_in_none": "Ne rien faire",
|
||||
"tag_in_subfolder": "Dans un sous dossier",
|
||||
@@ -1100,7 +1169,7 @@
|
||||
"tls_enforce_in": "Appliquer le TLS entrant",
|
||||
"tls_enforce_out": "Appliquer le TLS sortant",
|
||||
"tls_policy": "Politique de chiffrement",
|
||||
"tls_policy_warning": "<strong>Attention:</strong> Si vous décidez d’appliquer le transfert de courrier chiffré, vous risquez de perdre des courriels.<br>Les messages qui ne satisfont pas à la politique seront renvoyés avec une erreur grave par le système de messagerie.<br>Cette option s’applique à votre adresse courriel principale (login name), toutes les adresses dérivées de domaines alias ainsi que les adresses alias <b>avec cette seule boîte</b> comme cible.",
|
||||
"tls_policy_warning": "<strong>Attention :</strong> Si vous décidez d’appliquer le transfert de courrier chiffré, vous risquez de perdre des courriels.<br>Les messages qui ne satisfont pas à la politique seront renvoyés avec une erreur grave par le système de messagerie.<br>Cette option s’applique à votre adresse courriel principale (login name), toutes les adresses dérivées de domaines alias ainsi que les adresses alias <b>avec cette seule boîte de réception</b> comme cible.",
|
||||
"user_settings": "Paramètres utilisateur",
|
||||
"username": "Nom d'utilisateur",
|
||||
"verify": "Vérification",
|
||||
@@ -1111,7 +1180,29 @@
|
||||
"months": "mois",
|
||||
"year": "année",
|
||||
"years": "années",
|
||||
"with_app_password": "avec le mot de passe de l'application"
|
||||
"with_app_password": "avec le mot de passe de l'application",
|
||||
"apple_connection_profile_with_app_password": "Un nouveau mot de passe est généré et ajouté au profil, de sorte qu'aucun mot de passe ne doit être saisi lors de la configuration de votre appareil. Ne partagez pas le fichier car il vous donne un accès complet à votre boîte de réception.",
|
||||
"attribute": "Attribut",
|
||||
"direct_protocol_access": "Cet utilisateur de la boîte aux lettres dispose d'un <b>accès externe direct</b> aux protocoles et applications suivants. Votre administrateur contrôle ce paramètre. Il est possible de créer des mots de passe d'application pour accorder l'accès à des protocoles et des applications individuels.<br>Le bouton « Connexion au webmail » permet une connexion unique à SOGo et est toujours disponible.",
|
||||
"open_webmail_sso": "Connexion au webmail",
|
||||
"recent_successful_connections": "Voir les connexions réussies",
|
||||
"syncjob_EXIT_TLS_FAILURE": "Problème de connexion chiffrée",
|
||||
"syncjob_EXIT_AUTHENTICATION_FAILURE": "Problème d'authentification",
|
||||
"syncjob_EXIT_OVERQUOTA": "La boîte de réception cible a dépassé le quota",
|
||||
"login_history": "Historique des connexions",
|
||||
"change_password_hint_app_passwords": "Votre compte a %d mots de passe d'application qui ne seront pas modifiés. Pour les gérer, allez dans l'onglet Mots de passe de l'application.",
|
||||
"clear_recent_successful_connections": "Vider l'historique des connexions réussies",
|
||||
"created_on": "Créé le",
|
||||
"last_ui_login": "Dernière connexion sur l'interface",
|
||||
"syncjob_check_log": "Vérifier le journal",
|
||||
"syncjob_last_run_result": "Résultat du dernier lancement",
|
||||
"syncjob_EX_OK": "Succès",
|
||||
"syncjob_EXIT_CONNECTION_FAILURE": "Problème de connexion",
|
||||
"syncjob_EXIT_CONNECTION_FAILURE_HOST1": "Impossible de se connecter au serveur distant",
|
||||
"syncjob_EXIT_AUTHENTICATION_FAILURE_USER1": "Nom d'utilisateur ou mot de passe incorrect",
|
||||
"value": "Valeur",
|
||||
"allowed_protocols": "Protocoles autorisés",
|
||||
"mailbox": "Boîte de réception"
|
||||
},
|
||||
"warning": {
|
||||
"cannot_delete_self": "Impossible de supprimer l’utilisateur connecté",
|
||||
@@ -1120,9 +1211,32 @@
|
||||
"fuzzy_learn_error": "Erreur d’apprentissage du hachage flou: %s",
|
||||
"hash_not_found": "Hachage non trouvé ou déjà supprimé",
|
||||
"ip_invalid": "IP non valide ignorée : %s",
|
||||
"no_active_admin": "Impossible de désactiver le dernier administrateur active",
|
||||
"quota_exceeded_scope": "Dépassement du quota de domaine : Seules des boîtes illimitées peuvent être créées dans ce domaine.",
|
||||
"no_active_admin": "Impossible de désactiver le dernier administrateur actif",
|
||||
"quota_exceeded_scope": "Dépassement du quota de domaine : Seules des boîtes de réception illimitées peuvent être créées dans ce domaine.",
|
||||
"session_token": "Jeton de formulaire invalide : Jeton différent",
|
||||
"session_ua": "Jeton de formulaire invalide : erreur de validation User-Agent"
|
||||
"session_ua": "Jeton de formulaire invalide : erreur de validation User-Agent",
|
||||
"is_not_primary_alias": "Alias non primaire ignoré %s"
|
||||
},
|
||||
"datatables": {
|
||||
"decimal": ".",
|
||||
"expand_all": "Tout déplier",
|
||||
"thousands": ",",
|
||||
"paginate": {
|
||||
"first": "Premier",
|
||||
"last": "Dernier"
|
||||
},
|
||||
"aria": {
|
||||
"sortAscending": ": activer pour trier les colonnes en ordre croissant",
|
||||
"sortDescending": ": activer pour trier les colonnes en ordre décroissant"
|
||||
},
|
||||
"infoEmpty": "Affichage de 0 à 0 de 0 entrées",
|
||||
"infoFiltered": "(filtré à partir de _MAX_ entrées totales)",
|
||||
"lengthMenu": "Afficher les entrées _MENU_",
|
||||
"loadingRecords": "Chargement…",
|
||||
"processing": "Veuillez patienter…",
|
||||
"collapse_all": "Tout réduire"
|
||||
},
|
||||
"ratelimit": {
|
||||
"disabled": "Désactivé"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,114 @@
|
||||
"activate_api": "API aktiválása",
|
||||
"activate_send": "Küldés gomb aktiválása",
|
||||
"add": "Hozzáad",
|
||||
"active": "Aktív"
|
||||
"active": "Aktív",
|
||||
"api_info": "Az API még fejlesztés alatt áll. A dokumentáció megtalálható a <a href=\"/api\">/api</a> alatt",
|
||||
"allowed_methods": "Hozzáférés-Szabályozás-Engedélyezési-Módszerek",
|
||||
"logo_normal_label": "Normál",
|
||||
"logo_dark_label": "Sötét üzemmódhoz invertálva",
|
||||
"f2b_regex_info": "Figyelembe vett naplók: SOGo, Postfix, Dovecot, PHP-FPM.",
|
||||
"f2b_retry_window": "Újrapróbálkozási ablak (s) a maximális próbálkozásokhoz",
|
||||
"f2b_whitelist": "Fehérlistás hálózatok/hostok",
|
||||
"filter_table": "Szűrő táblázat",
|
||||
"forwarding_hosts": "Továbbító hostok",
|
||||
"forwarding_hosts_add_hint": "Megadhat IPv4/IPv6 címeket, hálózatokat CIDR jelölésben, állomásneveket (amelyek IP-címekre lesznek feloldva) vagy tartományneveket (amelyek IP-címekre lesznek feloldva az SPF rekordok vagy ezek hiányában az MX rekordok lekérdezésével).",
|
||||
"from": "A címről",
|
||||
"copy_to_clipboard": "Szöveg másolva a vágólapra!",
|
||||
"f2b_manage_external": "A Fail2Ban külső kezelése",
|
||||
"f2b_manage_external_info": "A Fail2ban továbbra is karbantartja a tiltólistát, de nem állít be aktívan szabályokat a forgalom blokkolására. Használja az alábbi generált tiltólistát a forgalom külső blokkolásához.",
|
||||
"f2b_max_ban_time": "Maximális tiltási idő (s)",
|
||||
"f2b_netban_ipv4": "IPv4 alhálózat mérete, amelyre tilalmat kell alkalmazni (8-32)",
|
||||
"f2b_netban_ipv6": "IPv6 alhálózat mérete, amelyre tilalmat kell alkalmazni (8-128)",
|
||||
"f2b_parameters": "Fail2ban paraméterek",
|
||||
"forwarding_hosts_hint": "A bejövő üzeneteket feltétel nélkül elfogadják az itt felsorolt összes állomásról. Ezeket az állomáshelyeket nem ellenőrzik a DNSBL-ek alapján, és nem vetik alá a szürkelistázásnak. A tőlük érkező spameket a rendszer soha nem utasítja el, de opcionálisan a Junk mappába iktathatja őket. Leggyakrabban olyan levelezőszerverek megadására használjuk, amelyeken olyan szabályt állítottunk be, amely a bejövő e-maileket a mailcow-kiszolgálóra továbbítja.",
|
||||
"guid_and_license": "GUID & Licenc",
|
||||
"help_text": "Súgó szöveg felülírása a bejelentkezési maszk alatt (HTML engedélyezett)",
|
||||
"html": "HTML",
|
||||
"import": "Import",
|
||||
"ip_check": "IP ellenőrzés",
|
||||
"ip_check_disabled": "Az IP-ellenőrzés le van tiltva. Bekapcsolhatja a következő menüpont alatt<br> <strong>Rendszer > Beállítások > Opciók > Személyreszabás</strong>",
|
||||
"is_mx_based": "MX alapú",
|
||||
"last_applied": "Utoljára alkalmazott",
|
||||
"link": "Link",
|
||||
"loading": "Kérjük, várj...",
|
||||
"login_time": "Bejelentkezési idő",
|
||||
"f2b_list_info": "Egy feketelistán szereplő állomás vagy hálózat mindig nagyobb súlyú, mint egy fehérlistás entitás. <b>A lista frissítései néhány másodpercig tartanak.</b>",
|
||||
"f2b_ban_time_increment": "A tiltási idő minden egyes tiltással növekszik",
|
||||
"additional_rows": " - további sorokat adtak hozzá",
|
||||
"admin": "Adminisztrátor",
|
||||
"admin_details": "Rendszergazda adatok szerkesztése",
|
||||
"admin_domains": "Domain hozzárendelések",
|
||||
"f2b_max_attempts": "Max. próbálkozások",
|
||||
"generate": "generálni",
|
||||
"admins": "Adminisztrátorok",
|
||||
"admins_ldap": "LDAP rendszergazdák",
|
||||
"allowed_origins": "Hozzáférés-Szabályozás-Engedélyezési-Származás",
|
||||
"api_allow_from": "API-hozzáférés engedélyezése ezekről az IP/CIDR hálózati jelölésekről",
|
||||
"api_key": "API-kulcs",
|
||||
"api_read_only": "Csak olvasható hozzáférés",
|
||||
"api_read_write": "Olvasás-írás hozzáférés",
|
||||
"api_skip_ip_check": "IP-ellenőrzés kihagyása az API esetében",
|
||||
"cors_settings": "CORS beállítások",
|
||||
"guid": "GUID - egyedi példányazonosító",
|
||||
"dkim_to": "A címre",
|
||||
"dkim_to_title": "Céltartomány(ok) - felülírásra kerül",
|
||||
"domain": "Domain",
|
||||
"domain_admin": "Domain adminisztrátor",
|
||||
"domain_admins": "Domain adminisztrátorok",
|
||||
"domain_s": "Domain(ek)",
|
||||
"duplicate": "Duplikátum",
|
||||
"duplicate_dkim": "Duplikált DKIM bejegyzés",
|
||||
"edit": "Szerkesztés",
|
||||
"empty": "Nincs eredmény",
|
||||
"excludes": "Kizárja ezeket a kedvezményezetteket",
|
||||
"f2b_ban_time": "Tilalmi idő (s)",
|
||||
"f2b_blacklist": "Feketelistás hálózatok/hostok",
|
||||
"f2b_filter": "Regex szűrők",
|
||||
"logo_info": "A képed 40px magasságúra lesz méretezve a felső navigációs sávhoz és max. 250px szélességűre a kezdőlaphoz. A skálázható grafika használata erősen ajánlott.",
|
||||
"dkim_add_key": "ARC/DKIM kulcs hozzáadása",
|
||||
"dkim_domains_selector": "Válogató",
|
||||
"dkim_domains_wo_keys": "A hiányzó kulcsokkal rendelkező tartományok kiválasztása",
|
||||
"dkim_from": "A címről",
|
||||
"dkim_from_title": "Forrás tartomány, ahonnan az adatokat másolni kell",
|
||||
"dkim_key_length": "DKIM kulcs hossza (bit)",
|
||||
"dkim_key_missing": "Kulcs hiányzik",
|
||||
"import_private_key": "Privát kulcs importálása",
|
||||
"in_use_by": "Használja a",
|
||||
"inactive": "Inaktív",
|
||||
"include_exclude": "Beleértve/Kivéve",
|
||||
"include_exclude_info": "Alapértelmezés szerint - kiválasztás nélkül - <b>minden postafiók</b> címzésre kerül.",
|
||||
"includes": "Vegye fel ezeket a címzetteket",
|
||||
"add_row": "Sor hozzáadása",
|
||||
"host": "Host",
|
||||
"active_rspamd_settings_map": "Aktív beállítások térképe",
|
||||
"add_admin": "Adminisztrátor hozzáadása",
|
||||
"add_forwarding_host": "Továbbító állomás hozzáadása",
|
||||
"add_relayhost": "Feladófüggő szállítás hozzáadása",
|
||||
"add_relayhost_hint": "Felhívjuk figyelmed, hogy ha vannak hitelesítési adatok, azok egyszerű szövegként kerülnek tárolásra.",
|
||||
"add_settings_rule": "Beállítási szabály hozzáadása",
|
||||
"add_transport": "Szállítás hozzáadása",
|
||||
"add_transports_hint": "Felhívjuk figyelmed, hogy ha vannak hitelesítési adatok, azok egyszerű szövegként kerülnek tárolásra.",
|
||||
"advanced_settings": "Speciális beállítások",
|
||||
"change_logo": "Logó módosítása",
|
||||
"dkim_key_unused": "Nem használt kulcs",
|
||||
"add_domain_admin": "Tartományi rendszergazda hozzáadása",
|
||||
"dkim_key_valid": "Érvényes kulcs",
|
||||
"dkim_keys": "ARC/DKIM kulcsok",
|
||||
"dkim_overwrite_key": "A meglévő DKIM kulcs felülírása",
|
||||
"dkim_private_key": "Privát kulcs",
|
||||
"app_links": "App linkek",
|
||||
"app_name": "Alkalmazás neve",
|
||||
"arrival_time": "Érkezési idő (szerveridő)",
|
||||
"authed_user": "Azonosított felhasználó",
|
||||
"ays": "Biztos, hogy folytatni akarod?",
|
||||
"ban_list_info": "A tiltott IP-címek listáját lásd alább: <b>hálózat (fennmaradó tiltási idő) - [akciók]</b>.<br />A tiltás feloldására várakozó IP-ket néhány másodpercen belül eltávolítjuk az aktív tiltási listáról.<br />A piros címkék a feketelistán szereplő aktív állandó tiltásokat jelzik.",
|
||||
"configuration": "Konfiguráció",
|
||||
"convert_html_to_text": "HTML átalakítása egyszerű szöveggé",
|
||||
"credentials_transport_warning": "<b>Figyelmeztetés</b>: Egy új közlekedési térképbejegyzés hozzáadása frissíti a hitelesítő adatokat minden olyan bejegyzéshez, amelynek a következő ugrás oszlopa megegyezik.",
|
||||
"customize": "Testreszabás",
|
||||
"destination": "Célállomás",
|
||||
"customer_id": "Ügyfél azonosító",
|
||||
"apps_name": "\"mailcow Apps\" név"
|
||||
},
|
||||
"edit": {
|
||||
"active": "Aktív",
|
||||
@@ -57,7 +164,7 @@
|
||||
"header": {
|
||||
"administration": "Beállítások és részletek",
|
||||
"apps": "Appok",
|
||||
"debug": "Rendszer információ",
|
||||
"debug": "Információ",
|
||||
"email": "E-Mail",
|
||||
"mailcow_config": "Beállítások",
|
||||
"quarantine": "Karantén",
|
||||
@@ -399,13 +506,89 @@
|
||||
"protocol_access": "Protokoll-hozzáférés módosítása",
|
||||
"quarantine_attachments": "Karantén mellékletek",
|
||||
"quarantine_category": "Karantén értesítési kategória módosítása",
|
||||
"quarantine_notification": "Karantén értesítések módosítása"
|
||||
"quarantine_notification": "Karantén értesítések módosítása",
|
||||
"eas_reset": "EAS-eszközök alaphelyzetbe állítása",
|
||||
"extend_sender_acl": "Küldő ACL külső címekkel való bővítésének engedélyezése",
|
||||
"mailbox_relayhost": "Relayhost módosítása egy postafiókhoz",
|
||||
"prohibited": "ACL által tiltott",
|
||||
"pushover": "Pushover",
|
||||
"ratelimit": "Mérték határ",
|
||||
"recipient_maps": "Címzett térképek",
|
||||
"smtp_ip_access": "Az SMTP engedélyezett állomásainak módosítása",
|
||||
"sogo_profile_reset": "SOGo profil visszaállítása",
|
||||
"spam_alias": "Ideiglenes álnevek",
|
||||
"spam_policy": "Fekete/Fehér lista",
|
||||
"spam_score": "Spam pontszám",
|
||||
"syncjobs": "Szinkronizálási feladatok",
|
||||
"tls_policy": "TLS szabályzat",
|
||||
"unlimited_quota": "Korlátlan kvóta a postafiókok számára",
|
||||
"sogo_access": "A SOGo-hozzáférés kezelésének lehetővé tétele"
|
||||
},
|
||||
"diagnostics": {
|
||||
"dns_records": "DNS bejegyzések"
|
||||
},
|
||||
"add": {
|
||||
"username": "Felhasználónév",
|
||||
"validation_success": "Sikeres ellenőrzés"
|
||||
"validation_success": "Sikeres ellenőrzés",
|
||||
"mailbox_quota_def": "Alapértelmezett postafiók kvóta",
|
||||
"password_repeat": "Megerősítő jelszó (ismétlés)",
|
||||
"post_domain_add": "A \"sogo-mailcow\" SOGo konténert újra kell indítani egy új tartomány hozzáadása után!<br><br>Kiegészítésképpen a tartományok DNS-konfigurációját is felül kell vizsgálni. A DNS-konfiguráció jóváhagyása után indítsa újra az \"acme-mailcow\"-t, hogy automatikusan generáljon tanúsítványokat az új tartományhoz (autoconfig.<domain>, autodiscover.<domain>).<br>Ez a lépés opcionális, és 24 óránként megismétlődik.",
|
||||
"dry": "Szinkronizálás szimulálása",
|
||||
"inactive": "Inaktív",
|
||||
"kind": "Kedves",
|
||||
"mailbox_quota_m": "Maximális kvóta postafiókonként (MiB)",
|
||||
"mailbox_username": "Felhasználónév (az e-mail cím bal oldali része)",
|
||||
"max_aliases": "Max. lehetséges álnevek",
|
||||
"max_mailboxes": "Max. lehetséges postafiókok",
|
||||
"mins_interval": "A lekérdezési időköz (perc)",
|
||||
"password": "Jelszó",
|
||||
"port": "Port",
|
||||
"public_comment": "Nyilvános megjegyzés",
|
||||
"target_domain": "Céltartomány",
|
||||
"timeout1": "Időtúllépés a távoli állomáshoz való csatlakozáskor",
|
||||
"timeout2": "Időtúllépés a helyi állomáshoz való csatlakozáskor",
|
||||
"validate": "Érvényesítsd",
|
||||
"description": "Leírás",
|
||||
"destination": "Célállomás",
|
||||
"disable_login": "Bejelentkezés letiltása (a bejövő leveleket továbbra is elfogadja)",
|
||||
"domain_matches_hostname": "Domain %s megegyezik a hostnévvel",
|
||||
"domain_quota_m": "Teljes tartományi kvóta (MiB)",
|
||||
"enc_method": "Titkosítási módszer",
|
||||
"exclude": "Objektumok kizárása (regex)",
|
||||
"full_name": "Teljes név",
|
||||
"gal": "Globális címlista",
|
||||
"goto_ham": "Tanulj <span class=\"text-success\"><b>sonkaként</b></span>",
|
||||
"goto_null": "Leveleket csendben eldobni",
|
||||
"goto_spam": "Tanuld <span class=\"text-danger\"><b>spamként</b></span>",
|
||||
"syncjob_hint": "Ne feledje, hogy a jelszavakat egyszerű szöveges formában kell elmenteni!",
|
||||
"target_address": "Továbbítási címek",
|
||||
"target_address_info": "<small>Teljes e-mail cím(ek) (vesszővel elválasztva).</small>",
|
||||
"bcc_dest_format": "A BCC-célpontnak egyetlen érvényes e-mail címnek kell lennie.<br>Ha több címre kell másolatot küldenie, hozzon létre egy aliast, és használja azt.",
|
||||
"comment_info": "A privát megjegyzés nem látható a felhasználó számára, míg a nyilvános megjegyzés tooltip-ként jelenik meg, amikor a felhasználó áttekintésében a megjegyzésre mutat.",
|
||||
"custom_params": "Egyéni paraméterek",
|
||||
"gal_info": "A GAL tartalmazza a tartomány összes objektumát, és egyetlen felhasználó sem szerkesztheti. A SOGo-ban a Szabad/Elfoglalt információ hiányzik, ha ki van kapcsolva! <b>Indítsa újra a SOGo-t a változások alkalmazásához.</b>",
|
||||
"hostname": "Házigazda",
|
||||
"backup_mx_options": "Továbbítási opciók",
|
||||
"custom_params_hint": "Megfelelő: --param=xy, Rossz: --param xy",
|
||||
"delete1": "Törlés a forrásból, ha befejeződött",
|
||||
"delete2": "A forráson kívüli üzenetek törlése a célállomáson",
|
||||
"delete2duplicates": "Duplikáltak törlése a célállomáson",
|
||||
"domain": "Domain",
|
||||
"nexthop": "Következő hop",
|
||||
"tags": "Címkék",
|
||||
"app_password": "Alkalmazás jelszó hozzáadása",
|
||||
"private_comment": "Privát megjegyzés",
|
||||
"alias_address_info": "<small>Teljes e-mail cím(ek) vagy @example.com, egy domainhez tartozó összes üzenetet elfogásához (vesszővel elválasztva). <b>csak mailcow tartományok</b>.</small>",
|
||||
"generate": "generál",
|
||||
"activate_filter_warn": "Az összes többi szűrő deaktiválódik, ha az aktív opció be van jelölve.",
|
||||
"active": "Aktív",
|
||||
"add": "Hozzáad",
|
||||
"add_domain_only": "Csak domain hozzáadása",
|
||||
"add_domain_restart": "Domain hozzáadása és a SOGo újraindítása",
|
||||
"alias_address": "Alias cím(ek)",
|
||||
"alias_domain": "Alias domain",
|
||||
"alias_domain_info": "<small>Csak érvényes tartománynevek (vesszővel elválasztva).</small>",
|
||||
"app_name": "Alkalmazás neve",
|
||||
"app_passwd_protocols": "Engedélyezett protokollok az alkalmazás jelszavához"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,9 @@
|
||||
"eas_reset": "EAS ierīču atiestatīšana",
|
||||
"extend_sender_acl": "Ļauj paplašināt sūtītāja ACL ar ārējām adresēm",
|
||||
"login_as": "Pieteikšanās kā pastkastes lietotājam",
|
||||
"mailbox_relayhost": "Pasta kastītes relayhost maiņa"
|
||||
"mailbox_relayhost": "Pasta kastītes relayhost maiņa",
|
||||
"prohibited": "Aizliegts ar ACL",
|
||||
"protocol_access": "Protokola piekļuves maiņa"
|
||||
},
|
||||
"add": {
|
||||
"activate_filter_warn": "Visi pārējie filtri tiks deaktivizēti, kad aktīvs ir atzīmēts.",
|
||||
@@ -33,7 +35,7 @@
|
||||
"delete2duplicates": "Dzēst dublikātus galamērķī",
|
||||
"description": "Apraksts",
|
||||
"domain": "Domēns",
|
||||
"domain_quota_m": "Kopējā domēna kvota (MiB)",
|
||||
"domain_quota_m": "Kopējā domēna kvota (MiB)",
|
||||
"enc_method": "Šifrēšanas metode",
|
||||
"exclude": "Izslēgt objektus (regex)",
|
||||
"full_name": "Pilns vārds",
|
||||
@@ -52,7 +54,7 @@
|
||||
"post_domain_add": "SOGO konteineru \"sogo-mailcow\" ir nepieciešams pārsāknēt pēc jauna domēna pievienošanas.<br><br>Papildus vajadzētu pārskatīt domēnu DNS konfigurāciju. Tiklīdz DNS konfigurācija ir apstiprināta, jāpārsāknē \"acme-mailcow\", lai automātiski izveidotu sertifikātus jaunajam domēnam (autoconfig.<domain>, autodiscover.<domain>).<br>Šis solis ir izvēles un tiks atkārtots ik pēc 24 stundām.",
|
||||
"quota_mb": "Kvota (MiB)",
|
||||
"relay_all": "Pārsūtīt visus saņēmējus",
|
||||
"relay_all_info": "<small>Ja izvēlies <b>nepārsūtīt</b> visus saņēmējus, tad Tev būs nepieciešams pievienot (\"tukšu\") pastkasti katram saņēmējam, kas būtu jāpārsūta.</small>",
|
||||
"relay_all_info": "↪ Ja izvēlies <b>nepārsūtīt</b> visus saņēmējus, tad Tev būs nepieciešams pievienot (\"aklo\") pastkasti katram saņēmējam, kas būtu jāpārsūta.",
|
||||
"relay_domain": "Pārsūtīt šo domēnu",
|
||||
"select": "Lūdzu izvēlaties...",
|
||||
"select_domain": "Lūdzu sākumā izvēlaties domēnu",
|
||||
@@ -104,14 +106,14 @@
|
||||
"f2b_ban_time": "Aizlieguma laiks (s)",
|
||||
"f2b_max_attempts": "Maks. piegājieni",
|
||||
"f2b_netban_ipv4": "IPv4 apakštīkla izmērs, lai piemērotu aizliegumu uz (8-32)",
|
||||
"f2b_netban_ipv6": "IPv6 apakštīkla izmērs, lai piemērotu aizliegumu uz (8-128)",
|
||||
"f2b_netban_ipv6": "IPv6 apakštīkla izmērs, lai piemērotu aizliegumu uz (8-128)",
|
||||
"f2b_parameters": "Fail2ban parametri",
|
||||
"f2b_retry_window": "Atkārtošanas logs (s) priekš maks. piegājiena",
|
||||
"f2b_whitelist": "Baltā saraksta tīkls/hosts",
|
||||
"filter_table": "Filtru tabula",
|
||||
"forwarding_hosts": "Hostu pārsūtīšana",
|
||||
"forwarding_hosts_add_hint": "Jūs varat norādīt IPv4/IPv6 addreses, tīklu iekš CIDR apzīmējuma, hosta nosaukumu (kas tiks atrisinātas IP adresēs), vai domēna vārdos (kas tiks atrisināts IP adresēs vaicājot SPF ierakstus vai, ja tādu nav, MX ierakstus).",
|
||||
"forwarding_hosts_hint": "Ienākošie ziņojumi ir bez nosacījumiem pieņemti no visiem šeit norādītajiem hostiem. Pēc tam šie hosti netiek pārbaudīti pret DNSBL vai pakļauti Greylistei. No tiem saņemtās mēstules nekad netiek noraidītas, bet pēc izvēles tās var pārvietot mapē Nevēlamais. Visbiežāk to izmanto, lai precizētu pasta serverus, kuros ir iestatīts noteikums, kas pārsūta ienākošos e-pasta ziņojumus uz jūsu mailcow serveri.",
|
||||
"forwarding_hosts_add_hint": "Var norādīt vai nu IPv4/IPv6 addreses, tīklu ar CIDR apzīmējumu, saimniekdatoru nosaukumus (kas tiks atrisināti IP adresēs) vai arī domēna vārdus (kas tiks atrisināti IP adresēs, vaicājot SPF ierakstus, vai, ja tādu nav, MX ierakstus).",
|
||||
"forwarding_hosts_hint": "Ienākošie ziņojumi tiek bez nosacījumiem pieņemti no visiem šeit norādītajiem saimniekdatoriem. Tie tad netiek pārbaudīti pret DNSBL vai pakļauti ievietošanai pelēkajā sarakstā. No tiem saņemtās mēstules nekad netiek noraidītas, bet pēc izvēles tās var pārvietot mapē \"Nevēlams\". Visbiežāk to izmanto, lai norādītu pasta serverus, kuros ir uzstādīts nosacījums, kas pārsūta ienākošās e-pasta vēstules uz Tavu mailcow serveri.",
|
||||
"help_text": "Ignorēt palīdzības tekstu zem pieteikšanās maskas (HTML ir atļauta)",
|
||||
"host": "Hosts",
|
||||
"import": "Importēt",
|
||||
@@ -120,7 +122,7 @@
|
||||
"inactive": "Neaktīvs",
|
||||
"link": "Saite",
|
||||
"loading": "Lūgums uzgaidīt...",
|
||||
"logo_info": "Jūsu attēls augšējā navigācijas joslā tiks palielināts līdz 40 pikseļiem un maks. sākumlapas platums par 250 pikseļi. Ir ļoti ieteicama pielāgojama grafikaYour image will be scaled to a height of 40px for the top navigation bar and a max. width of 250px for the start page. Ir ļoti ieteicama pielāgojamā grafika",
|
||||
"logo_info": "Tavs attēls augšējā pārvietošanās joslā tiks mērogots līdz 40 pikseļiem un ne vairāk par 250 pikseļiem platumā sākumlapā. Ļoti ieteicams izmantot mērogojamus attēlus.",
|
||||
"main_name": "\"mailcow UI\" nosaukums",
|
||||
"merged_vars_hint": "Pelēkās rindas tika apvienotas <code>vars.(local.)inc.php</code> un nevar tikt modificētas.",
|
||||
"no_new_rows": "Papildu rindas nav pieejamas",
|
||||
@@ -130,11 +132,11 @@
|
||||
"private_key": "Privāta atslēga",
|
||||
"quarantine": "Karantīna",
|
||||
"quarantine_exclude_domains": "Neņemt vērā domēnus un aizstājdomēnus",
|
||||
"quarantine_max_size": "Maks. izmērs MiB (lielāki vienumi ir atbrīvoti):",
|
||||
"quarantine_retention_size": "Atlikumi pastkastēs:",
|
||||
"quarantine_max_size": "Lielākais pieļaujamais izmērs MiB (lielāki vienumi tiek atmesti):<br><small>0 <b>nenorāda</b> neierobežotu.</small>",
|
||||
"quarantine_retention_size": "Paturējumi katrā pastkastē:<br><small>0 norāda, ka ir <b>atspējoti</b>.</small>",
|
||||
"r_active": "Aktīvie ierobežojumi",
|
||||
"r_inactive": "Neaktīvie ierobežojumi",
|
||||
"r_info": " Pelēki/atslēgti elementi aktīvo ierobežojumu sarakstā nav zināmi kā mailcow spēkā esoši ierobežojumi un tos nevar pārvietot. Jebkurā gadījumā nezināmi ierobežojumi tiks sakārtoti pēc pievienošanas. <br>Jūs varat pievienot jaunus elementus <code>inc/vars.local.inc.php</code>, lai varētu tos pārslēgt.",
|
||||
"r_info": "Pelēkie/atspējotie vienumi spēkā esošo ierobežojumu sarakstā mailcow nav zināmi kā derīgi ierobežojumi, un tos nevar pārvietot. Nezināmi ierobežojumi jebkurā gadījumā parādīšanas secībā. <br>Jaunus vienumus var pievienot <code>inc/vars.local.inc.php</code>, lai varētu tos pārslēgt.",
|
||||
"recipients": "Adresāts",
|
||||
"refresh": "Atsvaidzināt",
|
||||
"regen_api_key": "Reģenerēt API atslēgu",
|
||||
@@ -160,9 +162,10 @@
|
||||
"generate": "izveidot",
|
||||
"message": "Ziņojums",
|
||||
"last_applied": "Pēdējoreiz pielietots",
|
||||
"f2b_regex_info": "Vērā ņemtie žurnāli: SOGO, Postfix, Dovecot, PHP-FPM",
|
||||
"f2b_regex_info": "Vērā ņemtie žurnāli: SOGO, Postfix, Dovecot, PHP-FPM.",
|
||||
"sys_mails": "Sistēmas pasts",
|
||||
"ip_check_disabled": "IP pārbaude ir atspējota. To var iespējot<br><strong>Sistēma > Konfigurācija > iespējas > Pielāgot</strong>"
|
||||
"ip_check_disabled": "IP pārbaude ir atspējota. To var iespējot<br><strong>Sistēma > Konfigurācija > iespējas > Pielāgot</strong>",
|
||||
"rspamd_com_settings": "Iestatījuma nosaukums tiks izveidots automātiski. Lūgums zemāk skatīt priekšiestatījumu piemērus. Vairāk informācijas ir <a href=\"https://rspamd.com/doc/configuration/settings.html#settings-structure\" target=\"_blank\">Rspamd dokumentācijā</a>"
|
||||
},
|
||||
"danger": {
|
||||
"access_denied": "Piekļuve liegta, vai nepareizi dati",
|
||||
@@ -187,7 +190,7 @@
|
||||
"invalid_mime_type": "Nederīgs mime tips",
|
||||
"is_alias": "%s jau ir zināma kā aizstājadrese",
|
||||
"is_alias_or_mailbox": "%s jau ir zināms kā aizstājvārds, pastkaste vai aizstājadrese, kas ir izvērsta no aizstājdomēna.",
|
||||
"is_spam_alias": "%s jau ir zināma kā pagaidu aizstājadrese (aizstājadrese mēstulēm)",
|
||||
"is_spam_alias": "%s jau ir zināma kā pagaidu aizstājadrese (mēstuļu aizstājadrese)",
|
||||
"last_key": "Pēdējo atslēgu nevar izdzēst, tā vietā jāatspējo divpakāpju pārbaude.",
|
||||
"login_failed": "Ielogošanās neveiksmīga",
|
||||
"mailbox_invalid": "Pastkastes vārds ir nederīgs",
|
||||
@@ -216,7 +219,7 @@
|
||||
"validity_missing": "Lūdzu piešķiriet derīguma termiņu"
|
||||
},
|
||||
"diagnostics": {
|
||||
"cname_from_a": "Vērtība, kas iegūta no A/AAAA ieraksta. Tas tiek atbalstīts tik ilgi, kamēr ieraksts norāda pareizo resursu.",
|
||||
"cname_from_a": "Vērtība, kas iegūta no A/AAAA ieraksta. Tas tiek atbalstīts tik ilgi, kamēr ieraksts norāda uz pareizo resursu.",
|
||||
"dns_records": "DNS Ieraksti",
|
||||
"dns_records_24hours": "Lūdzu ņemiet vērā, ka DNS izmaiņas var aizņemt laiku līdz 24 stundām, lai pareizi varētu atspoguļot izmaiņas šajā lapā. Tas ir paredzēts, lai jūs varētu viegli uzzināt, kā konfigurēt savus DNS ierakstus un pārbaudīt, vai visi jūsu ieraksti ir pareizi saglabāti DNS.",
|
||||
"dns_records_data": "Pareizi dati",
|
||||
@@ -261,7 +264,7 @@
|
||||
"previous": "Iepriekšējā lapa",
|
||||
"quota_mb": "Kvota (MiB)",
|
||||
"relay_all": "Pārsūtīt visus adresātus",
|
||||
"relay_all_info": "<small>Ja tu izvēlies <b>nepārsūtīt</b> visus adresātus, tad tev vajadzēs pievienot (\"tukšu\") pastkasti katram saņēmējam, kas būtu jāpārsūta.</small>",
|
||||
"relay_all_info": "↪ Ja izvēlies <b>nepārsūtīt</b> visus adresātus, tad tev vajadzēs pievienot (\"aklo\") pastkasti katram saņēmējam, kas būtu jāpārsūta.",
|
||||
"relay_domain": "Pārsūtīt domēnu",
|
||||
"remove": "Noņemt",
|
||||
"resource": "Resurss",
|
||||
@@ -270,9 +273,9 @@
|
||||
"sieve_desc": "Īss apraksts",
|
||||
"sieve_type": "Filtra tips",
|
||||
"skipcrossduplicates": "Izlaist dublētus ziņojumus pa mapēm (pirmais nāk, pirmais kalpo)",
|
||||
"spam_alias": "Izveidot vai mainīt laika ierobežotas alias adreses",
|
||||
"spam_policy": "Pievienot vai noņemt vienības baltajā-/melnajā sarakstā",
|
||||
"spam_score": "Iestatīt pielāgotu surogātpastu",
|
||||
"spam_alias": "Izveidot vai mainīt laika ierobežotas aizstājadreses",
|
||||
"spam_policy": "Pievienot vai noņemt vienumus baltajā-/melnajā sarakstā",
|
||||
"spam_score": "Iestatīt pielāgotu surogātpasta vērtējumu",
|
||||
"subfolder2": "Sinhronizēt galamērķa apakšmapē<br><small>(tukšs = neizmantot apakšmapi)</small>",
|
||||
"syncjob": "Rediģēt sinhronizācijas darbu",
|
||||
"target_address": "Iet uz adresi/ēm <small>(komatu atdalītas)</small>",
|
||||
@@ -295,15 +298,15 @@
|
||||
"cancel": "Atcelt",
|
||||
"confirm_delete": "Apstiprināt dzēšanu",
|
||||
"delete_now": "Dzēst tagad",
|
||||
"delete_these_items": "Lūdzu apstipriniet darbīku šiem abjektiem:",
|
||||
"delete_these_items": "Lūgums apstiprināt izmaiņas šim objekta Id",
|
||||
"loading": "Lūdzu uzgaidiet...",
|
||||
"restart_container": "Restartēt konteineri",
|
||||
"restart_container_info": "<b>Important:</b> Piespiedu restartēšana var aizņemt ilgu laiku, lūdzu uzgaidiet.",
|
||||
"restart_now": "Restartēt "
|
||||
"restart_now": "Pārsāknēt tagad"
|
||||
},
|
||||
"header": {
|
||||
"administration": "Administrēšana",
|
||||
"debug": "Atkļūdošana",
|
||||
"administration": "Konfigurācija un informācija",
|
||||
"debug": "Informācija",
|
||||
"email": "E-pasts",
|
||||
"mailcow_config": "Konfigurācija",
|
||||
"quarantine": "Karantīna",
|
||||
@@ -315,7 +318,7 @@
|
||||
"no_action": "No action applicable"
|
||||
},
|
||||
"login": {
|
||||
"delayed": "Pieslēgšanās aizkavējās par %s sekundēm.",
|
||||
"delayed": "Pieteikšanās tika aizkavēta %s sekundēm.",
|
||||
"login": "Pieslēgties",
|
||||
"password": "Parole",
|
||||
"username": "Lietotājvārds"
|
||||
@@ -325,22 +328,22 @@
|
||||
"activate": "Activate",
|
||||
"active": "Aktīvs",
|
||||
"add": "Pievienot",
|
||||
"add_alias": "Pievienot alias",
|
||||
"add_alias": "Pievienot aizstājvārdu",
|
||||
"add_bcc_entry": "Pievienot BCC karti",
|
||||
"add_domain": "Pievienot domēnu",
|
||||
"add_domain_alias": "Pievienot domēna alias",
|
||||
"add_domain_alias": "Pievienot domēna aizstājvārdu",
|
||||
"add_filter": "Pievienot filtru",
|
||||
"add_mailbox": "Pievienot pastkasti",
|
||||
"add_recipient_map_entry": "Pievienot saņēmēja karti",
|
||||
"add_resource": "Pievienot resursu",
|
||||
"address_rewriting": "Adreses pārrakstīšana",
|
||||
"alias": "Alias",
|
||||
"aliases": "Aliases",
|
||||
"alias": "Aizstājvārds",
|
||||
"aliases": "Aizstājvārdi",
|
||||
"backup_mx": "Rezerves kopija MX",
|
||||
"bcc": "BCC",
|
||||
"bcc_destination": "BCC galamērķi/s",
|
||||
"bcc_destinations": "BCC galamērķi/s",
|
||||
"bcc_info": "BCC kartes tiek izmantotas, lai klusu pārsūtītu visu ziņojumu kopijas uz citu adresi. Saņēmēja kartes tipa ieraksts tiek izmantots, kad vietējais galamērķis darbojas kā pasta adresāts. Sūtītāja kartes atbilst vienam un tam pašam principam. <br/>\r\n Vietējais galamērķis netiks informēts par piegādes neveiksmi. ",
|
||||
"bcc_info": "BCC kartes tiek izmantotas, lai klusi pārsūtītu visu ziņojumu kopijas uz citu adresi. Saņēmēja kartes veida ieraksts tiek izmantots, kad vietējais galamērķis darbojas kā pasta saņēmējs. Sūtītāja kartes atbilst vienam un tam pašam principam.<br/>\n Vietējais galamērķis netiks informēts par neizdevušos piegādi.",
|
||||
"bcc_local_dest": "Vietējais galamērķis",
|
||||
"bcc_map_type": "BCC veids",
|
||||
"bcc_maps": "BCC kartes",
|
||||
@@ -354,7 +357,7 @@
|
||||
"dkim_key_length": "DKIM atslēgas garums (bits)",
|
||||
"domain": "Domēns",
|
||||
"domain_admins": "Domēna administratori",
|
||||
"domain_aliases": "Domēna aliases",
|
||||
"domain_aliases": "Domēna aizstājvārdi",
|
||||
"domain_quota": "Kvota",
|
||||
"domain_quota_total": "Kopējais domēna ierobežojums",
|
||||
"domains": "Domēns",
|
||||
@@ -372,7 +375,7 @@
|
||||
"last_run_reset": "Ievietot sarakstā kā nākamo",
|
||||
"mailbox_quota": "Maks. pastkastes izmērs",
|
||||
"mailboxes": "Pastkaste",
|
||||
"max_aliases": "Maks. iespejamās aliases",
|
||||
"max_aliases": "Lielākais aizstājvārdu skaits",
|
||||
"max_mailboxes": "Maks. iespējamās pastkastes",
|
||||
"max_quota": "Maks. kvota uz pastkasti",
|
||||
"mins_interval": "Intervāls (min)",
|
||||
@@ -392,11 +395,11 @@
|
||||
"running": "Darbojas",
|
||||
"set_postfilter": "Atzīmēt kā pēcfiltru",
|
||||
"set_prefilter": "Atzīmēt kā pimrsfiltru",
|
||||
"sieve_info": "Jūs varat saglabāt vairākus filtrus katram lietotājam, bet tikai viens pirmsfiltrs un viens pēcfiltrs var būt aktīvs vienlaicīgi.<br>\r\nKatrs filtrs tiks apstrādāts aprakstītajā kārtībā. Kļūdains vai izdots skripts \"Paturēt;\" pārtrauks turpmāko skriptu apstrādi.<br>\r\n<a href=\"https://github.com/mailcow/mailcow-dockerized/blob/master/data/conf/dovecot/global_sieve_before\" target=\"_blank\">Global sieve prefilter</a> → Pirmsfiltrs → Lietotāja skripts → Pēcfiltrs → <a href=\"https://github.com/mailcow/mailcow-dockerized/blob/master/data/conf/dovecot/global_sieve_after\" target=\"_blank\">Global sieve postfilter</a>",
|
||||
"spam_aliases": "Temp. alias",
|
||||
"sieve_info": "Katram lietotājam var saglabāt vairākus filtrus, bet tikai viens pirmsfiltrs un viens pēcfiltrs var darboties vienlaicīgi.<br>\nKatrs filtrs tiks apstrādāts norādītajā kārtībā. Ne kļūdains skripts, ne izdots \"keep;\" nepārtrauks turpmāko skriptu apstrādi. Vispārējo sieve skriptu izmaiņas izsauks Dovecot pārsāknēšanu.<br><br>Vispārējais sieve pirmsfiltrs • Pirmsfiltrs • Lietotāja skripti • Pēcfiltrs • Vispārējais sieve pēcfiltrs",
|
||||
"spam_aliases": "Pagaidu aizstājvārds",
|
||||
"status": "Status",
|
||||
"sync_jobs": "Sinhronizācijas darbi",
|
||||
"target_address": "Doties uz adresi",
|
||||
"target_address": "Doties uz adresi",
|
||||
"target_domain": "Mērķa domēns",
|
||||
"tls_enforce_in": "Piespiest TLS ienākošajiem",
|
||||
"tls_enforce_out": "Piespiest TLS izejošajiem",
|
||||
@@ -411,7 +414,13 @@
|
||||
"mailbox": "Pastkaste",
|
||||
"sieve_preset_2": "Vienmēr atzīmēt noteikta sūtītāja e-pastu kā izlasītu",
|
||||
"open_logs": "Atvērt žurnālus",
|
||||
"sieve_preset_8": "Pārvirzīt noteikta sūtītāja e-pastu, atzīmēt kā izlasītu un ievietot to apakšmapē"
|
||||
"sieve_preset_8": "Pārvirzīt noteikta sūtītāja e-pastu, atzīmēt kā izlasītu un ievietot to apakšmapē",
|
||||
"sogo_visible": "Aizstājvārds ir redzams SOGo",
|
||||
"sogo_visible_n": "Paslēpt aizstājvārdu SOGo",
|
||||
"sogo_visible_y": "Rādīt aizstājvārdu SOGo",
|
||||
"add_alias_expand": "Izvērst aizstājvārdu pār aizstājdomēniem",
|
||||
"alias_domain_alias_hint": "Aizstājvārdi <b>netiek</b> automātiski piemēroti domēnu aizstājvārdiem. Aizstājadrese <code>my-alias@domain</code> <b>nenosedz</b> adresi <code>my-alias@alias-domain</code> (kur \"alias-domain\" ir iedomāts \"domain\" aizstājdomēns).<br>Lūgums izmantot sieta atlasi, lai pārvirzītu pastu uz ārēju pastkasti (skatīt cilti \"Atlasīšana\" vai izmantot SOGo -> Pārsūtītājs). \"Izvērst aizstājvārdu pār aizstājdomēniem\" ir izmantojams, lai automātiski pievienotu trūkstošos aiztājvārdus.",
|
||||
"alias_domain_backupmx": "Aizstājdomēns ir neaktīvs retranslācijas domēnam"
|
||||
},
|
||||
"quarantine": {
|
||||
"action": "Darbības",
|
||||
@@ -445,18 +454,18 @@
|
||||
},
|
||||
"start": {
|
||||
"help": "Rādīt/Paslēp palīdzības paneli",
|
||||
"imap_smtp_server_auth_info": "Lūdzu, izmantojiet pilnu e-pasta adresi un PLAIN autentifikācijas mehānismu.<br>\r\nJūsu pieteikšanās dati tiks šifrēti, izmantojot servera puses obligātu šifrēšanu",
|
||||
"imap_smtp_server_auth_info": "Lūgums izmantot pilnu e-pasta adresi un PLAIN autentifikācijas mehānismu.<br>\nPieteikšanās dati tiks šifrēti ar servera puses obligātu šifrēšanu.",
|
||||
"mailcow_apps_detail": "Izmantojiet lietotni mailcow, lai piekļūtu savam pastam, kalendāram, kontaktiem un citām lietām.",
|
||||
"mailcow_panel_detail": "<b>Domēna administrators</b> izveidot, mainīt vai dzēst pastkastes un aliases, mainīt domēnus un lasīt papildu informāciju par saviem piešķirtajiem domēniem.<br>\r\n <b>Pastkastes lietotāji</b> var izveidot ierobežotus laika ierobežojumus (surogātpasta aliases), mainīt paroli un surogātpasta filtru iestatījumus."
|
||||
"mailcow_panel_detail": "<b>Domēna pārvaldītāji</b> izveido, maina vai izdzēš pastkastes un aizstājvārdus, maina domēnus un lasa papildu informāciju par piešķirtajiem domēniem.<br>\n<b>Pastkastes lietotāji</b> var izveidot laikā ierobežotus aizstājvārdus (surogātpasta aizstājvārdus), mainīt savu paroli un surogātpasta atlasīšanas iestatījumus."
|
||||
},
|
||||
"success": {
|
||||
"admin_modified": "Izmaiņas administrātoram ir saglabātas",
|
||||
"alias_added": "Aliasi pievienoti",
|
||||
"alias_domain_removed": "Alias domēns %s tika noņemts",
|
||||
"alias_modified": "Izmaiņas aliasiem %s ir saglabātas",
|
||||
"alias_removed": "Alias %s ir noņemts",
|
||||
"aliasd_added": "Pievients alias domēnam %s",
|
||||
"aliasd_modified": "Izmaiņas aloas domēnam %s ir saglabātas",
|
||||
"alias_added": "Aizstājadrese %s (%d) tika pievienota",
|
||||
"alias_domain_removed": "Aizstājdomēns %s tika noņemts",
|
||||
"alias_modified": "Aizstājadreses izmaiņas %s tika saglabātas",
|
||||
"alias_removed": "Aizstājvārds %s tika noņemts",
|
||||
"aliasd_added": "Pievienots aizstājdomēns %s",
|
||||
"aliasd_modified": "Aizstājdomēna %s izmaiņas tika saglabātas",
|
||||
"app_links": "Saglabāt izmaiņas lietotņu saitēm",
|
||||
"dkim_added": "DKIM atslēga saglabāta",
|
||||
"dkim_removed": "DKIM atslēga %s ir noņemta",
|
||||
@@ -467,7 +476,7 @@
|
||||
"domain_modified": "Izmaiņas domēnam %s ir saglabātas",
|
||||
"domain_removed": "Domēns %s ir noņemts",
|
||||
"eas_reset": "ActiveSync ierīces priekš lietotāja %s tika atiestatītas",
|
||||
"f2b_modified": "Izmaiņas Fail2ban parameteriem ir saglabātas",
|
||||
"f2b_modified": "Fail2ban parametru izmaiņas tika saglabātas",
|
||||
"forwarding_host_added": "Pāradresācijas hosts %s pievienotsd",
|
||||
"forwarding_host_removed": "Pāradresācijas hosts %s noņemts",
|
||||
"item_deleted": "Vērtība %s veiksmīgi dzēsta",
|
||||
@@ -492,7 +501,7 @@
|
||||
"confirm_totp_token": "Lūdzu apstipriniet Jūsu izmaiņas ievadot uzģenerēto tekstu",
|
||||
"delete_tfa": "Atspējot TFA",
|
||||
"disable_tfa": "Atspējot TFA līdz nākamajai veiksmīgai pieteikšanās",
|
||||
"enter_qr_code": "Jūsu TOTP kods, ja Jūsu ierīce nevar noskanēt QR kodus.",
|
||||
"enter_qr_code": "TOTP kods, ja Tava ierīce nevar nolasīt kvadrātkodus",
|
||||
"key_id": "Jūsu YubiKey identifikators",
|
||||
"key_id_totp": "Identifikators Jūsu atslēgai",
|
||||
"none": "Deaktivizēt",
|
||||
@@ -510,24 +519,24 @@
|
||||
"action": "Rīcība",
|
||||
"active": "Aktīvs",
|
||||
"active_sieve": "Aktīvais filtrs",
|
||||
"alias": "Alias",
|
||||
"alias_create_random": "Ģenerēt nejaušā nosaukuma alias",
|
||||
"alias_extend_all": "Pagarināt alias par 1 stundu",
|
||||
"alias": "Aizstājvārds",
|
||||
"alias_create_random": "Izveidot nejaušu aizstājvārdu",
|
||||
"alias_extend_all": "Pagarināt aizstājvārdus par 1 stundu",
|
||||
"alias_full_date": "d.m.Y, H:i:s T",
|
||||
"alias_remove_all": "Noņemt visus alias",
|
||||
"alias_remove_all": "Noņemt visus aizstājvārdus",
|
||||
"alias_select_validity": "Derīguma periods",
|
||||
"alias_time_left": "Laiks atlicis",
|
||||
"alias_valid_until": "Derīgs līdz",
|
||||
"aliases_also_send_as": "Atļauts arī sūtīt kā lietotājam",
|
||||
"aliases_send_as_all": "Nepārbaudīt sūtītāja peikļuvi domēnam/iem un alias domēniem",
|
||||
"aliases_send_as_all": "Nepārbaudīt sūtītāja piekļuvi šiem domēniem un to aizstājdomēniem",
|
||||
"change_password": "Nomainīt paroli",
|
||||
"client_configuration": "Parādīt konfigurācijas piemērus dažādām iekārtām",
|
||||
"client_configuration": "Parādīt konfigurācijas norādes e-pasta klientiem un tālruņiem",
|
||||
"create_syncjob": "Izveidot jaunu sinhronizācijas darbu",
|
||||
"day": "Dienas",
|
||||
"direct_aliases": "Tiešas alias adreses",
|
||||
"direct_aliases_desc": "Tiešie alias tiek ietekmēti no spam filtra un TLS politikas iestatījumiem affected by spam filter and TLS policy settings.",
|
||||
"direct_aliases": "Tiešas aizstājadreses",
|
||||
"direct_aliases_desc": "Tiešās aizstājadreses ir surogātpasta atlasīšanas un TLS nosacījumu iestatījumu ietekmētas.",
|
||||
"eas_reset": "Atiestatīt ActiveSync ierīces kešatmiņu",
|
||||
"eas_reset_help": "Daudzos gadījumos ierīces kešatmiņas atiestatīšana palīdz atjaunot bojāto ActiveSync profilu.<br><b>Uzmanību:</b> Visi elementi tiks atkārtoti ielādēti!",
|
||||
"eas_reset_help": "Daudzos gadījumos ierīces kešatmiņas atiestatīšana palīdz atjaunot bojāto ActiveSync profilu.<br><b>Uzmanību:</b> visi vienumi tiks atkārtoti lejupielādēti!",
|
||||
"eas_reset_now": "Atiestatīt tagad",
|
||||
"edit": "Labot",
|
||||
"encryption": "Šifrēšana",
|
||||
@@ -550,15 +559,15 @@
|
||||
"remove": "Noņemt",
|
||||
"running": "Running",
|
||||
"save_changes": "Saglabāt izmaiņas",
|
||||
"shared_aliases": "Koplietotās alias adreses",
|
||||
"shared_aliases_desc": "Koplietotais alias netiek ietekmēts no lietotāju darbībām. Pielāgots spam filtra iestatījums var būt arhivēts no domēna ietvaros uzstādīta noteikuma no administrātora..",
|
||||
"shared_aliases": "Kopīgotās aizstājadreses",
|
||||
"shared_aliases_desc": "Tādi lietotāja iestatījumi kā surogātpasta atlasīšana vai šifrēšanas nosacījumi neietekmē kopīgotos aizstājvārdus. Atbilstošu surogātpasta atlasi var izveidot tikai pārvaldītājs kā domēnu aptverošu nosacījumu.",
|
||||
"show_sieve_filters": "Parādīt aktīvā lietotāja Sieve filtru",
|
||||
"spam_aliases": "Pagaidu e-pasta alias",
|
||||
"spam_aliases": "Pagaidu e-pasta aizstājvārdi",
|
||||
"spamfilter": "Mēstuļu filtrs",
|
||||
"spamfilter_behavior": "Reitings",
|
||||
"spamfilter_bl": "Melnais saraksts",
|
||||
"spamfilter_bl_desc": "Melajā sarakstā iekļautās adreses vienmēr tiks uzskatītas par mēstulēm.",
|
||||
"spamfilter_default_score": "Noklusētās vērtības:",
|
||||
"spamfilter_bl_desc": "No melnajā sarakstā iekļautajām e-pasta adresēm saņemtās vēstules <b>vienmēr</b> tiks atzīmētas kā mēstules un noraidītas. Noraidītais pasts <b>netiks</b> ievietots karantīnā. Var izmantot aizstājzīmes. Atlasīšana tiek pielietota tikai tiešiem aizstājvārdiem (aizstājvārdiem ar vienu mērķa pastkasti), izņemot visu tverošos aizstājvārdus un pašu pastkasti.",
|
||||
"spamfilter_default_score": "Noklusējuma vērtības",
|
||||
"spamfilter_green": "Zaļš: šī nav mēstule",
|
||||
"spamfilter_hint": "Pirmā vērtība norāda uz zemu \"Spam vērtējumu\" vērtējumu, otra vērtība par \"Augstu spam vērtējumu\".",
|
||||
"spamfilter_red": "Sarkans: Šī vēstule noteikti ir spams un tiek nekavējoties noraidīta",
|
||||
@@ -569,7 +578,7 @@
|
||||
"spamfilter_table_remove": "noņemt",
|
||||
"spamfilter_table_rule": "Noteikums",
|
||||
"spamfilter_wl": "Baltais saraksts",
|
||||
"spamfilter_wl_desc": "Baltajā sarakstā iekļautās adreses nekad netiks klasificētas kā mēstules.",
|
||||
"spamfilter_wl_desc": "No baltā saraksta e-pasta adresēm saņemtās vēstules <b>nekad</b> netiks atzīmētas kā mēstules. Var tikt izmantotas aizstājzīmes. Atlase tiek piemērota tikai tiešiem aizstājvārdiem (aizstājvārdiem ar vienu mērķa pastkasti), izņemot visu tverošos aizstājvārdus un pašu pastkasti.",
|
||||
"spamfilter_yellow": "Dzeltens: šī vēstule visticamāk ir spams un tiks pārvietota uz Junk mapi",
|
||||
"status": "Status",
|
||||
"sync_jobs": "Sinhronizācijas uzdevumi",
|
||||
@@ -588,7 +597,9 @@
|
||||
"waiting": "Waiting",
|
||||
"week": "Nedēļa",
|
||||
"weeks": "Nedēļas",
|
||||
"open_logs": "Atvērt žurnālus"
|
||||
"open_logs": "Atvērt žurnālus",
|
||||
"apple_connection_profile_mailonly": "Šis savienojuma profils iekļauj IMAP un SMTP konfigurācijas parametrus Apple ierīcei.",
|
||||
"pushover_info": "Pašpiegādes paziņojumu iestatījumi attieksies uz visu tīro (ne surogātpasta) pastu, kas piegādāts uz <b>%s</b>, ieskaitot aizstājvārdus (kopīgotus, nekopīgotus, ar birkām)."
|
||||
},
|
||||
"datatables": {
|
||||
"paginate": {
|
||||
@@ -608,6 +619,7 @@
|
||||
},
|
||||
"warning": {
|
||||
"domain_added_sogo_failed": "Domēns pievienots, bet neizdevās pārsāknēt SOGO. Lūgums pārbaudīt servera žurnālus.",
|
||||
"dovecot_restart_failed": "Dovecot neizdevās pārsāknēties. Lūgums pārbaudīt žurnālus."
|
||||
"dovecot_restart_failed": "Dovecot neizdevās pārsāknēties. Lūgums pārbaudīt žurnālus",
|
||||
"is_not_primary_alias": "Izlaists aizstājvārds %s, kas nav galvenais"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -322,5 +322,148 @@
|
||||
"invalid_nexthop": "\"Next hop\"-format er ugyldig",
|
||||
"img_dimensions_exceeded": "Bildet overskriver maksimal bildestørrelse",
|
||||
"img_size_exceeded": "Bildet overskrider maksimal filstørrelse"
|
||||
},
|
||||
"debug": {
|
||||
"logs": "Logger",
|
||||
"update_available": "En oppdatering er tilgjengelig",
|
||||
"service": "Tjeneste",
|
||||
"show_ip": "Vis offentlig IP",
|
||||
"solr_dead": "Solr starter, er deaktivert eller døde",
|
||||
"memory": "Minne",
|
||||
"online_users": "Tilkoblede brukere",
|
||||
"restart_container": "Omstart",
|
||||
"size": "Størrelse",
|
||||
"solr_status": "Solr-status",
|
||||
"started_at": "Startet ved",
|
||||
"started_on": "Startet den",
|
||||
"static_logs": "Statiske logger",
|
||||
"success": "Suksess",
|
||||
"system_containers": "System og kontainere",
|
||||
"timezone": "Tidssone",
|
||||
"uptime": "Oppetid",
|
||||
"no_update_available": "Systemet kjører siste versjon",
|
||||
"update_failed": "Kunne ikke se etter oppdateringer",
|
||||
"username": "Brukernavn",
|
||||
"wip": "Foreløpig under utvikling"
|
||||
},
|
||||
"diagnostics": {
|
||||
"dns_records_24hours": "Vennligst vær oppmerksom på at endringer gjort i DNS kan ta opp til 24 timer før riktig status vises på denne siden. Den er ment som en måte for deg å enkelt se hvordan du kan sette opp DNS-oppføringene dine og se at alle oppføringer er korrekt lagret i DNS.",
|
||||
"cname_from_a": "Verdi hentet fra A/AAAA-oppføring. Dette er støttet så lenge oppføringen peker til riktig ressurs.",
|
||||
"dns_records_docs": "Vennligst også se <a target=\"_blank\" href=\"https://docs.mailcow.email/getstarted/prerequisite-dns\">dokumentasjonen</a>.",
|
||||
"dns_records": "DNS-oppføringer",
|
||||
"dns_records_data": "Korrekte data",
|
||||
"dns_records_name": "Navn",
|
||||
"dns_records_status": "Nåværende status",
|
||||
"dns_records_type": "Type",
|
||||
"optional": "Denne oppføringen er valgfri."
|
||||
},
|
||||
"edit": {
|
||||
"bcc_dest_format": "BCC-destinasjon må være en enkelt, gyldig epostadresse.<br>Hvis du trenger å sende en kopi til flere adresser, opprett et alias og bruk det her.",
|
||||
"pushover_info": "Innstillinger for pushvarslinger vil gjelde alle rene (ikke-spam) eposter levert til <b>%s</b>, inkludert aliaser (delte, ikke-delte, taggede).",
|
||||
"relay_transport_info": "<div class=\"badge fs-6 bg-info\">Info</div> Du kan definere transportmappinger for et spesifikt mål for dette domenet. Hvis dette ikke er definert, blir det gjort et MX-oppslag.",
|
||||
"delete2duplicates": "Slett duplikater på målvert",
|
||||
"description": "Beskrivelse",
|
||||
"disable_login": "Ikke tillat innlogging (innkommende epost blir likevel mottatt)",
|
||||
"domain_admin": "Endre domeneadministrator",
|
||||
"max_mailboxes": "Maks antall mailbokser",
|
||||
"quota_warning_bcc_info": "Advarsler blir sendt som separate kopier til de følgende mottakerne. Emnet vil få lagt til det korresponderende brukernavnet i parantes, for eksempel: <code>Kvotevarsel (user@example.com)</code>.",
|
||||
"domain_footer_skip_replies": "Ignorer bunntekst ved svar på epost",
|
||||
"extended_sender_acl": "Eksterne avsenderadresser",
|
||||
"extended_sender_acl_info": "En DKIM-domenenøkkel bør importeres, hvis tilgjengelig.<br>\n Husk å legge denne serveren til den korresponderende SPF TXT-oppføringen.<br>\n Når et domene eller aliasdomene legges til på denne serveren, og det overlapper med en ekstern adresse, blir den eksterne adressen fjernet.<br>\n Bruk @domain.tld for å tillate sending som *@domain.tld.",
|
||||
"password_repeat": "Bekreft passord (gjenta)",
|
||||
"pushover_title": "Varslingstittel",
|
||||
"pushover_vars": "Når et avsenderfilter ikke er definert, vil alle epostere bli vurdert.<br>Regex-filtre såvel så eksakte avsendersjekker kan bli individuelt definert og vil bli vurdert sekvensielt. De er ikke avhengige av hverandre.<br>Tilgjengelige variabler for tekst og tittel (vennligst observer policyer for databeskyttelse)",
|
||||
"admin": "Endre administrator",
|
||||
"domain_footer_info": "Bunntekst for hele domenet leggese til alle utgående eposter assosiert med en adresse innenfor dette domenet. <br> De følgende variablene kan brukes for bunnteksten:",
|
||||
"domain_footer_info_vars": {
|
||||
"custom": "{= foo =} - Hvis mailboksen har en spesialattributt \"foo\" med verdi \"bar\", vil den vise \"bar\"",
|
||||
"auth_user": "{= auth_user =} - Autentisert brukernavn spesifisert av en MTA",
|
||||
"from_user": "{= from_user =} - Fra brukerdelen av konvolutten, f.eks. for \"moo@mailcow.tld\" vil den returnere \"moo\"",
|
||||
"from_name": "{= from_name =} - Fra-navn fra konvolutten, f.eks. for \"Mailcow <moo@mailcow.tld>\" vil den vise \"Mailcow\"",
|
||||
"from_addr": "{= from_addr =} - Fra adressedelen av konvolutten",
|
||||
"from_domain": "{= from_domain =} - Fra domene-delen av konvolutten"
|
||||
},
|
||||
"mailbox_relayhost_info": "Aktiveres kun for mailboksen og direkte aliaser, overstyrer domene-videresendingsvert.",
|
||||
"mbox_rl_info": "Denne begrensningen gjelder for SASL-innloggingsnavnet, dersom det er likt noen \"from\"-adresser benyttet av den innloggede brukeren. En mailboks-begrensning overstyrer en domene-begrensning.",
|
||||
"allow_from_smtp_info": "La stå tom for å tillate alle avsendere.<br>IPv4/IPv6-adresser og -nettverk.",
|
||||
"domain": "Endre domene",
|
||||
"encryption": "Kryptering",
|
||||
"exclude": "Ekskluder objekter (regex)",
|
||||
"footer_exclude": "Ekskluder fra bunntekst",
|
||||
"gal_info": "GAL inneholder alle objeker i et domene og kan ikke redigeres av noen brukere. Ledig/opptatt-informasjon i SOGo mangler dersom den deaktiveres! <b>Start SOGo på nytt for å aktivere endringene.</b>",
|
||||
"grant_types": "Grant-typer",
|
||||
"hostname": "Vertsnavn",
|
||||
"inactive": "Inaktiv",
|
||||
"kind": "Type",
|
||||
"last_modified": "Sist endret",
|
||||
"lookup_mx": "Målet er et regex-uttrykk for å matche mot MX_navnet (<code>*\\.google\\.com</code> for å route all epost som skal til en MX-server som slutter på google.com, via dette målet)",
|
||||
"mailbox": "Endre mailboks",
|
||||
"mailbox_quota_def": "Standardkvote for mailboks",
|
||||
"max_quota": "Maks kvote pr. mailboks (MiB)",
|
||||
"maxage": "Maksimal alder for meldinger, i dager, som vil hentes fra ekstern<br><small>(0 = ignorer alder)</small>",
|
||||
"maxbytespersecond": "Maks bytes pr. sekund <br><small>(0 = ubegrenset)</small>",
|
||||
"pushover_sender_array": "Bare vurder de følgende avsenderadressene <small>(komma-separert)</small>",
|
||||
"pushover_sender_regex": "Vurder følgende avsender-regex",
|
||||
"pushover_text": "Varslingstekst",
|
||||
"pushover_sound": "Lyd",
|
||||
"pushover_verify": "Bekreft identifikasjon",
|
||||
"quota_mb": "Kvote (MiB)",
|
||||
"quota_warning_bcc": "Kvotevarsling BCC",
|
||||
"ratelimit": "Mengdebegrensning",
|
||||
"domain_footer": "Bunntekst for hele domenet",
|
||||
"private_comment": "Privat kommentar",
|
||||
"public_comment": "Offentlig kommentar",
|
||||
"client_id": "Klient-ID",
|
||||
"full_name": "Fullt navn",
|
||||
"gal": "Global adresseliste",
|
||||
"max_aliases": "Maks. antall aliaser",
|
||||
"mins_interval": "Intervall (min)",
|
||||
"multiple_bookings": "Flere bookinger",
|
||||
"none_inherit": "Ingen / arve",
|
||||
"acl": "ACL (rettighet)",
|
||||
"active": "Aktiv",
|
||||
"advanced_settings": "Avanserte innstillinger",
|
||||
"alias": "Endre alias",
|
||||
"allow_from_smtp": "Tillat kun disse IPene å bruke <b>SMTP</b>",
|
||||
"allowed_protocols": "Tillatte protokoller",
|
||||
"app_name": "Appnavn",
|
||||
"app_passwd": "App-passord",
|
||||
"app_passwd_protocols": "Tillatte protokoller for app-passord",
|
||||
"automap": "Prøv å automatisk mappe opp mapper (\"Sent items\", \"Sent\" => \"Sendt\" etc.)",
|
||||
"backup_mx_options": "Videresendingsalternativer",
|
||||
"client_secret": "Klient-hemmelighet",
|
||||
"comment_info": "En privat kommentar er ikke synlig for brukeren, mens en offentlig kommentar vises som et tooltip når man holder muspekeren over det",
|
||||
"created_on": "Opprettet den",
|
||||
"custom_attributes": "Valgfrie attributter",
|
||||
"delete1": "Slett fra kilde når fullført",
|
||||
"delete2": "Slett meldinger på målvert som ikke finnes på kildeverten",
|
||||
"delete_ays": "Vennligst bekreft slettingen.",
|
||||
"domain_footer_html": "HTML-bunntekst",
|
||||
"domain_footer_plain": "PLAIN-bunntekst",
|
||||
"domain_quota": "Domenekvote",
|
||||
"domains": "Domener",
|
||||
"dont_check_sender_acl": "Deaktivere sendersjekk for domene %s (+ aliasdomener)",
|
||||
"edit_alias_domain": "Endre aliasdomene",
|
||||
"force_pw_update": "Tving endring av passord ved neste innlogging",
|
||||
"force_pw_update_info": "Denne brukeren vil bare kunne logge inn på %s. App-passord kan fremdeles brukes.",
|
||||
"generate": "generer",
|
||||
"nexthop": "Neste hopp",
|
||||
"password": "Passord",
|
||||
"previous": "Forrige side",
|
||||
"pushover": "Pushover",
|
||||
"pushover_evaluate_x_prio": "Eskaler mail med høy prioritet [<code>X-Priority: 1</code>]",
|
||||
"pushover_only_x_prio": "Bare vurder epost med høy prioritet [<code>X-Priority: 1</code>]",
|
||||
"redirect_uri": "Omdirigerings-/tilbakekallings-URL",
|
||||
"relay_all": "Videresend alle mottakere",
|
||||
"relay_all_info": "↪ Hvis du velger å <b>ikke</b> videresende alle mottakkere, så må du legge til en (\"blind\") mailboks for hver eneste mottaker det skal videresendes for.",
|
||||
"relay_domain": "Videresend dette domenet",
|
||||
"relay_unknown_only": "Videresend kun ikke-eksisterende mailbokser. Eksisterende mailbokser vil bli levert lokalt.",
|
||||
"relayhost": "Avsender-avhengige transportmetoder",
|
||||
"remove": "Fjern",
|
||||
"resource": "Ressurs",
|
||||
"save": "Lagre endringer",
|
||||
"scope": "Omfang",
|
||||
"sender_acl": "Tillat å sende som",
|
||||
"sender_acl_disabled": "<span class=\"badge fs-6 bg-danger\">Avsender-sjekk er deaktivert</span>"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -185,7 +185,7 @@
|
||||
"filter_table": "Filtertabel",
|
||||
"forwarding_hosts": "Forwarding hosts",
|
||||
"forwarding_hosts_add_hint": "Het is mogelijk om IPv4- of IPv6-adressen, netwerken in CIDR-notatie, hostnames (worden omgezet naar IP-adressen) of domeinnamen (worden tevens omgezet naar IP-adressen of, bij gebrek daaraan, MX-records) op te geven.",
|
||||
"forwarding_hosts_hint": "Inkomende berichten worden onvoorwaardelijk geaccepteerd vanaf iedere host hieronder vermeld. Deze hosts worden hierdoor niet gecontroleerd op DNSBLs, en zullen de greylisting omzeilen. Spam wordt daarentegen zoals gebruikelijk in de spamfolder geplaatst. Dit wordt vaak gebruikt om mailservers te specificeren die forwarden naar deze Mailcow-server.",
|
||||
"forwarding_hosts_hint": "Inkomende berichten worden onvoorwaardelijk geaccepteerd vanaf iedere host hieronder vermeld. Deze hosts worden hierdoor niet gecontroleerd op DNSBLs, en zullen de greylisting omzeilen. Spam wordt daarentegen zoals gebruikelijk in de spamfolder geplaatst. Dit wordt vaak gebruikt om mailservers te specificeren die alles doorsturen naar deze Mailcow-server.",
|
||||
"from": "Afzender",
|
||||
"generate": "genereer",
|
||||
"guid": "Identificatienummer - GUID",
|
||||
@@ -295,7 +295,7 @@
|
||||
"to_top": "Naar boven",
|
||||
"transport_dest_format": "Voorbeeld: example.org, .example.org, *, mailbox@example.org (meerdere waarden zijn kommagescheiden)",
|
||||
"transport_maps": "Transport-maps",
|
||||
"transports_hint": "→ Een transport-map wordt boven een afzendergebonden transport-map verkozen.<br>→ Het uitgaande versleutelingsbeleid van individuele gebruikers wordt genegeerd en kan uitsluitend worden gehandhaafd doormiddel van globaal versleutelingsbeleid.<br>→ De transportservice is altijd \"smtp:\" en zal daarom met TLS proberen te verbinden. Wrapped TLS (SMTPS) wordt niet ondersteund.<br>→ Adressen overeenkomend met \"/localhost$/\" zullen altijd via \"local:\" getransporteerd worden, hierdoor zullen \"*\"-bestemmingen niet van toepassing zijn op deze adressen.<br>→ Om de aanmeldingsgegevens van een (voorbeeld) nexthop \"[host]:25\" te bepalen, zoekt Postfix <b>altijd</b> naar \"nexthop\" voodat er wordt gekeken naar \"[nexthop]:25\". Dit maakt het onmogelijk om \"nexthop\" en \"[nexthop]:25\" tegelijkertijd te gebruiken.",
|
||||
"transports_hint": "→ Een transport-map wordt boven een afzendergebonden transport-map verkozen.<br>→ Het uitgaande versleutelingsbeleid van individuele gebruikers wordt genegeerd en kan uitsluitend worden gehandhaafd door middel van globaal versleutelingsbeleid.<br>→ De transportservice is altijd \"smtp:\" en zal daarom met TLS proberen te verbinden. Wrapped TLS (SMTPS) wordt niet ondersteund.<br>→ Adressen overeenkomend met \"/localhost$/\" zullen altijd via \"local:\" getransporteerd worden, hierdoor zullen \"*\"-bestemmingen niet van toepassing zijn op deze adressen.<br>→ Om de aanmeldingsgegevens van een (voorbeeld) nexthop \"[host]:25\" te bepalen, zoekt Postfix <b>altijd</b> naar \"nexthop\" voodat er wordt gekeken naar \"[nexthop]:25\". Dit maakt het onmogelijk om \"nexthop\" en \"[nexthop]:25\" tegelijkertijd te gebruiken.",
|
||||
"ui_footer": "Footer (HTML toegestaan)",
|
||||
"ui_header_announcement": "Aankondigingen",
|
||||
"ui_header_announcement_active": "Activeer aankondiging",
|
||||
@@ -473,7 +473,7 @@
|
||||
"history_all_servers": "Geschiedenis (alle servers)",
|
||||
"in_memory_logs": "Geheugenlogs",
|
||||
"jvm_memory_solr": "JVM-geheugengebruik",
|
||||
"log_info": "<p>Mailcows <b>geheugenlogs</b> worden elke minuut afgesneden naar maximaal %d regels (LOG_LINES) om de stabiliteit te garanderen.<br>Geheugenlogs zijn niet bedoeld om bewaard te blijven. Alle applicaties die geheugenlogs schrijven worden ook naar het Docker-proces gelogd.<br>De geheugenlogs kunnen gebruikt worden voor het oplossen van problemen met bepaalde containers.</p><p><b>Externe logs</b> worden verzameld doormiddel van de API van deze applicaties.</p><p><b>Statische logs</b> zijn activiteitenlogs die niet naar het Docker-proces worden gelogd, maar wel bewaard moeten blijven (uitgezonderd API-logs).</p>",
|
||||
"log_info": "<p>Mailcows <b>geheugenlogs</b> worden elke minuut afgesneden naar maximaal %d regels (LOG_LINES) om de stabiliteit te garanderen.<br>Geheugenlogs zijn niet bedoeld om bewaard te blijven. Alle applicaties die geheugenlogs schrijven worden ook naar het Docker-proces gelogd.<br>De geheugenlogs kunnen gebruikt worden voor het oplossen van problemen met bepaalde containers.</p><p><b>Externe logs</b> worden verzameld door middel van de API van deze applicaties.</p><p><b>Statische logs</b> zijn activiteitenlogs die niet naar het Docker-proces worden gelogd, maar wel bewaard moeten blijven (uitgezonderd API-logs).</p>",
|
||||
"logs": "Logs",
|
||||
"restart_container": "Herstart",
|
||||
"solr_dead": "Solr is uitgeschakeld, uitgevallen of nog bezig met opstarten.",
|
||||
@@ -684,7 +684,7 @@
|
||||
"add_tls_policy_map": "Voeg versleutelingsbeleid toe",
|
||||
"address_rewriting": "Adresomleidingen",
|
||||
"alias": "Alias",
|
||||
"alias_domain_alias_hint": "Aliassen worden <b>niet</b> automatisch toegepast op domeinaliassen. Aliasadres <code>alias@domein</code> dekt het adres <code>alias@alias-domein</code> <b>niet</b> (waarbij \"alias-domein\" een aliasdomein is voor \"domein\").<br>Gebruik een filter om mail te forwarden naar een externe mailbox (zie het tabje \"Filters\" of gebruik SOGo -> Doorsturen).",
|
||||
"alias_domain_alias_hint": "Aliassen worden <b>niet</b> automatisch toegepast op domeinaliassen. Aliasadres <code>alias@domein</code> dekt het adres <code>alias@alias-domein</code> <b>niet</b> (waarbij \"alias-domein\" een aliasdomein is voor \"domein\").<br>Gebruik een filter om mail door te sturen naar een externe mailbox (zie het tabje \"Filters\" of gebruik SOGo -> Doorsturen).",
|
||||
"alias_domain_backupmx": "Aliasdomein inactief voor geforward domein",
|
||||
"aliases": "Aliassen",
|
||||
"allow_from_smtp": "Sta enkel de volgende IP-adressen toe voor <b>SMTP</b>",
|
||||
@@ -694,7 +694,7 @@
|
||||
"bcc": "BCC",
|
||||
"bcc_destination": "BCC-bestemming",
|
||||
"bcc_destinations": "BCC-bestemmingen",
|
||||
"bcc_info": "BCC-maps worden gebruikt om kopieën van alle berichten naar een ander adres te forwarden.<br>Wees er van bewust dat er geen melding wordt gedaan van een mislukte aflevering.",
|
||||
"bcc_info": "BCC-maps worden gebruikt om kopieën van alle berichten naar een ander adres door te sturen.<br>Wees er van bewust dat er geen melding wordt gedaan van een mislukte aflevering.",
|
||||
"bcc_local_dest": "Lokale bestemming",
|
||||
"bcc_map": "BCC-map",
|
||||
"bcc_map_type": "BCC-type",
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
"domain_quota_m": "Total de espaço por domínio (MiB):",
|
||||
"full_name": "Nome:",
|
||||
"mailbox_quota_m": "Máximo espaço por conta (MiB):",
|
||||
"mailbox_username": "Usuário (primeira parte do endereço de email):",
|
||||
"mailbox_username": "Utilizador (primeira parte do endereço de email):",
|
||||
"max_aliases": "Máximo de apelidos:",
|
||||
"max_mailboxes": "Máximo de contas:",
|
||||
"password": "Senha:",
|
||||
@@ -96,7 +96,7 @@
|
||||
"sender_acl_invalid": "Campo Sender ACL é inválido",
|
||||
"target_domain_invalid": "O endereço de Domínio Destino é inválido",
|
||||
"targetd_not_found": "Domínio de Destino não encontrado",
|
||||
"username_invalid": "Nome de usuário inválido",
|
||||
"username_invalid": "Nome de utilizador inválido",
|
||||
"validity_missing": "Você deve definir um período de validade"
|
||||
},
|
||||
"edit": {
|
||||
@@ -138,7 +138,7 @@
|
||||
"administration": "Administração",
|
||||
"email": "E-Mail",
|
||||
"mailcow_config": "Configuração",
|
||||
"user_settings": "Configurações do usuário"
|
||||
"user_settings": "Configurações do utilizador"
|
||||
},
|
||||
"info": {
|
||||
"no_action": "Nenhuma ação foi definida"
|
||||
@@ -147,7 +147,7 @@
|
||||
"delayed": "Sua entrada será atrasada por %s segundos.",
|
||||
"login": "Entrar",
|
||||
"password": "Senha",
|
||||
"username": "Usuário"
|
||||
"username": "Utilizador"
|
||||
},
|
||||
"mailbox": {
|
||||
"action": "Ação",
|
||||
@@ -186,7 +186,7 @@
|
||||
"target_domain": "Domínio Destino",
|
||||
"tls_enforce_in": "Forçar TLS na entrada",
|
||||
"tls_enforce_out": "Forçar TLS na saída",
|
||||
"username": "Usuário"
|
||||
"username": "Utilizador"
|
||||
},
|
||||
"quarantine": {
|
||||
"action": "Ação",
|
||||
@@ -199,7 +199,7 @@
|
||||
"help": "Mostrar/Ocultar painel de ajuda",
|
||||
"imap_smtp_server_auth_info": "Utilize o endereço de email completo com o método de autentucação PLAIN.<br>\r\nOs dados de login serão encryptados pelo servidor.",
|
||||
"mailcow_apps_detail": "Use um mailcow app para acessar seus emails, calendário, contatos e outras informações.",
|
||||
"mailcow_panel_detail": "<b>Administradores:</b> podem criar, alterar ou apagar contas e apelidos , alterar domínios e outras informações de seus domínios atribuídos.<br>\r\n\t<b>Usuários:</b> podem criar apelidos por tempo determinado , alterar senha e configuração do nível do filtro de spam."
|
||||
"mailcow_panel_detail": "<b>Administradores:</b> podem criar, alterar ou apagar contas e apelidos , alterar domínios e outras informações de seus domínios atribuídos.<br>\r\n\t<b>utilizadors:</b> podem criar apelidos por tempo determinado , alterar senha e configuração do nível do filtro de spam."
|
||||
},
|
||||
"success": {
|
||||
"admin_modified": "Administrador alterado com sucesso",
|
||||
@@ -267,7 +267,7 @@
|
||||
"tls_enforce_out": "Forçar TLS na saída",
|
||||
"tls_policy": "Regras de Encryptação",
|
||||
"tls_policy_warning": "<strong>Aviso:</strong> Se você selecionar para forçar o envio encryptado , alguns emails poderão ser rejeitados.<br>Mensages que não satisfizerem as politicas dos outros servidores serão rejeitadas definitivamente.",
|
||||
"user_settings": "Configurações do usuário",
|
||||
"user_settings": "Configurações do utilizador",
|
||||
"username": "Administrador",
|
||||
"week": "Semana",
|
||||
"weeks": "Semanas"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"acl": {
|
||||
"alias_domains": "Создание псевдонимов домена",
|
||||
"app_passwds": "Пароли приложений",
|
||||
"bcc_maps": "Правила BBC",
|
||||
"bcc_maps": "Правила BCC",
|
||||
"delimiter_action": "Обработка тегированной почты",
|
||||
"domain_desc": "Изменение описания домена",
|
||||
"domain_relayhost": "Изменение промежуточных узлов для домена",
|
||||
@@ -389,7 +389,7 @@
|
||||
"imagick_exception": "Ошибка в Imagick при чтении изображения",
|
||||
"img_invalid": "Невозможно проверить файл изображения",
|
||||
"img_tmp_missing": "Невозможно проверить файл изображения: временный файл не найден",
|
||||
"invalid_bcc_map_type": "Неверный тип правила BBC",
|
||||
"invalid_bcc_map_type": "Неверный тип правила BCC",
|
||||
"invalid_destination": "Назначение \"%s\" указано неверно",
|
||||
"invalid_filter_type": "Неверный тип фильтра",
|
||||
"invalid_host": "Хост %s указан неверно",
|
||||
@@ -523,7 +523,7 @@
|
||||
"app_passwd": "Пароль приложения",
|
||||
"automap": "Автоматическое слияние папок (\"Sent items\", \"Sent\" => \"Sent\" etc.)",
|
||||
"backup_mx_options": "Параметры резервного копирования MX",
|
||||
"bcc_dest_format": "Назначением для правила BBC должен быть единственный действительный адрес электронной почты.",
|
||||
"bcc_dest_format": "Назначением для правила BCC должен быть единственный действительный адрес электронной почты.",
|
||||
"client_id": "ID клиента",
|
||||
"client_secret": "Секретный ключ пользователя",
|
||||
"comment_info": "Приватный комментарий не виден пользователям, а публичный - отображается рядом с псевдонимом в личном кабинете пользователя",
|
||||
@@ -700,7 +700,7 @@
|
||||
"add": "Добавить",
|
||||
"add_alias": "Добавить псевдоним",
|
||||
"add_alias_expand": "Скопировать псевдонимы на псевдонимы домена",
|
||||
"add_bcc_entry": "Добавить правило BBC",
|
||||
"add_bcc_entry": "Добавить правило BCC",
|
||||
"add_domain": "Добавить домен",
|
||||
"add_domain_alias": "Добавить псевдоним домена",
|
||||
"add_domain_record_first": "Пожалуйста, сначала добавьте домен",
|
||||
@@ -719,14 +719,14 @@
|
||||
"allow_from_smtp_info": "Укажите IPv4/IPv6 адреса и/или подсети.<br>Оставьте поле пустым, чтобы разрешить отправку с любых адресов.",
|
||||
"allowed_protocols": "Разрешенные протоколы",
|
||||
"backup_mx": "Резервный MX",
|
||||
"bcc": "Правила BBC",
|
||||
"bcc": "Правила BCC",
|
||||
"bcc_destination": "Назначение BCC",
|
||||
"bcc_destinations": "Назначение BCC",
|
||||
"bcc_info": "Правила BCC используются для скрытой пересылки копий всех сообщений на другой адрес. Правило типа \"получатель\" используется, когда локальный получатель выступает в качестве получателя почты. Правило типа \"отправитель\" соответствуют тому же принципу. Локальный домен не будут проинформированы о неудачной доставке.",
|
||||
"bcc_local_dest": "Локальный домен",
|
||||
"bcc_map": "Правила BBC",
|
||||
"bcc_map": "Правила BCC",
|
||||
"bcc_map_type": "Тип BCC",
|
||||
"bcc_maps": "Правила BBC",
|
||||
"bcc_maps": "Правила BCC",
|
||||
"bcc_rcpt_map": "Получатель",
|
||||
"bcc_sender_map": "Отправитель",
|
||||
"bcc_to_rcpt": "Переключиться на тип \"получатель\"",
|
||||
@@ -1224,6 +1224,8 @@
|
||||
"session_ua": "Неверный токен формы: ошибка проверки User-Agent"
|
||||
},
|
||||
"datatables": {
|
||||
"collapse_all": "Свернуть все",
|
||||
"expand_all": "Развернуть все",
|
||||
"infoPostFix": ""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,7 +107,8 @@
|
||||
"post_domain_add": "SOGo container \"sogo-mailcow\" mora biti ponovno zagnan po dodajanju nove domene!<br><br>Dodatno se mora preveriti DNS konfiguracija domene. Ko je DNS konfiguracija domene odobrena, ponovno zaženite \"acme-mailcow\" za samodejno generiranje certifikatov za novo domeno (autoconfig.<domain>, autodiscover.<domain>).<br>Ta korak je opcijski in se ponovno poskuša vsakih 24 ur.",
|
||||
"relay_transport_info": "<div class=\"badge fs-6 bg-info\">Info</div> Definirate lahko preslikave transportov za cilj po meri za to domeno. Če ni nastavljena, se ustvari MX poizvedba.",
|
||||
"syncjob_hint": "Pozor! Gesla se morajo shraniti v plain-text!",
|
||||
"timeout2": "Časovna omejitev za povezavo do lokalnega gostitelja"
|
||||
"timeout2": "Časovna omejitev za povezavo do lokalnega gostitelja",
|
||||
"dry": "Simuliraj sinhronizacijo"
|
||||
},
|
||||
"admin": {
|
||||
"access": "Dostop",
|
||||
@@ -347,7 +348,10 @@
|
||||
"logo_dark_label": "Za temni način",
|
||||
"cors_settings": "Nastavitve CORS",
|
||||
"allowed_methods": "Dovoljene metode za upravljanje dostopa",
|
||||
"allowed_origins": "Upravljanje-dostopa-Dovoljeni-Viri"
|
||||
"allowed_origins": "Upravljanje-dostopa-Dovoljeni-Viri",
|
||||
"copy_to_clipboard": "Besedilo kopirano v odložišče!",
|
||||
"f2b_manage_external": "Zunanje upravljanje Fail2Ban",
|
||||
"f2b_manage_external_info": "Fail2ban bo še vedno vzdrževal seznam prepovedi, vendar ne bo aktivno nastavil pravil za blokiranje prometa. Uporabite spodnji ustvarjeni seznam prepovedi za zunanje blokiranje prometa."
|
||||
},
|
||||
"danger": {
|
||||
"alias_goto_identical": "Alias in goto naslov morata biti identična",
|
||||
@@ -476,7 +480,9 @@
|
||||
"temp_error": "Začasna napaka",
|
||||
"cors_invalid_method": "Navedena neveljavna Allow metoda",
|
||||
"cors_invalid_origin": "Naveden neveljaven Allow-Origin",
|
||||
"invalid_recipient_map_new": "Naveden neveljaven nov prejemnik: %s"
|
||||
"invalid_recipient_map_new": "Naveden neveljaven nov prejemnik: %s",
|
||||
"img_dimensions_exceeded": "Slika presega največje dovoljene dimenzije",
|
||||
"img_size_exceeded": "Slika presega največjo dovoljeno velikost datoteke"
|
||||
},
|
||||
"debug": {
|
||||
"containers_info": "Informacije o vsebniku (containerju)",
|
||||
@@ -511,7 +517,13 @@
|
||||
"no_update_available": "Sistem je na najnovejši verziji",
|
||||
"update_failed": "Ni mogoče preveriti za posodobitve",
|
||||
"username": "Uporabniško ime",
|
||||
"wip": "Trenutno v delu"
|
||||
"wip": "Trenutno v delu",
|
||||
"log_info": "<p>mailcow <b>in-memory dnevniki</b> se zbirajo v Redis seznamih in se vsako minuto omejijo na LOG_LINES (%d) da se zmanjša obremenitev.\n <br>In-memory dnevniki niso namenjeni trajnemu shranjevanju. Vse aplikacije, ki beležijo dnevnike in-memory, tudi beležijo v Docker daemon in posledično v privzeti gonilnik za dnevnik.\n <br>In-memory dnevniki se naj uporabljajo za odpravljanje manjših napak s containerji.</p>\n <p><b>Eksterni dnevniki</b> se zbirajo preko API-ja posamezne aplikacije.</p>\n <p><b>Statični dnevniki</b> so večinoma dnevniki aktivnosti, ki se ne beležijo v Dockerd, a jih je vseeno treba hraniti (razen API dnevnikov).</p>",
|
||||
"login_time": "Čas",
|
||||
"logs": "Dnevniki",
|
||||
"memory": "Spomin",
|
||||
"online_users": "Prijavljeni uporabniki",
|
||||
"restart_container": "Ponovno zaženi"
|
||||
},
|
||||
"datatables": {
|
||||
"infoFiltered": "(filtrirano od _MAX_ skupaj zapisov)",
|
||||
@@ -551,6 +563,98 @@
|
||||
},
|
||||
"edit": {
|
||||
"acl": "ACL (Dovoljenje)",
|
||||
"active": "Aktivno"
|
||||
"active": "Aktivno",
|
||||
"allow_from_smtp": "Dovoli samo tem IP naslovom da uporabijo <b>SMTP</b>",
|
||||
"bcc_dest_format": "Cilj BCC mora biti en veljaven email naslov.<br>Če morate poslati kopijo na več naslovov, ustvarite alias in ga uporabite tukaj.",
|
||||
"automap": "Poskušaj samodejno preslikati mape (\"Sent items\", \"Sent\" => \"Poslano\" ipd.)",
|
||||
"admin": "Uredi skrbnika",
|
||||
"domain_footer_info_vars": {
|
||||
"custom": "{= foo =} - Če ima poštni predal atribut po meri \"foo\" z vrednostjo \"bar\", spremenljivka vrne \"bar\"",
|
||||
"auth_user": "{= auth_user =} - Prijavljeno uporabniško ime, ki ga določi MTA",
|
||||
"from_user": "{= from_user =} - leva stran email naslova uporabnika, npr. za \"moo@mailcow.tld\" vrne \"moo\"",
|
||||
"from_name": "{= from_name =} - Prikazno ime, npr. za \"Mailcow <moo@mailcow.tld>\" vrne \"Mailcow\"",
|
||||
"from_addr": "{= from_addr =} - e-poštni naslov \"Od\"",
|
||||
"from_domain": "{= from_domain =} - domena e-poštnega naslova \"Od\""
|
||||
},
|
||||
"dont_check_sender_acl": "Onemogoči kontrolo pošiljatelja za domeno %s (+ alias domene)",
|
||||
"pushover_title": "Naslov obvestila",
|
||||
"domains": "Domene",
|
||||
"extended_sender_acl_info": "Če je DKIM domenski ključ na voljo, ga uvozite.<br>\n Ne pozabite dodati ta strežnik k ustreznemu SPF TXT zapisu.<br>\n Kadar koli je domena ali alias domena dodana k tem strežniku, ki se prekriva z zunanjim naslovom, je zunanji naslov odstranjen.<br>\n uporabite @domain.tld da dovolite pošiljanje kot *@domain.tld.",
|
||||
"lookup_mx": "Cilj je regular expression za ujemanje MX zapisov (<code>.*\\.google\\.com</code> za usmeritev vse pošte na MX, ki se konča z google.com, preko tega skoka)",
|
||||
"maxbytespersecond": "Največ bytov na sekundo <br><small>(0 = neomejeno)</small>",
|
||||
"pushover_sender_array": "Upoštevaj samo sledeče e-poštne naslove pošiljateljev <small>(ločeni z vejico)</small>",
|
||||
"mbox_rl_info": "Ta omejitev velja za SASL uporabniško ime, preverja se ujemanje s katerim koli \"from\" naslovom, ki ga uporablja prijavljeni uporabnik. Omejitev pošiljanja za poštni predal preglasi pravilo omejitve za domeno.",
|
||||
"kind": "Tip",
|
||||
"client_secret": "Client secret",
|
||||
"comment_info": "Zasebni komentar ni viden uporabniku, javni komentar pa je viden kot tooltip v uporabnikovem pregledu.",
|
||||
"created_on": "Ustvarjeno",
|
||||
"custom_attributes": "Atributi po meri",
|
||||
"delete1": "Izbriši na viru, ko je končano",
|
||||
"delete2": "Izbriši sporočila na cilju, ki ne obstajajo na viru",
|
||||
"delete2duplicates": "Izbriši dvojnike na cilju",
|
||||
"delete_ays": "Prosim potrdite proces izbrisa.",
|
||||
"description": "Opis",
|
||||
"disable_login": "Onemogoči prijavo (dohodna pošta je še vedno sprejeta)",
|
||||
"domain": "Uredi domeno",
|
||||
"domain_admin": "Uredi domenskega skrbnika",
|
||||
"domain_footer": "Noga za celo domeno",
|
||||
"domain_footer_html": "HTML noga",
|
||||
"pushover_vars": "Če ni definiran noben filter pošiljatelja, bodo upoštevana vsa sporočila.<br>Regex filtre in natančna preverjanja pošiljateljev je mogoče definirati posamezno in bodo obravnavani v nadaljevanju. Niso odvisni drug od drugega.<br>Uporabne spremenljivke za besedilo in naslov (prosimo, upoštevajte politike varstva podatkov)",
|
||||
"pushover_verify": "Preveri poverilnice",
|
||||
"quota_mb": "Omejitev (MiB)",
|
||||
"quota_warning_bcc": "BCC za sporočilo z opozorilom omejitve",
|
||||
"quota_warning_bcc_info": "Opozorila bodo poslana kot ločene kopije sledečim prejemnikom. K naslovu sporočila bo dodano uporabniško ime v oklepajih, npr. <code>Opozorilo omejitve (user@example.com)</code>",
|
||||
"ratelimit": "Omejitev pošiljanja",
|
||||
"advanced_settings": "Napredne nastavitve",
|
||||
"allow_from_smtp_info": "Pustite prazno da dovolite vse pošiljatelje.<br>IPv4/IPv6 naslovi in omrežja.",
|
||||
"allowed_protocols": "Dovoljeni protokoli",
|
||||
"app_name": "Ime aplikacije",
|
||||
"app_passwd": "Geslo aplikacije",
|
||||
"app_passwd_protocols": "Dovoljeni protokoli za geslo aplikacije",
|
||||
"backup_mx_options": "Možnosti posredovanja (relay)",
|
||||
"client_id": "Client ID",
|
||||
"domain_footer_info": "Noge za celo domeno so dodane k vsem izhodnim e-poštnim sporočilom v tej domeni.<br> V nogi se lahko uporabijo sledeče spremenljivke:",
|
||||
"domain_footer_plain": "PLAIN noga",
|
||||
"domain_footer_skip_replies": "Ne dodajaj noge v odgovorih na e-poštna sporočila",
|
||||
"domain_quota": "Omejitev (kvota) domene",
|
||||
"edit_alias_domain": "Uredi alias domeno",
|
||||
"exclude": "Izključi objekte (regex)",
|
||||
"extended_sender_acl": "Naslovi zunanjih pošiljateljev",
|
||||
"force_pw_update": "Obvezna zamenjava gesla ob naslednji prijavi",
|
||||
"force_pw_update_info": "Ta uporabnik se bo lahko prijavil samo v %s. Gesla aplikacij ostajajo v rabi.",
|
||||
"footer_exclude": "Izključi iz noge",
|
||||
"full_name": "Polno ime",
|
||||
"gal": "Globalni seznam naslovov (GAL)",
|
||||
"gal_info": "GAL vsebuje vse objekte v domeni in jih uporabniki ne morejo urejati. Če je onemogočeno, ni podatkov o o zasedenosti objekta! <b>Ponovno zaženite SOGo za uveljavitev sprememb.</b>",
|
||||
"generate": "generiraj",
|
||||
"grant_types": "Vrste dovoljenj",
|
||||
"hostname": "Ime gostitelja",
|
||||
"inactive": "Neaktivno",
|
||||
"last_modified": "Nazadnje spremenjeno",
|
||||
"mailbox": "Uredi poštni predal",
|
||||
"mailbox_quota_def": "Privzeta omejitev/kvota za poštni predal",
|
||||
"mailbox_relayhost_info": "Velja samo za poštni predal in neposredne aliase. Ne prepiše domenskega relay gostitelja.",
|
||||
"max_aliases": "Največ aliasov",
|
||||
"max_mailboxes": "Največ možnih poštnih predalov",
|
||||
"max_quota": "Največja omejitev/kvota na poštni predal (MiB)",
|
||||
"maxage": "Največja starost sporočil (v dnevih), po katerih bo poizvedeno iz oddaljenega vira <br><small>(0 = ne omejuj)</small>",
|
||||
"mins_interval": "Interval (min)",
|
||||
"multiple_bookings": "Več rezervacij",
|
||||
"none_inherit": "Brez / podeduj",
|
||||
"nexthop": "Naslednji skok",
|
||||
"password": "Geslo",
|
||||
"password_repeat": "Potrditev gesla (ponovite)",
|
||||
"previous": "Prejšnja stran",
|
||||
"private_comment": "Zasebni komentar",
|
||||
"public_comment": "Javni komentar",
|
||||
"pushover": "Pushover",
|
||||
"pushover_evaluate_x_prio": "Eskaliraj visoko prednostno pošto [<code>X-Priority: 1</code>]",
|
||||
"pushover_info": "Nastavitve potisnih obvestil bodo veljala za vsa čisto (ne spam) elektronsko pošto dostavljeno v <b>%s</b> vključno z aliasi (deljeni, nedeljeni, označeni)",
|
||||
"pushover_only_x_prio": "Upoštevaj samo pošto z visoko prioriteto [<code>X-Priority: 1</code>]",
|
||||
"pushover_sender_regex": "Upoštevaj sledeči regex za pošiljatelja",
|
||||
"pushover_text": "Besedilo obvestila",
|
||||
"pushover_sound": "Zvok",
|
||||
"encryption": "Šifriranje",
|
||||
"alias": "Uredi alias"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
"exclude": "Exkludera objekt (regex-filter)",
|
||||
"full_name": "Fullständiga namn",
|
||||
"gal": "Global adressbok",
|
||||
"gal_info": "Den global adressboken innehåller alla objekt i en domän och kan inte redigeras av någon användare. Informationen om tillgänglighet i SOGo är endast synlig när den globala adressboken är påslagen. <b>Starta om SOGo för att tillämpa ändringar.</b>",
|
||||
"gal_info": "Den global adressboken innehåller alla objekt i en domän och kan inte redigeras av någon användare. Informationen om tillgänglighet i SOGo är endast synlig när den globala adressboken är påslagen. <b>Starta om SOGo för att tillämpa ändringar.</b>",
|
||||
"generate": "generera",
|
||||
"goto_ham": "Markera detta som en <span class=\"text-success\"><b>felaktig spam-registrering</b>, detta kommer förhindra liknande fel i framtiden</span>",
|
||||
"goto_null": "Kasta e-postmeddelanande omedelbart",
|
||||
|
||||
@@ -391,7 +391,7 @@
|
||||
"last_key": "Останній ключ не можна видалити, натомість вимкніть TFA.",
|
||||
"login_failed": "Введено неправильний логін або пароль",
|
||||
"mailbox_invalid": "Неприпустима адреса поштового акаунту",
|
||||
"mailbox_quota_left_exceeded": "Недостатньо вільного місця (місця залишилося: %d МіБ)",
|
||||
"mailbox_quota_left_exceeded": "Недостатньо вільного місця (залишилося: %d МіБ)",
|
||||
"malformed_username": "Некоректне ім'я користувача",
|
||||
"map_content_empty": "Зміст правила не може бути порожнім",
|
||||
"max_alias_exceeded": "Перевищено максимальну кількість псевдонімів",
|
||||
@@ -478,7 +478,8 @@
|
||||
"extended_sender_acl_denied": "відсутній ACL для встановлення зовнішніх адрес відправників",
|
||||
"template_exists": "Шаблон %s вже існує",
|
||||
"template_id_invalid": "Ідентифікатор шаблону %s недійсний",
|
||||
"template_name_invalid": "Ім'я шаблону невірне"
|
||||
"template_name_invalid": "Ім'я шаблону невірне",
|
||||
"img_size_exceeded": "Зображення перевищує максимальний розмір файлу"
|
||||
},
|
||||
"debug": {
|
||||
"chart_this_server": "Діаграма (цей сервер)",
|
||||
@@ -626,7 +627,7 @@
|
||||
"admin": "Редагувати адміністратора",
|
||||
"allow_from_smtp": "Дозволити <b>SMTP</b> тільки для цих IP",
|
||||
"allow_from_smtp_info": "Вкажіть IPv4/IPv6 адреси та/або підмережі.<br>Залиште поле порожнім, щоб дозволити відправлення з будь-яких адрес.",
|
||||
"bcc_dest_format": "Призначенням правила BBC має бути єдина дійсна адреса електронної пошти.<br>Якщо вам потрібно надіслати копію на кілька адрес, створіть псевдонім і використовуйте його тут.",
|
||||
"bcc_dest_format": "Призначенням правила BCC має бути єдина дійсна адреса електронної пошти.<br>Якщо вам потрібно надіслати копію на кілька адрес, створіть псевдонім і використовуйте його тут.",
|
||||
"comment_info": "Приватний коментар не видно користувачам, а публічний - відображається поряд із псевдонімом в особистому кабінеті користувача",
|
||||
"domain_quota": "Квота домену",
|
||||
"dont_check_sender_acl": "Вимкнути перевірку відправника для домену %s та псевдонімів домену",
|
||||
@@ -725,7 +726,7 @@
|
||||
"add": "Додати",
|
||||
"add_alias": "Додати псевдонім",
|
||||
"add_alias_expand": "Копіювати псевдоніми на псевдоніми домену",
|
||||
"add_bcc_entry": "Додати правило BBC",
|
||||
"add_bcc_entry": "Додати правило BCC",
|
||||
"add_domain": "Додати домен",
|
||||
"add_domain_alias": "Додати псевдонім домену",
|
||||
"add_filter": "Додати фільтр",
|
||||
@@ -745,7 +746,7 @@
|
||||
"bcc_local_dest": "Локальний домен",
|
||||
"bcc_map": "Правила ВВС",
|
||||
"bcc_map_type": "Тип BCC",
|
||||
"bcc_maps": "Правила BBC",
|
||||
"bcc_maps": "Правила BCC",
|
||||
"bcc_rcpt_map": "Одержувач",
|
||||
"bcc_sender_map": "Відправник",
|
||||
"bcc_to_rcpt": "Перейти на тип \"одержувач\"",
|
||||
|
||||
@@ -336,7 +336,9 @@
|
||||
"validate_license_now": "通过证书服务器验证 GUID",
|
||||
"verify": "验证",
|
||||
"yes": "✓",
|
||||
"options": "选项"
|
||||
"options": "选项",
|
||||
"f2b_max_ban_time": "最长封禁时间(秒)",
|
||||
"copy_to_clipboard": "复制到粘贴板"
|
||||
},
|
||||
"danger": {
|
||||
"access_denied": "访问被拒绝或者表单数据无效",
|
||||
@@ -456,7 +458,8 @@
|
||||
"validity_missing": "请设置有效期",
|
||||
"value_missing": "请填入所有值",
|
||||
"yotp_verification_failed": "Yubico OTP 认证失败: %s",
|
||||
"template_exists": "模板 %s 已存在"
|
||||
"template_exists": "模板 %s 已存在",
|
||||
"template_name_invalid": "模板名称无效"
|
||||
},
|
||||
"debug": {
|
||||
"chart_this_server": "图表 (此服务器)",
|
||||
@@ -487,7 +490,11 @@
|
||||
"container_disabled": "容器已被停止或禁用",
|
||||
"container_running": "运行中",
|
||||
"cores": "核心数",
|
||||
"memory": "内存"
|
||||
"memory": "内存",
|
||||
"error_show_ip": "无法解析公网IP地址",
|
||||
"show_ip": "显示公网IP",
|
||||
"update_available": "有可用更新",
|
||||
"update_failed": "无法检查更新"
|
||||
},
|
||||
"diagnostics": {
|
||||
"cname_from_a": "来自 A/AAAA 记录的值。但只要记录指向正确的资源即可。",
|
||||
@@ -903,7 +910,7 @@
|
||||
"disabled": "禁用",
|
||||
"second": "msgs / 秒",
|
||||
"minute": "msgs / 分钟",
|
||||
"hour": "msgs / 小说",
|
||||
"hour": "msgs / 小时",
|
||||
"day": "msgs / 天"
|
||||
},
|
||||
"start": {
|
||||
@@ -1202,7 +1209,8 @@
|
||||
"paginate": {
|
||||
"first": "第一页",
|
||||
"last": "最后一页",
|
||||
"previous": "上一页"
|
||||
"previous": "上一页",
|
||||
"next": "下一页"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
31
data/web/reset-password.php
Normal file
31
data/web/reset-password.php
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/prerequisites.inc.php';
|
||||
|
||||
if (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == 'admin') {
|
||||
header('Location: /debug');
|
||||
exit();
|
||||
}
|
||||
elseif (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == 'domainadmin') {
|
||||
header('Location: /mailbox');
|
||||
exit();
|
||||
}
|
||||
elseif (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == 'user') {
|
||||
header('Location: /user');
|
||||
exit();
|
||||
}
|
||||
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/header.inc.php';
|
||||
$_SESSION['return_to'] = $_SERVER['REQUEST_URI'];
|
||||
$_SESSION['index_query_string'] = $_SERVER['QUERY_STRING'];
|
||||
|
||||
if (isset($_GET['token'])) $is_reset_token_valid = reset_password("check", $_GET['token']);
|
||||
else $is_reset_token_valid = False;
|
||||
|
||||
$template = 'reset-password.twig';
|
||||
$template_data = [
|
||||
'is_mobileconfig' => str_contains($_SESSION['index_query_string'], 'mobileconfig'),
|
||||
'is_reset_token_valid' => $is_reset_token_valid,
|
||||
'reset_token' => $_GET['token']
|
||||
];
|
||||
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/footer.inc.php';
|
||||
@@ -22,7 +22,7 @@
|
||||
<li><button class="dropdown-item" data-bs-target="#tab-config-quarantine" aria-selected="false" aria-controls="tab-config-quarantine" role="tab" data-bs-toggle="tab">{{ lang.admin.quarantine }}</button></li>
|
||||
<li><button class="dropdown-item" data-bs-target="#tab-config-quota" aria-selected="false" aria-controls="tab-config-quota" role="tab" data-bs-toggle="tab">{{ lang.admin.quota_notifications }}</button></li>
|
||||
<li><button class="dropdown-item" data-bs-target="#tab-config-rsettings" aria-selected="false" aria-controls="tab-config-rsettings" role="tab" data-bs-toggle="tab">{{ lang.admin.rspamd_settings_map }}</button></li>
|
||||
<li><button class="dropdown-item" data-bs-target="#tab-config-password-policy" aria-selected="false" aria-controls="tab-config-password-policy" role="tab" data-bs-toggle="tab">{{ lang.admin.password_policy }}</button></li>
|
||||
<li><button class="dropdown-item" data-bs-target="#tab-config-password-settings" aria-selected="false" aria-controls="tab-config-password-settings" role="tab" data-bs-toggle="tab">{{ lang.admin.password_settings }}</button></li>
|
||||
<li><button class="dropdown-item" data-bs-target="#tab-config-customize" aria-selected="false" aria-controls="tab-config-customize" role="tab" data-bs-toggle="tab">{{ lang.admin.customize }}</button></li>
|
||||
</ul>
|
||||
</li>
|
||||
@@ -51,7 +51,7 @@
|
||||
{% include 'admin/tab-config-quota.twig' %}
|
||||
{% include 'admin/tab-config-rsettings.twig' %}
|
||||
{% include 'admin/tab-config-customize.twig' %}
|
||||
{% include 'admin/tab-config-password-policy.twig' %}
|
||||
{% include 'admin/tab-config-password-settings.twig' %}
|
||||
{% include 'admin/tab-sys-mails.twig' %}
|
||||
{% include 'admin/tab-globalfilter-regex.twig' %}
|
||||
</div>
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
<div class="tab-pane fade" id="tab-config-password-policy" role="tabpanel" aria-labelledby="tab-config-password-policy">
|
||||
<div class="card mb-4">
|
||||
<div class="card-header d-flex fs-5">
|
||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-password-policy" data-bs-toggle="collapse" aria-controls="collapse-tab-config-password-policy">
|
||||
{{ lang.admin.password_policy }}
|
||||
</button>
|
||||
<span class="d-none d-md-block">{{ lang.admin.password_policy }}</span>
|
||||
</div>
|
||||
<div id="collapse-tab-config-password-policy" class="card-body collapse" data-bs-parent="#admin-content">
|
||||
<form class="form-horizontal" data-id="passwordpolicy" role="form" method="post">
|
||||
{% for name, value in password_complexity %}
|
||||
{% if name == 'length' %}
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-3 text-sm-end" for="length">{{ lang.admin.password_length }}:</label>
|
||||
<div class="col-sm-2">
|
||||
<input type="number" class="form-control" min="3" max="64" name="length" id="length" value="{{ value }}" required>
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
<input type="hidden" name="{{ name }}" value="0">
|
||||
<div class="row mb-2">
|
||||
<div class="offset-sm-3 col-sm-9">
|
||||
<label>
|
||||
<input type="checkbox" class="form-check-input" name="{{ name }}" id="{{ name }}" value="1" {% if value == 1 %}checked{% endif %}> {{ lang.admin['password_policy_'~name] }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
<div class="row mt-4 mb-2">
|
||||
<div class="offset-sm-3 col-sm-9">
|
||||
<div class="btn-group">
|
||||
<button class="btn btn-sm d-block d-sm-inline btn-success" data-item="passwordpolicy" data-action="edit_selected" data-id="passwordpolicy" data-api-url='edit/passwordpolicy' data-api-attr='{}' href="#"><i class="bi bi-check-lg"></i> {{ lang.admin.save }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
102
data/web/templates/admin/tab-config-password-settings.twig
Normal file
102
data/web/templates/admin/tab-config-password-settings.twig
Normal file
@@ -0,0 +1,102 @@
|
||||
<div class="tab-pane fade" id="tab-config-password-settings" role="tabpanel" aria-labelledby="tab-config-password-settings">
|
||||
<div class="card mb-4">
|
||||
<div class="card-header d-flex fs-5">
|
||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-password-settings" data-bs-toggle="collapse" aria-controls="collapse-tab-config-password-settings">
|
||||
{{ lang.admin.password_settings }}
|
||||
</button>
|
||||
<span class="d-none d-md-block">{{ lang.admin.password_settings }}</span>
|
||||
</div>
|
||||
<div id="collapse-tab-config-password-settings" class="card-body collapse" data-bs-parent="#admin-content">
|
||||
<form class="form-horizontal" data-id="passwordpolicy" role="form" method="post">
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<legend>
|
||||
{{ lang.admin.password_policy }}
|
||||
</legend>
|
||||
<hr />
|
||||
</div>
|
||||
</div>
|
||||
{% for name, value in password_complexity %}
|
||||
{% if name == 'length' %}
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-3 text-sm-end" for="length">{{ lang.admin.password_length }}:</label>
|
||||
<div class="col-sm-2">
|
||||
<input type="number" class="form-control" min="3" max="64" name="length" id="length" value="{{ value }}" required>
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
<input type="hidden" name="{{ name }}" value="0">
|
||||
<div class="row mb-2">
|
||||
<div class="offset-sm-3 col-sm-9">
|
||||
<label>
|
||||
<input type="checkbox" class="form-check-input" name="{{ name }}" id="{{ name }}" value="1" {% if value == 1 %}checked{% endif %}> {{ lang.admin['password_policy_'~name] }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
<div class="row mt-4 mb-2">
|
||||
<div class="offset-sm-3 col-sm-9">
|
||||
<div class="btn-group">
|
||||
<button class="btn btn-sm d-block d-sm-inline btn-success" data-item="passwordpolicy" data-action="edit_selected" data-id="passwordpolicy" data-api-url='edit/passwordpolicy' data-api-attr='{}' href="#"><i class="bi bi-check-lg"></i> {{ lang.admin.save }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<form class="form" role="form" data-id="pw_reset_notification" method="post" style="margin-top: 50px;">
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<legend>
|
||||
{{ lang.admin.password_reset_settings }}
|
||||
</legend>
|
||||
<hr />
|
||||
<small>{{ lang.admin.reset_password_vars|raw }}</small><br><br>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<div class="col-sm-6">
|
||||
<div>
|
||||
<label for="pw_reset_from">{{ lang.admin.quota_notification_sender }}:</label>
|
||||
<input type="email" class="form-control" id="pw_reset_from" name="from" value="{{ pw_reset_data.from }}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<div>
|
||||
<label for="pw_reset_subject">{{ lang.admin.quota_notification_subject }}:</label>
|
||||
<input type="text" class="form-control" id="pw_reset_subject" name="subject" value="{{ pw_reset_data.subject }}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-12" data-bs-target="#text_template" style="cursor:pointer" unselectable="on" data-bs-toggle="collapse">
|
||||
<span class="d-block"><i style="font-size:10pt;" class="bi bi-plus-square"></i> {{ lang.admin.password_reset_tmpl_text }}</span>
|
||||
<small>{{ lang.admin.restore_template }}</small>
|
||||
</div>
|
||||
<div id="text_template" class="col-12 collapse">
|
||||
<textarea autocorrect="off" spellcheck="false" autocapitalize="none" class="form-control textarea-code mb-2" rows="20" name="text_tmpl">{{ pw_reset_data.text_tmpl|raw }}</textarea>
|
||||
</div>
|
||||
<div class="col-12 mt-3" data-bs-target="#html_template" style="cursor:pointer" unselectable="on" data-bs-toggle="collapse">
|
||||
<span class="d-block"><i style="font-size:10pt;" class="bi bi-plus-square"></i> {{ lang.admin.password_reset_tmpl_html }}</span>
|
||||
<small>{{ lang.admin.restore_template }}</small>
|
||||
</div>
|
||||
<div id="html_template" class="col-12 collapse">
|
||||
<textarea autocorrect="off" spellcheck="false" autocapitalize="none" class="form-control textarea-code" rows="20" name="html_tmpl">{{ pw_reset_data.html_tmpl|raw }}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-10">
|
||||
<div>
|
||||
<br>
|
||||
<a type="button" class="btn btn-sm d-block d-sm-inline btn-success" data-action="edit_selected"
|
||||
data-item="pw_reset_notification"
|
||||
data-id="pw_reset_notification"
|
||||
data-api-url='edit/reset-password-notification'
|
||||
data-api-attr='{}'><i class="bi bi-check-lg"></i> {{ lang.user.save_changes }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -146,7 +146,6 @@
|
||||
var lang_fido2 = {{ lang_fido2|raw }};
|
||||
var docker_timeout = {{ docker_timeout|raw }} * 1000;
|
||||
var mailcow_cc_role = '{{ mailcow_cc_role }}';
|
||||
var last_login = '{{ last_login }}';
|
||||
var mailcow_info = {
|
||||
version_tag: '{{ mailcow_info.version_tag }}',
|
||||
last_version_tag: '{{ mailcow_info.last_version_tag }}',
|
||||
|
||||
@@ -112,6 +112,7 @@
|
||||
<option value="quarantine_notification" {% if template.attributes.acl_quarantine_notification == '1' %} selected{% endif %}>{{ lang.acl["quarantine_notification"] }}</option>
|
||||
<option value="quarantine_category" {% if template.attributes.acl_quarantine_category == '1' %} selected{% endif %}>{{ lang.acl["quarantine_category"] }}</option>
|
||||
<option value="app_passwds" {% if template.attributes.acl_app_passwds == '1' %} selected{% endif %}>{{ lang.acl["app_passwds"] }}</option>
|
||||
<option value="pw_reset" {% if template.attributes.acl_pw_reset == '1' %} selected{% endif %}>{{ lang.acl["pw_reset"] }}</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -203,6 +203,13 @@
|
||||
<input type="password" data-pwgen-field="true" class="form-control" name="password2" autocomplete="new-password">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-2" for="pw_recovery_email">{{ lang.edit.password_recovery_email }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="email" class="form-control" name="pw_recovery_email" value="{{ result.attributes.recovery_email }}">
|
||||
<small class="text-muted">{{ lang.admin.password_reset_info }}</small>
|
||||
</div>
|
||||
</div>
|
||||
<div data-acl="{{ acl.extend_sender_acl }}" class="row mb-4">
|
||||
<label class="control-label col-sm-2" for="extended_sender_acl">{{ lang.edit.extended_sender_acl }}</label>
|
||||
<div class="col-sm-10">
|
||||
|
||||
@@ -63,6 +63,9 @@
|
||||
{% endif %}
|
||||
</div>
|
||||
</form>
|
||||
<div class="mt-3 mb-4">
|
||||
<a href="/reset-password">{{ lang.login.forgot_password }}</a>
|
||||
</div>
|
||||
{% if login_delay %}
|
||||
<p><div class="my-4 alert alert-info">{{ lang.login.delayed|format(login_delay) }}</b></div></p>
|
||||
{% endif %}
|
||||
|
||||
@@ -149,6 +149,7 @@
|
||||
<option value="quarantine_notification" selected>{{ lang.acl["quarantine_notification"] }}</option>
|
||||
<option value="quarantine_category" selected>{{ lang.acl["quarantine_category"] }}</option>
|
||||
<option value="app_passwds" selected>{{ lang.acl["app_passwds"] }}</option>
|
||||
<option value="pw_reset" selected>{{ lang.acl["pw_reset"] }}</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
@@ -318,6 +319,7 @@
|
||||
<option value="quarantine_notification" selected>{{ lang.acl["quarantine_notification"] }}</option>
|
||||
<option value="quarantine_category" selected>{{ lang.acl["quarantine_category"] }}</option>
|
||||
<option value="app_passwds" selected>{{ lang.acl["app_passwds"] }}</option>
|
||||
<option value="pw_reset" selected>{{ lang.acl["pw_reset"] }}</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -309,6 +309,33 @@
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- pw change modal -->
|
||||
<!-- pw recovery email modal -->
|
||||
<div class="modal fade" id="pwRecoveryEmailModal" tabindex="-1" role="dialog" aria-labelledby="pwRecoveryEmailModalLabel">
|
||||
<div class="modal-dialog modal-lg" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h3 class="modal-title">{{ lang.user.pw_recovery_email }}</h3>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form class="form-horizontal" data-cached-form="false" data-id="pw_recovery_change" role="form" method="post" autocomplete="off">
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-3" for="pw_recovery_email">{{ lang.user.email }}</label>
|
||||
<div class="col-sm-9">
|
||||
<input type="email" class="form-control" name="pw_recovery_email" value="{{ mailboxdata.attributes.recovery_email }}">
|
||||
<small class="text-muted">{{ lang.user.password_reset_info }}</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="offset-sm-3 col-sm-9">
|
||||
<button class="btn btn-xs-lg d-block d-sm-inline btn-success" data-action="edit_selected" data-id="pw_recovery_change" data-item="null" data-api-url='edit/self' data-api-attr='{}' href="#">{{ lang.user.save }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- pw recovery email modal -->
|
||||
<!-- temp alias modal -->
|
||||
<div class="modal fade" id="tempAliasModal" tabindex="-1" role="dialog" aria-labelledby="tempAliasModalLabel">
|
||||
<div class="modal-dialog modal-lg" role="document">
|
||||
|
||||
57
data/web/templates/reset-password.twig
Normal file
57
data/web/templates/reset-password.twig
Normal file
@@ -0,0 +1,57 @@
|
||||
{% extends 'base.twig' %}
|
||||
|
||||
{% block navbar %}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row mb-4" style="margin-top: 60px">
|
||||
<div class="col-12 col-md-7 col-lg-6 col-xl-5 ms-auto me-auto">
|
||||
<div class="card">
|
||||
<div class="card-header d-flex align-items-center">
|
||||
<i class="bi bi-person-fill me-2"></i> {{ lang.login.reset_password }}
|
||||
<div class="ms-auto form-check form-switch my-auto d-flex align-items-center">
|
||||
<label class="form-check-label"><i class="bi bi-moon-fill"></i></label>
|
||||
<input class="form-check-input ms-2" type="checkbox" id="dark-mode-toggle">
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="text-center mailcow-logo mb-4">
|
||||
<img class="main-logo" src="{{ logo|default('/img/cow_mailcow.svg') }}" alt="mailcow">
|
||||
<img class="main-logo-dark" src="{{ logo_dark|default('/img/cow_mailcow.svg') }}" alt="mailcow-logo-dark">
|
||||
</div>
|
||||
<legend>{{ ui_texts.main_name|raw }}</legend><hr />
|
||||
|
||||
{% if is_reset_token_valid %}
|
||||
<form method="post" autofill="off">
|
||||
<input type="hidden" name="token" value="{{ reset_token }}" />
|
||||
<input type="password" autocorrect="off" autocapitalize="none" class="form-control mb-2" name="new_password" placeholder="{{ lang.login.new_password }}" />
|
||||
<input type="password" autocorrect="off" autocapitalize="none" class="form-control mb-2" name="new_password2" placeholder="{{ lang.login.new_password_confirm }}" />
|
||||
|
||||
<small id="mismatch_alert" class="text-danger d-none">{{ lang.login.password_mismatch }}</small>
|
||||
<div class="d-flex justify-content-end mt-4" style="position: relative">
|
||||
<button type="submit" class="btn btn-xs-lg d-block d-sm-inline btn-success" name="pw_reset">{{ lang.login.reset_password }}</button>
|
||||
</div>
|
||||
</form>
|
||||
{% elseif reset_token is null %}
|
||||
<form method="post" autofill="off">
|
||||
<input type="text" autocorrect="off" autocapitalize="none" class="form-control mb-2" name="username" placeholder="{{ lang.login.username }}" />
|
||||
|
||||
<div class="d-flex justify-content-end mt-4" style="position: relative">
|
||||
<button type="submit" class="btn btn-xs-lg d-block d-sm-inline btn-success" name="pw_reset_request">{{ lang.login.request_reset_password }}</button>
|
||||
</div>
|
||||
</form>
|
||||
{% else %}
|
||||
<p class="text-center">{{ lang.login.invalid_pass_reset_token|raw }}</p>
|
||||
<a href="/">{{ lang.login.back_to_mailcow }}</a>
|
||||
{% endif %}
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type='text/javascript'>
|
||||
var csrf_token = '{{ csrf_token }}';
|
||||
var mailcow_cc_username = '{{ mailcow_cc_username }}';
|
||||
</script>
|
||||
{% endblock %}
|
||||
@@ -50,6 +50,7 @@
|
||||
<p>{{ mailboxdata.quota_used|formatBytes(2) }} / {% if mailboxdata.quota == 0 %}∞{% else %}{{ mailboxdata.quota|formatBytes(2) }}{% endif %}<br>{{ mailboxdata.messages }} {{ lang.user.messages }}</p>
|
||||
<hr>
|
||||
<p><a href="#pwChangeModal" data-bs-toggle="modal"><i class="bi bi-pencil-fill"></i> {{ lang.user.change_password }}</a></p>
|
||||
{% if acl.pw_reset == 1 %}<p><a href="#pwRecoveryEmailModal" data-bs-toggle="modal"><i class="bi bi-pencil-fill"></i> {{ lang.user.pw_recovery_email }}</a></p>{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
@@ -155,7 +156,7 @@
|
||||
<li class="login-history" data-days="31"><a class="dropdown-item" href="#">1 {{ lang.user.month }}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="last-login mt-4"></div>
|
||||
<div class="last-login mt-4" id="recent-logins"></div>
|
||||
<span class="clear-last-logins mt-2">
|
||||
{{ lang.user.clear_recent_successful_connections }}
|
||||
</span>
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
version: '2.1'
|
||||
services:
|
||||
|
||||
unbound-mailcow:
|
||||
image: mailcow/unbound:1.21
|
||||
image: mailcow/unbound:1.23
|
||||
environment:
|
||||
- TZ=${TZ}
|
||||
- SKIP_UNBOUND_HEALTHCHECK=${SKIP_UNBOUND_HEALTHCHECK:-n}
|
||||
@@ -62,7 +61,7 @@ services:
|
||||
- redis
|
||||
|
||||
clamd-mailcow:
|
||||
image: mailcow/clamd:1.65
|
||||
image: mailcow/clamd:1.66
|
||||
restart: always
|
||||
depends_on:
|
||||
unbound-mailcow:
|
||||
@@ -81,7 +80,7 @@ services:
|
||||
- clamd
|
||||
|
||||
rspamd-mailcow:
|
||||
image: mailcow/rspamd:1.95
|
||||
image: mailcow/rspamd:1.97
|
||||
stop_grace_period: 30s
|
||||
depends_on:
|
||||
- dovecot-mailcow
|
||||
@@ -91,6 +90,7 @@ services:
|
||||
- IPV6_NETWORK=${IPV6_NETWORK:-fd4d:6169:6c63:6f77::/64}
|
||||
- REDIS_SLAVEOF_IP=${REDIS_SLAVEOF_IP:-}
|
||||
- REDIS_SLAVEOF_PORT=${REDIS_SLAVEOF_PORT:-}
|
||||
- SPAMHAUS_DQS_KEY=${SPAMHAUS_DQS_KEY:-}
|
||||
volumes:
|
||||
- ./data/hooks/rspamd:/hooks:Z
|
||||
- ./data/conf/rspamd/custom/:/etc/rspamd/custom:z
|
||||
@@ -111,7 +111,7 @@ services:
|
||||
- rspamd
|
||||
|
||||
php-fpm-mailcow:
|
||||
image: mailcow/phpfpm:1.87
|
||||
image: mailcow/phpfpm:1.88
|
||||
command: "php-fpm -d date.timezone=${TZ} -d expose_php=0"
|
||||
depends_on:
|
||||
- redis-mailcow
|
||||
@@ -168,6 +168,7 @@ services:
|
||||
- DEMO_MODE=${DEMO_MODE:-n}
|
||||
- WEBAUTHN_ONLY_TRUSTED_VENDORS=${WEBAUTHN_ONLY_TRUSTED_VENDORS:-n}
|
||||
- CLUSTERMODE=${CLUSTERMODE:-}
|
||||
- FLATCURVE_EXPERIMENTAL=${FLATCURVE_EXPERIMENTAL:-}
|
||||
restart: always
|
||||
networks:
|
||||
mailcow-network:
|
||||
@@ -175,7 +176,7 @@ services:
|
||||
- phpfpm
|
||||
|
||||
sogo-mailcow:
|
||||
image: mailcow/sogo:1.123
|
||||
image: mailcow/sogo:1.124
|
||||
environment:
|
||||
- DBNAME=${DBNAME}
|
||||
- DBUSER=${DBUSER}
|
||||
@@ -222,7 +223,7 @@ services:
|
||||
- sogo
|
||||
|
||||
dovecot-mailcow:
|
||||
image: mailcow/dovecot:1.28.2
|
||||
image: mailcow/dovecot:2.0
|
||||
depends_on:
|
||||
- mysql-mailcow
|
||||
- netfilter-mailcow
|
||||
@@ -265,6 +266,7 @@ services:
|
||||
- REDIS_SLAVEOF_IP=${REDIS_SLAVEOF_IP:-}
|
||||
- REDIS_SLAVEOF_PORT=${REDIS_SLAVEOF_PORT:-}
|
||||
- COMPOSE_PROJECT_NAME=${COMPOSE_PROJECT_NAME:-mailcow-dockerized}
|
||||
- FLATCURVE_EXPERIMENTAL=${FLATCURVE_EXPERIMENTAL:-n}
|
||||
ports:
|
||||
- "${DOVEADM_PORT:-127.0.0.1:19991}:12345"
|
||||
- "${IMAP_PORT:-143}:143"
|
||||
@@ -290,7 +292,7 @@ services:
|
||||
ofelia.job-exec.dovecot_sarules.schedule: "@every 24h"
|
||||
ofelia.job-exec.dovecot_sarules.command: "/bin/bash -c \"/usr/local/bin/sa-rules.sh\""
|
||||
ofelia.job-exec.dovecot_fts.schedule: "@every 24h"
|
||||
ofelia.job-exec.dovecot_fts.command: "/usr/bin/curl http://solr:8983/solr/dovecot-fts/update?optimize=true"
|
||||
ofelia.job-exec.dovecot_fts.command: "/bin/bash -c \"/usr/local/bin/gosu vmail /usr/local/bin/optimize-fts.sh\""
|
||||
ofelia.job-exec.dovecot_repl_health.schedule: "@every 5m"
|
||||
ofelia.job-exec.dovecot_repl_health.command: "/bin/bash -c \"/usr/local/bin/gosu vmail /usr/local/bin/repl_health.sh\""
|
||||
ulimits:
|
||||
@@ -305,7 +307,7 @@ services:
|
||||
- dovecot
|
||||
|
||||
postfix-mailcow:
|
||||
image: mailcow/postfix:1.74
|
||||
image: mailcow/postfix:1.75
|
||||
depends_on:
|
||||
mysql-mailcow:
|
||||
condition: service_started
|
||||
@@ -405,13 +407,14 @@ services:
|
||||
condition: service_started
|
||||
unbound-mailcow:
|
||||
condition: service_healthy
|
||||
image: mailcow/acme:1.87
|
||||
image: mailcow/acme:1.89
|
||||
dns:
|
||||
- ${IPV4_NETWORK:-172.22.1}.254
|
||||
environment:
|
||||
- LOG_LINES=${LOG_LINES:-9999}
|
||||
- ACME_CONTACT=${ACME_CONTACT:-}
|
||||
- ADDITIONAL_SAN=${ADDITIONAL_SAN}
|
||||
- AUTODISCOVER_SAN=${AUTODISCOVER_SAN:-y}
|
||||
- MAILCOW_HOSTNAME=${MAILCOW_HOSTNAME}
|
||||
- DBNAME=${DBNAME}
|
||||
- DBUSER=${DBUSER}
|
||||
@@ -441,7 +444,7 @@ services:
|
||||
- acme
|
||||
|
||||
netfilter-mailcow:
|
||||
image: mailcow/netfilter:1.58
|
||||
image: mailcow/netfilter:1.59
|
||||
stop_grace_period: 30s
|
||||
restart: always
|
||||
privileged: true
|
||||
@@ -460,7 +463,7 @@ services:
|
||||
- /lib/modules:/lib/modules:ro
|
||||
|
||||
watchdog-mailcow:
|
||||
image: mailcow/watchdog:2.02
|
||||
image: mailcow/watchdog:2.04
|
||||
dns:
|
||||
- ${IPV4_NETWORK:-172.22.1}.254
|
||||
tmpfs:
|
||||
@@ -477,7 +480,6 @@ services:
|
||||
- mysql-mailcow
|
||||
- acme-mailcow
|
||||
- redis-mailcow
|
||||
|
||||
environment:
|
||||
- IPV6_NETWORK=${IPV6_NETWORK:-fd4d:6169:6c63:6f77::/64}
|
||||
- LOG_LINES=${LOG_LINES:-9999}
|
||||
@@ -532,7 +534,7 @@ services:
|
||||
- watchdog
|
||||
|
||||
dockerapi-mailcow:
|
||||
image: mailcow/dockerapi:2.07
|
||||
image: mailcow/dockerapi:2.08
|
||||
security_opt:
|
||||
- label=disable
|
||||
restart: always
|
||||
@@ -553,7 +555,7 @@ services:
|
||||
|
||||
##### Will be removed soon #####
|
||||
solr-mailcow:
|
||||
image: mailcow/solr:1.8.2
|
||||
image: mailcow/solr:1.8.3
|
||||
restart: always
|
||||
depends_on:
|
||||
- netfilter-mailcow
|
||||
@@ -565,6 +567,7 @@ services:
|
||||
- TZ=${TZ}
|
||||
- SOLR_HEAP=${SOLR_HEAP:-1024}
|
||||
- SKIP_SOLR=${SKIP_SOLR:-y}
|
||||
- FLATCURVE_EXPERIMENTAL=${FLATCURVE_EXPERIMENTAL:-n}
|
||||
networks:
|
||||
mailcow-network:
|
||||
aliases:
|
||||
@@ -572,7 +575,7 @@ services:
|
||||
################################
|
||||
|
||||
olefy-mailcow:
|
||||
image: mailcow/olefy:1.12
|
||||
image: mailcow/olefy:1.13
|
||||
restart: always
|
||||
environment:
|
||||
- TZ=${TZ}
|
||||
@@ -592,9 +595,10 @@ services:
|
||||
ofelia-mailcow:
|
||||
image: mcuadros/ofelia:latest
|
||||
restart: always
|
||||
command: daemon --docker
|
||||
command: daemon --docker -f label=com.docker.compose.project=${COMPOSE_PROJECT_NAME}
|
||||
environment:
|
||||
- TZ=${TZ}
|
||||
- COMPOSE_PROJECT_NAME=${COMPOSE_PROJECT_NAME}
|
||||
depends_on:
|
||||
- sogo-mailcow
|
||||
- dovecot-mailcow
|
||||
|
||||
@@ -25,6 +25,16 @@ for bin in openssl curl docker git awk sha1sum grep cut; do
|
||||
if [[ -z $(which ${bin}) ]]; then echo "Cannot find ${bin}, exiting..."; exit 1; fi
|
||||
done
|
||||
|
||||
# Check Docker Version (need at least 24.X)
|
||||
docker_version=$(docker -v | grep -oP '\d+\.\d+\.\d+' | cut -d '.' -f 1)
|
||||
|
||||
if [[ $docker_version -lt 24 ]]; then
|
||||
echo -e "\e[31mCannot find Docker with a Version higher or equals 24.0.0\e[0m"
|
||||
echo -e "\e[33mmailcow needs a newer Docker version to work properly...\e[0m"
|
||||
echo -e "\e[31mPlease update your Docker installation... exiting\e[0m"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if docker compose > /dev/null 2>&1; then
|
||||
if docker compose version --short | grep -e "^2." -e "^v2." > /dev/null 2>&1; then
|
||||
COMPOSE_VERSION=native
|
||||
@@ -147,40 +157,44 @@ done
|
||||
|
||||
MEM_TOTAL=$(awk '/MemTotal/ {print $2}' /proc/meminfo)
|
||||
|
||||
if [ ${MEM_TOTAL} -le "2621440" ]; then
|
||||
echo "Installed memory is <= 2.5 GiB. It is recommended to disable ClamAV to prevent out-of-memory situations."
|
||||
echo "ClamAV can be re-enabled by setting SKIP_CLAMD=n in mailcow.conf."
|
||||
read -r -p "Do you want to disable ClamAV now? [Y/n] " response
|
||||
case $response in
|
||||
[nN][oO]|[nN])
|
||||
SKIP_CLAMD=n
|
||||
if [ -z "${SKIP_CLAMD}" ]; then
|
||||
if [ ${MEM_TOTAL} -le "2621440" ]; then
|
||||
echo "Installed memory is <= 2.5 GiB. It is recommended to disable ClamAV to prevent out-of-memory situations."
|
||||
echo "ClamAV can be re-enabled by setting SKIP_CLAMD=n in mailcow.conf."
|
||||
read -r -p "Do you want to disable ClamAV now? [Y/n] " response
|
||||
case $response in
|
||||
[nN][oO]|[nN])
|
||||
SKIP_CLAMD=n
|
||||
;;
|
||||
*)
|
||||
SKIP_CLAMD=y
|
||||
;;
|
||||
*)
|
||||
SKIP_CLAMD=y
|
||||
;;
|
||||
esac
|
||||
else
|
||||
SKIP_CLAMD=n
|
||||
esac
|
||||
else
|
||||
SKIP_CLAMD=n
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ ${MEM_TOTAL} -le "2097152" ]; then
|
||||
echo "Disabling Solr on low-memory system."
|
||||
SKIP_SOLR=y
|
||||
elif [ ${MEM_TOTAL} -le "3670016" ]; then
|
||||
echo "Installed memory is <= 3.5 GiB. It is recommended to disable Solr to prevent out-of-memory situations."
|
||||
echo "Solr is a prone to run OOM and should be monitored. The default Solr heap size is 1024 MiB and should be set in mailcow.conf according to your expected load."
|
||||
echo "Solr can be re-enabled by setting SKIP_SOLR=n in mailcow.conf but will refuse to start with less than 2 GB total memory."
|
||||
read -r -p "Do you want to disable Solr now? [Y/n] " response
|
||||
case $response in
|
||||
[nN][oO]|[nN])
|
||||
SKIP_SOLR=n
|
||||
if [ -z "${SKIP_SOLR}" ]; then
|
||||
if [ ${MEM_TOTAL} -le "2097152" ]; then
|
||||
echo "Disabling Solr on low-memory system."
|
||||
SKIP_SOLR=y
|
||||
elif [ ${MEM_TOTAL} -le "3670016" ]; then
|
||||
echo "Installed memory is <= 3.5 GiB. It is recommended to disable Solr to prevent out-of-memory situations."
|
||||
echo "Solr is a prone to run OOM and should be monitored. The default Solr heap size is 1024 MiB and should be set in mailcow.conf according to your expected load."
|
||||
echo "Solr can be re-enabled by setting SKIP_SOLR=n in mailcow.conf but will refuse to start with less than 2 GB total memory."
|
||||
read -r -p "Do you want to disable Solr now? [Y/n] " response
|
||||
case $response in
|
||||
[nN][oO]|[nN])
|
||||
SKIP_SOLR=n
|
||||
;;
|
||||
*)
|
||||
SKIP_SOLR=y
|
||||
;;
|
||||
*)
|
||||
SKIP_SOLR=y
|
||||
;;
|
||||
esac
|
||||
else
|
||||
SKIP_SOLR=n
|
||||
esac
|
||||
else
|
||||
SKIP_SOLR=n
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ ${SKIP_BRANCH} != y ]]; then
|
||||
@@ -336,6 +350,13 @@ MAILDIR_GC_TIME=7200
|
||||
|
||||
ADDITIONAL_SAN=
|
||||
|
||||
# Obtain certificates for autodiscover.* and autoconfig.* domains.
|
||||
# This can be useful to switch off in case you are in a scenario where a reverse proxy already handles those.
|
||||
# There are mixed scenarios where ports 80,443 are occupied and you do not want to share certs
|
||||
# between services. So acme-mailcow obtains for maildomains and all web-things get handled
|
||||
# in the reverse proxy.
|
||||
AUTODISCOVER_SAN=y
|
||||
|
||||
# Additional server names for mailcow UI
|
||||
#
|
||||
# Specify alternative addresses for the mailcow UI to respond to
|
||||
|
||||
@@ -55,10 +55,10 @@ ENV_FILE=${SCRIPT_DIR}/../.env
|
||||
THREADS=$(echo ${THREADS:-1})
|
||||
ARCH=$(uname -m)
|
||||
|
||||
if ! [[ "${THREADS}" =~ ^[1-9]+$ ]] ; then
|
||||
if ! [[ "${THREADS}" =~ ^[1-9][0-9]?$ ]] ; then
|
||||
echo "Thread input is not a number!"
|
||||
exit 1
|
||||
elif [[ "${THREADS}" =~ ^[1-9]+$ ]] ; then
|
||||
elif [[ "${THREADS}" =~ ^[1-9][0-9]?$ ]] ; then
|
||||
echo "Using ${THREADS} Thread(s) for this run."
|
||||
echo "Notice: You can set the Thread count with the THREADS Variable before you run this script."
|
||||
fi
|
||||
@@ -199,7 +199,7 @@ function restore() {
|
||||
case "$1" in
|
||||
vmail)
|
||||
docker stop $(docker ps -qf name=dovecot-mailcow)
|
||||
docker run -it --name mailcow-backup --rm \
|
||||
docker run -i --name mailcow-backup --rm \
|
||||
-v ${RESTORE_LOCATION}:/backup:z \
|
||||
-v $(docker volume ls -qf name=^${CMPS_PRJ}_vmail-vol-1$):/vmail:z \
|
||||
${DEBIAN_DOCKER_IMAGE} /bin/tar --use-compress-program="pigz -d -p ${THREADS}" -Pxvf /backup/backup_vmail.tar.gz
|
||||
@@ -218,7 +218,7 @@ function restore() {
|
||||
;;
|
||||
redis)
|
||||
docker stop $(docker ps -qf name=redis-mailcow)
|
||||
docker run -it --name mailcow-backup --rm \
|
||||
docker run -i --name mailcow-backup --rm \
|
||||
-v ${RESTORE_LOCATION}:/backup:z \
|
||||
-v $(docker volume ls -qf name=^${CMPS_PRJ}_redis-vol-1$):/redis:z \
|
||||
${DEBIAN_DOCKER_IMAGE} /bin/tar --use-compress-program="pigz -d -p ${THREADS}" -Pxvf /backup/backup_redis.tar.gz
|
||||
@@ -226,7 +226,7 @@ function restore() {
|
||||
;;
|
||||
crypt)
|
||||
docker stop $(docker ps -qf name=dovecot-mailcow)
|
||||
docker run -it --name mailcow-backup --rm \
|
||||
docker run -i --name mailcow-backup --rm \
|
||||
-v ${RESTORE_LOCATION}:/backup:z \
|
||||
-v $(docker volume ls -qf name=^${CMPS_PRJ}_crypt-vol-1$):/crypt:z \
|
||||
${DEBIAN_DOCKER_IMAGE} /bin/tar --use-compress-program="pigz -d -p ${THREADS}" -Pxvf /backup/backup_crypt.tar.gz
|
||||
@@ -239,7 +239,7 @@ function restore() {
|
||||
echo -e "Continuing anyhow. If rspamd is crashing opon boot try remove the rspamd volume with docker volume rm ${CMPS_PRJ}_rspamd-vol-1 after you've stopped the stack.\e[0m"
|
||||
sleep 2
|
||||
docker stop $(docker ps -qf name=rspamd-mailcow)
|
||||
docker run -it --name mailcow-backup --rm \
|
||||
docker run -i --name mailcow-backup --rm \
|
||||
-v ${RESTORE_LOCATION}:/backup:z \
|
||||
-v $(docker volume ls -qf name=^${CMPS_PRJ}_rspamd-vol-1$):/rspamd:z \
|
||||
${DEBIAN_DOCKER_IMAGE} /bin/tar --use-compress-program="pigz -d -p ${THREADS}" -Pxvf /backup/backup_rspamd.tar.gz
|
||||
@@ -250,7 +250,7 @@ function restore() {
|
||||
echo -e "Skipping rspamd due to compatibility issues!\e[0m"
|
||||
else
|
||||
docker stop $(docker ps -qf name=rspamd-mailcow)
|
||||
docker run -it --name mailcow-backup --rm \
|
||||
docker run -i --name mailcow-backup --rm \
|
||||
-v ${RESTORE_LOCATION}:/backup:z \
|
||||
-v $(docker volume ls -qf name=^${CMPS_PRJ}_rspamd-vol-1$):/rspamd:z \
|
||||
${DEBIAN_DOCKER_IMAGE} /bin/tar --use-compress-program="pigz -d -p ${THREADS}" -Pxvf /backup/backup_rspamd.tar.gz
|
||||
@@ -259,7 +259,7 @@ function restore() {
|
||||
;;
|
||||
postfix)
|
||||
docker stop $(docker ps -qf name=postfix-mailcow)
|
||||
docker run -it --name mailcow-backup --rm \
|
||||
docker run -i --name mailcow-backup --rm \
|
||||
-v ${RESTORE_LOCATION}:/backup:z \
|
||||
-v $(docker volume ls -qf name=^${CMPS_PRJ}_postfix-vol-1$):/postfix:z \
|
||||
${DEBIAN_DOCKER_IMAGE} /bin/tar --use-compress-program="pigz -d -p ${THREADS}" -Pxvf /backup/backup_postfix.tar.gz
|
||||
@@ -295,7 +295,7 @@ function restore() {
|
||||
${SQLIMAGE} /bin/bash -c "shopt -s dotglob ; /bin/rm -rf /var/lib/mysql/* ; rsync -avh --usermap=root:mysql --groupmap=root:mysql /backup/ /var/lib/mysql/"
|
||||
elif [[ -f "${RESTORE_LOCATION}/backup_mysql.gz" ]]; then
|
||||
docker run \
|
||||
-it --name mailcow-backup --rm \
|
||||
-i --name mailcow-backup --rm \
|
||||
-v $(docker volume ls -qf name=^${CMPS_PRJ}_mysql-vol-1$):/var/lib/mysql/:z \
|
||||
--entrypoint= \
|
||||
-u mysql \
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
version: '2.1'
|
||||
services:
|
||||
unbound-mailcow:
|
||||
build: ./data/Dockerfiles/unbound
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
version: '2.1'
|
||||
services:
|
||||
|
||||
clamd-mailcow:
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
version: '2.1'
|
||||
services:
|
||||
|
||||
php-fpm-mailcow:
|
||||
@@ -26,6 +25,6 @@ services:
|
||||
- /var/run/mysqld/mysqld.sock:/var/run/mysqld/mysqld.sock
|
||||
|
||||
mysql-mailcow:
|
||||
image: alpine:3.19
|
||||
image: alpine:3.20
|
||||
command: /bin/true
|
||||
restart: "no"
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user