Compare commits
42 Commits
feat/custo
...
feature/ft
Author | SHA1 | Date | |
---|---|---|---|
|
f09c8534f5 | ||
|
0408bbf57f | ||
|
eb4a33dc27 | ||
|
a0ae59f8bf | ||
|
60871fa7d0 | ||
|
59a4031e24 | ||
|
04f55fc748 | ||
|
3ba3f1c2bd | ||
|
b0fd9787b5 | ||
|
df3de09050 | ||
|
86079429b3 | ||
|
ed476aae6b | ||
|
f0e27312f9 | ||
|
3425bcfbf0 | ||
|
bfa81b318d | ||
|
8dba0ca7dd | ||
|
5bd3394ed9 | ||
|
c0e66254b9 | ||
|
aec2dd1252 | ||
|
d86e9a22f4 | ||
|
db73f83c4e | ||
|
28582c5842 | ||
|
3d637aca25 | ||
|
d079ff49c6 | ||
|
2d6ce926e1 | ||
|
60ddfe3be2 | ||
|
30e2d944cd | ||
|
99ea569288 | ||
|
c98ef0d0c5 | ||
|
f09ca0a36a | ||
|
cdce97bd59 | ||
|
ed8941440a | ||
|
570170a5b1 | ||
|
df2c33d323 | ||
|
f2e0e50f87 | ||
|
26c5ed73e2 | ||
|
148b511f9d | ||
|
311007700b | ||
|
3a9177bd4c | ||
|
bca09e3afa | ||
|
cfba96f7e0 | ||
|
c82f38a025 |
@@ -14,7 +14,7 @@ jobs:
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: Mark/Close Stale Issues and Pull Requests 🗑️
|
||||
uses: actions/stale@v8.0.0
|
||||
uses: actions/stale@v7.0.0
|
||||
with:
|
||||
repo-token: ${{ secrets.STALE_ACTION_PAT }}
|
||||
days-before-stale: 60
|
||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@@ -13,6 +13,7 @@ data/conf/dovecot/acl_anyone
|
||||
data/conf/dovecot/dovecot-master.passwd
|
||||
data/conf/dovecot/dovecot-master.userdb
|
||||
data/conf/dovecot/extra.conf
|
||||
data/conf/dovecot/dovecot-fts-flatcurve.conf
|
||||
data/conf/dovecot/global_sieve_*
|
||||
data/conf/dovecot/last_login
|
||||
data/conf/dovecot/lua
|
||||
|
@@ -274,49 +274,6 @@ class DockerUtils:
|
||||
res = { 'type': 'success', 'msg': 'Scheduled immediate delivery'}
|
||||
return Response(content=json.dumps(res, indent=4), media_type="application/json")
|
||||
|
||||
# api call: container_post - post_action: exec - cmd: sogo - task: customize_enable
|
||||
def container_post__exec__sogo__customize_enable(self, container_id, request_json):
|
||||
for container in self.docker_client.containers.list(filters={"id": container_id}):
|
||||
cmd = ["/bin/bash", "-c", "/customize.sh enable"]
|
||||
sogo_return = container.exec_run(cmd)
|
||||
return exec_run_handler('utf8_text_only', sogo_return)
|
||||
# api call: container_post - post_action: exec - cmd: sogo - task: customize_disable
|
||||
def container_post__exec__sogo__customize_disable(self, container_id, request_json):
|
||||
for container in self.docker_client.containers.list(filters={"id": container_id}):
|
||||
cmd = ["/bin/bash", "-c", "/customize.sh disable"]
|
||||
sogo_return = container.exec_run(cmd)
|
||||
return exec_run_handler('utf8_text_only', sogo_return)
|
||||
# api call: container_post - post_action: exec - cmd: sogo - task: set_logo
|
||||
def container_post__exec__sogo__set_logo(self, container_id, request_json):
|
||||
for container in self.docker_client.containers.list(filters={"id": container_id}):
|
||||
cmd = ["/bin/bash", "-c", "/customize.sh set_logo"]
|
||||
sogo_return = container.exec_run(cmd)
|
||||
return exec_run_handler('utf8_text_only', sogo_return)
|
||||
# api call: container_post - post_action: exec - cmd: sogo - task: remove_logo
|
||||
def container_post__exec__sogo__remove_logo(self, container_id, request_json):
|
||||
for container in self.docker_client.containers.list(filters={"id": container_id}):
|
||||
cmd = ["/bin/bash", "-c", "rm -f /usr/lib/GNUstep/SOGo/WebServerResources/img/sogo-full.svg"]
|
||||
sogo_return = container.exec_run(cmd)
|
||||
return exec_run_handler('utf8_text_only', sogo_return)
|
||||
# api call: container_post - post_action: exec - cmd: sogo - task: set_favicon
|
||||
def container_post__exec__sogo__set_favicon(self, container_id, request_json):
|
||||
for container in self.docker_client.containers.list(filters={"id": container_id}):
|
||||
cmd = ["/bin/bash", "-c", "/customize.sh set_favicon"]
|
||||
sogo_return = container.exec_run(cmd)
|
||||
return exec_run_handler('utf8_text_only', sogo_return)
|
||||
# api call: container_post - post_action: exec - cmd: sogo - task: remove_favicon
|
||||
def container_post__exec__sogo__remove_favicon(self, container_id, request_json):
|
||||
for container in self.docker_client.containers.list(filters={"id": container_id}):
|
||||
cmd = ["/bin/bash", "-c", "cp /sogo.ico /usr/lib/GNUstep/SOGo/WebServerResources/img/sogo.ico"]
|
||||
sogo_return = container.exec_run(cmd)
|
||||
return exec_run_handler('utf8_text_only', sogo_return)
|
||||
# api call: container_post - post_action: exec - cmd: sogo - task: set_theme
|
||||
def container_post__exec__sogo__set_theme(self, container_id, request_json):
|
||||
for container in self.docker_client.containers.list(filters={"id": container_id}):
|
||||
cmd = ["/bin/bash", "-c", "/customize.sh set_theme"]
|
||||
sogo_return = container.exec_run(cmd)
|
||||
return exec_run_handler('utf8_text_only', sogo_return)
|
||||
|
||||
# api call: container_post - post_action: exec - cmd: mailq - task: list
|
||||
def container_post__exec__mailq__list(self, container_id, request_json):
|
||||
for container in self.docker_client.containers.list(filters={"id": container_id}):
|
||||
@@ -423,15 +380,7 @@ class DockerUtils:
|
||||
if 'maildir' in request_json:
|
||||
for container in self.docker_client.containers.list(filters={"id": container_id}):
|
||||
sane_name = re.sub(r'\W+', '', request_json['maildir'])
|
||||
vmail_name = request_json['maildir'].replace("'", "'\\''")
|
||||
cmd_vmail = "if [[ -d '/var/vmail/" + vmail_name + "' ]]; then /bin/mv '/var/vmail/" + vmail_name + "' '/var/vmail/_garbage/" + str(int(time.time())) + "_" + sane_name + "'; fi"
|
||||
index_name = request_json['maildir'].split("/")
|
||||
if len(index_name) > 1:
|
||||
index_name = index_name[1].replace("'", "'\\''") + "@" + index_name[0].replace("'", "'\\''")
|
||||
cmd_vmail_index = "if [[ -d '/var/vmail_index/" + index_name + "' ]]; then /bin/mv '/var/vmail_index/" + index_name + "' '/var/vmail/_garbage/" + str(int(time.time())) + "_" + sane_name + "_index'; fi"
|
||||
cmd = ["/bin/bash", "-c", cmd_vmail + " && " + cmd_vmail_index]
|
||||
else:
|
||||
cmd = ["/bin/bash", "-c", cmd_vmail]
|
||||
cmd = ["/bin/bash", "-c", "if [[ -d '/var/vmail/" + request_json['maildir'].replace("'", "'\\''") + "' ]]; then /bin/mv '/var/vmail/" + request_json['maildir'].replace("'", "'\\''") + "' '/var/vmail/_garbage/" + str(int(time.time())) + "_" + sane_name + "'; fi"]
|
||||
maildir_cleanup = container.exec_run(cmd, user='vmail')
|
||||
return exec_run_handler('generic', maildir_cleanup)
|
||||
# api call: container_post - post_action: exec - cmd: rspamd - task: worker_password
|
||||
|
@@ -1,27 +1,17 @@
|
||||
FROM debian:bullseye-slim
|
||||
FROM debian:bullseye-slim as build
|
||||
LABEL maintainer "Andre Peters <andre.peters@servercow.de>"
|
||||
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
# renovate: datasource=github-tags depName=dovecot/core versioning=semver-coerced
|
||||
ARG DOVECOT=2.3.20
|
||||
# renovate: datasource=github-releases depName=tianon/gosu versioning=semver-coerced
|
||||
ARG GOSU_VERSION=1.16
|
||||
ARG DOVECOT=2.3.19.1
|
||||
ARG FLATCURVE=v0.3.2
|
||||
ARG XAPIAN=1.4.21
|
||||
ENV LC_ALL C
|
||||
|
||||
|
||||
# Add groups and users before installing Dovecot to not break compatibility
|
||||
RUN groupadd -g 5000 vmail \
|
||||
&& groupadd -g 401 dovecot \
|
||||
&& groupadd -g 402 dovenull \
|
||||
&& groupadd -g 999 sogo \
|
||||
&& usermod -a -G sogo nobody \
|
||||
&& useradd -g vmail -u 5000 vmail -d /var/vmail \
|
||||
&& useradd -c "Dovecot unprivileged user" -d /dev/null -u 401 -g dovecot -s /bin/false dovecot \
|
||||
&& useradd -c "Dovecot login user" -d /dev/null -u 402 -g dovenull -s /bin/false dovenull \
|
||||
&& touch /etc/default/locale \
|
||||
RUN touch /etc/default/locale \
|
||||
&& apt-get update \
|
||||
&& apt-get -y --no-install-recommends install \
|
||||
build-essential \
|
||||
apt-transport-https \
|
||||
ca-certificates \
|
||||
cpanminus \
|
||||
@@ -62,7 +52,6 @@ RUN groupadd -g 5000 vmail \
|
||||
libproc-processtable-perl \
|
||||
libreadonly-perl \
|
||||
libregexp-common-perl \
|
||||
libssl-dev \
|
||||
libsys-meminfo-perl \
|
||||
libterm-readkey-perl \
|
||||
libtest-deep-perl \
|
||||
@@ -78,7 +67,13 @@ RUN groupadd -g 5000 vmail \
|
||||
libunicode-string-perl \
|
||||
liburi-perl \
|
||||
libwww-perl \
|
||||
libstemmer-dev \
|
||||
libexttextcat-dev \
|
||||
libldap-dev \
|
||||
libghc-bzlib-dev \
|
||||
lua-sql-mysql \
|
||||
liblz4-dev \
|
||||
libzstd-dev \
|
||||
lua-socket \
|
||||
mariadb-client \
|
||||
procps \
|
||||
@@ -89,32 +84,152 @@ RUN groupadd -g 5000 vmail \
|
||||
syslog-ng-core \
|
||||
syslog-ng-mod-redis \
|
||||
wget \
|
||||
git \
|
||||
bison \
|
||||
flex \
|
||||
build-essential \
|
||||
autoconf \
|
||||
automake \
|
||||
libtool \
|
||||
make \
|
||||
libxapian-dev \
|
||||
default-libmysqlclient-dev \
|
||||
libicu-dev \
|
||||
zlib1g-dev \
|
||||
pkg-config \
|
||||
libsqlite3-dev \
|
||||
liblua5.3-dev \
|
||||
&& dpkgArch="$(dpkg --print-architecture | awk -F- '{ print $NF }')" \
|
||||
&& wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch" \
|
||||
&& chmod +x /usr/local/bin/gosu \
|
||||
&& gosu nobody true \
|
||||
&& apt-key adv --fetch-keys https://repo.dovecot.org/DOVECOT-REPO-GPG \
|
||||
&& echo "deb https://repo.dovecot.org/ce-${DOVECOT}/debian/bullseye bullseye main" > /etc/apt/sources.list.d/dovecot.list \
|
||||
&& apt-get update \
|
||||
&& apt-get -y --no-install-recommends install \
|
||||
dovecot-lua \
|
||||
dovecot-managesieved \
|
||||
dovecot-sieve \
|
||||
dovecot-lmtpd \
|
||||
dovecot-ldap \
|
||||
dovecot-mysql \
|
||||
dovecot-core \
|
||||
dovecot-pop3d \
|
||||
dovecot-imapd \
|
||||
dovecot-solr \
|
||||
&& pip3 install mysql-connector-python html2text jinja2 redis \
|
||||
&& apt-get autoremove --purge -y \
|
||||
&& apt-get autoclean \
|
||||
&& rm -rf /var/lib/apt/lists/* \
|
||||
&& rm -rf /tmp/* /var/tmp/* /root/.cache/
|
||||
# imapsync dependencies
|
||||
RUN cpan Crypt::OpenSSL::PKCS12
|
||||
&& gosu nobody true
|
||||
# && apt-key adv --fetch-keys https://repo.dovecot.org/DOVECOT-REPO-GPG \
|
||||
# && echo "deb https://repo.dovecot.org/ce-${DOVECOT}/debian/bullseye bullseye main" > /etc/apt/sources.list.d/dovecot.list \
|
||||
# && apt-get update \
|
||||
# && apt-get -y --no-install-recommends install \
|
||||
# dovecot-lua \
|
||||
# dovecot-managesieved \
|
||||
# dovecot-sieve \
|
||||
# dovecot-lmtpd \
|
||||
# dovecot-ldap \
|
||||
# dovecot-mysql \
|
||||
# dovecot-core \
|
||||
# dovecot-pop3d \
|
||||
# dovecot-imapd \
|
||||
# dovecot-dev
|
||||
|
||||
RUN cd /tmp && git clone --depth 1 --branch ${DOVECOT} https://github.com/dovecot/core.git dovecot/core && cd dovecot/core \
|
||||
&& ./autogen.sh \
|
||||
&& PANDOC=false ./configure --prefix=/usr --sysconfdir=/etc --localstatedir=/var --with-ssldir=/etc/ssl --enable-maintainer-mode --with-sql=yes --with-lua=yes --with-mysql --with-ldap --with-zstd --with-lz4 --with-ssl=openssl --with-notify=inotify --with-bzlib --with-zlib --enable-hardening --with-stemmer --with-textcat --with-icu \
|
||||
&& make -j6 \
|
||||
&& make install \
|
||||
&& make clean
|
||||
|
||||
RUN cd /tmp && git clone --depth 1 --branch release-0.5 https://github.com/dovecot/pigeonhole dovecot/pigeonhole && cd dovecot/pigeonhole \
|
||||
&& ./autogen.sh \
|
||||
&& ./configure --with-dovecot=/usr/lib/dovecot --with-managesieve\
|
||||
&& make -j6 \
|
||||
&& make install \
|
||||
&& make clean
|
||||
|
||||
RUN cd /tmp && wget https://oligarchy.co.uk/xapian/${XAPIAN}/xapian-core-${XAPIAN}.tar.xz && tar xf xapian-core-${XAPIAN}.tar.xz && cd xapian-core-${XAPIAN} \
|
||||
&& ./configure --prefix=/usr/local/xapian \
|
||||
&& make -j6 \
|
||||
&& make install \
|
||||
&& make clean
|
||||
|
||||
RUN cd /tmp && git clone --depth 1 --branch ${FLATCURVE} https://github.com/slusarz/dovecot-fts-flatcurve.git dovecot/flatcurve && cd dovecot/flatcurve \
|
||||
&& ./autogen.sh \
|
||||
&& ./configure --with-dovecot=/usr/lib/dovecot \
|
||||
&& make -j6 \
|
||||
&& make install \
|
||||
&& make clean
|
||||
|
||||
FROM debian:bullseye-slim
|
||||
RUN groupadd -g 5000 vmail \
|
||||
&& groupadd -g 401 dovecot \
|
||||
&& groupadd -g 402 dovenull \
|
||||
&& groupadd -g 999 sogo \
|
||||
&& usermod -a -G sogo nobody \
|
||||
&& useradd -g vmail -u 5000 vmail -d /var/vmail \
|
||||
&& useradd -c "Dovecot unprivileged user" -d /dev/null -u 401 -g dovecot -s /bin/false dovecot \
|
||||
&& useradd -c "Dovecot login user" -d /dev/null -u 402 -g dovenull -s /bin/false dovenull \
|
||||
&& apt update && apt install lua-socket \
|
||||
mariadb-client \
|
||||
libstemmer-dev \
|
||||
libexttextcat-dev \
|
||||
libicu-dev \
|
||||
libxapian-dev \
|
||||
libsqlite3-dev \
|
||||
liblua5.3-dev \
|
||||
lua-sql-mysql \
|
||||
libldap-dev \
|
||||
procps \
|
||||
python3-pip \
|
||||
redis-server \
|
||||
supervisor \
|
||||
syslog-ng \
|
||||
syslog-ng-core \
|
||||
syslog-ng-mod-redis \
|
||||
cpanminus \
|
||||
curl \
|
||||
libauthen-ntlm-perl \
|
||||
libcgi-pm-perl \
|
||||
libcrypt-openssl-rsa-perl \
|
||||
libcrypt-ssleay-perl \
|
||||
libdata-uniqid-perl \
|
||||
libdbd-mysql-perl \
|
||||
libdbi-perl \
|
||||
libdigest-hmac-perl \
|
||||
libdist-checkconflicts-perl \
|
||||
libencode-imaputf7-perl \
|
||||
libfile-copy-recursive-perl \
|
||||
libfile-tail-perl \
|
||||
libhtml-parser-perl \
|
||||
libio-compress-perl \
|
||||
libio-socket-inet6-perl \
|
||||
libio-socket-ssl-perl \
|
||||
libio-tee-perl \
|
||||
libipc-run-perl \
|
||||
libjson-webtoken-perl \
|
||||
liblockfile-simple-perl \
|
||||
libmail-imapclient-perl \
|
||||
libmodule-implementation-perl \
|
||||
libmodule-scandeps-perl \
|
||||
libnet-ssleay-perl \
|
||||
libpackage-stash-perl \
|
||||
libpackage-stash-xs-perl \
|
||||
libpar-packer-perl \
|
||||
libparse-recdescent-perl \
|
||||
libproc-processtable-perl \
|
||||
libreadonly-perl \
|
||||
libregexp-common-perl \
|
||||
libsys-meminfo-perl \
|
||||
libterm-readkey-perl \
|
||||
libtest-deep-perl \
|
||||
libtest-fatal-perl \
|
||||
libtest-mock-guard-perl \
|
||||
libtest-mockobject-perl \
|
||||
libtest-nowarnings-perl \
|
||||
libtest-pod-perl \
|
||||
libtest-requires-perl \
|
||||
libtest-simple-perl \
|
||||
libtest-warn-perl \
|
||||
libtry-tiny-perl \
|
||||
libunicode-string-perl \
|
||||
liburi-perl \
|
||||
libwww-perl \
|
||||
dnsutils \
|
||||
gettext-base -y --no-install-recommends \
|
||||
&& pip3 install mysql-connector-python html2text jinja2 redis
|
||||
COPY --from=build /usr/lib/dovecot /usr/lib/dovecot
|
||||
COPY --from=build /usr/bin/doveconf /usr/bin/doveconf
|
||||
COPY --from=build /usr/bin/doveadm /usr/bin/doveadm
|
||||
COPY --from=build /usr/bin/dovecot-sysreport /usr/bin/dovecot-sysreport
|
||||
COPY --from=build /usr/sbin/dovecot /usr/sbin/dovecot
|
||||
COPY --from=build /usr/libexec/dovecot/ /usr/libexec/dovecot/
|
||||
COPY --from=build /usr/local/bin /usr/local/bin
|
||||
COPY --from=build /usr/local/xapian/ /usr/local/xapian
|
||||
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
|
||||
|
@@ -109,17 +109,19 @@ EOF
|
||||
|
||||
echo -n ${ACL_ANYONE} > /etc/dovecot/acl_anyone
|
||||
|
||||
if [[ "${SKIP_SOLR}" =~ ^([yY][eE][sS]|[yY])+$ ]]; then
|
||||
if [[ "${SKIP_XAPIAN}" =~ ^([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
|
||||
else
|
||||
echo -n 'quota acl zlib mail_crypt mail_crypt_acl mail_log notify fts fts_solr 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_solr listescape replication' > /etc/dovecot/mail_plugins_imap
|
||||
echo -n 'quota sieve acl zlib mail_crypt mail_crypt_acl fts fts_solr notify listescape replication' > /etc/dovecot/mail_plugins_lmtp
|
||||
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
|
||||
fi
|
||||
chmod 644 /etc/dovecot/mail_plugins /etc/dovecot/mail_plugins_imap /etc/dovecot/mail_plugins_lmtp /templates/quarantine.tpl
|
||||
|
||||
sed -i 's/vsz_limit.*/vsz_limit = '${XAPIAN_HEAP}m/g /etc/dovecot/dovecot-fts-flatcurve.conf
|
||||
|
||||
cat <<EOF > /etc/dovecot/sql/dovecot-dict-sql-userdb.conf
|
||||
# Autogenerated by mailcow
|
||||
driver = mysql
|
||||
|
@@ -8492,7 +8492,6 @@ sub xoauth2
|
||||
require HTML::Entities ;
|
||||
require JSON ;
|
||||
require JSON::WebToken::Crypt::RSA ;
|
||||
require Crypt::OpenSSL::PKCS12;
|
||||
require Crypt::OpenSSL::RSA ;
|
||||
require Encode::Byte ;
|
||||
require IO::Socket::SSL ;
|
||||
@@ -8533,9 +8532,8 @@ sub xoauth2
|
||||
|
||||
$sync->{ debug } and myprint( "Service account: $iss\nKey file: $keyfile\nKey password: $keypass\n");
|
||||
|
||||
# Get private key from p12 file
|
||||
my $pkcs12 = Crypt::OpenSSL::PKCS12->new_from_file($keyfile);
|
||||
$key = $pkcs12->private_key($keypass);
|
||||
# Get private key from p12 file (would be better in perl...)
|
||||
$key = `openssl pkcs12 -in "$keyfile" -nodes -nocerts -passin pass:$keypass -nomacver`;
|
||||
|
||||
$sync->{ debug } and myprint( "Private key:\n$key\n");
|
||||
}
|
||||
|
@@ -64,40 +64,28 @@ def refreshF2boptions():
|
||||
global f2boptions
|
||||
global quit_now
|
||||
global exit_code
|
||||
|
||||
f2boptions = {}
|
||||
|
||||
if not r.get('F2B_OPTIONS'):
|
||||
f2boptions['ban_time'] = r.get('F2B_BAN_TIME')
|
||||
f2boptions['max_ban_time'] = r.get('F2B_MAX_BAN_TIME')
|
||||
f2boptions['ban_time_increment'] = r.get('F2B_BAN_TIME_INCREMENT')
|
||||
f2boptions['max_attempts'] = r.get('F2B_MAX_ATTEMPTS')
|
||||
f2boptions['retry_window'] = r.get('F2B_RETRY_WINDOW')
|
||||
f2boptions['netban_ipv4'] = r.get('F2B_NETBAN_IPV4')
|
||||
f2boptions['netban_ipv6'] = r.get('F2B_NETBAN_IPV6')
|
||||
f2boptions = {}
|
||||
f2boptions['ban_time'] = int
|
||||
f2boptions['max_attempts'] = int
|
||||
f2boptions['retry_window'] = int
|
||||
f2boptions['netban_ipv4'] = int
|
||||
f2boptions['netban_ipv6'] = int
|
||||
f2boptions['ban_time'] = r.get('F2B_BAN_TIME') or 1800
|
||||
f2boptions['max_attempts'] = r.get('F2B_MAX_ATTEMPTS') or 10
|
||||
f2boptions['retry_window'] = r.get('F2B_RETRY_WINDOW') or 600
|
||||
f2boptions['netban_ipv4'] = r.get('F2B_NETBAN_IPV4') or 32
|
||||
f2boptions['netban_ipv6'] = r.get('F2B_NETBAN_IPV6') or 128
|
||||
r.set('F2B_OPTIONS', json.dumps(f2boptions, ensure_ascii=False))
|
||||
else:
|
||||
try:
|
||||
f2boptions = {}
|
||||
f2boptions = json.loads(r.get('F2B_OPTIONS'))
|
||||
except ValueError:
|
||||
print('Error loading F2B options: F2B_OPTIONS is not json')
|
||||
quit_now = True
|
||||
exit_code = 2
|
||||
|
||||
verifyF2boptions(f2boptions)
|
||||
r.set('F2B_OPTIONS', json.dumps(f2boptions, ensure_ascii=False))
|
||||
|
||||
def verifyF2boptions(f2boptions):
|
||||
verifyF2boption(f2boptions,'ban_time', 1800)
|
||||
verifyF2boption(f2boptions,'max_ban_time', 10000)
|
||||
verifyF2boption(f2boptions,'ban_time_increment', True)
|
||||
verifyF2boption(f2boptions,'max_attempts', 10)
|
||||
verifyF2boption(f2boptions,'retry_window', 600)
|
||||
verifyF2boption(f2boptions,'netban_ipv4', 32)
|
||||
verifyF2boption(f2boptions,'netban_ipv6', 128)
|
||||
|
||||
def verifyF2boption(f2boptions, f2boption, f2bdefault):
|
||||
f2boptions[f2boption] = f2boptions[f2boption] if f2boption in f2boptions and f2boptions[f2boption] is not None else f2bdefault
|
||||
|
||||
def refreshF2bregex():
|
||||
global f2bregex
|
||||
global quit_now
|
||||
@@ -159,7 +147,6 @@ def ban(address):
|
||||
global lock
|
||||
refreshF2boptions()
|
||||
BAN_TIME = int(f2boptions['ban_time'])
|
||||
BAN_TIME_INCREMENT = bool(f2boptions['ban_time_increment'])
|
||||
MAX_ATTEMPTS = int(f2boptions['max_attempts'])
|
||||
RETRY_WINDOW = int(f2boptions['retry_window'])
|
||||
NETBAN_IPV4 = '/' + str(f2boptions['netban_ipv4'])
|
||||
@@ -187,16 +174,20 @@ def ban(address):
|
||||
net = ipaddress.ip_network((address + (NETBAN_IPV4 if type(ip) is ipaddress.IPv4Address else NETBAN_IPV6)), strict=False)
|
||||
net = str(net)
|
||||
|
||||
if not net in bans:
|
||||
bans[net] = {'attempts': 0, 'last_attempt': 0, 'ban_counter': 0}
|
||||
if not net in bans or time.time() - bans[net]['last_attempt'] > RETRY_WINDOW:
|
||||
bans[net] = { 'attempts': 0 }
|
||||
active_window = RETRY_WINDOW
|
||||
else:
|
||||
active_window = time.time() - bans[net]['last_attempt']
|
||||
|
||||
bans[net]['attempts'] += 1
|
||||
bans[net]['last_attempt'] = time.time()
|
||||
|
||||
active_window = time.time() - bans[net]['last_attempt']
|
||||
|
||||
if bans[net]['attempts'] >= MAX_ATTEMPTS:
|
||||
cur_time = int(round(time.time()))
|
||||
NET_BAN_TIME = BAN_TIME if not BAN_TIME_INCREMENT else BAN_TIME * 2 ** bans[net]['ban_counter']
|
||||
logCrit('Banning %s for %d minutes' % (net, NET_BAN_TIME / 60 ))
|
||||
logCrit('Banning %s for %d minutes' % (net, BAN_TIME / 60))
|
||||
if type(ip) is ipaddress.IPv4Address:
|
||||
with lock:
|
||||
chain = iptc.Chain(iptc.Table(iptc.Table.FILTER), 'MAILCOW')
|
||||
@@ -215,7 +206,7 @@ def ban(address):
|
||||
rule.target = target
|
||||
if rule not in chain.rules:
|
||||
chain.insert_rule(rule)
|
||||
r.hset('F2B_ACTIVE_BANS', '%s' % net, cur_time + NET_BAN_TIME)
|
||||
r.hset('F2B_ACTIVE_BANS', '%s' % net, cur_time + BAN_TIME)
|
||||
else:
|
||||
logWarn('%d more attempts in the next %d seconds until %s is banned' % (MAX_ATTEMPTS - bans[net]['attempts'], RETRY_WINDOW, net))
|
||||
|
||||
@@ -247,8 +238,7 @@ def unban(net):
|
||||
r.hdel('F2B_ACTIVE_BANS', '%s' % net)
|
||||
r.hdel('F2B_QUEUE_UNBAN', '%s' % net)
|
||||
if net in bans:
|
||||
bans[net]['attempts'] = 0
|
||||
bans[net]['ban_counter'] += 1
|
||||
del bans[net]
|
||||
|
||||
def permBan(net, unban=False):
|
||||
global lock
|
||||
@@ -342,7 +332,7 @@ def watch():
|
||||
logWarn('%s matched rule id %s (%s)' % (addr, rule_id, item['data']))
|
||||
ban(addr)
|
||||
except Exception as ex:
|
||||
logWarn('Error reading log line from pubsub: %s' % ex)
|
||||
logWarn('Error reading log line from pubsub')
|
||||
quit_now = True
|
||||
exit_code = 2
|
||||
|
||||
@@ -376,8 +366,6 @@ def snat4(snat_target):
|
||||
chain.insert_rule(new_rule)
|
||||
else:
|
||||
for position, rule in enumerate(chain.rules):
|
||||
if not hasattr(rule.target, 'parameter'):
|
||||
continue
|
||||
match = all((
|
||||
new_rule.get_src() == rule.get_src(),
|
||||
new_rule.get_dst() == rule.get_dst(),
|
||||
@@ -437,8 +425,6 @@ def autopurge():
|
||||
time.sleep(10)
|
||||
refreshF2boptions()
|
||||
BAN_TIME = int(f2boptions['ban_time'])
|
||||
MAX_BAN_TIME = int(f2boptions['max_ban_time'])
|
||||
BAN_TIME_INCREMENT = bool(f2boptions['ban_time_increment'])
|
||||
MAX_ATTEMPTS = int(f2boptions['max_attempts'])
|
||||
QUEUE_UNBAN = r.hgetall('F2B_QUEUE_UNBAN')
|
||||
if QUEUE_UNBAN:
|
||||
@@ -446,9 +432,7 @@ def autopurge():
|
||||
unban(str(net))
|
||||
for net in bans.copy():
|
||||
if bans[net]['attempts'] >= MAX_ATTEMPTS:
|
||||
NET_BAN_TIME = BAN_TIME if not BAN_TIME_INCREMENT else BAN_TIME * 2 ** bans[net]['ban_counter']
|
||||
TIME_SINCE_LAST_ATTEMPT = time.time() - bans[net]['last_attempt']
|
||||
if TIME_SINCE_LAST_ATTEMPT > NET_BAN_TIME or TIME_SINCE_LAST_ATTEMPT > MAX_BAN_TIME:
|
||||
if time.time() - bans[net]['last_attempt'] > BAN_TIME:
|
||||
unban(net)
|
||||
|
||||
def isIpNetwork(address):
|
||||
|
@@ -1,4 +1,4 @@
|
||||
FROM php:8.2-fpm-alpine3.17
|
||||
FROM php:8.1-fpm-alpine3.17
|
||||
LABEL maintainer "Andre Peters <andre.peters@servercow.de>"
|
||||
|
||||
# renovate: datasource=github-tags depName=krakjoe/apcu versioning=semver-coerced
|
||||
@@ -12,7 +12,7 @@ ARG MEMCACHED_PECL_VERSION=3.2.0
|
||||
# renovate: datasource=github-tags depName=phpredis/phpredis versioning=semver-coerced
|
||||
ARG REDIS_PECL_VERSION=5.3.7
|
||||
# renovate: datasource=github-tags depName=composer/composer versioning=semver-coerced
|
||||
ARG COMPOSER_VERSION=2.5.5
|
||||
ARG COMPOSER_VERSION=2.5.4
|
||||
|
||||
RUN apk add -U --no-cache autoconf \
|
||||
aspell-dev \
|
||||
@@ -52,7 +52,6 @@ RUN apk add -U --no-cache autoconf \
|
||||
libxpm-dev \
|
||||
libzip \
|
||||
libzip-dev \
|
||||
linux-headers \
|
||||
make \
|
||||
mysql-client \
|
||||
openldap-dev \
|
||||
@@ -76,7 +75,7 @@ RUN apk add -U --no-cache autoconf \
|
||||
--with-webp \
|
||||
--with-xpm \
|
||||
--with-avif \
|
||||
&& docker-php-ext-install -j 4 exif gd gettext intl ldap opcache pcntl pdo pdo_mysql pspell soap sockets sysvsem zip bcmath gmp \
|
||||
&& docker-php-ext-install -j 4 exif gd gettext intl ldap opcache pcntl pdo pdo_mysql pspell soap sockets zip bcmath gmp \
|
||||
&& docker-php-ext-configure imap --with-imap --with-imap-ssl \
|
||||
&& docker-php-ext-install -j 4 imap \
|
||||
&& curl --silent --show-error https://getcomposer.org/installer | php -- --version=${COMPOSER_VERSION} \
|
||||
@@ -100,7 +99,6 @@ RUN apk add -U --no-cache autoconf \
|
||||
libxml2-dev \
|
||||
libxpm-dev \
|
||||
libzip-dev \
|
||||
linux-headers \
|
||||
make \
|
||||
openldap-dev \
|
||||
pcre-dev \
|
||||
|
@@ -25,7 +25,6 @@ RUN echo "Building from repository $SOGO_DEBIAN_REPOSITORY" \
|
||||
psmisc \
|
||||
wget \
|
||||
patch \
|
||||
redis-tools \
|
||||
&& dpkgArch="$(dpkg --print-architecture | awk -F- '{ print $NF }')" \
|
||||
&& wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch" \
|
||||
&& chmod +x /usr/local/bin/gosu \
|
||||
@@ -47,14 +46,10 @@ COPY syslog-ng-redis_slave.conf /etc/syslog-ng/syslog-ng-redis_slave.conf
|
||||
COPY supervisord.conf /etc/supervisor/supervisord.conf
|
||||
COPY acl.diff /acl.diff
|
||||
COPY stop-supervisor.sh /usr/local/sbin/stop-supervisor.sh
|
||||
COPY customize.sh /
|
||||
COPY docker-entrypoint.sh /
|
||||
|
||||
RUN rm -rf /usr/lib/GNUstep/SOGo/WebServerResources/img/sogo-full.svg
|
||||
RUN mv /usr/lib/GNUstep/SOGo/WebServerResources/img/sogo.ico /sogo.ico
|
||||
RUN chmod +x /bootstrap-sogo.sh \
|
||||
/usr/local/sbin/stop-supervisor.sh \
|
||||
/customize.sh
|
||||
/usr/local/sbin/stop-supervisor.sh
|
||||
|
||||
ENTRYPOINT ["/docker-entrypoint.sh"]
|
||||
|
||||
|
@@ -240,8 +240,6 @@ chmod 600 /var/lib/sogo/GNUstep/Defaults/sogod.plist
|
||||
|
||||
# Copy logo, if any
|
||||
[[ -f /etc/sogo/sogo-full.svg ]] && cp /etc/sogo/sogo-full.svg /usr/lib/GNUstep/SOGo/WebServerResources/img/sogo-full.svg
|
||||
# Use the mailcow logo if no sogo-full.svg file does exist
|
||||
! [[ -f /usr/lib/GNUstep/SOGo/WebServerResources/img/sogo-full.svg ]] && cp /etc/sogo/cow_mailcow.svg /usr/lib/GNUstep/SOGo/WebServerResources/img/sogo-full.svg
|
||||
|
||||
# Rsync web content
|
||||
echo "Syncing web content with named volume"
|
||||
|
@@ -1,112 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [[ "$1" == "enable" ]]; then
|
||||
# enable debug mode
|
||||
if grep -q "SOGoUIxDebugEnabled = YES;" "/etc/sogo/sogo.conf"; then
|
||||
sed -i "s|//SOGoUIxDebugEnabled = YES;|SOGoUIxDebugEnabled = YES;|" "/etc/sogo/sogo.conf"
|
||||
else
|
||||
echo "SOGoUIxDebugEnabled = YES;" >> "/etc/sogo/sogo.conf"
|
||||
fi
|
||||
|
||||
echo "Success: SOGoUIxDebugEnabled has been enabled"
|
||||
elif [[ "$1" == "disable" ]]; then
|
||||
# disable debug mode
|
||||
if grep -q "SOGoUIxDebugEnabled = YES;" "/etc/sogo/sogo.conf"; then
|
||||
if ! grep -q "//SOGoUIxDebugEnabled = YES;" "/etc/sogo/sogo.conf"; then
|
||||
sed -i "s|SOGoUIxDebugEnabled = YES;|//SOGoUIxDebugEnabled = YES;|" "/etc/sogo/sogo.conf"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "Success: SOGoUIxDebugEnabled has been disabled"
|
||||
elif [[ "$1" == "set_theme" ]]; then
|
||||
# Get the sogo palettes from Redis
|
||||
PRIMARY=$(redis-cli -h redis HGET SOGO_THEME primary)
|
||||
if [ $? -ne 0 ]; then
|
||||
PRIMARY="green"
|
||||
fi
|
||||
ACCENT=$(redis-cli -h redis HGET SOGO_THEME accent)
|
||||
if [ $? -ne 0 ]; then
|
||||
ACCENT="green"
|
||||
fi
|
||||
BACKGROUND=$(redis-cli -h redis HGET SOGO_THEME background)
|
||||
if [ $? -ne 0 ]; then
|
||||
BACKGROUND="grey"
|
||||
fi
|
||||
|
||||
# Read custom palettes
|
||||
if [ -f /etc/sogo/custom-palettes.js ]; then
|
||||
COLORS=$(cat /etc/sogo/custom-palettes.js)
|
||||
else
|
||||
COLORS=""
|
||||
fi
|
||||
|
||||
# Write theme to /usr/lib/GNUstep/SOGo/WebServerResources/js/theme.js
|
||||
cat > /usr/lib/GNUstep/SOGo/WebServerResources/js/theme.js <<EOL
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
angular.module('SOGo.Common')
|
||||
.config(configure)
|
||||
|
||||
configure.\$inject = ['\$mdThemingProvider'];
|
||||
function configure(\$mdThemingProvider) {
|
||||
|
||||
$COLORS
|
||||
|
||||
var primary = \$mdThemingProvider.extendPalette('$PRIMARY', {});
|
||||
var accent = \$mdThemingProvider.extendPalette('$ACCENT', {
|
||||
'A100': 'ffffff'
|
||||
});
|
||||
var background = \$mdThemingProvider.extendPalette('$BACKGROUND', {});
|
||||
|
||||
\$mdThemingProvider.definePalette('primary-cow', primary);
|
||||
\$mdThemingProvider.definePalette('accent-cow', accent);
|
||||
\$mdThemingProvider.definePalette('background-cow', background);
|
||||
|
||||
\$mdThemingProvider.theme('default')
|
||||
.primaryPalette('primary-cow', primarySettings)
|
||||
.accentPalette('accent-cow', accentSettings)
|
||||
.backgroundPalette('background-cow', backgroundSettings);
|
||||
\$mdThemingProvider.generateThemesOnDemand(false);
|
||||
}
|
||||
})();
|
||||
EOL
|
||||
|
||||
echo "Success: Theme configuration written"
|
||||
elif [[ "$1" == "set_logo" ]]; then
|
||||
# Get the image data from Redis and save it to a tmp file
|
||||
redis-cli -h redis GET MAIN_LOGO > /tmp/logo_base64.txt
|
||||
|
||||
# Check if mime type is svg+xml
|
||||
mime_type=$(awk -F'[:;]' '{print $2}' /tmp/logo_base64.txt | sed 's/.*\///')
|
||||
if [ "$mime_type" != "svg+xml" ]; then
|
||||
echo "Error: Image format must be of type svg"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Decode base64 and save to file
|
||||
payload=$(cat /tmp/logo_base64.txt | sed 's/^data:[^;]*;//' | awk '{ sub(/^base64,/, ""); print $0 }')
|
||||
echo $payload | base64 -d | tee /usr/lib/GNUstep/SOGo/WebServerResources/img/sogo-full.svg > /dev/null
|
||||
|
||||
# Remove temp file
|
||||
rm /tmp/logo_base64.txt
|
||||
echo "Success: Image has been set"
|
||||
elif [[ "$1" == "set_favicon" ]]; then
|
||||
# Get the image data from Redis and save it to a tmp file
|
||||
redis-cli -h redis GET FAVICON > /tmp/favicon_base64.txt
|
||||
|
||||
# Check if mime type is png or ico
|
||||
mime_type=$(awk -F'[:;]' '{print $2}' /tmp/favicon_base64.txt | sed 's/.*\///')
|
||||
if [[ "$mime_type" != "png" && "$mime_type" != "ico" ]]; then
|
||||
echo "Error: Image format must be of type png or ico"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Decode base64 and save to file
|
||||
payload=$(cat /tmp/favicon_base64.txt | sed 's/^data:[^;]*;//' | awk '{ sub(/^base64,/, ""); print $0 }')
|
||||
echo $payload | base64 -d | tee /usr/lib/GNUstep/SOGo/WebServerResources/img/sogo.ico > /dev/null
|
||||
|
||||
# Remove temp file
|
||||
rm /tmp/favicon_base64.txt
|
||||
echo "Success: Image has been set"
|
||||
fi
|
@@ -24,7 +24,7 @@ server {
|
||||
add_header X-Download-Options "noopen" always;
|
||||
add_header X-Frame-Options "SAMEORIGIN" always;
|
||||
add_header X-Permitted-Cross-Domain-Policies "none" always;
|
||||
add_header X-Robots-Tag "noindex, nofollow" always;
|
||||
add_header X-Robots-Tag "none" always;
|
||||
add_header X-XSS-Protection "1; mode=block" always;
|
||||
|
||||
fastcgi_hide_header X-Powered-By;
|
||||
|
23
data/conf/dovecot/dovecot-fts-flatcurve.conf
Normal file
23
data/conf/dovecot/dovecot-fts-flatcurve.conf
Normal file
@@ -0,0 +1,23 @@
|
||||
plugin {
|
||||
fts = flatcurve
|
||||
fts_autoindex = yes
|
||||
|
||||
fts_languages = en de
|
||||
|
||||
fts_tokenizers = generic email-address
|
||||
fts_tokenizer_generic = algorithm=simple
|
||||
# All of these are optional, and indicate the default values.
|
||||
# They are listed here for documentation purposes; most people should
|
||||
# not need to define/override in their config.
|
||||
fts_flatcurve_commit_limit = 500
|
||||
fts_flatcurve_max_term_size = 30
|
||||
fts_flatcurve_min_term_size = 2
|
||||
fts_flatcurve_optimize_limit = 10
|
||||
fts_flatcurve_rotate_size = 5000
|
||||
fts_flatcurve_rotate_time = 5000
|
||||
fts_flatcurve_substring_search = yes
|
||||
}
|
||||
|
||||
service indexer-worker {
|
||||
vsz_limit = 1024m
|
||||
}
|
@@ -11,6 +11,7 @@ auth_mechanisms = plain login
|
||||
#mail_debug = yes
|
||||
#auth_debug = yes
|
||||
log_path = syslog
|
||||
log_debug = category=fts-flatcurve
|
||||
disable_plaintext_auth = yes
|
||||
# Uncomment on NFS share
|
||||
#mmap_disable = yes
|
||||
@@ -189,9 +190,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
|
||||
@@ -242,6 +240,7 @@ plugin {
|
||||
mail_log_events = delete undelete expunge copy mailbox_delete mailbox_rename
|
||||
mail_log_fields = uid box msgid size
|
||||
mail_log_cached_only = yes
|
||||
|
||||
}
|
||||
service quota-warning {
|
||||
executable = script /usr/local/bin/quota_notify.py
|
||||
@@ -297,6 +296,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/dovecot-fts-flatcurve.conf
|
||||
# </Includes>
|
||||
default_client_limit = 10400
|
||||
default_vsz_limit = 1024 M
|
||||
|
@@ -8,7 +8,7 @@ VIRUS_FOUND {
|
||||
}
|
||||
# Bad policy from free mail providers
|
||||
FREEMAIL_POLICY_FAILURE {
|
||||
expression = "FREEMAIL_FROM & !DMARC_POLICY_ALLOW & !MAILLIST& !WHITELISTED_FWD_HOST & -g+:policies";
|
||||
expression = "-g+:policies & !DMARC_POLICY_ALLOW & !MAILLIST & ( FREEMAIL_ENVFROM | FREEMAIL_FROM ) & !WHITELISTED_FWD_HOST";
|
||||
score = 16.0;
|
||||
}
|
||||
# Applies to freemail with undisclosed recipients
|
||||
|
@@ -159,8 +159,8 @@ BAZAAR_ABUSE_CH {
|
||||
}
|
||||
|
||||
URLHAUS_ABUSE_CH {
|
||||
type = "selector";
|
||||
selector = "urls";
|
||||
type = "url";
|
||||
filter = "full";
|
||||
map = "https://urlhaus.abuse.ch/downloads/text_online/";
|
||||
score = 10.0;
|
||||
}
|
||||
|
@@ -1,182 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
version="1.1"
|
||||
id="layer1"
|
||||
x="0px"
|
||||
y="0px"
|
||||
width="434.82101"
|
||||
height="376.871"
|
||||
viewBox="0 0 434.82101 376.871"
|
||||
enable-background="new 0 0 374.82 356.871"
|
||||
xml:space="preserve"
|
||||
inkscape:version="0.91 r13725"
|
||||
sodipodi:docname="cow_mailcow.svg"><metadata
|
||||
id="metadata77"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title><cc:license
|
||||
rdf:resource="" /></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs75" /><sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1721"
|
||||
inkscape:window-height="1177"
|
||||
id="namedview73"
|
||||
showgrid="false"
|
||||
inkscape:zoom="1.4142136"
|
||||
inkscape:cx="219.01206"
|
||||
inkscape:cy="236.74714"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="layer1"
|
||||
fit-margin-top="10"
|
||||
fit-margin-left="50"
|
||||
fit-margin-bottom="10"
|
||||
fit-margin-right="10"
|
||||
showguides="true" /><g
|
||||
id="g3"
|
||||
transform="translate(50,10)"><g
|
||||
id="grey_5_"><path
|
||||
d="m 55.948,213.25 c 0.07331,-20.26146 -0.716379,-17.26061 -3.655806,-39.26743 2.227824,-22.4392 -7.627923,-38.85857 -7.669233,-58.34044 0,-4.715 -5.805961,-6.78013 -4.760961,-11.13713 -6.292,13.037 -9.833,27.707 -9.833,43.222 0,25.946 9.89,49.533 26.027,67.059 -0.048,-0.511 -0.082,-1.023 -0.108,-1.536 z"
|
||||
id="path6"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#3d5263"
|
||||
sodipodi:nodetypes="ccccscc" /></g><g
|
||||
id="yellow"><path
|
||||
d="m 254.808,180.412 -0.567,0.455 c -10.49,39.88 -40.951,71.658 -80.048,83.996 l 10.952,9.206 53.296,44.799 31.601,26.563 c 0.783,-2.011 1.229,-4.19 1.231,-6.478 0,-0.007 10e-4,-0.013 10e-4,-0.02 l 0,-16.836 0,-10e-4 0,-28.141 0,-126.736 -16.466,13.193 z"
|
||||
id="path9"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#f9e82d" /><path
|
||||
d="m 23.027,185.52 -6.574,-5.225 -16.452,-13.076 0,90.407 0,81.307 c 0,2.295 0.447,4.481 1.233,6.499 l 58.39,-48.683 26.964,-22.481 12.38,-10.321 C 62.73,251.524 34.307,222.274 23.027,185.52 Z"
|
||||
id="path11"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#f9e82d" /><path
|
||||
d="m 238.441,318.868 -53.296,-44.799 -10.952,-9.206 c -11.431,3.607 -23.597,5.558 -36.22,5.558 -13.653,0 -26.772,-2.28 -39.004,-6.474 l -12.38,10.321 -26.965,22.482 -58.39,48.683 c 2.605,6.69 9.094,11.438 16.706,11.438 l 235.394,0 c 7.613,0 14.103,-4.749 16.707,-11.44 l -31.6,-26.563 z"
|
||||
id="path13"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#edd514;fill-opacity:0.89499996" /></g><g
|
||||
id="grey_4_"><path
|
||||
enable-background="new "
|
||||
d="M 238.441,318.868 C 196.984,322.876 123.368,324.434 59.625,296.75 38.082,287.394 17.666,274.7 0.002,257.627 l 0,81.307 c 0,2.295 0.447,4.481 1.233,6.499 2.605,6.69 9.094,11.438 16.706,11.438 l 235.394,0 c 7.613,0 14.103,-4.749 16.707,-11.44 0.783,-2.011 1.229,-4.19 1.231,-6.478 l 0,-24.584 c 0,0 -12.58,2.541 -32.832,4.499 z"
|
||||
id="path16"
|
||||
inkscape:connector-curvature="0"
|
||||
style="opacity:0.1;fill:#3d5263" /><path
|
||||
enable-background="new "
|
||||
d="m 86.588,274.268 c 14.979,6.703 31.579,10.435 49.051,10.435 17.648,0 34.408,-3.803 49.505,-10.634 37.082,-16.777 64.125,-51.824 69.664,-93.657 l -0.567,0.455 c -10.49,39.88 -40.951,71.658 -80.048,83.996 -11.431,3.607 -23.597,5.558 -36.22,5.558 -13.653,0 -26.772,-2.28 -39.004,-6.474 C 62.731,251.524 34.308,222.274 23.028,185.52 l -6.574,-5.225 c 5.525,42.054 32.786,77.261 70.134,93.973 z"
|
||||
id="path18"
|
||||
inkscape:connector-curvature="0"
|
||||
style="opacity:0.1;fill:#3d5263" /></g><g
|
||||
id="white_1_"><path
|
||||
d="m 54.293,63.875 c -1.799,1.745 -3.541,3.548 -5.229,5.402 -0.042,0.046 -0.085,0.092 -0.127,0.139 -0.234,0.258 -0.473,0.51 -0.705,0.77 0.055,-0.055 0.111,-0.108 0.166,-0.163 21.76,-21.782 51.828,-35.259 85.046,-35.259 66.396,0 120.222,53.826 120.222,120.223 0,30.718 -11.526,58.74 -30.482,79.991 21.633,-21.737 35.006,-51.7 35.01,-84.791 0,-0.004 0,-0.009 0,-0.013 0,-21.143 -5.465,-41.007 -15.049,-58.269 -1.449,-2.608 -2.991,-5.157 -4.624,-7.643 -5.377,-8.187 -11.727,-15.676 -18.885,-22.307 -5.903,-5.467 -12.351,-10.354 -19.26,-14.558 -4.278,-2.604 -8.734,-4.944 -13.341,-7.006 -10.627,-4.756 -22.07,-8.016 -34.062,-9.509 -4.915,-0.612 -9.921,-0.931 -15.001,-0.931 -5.747,0 -11.398,0.409 -16.93,1.189 -12.291,1.733 -23.981,5.329 -34.784,10.487 -4.742,2.264 -9.313,4.83 -13.688,7.672 -6.561,4.266 -12.682,9.149 -18.277,14.576 z"
|
||||
id="path21"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#ffffff" /><path
|
||||
d="m 95.828,118.535 c 2.559,0 4.63,-2.071 4.63,-4.629 0,-2.553 -2.071,-4.626 -4.63,-4.626 -2.558,0 -4.634,2.074 -4.634,4.626 10e-4,2.557 2.076,4.629 4.634,4.629 z"
|
||||
id="path23"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#ffffff" /><path
|
||||
d="m 186.85,118.535 c 2.556,0 4.629,-2.071 4.629,-4.629 0,-2.553 -2.074,-4.626 -4.629,-4.626 -2.559,0 -4.631,2.074 -4.631,4.626 0,2.557 2.073,4.629 4.631,4.629 z"
|
||||
id="path25"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#ffffff" /></g><g
|
||||
id="grey_3_"><g
|
||||
id="g28"><path
|
||||
d="m 223.701,234.394 c 18.648,-21.18 29.965,-48.971 29.965,-79.408 0,-66.396 -53.825,-120.223 -120.222,-120.223 -33.218,0 -63.286,13.477 -85.046,35.259 -4.591,5.125 -8.746,10.647 -12.413,16.507 -1.524,2.437 -2.963,4.931 -4.314,7.48 -7.067,13.341 -11.704,28.167 -13.301,43.893 -0.411,4.043 -0.622,8.146 -0.622,12.298 0,3.849 0.188,7.653 0.542,11.409 0.776,8.241 2.38,16.24 4.735,23.912 11.281,36.754 39.703,66.004 75.941,78.427 12.231,4.193 25.351,6.474 39.004,6.474 12.623,0 24.79,-1.95 36.22,-5.558 18.139,-5.725 34.412,-15.64 47.7,-28.603 0.536,-0.522 1.811,-1.867 1.811,-1.867 z m -5.788,-58.356 c -2.132,7.217 -5.052,14.085 -8.668,20.495 -16.571,29.372 -47.64,49.146 -83.233,49.146 -27.584,0 -52.447,-11.88 -69.956,-30.895 C 39.919,197.26 30.03,173.673 30.03,147.726 c 0,-15.515 3.54,-30.185 9.833,-43.222 15.648,-32.42 48.344,-54.73 86.15,-54.73 3.967,0 7.876,0.25 11.717,0.728 47.479,5.898 84.262,47.175 84.262,97.224 -0.002,9.846 -1.431,19.348 -4.079,28.312 z"
|
||||
id="path30"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#f1f2f2" /></g><path
|
||||
d="m 49.064,69.277 c -0.042,0.046 -0.085,0.092 -0.127,0.139 0.042,-0.047 0.085,-0.093 0.127,-0.139 z"
|
||||
id="path32"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#f1f2f2" /></g><g
|
||||
id="darkbrown_1_"><path
|
||||
d="m 257.626,161.89 c -0.488,5.062 -1.29,10.032 -2.387,14.89 -0.31,1.371 -0.643,2.733 -0.999,4.086 l 0.567,-0.455 16.466,-13.193 0,-0.023 -13.647,-5.305 z"
|
||||
id="path35"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#5a3620" /><path
|
||||
d="m 0.001,167.219 16.451,13.076 6.574,5.225 c -2.354,-7.672 -3.959,-15.671 -4.735,-23.912 l -2.85,0.871 L 0,167.196"
|
||||
id="path37"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#5a3620" /><path
|
||||
d="m 87.491,192.337 c -6.21,0 -11.254,5.034 -11.254,11.257 0,6.216 5.043,11.257 11.254,11.257 6.221,0 11.261,-5.041 11.261,-11.257 0,-6.223 -5.041,-11.257 -11.261,-11.257 z"
|
||||
id="path39"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#5a3620" /><path
|
||||
d="m 181.307,192.337 c -6.218,0 -11.259,5.034 -11.259,11.257 0,6.216 5.041,11.257 11.259,11.257 6.22,0 11.257,-5.041 11.257,-11.257 0,-6.223 -5.037,-11.257 -11.257,-11.257 z"
|
||||
id="path41"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#5a3620" /><path
|
||||
d="m 182.997,102.25057 c -6.963,0 -15.44243,7.76632 -15.44243,14.73532 0,6.965 8.12588,17.2072 15.08888,17.2072 6.968,0 15.79898,-9.53609 15.79898,-16.50009 0.001,-6.97 -8.47743,-15.44243 -15.44543,-15.44243 z m 3.853,16.28443 c -2.558,0 -4.631,-2.072 -4.631,-4.629 0,-2.552 2.072,-4.626 4.631,-4.626 2.555,0 4.629,2.073 4.629,4.626 0,2.558 -2.073,4.629 -4.629,4.629 z"
|
||||
id="path43"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#5a3620"
|
||||
sodipodi:nodetypes="ssscssssss" /><path
|
||||
d="m 89.709786,102.60413 c -6.971,0 -14.379767,8.11987 -14.379767,15.08887 0,6.965 8.824981,16.14653 15.793981,16.14653 6.963,0 15.79298,-9.18253 15.79298,-16.14653 0.001,-6.97 -10.243194,-15.08887 -17.207194,-15.08887 z M 95.828,118.535 c -2.559,0 -4.634,-2.072 -4.634,-4.629 0,-2.552 2.076,-4.626 4.634,-4.626 2.559,0 4.63,2.073 4.63,4.626 0,2.558 -2.071,4.629 -4.63,4.629 z"
|
||||
id="path45"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#5a3620"
|
||||
sodipodi:nodetypes="ssscssssss" /></g><g
|
||||
id="cream"><path
|
||||
d="m 336.302,256.425 c 3.59,-9.155 7.701,-11 9.346,-11.346 -40.757,3.757 -36.661,27.769 -34.026,35.96 0.55,1.712 1.037,2.733 1.037,2.733 0,0 2.031,4.787 7.536,8.748 4.149,2.986 10.27,5.503 18.995,5.144 27.063,0.461 35.631,-50.166 35.631,-50.166 -6.654,11.655 -26.404,9.876 -38.519,8.927 z"
|
||||
id="path48"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#fef3df" /><path
|
||||
d="m 48.937,69.415 c 0.042,-0.046 0.085,-0.092 0.127,-0.139 1.688,-1.854 3.43,-3.657 5.229,-5.402 -8.915,-6.977 -24.344,-15.826 -41.744,-11.633 0,0 2.814,20.458 23.437,34.287 3.667,-5.86 7.822,-11.381 12.413,-16.507 -0.055,0.055 -0.111,0.108 -0.166,0.163 0.231,-0.258 0.47,-0.511 0.704,-0.769 z"
|
||||
id="path50"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#fef3df" /><path
|
||||
d="m 258.812,52.242 c -15.831,-3.815 -30.029,3.169 -39.176,9.714 7.158,6.63 13.508,14.12 18.885,22.307 17.763,-13.689 20.291,-32.021 20.291,-32.021 z"
|
||||
id="path52"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#fef3df" /><path
|
||||
d="m 134.269,160.225 c -43.299,0 -78.388,22.964 -78.388,51.289 0,0.582 0.038,1.157 0.067,1.735 0.026,0.514 0.06,1.025 0.108,1.535 17.508,19.015 42.371,30.895 69.956,30.895 35.594,0 66.662,-19.774 83.233,-49.146 -9.796,-21.016 -39.651,-36.308 -74.976,-36.308 z M 87.491,214.85 c -6.211,0 -11.254,-5.041 -11.254,-11.257 0,-6.223 5.044,-11.257 11.254,-11.257 6.22,0 11.261,5.034 11.261,11.257 0,6.216 -5.04,11.257 -11.261,11.257 z m 93.816,0 c -6.218,0 -11.259,-5.041 -11.259,-11.257 0,-6.223 5.041,-11.257 11.259,-11.257 6.22,0 11.257,5.034 11.257,11.257 0,6.216 -5.037,11.257 -11.257,11.257 z"
|
||||
id="path54"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#fef3df" /><path
|
||||
d="M 86.265,0 C 68.102,16.373 86.113,41.427 86.258,41.628 97.061,36.47 108.751,32.874 121.042,31.141 97.629,27.686 86.265,0 86.265,0 Z"
|
||||
id="path56"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#fef3df" /><path
|
||||
d="m 186.204,0 c 0,0 -10.863,26.476 -33.231,30.883 11.992,1.493 23.435,4.752 34.062,9.509 C 190.383,35.136 202.036,14.271 186.204,0 Z"
|
||||
id="path58"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#fef3df" /></g><g
|
||||
id="g60"><path
|
||||
d="m 217.913,176.038 c 2.647,-8.964 6.55187,-25.89162 6.55187,-35.73662 C 224.46487,90.252379 185.208,56.4 137.728,50.502 c -2.157,28.03 3.629,87.043 80.185,125.536 z m -47.53,-58.345 c 0,-6.97 5.651,-12.614 12.614,-12.614 6.968,0 12.617,5.645 12.617,12.614 0,6.964 -5.649,12.611 -12.617,12.611 -6.963,0 -12.614,-5.646 -12.614,-12.611 z"
|
||||
id="path62"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#87654a"
|
||||
sodipodi:nodetypes="csccsssss" /></g><g
|
||||
id="brown"><path
|
||||
d="m 312.658,283.772 c 0,0 -0.487,-1.021 -1.037,-2.733 -3.758,3.317 -13.036,10.236 -27.03,12.416 l 0,-10e-4 c -0.009,0.002 -0.019,0.003 -0.027,0.005 -4.044,0.628 -8.479,0.863 -13.29,0.497 l 0,28.141 c 2.059,-0.801 4.607,-1.834 7.477,-3.083 5.462,-2.377 12.093,-5.542 18.771,-9.395 0.027,-0.016 0.054,-0.031 0.081,-0.047 8.158,-4.713 16.37,-10.452 22.593,-17.052 -5.506,-3.961 -7.538,-8.748 -7.538,-8.748 z"
|
||||
id="path65"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#b58765" /><path
|
||||
d="m 12.549,52.242 c 17.4,-4.193 32.83,4.656 41.744,11.633 C 59.888,58.449 66.009,53.565 72.57,49.301 48.272,18.498 2.169,37.201 2.169,37.201 -1.114,67.502 15.288,84.594 31.672,94.01 33.023,91.461 34.462,88.966 35.986,86.53 15.363,72.699 12.549,52.242 12.549,52.242 Z"
|
||||
id="path67"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#b58765" /><path
|
||||
d="m 200.376,47.398 c 6.909,4.205 13.356,9.091 19.26,14.558 9.146,-6.545 23.345,-13.529 39.176,-9.714 0,0 -2.527,18.332 -20.291,32.021 1.633,2.485 3.175,5.034 4.624,7.643 15.141,-9.784 29.097,-26.539 26.046,-54.704 0,-10e-4 -44.152,-17.909 -68.815,10.196 z"
|
||||
id="path69"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#b58765" /><path
|
||||
d="m 138.854,50.502 c -3.841,-0.478 -8.875,-0.728 -12.842,-0.728 -37.806,0 -70.502,22.31 -86.15,54.73 -1.045,4.357 -1.603,8.897 -1.603,13.612 0,1.454 0.085,2.787 0.121,4.175 0.127,3.935 0.448,7.585 0.855,11.135 4.291755,24.95762 7.959057,42.49186 13.464,66.758 0.056,0.407 0.164,0.804 0.224,1.211 0.617,4.028 1.642,7.992 3.025,11.854 -0.029,-0.578 -0.067,-1.153 -0.067,-1.735 0,-28.325 35.089,-51.289 78.388,-51.289 35.325,0 65.181,15.292 74.977,36.308 3.616,-6.409 6.536,-13.277 8.668,-20.495 C 179.98905,152.54886 163.9995,134.88987 153.25313,111.82124 142.50675,88.752624 137.775,64.517 138.854,50.502 Z m -47.73,79.802 c -6.97,0 -12.612,-5.646 -12.612,-12.611 0,-6.97 5.642,-12.614 12.612,-12.614 6.964,0 12.611,5.645 12.611,12.614 0.001,6.964 -5.648,12.611 -12.611,12.611 z"
|
||||
id="path71"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#b58765"
|
||||
sodipodi:nodetypes="cscscccccssccscssscs" /></g></g></svg>
|
Before Width: | Height: | Size: 14 KiB |
@@ -1,7 +0,0 @@
|
||||
$mdThemingProvider.definePalette("sogo-green",{50:"eaf5e9",100:"cbe5c8",200:"aad6a5",300:"88c781",400:"66b86a",500:"56b04c",600:"4da143",700:"388e3c",800:"367d2e",900:"225e1b",A100:"ffffff",A200:"69f0ae",A400:"00e676",A700:"00c853",contrastDefaultColor:"dark",contrastLightColors:["300","400","500","600","700","800","900"]})
|
||||
$mdThemingProvider.definePalette("sogo-blue",{50:"f0faf9",100:"e1f5f3",200:"ceebe8",300:"bfe0dd",400:"b2d6d3",500:"a1ccc8",600:"8ebfbb",700:"7db3b0",800:"639997",900:"4d8080",A100:"d4f7fa",A200:"c3f5fa",A400:"53e3f0",A700:"00b0c0",contrastDefaultColor:"light",contrastDarkColors:["50","100","200"]})
|
||||
$mdThemingProvider.definePalette("sogo-grey",$mdThemingProvider.extendPalette("grey",{1e3:"baa870"}))
|
||||
|
||||
var primarySettings = {default:"900","hue-1":"400","hue-2":"800","hue-3":"A700"}
|
||||
var accentSettings = {default:"500","hue-1":"A100","hue-2":"300","hue-3":"A700"}
|
||||
var backgroundSettings = {}
|
@@ -1,34 +1,36 @@
|
||||
/* EXAMPLE - EXAMPLE - EXAMPLE - EXAMPLE - EXAMPLE - EXAMPLE - EXAMPLE
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
angular.module('SOGo.Common')
|
||||
.config(configure)
|
||||
|
||||
configure.$inject = ['$mdThemingProvider'];
|
||||
function configure($mdThemingProvider) {
|
||||
|
||||
$mdThemingProvider.definePalette("sogo-green",{50:"eaf5e9",100:"cbe5c8",200:"aad6a5",300:"88c781",400:"66b86a",500:"56b04c",600:"4da143",700:"388e3c",800:"367d2e",900:"225e1b",A100:"ffffff",A200:"69f0ae",A400:"00e676",A700:"00c853",contrastDefaultColor:"dark",contrastLightColors:["300","400","500","600","700","800","900"]})
|
||||
$mdThemingProvider.definePalette("sogo-blue",{50:"f0faf9",100:"e1f5f3",200:"ceebe8",300:"bfe0dd",400:"b2d6d3",500:"a1ccc8",600:"8ebfbb",700:"7db3b0",800:"639997",900:"4d8080",A100:"d4f7fa",A200:"c3f5fa",A400:"53e3f0",A700:"00b0c0",contrastDefaultColor:"light",contrastDarkColors:["50","100","200"]})
|
||||
$mdThemingProvider.definePalette("sogo-grey",$mdThemingProvider.extendPalette("grey",{1e3:"baa870"}))
|
||||
|
||||
var primarySettings = {default:"900","hue-1":"400","hue-2":"800","hue-3":"A700"}
|
||||
var accentSettings = {default:"500","hue-1":"A100","hue-2":"300","hue-3":"A700"}
|
||||
var backgroundSettings = {}
|
||||
|
||||
var primary = $mdThemingProvider.extendPalette('sogo-blue', {});
|
||||
var accent = $mdThemingProvider.extendPalette('sogo-green', {
|
||||
'A100': 'ffffff'
|
||||
var greyMap = $mdThemingProvider.extendPalette('grey', {
|
||||
'200': 'F5F5F5',
|
||||
'300': 'E5E5E5',
|
||||
'1000': '4C566A'
|
||||
});
|
||||
var background = $mdThemingProvider.extendPalette('sogo-grey', {});
|
||||
|
||||
$mdThemingProvider.definePalette('primary-cow', primary);
|
||||
$mdThemingProvider.definePalette('accent-cow', accent);
|
||||
$mdThemingProvider.definePalette('background-cow', background);
|
||||
|
||||
var greenCow = $mdThemingProvider.extendPalette('green', {
|
||||
'600': 'E5E5E5'
|
||||
});
|
||||
$mdThemingProvider.definePalette('frost-grey', greyMap);
|
||||
$mdThemingProvider.definePalette('green-cow', greenCow);
|
||||
$mdThemingProvider.theme('default')
|
||||
.primaryPalette('primary-cow', primarySettings)
|
||||
.accentPalette('accent-cow', accentSettings)
|
||||
.backgroundPalette('background-cow', backgroundSettings);
|
||||
.primaryPalette('green-cow', {
|
||||
'default': '400',
|
||||
'hue-1': '400',
|
||||
'hue-2': '600',
|
||||
'hue-3': 'A700'
|
||||
})
|
||||
.accentPalette('green', {
|
||||
'default': '600',
|
||||
'hue-1': '300',
|
||||
'hue-2': '300',
|
||||
'hue-3': 'A700'
|
||||
})
|
||||
.backgroundPalette('frost-grey');
|
||||
$mdThemingProvider.generateThemesOnDemand(false);
|
||||
}
|
||||
})();
|
||||
*/
|
@@ -62,7 +62,7 @@
|
||||
SOGoFirstDayOfWeek = "1";
|
||||
|
||||
SOGoSieveFolderEncoding = "UTF-8";
|
||||
SOGoPasswordChangeEnabled = NO;
|
||||
SOGoPasswordChangeEnabled = YES;
|
||||
SOGoSentFolderName = "Sent";
|
||||
SOGoMailShowSubscribedFoldersOnly = NO;
|
||||
NGImap4ConnectionStringSeparator = "/";
|
||||
|
@@ -103,12 +103,9 @@ $template_data = [
|
||||
'rsettings' => $rsettings,
|
||||
'rspamd_regex_maps' => $rspamd_regex_maps,
|
||||
'logo_specs' => customize('get', 'main_logo_specs'),
|
||||
'favicon_specs' => customize('get', 'favicon_specs'),
|
||||
'ip_check' => customize('get', 'ip_check'),
|
||||
'password_complexity' => password_complexity('get'),
|
||||
'show_rspamd_global_filters' => @$_SESSION['show_rspamd_global_filters'],
|
||||
'sogo_palettes' => $GLOBALS['SOGO_PALETTES'],
|
||||
'sogo_theme' => customize('get', 'sogo_theme'),
|
||||
'lang_admin' => json_encode($lang['admin']),
|
||||
'lang_datatables' => json_encode($lang['datatables'])
|
||||
];
|
||||
|
@@ -3176,10 +3176,8 @@ paths:
|
||||
example:
|
||||
attr:
|
||||
ban_time: "86400"
|
||||
ban_time_increment: "1"
|
||||
blacklist: "10.100.6.5/32,10.100.8.4/32"
|
||||
max_attempts: "5"
|
||||
max_ban_time: "86400"
|
||||
netban_ipv4: "24"
|
||||
netban_ipv6: "64"
|
||||
retry_window: "600"
|
||||
@@ -3193,17 +3191,11 @@ paths:
|
||||
description: the backlisted ips or hostnames separated by comma
|
||||
type: string
|
||||
ban_time:
|
||||
description: the time an ip should be banned
|
||||
description: the time a ip should be banned
|
||||
type: number
|
||||
ban_time_increment:
|
||||
description: if the time of the ban should increase each time
|
||||
type: boolean
|
||||
max_attempts:
|
||||
description: the maximum numbe of wrong logins before a ip is banned
|
||||
type: number
|
||||
max_ban_time:
|
||||
description: the maximum time an ip should be banned
|
||||
type: number
|
||||
netban_ipv4:
|
||||
description: the networks mask to ban for ipv4
|
||||
type: number
|
||||
@@ -4121,12 +4113,10 @@ paths:
|
||||
response:
|
||||
value:
|
||||
ban_time: 604800
|
||||
ban_time_increment: 1
|
||||
blacklist: |-
|
||||
45.82.153.37/32
|
||||
92.118.38.52/32
|
||||
max_attempts: 1
|
||||
max_ban_time: 604800
|
||||
netban_ipv4: 32
|
||||
netban_ipv6: 128
|
||||
perm_bans:
|
||||
@@ -5602,109 +5592,6 @@ paths:
|
||||
description: You can list all mailboxes existing in system for a specific domain.
|
||||
operationId: Get mailboxes of a domain
|
||||
summary: Get mailboxes of a domain
|
||||
/api/v1/edit/sogo_theme/:
|
||||
post:
|
||||
responses:
|
||||
"401":
|
||||
$ref: "#/components/responses/Unauthorized"
|
||||
"200":
|
||||
content:
|
||||
application/json:
|
||||
examples:
|
||||
response:
|
||||
value:
|
||||
- type: success
|
||||
log:
|
||||
- customize
|
||||
- edit
|
||||
- sogo_theme
|
||||
- primary: "brown"
|
||||
accent: "brown"
|
||||
background: "amber"
|
||||
msg:
|
||||
- sogo_theme_modified
|
||||
schema:
|
||||
properties:
|
||||
log:
|
||||
description: contains request object
|
||||
items: {}
|
||||
type: array
|
||||
msg:
|
||||
items: {}
|
||||
type: array
|
||||
type:
|
||||
enum:
|
||||
- success
|
||||
- danger
|
||||
- error
|
||||
type: string
|
||||
type: object
|
||||
description: OK
|
||||
headers: {}
|
||||
tags:
|
||||
- Customize
|
||||
description: >-
|
||||
Using this endpoint you can edit the sogo theme. SOGo has to be restarted after each change.
|
||||
operationId: Edit SOGo theme
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
example:
|
||||
primary: "brown"
|
||||
accent: "brown"
|
||||
background: "amber"
|
||||
summary: Edit SOGo theme
|
||||
/api/v1/delete/sogo_theme/:
|
||||
post:
|
||||
responses:
|
||||
"401":
|
||||
$ref: "#/components/responses/Unauthorized"
|
||||
"200":
|
||||
content:
|
||||
application/json:
|
||||
examples:
|
||||
response:
|
||||
value:
|
||||
- type: success
|
||||
log:
|
||||
- customize
|
||||
- delete
|
||||
- sogo_theme
|
||||
- items:
|
||||
- sogo-theme
|
||||
msg: "sogo_theme_removed"
|
||||
schema:
|
||||
properties:
|
||||
log:
|
||||
description: contains request object
|
||||
items: {}
|
||||
type: array
|
||||
msg:
|
||||
items: {}
|
||||
type: array
|
||||
type:
|
||||
enum:
|
||||
- success
|
||||
- danger
|
||||
- error
|
||||
type: string
|
||||
type: object
|
||||
description: OK
|
||||
headers: {}
|
||||
tags:
|
||||
- Customize
|
||||
description: >-
|
||||
Using this endpoint you can reset the sogo theme. SOGo has to be restarted after each change.
|
||||
operationId: Reset SOGo theme
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
example:
|
||||
- items:
|
||||
- "sogo-theme"
|
||||
summary: Reset SOGo theme
|
||||
|
||||
tags:
|
||||
- name: Domains
|
||||
@@ -5749,5 +5636,3 @@ tags:
|
||||
description: Get the status of your cow
|
||||
- name: Ratelimits
|
||||
description: Edit domain ratelimits
|
||||
- name: Customize
|
||||
description: You can customize mailcow's appearance
|
@@ -342,10 +342,6 @@ div.dataTables_wrapper div.dt-row {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
div.dataTables_wrapper span.sorting-value {
|
||||
display: none;
|
||||
}
|
||||
|
||||
div.dataTables_scrollHead table.dataTable {
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
|
@@ -66,6 +66,4 @@ table tbody tr td input[type="checkbox"] {
|
||||
padding: .2em .4em .3em !important;
|
||||
background-color: #ececec!important;
|
||||
}
|
||||
.badge.bg-info .bi {
|
||||
font-size: inherit;
|
||||
}
|
||||
|
||||
|
@@ -20,11 +20,6 @@ legend {
|
||||
background-color: #7a7a7a !important;
|
||||
border-color: #5c5c5c !important;
|
||||
}
|
||||
.btn-dark {
|
||||
color: #000 !important;;
|
||||
background-color: #f6f6f6 !important;;
|
||||
border-color: #ddd !important;;
|
||||
}
|
||||
.btn-check:checked+.btn-secondary, .btn-check:active+.btn-secondary, .btn-secondary:active, .btn-secondary.active, .show>.btn-secondary.dropdown-toggle {
|
||||
border-color: #7a7a7a !important;
|
||||
}
|
||||
|
@@ -73,81 +73,6 @@ function customize($_action, $_item, $_data = null) {
|
||||
);
|
||||
return false;
|
||||
}
|
||||
$docker_return = docker('post', 'sogo-mailcow', 'exec', array('cmd' => 'sogo', 'task' => 'set_logo'));
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'success',
|
||||
'log' => array(__FUNCTION__, $_action, $_item, $_data),
|
||||
'msg' => 'upload_success'
|
||||
);
|
||||
break;
|
||||
case 'favicon':
|
||||
if (in_array($_data['favicon']['type'], array('image/png', 'image/x-icon'))) {
|
||||
try {
|
||||
if (file_exists($_data['favicon']['tmp_name']) !== true) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_item, $_data),
|
||||
'msg' => 'img_tmp_missing'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
$image = new Imagick($_data['favicon']['tmp_name']);
|
||||
if ($image->valid() !== true) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_item, $_data),
|
||||
'msg' => 'img_invalid'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
$available_sizes = array(32, 128, 180, 192, 256);
|
||||
if ($image->getImageWidth() != $image->getImageHeight()) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_item, $_data),
|
||||
'msg' => 'img_invalid'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
if (!in_array($image->getImageWidth(), $available_sizes)) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_item, $_data),
|
||||
'msg' => 'img_invalid'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
$image->destroy();
|
||||
}
|
||||
catch (ImagickException $e) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_item, $_data),
|
||||
'msg' => 'img_invalid'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_item, $_data),
|
||||
'msg' => 'invalid_mime_type'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
$redis->Set('FAVICON', 'data:' . $_data['favicon']['type'] . ';base64,' . base64_encode(file_get_contents($_data['favicon']['tmp_name'])));
|
||||
}
|
||||
catch (RedisException $e) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_item, $_data),
|
||||
'msg' => array('redis_error', $e)
|
||||
);
|
||||
return false;
|
||||
}
|
||||
$docker_return = docker('post', 'sogo-mailcow', 'exec', array('cmd' => 'sogo', 'task' => 'set_favicon'));
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'success',
|
||||
'log' => array(__FUNCTION__, $_action, $_item, $_data),
|
||||
@@ -254,34 +179,6 @@ function customize($_action, $_item, $_data = null) {
|
||||
'msg' => 'ip_check_opt_in_modified'
|
||||
);
|
||||
break;
|
||||
case 'sogo_theme':
|
||||
$_data['primary'] = (isset($_data['primary']) && in_array($_data['primary'], $GLOBALS['SOGO_PALETTES'])) ? $_data['primary'] : 'green';
|
||||
$_data['accent'] = (isset($_data['accent']) && in_array($_data['accent'], $GLOBALS['SOGO_PALETTES'])) ? $_data['accent'] : 'green';
|
||||
$_data['background'] = (isset($_data['background']) && in_array($_data['background'], $GLOBALS['SOGO_PALETTES'])) ? $_data['background'] : 'grey';
|
||||
|
||||
try {
|
||||
$redis->hSet('SOGO_THEME', 'primary', $_data['primary']);
|
||||
$redis->hSet('SOGO_THEME', 'accent', $_data['accent']);
|
||||
$redis->hSet('SOGO_THEME', 'background', $_data['background']);
|
||||
}
|
||||
catch (RedisException $e) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_item, $_data),
|
||||
'msg' => array('redis_error', $e)
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
$docker_return = docker('post', 'sogo-mailcow', 'exec', array('cmd' => 'sogo', 'task' => 'customize_enable'));
|
||||
$docker_return = docker('post', 'sogo-mailcow', 'exec', array('cmd' => 'sogo', 'task' => 'set_theme'));
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'success',
|
||||
'log' => array(__FUNCTION__, $_action, $_item, $_data),
|
||||
'msg' => 'sogo_theme_modified'
|
||||
);
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'delete':
|
||||
@@ -306,7 +203,6 @@ function customize($_action, $_item, $_data = null) {
|
||||
case 'main_logo':
|
||||
try {
|
||||
if ($redis->del('MAIN_LOGO')) {
|
||||
$docker_return = docker('post', 'sogo-mailcow', 'exec', array('cmd' => 'sogo', 'task' => 'remove_logo'));
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'success',
|
||||
'log' => array(__FUNCTION__, $_action, $_item, $_data),
|
||||
@@ -324,51 +220,6 @@ function customize($_action, $_item, $_data = null) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case 'favicon':
|
||||
try {
|
||||
if ($redis->del('FAVICON')) {
|
||||
$docker_return = docker('post', 'sogo-mailcow', 'exec', array('cmd' => 'sogo', 'task' => 'remove_favicon'));
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'success',
|
||||
'log' => array(__FUNCTION__, $_action, $_item, $_data),
|
||||
'msg' => 'reset_favicon'
|
||||
);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (RedisException $e) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_item, $_data),
|
||||
'msg' => array('redis_error', $e)
|
||||
);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case 'sogo_theme':
|
||||
try {
|
||||
$redis->hSet('SOGO_THEME', 'primary', 'sogo-blue');
|
||||
$redis->hSet('SOGO_THEME', 'accent', 'sogo-green');
|
||||
$redis->hSet('SOGO_THEME', 'background', 'sogo-grey');
|
||||
}
|
||||
catch (RedisException $e) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_item, $_data),
|
||||
'msg' => array('redis_error', $e)
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
$docker_return = docker('post', 'sogo-mailcow', 'exec', array('cmd' => 'sogo', 'task' => 'set_theme'));
|
||||
$docker_return = docker('post', 'sogo-mailcow', 'exec', array('cmd' => 'sogo', 'task' => 'customize_disable'));
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'success',
|
||||
'log' => array(__FUNCTION__, $_action, $_item, $_data),
|
||||
'msg' => 'sogo_theme_removed'
|
||||
);
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'get':
|
||||
@@ -400,19 +251,6 @@ function customize($_action, $_item, $_data = null) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case 'favicon':
|
||||
try {
|
||||
return $redis->get('FAVICON');
|
||||
}
|
||||
catch (RedisException $e) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_item, $_data),
|
||||
'msg' => array('redis_error', $e)
|
||||
);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case 'ui_texts':
|
||||
try {
|
||||
$data['title_name'] = ($title_name = $redis->get('TITLE_NAME')) ? $title_name : 'mailcow UI';
|
||||
@@ -457,25 +295,6 @@ function customize($_action, $_item, $_data = null) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case 'favicon_specs':
|
||||
try {
|
||||
$image = new Imagick();
|
||||
$img_data = explode('base64,', customize('get', 'favicon'));
|
||||
if ($img_data[1]) {
|
||||
$image->readImageBlob(base64_decode($img_data[1]));
|
||||
return $image->identifyImage();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
catch (ImagickException $e) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_item, $_data),
|
||||
'msg' => 'imagick_exception'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case 'ip_check':
|
||||
try {
|
||||
$ip_check = ($ip_check = $redis->get('IP_CHECK')) ? $ip_check : 0;
|
||||
@@ -490,28 +309,6 @@ function customize($_action, $_item, $_data = null) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case 'sogo_theme':
|
||||
$data = array();
|
||||
try {
|
||||
$data['primary'] = $redis->hGet('SOGO_THEME', 'primary');
|
||||
$data['accent'] = $redis->hGet('SOGO_THEME', 'accent');
|
||||
$data['background'] = $redis->hGet('SOGO_THEME', 'background');
|
||||
}
|
||||
catch (RedisException $e) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_item, $_data),
|
||||
'msg' => array('redis_error', $e)
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
$data['primary'] = empty($data['primary']) ? 'sogo-blue' : $data['primary'];
|
||||
$data['accent'] = empty($data['accent']) ? 'sogo-green' : $data['accent'];
|
||||
$data['background'] = empty($data['background']) ? 'sogo-grey' : $data['background'];
|
||||
|
||||
return $data;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@@ -239,9 +239,7 @@ function fail2ban($_action, $_data = null) {
|
||||
$is_now = fail2ban('get');
|
||||
if (!empty($is_now)) {
|
||||
$ban_time = intval((isset($_data['ban_time'])) ? $_data['ban_time'] : $is_now['ban_time']);
|
||||
$ban_time_increment = (isset($_data['ban_time_increment']) && $_data['ban_time_increment'] == "1") ? 1 : 0;
|
||||
$max_attempts = intval((isset($_data['max_attempts'])) ? $_data['max_attempts'] : $is_now['max_attempts']);
|
||||
$max_ban_time = intval((isset($_data['max_ban_time'])) ? $_data['max_ban_time'] : $is_now['max_ban_time']);
|
||||
$retry_window = intval((isset($_data['retry_window'])) ? $_data['retry_window'] : $is_now['retry_window']);
|
||||
$netban_ipv4 = intval((isset($_data['netban_ipv4'])) ? $_data['netban_ipv4'] : $is_now['netban_ipv4']);
|
||||
$netban_ipv6 = intval((isset($_data['netban_ipv6'])) ? $_data['netban_ipv6'] : $is_now['netban_ipv6']);
|
||||
@@ -258,8 +256,6 @@ function fail2ban($_action, $_data = null) {
|
||||
}
|
||||
$f2b_options = array();
|
||||
$f2b_options['ban_time'] = ($ban_time < 60) ? 60 : $ban_time;
|
||||
$f2b_options['ban_time_increment'] = ($ban_time_increment == 1) ? true : false;
|
||||
$f2b_options['max_ban_time'] = ($max_ban_time < 60) ? 60 : $max_ban_time;
|
||||
$f2b_options['netban_ipv4'] = ($netban_ipv4 < 8) ? 8 : $netban_ipv4;
|
||||
$f2b_options['netban_ipv6'] = ($netban_ipv6 < 8) ? 8 : $netban_ipv6;
|
||||
$f2b_options['netban_ipv4'] = ($netban_ipv4 > 32) ? 32 : $netban_ipv4;
|
||||
|
@@ -1015,58 +1015,20 @@ function formatBytes($size, $precision = 2) {
|
||||
}
|
||||
return round(pow(1024, $base - floor($base)), $precision) . $suffixes[floor($base)];
|
||||
}
|
||||
function update_sogo_static_view($mailbox = null) {
|
||||
function update_sogo_static_view() {
|
||||
if (getenv('SKIP_SOGO') == "y") {
|
||||
return true;
|
||||
}
|
||||
global $pdo;
|
||||
global $lang;
|
||||
|
||||
$mailbox_exists = false;
|
||||
if ($mailbox !== null) {
|
||||
// Check if the mailbox exists
|
||||
$stmt = $pdo->prepare("SELECT username FROM mailbox WHERE username = :mailbox AND active = '1'");
|
||||
$stmt->execute(array(':mailbox' => $mailbox));
|
||||
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
if ($row){
|
||||
$mailbox_exists = true;
|
||||
}
|
||||
}
|
||||
|
||||
$query = "REPLACE INTO _sogo_static_view (`c_uid`, `domain`, `c_name`, `c_password`, `c_cn`, `mail`, `aliases`, `ad_aliases`, `ext_acl`, `kind`, `multiple_bookings`)
|
||||
SELECT
|
||||
mailbox.username,
|
||||
mailbox.domain,
|
||||
mailbox.username,
|
||||
IF(JSON_UNQUOTE(JSON_VALUE(attributes, '$.force_pw_update')) = '0',
|
||||
IF(JSON_UNQUOTE(JSON_VALUE(attributes, '$.sogo_access')) = 1, password, '{SSHA256}A123A123A321A321A321B321B321B123B123B321B432F123E321123123321321'),
|
||||
'{SSHA256}A123A123A321A321A321B321B321B123B123B321B432F123E321123123321321'),
|
||||
mailbox.name,
|
||||
mailbox.username,
|
||||
IFNULL(GROUP_CONCAT(ga.aliases ORDER BY ga.aliases SEPARATOR ' '), ''),
|
||||
IFNULL(gda.ad_alias, ''),
|
||||
IFNULL(external_acl.send_as_acl, ''),
|
||||
mailbox.kind,
|
||||
mailbox.multiple_bookings
|
||||
FROM
|
||||
mailbox
|
||||
LEFT OUTER JOIN grouped_mail_aliases ga ON ga.username REGEXP CONCAT('(^|,)', mailbox.username, '($|,)')
|
||||
LEFT OUTER JOIN grouped_domain_alias_address gda ON gda.username = mailbox.username
|
||||
LEFT OUTER JOIN grouped_sender_acl_external external_acl ON external_acl.username = mailbox.username
|
||||
WHERE
|
||||
mailbox.active = '1'";
|
||||
|
||||
if ($mailbox_exists) {
|
||||
$query .= " AND mailbox.username = :mailbox";
|
||||
$stmt = $pdo->prepare($query);
|
||||
$stmt->execute(array(':mailbox' => $mailbox));
|
||||
} else {
|
||||
$query .= " GROUP BY mailbox.username";
|
||||
$stmt = $pdo->query($query);
|
||||
}
|
||||
|
||||
$stmt = $pdo->query("SELECT 'OK' FROM INFORMATION_SCHEMA.TABLES
|
||||
WHERE TABLE_NAME = 'sogo_view'");
|
||||
$num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
|
||||
if ($num_results != 0) {
|
||||
$stmt = $pdo->query("REPLACE INTO _sogo_static_view (`c_uid`, `domain`, `c_name`, `c_password`, `c_cn`, `mail`, `aliases`, `ad_aliases`, `ext_acl`, `kind`, `multiple_bookings`)
|
||||
SELECT `c_uid`, `domain`, `c_name`, `c_password`, `c_cn`, `mail`, `aliases`, `ad_aliases`, `ext_acl`, `kind`, `multiple_bookings` from sogo_view");
|
||||
$stmt = $pdo->query("DELETE FROM _sogo_static_view WHERE `c_uid` NOT IN (SELECT `username` FROM `mailbox` WHERE `active` = '1');");
|
||||
|
||||
}
|
||||
flush_memcached();
|
||||
}
|
||||
function edit_user_account($_data) {
|
||||
|
@@ -1264,13 +1264,11 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
||||
));
|
||||
}
|
||||
|
||||
update_sogo_static_view($username);
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'success',
|
||||
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
|
||||
'msg' => array('mailbox_added', htmlspecialchars($username))
|
||||
);
|
||||
return true;
|
||||
break;
|
||||
case 'resource':
|
||||
$domain = idn_to_ascii(strtolower(trim($_data['domain'])), 0, INTL_IDNA_VARIANT_UTS46);
|
||||
@@ -3132,10 +3130,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
||||
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
|
||||
'msg' => array('mailbox_modified', $username)
|
||||
);
|
||||
|
||||
update_sogo_static_view($username);
|
||||
}
|
||||
return true;
|
||||
break;
|
||||
case 'mailbox_templates':
|
||||
if ($_SESSION['mailcow_cc_role'] != "admin") {
|
||||
@@ -5058,15 +5053,12 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
update_sogo_static_view($username);
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'success',
|
||||
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
|
||||
'msg' => array('mailbox_removed', htmlspecialchars($username))
|
||||
);
|
||||
}
|
||||
return true;
|
||||
break;
|
||||
case 'mailbox_templates':
|
||||
if ($_SESSION['mailcow_cc_role'] != "admin") {
|
||||
@@ -5272,7 +5264,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
if ($_action != 'get' && in_array($_type, array('domain', 'alias', 'alias_domain', 'resource')) && getenv('SKIP_SOGO') != "y") {
|
||||
if ($_action != 'get' && in_array($_type, array('domain', 'alias', 'alias_domain', 'mailbox', 'resource')) && getenv('SKIP_SOGO') != "y") {
|
||||
update_sogo_static_view();
|
||||
}
|
||||
}
|
||||
|
@@ -40,7 +40,6 @@ $globalVariables = [
|
||||
'ui_texts' => $UI_TEXTS,
|
||||
'css_path' => '/cache/'.basename($CSSPath),
|
||||
'logo' => customize('get', 'main_logo'),
|
||||
'favicon' => customize('get', 'favicon'),
|
||||
'available_languages' => $AVAILABLE_LANGUAGES,
|
||||
'lang' => $lang,
|
||||
'skip_sogo' => (getenv('SKIP_SOGO') == 'y'),
|
||||
|
@@ -125,14 +125,6 @@ if (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == "admi
|
||||
if (isset($_POST["reset_main_logo"])) {
|
||||
customize('delete', 'main_logo');
|
||||
}
|
||||
if (isset($_POST["submit_favicon"])) {
|
||||
if ($_FILES['favicon']['error'] == 0) {
|
||||
customize('add', 'favicon', $_FILES);
|
||||
}
|
||||
}
|
||||
if (isset($_POST["reset_favicon"])) {
|
||||
customize('delete', 'favicon');
|
||||
}
|
||||
// Some actions will not be available via API
|
||||
if (isset($_POST["license_validate_now"])) {
|
||||
license('verify');
|
||||
|
@@ -210,30 +210,6 @@ $FIDO2_USER_PRESENT_FLAG = true;
|
||||
|
||||
$FIDO2_FORMATS = array('apple', 'android-key', 'android-safetynet', 'fido-u2f', 'none', 'packed', 'tpm');
|
||||
|
||||
$SOGO_PALETTES = array(
|
||||
'sogo-green',
|
||||
'sogo-blue',
|
||||
'sogo-grey',
|
||||
'red',
|
||||
'pink',
|
||||
'purple',
|
||||
'deep-purple',
|
||||
'indigo',
|
||||
'blue',
|
||||
'light-blue',
|
||||
'cyan',
|
||||
'teal',
|
||||
'green',
|
||||
'light-green',
|
||||
'lime',
|
||||
'yellow',
|
||||
'amber',
|
||||
'orange',
|
||||
'deep-orange',
|
||||
'brown',
|
||||
'grey',
|
||||
'blue-grey'
|
||||
);
|
||||
|
||||
// Set visible Rspamd maps in mailcow UI, do not change unless you know what you are doing
|
||||
$RSPAMD_MAPS = array(
|
||||
|
@@ -117,8 +117,8 @@ jQuery(function($){
|
||||
data: 'tfa_active',
|
||||
defaultContent: '',
|
||||
render: function (data, type) {
|
||||
if(data == 1) return '<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>';
|
||||
else return '<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>';
|
||||
if(data == 1) return '<i class="bi bi-check-lg"></i>';
|
||||
else return '<i class="bi bi-x-lg"></i>';
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -126,8 +126,8 @@ jQuery(function($){
|
||||
data: 'active',
|
||||
defaultContent: '',
|
||||
render: function (data, type) {
|
||||
if(data == 1) return '<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>';
|
||||
else return '<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>';
|
||||
if(data == 1) return '<i class="bi bi-check-lg"></i>';
|
||||
else return '<i class="bi bi-x-lg"></i>';
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -260,8 +260,8 @@ jQuery(function($){
|
||||
data: 'tfa_active',
|
||||
defaultContent: '',
|
||||
render: function (data, type) {
|
||||
if(data == 1) return '<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>';
|
||||
else return '<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>';
|
||||
if(data == 1) return '<i class="bi bi-check-lg"></i>';
|
||||
else return '<i class="bi bi-x-lg"></i>';
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -269,8 +269,8 @@ jQuery(function($){
|
||||
data: 'active',
|
||||
defaultContent: '',
|
||||
render: function (data, type) {
|
||||
if(data == 1) return '<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>';
|
||||
else return '<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>';
|
||||
if(data == 1) return '<i class="bi bi-check-lg"></i>';
|
||||
else return '<i class="bi bi-x-lg"></i>';
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -337,7 +337,7 @@ jQuery(function($){
|
||||
data: 'keep_spam',
|
||||
defaultContent: '',
|
||||
render: function(data, type){
|
||||
return 'yes'==data?'<i class="bi bi-x-lg"><span class="sorting-value">yes</span></i>':'no'==data&&'<i class="bi bi-check-lg"><span class="sorting-value">no</span></i>';
|
||||
return 'yes'==data?'<i class="bi bi-x-lg"></i>':'no'==data&&'<i class="bi bi-check-lg"></i>';
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -414,8 +414,8 @@ jQuery(function($){
|
||||
data: 'active',
|
||||
defaultContent: '',
|
||||
render: function (data, type) {
|
||||
if(data == 1) return '<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>';
|
||||
else return '<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>';
|
||||
if(data == 1) return '<i class="bi bi-check-lg"></i>';
|
||||
else return '<i class="bi bi-x-lg"></i>';
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -492,8 +492,8 @@ jQuery(function($){
|
||||
data: 'active',
|
||||
defaultContent: '',
|
||||
render: function (data, type) {
|
||||
if(data == 1) return '<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>';
|
||||
else return '<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>';
|
||||
if(data == 1) return '<i class="bi bi-check-lg"></i>';
|
||||
else return '<i class="bi bi-x-lg"></i>';
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@@ -1181,7 +1181,7 @@ jQuery(function($){
|
||||
|
||||
if (table = $('#' + log_table).DataTable()) {
|
||||
var heading = $('#' + log_table).closest('.card').find('.card-header');
|
||||
var load_rows = (table.data().length + 1) + '-' + (table.data().length + new_nrows)
|
||||
var load_rows = (table.page.len() + 1) + '-' + (table.page.len() + new_nrows)
|
||||
|
||||
$.get('/api/v1/get/logs/' + log_url + '/' + load_rows).then(function(data){
|
||||
if (data.length === undefined) { mailcow_alert_box(lang.no_new_rows, "info"); return; }
|
||||
|
@@ -607,7 +607,7 @@ jQuery(function($){
|
||||
defaultContent: '',
|
||||
responsivePriority: 6,
|
||||
render: function (data, type) {
|
||||
return 1==data?'<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>':(0==data?'<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>':2==data&&'—');
|
||||
return 1==data?'<i class="bi bi-check-lg"></i>':(0==data?'<i class="bi bi-x-lg"></i>':2==data&&'—');
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -754,7 +754,7 @@ jQuery(function($){
|
||||
data: 'attributes.gal',
|
||||
defaultContent: '',
|
||||
render: function (data, type) {
|
||||
return 1==data?'<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>':'<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>';
|
||||
return 1==data?'<i class="bi bi-check-lg"></i>':'<i class="bi bi-x-lg"></i>';
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -762,7 +762,7 @@ jQuery(function($){
|
||||
data: 'attributes.backupmx',
|
||||
defaultContent: '',
|
||||
render: function (data, type) {
|
||||
return 1==data?'<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>':'<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>';
|
||||
return 1==data?'<i class="bi bi-check-lg"></i>':'<i class="bi bi-x-lg"></i>';
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -770,7 +770,7 @@ jQuery(function($){
|
||||
data: 'attributes.relay_all_recipients',
|
||||
defaultContent: '',
|
||||
render: function (data, type) {
|
||||
return 1==data?'<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>':'<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>';
|
||||
return 1==data?'<i class="bi bi-check-lg"></i>':'<i class="bi bi-x-lg"></i>';
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -778,7 +778,7 @@ jQuery(function($){
|
||||
data: 'attributes.relay_unknown_only',
|
||||
defaultContent: '',
|
||||
render: function (data, type) {
|
||||
return 1==data?'<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>':'<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>';
|
||||
return 1==data?'<i class="bi bi-check-lg"></i>':'<i class="bi bi-x-lg"></i>';
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -787,7 +787,7 @@ jQuery(function($){
|
||||
defaultContent: '',
|
||||
responsivePriority: 4,
|
||||
render: function (data, type) {
|
||||
return 1==data?'<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>':'<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>';
|
||||
return 1==data?'<i class="bi bi-check-lg"></i>':'<i class="bi bi-x-lg"></i>';
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -1093,7 +1093,7 @@ jQuery(function($){
|
||||
defaultContent: '',
|
||||
responsivePriority: 4,
|
||||
render: function (data, type) {
|
||||
return 1==data?'<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>':(0==data?'<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>':2==data&&'—');
|
||||
return 1==data?'<i class="bi bi-check-lg"></i>':(0==data?'<i class="bi bi-x-lg"></i>':2==data&&'—');
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -1164,13 +1164,13 @@ jQuery(function($){
|
||||
|
||||
item.attributes.quota = humanFileSize(item.attributes.quota);
|
||||
|
||||
item.attributes.tls_enforce_in = '<i class="text-' + (item.attributes.tls_enforce_in == 1 ? 'success bi bi-lock-fill' : 'danger bi bi-unlock-fill') + '"><span class="sorting-value">' + (item.attributes.tls_enforce_in == 1 ? '1' : '0') + '</span></i>';
|
||||
item.attributes.tls_enforce_out = '<i class="text-' + (item.attributes.tls_enforce_out == 1 ? 'success bi bi-lock-fill' : 'danger bi bi-unlock-fill') + '"><span class="sorting-value">' + (item.attributes.tls_enforce_out == 1 ? '1' : '0') + '</span></i>';
|
||||
item.attributes.pop3_access = '<i class="text-' + (item.attributes.pop3_access == 1 ? 'success' : 'danger') + ' bi bi-' + (item.attributes.pop3_access == 1 ? 'check-lg' : 'x-lg') + '"><span class="sorting-value">' + (item.attributes.pop3_access == 1 ? '1' : '0') + '</span></i>';
|
||||
item.attributes.imap_access = '<i class="text-' + (item.attributes.imap_access == 1 ? 'success' : 'danger') + ' bi bi-' + (item.attributes.imap_access == 1 ? 'check-lg' : 'x-lg') + '"><span class="sorting-value">' + (item.attributes.imap_access == 1 ? '1' : '0') + '</span></i>';
|
||||
item.attributes.smtp_access = '<i class="text-' + (item.attributes.smtp_access == 1 ? 'success' : 'danger') + ' bi bi-' + (item.attributes.smtp_access == 1 ? 'check-lg' : 'x-lg') + '"><span class="sorting-value">' + (item.attributes.smtp_access == 1 ? '1' : '0') + '</span></i>';
|
||||
item.attributes.sieve_access = '<i class="text-' + (item.attributes.sieve_access == 1 ? 'success' : 'danger') + ' bi bi-' + (item.attributes.sieve_access == 1 ? 'check-lg' : 'x-lg') + '"><span class="sorting-value">' + (item.attributes.sieve_access == 1 ? '1' : '0') + '</span></i>';
|
||||
item.attributes.sogo_access = '<i class="text-' + (item.attributes.sogo_access == 1 ? 'success' : 'danger') + ' bi bi-' + (item.attributes.sogo_access == 1 ? 'check-lg' : 'x-lg') + '"><span class="sorting-value">' + (item.attributes.sogo_access == 1 ? '1' : '0') + '</span></i>';
|
||||
item.attributes.tls_enforce_in = '<i class="text-' + (item.attributes.tls_enforce_in == 1 ? 'success bi bi-lock-fill' : 'danger bi bi-unlock-fill') + '"></i>';
|
||||
item.attributes.tls_enforce_out = '<i class="text-' + (item.attributes.tls_enforce_out == 1 ? 'success bi bi-lock-fill' : 'danger bi bi-unlock-fill') + '"></i>';
|
||||
item.attributes.pop3_access = '<i class="text-' + (item.attributes.pop3_access == 1 ? 'success' : 'danger') + ' bi bi-' + (item.attributes.pop3_access == 1 ? 'check-lg' : 'x-lg') + '"></i>';
|
||||
item.attributes.imap_access = '<i class="text-' + (item.attributes.imap_access == 1 ? 'success' : 'danger') + ' bi bi-' + (item.attributes.imap_access == 1 ? 'check-lg' : 'x-lg') + '"></i>';
|
||||
item.attributes.smtp_access = '<i class="text-' + (item.attributes.smtp_access == 1 ? 'success' : 'danger') + ' bi bi-' + (item.attributes.smtp_access == 1 ? 'check-lg' : 'x-lg') + '"></i>';
|
||||
item.attributes.sieve_access = '<i class="text-' + (item.attributes.sieve_access == 1 ? 'success' : 'danger') + ' bi bi-' + (item.attributes.sieve_access == 1 ? 'check-lg' : 'x-lg') + '"></i>';
|
||||
item.attributes.sogo_access = '<i class="text-' + (item.attributes.sogo_access == 1 ? 'success' : 'danger') + ' bi bi-' + (item.attributes.sogo_access == 1 ? 'check-lg' : 'x-lg') + '"></i>';
|
||||
if (item.attributes.quarantine_notification === 'never') {
|
||||
item.attributes.quarantine_notification = lang.never;
|
||||
} else if (item.attributes.quarantine_notification === 'hourly') {
|
||||
@@ -1188,6 +1188,7 @@ jQuery(function($){
|
||||
item.attributes.quarantine_category = lang.q_all;
|
||||
}
|
||||
|
||||
|
||||
if (item.template.toLowerCase() == "default"){
|
||||
item.action = '<div class="btn-group">' +
|
||||
'<a href="/edit/template/' + encodeURIComponent(item.id) + '" class="btn btn-xs btn-xs-half btn-secondary"><i class="bi bi-pencil-fill"></i> ' + lang.edit + '</a>' +
|
||||
@@ -1328,7 +1329,7 @@ jQuery(function($){
|
||||
defaultContent: '',
|
||||
responsivePriority: 4,
|
||||
render: function (data, type) {
|
||||
return 1==data?'<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>':(0==data?'<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>':2==data&&'—');
|
||||
return 1==data?'<i class="bi bi-check-lg"></i>':(0==data?'<i class="bi bi-x-lg"></i>':2==data&&'—');
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -1439,7 +1440,7 @@ jQuery(function($){
|
||||
data: 'active',
|
||||
defaultContent: '',
|
||||
render: function (data, type) {
|
||||
return 1==data?'<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>':(0==data?'<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>':2==data&&'—');
|
||||
return 1==data?'<i class="bi bi-check-lg"></i>':(0==data?'<i class="bi bi-x-lg"></i>':2==data&&'—');
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -1577,7 +1578,7 @@ jQuery(function($){
|
||||
data: 'active',
|
||||
defaultContent: '',
|
||||
render: function (data, type) {
|
||||
return 1==data?'<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>':(0==data?'<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>':2==data&&'—');
|
||||
return 1==data?'<i class="bi bi-check-lg"></i>':(0==data?'<i class="bi bi-x-lg"></i>':2==data&&'—');
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -1674,7 +1675,7 @@ jQuery(function($){
|
||||
data: 'active',
|
||||
defaultContent: '',
|
||||
render: function (data, type) {
|
||||
return 1==data?'<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>':0==data&&'<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>';
|
||||
return 1==data?'<i class="bi bi-check-lg"></i>':0==data&&'<i class="bi bi-x-lg"></i>';
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -1781,7 +1782,7 @@ jQuery(function($){
|
||||
data: 'active',
|
||||
defaultContent: '',
|
||||
render: function (data, type) {
|
||||
return 1==data?'<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>':0==data&&'<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>';
|
||||
return 1==data?'<i class="bi bi-check-lg"></i>':0==data&&'<i class="bi bi-x-lg"></i>';
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -1916,7 +1917,7 @@ jQuery(function($){
|
||||
data: 'sogo_visible',
|
||||
defaultContent: '',
|
||||
render: function(data, type){
|
||||
return 1==data?'<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>':0==data&&'<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>';
|
||||
return 1==data?'<i class="bi bi-check-lg"></i>':0==data&&'<i class="bi bi-x-lg"></i>';
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -1935,7 +1936,7 @@ jQuery(function($){
|
||||
defaultContent: '',
|
||||
responsivePriority: 6,
|
||||
render: function (data, type) {
|
||||
return 1==data?'<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>':0==data&&'<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>';
|
||||
return 1==data?'<i class="bi bi-check-lg"></i>':0==data&&'<i class="bi bi-x-lg"></i>';
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -1951,10 +1952,6 @@ jQuery(function($){
|
||||
table.on('responsive-resize', function (e, datatable, columns){
|
||||
hideTableExpandCollapseBtn('#tab-mbox-aliases', '#alias_table');
|
||||
});
|
||||
|
||||
table.on( 'draw', function (){
|
||||
$('#alias_table [data-bs-toggle="tooltip"]').tooltip();
|
||||
});
|
||||
}
|
||||
function draw_aliasdomain_table() {
|
||||
// just recalc width if instance already exists
|
||||
@@ -2034,7 +2031,7 @@ jQuery(function($){
|
||||
data: 'active',
|
||||
defaultContent: '',
|
||||
render: function (data, type) {
|
||||
return 1==data?'<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>':0==data&&'<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>';
|
||||
return 1==data?'<i class="bi bi-check-lg"></i>':0==data&&'<i class="bi bi-x-lg"></i>';
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -2170,7 +2167,7 @@ jQuery(function($){
|
||||
data: 'active',
|
||||
defaultContent: '',
|
||||
render: function (data, type) {
|
||||
return 1==data?'<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>':0==data&&'<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>';
|
||||
return 1==data?'<i class="bi bi-check-lg"></i>':0==data&&'<i class="bi bi-x-lg"></i>';
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@@ -1744,9 +1744,6 @@ if (isset($_GET['query'])) {
|
||||
case "rlhash":
|
||||
echo ratelimit('delete', null, implode($items));
|
||||
break;
|
||||
case "sogo_theme":
|
||||
process_delete_return(customize('delete', 'sogo_theme', $items));
|
||||
break;
|
||||
// return no route found if no case is matched
|
||||
default:
|
||||
http_response_code(404);
|
||||
@@ -1941,9 +1938,6 @@ if (isset($_GET['query'])) {
|
||||
case "ip_check":
|
||||
process_edit_return(customize('edit', 'ip_check', $attr));
|
||||
break;
|
||||
case "sogo_theme":
|
||||
process_edit_return(customize('edit', 'sogo_theme', $attr));
|
||||
break;
|
||||
case "self":
|
||||
if ($_SESSION['mailcow_cc_role'] == "domainadmin") {
|
||||
process_edit_return(domain_admin('edit', $attr));
|
||||
|
@@ -105,8 +105,7 @@
|
||||
"timeout2": "Časový limit pro připojení k lokálnímu serveru",
|
||||
"username": "Uživatelské jméno",
|
||||
"validate": "Ověřit",
|
||||
"validation_success": "Úspěšně ověřeno",
|
||||
"tags": "Štítky"
|
||||
"validation_success": "Úspěšně ověřeno"
|
||||
},
|
||||
"admin": {
|
||||
"access": "Přístupy",
|
||||
@@ -334,11 +333,7 @@
|
||||
"username": "Uživatelské jméno",
|
||||
"validate_license_now": "Ověřit GUID na licenčním serveru",
|
||||
"verify": "Ověřit",
|
||||
"yes": "✓",
|
||||
"f2b_ban_time_increment": "Délka banu je prodlužována s každým dalším banem",
|
||||
"f2b_max_ban_time": "Maximální délka banu (s)",
|
||||
"ip_check": "Kontrola IP",
|
||||
"ip_check_disabled": "Kontrola IP je vypnuta. Můžete ji zapnout v <br> <strong>System > Nastavení > Options > Přizpůsobení</strong>"
|
||||
"yes": "✓"
|
||||
},
|
||||
"danger": {
|
||||
"access_denied": "Přístup odepřen nebo jsou neplatná data ve formuláři",
|
||||
|
@@ -4,15 +4,15 @@
|
||||
"app_passwds": "Administrer app-adgangskoder",
|
||||
"bcc_maps": "BCC kort",
|
||||
"delimiter_action": "Afgrænsning handling",
|
||||
"eas_reset": "Nulstil EAS enheder",
|
||||
"eas_reset": "Nulstil EAS endheder",
|
||||
"extend_sender_acl": "Tillad at udvide afsenderens ACL med eksterne adresser",
|
||||
"filters": "Filtre",
|
||||
"login_as": "Login som mailboks bruger",
|
||||
"prohibited": "Nægtet af ACL",
|
||||
"protocol_access": "Skift protokol adgang",
|
||||
"prohibited": "Forbudt af ACL",
|
||||
"protocol_access": "Ændre protokol adgang",
|
||||
"pushover": "Pushover",
|
||||
"quarantine": "Karantænehandlinger",
|
||||
"quarantine_attachments": "Karantænevedhæftede filer",
|
||||
"quarantine": "Karantæneaktioner",
|
||||
"quarantine_attachments": "Karantæne vedhæftede filer",
|
||||
"quarantine_notification": "Skift karantænemeddelelser",
|
||||
"ratelimit": "Satsgrænse",
|
||||
"recipient_maps": "Modtagerkort",
|
||||
@@ -20,15 +20,12 @@
|
||||
"sogo_access": "Tillad styring af SOGo-adgang",
|
||||
"sogo_profile_reset": "Nulstil SOGo-profil",
|
||||
"spam_alias": "Midlertidige aliasser",
|
||||
"spam_policy": "Sortliste/hvidliste",
|
||||
"spam_policy": "Sortliste / hvidliste",
|
||||
"spam_score": "Spam-score",
|
||||
"syncjobs": "Synkroniserings job",
|
||||
"tls_policy": "TLS politik",
|
||||
"unlimited_quota": "Ubegrænset plads for mailbokse",
|
||||
"domain_desc": "Skift domæne beskrivelse",
|
||||
"domain_relayhost": "Skift relæ host for et domæne",
|
||||
"mailbox_relayhost": "Skift relæ-host for en postkasse",
|
||||
"quarantine_category": "Skift kategorien for karantænemeddelelse"
|
||||
"domain_desc": "Skift domæne beskrivelse"
|
||||
},
|
||||
"add": {
|
||||
"activate_filter_warn": "Alle andre filtre deaktiveres, når aktiv er markeret.",
|
||||
@@ -62,7 +59,7 @@
|
||||
"gal": "Global adresseliste",
|
||||
"gal_info": "GAL indeholder alle objekter i et domæne og kan ikke redigeres af nogen bruger. Information om ledig / optaget i SOGo mangler, hvis deaktiveret! <b> Genstart SOGo for at anvende ændringer. </b>",
|
||||
"generate": "generere",
|
||||
"goto_ham": "Lær som <span class=\"text-success\"><b>ønsket</b></span>",
|
||||
"goto_ham": "Lær som <span class=\"text-success\"><b>ham</b></span>",
|
||||
"goto_null": "Kassér e-mail i stilhed",
|
||||
"goto_spam": "Lær som <span class=\"text-danger\"><b>spam</b></span>",
|
||||
"hostname": "Vært",
|
||||
@@ -83,7 +80,7 @@
|
||||
"private_comment": "Privat kommentar",
|
||||
"public_comment": "Offentlig kommentar",
|
||||
"quota_mb": "Kvota (Mb)",
|
||||
"relay_all": "Besvar alle modtager",
|
||||
"relay_all": "Send alle modtagere videre",
|
||||
"relay_all_info": "↪ Hvis du vælger <b> ikke </b> at videresende alle modtagere, skal du tilføje et (\"blind\") postkasse til hver enkelt modtager, der skal videresendes.",
|
||||
"relay_domain": "Send dette domæne videre",
|
||||
"relay_transport_info": "<div class=\"badge fs-6 bg-info\">Info</div> Du kan definere transportkort til en tilpasset destination for dette domæne. Hvis ikke indstillet, foretages der et MX-opslag.",
|
||||
@@ -104,10 +101,7 @@
|
||||
"timeout2": "Timeout for forbindelse til lokal vært",
|
||||
"username": "Brugernavn",
|
||||
"validate": "Bekræft",
|
||||
"validation_success": "Valideret med succes",
|
||||
"bcc_dest_format": "BCC-destination skal være en enkelt gyldig e-mail-adresse.<br>Hvis du har brug for at sende en kopi til flere adresser, kan du oprette et alias og bruge det her.",
|
||||
"app_passwd_protocols": "Tilladte protokoller for app adgangskode",
|
||||
"tags": "Tag's"
|
||||
"validation_success": "Valideret med succes"
|
||||
},
|
||||
"admin": {
|
||||
"access": "Adgang",
|
||||
@@ -314,10 +308,7 @@
|
||||
"username": "Brugernavn",
|
||||
"validate_license_now": "Valider GUID mod licensserver",
|
||||
"verify": "Verificere",
|
||||
"yes": "✓",
|
||||
"ip_check_opt_in": "Opt-In for brug af tredjepartstjeneste <strong>ipv4.mailcow.email</strong> og <strong>ipv6.mailcow.email</strong> til at finde eksterne IP-adresser.",
|
||||
"queue_unban": "unban",
|
||||
"admins": "Administratorer"
|
||||
"yes": "✓"
|
||||
},
|
||||
"danger": {
|
||||
"access_denied": "Adgang nægtet eller ugyldig formular data",
|
||||
@@ -434,8 +425,7 @@
|
||||
"username_invalid": "Brugernavn %s kan ikke bruges",
|
||||
"validity_missing": "Tildel venligst en gyldighedsperiode",
|
||||
"value_missing": "Angiv alle værdier",
|
||||
"yotp_verification_failed": "Yubico OTP verifikationen mislykkedes: %s",
|
||||
"webauthn_publickey_failed": "Der er ikke gemt nogen offentlig nøgle for den valgte autentifikator"
|
||||
"yotp_verification_failed": "Yubico OTP verifikationen mislykkedes: %s"
|
||||
},
|
||||
"debug": {
|
||||
"chart_this_server": "Diagram (denne server)",
|
||||
@@ -452,8 +442,7 @@
|
||||
"solr_status": "Solr-status",
|
||||
"started_on": "Startede den",
|
||||
"static_logs": "Statiske logfiler",
|
||||
"system_containers": "System og Beholdere",
|
||||
"error_show_ip": "Kunne ikke finde de offentlige IP-adresser"
|
||||
"system_containers": "System og Beholdere"
|
||||
},
|
||||
"diagnostics": {
|
||||
"cname_from_a": "Værdi afledt af A / AAAA-post. Dette understøttes, så længe posten peger på den korrekte ressource.",
|
||||
@@ -564,11 +553,7 @@
|
||||
"title": "Rediger objekt",
|
||||
"unchanged_if_empty": "Lad være tomt, hvis uændret",
|
||||
"username": "Brugernavn",
|
||||
"validate_save": "Valider og gem",
|
||||
"admin": "Rediger administrator",
|
||||
"lookup_mx": "Destination er et regulært udtryk, der matcher MX-navnet (<code>.*google\\.dk</code> for at dirigere al e-mail, der er målrettet til en MX, der ender på google.dk, over dette hop)",
|
||||
"mailbox_relayhost_info": "Anvendt på postkassen og kun direkte aliasser, og overskriver et domæne relæ-host.",
|
||||
"quota_warning_bcc": "Kvoteadvarsel BCC"
|
||||
"validate_save": "Valider og gem"
|
||||
},
|
||||
"footer": {
|
||||
"cancel": "Afbestille",
|
||||
@@ -586,7 +571,7 @@
|
||||
"header": {
|
||||
"administration": "Konfiguration og detailer",
|
||||
"apps": "Apps",
|
||||
"debug": "Information",
|
||||
"debug": "Systemoplysninger",
|
||||
"email": "E-Mail",
|
||||
"mailcow_config": "Konfiguration",
|
||||
"quarantine": "Karantæne",
|
||||
@@ -754,10 +739,7 @@
|
||||
"username": "Brugernavn",
|
||||
"waiting": "Venter",
|
||||
"weekly": "Ugentlig",
|
||||
"yes": "✓",
|
||||
"goto_ham": "Lær som <b>ønsket</b>",
|
||||
"catch_all": "Fang-alt",
|
||||
"open_logs": "Åben logfiler"
|
||||
"yes": "✓"
|
||||
},
|
||||
"oauth2": {
|
||||
"access_denied": "Log ind som mailboks ejer for at give adgang via OAuth2.",
|
||||
@@ -1048,7 +1030,7 @@
|
||||
"spamfilter_table_empty": "Intet data at vise",
|
||||
"spamfilter_table_remove": "slet",
|
||||
"spamfilter_table_rule": "Regl",
|
||||
"spamfilter_wl": "Hvidliste",
|
||||
"spamfilter_wl": "Hvisliste",
|
||||
"spamfilter_wl_desc": "Hvidlistede e-mail-adresser til <b>aldrig</b> at klassificeres som spam. Wildcards kan bruges. Et filter anvendes kun på direkte aliaser (aliaser med en enkelt målpostkasse) eksklusive catch-aliaser og selve en postkasse.",
|
||||
"spamfilter_yellow": "Gul: denne besked kan være spam, vil blive tagget som spam og flyttes til din junk-mappe",
|
||||
"status": "Status",
|
||||
@@ -1084,11 +1066,5 @@
|
||||
"quota_exceeded_scope": "Domænekvote overskredet: Kun ubegrænsede postkasser kan oprettes i dette domæneomfang.",
|
||||
"session_token": "Form nøgle ugyldig: Nøgle passer ikke",
|
||||
"session_ua": "Form nøgle ugyldig: Bruger-Agent gyldighedskontrols fejl"
|
||||
},
|
||||
"datatables": {
|
||||
"lengthMenu": "Vis _MENU_ poster",
|
||||
"paginate": {
|
||||
"first": "Først"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -145,7 +145,6 @@
|
||||
"ays": "Soll der Vorgang wirklich ausgeführt werden?",
|
||||
"ban_list_info": "Übersicht ausgesperrter Netzwerke: <b>Netzwerk (verbleibende Bannzeit) - [Aktionen]</b>.<br />IPs, die zum Entsperren eingereiht werden, verlassen die Liste aktiver Banns nach wenigen Sekunden.<br />Rote Labels sind Indikatoren für aktive Blacklist-Einträge.",
|
||||
"change_logo": "Logo ändern",
|
||||
"change_favicon": "Favicon ändern",
|
||||
"configuration": "Konfiguration",
|
||||
"convert_html_to_text": "Konvertiere HTML zu reinem Text",
|
||||
"credentials_transport_warning": "<b>Warnung</b>: Das Hinzufügen einer neuen Regel bewirkt die Aktualisierung der Authentifizierungsdaten aller vorhandenen Einträge mit identischem Next Hop.",
|
||||
@@ -176,12 +175,10 @@
|
||||
"empty": "Keine Einträge vorhanden",
|
||||
"excludes": "Diese Empfänger ausschließen",
|
||||
"f2b_ban_time": "Bannzeit in Sekunden",
|
||||
"f2b_ban_time_increment": "Bannzeit erhöht sich mit jedem Bann",
|
||||
"f2b_blacklist": "Blacklist für Netzwerke und Hosts",
|
||||
"f2b_filter": "Regex-Filter",
|
||||
"f2b_list_info": "Ein Host oder Netzwerk auf der Blacklist wird immer eine Whitelist-Einheit überwiegen. <b>Die Aktualisierung der Liste dauert einige Sekunden.</b>",
|
||||
"f2b_max_attempts": "Max. Versuche",
|
||||
"f2b_max_ban_time": "Maximale Bannzeit in Sekunden",
|
||||
"f2b_netban_ipv4": "Netzbereich für IPv4-Banns (8-32)",
|
||||
"f2b_netban_ipv6": "Netzbereich für IPv6-Banns (8-128)",
|
||||
"f2b_parameters": "Fail2ban-Parameter",
|
||||
@@ -217,7 +214,6 @@
|
||||
"loading": "Bitte warten...",
|
||||
"login_time": "Zeit",
|
||||
"logo_info": "Die hochgeladene Grafik wird für die Navigationsleiste auf eine Höhe von 40px skaliert. Für die Darstellung auf der Login-Maske beträgt die skalierte Breite maximal 250px. Eine frei skalierbare Grafik (etwa SVG) wird empfohlen.",
|
||||
"favicon_info": "Das Bild muss eine PNG- oder ICO-Datei mit den Abmessungen <code>32 x 32</code>, <code>128 x 128</code>, <code>180 x 180</code>, <code>192 x 192</code> oder <code>256 x 256</code> sein. SOGo muss nachdem ändern neugestartet werden.",
|
||||
"lookup_mx": "Ziel mit MX vergleichen (Regex, etwa <code>.*google\\.com</code>, um alle Ziele mit MX *google.com zu routen)",
|
||||
"main_name": "\"mailcow UI\" Name",
|
||||
"merged_vars_hint": "Ausgegraute Reihen wurden aus der Datei <code>vars.(local.)inc.php</code> gelesen und können hier nicht verändert werden.",
|
||||
@@ -308,8 +304,6 @@
|
||||
"sender": "Sender",
|
||||
"service": "Dienst",
|
||||
"service_id": "Service",
|
||||
"sogo_theme": "SOGo Theme",
|
||||
"sogo_theme_info": "SOGo muss nachdem ändern neugestartet werden.",
|
||||
"source": "Quelle",
|
||||
"spamfilter": "Spamfilter",
|
||||
"subject": "Betreff",
|
||||
@@ -1044,7 +1038,6 @@
|
||||
"relayhost_added": "Map-Eintrag %s wurde hinzugefügt",
|
||||
"relayhost_removed": "Map-Eintrag %s wurde entfernt",
|
||||
"reset_main_logo": "Standardgrafik wurde wiederhergestellt",
|
||||
"reset_favicon": "Standard favicon wurde wiederhergestellt",
|
||||
"resource_added": "Ressource %s wurde angelegt",
|
||||
"resource_modified": "Änderungen an Ressource %s wurden gespeichert",
|
||||
"resource_removed": "Ressource %s wurde entfernt",
|
||||
@@ -1057,8 +1050,6 @@
|
||||
"template_modified": "Änderungen am Template %s wurden gespeichert",
|
||||
"template_removed": "Template ID %s wurde gelöscht",
|
||||
"sogo_profile_reset": "ActiveSync-Gerät des Benutzers %s wurde zurückgesetzt",
|
||||
"sogo_theme_modified": "SOGo Theme wurde gespeichert",
|
||||
"sogo_theme_removed": "SOGo Theme wurde entfernt",
|
||||
"tls_policy_map_entry_deleted": "TLS-Richtlinie mit der ID %s wurde gelöscht",
|
||||
"tls_policy_map_entry_saved": "TLS-Richtlinieneintrag \"%s\" wurde gespeichert",
|
||||
"ui_texts": "Änderungen an UI-Texten",
|
||||
|
@@ -147,7 +147,6 @@
|
||||
"ays": "Are you sure you want to proceed?",
|
||||
"ban_list_info": "See a list of banned IPs below: <b>network (remaining ban time) - [actions]</b>.<br />IPs queued to be unbanned will be removed from the active ban list within a few seconds.<br />Red labels indicate active permanent bans by blacklisting.",
|
||||
"change_logo": "Change logo",
|
||||
"change_favicon": "Change favicon",
|
||||
"configuration": "Configuration",
|
||||
"convert_html_to_text": "Convert HTML to plain text",
|
||||
"credentials_transport_warning": "<b>Warning</b>: Adding a new transport map entry will update the credentials for all entries with a matching next hop column.",
|
||||
@@ -178,12 +177,10 @@
|
||||
"empty": "No results",
|
||||
"excludes": "Excludes these recipients",
|
||||
"f2b_ban_time": "Ban time (s)",
|
||||
"f2b_ban_time_increment": "Ban time is incremented with each ban",
|
||||
"f2b_blacklist": "Blacklisted networks/hosts",
|
||||
"f2b_filter": "Regex filters",
|
||||
"f2b_list_info": "A blacklisted host or network will always outweigh a whitelist entity. <b>List updates will take a few seconds to be applied.</b>",
|
||||
"f2b_max_attempts": "Max. attempts",
|
||||
"f2b_max_ban_time": "Max. ban time (s)",
|
||||
"f2b_netban_ipv4": "IPv4 subnet size to apply ban on (8-32)",
|
||||
"f2b_netban_ipv6": "IPv6 subnet size to apply ban on (8-128)",
|
||||
"f2b_parameters": "Fail2ban parameters",
|
||||
@@ -219,7 +216,6 @@
|
||||
"loading": "Please wait...",
|
||||
"login_time": "Login time",
|
||||
"logo_info": "Your image will be scaled to a height of 40px for the top navigation bar and a max. width of 250px for the start page. A scalable graphic is highly recommended.",
|
||||
"favicon_info": "The image has to be a PNG or ICO file in the dimensions <code>32 x 32</code>, <code>128 x 128</code>, <code>180 x 180</code>, <code>192 x 192</code>, or <code>256 x 256</code>. Restart SOGo after changing the favicon",
|
||||
"lookup_mx": "Destination is a regular expression to match against MX name (<code>.*google\\.com</code> to route all mail targeted to a MX ending in google.com over this hop)",
|
||||
"main_name": "\"mailcow UI\" name",
|
||||
"merged_vars_hint": "Greyed out rows were merged from <code>vars.(local.)inc.php</code> and cannot be modified.",
|
||||
@@ -313,11 +309,6 @@
|
||||
"sender": "Sender",
|
||||
"service": "Service",
|
||||
"service_id": "Service ID",
|
||||
"sogo_theme": "SOGo Theme",
|
||||
"sogo_theme_info": "Restart SOGo after changing the theme.",
|
||||
"sogo_theme_primary": "Primary Color:",
|
||||
"sogo_theme_accent": "Accent Color:",
|
||||
"sogo_theme_background": "Background Color:",
|
||||
"source": "Source",
|
||||
"spamfilter": "Spam filter",
|
||||
"subject": "Subject",
|
||||
@@ -1054,7 +1045,6 @@
|
||||
"relayhost_added": "Map entry %s has been added",
|
||||
"relayhost_removed": "Map entry %s has been removed",
|
||||
"reset_main_logo": "Reset to default logo",
|
||||
"reset_favicon": "Reset to default favicon",
|
||||
"resource_added": "Resource %s has been added",
|
||||
"resource_modified": "Changes to mailbox %s have been saved",
|
||||
"resource_removed": "Resource %s has been removed",
|
||||
@@ -1064,8 +1054,6 @@
|
||||
"settings_map_added": "Added settings map entry",
|
||||
"settings_map_removed": "Removed settings map ID %s",
|
||||
"sogo_profile_reset": "SOGo profile for user %s was reset",
|
||||
"sogo_theme_modified": "SOGo Theme has been modified",
|
||||
"sogo_theme_removed": "SOGo Theme has been removed",
|
||||
"template_added": "Added template %s",
|
||||
"template_modified": "Changes to template %s have been saved",
|
||||
"template_removed": "Template ID %s has been deleted",
|
||||
|
@@ -141,11 +141,9 @@
|
||||
"empty": "Sin resultados",
|
||||
"excludes": "Excluye a estos destinatarios",
|
||||
"f2b_ban_time": "Tiempo de restricción (s)",
|
||||
"f2b_ban_time_increment": "Tiempo de restricción se incrementa con cada restricción",
|
||||
"f2b_blacklist": "Redes y hosts en lista negra",
|
||||
"f2b_list_info": "Un host o red en lista negra siempre superará a una entidad de la lista blanca. <b>Las actualizaciones de la lista tardarán unos segundos en aplicarse.</b>",
|
||||
"f2b_max_attempts": "Max num. de intentos",
|
||||
"f2b_max_ban_time": "Max tiempo de restricción (s)",
|
||||
"f2b_netban_ipv4": "Tamaño de subred IPv4 para aplicar la restricción (8-32)",
|
||||
"f2b_netban_ipv6": "Tamaño de subred IPv6 para aplicar la restricción (8-128)",
|
||||
"f2b_parameters": "Parametros Fail2ban",
|
||||
|
@@ -24,7 +24,7 @@
|
||||
"spam_policy": "Liste Noire/Liste Blanche",
|
||||
"spam_score": "Score SPAM",
|
||||
"syncjobs": "Tâches de synchronisation",
|
||||
"tls_policy": "Politique TLS",
|
||||
"tls_policy": "Police TLS",
|
||||
"unlimited_quota": "Quota illimité pour les boites de courriel",
|
||||
"domain_desc": "Modifier la description du domaine",
|
||||
"domain_relayhost": "Changer le relais pour un domaine",
|
||||
@@ -106,8 +106,7 @@
|
||||
"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.",
|
||||
"tags": "Etiquettes",
|
||||
"app_passwd_protocols": "Protocoles autorisés pour le mot de passe de l'application"
|
||||
"tags": "Etiquettes"
|
||||
},
|
||||
"admin": {
|
||||
"access": "Accès",
|
||||
@@ -172,13 +171,11 @@
|
||||
"edit": "Editer",
|
||||
"empty": "Aucun résultat",
|
||||
"excludes": "Exclure ces destinataires",
|
||||
"f2b_ban_time": "Durée du bannissement (s)",
|
||||
"f2b_ban_time_increment": "Durée du bannissement est augmentée à chaque bannissement",
|
||||
"f2b_ban_time": "Durée du bannissement(s)",
|
||||
"f2b_blacklist": "Réseaux/Domaines sur Liste Noire",
|
||||
"f2b_filter": "Filtre(s) Regex",
|
||||
"f2b_list_info": "Un hôte ou un réseau sur liste noire l'emportera toujours sur une entité de liste blanche. <b>L'application des mises à jour de liste prendra quelques secondes.</b>",
|
||||
"f2b_max_attempts": "Nb max. de tentatives",
|
||||
"f2b_max_ban_time": "Max. durée du bannissement (s)",
|
||||
"f2b_netban_ipv4": "Taille du sous-réseau IPv4 pour l'application du bannissement (8-32)",
|
||||
"f2b_netban_ipv6": "Taille du sous-réseau IPv6 pour l'application du bannissement (8-128)",
|
||||
"f2b_parameters": "Paramètres Fail2ban",
|
||||
@@ -324,9 +321,7 @@
|
||||
"admins": "Administrateurs",
|
||||
"api_read_only": "Accès lecture-seule",
|
||||
"password_policy_lowerupper": "Doit contenir des caractères minuscules et majuscules",
|
||||
"password_policy_numbers": "Doit contenir au moins un chiffre",
|
||||
"ip_check": "Vérification IP",
|
||||
"ip_check_disabled": "La vérification IP est désactivée. Vous pouvez l'activer sous<br> <strong>Système > Configuration > Options > Personnaliser</strong>"
|
||||
"password_policy_numbers": "Doit contenir au moins un chiffre"
|
||||
},
|
||||
"danger": {
|
||||
"access_denied": "Accès refusé ou données de formulaire non valides",
|
||||
@@ -445,12 +440,7 @@
|
||||
"username_invalid": "Le nom d'utilisateur %s ne peut pas être utilisé",
|
||||
"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",
|
||||
"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"
|
||||
"yotp_verification_failed": "La vérification Yubico OTP a échoué : %s"
|
||||
},
|
||||
"debug": {
|
||||
"chart_this_server": "Graphique (ce serveur)",
|
||||
@@ -588,7 +578,7 @@
|
||||
"unchanged_if_empty": "Si non modifié, laisser en blanc",
|
||||
"username": "Nom d'utilisateur",
|
||||
"validate_save": "Valider et sauver",
|
||||
"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)",
|
||||
"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."
|
||||
},
|
||||
"footer": {
|
||||
@@ -1091,12 +1081,9 @@
|
||||
"username": "Nom d'utilisateur",
|
||||
"verify": "Vérification",
|
||||
"waiting": "En attente",
|
||||
"week": "semaine",
|
||||
"week": "Semaine",
|
||||
"weekly": "Hebdomadaire",
|
||||
"weeks": "semaines",
|
||||
"months": "mois",
|
||||
"year": "année",
|
||||
"years": "années"
|
||||
"weeks": "semaines"
|
||||
},
|
||||
"warning": {
|
||||
"cannot_delete_self": "Impossible de supprimer l’utilisateur connecté",
|
||||
|
@@ -175,12 +175,10 @@
|
||||
"empty": "Nessun risultato",
|
||||
"excludes": "Esclude questi destinatari",
|
||||
"f2b_ban_time": "Tempo di blocco (s)",
|
||||
"f2b_ban_time_increment": "Tempo di blocco aumenta ad ogni blocco",
|
||||
"f2b_blacklist": "Host/reti in blacklist",
|
||||
"f2b_filter": "Filtri Regex",
|
||||
"f2b_list_info": "Un host oppure una rete in blacklist, avrà sempre un peso maggiore rispetto ad una in whitelist. <b>L'aggiornamento della lista richiede alcuni secondi per la sua entrata in azione.</b>",
|
||||
"f2b_max_attempts": "Tentativi massimi",
|
||||
"f2b_max_ban_time": "Tempo massimo di blocco (s)",
|
||||
"f2b_netban_ipv4": "IPv4 subnet size to apply ban on (8-32)",
|
||||
"f2b_netban_ipv6": "IPv6 subnet size to apply ban on (8-128)",
|
||||
"f2b_parameters": "Parametri Fail2ban",
|
||||
|
@@ -168,12 +168,10 @@
|
||||
"empty": "Geen resultaten",
|
||||
"excludes": "Exclusief",
|
||||
"f2b_ban_time": "Verbanningstijd (s)",
|
||||
"f2b_ban_time_increment": "Verbanningstijd wordt verhoogd met elk verbanning",
|
||||
"f2b_blacklist": "Netwerken/hosts op de blacklist",
|
||||
"f2b_filter": "Regex-filters",
|
||||
"f2b_list_info": "Een host of netwerk op de blacklist staat altijd boven eenzelfde op de whitelist. <b>Het doorvoeren van wijzigingen kan enkele seconden in beslag nemen.</b>",
|
||||
"f2b_max_attempts": "Maximaal aantal pogingen",
|
||||
"f2b_max_ban_time": "Maximaal verbanningstijd (s)",
|
||||
"f2b_netban_ipv4": "Voer de IPv4-subnetgrootte in waar de verbanning van kracht moet zijn (8-32)",
|
||||
"f2b_netban_ipv6": "Voer de IPv6-subnetgrootte in waar de verbanning van kracht moet zijn (8-128)",
|
||||
"f2b_parameters": "Fail2ban",
|
||||
|
@@ -1,8 +1,7 @@
|
||||
{
|
||||
"acl": {
|
||||
"sogo_profile_reset": "Usuń profil SOGo (webmail)",
|
||||
"syncjobs": "Polecenie synchronizacji",
|
||||
"alias_domains": "Dodaj aliasy domen"
|
||||
"syncjobs": "Polecenie synchronizacji"
|
||||
},
|
||||
"add": {
|
||||
"active": "Aktywny",
|
||||
|
@@ -60,7 +60,7 @@ elseif (isset($_GET['login'])) {
|
||||
':remote_addr' => ($_SERVER['HTTP_X_REAL_IP'] ?? $_SERVER['REMOTE_ADDR'])
|
||||
));
|
||||
// redirect to sogo (sogo will get the correct credentials via nginx auth_request
|
||||
header("Location: /SOGo/so/{$login}");
|
||||
header("Location: /SOGo/so/${login}");
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
@@ -7,8 +7,6 @@
|
||||
<span class="d-none d-md-block">{{ lang.admin.customize }}</span>
|
||||
</div>
|
||||
<div id="collapse-tab-config-customize" class="card-body collapse" data-bs-parent="#admin-content">
|
||||
<div class="row">
|
||||
<div class="col-12 col-lg-6 d-flex flex-column">
|
||||
<legend><i class="bi bi-file-image"></i> {{ lang.admin.change_logo }}</legend><hr />
|
||||
<p class="text-muted">{{ lang.admin.logo_info }}</p>
|
||||
<form class="form-inline" role="form" method="post" enctype="multipart/form-data">
|
||||
@@ -18,78 +16,22 @@
|
||||
</p>
|
||||
</form>
|
||||
{% if logo %}
|
||||
<div class="thumbnail mt-auto">
|
||||
<div class="row">
|
||||
<div class="col-sm-4">
|
||||
<div class="thumbnail">
|
||||
<img class="img-thumbnail" src="{{ logo }}" alt="mailcow logo">
|
||||
<div class="caption d-flex flex-wrap mt-2 mb-4">
|
||||
<div class="caption">
|
||||
<span class="badge fs-5 bg-info">{{ logo_specs.geometry.width }}x{{ logo_specs.geometry.height }} px</span>
|
||||
<span class="badge fs-5 bg-info mx-2">{{ logo_specs.mimetype }}</span>
|
||||
<span class="badge fs-5 bg-info">{{ logo_specs.mimetype }}</span>
|
||||
<span class="badge fs-5 bg-info">{{ logo_specs.fileSize }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
<form class="form-inline" role="form" method="post">
|
||||
<p><button name="reset_main_logo" type="submit" class="btn btn-sm d-block d-sm-inline btn-secondary">{{ lang.admin.reset_default }}</button></p>
|
||||
</form>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="col-12 col-lg-6 d-flex flex-column">
|
||||
<legend><i class="bi bi-file-image"></i> {{ lang.admin.change_favicon }}</legend><hr />
|
||||
<p class="text-muted">{{ lang.admin.favicon_info|raw }}</p>
|
||||
<form class="form-inline" role="form" method="post" enctype="multipart/form-data">
|
||||
<p>
|
||||
<input class="mb-4" type="file" name="favicon" accept="image/x-icon, image/png"><br>
|
||||
<button name="submit_favicon" type="submit" class="btn btn-sm d-block d-sm-inline btn-secondary"><i class="bi bi-upload"></i> {{ lang.admin.upload }}</button>
|
||||
</p>
|
||||
</form>
|
||||
{% if favicon %}
|
||||
<div class="thumbnail mt-auto">
|
||||
<img class="img-thumbnail" src="{{ favicon }}" alt="mailcow favicon">
|
||||
<div class="caption d-flex flex-wrap mt-2 mb-4">
|
||||
<span class="badge fs-5 bg-info">{{ favicon_specs.geometry.width }}x{{ favicon_specs.geometry.height }} px</span>
|
||||
<span class="badge fs-5 bg-info mx-2">{{ favicon_specs.mimetype }}</span>
|
||||
<span class="badge fs-5 bg-info">{{ favicon_specs.fileSize }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<form class="form-inline" role="form" method="post">
|
||||
<p><button name="reset_favicon" type="submit" class="btn btn-sm d-block d-sm-inline btn-secondary">{{ lang.admin.reset_default }}</button></p>
|
||||
</form>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% if not skip_sogo %}
|
||||
<legend style="padding-top:20px" unselectable="on">{{ lang.admin.sogo_theme }}</legend><hr />
|
||||
<form class="form" data-id="sogo_theme" role="form" method="post">
|
||||
<div class="mb-4 row">
|
||||
<div class="col-12 col-md-4 mb-2">
|
||||
<label class="d-block" for="sogo_primary">{{ lang.admin.sogo_theme_primary }}</label>
|
||||
<select multiple data-width="100%" id="sogo_primary" name="primary" class="selectpicker show-tick" data-max-options="1" data-id="sogo_theme">
|
||||
{% for sogo_palette in sogo_palettes %}
|
||||
<option {% if sogo_palette == sogo_theme.primary %}selected{% endif %} value="{{ sogo_palette }}">{{ sogo_palette }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-12 col-md-4 mb-2">
|
||||
<label class="d-block" for="sogo_accent">{{ lang.admin.sogo_theme_accent }}</label>
|
||||
<select multiple data-width="100%" id="sogo_accent" name="accent" class="selectpicker show-tick" data-max-options="1" data-id="sogo_theme">
|
||||
{% for sogo_palette in sogo_palettes %}
|
||||
<option {% if sogo_palette == sogo_theme.accent %}selected{% endif %} value="{{ sogo_palette }}">{{ sogo_palette }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-12 col-md-4 mb-2">
|
||||
<label class="d-block" for="sogo_background">{{ lang.admin.sogo_theme_background }}</label>
|
||||
<select multiple data-width="100%" id="sogo_background" name="background" class="selectpicker show-tick" data-max-options="1" data-id="sogo_theme">
|
||||
{% for sogo_palette in sogo_palettes %}
|
||||
<option {% if sogo_palette == sogo_theme.background %}selected{% endif %} value="{{ sogo_palette }}">{{ sogo_palette }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<p class="text-muted">{{ lang.admin.sogo_theme_info }}</p>
|
||||
<p><div class="btn-group">
|
||||
<button class="btn btn-sm btn-xs-half d-block d-sm-inline btn-success" type="button" data-action="edit_selected" data-item="sogo-theme" data-id="sogo_theme" data-reload="no" data-api-url='edit/sogo_theme' data-api-attr='{}'><i class="bi bi-check-lg"></i> {{ lang.admin.save }}</button>
|
||||
<button class="btn btn-sm btn-xs-half d-block d-sm-inline btn-danger" type="button" data-action="delete_selected" data-item="sogo-theme" data-id="sogo_theme" data-api-url="delete/sogo_theme"><i class="bi bi-trash"></i> {{ lang.admin.remove }}</button>
|
||||
</div></p>
|
||||
</form>
|
||||
{% endif %}
|
||||
<legend style="padding-top:20px" unselectable="on">{{ lang.admin.ip_check }}</legend><hr />
|
||||
<div id="ip_check">
|
||||
|
@@ -12,14 +12,6 @@
|
||||
<label for="f2b_ban_time">{{ lang.admin.f2b_ban_time }}:</label>
|
||||
<input type="number" class="form-control" id="f2b_ban_time" name="ban_time" value="{{ f2b_data.ban_time }}" required>
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<label for="f2b_max_ban_time">{{ lang.admin.f2b_max_ban_time }}:</label>
|
||||
<input type="number" class="form-control" id="f2b_max_ban_time" name="max_ban_time" value="{{ f2b_data.max_ban_time }}" required>
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<input class="form-check-input" type="checkbox" value="1" name="ban_time_increment" id="f2b_ban_time_increment" {% if f2b_data.ban_time_increment == 1 %}checked{% endif %}>
|
||||
<label class="form-check-label" for="f2b_ban_time_increment">{{ lang.admin.f2b_ban_time_increment }}</label>
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<label for="f2b_max_attempts">{{ lang.admin.f2b_max_attempts }}:</label>
|
||||
<input type="number" class="form-control" id="f2b_max_attempts" name="max_attempts" value="{{ f2b_data.max_attempts }}" required>
|
||||
|
@@ -23,8 +23,8 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<link rel="shortcut icon" href="{{ favicon|default('/favicon.png') }}" type="image/png">
|
||||
<link rel="icon" href="{{ favicon|default('/favicon.png') }}" type="image/png">
|
||||
<link rel="shortcut icon" href="/favicon.png" type="image/png">
|
||||
<link rel="icon" href="/favicon.png" type="image/png">
|
||||
</head>
|
||||
<body>
|
||||
<div class="overlay"></div>
|
||||
|
@@ -612,7 +612,7 @@
|
||||
<li class="table_collapse_option"><a class="dropdown-item" data-datatables-expand="rl_log" data-table="rl_log" href="#">{{ lang.datatables.expand_all }}</a></li>
|
||||
<li class="table_collapse_option"><a class="dropdown-item" data-datatables-collapse="rl_log" data-table="rl_log" href="#">{{ lang.datatables.collapse_all }}</a></li>
|
||||
</ul>
|
||||
<p class="text-muted">{{ lang.admin.hash_remove_info|raw }}</p>
|
||||
<p class="text-muted">{{ lang.admin.hash_remove_info }}</p>
|
||||
<table id="rl_log" class="table table-striped dt-responsive w-100"></table>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -109,25 +109,25 @@
|
||||
<label class="control-label col-sm-2">{{ lang.user.quarantine_notification }}</label>
|
||||
<div class="col-sm-10">
|
||||
<div class="btn-group" data-acl="{{ acl.quarantine_notification }}">
|
||||
<button type="button" class="btn btn-sm btn-xs-quart d-block d-sm-inline btn-light{% if quarantine_notification == 'never' %} btn-dark{% endif %}"
|
||||
<button type="button" class="btn btn-sm btn-xs-quart d-block d-sm-inline btn-secondary{% if quarantine_notification == 'never' %} active{% endif %}"
|
||||
data-action="edit_selected"
|
||||
data-item="{{ mailbox }}"
|
||||
data-id="quarantine_notification"
|
||||
data-api-url='edit/quarantine_notification'
|
||||
data-api-attr='{"quarantine_notification":"never"}'>{{ lang.user.never }}</button>
|
||||
<button type="button" class="btn btn-sm btn-xs-quart d-block d-sm-inline btn-light{% if quarantine_notification == 'hourly' %} btn-dark{% endif %}"
|
||||
<button type="button" class="btn btn-sm btn-xs-quart d-block d-sm-inline btn-secondary{% if quarantine_notification == 'hourly' %} active{% endif %}"
|
||||
data-action="edit_selected"
|
||||
data-item="{{ mailbox }}"
|
||||
data-id="quarantine_notification"
|
||||
data-api-url='edit/quarantine_notification'
|
||||
data-api-attr='{"quarantine_notification":"hourly"}'>{{ lang.user.hourly }}</button>
|
||||
<button type="button" class="btn btn-sm btn-xs-quart d-block d-sm-inline btn-light{% if quarantine_notification == 'daily' %} btn-dark{% endif %}"
|
||||
<button type="button" class="btn btn-sm btn-xs-quart d-block d-sm-inline btn-secondary{% if quarantine_notification == 'daily' %} active{% endif %}"
|
||||
data-action="edit_selected"
|
||||
data-item="{{ mailbox }}"
|
||||
data-id="quarantine_notification"
|
||||
data-api-url='edit/quarantine_notification'
|
||||
data-api-attr='{"quarantine_notification":"daily"}'>{{ lang.user.daily }}</button>
|
||||
<button type="button" class="btn btn-sm btn-xs-quart d-block d-sm-inline btn-light{% if quarantine_notification == 'weekly' %} btn-dark{% endif %}"
|
||||
<button type="button" class="btn btn-sm btn-xs-quart d-block d-sm-inline btn-secondary{% if quarantine_notification == 'weekly' %} active{% endif %}"
|
||||
data-action="edit_selected"
|
||||
data-item="{{ mailbox }}"
|
||||
data-id="quarantine_notification"
|
||||
@@ -141,19 +141,19 @@
|
||||
<label class="control-label col-sm-2">{{ lang.user.quarantine_category }}</label>
|
||||
<div class="col-sm-10">
|
||||
<div class="btn-group" data-acl="{{ acl.quarantine_category }}">
|
||||
<button type="button" class="btn btn-sm btn-xs-third d-block d-sm-inline btn-light{% if quarantine_category == 'reject' %} btn-dark{% endif %}"
|
||||
<button type="button" class="btn btn-sm btn-xs-third d-block d-sm-inline btn-secondary{% if quarantine_category == 'reject' %} active{% endif %}"
|
||||
data-action="edit_selected"
|
||||
data-item="{{ mailbox }}"
|
||||
data-id="quarantine_category"
|
||||
data-api-url='edit/quarantine_category'
|
||||
data-api-attr='{"quarantine_category":"reject"}'>{{ lang.user.q_reject }}</button>
|
||||
<button type="button" class="btn btn-sm btn-xs-third d-block d-sm-inline btn-light{% if quarantine_category == 'add_header' %} btn-dark{% endif %}"
|
||||
<button type="button" class="btn btn-sm btn-xs-third d-block d-sm-inline btn-secondary{% if quarantine_category == 'add_header' %} active{% endif %}"
|
||||
data-action="edit_selected"
|
||||
data-item="{{ mailbox }}"
|
||||
data-id="quarantine_category"
|
||||
data-api-url='edit/quarantine_category'
|
||||
data-api-attr='{"quarantine_category":"add_header"}'>{{ lang.user.q_add_header }}</button>
|
||||
<button type="button" class="btn btn-sm btn-xs-third d-block d-sm-inline btn-light{% if quarantine_category == 'all' %} btn-dark{% endif %}"
|
||||
<button type="button" class="btn btn-sm btn-xs-third d-block d-sm-inline btn-secondary{% if quarantine_category == 'all' %} active{% endif %}"
|
||||
data-action="edit_selected"
|
||||
data-item="{{ mailbox }}"
|
||||
data-id="quarantine_category"
|
||||
@@ -167,13 +167,13 @@
|
||||
<label class="control-label col-sm-2" for="sender_acl">{{ lang.user.tls_policy }}</label>
|
||||
<div class="col-sm-10">
|
||||
<div class="btn-group" data-acl="{{ acl.tls_policy }}">
|
||||
<button type="button" class="btn btn-sm btn-xs-half d-block d-sm-inline btn-light{% if get_tls_policy.tls_enforce_in == '1' %} btn-dark"{% endif %}"
|
||||
<button type="button" class="btn btn-sm btn-xs-half d-block d-sm-inline btn-secondary{% if get_tls_policy.tls_enforce_in == '1' %} active"{% endif %}"
|
||||
data-action="edit_selected"
|
||||
data-item="{{ mailbox }}"
|
||||
data-id="tls_policy"
|
||||
data-api-url='edit/tls_policy'
|
||||
data-api-attr='{"tls_enforce_in": {% if get_tls_policy.tls_enforce_in == '1' %}0{% else %}1{% endif %} }'>{{ lang.user.tls_enforce_in }}</button>
|
||||
<button type="button" class="btn btn-sm btn-xs-half d-block d-sm-inline btn-light{% if get_tls_policy.tls_enforce_out == '1' %} btn-dark"{% endif %}"
|
||||
<button type="button" class="btn btn-sm btn-xs-half d-block d-sm-inline btn-secondary{% if get_tls_policy.tls_enforce_out == '1' %} active"{% endif %}"
|
||||
data-action="edit_selected"
|
||||
data-item="{{ mailbox }}"
|
||||
data-id="tls_policy"
|
||||
|
@@ -19,7 +19,7 @@
|
||||
</li>
|
||||
<li class="nav-item" role="presentation"><button class="nav-link" aria-controls="tab-resources" role="tab" data-bs-toggle="tab" data-bs-target="#tab-resources">{{ lang.mailbox.resources }}</button></li>
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" data-bs-toggle="dropdown" href="#">{{ lang.mailbox.aliases }}</a>
|
||||
<a class="nav-link dropdown-toggle" data-bs-toggle="dropdown" data-bs-target="#">{{ lang.mailbox.aliases }}</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li role="presentation"><button class="dropdown-item" aria-selected="false" aria-controls="tab-mbox-aliases" role="tab" data-bs-toggle="tab" data-bs-target="#tab-mbox-aliases">{{ lang.mailbox.aliases }}</button></li>
|
||||
<li role="presentation"><button class="dropdown-item" aria-selected="false" aria-controls="tab-domain-aliases" role="tab" data-bs-toggle="tab" data-bs-target="#tab-domain-aliases">{{ lang.mailbox.domain_aliases }}</button></li>
|
||||
|
@@ -54,7 +54,6 @@
|
||||
<li class="dropdown-header">SMTP</li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/mailbox' data-api-attr='{"smtp_access":1}' href="#">{{ lang.mailbox.activate }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/mailbox' data-api-attr='{"smtp_access":0}' href="#">{{ lang.mailbox.deactivate }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li class="dropdown-header">Sieve</li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/mailbox' data-api-attr='{"sieve_access":1}' href="#">{{ lang.mailbox.activate }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/mailbox' data-api-attr='{"sieve_access":0}' href="#">{{ lang.mailbox.deactivate }}</a></li>
|
||||
|
@@ -12,19 +12,19 @@
|
||||
<div class="col-sm-3 col-12 text-sm-end text-start text-xs-bold mb-4">{{ lang.user.tag_handling }}:</div>
|
||||
<div class="col-sm-9 col-12">
|
||||
<div class="btn-group" data-acl="{{ acl.delimiter_action }}">
|
||||
<button type="button" class="btn btn-sm btn-xs-third d-block d-sm-inline btn-light{% if get_tagging_options == 'subfolder' %} btn-dark{% endif %}"
|
||||
<button type="button" class="btn btn-sm btn-xs-third d-block d-sm-inline btn-secondary{% if get_tagging_options == 'subfolder' %} active{% endif %}"
|
||||
data-action="edit_selected"
|
||||
data-item="{{ mailcow_cc_username }}"
|
||||
data-id="delimiter_action"
|
||||
data-api-url='edit/delimiter_action'
|
||||
data-api-attr='{"tagged_mail_handler":"subfolder"}'>{{ lang.user.tag_in_subfolder }}</button>
|
||||
<button type="button" class="btn btn-sm btn-xs-third d-block d-sm-inline btn-light{% if get_tagging_options == 'subject' %} btn-dark{% endif %}"
|
||||
<button type="button" class="btn btn-sm btn-xs-third d-block d-sm-inline btn-secondary{% if get_tagging_options == 'subject' %} active{% endif %}"
|
||||
data-action="edit_selected"
|
||||
data-item="{{ mailcow_cc_username }}"
|
||||
data-id="delimiter_action"
|
||||
data-api-url='edit/delimiter_action'
|
||||
data-api-attr='{"tagged_mail_handler":"subject"}'>{{ lang.user.tag_in_subject }}</button>
|
||||
<button type="button" class="btn btn-sm btn-xs-third d-block d-sm-inline btn-light{% if get_tagging_options == 'none' %} btn-dark{% endif %}"
|
||||
<button type="button" class="btn btn-sm btn-xs-third d-block d-sm-inline btn-secondary{% if get_tagging_options == 'none' %} active{% endif %}"
|
||||
data-action="edit_selected"
|
||||
data-item="{{ mailcow_cc_username }}"
|
||||
data-id="delimiter_action"
|
||||
@@ -40,13 +40,13 @@
|
||||
<div class="col-sm-3 col-12 text-sm-end text-start text-xs-bold mb-4">{{ lang.user.tls_policy }}:</div>
|
||||
<div class="col-sm-9 col-12">
|
||||
<div class="btn-group" data-acl="{{ acl.tls_policy }}">
|
||||
<button type="button" class="btn btn-sm btn-xs-half d-block d-sm-inline btn-light{% if get_tls_policy.tls_enforce_in == '1' %} btn-dark"{% endif %}"
|
||||
<button type="button" class="btn btn-sm btn-xs-half d-block d-sm-inline btn-secondary{% if get_tls_policy.tls_enforce_in == '1' %} active"{% endif %}"
|
||||
data-action="edit_selected"
|
||||
data-item="{{ mailcow_cc_username }}"
|
||||
data-id="tls_policy"
|
||||
data-api-url='edit/tls_policy'
|
||||
data-api-attr='{"tls_enforce_in": {% if get_tls_policy.tls_enforce_in == '1' %}0{% else %}1{% endif %} }'>{{ lang.user.tls_enforce_in }}</button>
|
||||
<button type="button" class="btn btn-sm btn-xs-half d-block d-sm-inline btn-light{% if get_tls_policy.tls_enforce_out == '1' %} btn-dark"{% endif %}"
|
||||
<button type="button" class="btn btn-sm btn-xs-half d-block d-sm-inline btn-secondary{% if get_tls_policy.tls_enforce_out == '1' %} active"{% endif %}"
|
||||
data-action="edit_selected"
|
||||
data-item="{{ mailcow_cc_username }}"
|
||||
data-id="tls_policy"
|
||||
@@ -61,25 +61,25 @@
|
||||
<div class="col-sm-3 col-12 text-sm-end text-start text-xs-bold mb-4">{{ lang.user.quarantine_notification }}:</div>
|
||||
<div class="col-sm-9 col-12">
|
||||
<div class="btn-group" data-acl="{{ acl.quarantine_notification }}">
|
||||
<button type="button" class="btn btn-sm btn-xs-quart d-block d-sm-inline btn-light{% if quarantine_notification == 'never' %} btn-dark{% endif %}"
|
||||
<button type="button" class="btn btn-sm btn-xs-quart d-block d-sm-inline btn-secondary{% if quarantine_notification == 'never' %} active{% endif %}"
|
||||
data-action="edit_selected"
|
||||
data-item="{{ mailcow_cc_username }}"
|
||||
data-id="quarantine_notification"
|
||||
data-api-url='edit/quarantine_notification'
|
||||
data-api-attr='{"quarantine_notification":"never"}'>{{ lang.user.never }}</button>
|
||||
<button type="button" class="btn btn-sm btn-xs-quart d-block d-sm-inline btn-light{% if quarantine_notification == 'hourly' %} btn-dark{% endif %}"
|
||||
<button type="button" class="btn btn-sm btn-xs-quart d-block d-sm-inline btn-secondary{% if quarantine_notification == 'hourly' %} active{% endif %}"
|
||||
data-action="edit_selected"
|
||||
data-item="{{ mailcow_cc_username }}"
|
||||
data-id="quarantine_notification"
|
||||
data-api-url='edit/quarantine_notification'
|
||||
data-api-attr='{"quarantine_notification":"hourly"}'>{{ lang.user.hourly }}</button>
|
||||
<button type="button" class="btn btn-sm btn-xs-quart d-block d-sm-inline btn-light{% if quarantine_notification == 'daily' %} btn-dark{% endif %}"
|
||||
<button type="button" class="btn btn-sm btn-xs-quart d-block d-sm-inline btn-secondary{% if quarantine_notification == 'daily' %} active{% endif %}"
|
||||
data-action="edit_selected"
|
||||
data-item="{{ mailcow_cc_username }}"
|
||||
data-id="quarantine_notification"
|
||||
data-api-url='edit/quarantine_notification'
|
||||
data-api-attr='{"quarantine_notification":"daily"}'>{{ lang.user.daily }}</button>
|
||||
<button type="button" class="btn btn-sm btn-xs-quart d-block d-sm-inline btn-light{% if quarantine_notification == 'weekly' %} btn-dark{% endif %}"
|
||||
<button type="button" class="btn btn-sm btn-xs-quart d-block d-sm-inline btn-secondary{% if quarantine_notification == 'weekly' %} active{% endif %}"
|
||||
data-action="edit_selected"
|
||||
data-item="{{ mailcow_cc_username }}"
|
||||
data-id="quarantine_notification"
|
||||
@@ -93,19 +93,19 @@
|
||||
<div class="col-sm-3 col-12 text-sm-end text-start text-xs-bold mb-4">{{ lang.user.quarantine_category }}:</div>
|
||||
<div class="col-sm-9 col-12">
|
||||
<div class="btn-group" data-acl="{{ acl.quarantine_category }}">
|
||||
<button type="button" class="btn btn-sm btn-xs-third d-block d-sm-inline btn-light{% if quarantine_category == 'reject' %} btn-dark{% endif %}"
|
||||
<button type="button" class="btn btn-sm btn-xs-third d-block d-sm-inline btn-secondary{% if quarantine_category == 'reject' %} active{% endif %}"
|
||||
data-action="edit_selected"
|
||||
data-item="{{ mailcow_cc_username }}"
|
||||
data-id="quarantine_category"
|
||||
data-api-url='edit/quarantine_category'
|
||||
data-api-attr='{"quarantine_category":"reject"}'>{{ lang.user.q_reject }}</button>
|
||||
<button type="button" class="btn btn-sm btn-xs-third d-block d-sm-inline btn-light{% if quarantine_category == 'add_header' %} btn-dark{% endif %}"
|
||||
<button type="button" class="btn btn-sm btn-xs-third d-block d-sm-inline btn-secondary{% if quarantine_category == 'add_header' %} active{% endif %}"
|
||||
data-action="edit_selected"
|
||||
data-item="{{ mailcow_cc_username }}"
|
||||
data-id="quarantine_category"
|
||||
data-api-url='edit/quarantine_category'
|
||||
data-api-attr='{"quarantine_category":"add_header"}'>{{ lang.user.q_add_header }}</button>
|
||||
<button type="button" class="btn btn-sm btn-xs-third d-block d-sm-inline btn-light{% if quarantine_category == 'all' %} btn-dark{% endif %}"
|
||||
<button type="button" class="btn btn-sm btn-xs-third d-block d-sm-inline btn-secondary{% if quarantine_category == 'all' %} active{% endif %}"
|
||||
data-action="edit_selected"
|
||||
data-item="{{ mailcow_cc_username }}"
|
||||
data-id="quarantine_category"
|
||||
|
@@ -106,7 +106,7 @@ services:
|
||||
- rspamd
|
||||
|
||||
php-fpm-mailcow:
|
||||
image: mailcow/phpfpm:1.83
|
||||
image: mailcow/phpfpm:1.82
|
||||
command: "php-fpm -d date.timezone=${TZ} -d expose_php=0"
|
||||
depends_on:
|
||||
- redis-mailcow
|
||||
@@ -154,7 +154,7 @@ services:
|
||||
- API_KEY_READ_ONLY=${API_KEY_READ_ONLY:-invalid}
|
||||
- API_ALLOW_FROM=${API_ALLOW_FROM:-invalid}
|
||||
- COMPOSE_PROJECT_NAME=${COMPOSE_PROJECT_NAME:-mailcow-dockerized}
|
||||
- SKIP_SOLR=${SKIP_SOLR:-y}
|
||||
- SKIP_XAPIAN=${SKIP_XAPIAN:-y}
|
||||
- SKIP_CLAMD=${SKIP_CLAMD:-n}
|
||||
- SKIP_SOGO=${SKIP_SOGO:-n}
|
||||
- ALLOW_ADMIN_EMAIL_LOGIN=${ALLOW_ADMIN_EMAIL_LOGIN:-n}
|
||||
@@ -169,7 +169,7 @@ services:
|
||||
- phpfpm
|
||||
|
||||
sogo-mailcow:
|
||||
image: mailcow/sogo:1.118
|
||||
image: mailcow/sogo:1.115
|
||||
environment:
|
||||
- DBNAME=${DBNAME}
|
||||
- DBUSER=${DBUSER}
|
||||
@@ -191,7 +191,7 @@ services:
|
||||
volumes:
|
||||
- ./data/hooks/sogo:/hooks:Z
|
||||
- ./data/conf/sogo/:/etc/sogo/:z
|
||||
- ./data/web/inc/init_db.inc.php:/init_db.inc.php:z
|
||||
- ./data/web/inc/init_db.inc.php:/init_db.inc.php:Z
|
||||
- ./data/conf/sogo/custom-favicon.ico:/usr/lib/GNUstep/SOGo/WebServerResources/img/sogo.ico:z
|
||||
- ./data/conf/sogo/custom-theme.js:/usr/lib/GNUstep/SOGo/WebServerResources/js/theme.js:z
|
||||
- ./data/conf/sogo/custom-sogo.js:/usr/lib/GNUstep/SOGo/WebServerResources/js/custom-sogo.js:z
|
||||
@@ -216,7 +216,7 @@ services:
|
||||
- sogo
|
||||
|
||||
dovecot-mailcow:
|
||||
image: mailcow/dovecot:1.23
|
||||
image: mailcow/dovecot:1.20-xapian
|
||||
depends_on:
|
||||
- mysql-mailcow
|
||||
dns:
|
||||
@@ -250,7 +250,8 @@ services:
|
||||
- ALLOW_ADMIN_EMAIL_LOGIN=${ALLOW_ADMIN_EMAIL_LOGIN:-n}
|
||||
- MAILDIR_GC_TIME=${MAILDIR_GC_TIME:-7200}
|
||||
- ACL_ANYONE=${ACL_ANYONE:-disallow}
|
||||
- SKIP_SOLR=${SKIP_SOLR:-y}
|
||||
- SKIP_XAPIAN=${SKIP_XAPIAN:-y}
|
||||
- XAPIAN_HEAP=${XAPIAN_HEAP:-1024}
|
||||
- MAILDIR_SUB=${MAILDIR_SUB:-}
|
||||
- MASTER=${MASTER:-y}
|
||||
- REDIS_SLAVEOF_IP=${REDIS_SLAVEOF_IP:-}
|
||||
@@ -281,7 +282,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: "doveadm fts optimize -A"
|
||||
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:
|
||||
@@ -425,7 +426,7 @@ services:
|
||||
- acme
|
||||
|
||||
netfilter-mailcow:
|
||||
image: mailcow/netfilter:1.52
|
||||
image: mailcow/netfilter:1.51
|
||||
stop_grace_period: 30s
|
||||
depends_on:
|
||||
- dovecot-mailcow
|
||||
@@ -510,7 +511,7 @@ services:
|
||||
- watchdog
|
||||
|
||||
dockerapi-mailcow:
|
||||
image: mailcow/dockerapi:2.04
|
||||
image: mailcow/dockerapi:2.01
|
||||
security_opt:
|
||||
- label=disable
|
||||
restart: always
|
||||
@@ -528,22 +529,6 @@ services:
|
||||
aliases:
|
||||
- dockerapi
|
||||
|
||||
solr-mailcow:
|
||||
image: mailcow/solr:1.8.1
|
||||
restart: always
|
||||
volumes:
|
||||
- solr-vol-1:/opt/solr/server/solr/dovecot-fts/data
|
||||
ports:
|
||||
- "${SOLR_PORT:-127.0.0.1:18983}:8983"
|
||||
environment:
|
||||
- TZ=${TZ}
|
||||
- SOLR_HEAP=${SOLR_HEAP:-1024}
|
||||
- SKIP_SOLR=${SKIP_SOLR:-y}
|
||||
networks:
|
||||
mailcow-network:
|
||||
aliases:
|
||||
- solr
|
||||
|
||||
olefy-mailcow:
|
||||
image: mailcow/olefy:1.11
|
||||
restart: always
|
||||
@@ -599,7 +584,6 @@ services:
|
||||
- netfilter-mailcow
|
||||
- watchdog-mailcow
|
||||
- dockerapi-mailcow
|
||||
- solr-mailcow
|
||||
environment:
|
||||
- TZ=${TZ}
|
||||
image: robbertkl/ipv6nat
|
||||
@@ -631,7 +615,6 @@ volumes:
|
||||
mysql-socket-vol-1:
|
||||
redis-vol-1:
|
||||
rspamd-vol-1:
|
||||
solr-vol-1:
|
||||
postfix-vol-1:
|
||||
crypt-vol-1:
|
||||
sogo-web-vol-1:
|
||||
|
@@ -122,23 +122,23 @@ else
|
||||
fi
|
||||
|
||||
if [ ${MEM_TOTAL} -le "2097152" ]; then
|
||||
echo "Disabling Solr on low-memory system."
|
||||
SKIP_SOLR=y
|
||||
echo "Disabling Xapian (full text search, build in Dovecot) on low-memory system."
|
||||
SKIP_XAPIAN=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
|
||||
echo "Installed memory is <= 3.5 GiB. We suggest you to disable Xapian (full text search, build in Dovecot) to prevent out-of-memory situations."
|
||||
echo "The default Xapian heap size is 1024 MiB and should be set in mailcow.conf according to your expected load."
|
||||
echo "Xapian can be re-enabled by setting SKIP_XAPIAN=n in mailcow.conf but will refuse to start with less than 2 GB total memory."
|
||||
read -r -p "Do you want to disable the FTS Xapian now? [Y/n] " response
|
||||
case $response in
|
||||
[nN][oO]|[nN])
|
||||
SKIP_SOLR=n
|
||||
SKIP_XAPIAN=n
|
||||
;;
|
||||
*)
|
||||
SKIP_SOLR=y
|
||||
SKIP_XAPIAN=y
|
||||
;;
|
||||
esac
|
||||
else
|
||||
SKIP_SOLR=n
|
||||
SKIP_XAPIAN=n
|
||||
fi
|
||||
|
||||
if [[ ${SKIP_BRANCH} != y ]]; then
|
||||
@@ -205,8 +205,8 @@ DBUSER=mailcow
|
||||
|
||||
# Please use long, random alphanumeric strings (A-Za-z0-9)
|
||||
|
||||
DBPASS=$(LC_ALL=C </dev/urandom tr -dc A-Za-z0-9 2> /dev/null | head -c 28)
|
||||
DBROOT=$(LC_ALL=C </dev/urandom tr -dc A-Za-z0-9 2> /dev/null | head -c 28)
|
||||
DBPASS=$(LC_ALL=C </dev/urandom tr -dc A-Za-z0-9 | head -c 28)
|
||||
DBROOT=$(LC_ALL=C </dev/urandom tr -dc A-Za-z0-9 | head -c 28)
|
||||
|
||||
# ------------------------------
|
||||
# HTTP/S Bindings
|
||||
@@ -243,7 +243,6 @@ POPS_PORT=995
|
||||
SIEVE_PORT=4190
|
||||
DOVEADM_PORT=127.0.0.1:19991
|
||||
SQL_PORT=127.0.0.1:13306
|
||||
SOLR_PORT=127.0.0.1:18983
|
||||
REDIS_PORT=127.0.0.1:7654
|
||||
|
||||
# Your timezone
|
||||
@@ -261,7 +260,7 @@ COMPOSE_PROJECT_NAME=mailcowdockerized
|
||||
# Switch here between native (compose plugin) and standalone
|
||||
# For more informations take a look at the mailcow docs regarding the configuration options.
|
||||
# Normally this should be untouched but if you decided to use either of those you can switch it manually here.
|
||||
# Please be aware that at least one of those variants should be installed on your machine or mailcow will fail.
|
||||
# Please be aware that at least one of those variants should be installed on your maschine or mailcow will fail.
|
||||
|
||||
DOCKER_COMPOSE_VERSION=${COMPOSE_VERSION}
|
||||
|
||||
@@ -329,14 +328,14 @@ SKIP_CLAMD=${SKIP_CLAMD}
|
||||
|
||||
SKIP_SOGO=n
|
||||
|
||||
# Skip Solr on low-memory systems or if you do not want to store a readable index of your mails in solr-vol-1.
|
||||
# Skip Xapian (FTS) on low-memory systems or if you do not want to store a readable index of your mails in vmail-index-vol-1.
|
||||
|
||||
SKIP_SOLR=${SKIP_SOLR}
|
||||
SKIP_XAPIAN=${SKIP_XAPIAN}
|
||||
|
||||
# Solr heap size in MB, there is no recommendation, please see Solr docs.
|
||||
# Solr is a prone to run OOM and should be monitored. Unmonitored Solr setups are not recommended.
|
||||
# Xapian heap size in MB, there is no recommendation, please see Xapians docs.
|
||||
# Xapian is replacing solr completely. It is supposed to be much more efficient in CPU and RAM consumption.
|
||||
|
||||
SOLR_HEAP=1024
|
||||
XAPIAN_HEAP=1024
|
||||
|
||||
# Allow admins to log into SOGo as email user (without any password)
|
||||
|
||||
|
15
helper-scripts/expiry-dates.sh
Executable file → Normal file
15
helper-scripts/expiry-dates.sh
Executable file → Normal file
@@ -3,11 +3,10 @@
|
||||
[[ -f mailcow.conf ]] && source mailcow.conf
|
||||
[[ -f ../mailcow.conf ]] && source ../mailcow.conf
|
||||
|
||||
POSTFIX=$(echo | openssl s_client -connect ${MAILCOW_HOSTNAME}:${SMTP_PORT} -starttls smtp 2>/dev/null | openssl x509 -inform pem -noout -enddate | cut -d "=" -f 2)
|
||||
DOVECOT=$(echo | openssl s_client -connect ${MAILCOW_HOSTNAME}:${IMAP_PORT} -starttls imap 2>/dev/null | openssl x509 -inform pem -noout -enddate | cut -d "=" -f 2)
|
||||
NGINX=$(echo | openssl s_client -connect ${MAILCOW_HOSTNAME}:${HTTPS_PORT} 2>/dev/null | openssl x509 -inform pem -noout -enddate | cut -d "=" -f 2)
|
||||
|
||||
echo "TLS expiry dates:"
|
||||
echo "Postfix: ${POSTFIX}"
|
||||
echo "Dovecot: ${DOVECOT}"
|
||||
echo "Nginx: ${NGINX}"
|
||||
POSTFIX=$(echo | openssl s_client -connect ${MAILCOW_HOSTNAME}:25 -starttls smtp 2>/dev/null | openssl x509 -inform pem -noout -enddate | cut -d "=" -f 2)
|
||||
DOVECOT=$(echo | openssl s_client -connect ${MAILCOW_HOSTNAME}:143 -starttls imap 2>/dev/null | openssl x509 -inform pem -noout -enddate | cut -d "=" -f 2)
|
||||
NGINX=$(echo | openssl s_client -connect ${MAILCOW_HOSTNAME}:443 2>/dev/null | openssl x509 -inform pem -noout -enddate | cut -d "=" -f 2)
|
||||
echo TLS expiry dates:
|
||||
echo Postfix: ${POSTFIX}
|
||||
echo Dovecot: ${DOVECOT}
|
||||
echo Nginx: ${NGINX}
|
||||
|
@@ -19,7 +19,7 @@ read -r -p "Are you sure you want to reset the mailcow administrator account? [y
|
||||
response=${response,,} # tolower
|
||||
if [[ "$response" =~ ^(yes|y)$ ]]; then
|
||||
echo -e "\nWorking, please wait..."
|
||||
random=$(</dev/urandom tr -dc _A-Z-a-z-0-9 2> /dev/null | head -c${1:-16})
|
||||
random=$(</dev/urandom tr -dc _A-Z-a-z-0-9 | head -c${1:-16})
|
||||
password=$(docker exec -it $(docker ps -qf name=dovecot-mailcow) doveadm pw -s SSHA256 -p ${random} | tr -d '\r')
|
||||
docker exec -it $(docker ps -qf name=mysql-mailcow) mysql -u${DBUSER} -p${DBPASS} ${DBNAME} -e "DELETE FROM admin WHERE username='admin';"
|
||||
docker exec -it $(docker ps -qf name=mysql-mailcow) mysql -u${DBUSER} -p${DBPASS} ${DBNAME} -e "DELETE FROM domain_admins WHERE username='admin';"
|
||||
|
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
# renovate: datasource=github-releases depName=nextcloud/server versioning=semver extractVersion=^v(?<version>.*)$
|
||||
NEXTCLOUD_VERSION=26.0.1
|
||||
NEXTCLOUD_VERSION=25.0.3
|
||||
|
||||
echo -ne "Checking prerequisites..."
|
||||
sleep 1
|
||||
@@ -97,12 +97,8 @@ elif [[ ${NC_UPDATE} == "y" ]]; then
|
||||
echo -e "\033[31mError: Nextcloud occ not found. Is Nextcloud installed?\033[0m"
|
||||
exit 1
|
||||
fi
|
||||
if grep -Pq 'This version of Nextcloud is not compatible with (?:PHP)?(?>=?)(?:PHP)?(?>.+)' <<<$(docker exec -it -u www-data $(docker ps -f name=php-fpm-mailcow -q) bash -c "/web/nextcloud/occ --no-warnings status"); then
|
||||
echo -e "\033[31mError: This version of Nextcloud is not compatible with the current PHP version of php-fpm-mailcow, we'll fix it\033[0m"
|
||||
wget -q https://raw.githubusercontent.com/nextcloud/server/v26.0.0/lib/versioncheck.php -O ./data/web/nextcloud/lib/versioncheck.php
|
||||
echo -e "\e[33mPlease restart the update again.\e[0m"
|
||||
elif ! grep -q 'installed: true' <<<$(docker exec -it -u www-data $(docker ps -f name=php-fpm-mailcow -q) bash -c "/web/nextcloud/occ --no-warnings status"); then
|
||||
echo -e "\033[31mError: Nextcloud seems not to be installed.\033[0m"
|
||||
if ! grep -q 'installed: true' <<<$(docker exec -it -u www-data $(docker ps -f name=php-fpm-mailcow -q) bash -c "/web/nextcloud/occ --no-warnings status"); then
|
||||
echo "Nextcloud seems not to be installed."
|
||||
exit 1
|
||||
else
|
||||
docker exec -it -u www-data $(docker ps -f name=php-fpm-mailcow -q) bash -c "php /web/nextcloud/updater/updater.phar"
|
||||
@@ -126,7 +122,7 @@ elif [[ ${NC_INSTALL} == "y" ]]; then
|
||||
&& chmod +x ./data/web/nextcloud/occ
|
||||
|
||||
echo -e "\033[33mCreating 'nextcloud' database...\033[0m"
|
||||
NC_DBPASS=$(</dev/urandom tr -dc A-Za-z0-9 2> /dev/null | head -c 28)
|
||||
NC_DBPASS=$(</dev/urandom tr -dc A-Za-z0-9 | head -c 28)
|
||||
NC_DBUSER=nextcloud
|
||||
NC_DBNAME=nextcloud
|
||||
|
||||
@@ -142,7 +138,7 @@ elif [[ ${NC_INSTALL} == "y" ]]; then
|
||||
|
||||
echo ""
|
||||
echo -e "\033[33mInstalling Nextcloud...\033[0m"
|
||||
ADMIN_NC_PASS=$(</dev/urandom tr -dc A-Za-z0-9 2> /dev/null | head -c 28)
|
||||
ADMIN_NC_PASS=$(</dev/urandom tr -dc A-Za-z0-9 | head -c 28)
|
||||
|
||||
echo -ne "[1/4] Setting correct permissions for www-data"
|
||||
docker exec -it $(docker ps -f name=php-fpm-mailcow -q) /bin/bash -c "chown -R www-data:www-data /web/nextcloud"
|
||||
|
97
update.sh
97
update.sh
@@ -176,19 +176,18 @@ remove_obsolete_nginx_ports() {
|
||||
}
|
||||
|
||||
detect_docker_compose_command(){
|
||||
if ! [[ "${DOCKER_COMPOSE_VERSION}" =~ ^(native|standalone)$ ]]; then
|
||||
if ! [ "${DOCKER_COMPOSE_VERSION}" == "native" ] && ! [ "${DOCKER_COMPOSE_VERSION}" == "standalone" ]; then
|
||||
if docker compose > /dev/null 2>&1; then
|
||||
if docker compose version --short | grep "2." > /dev/null 2>&1; then
|
||||
DOCKER_COMPOSE_VERSION=native
|
||||
COMPOSE_COMMAND="docker compose"
|
||||
echo -e "\e[31mFound Docker Compose Plugin (native).\e[0m"
|
||||
echo -e "\e[31mSetting the DOCKER_COMPOSE_VERSION Variable to native\e[0m"
|
||||
sed -i 's/^DOCKER_COMPOSE_VERSION=.*/DOCKER_COMPOSE_VERSION=native/' $SCRIPT_DIR/mailcow.conf
|
||||
sleep 2
|
||||
echo -e "\e[33mNotice: You'll have to update this Compose Version via your Package Manager manually!\e[0m"
|
||||
else
|
||||
echo -e "\e[31mCannot find Docker Compose with a Version Higher than 2.X.X.\e[0m"
|
||||
echo -e "\e[31mPlease update/install it manually regarding to this doc site: https://docs.mailcow.email/i_u_m/i_u_m_install/\e[0m"
|
||||
echo -e "\e[31mPlease update/install it manually regarding to this doc site: https://mailcow.github.io/mailcow-dockerized-docs/i_u_m/i_u_m_install/\e[0m"
|
||||
exit 1
|
||||
fi
|
||||
elif docker-compose > /dev/null 2>&1; then
|
||||
@@ -198,60 +197,26 @@ if ! [[ "${DOCKER_COMPOSE_VERSION}" =~ ^(native|standalone)$ ]]; then
|
||||
COMPOSE_COMMAND="docker-compose"
|
||||
echo -e "\e[31mFound Docker Compose Standalone.\e[0m"
|
||||
echo -e "\e[31mSetting the DOCKER_COMPOSE_VERSION Variable to standalone\e[0m"
|
||||
sed -i 's/^DOCKER_COMPOSE_VERSION=.*/DOCKER_COMPOSE_VERSION=standalone/' $SCRIPT_DIR/mailcow.conf
|
||||
sleep 2
|
||||
echo -e "\e[33mNotice: For an automatic update of docker-compose please use the update_compose.sh scripts located at the helper-scripts folder.\e[0m"
|
||||
else
|
||||
echo -e "\e[31mCannot find Docker Compose with a Version Higher than 2.X.X.\e[0m"
|
||||
echo -e "\e[31mPlease update/install regarding to this doc site: https://docs.mailcow.email/i_u_m/i_u_m_install/\e[0m"
|
||||
echo -e "\e[31mPlease update/install regarding to this doc site: https://mailcow.github.io/mailcow-dockerized-docs/i_u_m/i_u_m_install/\e[0m"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
else
|
||||
echo -e "\e[31mCannot find Docker Compose.\e[0m"
|
||||
echo -e "\e[31mPlease install it regarding to this doc site: https://docs.mailcow.email/i_u_m/i_u_m_install/\e[0m"
|
||||
echo -e "\e[31mPlease install it regarding to this doc site: https://mailcow.github.io/mailcow-dockerized-docs/i_u_m/i_u_m_install/\e[0m"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
elif [ "${DOCKER_COMPOSE_VERSION}" == "native" ]; then
|
||||
COMPOSE_COMMAND="docker compose"
|
||||
# Check if Native Compose works and has not been deleted
|
||||
if ! $COMPOSE_COMMAND > /dev/null 2>&1; then
|
||||
# IF it not exists/work anymore try the other command
|
||||
COMPOSE_COMMAND="docker-compose"
|
||||
if ! $COMPOSE_COMMAND > /dev/null 2>&1 || ! $COMPOSE_COMMAND --version | grep "^2." > /dev/null 2>&1; then
|
||||
# IF it cannot find Standalone in > 2.X, then script stops
|
||||
echo -e "\e[31mCannot find Docker Compose or the Version is lower then 2.X.X.\e[0m"
|
||||
echo -e "\e[31mPlease install it regarding to this doc site: https://docs.mailcow.email/i_u_m/i_u_m_install/\e[0m"
|
||||
exit 1
|
||||
fi
|
||||
# If it finds the standalone Plugin it will use this instead and change the mailcow.conf Variable accordingly
|
||||
echo -e "\e[31mFound different Docker Compose Version then declared in mailcow.conf!\e[0m"
|
||||
echo -e "\e[31mSetting the DOCKER_COMPOSE_VERSION Variable from native to standalone\e[0m"
|
||||
sed -i 's/^DOCKER_COMPOSE_VERSION=.*/DOCKER_COMPOSE_VERSION=standalone/' $SCRIPT_DIR/mailcow.conf
|
||||
sleep 2
|
||||
fi
|
||||
|
||||
|
||||
elif [ "${DOCKER_COMPOSE_VERSION}" == "standalone" ]; then
|
||||
COMPOSE_COMMAND="docker-compose"
|
||||
# Check if Standalone Compose works and has not been deleted
|
||||
if ! $COMPOSE_COMMAND > /dev/null 2>&1 && ! $COMPOSE_COMMAND --version > /dev/null 2>&1 | grep "^2." > /dev/null 2>&1; then
|
||||
# IF it not exists/work anymore try the other command
|
||||
COMPOSE_COMMAND="docker compose"
|
||||
if ! $COMPOSE_COMMAND > /dev/null 2>&1; then
|
||||
# IF it cannot find Native in > 2.X, then script stops
|
||||
echo -e "\e[31mCannot find Docker Compose.\e[0m"
|
||||
echo -e "\e[31mPlease install it regarding to this doc site: https://docs.mailcow.email/i_u_m/i_u_m_install/\e[0m"
|
||||
exit 1
|
||||
fi
|
||||
# If it finds the native Plugin it will use this instead and change the mailcow.conf Variable accordingly
|
||||
echo -e "\e[31mFound different Docker Compose Version then declared in mailcow.conf!\e[0m"
|
||||
echo -e "\e[31mSetting the DOCKER_COMPOSE_VERSION Variable from standalone to native\e[0m"
|
||||
sed -i 's/^DOCKER_COMPOSE_VERSION=.*/DOCKER_COMPOSE_VERSION=native/' $SCRIPT_DIR/mailcow.conf
|
||||
sleep 2
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -361,12 +326,8 @@ while (($#)); do
|
||||
echo -e "\e[32mRunning in forced mode...\e[0m"
|
||||
FORCE=y
|
||||
;;
|
||||
-d|--dev)
|
||||
echo -e "\e[32mRunning in Developer mode...\e[0m"
|
||||
DEV=y
|
||||
;;
|
||||
--help|-h)
|
||||
echo './update.sh [-c|--check, --ours, --gc, --nightly, --prefetch, --skip-start, --skip-ping-check, --stable, -f|--force, -d|--dev, -h|--help]
|
||||
echo './update.sh [-c|--check, --ours, --gc, --nightly, --prefetch, --skip-start, --skip-ping-check, --stable, -f|--force, -h|--help]
|
||||
|
||||
-c|--check - Check for updates and exit (exit codes => 0: update available, 3: no updates)
|
||||
--ours - Use merge strategy option "ours" to solve conflicts in favor of non-mailcow code (local changes over remote changes), not recommended!
|
||||
@@ -377,7 +338,6 @@ while (($#)); do
|
||||
--skip-ping-check - Skip ICMP Check to public DNS resolvers (Use it only if you´ve blocked any ICMP Connections to your mailcow machine)
|
||||
--stable - Switch your mailcow updates to the stable (master) branch. Default unless you changed it with --nightly.
|
||||
-f|--force - Force update, do not ask questions
|
||||
-d|--dev - Enables Developer Mode (No Checkout of update.sh for tests)
|
||||
'
|
||||
exit 1
|
||||
esac
|
||||
@@ -428,8 +388,8 @@ CONFIG_ARRAY=(
|
||||
"MAILDIR_GC_TIME"
|
||||
"MAILDIR_SUB"
|
||||
"ACL_ANYONE"
|
||||
"SOLR_HEAP"
|
||||
"SKIP_SOLR"
|
||||
"XAPIAN_HEAP"
|
||||
"SKIP_XAPIAN"
|
||||
"ENABLE_SSL_SNI"
|
||||
"ALLOW_ADMIN_EMAIL_LOGIN"
|
||||
"SKIP_HTTP_VERIFICATION"
|
||||
@@ -550,20 +510,20 @@ for option in ${CONFIG_ARRAY[@]}; do
|
||||
echo '# Otherwise a user might share data with too many other users.' >> mailcow.conf
|
||||
echo 'ACL_ANYONE=disallow' >> mailcow.conf
|
||||
fi
|
||||
elif [[ ${option} == "SOLR_HEAP" ]]; then
|
||||
elif [[ ${option} == "XAPIAN_HEAP" ]]; then
|
||||
if ! grep -q ${option} mailcow.conf; then
|
||||
echo "Adding new option \"${option}\" to mailcow.conf"
|
||||
echo '# Solr heap size, there is no recommendation, please see Solr docs.' >> mailcow.conf
|
||||
echo '# Solr is a prone to run OOM on large systems and should be monitored. Unmonitored Solr setups are not recommended.' >> mailcow.conf
|
||||
echo '# Solr will refuse to start with total system memory below or equal to 2 GB.' >> mailcow.conf
|
||||
echo "SOLR_HEAP=1024" >> mailcow.conf
|
||||
echo "Replacing SOLR_HEAP with \"${option}\" in mailcow.conf"
|
||||
sed -i '/# Solr heap size in MB, there is no recommendation, please see Solr docs./c\# Xapian heap size in MB, there is no recommendation, please see Xapians docs.' mailcow.conf
|
||||
sed -i '/# Solr is a prone to run OOM on large systems and should be monitored. Unmonitored Solr setups are not recommended./c\# Xapian is replacing solr completely. It is supposed to be much more efficient in CPU and RAM consumption.' mailcow.conf
|
||||
sed -i '/SOLR_HEAP=/c\XAPIAN_HEAP=' mailcow.conf
|
||||
fi
|
||||
elif [[ ${option} == "SKIP_SOLR" ]]; then
|
||||
elif [[ ${option} == "SKIP_XAPIAN" ]]; then
|
||||
if ! grep -q ${option} mailcow.conf; then
|
||||
echo "Adding new option \"${option}\" to mailcow.conf"
|
||||
echo '# Solr is disabled by default after upgrading from non-Solr to Solr-enabled mailcows.' >> mailcow.conf
|
||||
echo '# Disable Solr or if you do not want to store a readable index of your mails in solr-vol-1.' >> mailcow.conf
|
||||
echo "SKIP_SOLR=y" >> mailcow.conf
|
||||
echo "Replacing SKIP_SOLR with \"${option}\" in mailcow.conf"
|
||||
sed -i '/# Skip Solr on low-memory systems or if you do not want to store a readable index of your mails in solr-vol-1./c\# Skip Xapian (FTS) on low-memory systems or if you do not want to store a readable index of your mails in vmail-index-vol-1.' mailcow.conf
|
||||
sed -i '/SKIP_SOLR=/c\SKIP_XAPIAN=' mailcow.conf
|
||||
echo "Removing Solr-Port Binding from mailcow.conf"
|
||||
sed -i '/SOLR_PORT=/d' mailcow.conf
|
||||
fi
|
||||
elif [[ ${option} == "ENABLE_SSL_SNI" ]]; then
|
||||
if ! grep -q ${option} mailcow.conf; then
|
||||
@@ -637,7 +597,7 @@ for option in ${CONFIG_ARRAY[@]}; do
|
||||
echo "Adding new option \"${option}\" to mailcow.conf"
|
||||
echo '# Password hash algorithm' >> mailcow.conf
|
||||
echo '# Only certain password hash algorithm are supported. For a fully list of supported schemes,' >> mailcow.conf
|
||||
echo '# see https://docs.mailcow.email/models/model-passwd/' >> mailcow.conf
|
||||
echo '# see https://mailcow.github.io/mailcow-dockerized-docs/models/model-passwd/' >> mailcow.conf
|
||||
echo "MAILCOW_PASS_SCHEME=BLF-CRYPT" >> mailcow.conf
|
||||
fi
|
||||
elif [[ ${option} == "ADDITIONAL_SERVER_NAMES" ]]; then
|
||||
@@ -657,7 +617,7 @@ for option in ${CONFIG_ARRAY[@]}; do
|
||||
echo '# Optional: Leave empty for none' >> mailcow.conf
|
||||
echo '# This value is only used on first order!' >> mailcow.conf
|
||||
echo '# Setting it at a later point will require the following steps:' >> mailcow.conf
|
||||
echo '# https://docs.mailcow.email/troubleshooting/debug-reset_tls/' >> mailcow.conf
|
||||
echo '# https://mailcow.github.io/mailcow-dockerized-docs/troubleshooting/debug-reset_tls/' >> mailcow.conf
|
||||
echo 'ACME_CONTACT=' >> mailcow.conf
|
||||
fi
|
||||
elif [[ ${option} == "WEBAUTHN_ONLY_TRUSTED_VENDORS" ]]; then
|
||||
@@ -767,17 +727,15 @@ elif [ $NEW_BRANCH == "nightly" ] && [ $CURRENT_BRANCH != "nightly" ]; then
|
||||
git checkout -f ${BRANCH}
|
||||
fi
|
||||
|
||||
if [ ! $DEV ]; then
|
||||
echo -e "\e[32mChecking for newer update script...\e[0m"
|
||||
SHA1_1=$(sha1sum update.sh)
|
||||
git fetch origin #${BRANCH}
|
||||
git checkout origin/${BRANCH} update.sh
|
||||
SHA1_2=$(sha1sum update.sh)
|
||||
if [[ ${SHA1_1} != ${SHA1_2} ]]; then
|
||||
echo -e "\e[32mChecking for newer update script...\e[0m"
|
||||
SHA1_1=$(sha1sum update.sh)
|
||||
git fetch origin #${BRANCH}
|
||||
git checkout origin/${BRANCH} update.sh
|
||||
SHA1_2=$(sha1sum update.sh)
|
||||
if [[ ${SHA1_1} != ${SHA1_2} ]]; then
|
||||
echo "update.sh changed, please run this script again, exiting."
|
||||
chmod +x update.sh
|
||||
exit 2
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ ! $FORCE ]; then
|
||||
@@ -944,6 +902,9 @@ else
|
||||
echo -e "\e[33mCannot determine current git repository version...\e[0m"
|
||||
fi
|
||||
|
||||
# Set DOCKER_COMPOSE_VERSION
|
||||
sed -i 's/^DOCKER_COMPOSE_VERSION=$/DOCKER_COMPOSE_VERSION='$DOCKER_COMPOSE_VERSION'/g' mailcow.conf
|
||||
|
||||
if [[ ${SKIP_START} == "y" ]]; then
|
||||
echo -e "\e[33mNot starting mailcow, please run \"$COMPOSE_COMMAND up -d --remove-orphans\" to start mailcow.\e[0m"
|
||||
else
|
||||
|
Reference in New Issue
Block a user