diff --git a/.docker/release/Dockerfile b/.docker/release/Dockerfile index 97757bb44..0e6473191 100644 --- a/.docker/release/Dockerfile +++ b/.docker/release/Dockerfile @@ -1,51 +1,192 @@ +# syntax=docker/dockerfile:1 + +FROM alpine:3.24.3 AS builder +RUN apk add --no-cache php85 php85-json php-phar php-zip +RUN apk add --no-cache npm +RUN npm install -g gulp yarn +WORKDIR /source +COPY package.json yarn.lock ./ +RUN yarn install +COPY . . +# Patch release.php with hotfix from: https://github.com/xgbstar1/snappymail-docker/blob/main/Dockerfile, so that release.php doesn't fail with error +RUN sed -i 's_^if.*rename.*snappymail.v.0.0.0.*$_if (!!system("mv snappymail/v/0.0.0 snappymail/v/{$package->version}")) {_' cli/release.php || true +RUN php release.php +RUN set -eux; \ + VERSION=$( ls build/dist/releases/webmail ); \ + ls -al build/dist/releases/webmail/$VERSION/snappymail-$VERSION.tar.gz; \ + mkdir -p /snappymail; \ + tar -zxvf build/dist/releases/webmail/$VERSION/snappymail-$VERSION.tar.gz -C /snappymail; \ + find /snappymail -type d -exec chmod 550 {} \; ; \ + find /snappymail -type f -exec chmod 440 {} \; ; \ + find /snappymail/data -type d -exec chmod 750 {} \; ; \ + # Remove unneeded files + rm -v /snappymail/README.md /snappymail/_include.php + # Inspired by the original Rainloop dockerfile from youtous on GitLab -FROM php:8.1-fpm-bullseye +FROM php:8.5-fpm-alpine AS final -ARG FILES_ZIP - - - -LABEL org.label-schema.description="SnappyMail webmail client image using nginx, php-fpm based on Debian Buster" - -ENV UID=991 GID=991 UPLOAD_MAX_SIZE=25M LOG_TO_STDERR=true MEMORY_LIMIT=128M SECURE_COOKIES=true -ENV fpm.pool.clear_env=false +LABEL org.label-schema.description="SnappyMail webmail client image using nginx, php-fpm on Alpine" # Install dependencies such as nginx -RUN mkdir -p /usr/share/man/man1/ /usr/share/man/man3/ /usr/share/man/man7/ && \ - apt-get update -q --fix-missing && \ - apt-get -y upgrade && \ - apt-get install --no-install-recommends -y \ - apt-transport-https gnupg openssl wget curl ca-certificates nginx supervisor sudo \ - unzip libzip-dev libxml2-dev libldb-dev libldap2-dev \ - sqlite3 libsqlite3-dev libsqlite3-0 libpq-dev postgresql-client mariadb-client logrotate \ - zip mlocate libpcre3-dev libicu-dev \ - build-essential chrpath libssl-dev \ - libxft-dev libfreetype6 libfreetype6-dev \ - libpng-dev libjpeg62-turbo-dev \ - libfontconfig1 libfontconfig1-dev \ - && \ - rm -rf /var/lib/apt/lists/* +RUN apk add --no-cache ca-certificates nginx supervisor bash # Install PHP extensions -RUN php -m && \ - docker-php-ext-configure ldap --with-libdir=lib/$(uname -m)-linux-gnu/ && \ - docker-php-ext-configure intl && \ - docker-php-ext-configure gd --with-freetype --with-jpeg && \ - docker-php-ext-install ldap opcache pdo_mysql pdo_pgsql zip intl gd && \ - php -m +# apcu +RUN set -eux; \ + apk add --no-cache --virtual .build-dependencies $PHPIZE_DEPS; \ + pecl install apcu; \ + docker-php-ext-enable apcu; \ + docker-php-source delete; \ + apk del .build-dependencies; + +# gd +RUN set -eux; \ + apk add --no-cache freetype libjpeg-turbo libpng; \ + apk add --no-cache --virtual .deps freetype-dev libjpeg-turbo-dev libpng-dev; \ + docker-php-ext-configure gd --with-freetype --with-jpeg; \ + docker-php-ext-install gd; \ + apk del .deps + +# gmagick +# RUN set -eux; \ +# apk add --no-cache graphicsmagick libgomp; \ +# apk add --no-cache --virtual .deps graphicsmagick-dev libtool; \ +# apk add --no-cache --virtual .build-dependencies $PHPIZE_DEPS; \ +# pecl install gmagick-2.0.6RC1; \ +# docker-php-ext-enable gmagick; \ +# docker-php-source delete; \ +# apk del .build-dependencies; \ +# apk del .deps + +# gnupg +RUN set -eux; \ + apk add --no-cache gnupg gpgme; \ + apk add --no-cache --virtual .deps gpgme-dev; \ + apk add --no-cache --virtual .build-dependencies $PHPIZE_DEPS; \ + pecl install gnupg; \ + docker-php-ext-enable gnupg; \ + docker-php-source delete; \ + apk del .build-dependencies; \ + apk del .deps + +# imagick +RUN set -eux; \ + apk add --no-cache imagemagick libgomp; \ + apk add --no-cache --virtual .deps imagemagick-dev; \ + apk add --no-cache --virtual .build-dependencies $PHPIZE_DEPS; \ + echo | pecl install imagick; \ + docker-php-ext-enable imagick; \ + docker-php-source delete; \ + apk del .build-dependencies; \ + apk del .deps + +# intl +RUN set -eux; \ + apk add --no-cache icu-libs; \ + apk add --no-cache --virtual .deps icu-dev; \ + docker-php-ext-configure intl; \ + docker-php-ext-install intl; \ + apk del .deps + +# ldap +RUN set -eux; \ + apk add --no-cache libldap; \ + apk add --no-cache --virtual .deps openldap-dev; \ + docker-php-ext-configure ldap; \ + docker-php-ext-install ldap; \ + apk del .deps + +# mysql +RUN docker-php-ext-install pdo_mysql + +# postgres +RUN set -eux; \ + apk add --no-cache postgresql-libs; \ + apk add --no-cache --virtual .deps postgresql-dev; \ + docker-php-ext-install pdo_pgsql; \ + apk del .deps + +# redis +RUN set -eux; \ + apk add --no-cache liblzf zstd-libs; \ + apk add --no-cache --virtual .deps zstd-dev; \ + apk add --no-cache --virtual .build-dependencies $PHPIZE_DEPS; \ + pecl install igbinary; \ + docker-php-ext-enable igbinary; \ + pecl install --configureoptions 'enable-redis-igbinary="yes" enable-redis-lzf="yes" enable-redis-zstd="yes"' redis; \ + docker-php-ext-enable redis; \ + docker-php-source delete; \ + apk del .build-dependencies; \ + apk del .deps + +# sqlite +RUN set -eux; \ + apk add --no-cache sqlite-libs; \ + apk add --no-cache --virtual .deps sqlite-dev; \ + docker-php-ext-install pdo_sqlite; \ + apk del .deps + +# tidy +RUN set -eux; \ + apk add --no-cache tidyhtml; \ + apk add --no-cache --virtual .deps tidyhtml-dev; \ + docker-php-ext-install tidy; \ + apk del .deps + +# uuid +RUN set -eux; \ + apk add --no-cache libuuid; \ + apk add --no-cache --virtual .deps util-linux-dev; \ + apk add --no-cache --virtual .build-dependencies $PHPIZE_DEPS; \ + pecl install uuid; \ + docker-php-ext-enable uuid; \ + docker-php-source delete; \ + apk del .build-dependencies; \ + apk del .deps + +# xxtea - Manually install php8 compatible version from https://github.com/xxtea/xxtea-pecl master branch +RUN set -eux; \ + apk add --no-cache --virtual .build-dependencies $PHPIZE_DEPS; \ + wget -q https://github.com/xxtea/xxtea-pecl/tarball/3f5888a29045e12301254151737c5dab4523a1c1 -O xxtea.tar; \ + echo '9cbfd9c27255767deb26ddedf69e738d401d88ac9762d82c8510f9768842ca18 xxtea.tar' | sha256sum -c -; \ + tar -C /usr/src -xvf xxtea.tar; \ + cd /usr/src/xxtea-xxtea-pecl-3f5888a; \ + phpize; \ + ./configure --with-php-config=/usr/local/bin/php-config --enable-xxtea=yes; \ + make install; \ + docker-php-ext-enable xxtea; \ + cd -; \ + rm -fv xxtea.tar; \ + rm -rfv /usr/src/xxtea*; \ + apk del .build-dependencies; + +# zip +RUN set -eux; \ + apk add --no-cache libzip; \ + apk add --no-cache --virtual .deps libzip-dev; \ + docker-php-ext-install zip; \ + apk del .deps # Install snappymail -WORKDIR /tmp -COPY ${FILES_ZIP} . -RUN mkdir /snappymail && \ - unzip -q ${FILES_ZIP} -d /snappymail && \ - find /snappymail -type d -exec chmod 755 {} \; && \ - find /snappymail -type f -exec chmod 644 {} \; && \ - rm -rf ${FILES_ZIP} +# The 'www-data' user/group in alpine is 82:82. The 'nginx' user/group in alpine is 101:101, and is part of www-data group +COPY --chown=www-data:www-data --from=builder /snappymail /snappymail +# Use a custom snappymail data folder +RUN mv -v /snappymail/data /var/lib/snappymail; +# Setup configs +COPY --chown=root:root .docker/release/files / +RUN set -eux; \ + chown www-data:www-data /snappymail/include.php; \ + chmod 440 /snappymail/include.php; \ + chmod +x /entrypoint.sh; \ + # Disable the built-in php-fpm configs, since we're using our own config + mv -v /usr/local/etc/php-fpm.d/docker.conf /usr/local/etc/php-fpm.d/docker.conf.disabled; \ + mv -v /usr/local/etc/php-fpm.d/www.conf /usr/local/etc/php-fpm.d/www.conf.disabled; \ + mv -v /usr/local/etc/php-fpm.d/zz-docker.conf /usr/local/etc/php-fpm.d/zz-docker.conf.disabled; -# Install other content -COPY files / -RUN chmod +x /entrypoint.sh && chmod +x /logrotate-loop.sh -VOLUME /snappymail/data +USER root +WORKDIR /snappymail +VOLUME /var/lib/snappymail EXPOSE 8888 +EXPOSE 9000 +ENTRYPOINT [] CMD ["/entrypoint.sh"] diff --git a/.docker/release/files/entrypoint.sh b/.docker/release/files/entrypoint.sh old mode 100644 new mode 100755 index eed82bf5b..c0ed7df0c --- a/.docker/release/files/entrypoint.sh +++ b/.docker/release/files/entrypoint.sh @@ -1,23 +1,26 @@ #!/bin/sh +set -eu -# Create not root user -groupadd --gid "$GID" php-cli -f -adduser --uid "$UID" --disabled-password --gid "$GID" --shell /bin/bash --home /home/php-cli php-cli --force --gecos "" +DEBUG=${DEBUG:-} +if [ "$DEBUG" = 'true' ]; then + set -x +fi +UPLOAD_MAX_SIZE=${UPLOAD_MAX_SIZE:-25M} +MEMORY_LIMIT=${MEMORY_LIMIT:-128M} +SECURE_COOKIES=${SECURE_COOKIES:-true} +# Disable listening on ipv6 for ipv4-only environments, or nginx will fail to start +if ! ip a | grep 'inet6 ' > /dev/null; then + echo "[INFO] ipv6 is disabled. Configuring nginx to not listen on ipv6" + sed -i '/listen \[::\]:/d' /etc/nginx/nginx.conf +fi # Set attachment size limit sed -i "s//$UPLOAD_MAX_SIZE/g" /usr/local/etc/php-fpm.d/php-fpm.conf /etc/nginx/nginx.conf sed -i "s//$MEMORY_LIMIT/g" /usr/local/etc/php-fpm.d/php-fpm.conf -# Set log output to STDERR if wanted (LOG_TO_STDERR=true) -if [ "$LOG_TO_STDERR" = true ]; then - echo "[INFO] Logging to stderr activated" - sed -i "s/.*error_log.*$/error_log \/dev\/stderr warn;/" /etc/nginx/nginx.conf - sed -i "s/.*error_log.*$/php_admin_value[error_log] = \/dev\/stderr/" /usr/local/etc/php-fpm.d/php-fpm.conf -fi - # Secure cookies -if [ "${SECURE_COOKIES}" = true ]; then +if [ "${SECURE_COOKIES}" = 'true' ]; then echo "[INFO] Secure cookies activated" { echo 'session.cookie_httponly = On'; @@ -26,43 +29,58 @@ if [ "${SECURE_COOKIES}" = true ]; then } > /usr/local/etc/php/conf.d/cookies.ini; fi -# Copy snappymail default config if absent -SNAPPYMAIL_CONFIG_FILE=/snappymail/data/_data_/_default_/configs/application.ini +echo "[INFO] Snappymail version: $( ls /snappymail/snappymail/v )" + +# Set permissions on snappymail data +echo "[INFO] Setting permissions on /var/lib/snappymail" +chown -R www-data:www-data /var/lib/snappymail/ +chmod 550 /var/lib/snappymail/ +find /var/lib/snappymail/ -type d -exec chmod 750 {} \; + +# Create snappymail default config if absent +SNAPPYMAIL_CONFIG_FILE=/var/lib/snappymail/_data_/_default_/configs/application.ini if [ ! -f "$SNAPPYMAIL_CONFIG_FILE" ]; then - echo "[INFO] Creating default Snappymail configuration" - mkdir -p $(dirname $SNAPPYMAIL_CONFIG_FILE) - cp /usr/local/include/application.ini $SNAPPYMAIL_CONFIG_FILE + echo "[INFO] Creating default Snappymail configuration: $SNAPPYMAIL_CONFIG_FILE" + # Run snappymail and exit. This populates the snappymail data directory and generates the config file + # On error, print php exception and exit + EXITCODE= + su - www-data -s /bin/sh -c 'php /snappymail/index.php' > /tmp/out || EXITCODE=$? + if [ -n "$EXITCODE" ]; then + cat /tmp/out + exit "$EXITCODE" + fi fi +echo "[INFO] Overriding values in snappymail configuration: $SNAPPYMAIL_CONFIG_FILE" # Enable output of snappymail logs -if [ "${LOG_TO_STDERR}" = true ]; then - sed -z 's/\; Enable logging\nenable = Off/\; Enable logging\nenable = On/' -i $SNAPPYMAIL_CONFIG_FILE - sed 's/^filename = .*/filename = "errors.log"/' -i $SNAPPYMAIL_CONFIG_FILE - sed 's/^write_on_error_only = .*/write_on_error_only = Off/' -i $SNAPPYMAIL_CONFIG_FILE - sed 's/^write_on_php_error_only = .*/write_on_php_error_only = On/' -i $SNAPPYMAIL_CONFIG_FILE -else - sed -z 's/\; Enable logging\nenable = On/\; Enable logging\nenable = Off/' -i $SNAPPYMAIL_CONFIG_FILE -fi +sed '/^\; Enable logging/{ +N +s/enable = Off/enable = On/ +}' -i $SNAPPYMAIL_CONFIG_FILE +# Redirect snappymail logs to stderr /stdout +sed 's/^filename = .*/filename = "stderr"/' -i $SNAPPYMAIL_CONFIG_FILE +sed 's/^write_on_error_only = .*/write_on_error_only = Off/' -i $SNAPPYMAIL_CONFIG_FILE +sed 's/^write_on_php_error_only = .*/write_on_php_error_only = On/' -i $SNAPPYMAIL_CONFIG_FILE # Always enable snappymail Auth logging sed 's/^auth_logging = .*/auth_logging = On/' -i $SNAPPYMAIL_CONFIG_FILE sed 's/^auth_logging_filename = .*/auth_logging_filename = "auth.log"/' -i $SNAPPYMAIL_CONFIG_FILE sed 's/^auth_logging_format = .*/auth_logging_format = "[{date:Y-m-d H:i:s}] Auth failed: ip={request:ip} user={imap:login} host={imap:host} port={imap:port}"/' -i $SNAPPYMAIL_CONFIG_FILE -# Redirect snappymail logs to stderr /stdout -mkdir -p /snappymail/data/_data_/_default_/logs/ -# empty logs -cp /dev/null /snappymail/data/_data_/_default_/logs/errors.log -cp /dev/null /snappymail/data/_data_/_default_/logs/auth.log -chown -R php-cli:php-cli /snappymail/data/ +sed 's/^auth_syslog = .*/auth_syslog = Off/' -i $SNAPPYMAIL_CONFIG_FILE -# Fix permissions -chown -R $UID:$GID /snappymail/data /var/log /var/lib/nginx -chmod o+w /dev/stdout -chmod o+w /dev/stderr +( + while ! nc -vz -w 1 127.0.0.1 8888 > /dev/null 2>&1; do echo "[INFO] Checking whether nginx is alive"; sleep 1; done + while ! nc -vz -w 1 127.0.0.1 9000 > /dev/null 2>&1; do echo "[INFO] Checking whether php-fpm is alive"; sleep 1; done + # Create snappymail admin password if absent + SNAPPYMAIL_ADMIN_PASSWORD_FILE=/var/lib/snappymail/_data_/_default_/admin_password.txt + if [ ! -f "$SNAPPYMAIL_ADMIN_PASSWORD_FILE" ]; then + echo "[INFO] Creating Snappymail admin password file: $SNAPPYMAIL_ADMIN_PASSWORD_FILE" + wget -T 1 -qO- 'http://127.0.0.1:8888/?/AdminAppData/0/12345/' > /dev/null + echo "[INFO] Snappymail Admin Panel ready at http://localhost:8888/?admin. Login using password in $SNAPPYMAIL_ADMIN_PASSWORD_FILE" + fi - -# Touch supervisord PID file in order to fix permissions -touch /run/supervisord.pid -chown php-cli:php-cli /run/supervisord.pid + wget -T 1 -qO- 'http://127.0.0.1:8888/' > /dev/null + echo "[INFO] Snappymail ready at http://localhost:8888/" +) & # RUN ! -exec sudo -u php-cli -g php-cli /usr/bin/supervisord -c '/supervisor.conf' --pidfile '/run/supervisord.pid' +exec /usr/bin/supervisord -c /supervisor.conf --pidfile /run/supervisord.pid diff --git a/.docker/release/files/etc/logrotate.d/snappymail b/.docker/release/files/etc/logrotate.d/snappymail deleted file mode 100644 index 701631d98..000000000 --- a/.docker/release/files/etc/logrotate.d/snappymail +++ /dev/null @@ -1,5 +0,0 @@ -/snappymail/data/_data_/_default_/logs/* { - size 10M - rotate 0 - missingok -} \ No newline at end of file diff --git a/.docker/release/files/etc/nginx/nginx.conf b/.docker/release/files/etc/nginx/nginx.conf index 1bb643f23..aff3829cf 100644 --- a/.docker/release/files/etc/nginx/nginx.conf +++ b/.docker/release/files/etc/nginx/nginx.conf @@ -11,7 +11,7 @@ http { default_type application/octet-stream; access_log off; - error_log /tmp/ngx_error.log error; + error_log /dev/stderr error; sendfile on; keepalive_timeout 15; @@ -52,6 +52,8 @@ http { server { listen 8888; + listen [::]:8888; + #listen [::]:8888 ipv6only=off; root /snappymail; index index.php; charset utf-8; @@ -95,7 +97,7 @@ http { fastcgi_param PATH_INFO $fastcgi_path_info; fastcgi_param HTTP_PROXY ""; fastcgi_index index.php; - fastcgi_pass unix:/tmp/php-fpm.sock; + fastcgi_pass 127.0.0.1:9000; fastcgi_intercept_errors on; fastcgi_request_buffering off; fastcgi_param REMOTE_ADDR $http_x_real_ip; diff --git a/.docker/release/files/logrotate-loop.sh b/.docker/release/files/logrotate-loop.sh deleted file mode 100644 index ba1d42469..000000000 --- a/.docker/release/files/logrotate-loop.sh +++ /dev/null @@ -1,113 +0,0 @@ -#!/bin/bash -# ---------------------------------------------------------------------- -# Simple script to invoke logrotate at regular intervals -# ---------------------------------------------------------------------- - -# from https://github.com/misho-kr/docker-appliances/blob/master/nginx-nodejs/logrotate-loop.sh - -LOGROTATE_BIN="logrotate" - -STATE="$HOME/logrotate.state" -CONF="/etc/logrotate.d/snappymail" - -export LOGROTATE_BIN STATE CONF - -RUN_INTERVAL="3600" # every hour - -# helper functions for logging -export FMT="%a %b %d %Y %H:%M:%S GMT%z (%Z)" - -function log_date() { - echo "$(date +"$FMT"): $*" -} - -# ---------------------------------------------------------------------- -# Main loop of the logrotate service: -# -# while True: -# sleep N seconds -# run logrotate -# -# ---------------------------------------------------------------------- - -function logrotate_loop() { - - trap on_terminate TERM INT - - local interval="${1}" - - log_date "====================================================" - log_date - log_date "logrotate service starting (pid=$$)" - log_date "logrotate process will run every ${interval} seconds" - - while true; do - - current_time=$(date "+%s") - next_run_time=$(( current_time + interval )) - - while (( current_time < next_run_time )) - do - logrotate_sleep $(( next_run_time - current_time )) - current_time=$(date "+%s") - done - - logrotate_run - done -} - -# helper function to execute logrotate and pass it the right parameters -function logrotate_run() { - - log_date "logrotate will run now" - ${LOGROTATE_BIN} -s ${STATE} ${CONF} -} - -# ---------------------------------------------------------------------- -# Procedure to idle the execution for a number of seconds -# -# There are two requirements: -# -# - export the PID of the sleep command so that it can be terminated -# in case the logrotate service is being shutdown -# - keep this (bash) process responsive to SIGTERM while in sleep -# mode (normally the signal will be masked and will not be delivered -# until the subprocess completes) -# ---------------------------------------------------------------------- - -proc_sleep_pid="" - -function logrotate_sleep() { - - local sleep_interval=${1} - - log_date "logrotate will sleep for ${sleep_interval} seconds" - - ( exec -a "logrotate: sleep" sleep ${sleep_interval} )& - - proc_sleep_pid=$! - wait ${proc_sleep_pid} -} - -# ---------------------------------------------------------------------- -# Signal handler for logrotate service to make sure the process exits: -# -# - properly by terminating the sleep process that is used to idle -# the service -# - gracefully by writing a message in the log -# ---------------------------------------------------------------------- - -function on_terminate() { - - log_date "logrotate will terminate" - log_date - - kill -TERM ${proc_sleep_pid} - exit 0 -} - -# ---------------------------------------------------------------------- -# main -# ---------------------------------------------------------------------- - -logrotate_loop ${1:-RUN_INTERVAL} diff --git a/.docker/release/files/snappymail/include.php b/.docker/release/files/snappymail/include.php new file mode 100644 index 000000000..53ba30722 --- /dev/null +++ b/.docker/release/files/snappymail/include.php @@ -0,0 +1,3 @@ + diff --git a/.docker/release/files/supervisor.conf b/.docker/release/files/supervisor.conf index da6c6aefe..13a12a290 100644 --- a/.docker/release/files/supervisor.conf +++ b/.docker/release/files/supervisor.conf @@ -1,10 +1,13 @@ [supervisord] nodaemon=true +user=root +logfile=/dev/null +logfile_maxbytes=0 [program:nginx] command=nginx -c /etc/nginx/nginx.conf -g 'daemon off;' process_name=%(program_name)s_%(process_num)02d -user=php-cli +user=root numprocs=1 autostart=true autorestart=false @@ -17,7 +20,7 @@ stderr_logfile_maxbytes=0 [program:php-fpm] command=php-fpm -F process_name=%(program_name)s_%(process_num)02d -user=php-cli +user=root numprocs=1 autostart=true autorestart=false @@ -27,34 +30,11 @@ stdout_logfile_maxbytes=0 stderr_logfile=/dev/stderr stderr_logfile_maxbytes=0 -; reads snappymail logs -[program:snappymail-auth] -command=tail -f /snappymail/data/_data_/_default_/logs/auth.log -stdout_logfile=/dev/stdout -stdout_logfile_maxbytes=0 -stderr_logfile=/dev/stderr -stderr_logfile_maxbytes=0 - -[program:snappymail-errors] -command=tail -f /snappymail/data/_data_/_default_/logs/errors.log -# everything is an error -stdout_logfile=/dev/stderr -stdout_logfile_maxbytes=0 -redirect_stderr=true - -[program:logrotate] -command=/logrotate-loop.sh -autorestart=true -stdout_logfile=/dev/stdout -stdout_logfile_maxbytes=0 -stderr_logfile=/dev/stderr -stderr_logfile_maxbytes=0 - [eventlistener:subprocess-stopped] command=php /listener.php process_name=%(program_name)s_%(process_num)02d -user=php-cli +user=root numprocs=1 events=PROCESS_STATE_EXITED,PROCESS_STATE_STOPPED,PROCESS_STATE_FATAL autostart=true -autorestart=unexpected \ No newline at end of file +autorestart=unexpected diff --git a/.docker/release/files/usr/local/etc/php-fpm.d/php-fpm.conf b/.docker/release/files/usr/local/etc/php-fpm.d/php-fpm.conf index 456fdb798..fbee3d4e0 100644 --- a/.docker/release/files/usr/local/etc/php-fpm.d/php-fpm.conf +++ b/.docker/release/files/usr/local/etc/php-fpm.d/php-fpm.conf @@ -1,15 +1,21 @@ [global] daemonize = no +error_log = /dev/stderr +log_buffering = no [default] -listen = /tmp/php-fpm.sock +listen = 9000 +user = www-data +listen.owner = www-data +listen.group = www-data pm = ondemand pm.max_children = 30 pm.process_idle_timeout = 10s pm.max_requests = 500 catch_workers_output = yes +decorate_workers_output = no chdir = / -php_admin_value[error_log] = /tmp/php_error.log +pm.status_path = /status php_admin_value[log_errors] = On php_admin_value[expose_php] = Off php_admin_value[display_errors] = Off diff --git a/.docker/release/files/usr/local/include/application.ini b/.docker/release/files/usr/local/include/application.ini deleted file mode 100644 index 2a8958eea..000000000 --- a/.docker/release/files/usr/local/include/application.ini +++ /dev/null @@ -1,309 +0,0 @@ -; SnappyMail configuration file -; Please don't add custom parameters here, those will be overwritten - -[webmail] -; Text displayed as page title -title = "SnappyMail Webmail" - -; Text displayed on startup -loading_description = "SnappyMail" -favicon_url = "" -app_path = "" - -; Theme used by default -theme = "Default" - -; Allow theme selection on settings screen -allow_themes = On -allow_user_background = Off - -; Language used by default -language = "en" - -; Admin Panel interface language -language_admin = "en" - -; Allow language selection on settings screen -allow_languages_on_settings = On -allow_additional_accounts = On -allow_additional_identities = On - -; Number of messages displayed on page by default -messages_per_page = 20 - -; Mark message read after N seconds -message_read_delay = 5 - -; File size limit (MB) for file upload on compose screen -; 0 for unlimited. -attachment_size_limit = 2 - -[interface] -show_attachment_thumbnail = On - -[contacts] -; Enable contacts -enable = Off -allow_sync = Off -sync_interval = 20 -type = "sqlite" -pdo_dsn = "host=127.0.0.1;port=3306;dbname=snappymail" -pdo_user = "root" -pdo_password = "" -suggestions_limit = 30 - -[security] -; Enable CSRF protection (http://en.wikipedia.org/wiki/Cross-site_request_forgery) -csrf_protection = On -custom_server_signature = "SnappyMail" -x_xss_protection_header = "1; mode=block" -openpgp = Off - -; Login and password for web admin panel -admin_login = "admin" -admin_password = "" -admin_totp = "" - -; Access settings -allow_admin_panel = On -hide_x_mailer_header = On -admin_panel_host = "" -admin_panel_key = "admin" - -; For example to allow all images use "img-src https:". More info at https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy#directives -content_security_policy = "" - -; Report CSP errors to PHP and/or SnappyMail Log -csp_report = Off - -; A valid cipher method from https://php.net/openssl_get_cipher_methods -encrypt_cipher = "aes-256-cbc-hmac-sha1" - -; Strict, Lax or None -cookie_samesite = "Strict" - -; Additional allowed Sec-Fetch combinations separated by ";". -; For example: -; * Allow iframe on same domain in any mode: dest=iframe,site=same-origin -; * Allow navigate to iframe on same domain: mode=navigate,dest=iframe,site=same-origin -; * Allow navigate to iframe on (sub)domain: mode=navigate,dest=iframe,site=same-site -; * Allow navigate to iframe from any domain: mode=navigate,dest=iframe,site=cross-site -; -; Default is "site=same-origin;site=none" -secfetch_allow = "" - -[admin_panel] -allow_update = Off - -[ssl] -; Require verification of SSL certificate used. -verify_certificate = Off - -; Allow self-signed certificates. Requires verify_certificate. -allow_self_signed = On - -; https://www.openssl.org/docs/man1.1.1/man3/SSL_CTX_set_security_level.html -security_level = 1 - -; Location of Certificate Authority file on local filesystem (/etc/ssl/certs/ca-certificates.crt) -cafile = "" - -; capath must be a correctly hashed certificate directory. (/etc/ssl/certs/) -capath = "" - -; Location of client certificate file (pem format with private key) on local filesystem -local_cert = "" - -; This can help mitigate the CRIME attack vector. -disable_compression = On - -[capa] -quota = On -dangerous_actions = On -message_actions = On -attachments_actions = On - -[login] -; If someone logs in without "@domain.tld", this value will be used -; When this value is HTTP_HOST, the $_SERVER["HTTP_HOST"] value is used. -; When this value is SERVER_NAME, the $_SERVER["SERVER_NAME"] value is used. -; When this value is gethostname, the gethostname() value is used. -; -default_domain = "" - -; Allow language selection on webmail login screen -allow_languages_on_login = On -determine_user_language = On -determine_user_domain = Off -login_lowercase = On - -; This option allows webmail to remember the logged in user -; once they closed the browser window. -; -; Values: -; "DefaultOff" - can be used, disabled by default; -; "DefaultOn" - can be used, enabled by default; -; "Unused" - cannot be used -sign_me_auto = "DefaultOff" - -[plugins] -; Enable plugin support -enable = Off - -; Comma-separated list of enabled plugins -enabled_list = "" - -[defaults] -; Editor mode used by default (Plain, Html) -view_editor_type = "Html" - -; layout: 0 - no preview, 1 - side preview, 2 - bottom preview -view_layout = 1 -view_use_checkboxes = On -autologout = 30 -view_html = On -show_images = Off -contacts_autosave = On -mail_use_threads = Off -allow_draft_autosave = On -mail_reply_same_folder = Off - -[logs] -; Enable logging -enable = Off - -; Path where log files will be stored -path = "" - -; Log messages of set RFC 5424 section 6.2.1 Severity level and higher (0 = highest, 7 = lowest). -; 0 = Emergency -; 1 = Alert -; 2 = Critical -; 3 = Error -; 4 = Warning -; 5 = Notice -; 6 = Informational -; 7 = Debug -level = 4 - -; Required for development purposes only. -; Disabling this option is not recommended. -hide_passwords = On -time_zone = "UTC" - -; Log filename. -; For security reasons, some characters are removed from filename. -; Allows for pattern-based folder creation (see examples below). -; -; Patterns: -; {date:Y-m-d} - Replaced by pattern-based date -; Detailed info: http://www.php.net/manual/en/function.date.php -; {user:email} - Replaced by user's email address -; If user is not logged in, value is set to "unknown" -; {user:login} - Replaced by user's login (the user part of an email) -; If user is not logged in, value is set to "unknown" -; {user:domain} - Replaced by user's domain name (the domain part of an email) -; If user is not logged in, value is set to "unknown" -; {user:uid} - Replaced by user's UID regardless of account currently used -; -; {user:ip} -; {request:ip} - Replaced by user's IP address -; -; Others: -; {imap:login} {imap:host} {imap:port} -; {smtp:login} {smtp:host} {smtp:port} -; -; Examples: -; filename = "log-{date:Y-m-d}.txt" -; filename = "{date:Y-m-d}/{user:domain}/{user:email}_{user:uid}.log" -; filename = "{user:email}-{date:Y-m-d}.txt" -; filename = "syslog" -filename = "log-{date:Y-m-d}.txt" - -; Enable auth logging in a separate file (for fail2ban) -auth_logging = Off -auth_logging_filename = "fail2ban/auth-{date:Y-m-d}.txt" -auth_logging_format = "[{date:Y-m-d H:i:s}] Auth failed: ip={request:ip} user={imap:login} host={imap:host} port={imap:port}" - -; Enable auth logging to syslog for fail2ban -auth_syslog = On - -[debug] -; Special option required for development purposes -enable = Off - -[cache] -; The section controls caching of the entire application. -; -; Enables caching in the system -enable = On - -; Path where cache files will be stored -path = "" - -; Additional caching key. If changed, cache is purged -index = "v1" - -; Can be: files, APCU, memcache, redis (beta) -fast_cache_driver = "files" - -; Additional caching key. If changed, fast cache is purged -fast_cache_index = "v1" - -; Browser-level cache. If enabled, caching is maintainted without using files -http = On - -; Browser-level cache time (seconds, Expires header) -http_expires = 3600 - -; Caching message UIDs when searching and sorting (threading) -server_uids = On - -[imap] -use_force_selection = Off -use_expunge_all_on_delete = Off -message_list_fast_simple_search = On -message_list_permanent_filter = "" -message_all_headers = Off -show_login_alert = On - -[labs] -cache_system_data = On -date_from_headers = On -allow_message_append = Off -login_fault_delay = 1 -log_ajax_response_write_limit = 300 -allow_html_editor_biti_buttons = Off -allow_ctrl_enter_on_compose = On -try_to_detect_hidden_images = Off -use_app_debug_js = Off -use_app_debug_css = Off -smtp_show_server_errors = Off -sieve_auth_plain_initial = On -sieve_allow_fileinto_inbox = Off -mail_func_clear_headers = On -mail_func_additional_parameters = Off -folders_spec_limit = 50 -curl_proxy = "" -curl_proxy_auth = "" -force_https = Off -custom_login_link = "" -custom_logout_link = "" -http_client_ip_check_proxy = Off -fast_cache_memcache_host = "127.0.0.1" -fast_cache_memcache_port = 11211 -fast_cache_redis_host = "127.0.0.1" -fast_cache_redis_port = 6379 -use_local_proxy_for_external_images = On -image_exif_auto_rotate = Off -cookie_default_path = "" -cookie_default_secure = Off -check_new_messages = On -replace_env_in_configuration = "" -boundary_prefix = "" -dev_email = "" -dev_password = "" - -[version] -current = "2.24.5" -saved = "Sun, 18 Dec 2022 22:10:48 +0000" diff --git a/.docker/release/test/build_and_test.sh b/.docker/release/test/build_and_test.sh new file mode 100755 index 000000000..f332ad2c2 --- /dev/null +++ b/.docker/release/test/build_and_test.sh @@ -0,0 +1,7 @@ +#!/bin/sh +# This script uses docker buildx to build a docker image, and loads it into the docker daemon. Then it executes ./test.sh to test the docker image +# It is useful for testing release builds in development +set -eu +IMAGE=snappymail/snappymail:test +DOCKER_BUILDX=1 docker build -t "$IMAGE" -f .docker/release/Dockerfile . +.docker/release/test/test.sh "$IMAGE" diff --git a/.docker/release/test/config.yaml b/.docker/release/test/config.yaml new file mode 100644 index 000000000..47cf00ea9 --- /dev/null +++ b/.docker/release/test/config.yaml @@ -0,0 +1,29 @@ +# See: https://github.com/GoogleContainerTools/container-structure-test +# See: https://github.com/GoogleContainerTools/container-structure-test/issues/78 +schemaVersion: 2.0.0 +commandTests: + - name: Integration test + command: /bin/sh + args: + - -c + - | + set -eux + DEBUG=true /entrypoint.sh > /tmp/test 2>&1 & + sleep 5 + cat /tmp/test + pidof supervisord + pidof nginx + pidof php-fpm + ls -al /var/lib/snappymail/_data_/_default_/configs/application.ini + ls -al /var/lib/snappymail/_data_/_default_/admin_password.txt + nc -vz 127.0.0.1 8888 + nc -vz 127.0.0.1 9000 + wget -S -T 3 -O /dev/null http://127.0.0.1:8888 + kill `pidof supervisord` +metadataTest: + exposedPorts: ["8888", "9000"] + volumes: ["/var/lib/snappymail"] + entrypoint: [] + cmd: ["/entrypoint.sh"] + workdir: /snappymail + user: root diff --git a/.docker/release/test/test.sh b/.docker/release/test/test.sh new file mode 100755 index 000000000..1981cb358 --- /dev/null +++ b/.docker/release/test/test.sh @@ -0,0 +1,10 @@ +#!/bin/sh +# This script tests a given docker image using https://github.com/GoogleContainerTools/container-structure-test +set -eu +SCRIPT_DIR=$( cd "$(dirname "$0")" && pwd ) +IMAGE=${1:-} +echo "Testing image: $IMAGE" +docker run --rm -i \ + -v /var/run/docker.sock:/var/run/docker.sock:ro \ + -v "$SCRIPT_DIR/config.yaml:/config.yaml:ro" \ + gcr.io/gcp-runtimes/container-structure-test:latest test --image "$IMAGE" --config config.yaml diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 000000000..16ef81459 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,2 @@ +/.git +/node_modules diff --git a/.eslintrc.js b/.eslintrc.js index 06370b344..e22cb986d 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -3,7 +3,7 @@ module.exports = { // extends: ['eslint:recommended', 'plugin:prettier/recommended'], extends: ['eslint:recommended'], parserOptions: { - ecmaVersion: 6, + ecmaVersion: 11, sourceType: 'module' }, env: { @@ -35,10 +35,17 @@ module.exports = { // vendors/bootstrap/bootstrap.native.js 'BSN': "readonly", // Mailvelope - 'mailvelope': "readonly" + 'mailvelope': "readonly", + // Punycode + 'IDN': "readonly", + // Turndown + 'TurndownService': "readonly", + // Marked + 'marked': "readonly" }, // http://eslint.org/docs/rules/ rules: { + 'no-cond-assign': 0, // plugins 'no-mixed-spaces-and-tabs': 'off', 'max-len': [ diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index fc1bece3e..b37d3418e 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1,2 +1,2 @@ -community_bridge: SnappyMail +github: the-djmaze custom: ["https://www.paypal.me/thedjmaze", "https://snappymail.eu"] diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 2f48abb98..998692964 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -28,9 +28,11 @@ If applicable, add screenshots to help explain your problem. - IMAP daemon: [e.g. courier, dovecot] - PHP version: - SnappyMail Version: +- Mode: [e.g. standalone, nextcloud, cyberpanel, docker] -**[Debug/logging information](https://github.com/the-djmaze/snappymail/wiki/FAQ#how-do-i-enable-logging)** -Place them here (few lines) or as attachments (many lines) +**Debug/logging information** +[Read here how to log](https://github.com/the-djmaze/snappymail/wiki/FAQ#how-do-i-enable-logging) +- [ ] I've placed them here (few lines) or as attachments (many lines) **Additional context** Add any other context about the problem here. diff --git a/.github/workflows/docker-pr.yml b/.github/workflows/docker-pr.yml new file mode 100644 index 000000000..af069cdf6 --- /dev/null +++ b/.github/workflows/docker-pr.yml @@ -0,0 +1,93 @@ +name: docker-pr + +on: + pull_request: + branches: + - master + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + + # This step generates the docker tags + - name: Docker meta + id: meta + uses: docker/metadata-action@v4 + env: + # This env var ensures {{sha}} is a real commit SHA for type=ref,event=pr + DOCKER_METADATA_PR_HEAD_SHA: 'true' + with: + images: | + djmaze/snappymail + ghcr.io/${{ github.repository }} + # type=ref,event=pr generates tag(s) on PRs only. E.g. 'pr-123', 'pr-123-abc0123' + tags: | + type=ref,event=pr + type=ref,suffix=-{{sha}},event=pr + # The rest of the org.opencontainers.image.xxx labels are dynamically generated + labels: | + org.opencontainers.image.description=SnappyMail + org.opencontainers.image.licenses=AGPLv3 + + # See: https://github.com/docker/build-push-action/blob/v2.6.1/docs/advanced/cache.md#github-cache + - name: Set up QEMU + uses: docker/setup-qemu-action@v2 + + - name: Set up Docker Buildx + id: buildx + uses: docker/setup-buildx-action@v2 + + - name: Cache Docker layers + uses: actions/cache@v3 + with: + path: /tmp/.buildx-cache + key: ${{ runner.os }}-buildx-${{ github.sha }} + restore-keys: | + ${{ runner.os }}-buildx- + + # See: https://github.com/docker/buildx/issues/59 + - name: Build + id: build + uses: docker/build-push-action@v3 + with: + context: '.' + file: ./.docker/release/Dockerfile + platforms: linux/amd64 + push: false + load: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=local,src=/tmp/.buildx-cache + cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max + + - name: Docker images + run: | + docker images + + - name: Test + run: | + TAG=$( echo "${{ steps.meta.outputs.tags }}" | head -n1 ) + .docker/release/test/test.sh "$TAG" + + - name: Build all archs + uses: docker/build-push-action@v3 + with: + context: '.' + file: ./.docker/release/Dockerfile + platforms: linux/386,linux/amd64,linux/arm64 + push: false + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=local,src=/tmp/.buildx-cache + cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max + + # Temp fix + # https://github.com/docker/build-push-action/issues/252 + # https://github.com/moby/buildkit/issues/1896 + - name: Move cache + run: | + rm -rf /tmp/.buildx-cache + mv /tmp/.buildx-cache-new /tmp/.buildx-cache diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml new file mode 100644 index 000000000..b957e2fc8 --- /dev/null +++ b/.github/workflows/docker.yml @@ -0,0 +1,117 @@ +name: docker + +on: + push: + tags: + - 'v2.*' + +# This is needed to push to GitHub Container Registry. See https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-container-registry +permissions: + contents: read + packages: write + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + + # This step generates the docker tags + - name: Docker meta + id: meta + uses: docker/metadata-action@v4 + env: + # This env var ensures {{sha}} is a real commit SHA for type=ref,event=pr + DOCKER_METADATA_PR_HEAD_SHA: 'true' + with: + images: | + djmaze/snappymail + ghcr.io/${{ github.repository }} + # type=ref,event=branch generates tag(s) on branch only. E.g. 'master', 'master-abc0123' + # type=ref,event=tag generates tag(s) on tags only. E.g. 'v0.0.0', 'v0.0.0-abc0123', and 'latest' + tags: | + type=ref,event=branch + type=ref,event=tag + # The rest of the org.opencontainers.image.xxx labels are dynamically generated + labels: | + org.opencontainers.image.description=SnappyMail + org.opencontainers.image.licenses=AGPLv3 + + # See: https://github.com/docker/build-push-action/blob/v2.6.1/docs/advanced/cache.md#github-cache + - name: Set up QEMU + uses: docker/setup-qemu-action@v2 + + - name: Set up Docker Buildx + id: buildx + uses: docker/setup-buildx-action@v2 + + - name: Cache Docker layers + uses: actions/cache@v3 + with: + path: /tmp/.buildx-cache + key: ${{ runner.os }}-buildx-${{ github.sha }} + restore-keys: | + ${{ runner.os }}-buildx- + + - name: Login to Docker Hub registry + if: startsWith(github.ref, 'refs/tags/') # Login only on tags + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Login to GitHub Container Registry + if: startsWith(github.ref, 'refs/tags/') # Login only on tags + uses: docker/login-action@v2 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + # See: https://github.com/docker/buildx/issues/59 + - name: Build + id: build + uses: docker/build-push-action@v3 + with: + context: '.' + file: ./.docker/release/Dockerfile + platforms: linux/amd64 + push: false + load: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=local,src=/tmp/.buildx-cache + cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max + + - name: Docker images + run: | + docker images + + - name: Test + run: | + TAG=$( echo "${{ steps.meta.outputs.tags }}" | head -n1 ) + .docker/release/test/test.sh "$TAG" + + - name: Build and push + id: build-and-push + uses: docker/build-push-action@v3 + with: + context: '.' + file: ./.docker/release/Dockerfile + # TODO: Add more arches? + # platforms: linux/386,linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64,linux/s390x + platforms: linux/386,linux/amd64,linux/arm64 + push: ${{ startsWith(github.ref, 'refs/tags/') }} # Push only on tags + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=local,src=/tmp/.buildx-cache + cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max + + # Temp fix + # https://github.com/docker/build-push-action/issues/252 + # https://github.com/moby/buildkit/issues/1896 + - name: Move cache + run: | + rm -rf /tmp/.buildx-cache + mv /tmp/.buildx-cache-new /tmp/.buildx-cache diff --git a/.gitignore b/.gitignore index 46428042c..5f49d65d5 100644 --- a/.gitignore +++ b/.gitignore @@ -17,6 +17,7 @@ /data /MULTIPLY /include.php +/issues .idea/ .env /test @@ -24,6 +25,8 @@ /vendors/knockout/spec /vendors/openpgp-5 !/vendors/openpgp-5/dist +/vendors/squire2 +!/vendors/squire2/dist /vendors/vanillaqr.js/ /integrations/nextcloud/rainloop /integrations/owncloud/rainloop diff --git a/.gitmodules b/.gitmodules index cfb771834..ccf1009a6 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,7 @@ [submodule "vendors/openpgp-5"] path = vendors/openpgp-5 url = git@github.com:the-djmaze/openpgpjs.git +[submodule "vendors/squire2"] + path = vendors/squire2 + url = git@github.com:the-djmaze/Squire.git + branch = snappymail diff --git a/.htaccess b/.htaccess index 449dcc730..71041371a 100644 --- a/.htaccess +++ b/.htaccess @@ -1,7 +1,15 @@ + + AcceptPathInfo On + + RewriteEngine On # Redirect cPanel RewriteRule cpsess.* https://%{HTTP_HOST}/ [L,R=301] + + RewriteCond %{REQUEST_FILENAME} !-f + RewriteCond %{REQUEST_FILENAME} !-d + RewriteRule ^(.+)$ index.php/$1 [L,QSA] @@ -26,7 +34,6 @@ # Header set Strict-Transport-Security "max-age=31536000" Header set imagetoolbar "no" # Header set X-Content-Type-Options "nosniff" -# Header set X-Frame-Options "DENY" # Header set X-XSS-Protection "1; mode=block" Header set Service-Worker-Allowed "/" diff --git a/CHANGELOG.md b/CHANGELOG.md index 2cd8494e0..d31a1b771 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,43 +1,1638 @@ +## 2.38.2 – 2024-10-09 +### Fixed +- error '$index is not defined' in Settings > Accounts + [#1797](https://github.com/the-djmaze/snappymail/issues/1797) + + +## 2.38.1 – 2024-10-08 + +### Added +- Admin - Extensions search filter +- Options to unset current font family and size + [#1726](https://github.com/the-djmaze/snappymail/issues/1726) +- Option to allow insecure cryptkey + [#1746](https://github.com/the-djmaze/snappymail/issues/1746) +- Save vCard FN property + [#1761](https://github.com/the-djmaze/snappymail/issues/1761) +- Docker Nginx should listen on IPv6 addresses in addition to IPv4 + [#1770](https://github.com/the-djmaze/snappymail/issues/1770) +- Full-screen Message View on Double-Click + [#1787](https://github.com/the-djmaze/snappymail/issues/1787) + +### Changed +- Use the custom Squire as submodule vendors/squire2 +- Disallow noembed and noframes HTML elements +- Keep 1 space between HTML elements in compressed templates +- Squire: sanitizeToDOMFragment now uses cleanHTML() +- Squire: improved handling of BR elements + [#1389](https://github.com/the-djmaze/snappymail/issues/1389) +- Nextcloud border-radius by @gnilebein + [#1790](https://github.com/the-djmaze/snappymail/pull/1790) +- Compose window sentFolder handling for + [#1793](https://github.com/the-djmaze/snappymail/pull/1793) +- Update Portuguese by @ner00 +- Update Polish by @tinola +- Update French by @hguilbert +- Update Portuguese (Brazil) by @mstolf + +### Fixed +- Composer dialog scroll got broken in v2.28 +- Composer dialog "from" triangle button wrong position due to font changes +- Admin - Config `search` should be ko.observable() not ko.observableArray() +- Squire: paste images + [#1389](https://github.com/the-djmaze/snappymail/issues/1389) +- Domain whitelist failures on login + [#1706](https://github.com/the-djmaze/snappymail/issues/1706) +- Sieve parse errors +- Sieve support `index` was not optional for + [#1709](https://github.com/the-djmaze/snappymail/issues/1709) +- Pagination problem for large mailbox after 2.36.1 + [#1716](https://github.com/the-djmaze/snappymail/issues/1716) +- Undefined constant "LOG_ERROR" + [#1754](https://github.com/the-djmaze/snappymail/issues/1754) +- Search Filter Capital "B" not working + [#1780](https://github.com/the-djmaze/snappymail/issues/1780) +- PHP 8.4: Implicitly nullable parameter declarations deprecated + + +## 2.38.0 – 2024-09-16 + +### Added +- Remove `tel:` links when converting HTML to plain + [#1724](https://github.com/the-djmaze/snappymail/issues/1724) +- Convert HTML to Markdown instead of plain, by using [Turndown](https://github.com/mixmark-io/turndown) + [#1604](https://github.com/the-djmaze/snappymail/issues/1604) +- Check HTMLInputElement.validity() for + [#1733](https://github.com/the-djmaze/snappymail/issues/1733) + +### Changed +- Use a modified [Squire 2.3.2](https://github.com/the-djmaze/Squire/commits/snappymail/) +- cleanHtml use allowedTags instead of disallowedTags and improved CSS handling +- Update Portuguese by @ner00 + +### Fixed +- mXSS exploit found by SonarSource + [CVE-2024-45800](https://github.com/the-djmaze/snappymail/security/advisories/GHSA-2rq7-79vp-ffxm) +- Call to a member function Email() on null + [#1706](https://github.com/the-djmaze/snappymail/issues/1706) +- IMAP capabilities via IMAP Proxy + [#1725](https://github.com/the-djmaze/snappymail/issues/1725) +- Messages on page setting is not validated against 999 max + [#1733](https://github.com/the-djmaze/snappymail/issues/1733) + + +## 2.37.3 – 2024-08-27 + +### Added +- Mark images with width=1 as tracking pixel +- Show warning in Admin -> About when PHP runs in 32bit +- Edit ACL rules + [#157](https://github.com/the-djmaze/snappymail/issues/157) +- Show GnuPG version for + [#1560](https://github.com/the-djmaze/snappymail/issues/1560) +- Make sure only scalar values are allowed in $_ENV for + [#1560](https://github.com/the-djmaze/snappymail/issues/1560) +- Change minimum new mail check interval + [#1678](https://github.com/the-djmaze/snappymail/issues/1678) +- Sieve editor does not support "index" extension + [#1709](https://github.com/the-djmaze/snappymail/issues/1709) + +### Changed +- Improved domain autoconfig interaction +- MS autodiscover priorities DNS over subdomain +- Simplify sieve scripts list + [#1675](https://github.com/the-djmaze/snappymail/issues/1675) +- Handling of (token) errors due to + [#1706](https://github.com/the-djmaze/snappymail/issues/1706) +- Sabre/Xml to v4.0.5 +- Update Chinese by @Artoria2e5 +- Update French by @hguilbert + +### Fixed +- Thread sorting visible after disabling the imap capability + [#1574](https://github.com/the-djmaze/snappymail/issues/1574) +- Creating new message impossible as long as a draft exists? + [#1710](https://github.com/the-djmaze/snappymail/issues/1710) +- InvalidToken error at login + [#1706](https://github.com/the-djmaze/snappymail/issues/1706) + +### Nextcloud +- Force Nextcloud personal language by default + [#1428](https://github.com/the-djmaze/snappymail/issues/1428) + + +## 2.37.2 – 2024-08-13 + +### Added +- Validate Fetch JSON response + +### Fixed +- PATH_INFO bug due to Office365 OAuth login +- Prevent logout loop on error + +### Nextcloud +- Failed loading due to Office365 OAuth2 attempt + [#1703](https://github.com/the-djmaze/snappymail/issues/1703) + + +## 2.37.1 – 2024-08-12 + +### Fixed +- Gulp v5 broke the fonts + +### Nextcloud +- Support v30 + + +## 2.37.0 – 2024-08-12 + +### Added +- JavaScript event `rl-vm-visible` +- Detailed error message on account switch failure for + [#1594](https://github.com/the-djmaze/snappymail/issues/1594) +- Workarounds for Microsoft OAuth2 (currently requires Apache AcceptPathInfo) + [#1645](https://github.com/the-djmaze/snappymail/issues/1645) +- Support "mark for deletion" + [#1657](https://github.com/the-djmaze/snappymail/issues/1657) by @smsoft-ru +- Invoke "Update Identity" pop up right after login (when not initialized) + [#1689](https://github.com/the-djmaze/snappymail/issues/1689) +- Keyboard shortcut for "Swap default (background) color" + [#1690](https://github.com/the-djmaze/snappymail/issues/1690) + +### Changed +- Updated gulp to v5 +- Replaced vulnerable gulp-header with gulp-append-prepend +- Removed abandoned vulnerable rollup-plugin-html +- Align save button in admin security settings +- Made registerProtocolHandler('mailto') optional by activating at Settings -> General +- Improved InvalidToken handling for + [#1653](https://github.com/the-djmaze/snappymail/issues/1653) +- Cleanup localizations +- Update French by @hguilbert +- Update German by @tkasch +- Update Polish by @tinola +- Update Portuguese by @ner00 + +### Fixed +- prevent multiple afterShow() and afterHide() due to `transitionend` on multiple CSS properties +- Attempt to read property "smimeSigned" on null +- Refreshing mail list doesn't update current message + [#1654](https://github.com/the-djmaze/snappymail/issues/1654) +- Deletion of CACHE folder causing error + [#1660](https://github.com/the-djmaze/snappymail/issues/1660) +- Multiple line breaks are not displayed + [#1666](https://github.com/the-djmaze/snappymail/issues/1666) +- RainLoop\Exceptions\ClientException::__construct(): Argument #2 ($oPrevious) must be of type ?Throwable, string given + [#1686](https://github.com/the-djmaze/snappymail/issues/1686) +- SpamAssassin Division by zero + [#1694](https://github.com/the-djmaze/snappymail/issues/1694) +- Failed to parse RFC 2822 date '6 Jul 2024 16:42:09 +0200' + [#1694](https://github.com/the-djmaze/snappymail/issues/1694) +- Fix capabilities when THREAD is disabled + [#1698](https://github.com/the-djmaze/snappymail/pull/1698) by @akhil1508 + +### Nextcloud +- Failed loading due to incorrect `app_path` +- Bugfix language detection +- Allow multi-account in nc with oauth login + [#1699](https://github.com/the-djmaze/snappymail/pull/1699) by @akhil1508 + + +## 2.36.4 – 2024-06-25 + +### Added +- Customize private key passphrase expiration interval + [#1545](https://github.com/the-djmaze/snappymail/discussions/1545) +- AdvancedSearch support for filtering mails before a given date + [#1606](https://github.com/the-djmaze/snappymail/pull/1606) by @codiflow +- Control valid spam and virus headers + [#1607](https://github.com/the-djmaze/snappymail/issues/1607) +- Remember S/MIME private Key without function + [#1611](https://github.com/the-djmaze/snappymail/issues/1611) +- Resize compose dialog +- Magnetic theme + [#1637](https://github.com/the-djmaze/snappymail/pull/1637) by @TheCuteFoxxy + +### Changed +- Improved signing messages by allowing to choose between the options +- Improved language detection code +- More detailed Decrypt errors +- Update French by @hguilbert +- Update Polish by @tinola +- Update Portuguese by @ner00 +- Update Spanish by @huloza + +### Fixed +- Default language error +- Undefined $sEmail in DoAdminDomainMatch +- Handling Autocrypt header failed on `=` + [#1608](https://github.com/the-djmaze/snappymail/issues/1608) +- Blank lines are inserted when editing draft + [#1609](https://github.com/the-djmaze/snappymail/issues/1609) +- Workaround Cyrus MAILBOXID bug (disable OBJECTID capability by default due to impact) + [#1640](https://github.com/the-djmaze/snappymail/issues/1640) +- Workaround HTML with multiple body elements or MIME with multiple text/html + [#1641](https://github.com/the-djmaze/snappymail/issues/1641) + +### Nextcloud +- OIDC stay logged in + [#1620](https://github.com/the-djmaze/snappymail/pull/1620) by @avinash-0007 + + +## 2.36.3 – 2024-05-27 + +### Changed +- UserAuth prevent plugin errors (like the Nextcloud plugin did) + +### Fixed +- Undefined variable $aTokenData + [#1567](https://github.com/the-djmaze/snappymail/issues/1567) + + +## 2.36.2 – 2024-05-26 + +### Added +- "copy to" action in menu's for + [#1559](https://github.com/the-djmaze/snappymail/issues/1559) +- Log signal info for + [#1569](https://github.com/the-djmaze/snappymail/issues/1569) +- OpenPGP.js automatically import backup keys from server + +### Changed +- Improved "remember me" cookie handling +- Update Basque by @Thadah +- Update Portuguese by @ner00 + +### Fixed +- "Account already exists" + [#1561](https://github.com/the-djmaze/snappymail/issues/1561) +- Properly escape path separator in tar.php file list regex + [#1562](https://github.com/the-djmaze/snappymail/pull/1562) by @sevmonster +- Prevent mkdir() error + [#1565](https://github.com/the-djmaze/snappymail/issues/1565) +- SCRAM Exception when trying to log in to SMTP + [#1575](https://github.com/the-djmaze/snappymail/issues/1575) +- Error when redirected back to instance after Gmail OAuth + [#1580](https://github.com/the-djmaze/snappymail/issues/1580) +- Uncaught TypeError: hasPublicKeyForEmails(...).then is not a function + [#1589](https://github.com/the-djmaze/snappymail/issues/1589) +- Undefined variable $sFilename +- GPG/PGP exec() return false handling + +### Nextcloud +- OIDC login active again + [#1572](https://github.com/the-djmaze/snappymail/pull/1572) by @avinash-0007 + + +## 2.36.1 – 2024-04-23 + +### Added +- Autoconfig detect through DNS SRV (RFC 6186 & 8314) and disable MX +- Have I Been Pwned class to check breached passwords and email addresses +- Handle RFC 5987 in Content-Disposition header +- Ignore text/x-amp-html +- Show SMTP error to user + [#1521](https://github.com/the-djmaze/snappymail/issues/1521) +- OAuth2 for login using gmail (and others) + +### Changed +- logMask all AUTHENTICATE requests +- ErrorTip use white-space: pre +- Simplify LoginProcess handling +- ES2020 everywhere (require Safari 13.1) +- Modified Squire to be more in line with v2.2.8 +- CSS set min-width for .attachmentParent and .flagParent to line them up +- cPanel use extension login-cpanel instead of login-remote +- Improved login credentials handling +- Speedup Knockout a bit and removed `with($context)` scope +- Update Belarusian by @spoooyders +- Update Chinese by @mayswind +- Update French by @hguilbert +- Update Polish by @tinola +- Update Portuguese by @ner00 + +### Fixed +- Content encoding and type detection in JavaScript could fail due to case-sensitivity. +- Extensions set logger failed +- GnuPG check open_basedir and if shell_exec is disabled + [#1385](https://github.com/the-djmaze/snappymail/issues/1385) + [#1496](https://github.com/the-djmaze/snappymail/issues/1496) + [#1555](https://github.com/the-djmaze/snappymail/issues/1555) +- Hide pagination when search result has no messages +- Prevent mbstring error before setup.php +- Prevent MessagesPerPage Infinity + [#1540](https://github.com/the-djmaze/snappymail/issues/1540) +- Reseal CryptKey failed + [#1543](https://github.com/the-djmaze/snappymail/issues/1543) + +### Nextcloud +- Add an occ command to set up the login settings + [#1552](https://github.com/the-djmaze/snappymail/issues/1552) + + +## 2.36.0 – 2024-03-18 + +### Added +- Allow setting the supported THREAD algorithm +- Icon to system folders +- Remove remembered password after 15 minutes of inactivity + [#1142](https://github.com/the-djmaze/snappymail/issues/1142) +- Swap background and text color for unreadable text on dark background + [#1486](https://github.com/the-djmaze/snappymail/issues/1486) +- Generate TOTP code at ?Admin -> Security + [#1501](https://github.com/the-djmaze/snappymail/issues/1501) +- Button to change S/MIME private key passphrase + [#1505](https://github.com/the-djmaze/snappymail/issues/1505) +- Belarusian + [#1512](https://github.com/the-djmaze/snappymail/pull/1512) by @spoooyders +- Log some domain idn_to_ascii issues + [#1513](https://github.com/the-djmaze/snappymail/issues/1513) + +### Changed +- On folder/mailbox rename, also rename all children instead of reloading all +- Seal MainAccount CryptKey and on error ask old login passphrase to reseal key. +- Moved cache drivers outside core into extensions +- Sieve always allow fileinto INBOX + [#1510](https://github.com/the-djmaze/snappymail/issues/1510) +- Moved application.ini `sieve_auth_plain_initial` to per domain config +- Languages use rfc5646, by using the shortest ISO 639 code by default +- Update French by @hguilbert +- Update Portuguese by @ner00 + +### Fixed +- On folder/mailbox rename, the old fullName must be removed from cache +- On folder/mailbox rename, the checkable option was not renamed +- Sort accounts drag & drop +- S/MIME encrypted and opaque signed not visible + [#1450](https://github.com/the-djmaze/snappymail/issues/1450) +- Wrong last UID of thread + [#1507](https://github.com/the-djmaze/snappymail/issues/1507) +- Creation of dynamic property SnappyMail\DAV\Client::$HTTP + [#1509](https://github.com/the-djmaze/snappymail/issues/1509) +- "Download as ZIP" fails for messages + [#1514](https://github.com/the-djmaze/snappymail/issues/1514) +- SMTP "Authentication failed" when IMAP uses `shortLogin` and SMTP not + [#1517](https://github.com/the-djmaze/snappymail/issues/1517) + + +## 2.35.4 – 2024-03-16 + +### Added +- \SnappyMail\IDN::toAscii() + +### Changed +- OpenPGP.js to v5.11.1 +- punycode.js lowercase domain names +- application.ini `login_lowercase` removed and now configurable per domain JSON `lowerLogin` +- Update Portuguese by @ner00 + +### Fixed +- Raise JS TypeEroor "toLowerCase" after update + [#1491](https://github.com/the-djmaze/snappymail/issues/1491) +- Call to undefined function shell_exec + [#1496](https://github.com/the-djmaze/snappymail/issues/1496) +- Download attachments as ZIP doesn't work for PGP encrypted mail + [#1499](https://github.com/the-djmaze/snappymail/issues/1499) +- Importing or downloading a PGP public key attachment from a PGP encrypted message doesn't work + [#1500](https://github.com/the-djmaze/snappymail/issues/1500) +- VCard PHP Notice: Undefined index: ENCODING + +### Nextcloud +- Changed stored password handling +- Can't login from nextcloud with 2.35.3 bug Nextcloud + [#1490](https://github.com/the-djmaze/snappymail/issues/1490) + + +## 2.35.3 – 2024-03-12 + +### Added +- GnuPG can be disabled +- Missing strings for localization inside identity popup (Cryptography > S/MIME) + [#1458](https://github.com/the-djmaze/snappymail/issues/1458) +- Automatically verify PGP and S/MIME signed messages +- TNEFDecoder for + [#1012](https://github.com/the-djmaze/snappymail/discussions/1012) +- RTF to HTML converter for + [#1012](https://github.com/the-djmaze/snappymail/discussions/1012) +- Polyfill for PHP ctype + [#1250](https://github.com/the-djmaze/snappymail/issues/1250) + +### Changed +- `new Error()` to `Error()` +- Reduce KnockoutJS footprint by removing unused code +- CSS reposition rainloopErrorTip location +- Improved error handling on PGP and S/MIME decrypt +- Improved OpenPGP.js import keys +- Use Identity S/MIME key and certificate from server instead of POST +- application.ini `[webmail]language_admin` to `[admin_panel]language` +- application.ini `[security]admin_panel_host` to `[admin_panel]host` +- application.ini `[security]admin_panel_key` to `[admin_panel]key` +- Drop deprecated Domain::SetConfig() +- Internationalized domain names are now handled as punycode +- Cacher->Get() can now return NULL +- Update French by @hguilbert +- Update Polish by @tinola +- Update Portuguese by @ner00 + +### Fixed +- Handling of Internationalized Domain Names in several areas +- Decrypt error message +- Stalwart ManageSieve Error 352 when getting Filters + [#1455](https://github.com/the-djmaze/snappymail/issues/1455) +- Nextcloud V25+ theme slightly broken + [#1463](https://github.com/the-djmaze/snappymail/issues/1463) +- PGP decryption fails with "Not armored text" + [#1462](https://github.com/the-djmaze/snappymail/issues/1462) +- AUTH_BASIC falling through as AUTH_BEARER; change AUTH_BEARER to a different value + [#1461](https://github.com/the-djmaze/snappymail/issues/1461) +- SetPassword expects \SnappyMail\SensitiveString +- Crash on importing corrupt OpenPGP keys +- Crash on old browsers instead of showing error +- Ignore popups on logoutReload() + [#1467](https://github.com/the-djmaze/snappymail/issues/1467) +- Custom SASLMechanisms fail in IMAP when the connection is secure + [#1484](https://github.com/the-djmaze/snappymail/pull/1484) by @botsarenthuman + + +## 2.35.2 – 2024-02-27 + +### Added +- GnuPG error handling +- Missing strings for localization inside identity popup (Cryptography > S/MIME) + [#1458](https://github.com/the-djmaze/snappymail/issues/1458) + +### Changed +- Update Portuguese by @ner00 + +### Fixed +- Drop support for gnupg PECL extension as it fails with "no passphrase" issues +- Error 352 when getting Filters + [#1455](https://github.com/the-djmaze/snappymail/issues/1455) + +### Nextcloud +- SetPassword(): Argument #1 must be of type SensitiveString, string given + [#1456](https://github.com/the-djmaze/snappymail/issues/1456) + + +## 2.35.1 – 2024-02-26 + +### Added +- Search functionality in Admin -> Config +- Cache S/MIME passphrases when "remember" is checked +- Import S/MIME certificate popup +- pre-verify S/MIME opaque signed messages so we have a body to view +- Sort PGP keys and S/MIME certificates on email address +- Optionally use existing private key to generate S/MIME certificate + +### Changed +- Better handling to detect which PGP or S/MIME sign/encrypt to use +- Improved StorageType handling +- Cleanup and improved Capa handling +- OPEN_PGP should be OPENPGP as it is one word +- Use get_debug_type() instead of gettype() +- Require OpenSSL due to S/MIME +- AbstractProvider::IsActive() is now an abstract method and must be defined in child class +- Make better use of SnappyMail\SensitiveString +- Update Polish translation by @tinola + +### Fixed +- Verify S/MIME signatures got broken allong the way while implementing this +- Generate S/MIME self-signed certificate failed to keep existing private key +- MIME parser RegExp didn't escape boundary which caused issues +- TypeError: b64Encode(...).match(...) is null on saving compose draft +- Fix timestampToString() for future dates + + +## 2.35.0 – 2024-02-20 + +### Added +- S/MIME support + [#259](https://github.com/the-djmaze/snappymail/issues/259) + +### Changed +- Disable IMAP METADATA by default (hardly used) +- Update Polish translation by @tinola +- Rename CSS .openpgp-control to .crypto-control +- Renamed some methods in PHP + +### Fixed +- When moving a folder/mailbox check for parent delimiter +- Mask `passphrase` in the logs for PHP < 8.2 +- Added some missing translations +- Sign messages using PGP +- Check for CONDSTORE or QRESYNC to get the HIGHESTMODSEQ +- Unable to login on certain IMAP server since 2.34.2 + [#1438](https://github.com/the-djmaze/snappymail/issues/1438) + +### Nextcloud +- Save as .eml + [#1425](https://github.com/the-djmaze/snappymail/issues/1425) + + +## 2.34.2 – 2024-02-14 + +### Fixed +- Message was sent but not saved to sent items folder + [#1432](https://github.com/the-djmaze/snappymail/issues/1432) +- Login with scram failed + [#1433](https://github.com/the-djmaze/snappymail/issues/1433) + + +## 2.34.1 – 2024-02-13 + +### Added +- Autocrypt support + [#342](https://github.com/the-djmaze/snappymail/issues/342) +- Load the mailboxes/folders of all namespaces (other users, global, shared, etc.) +- Load keys from server into OpenPGP.js + [#973](https://github.com/the-djmaze/snappymail/issues/973) +- Import PGP Keys from remote key servers +- Sort Inbox Folders with Unread Messages First + [#1427](https://github.com/the-djmaze/snappymail/issues/1427) +- Define JMAP FolderModel.myRights +- Identity Management: add identity display name + [#1405](https://github.com/the-djmaze/snappymail/issues/1405) +- Identity Management: add per-identity "sent" folder + [#1404](https://github.com/the-djmaze/snappymail/issues/1404) +- Some support for JSON-LD / Structured Email + [#1422](https://github.com/the-djmaze/snappymail/issues/1422) +- Domain Autoconfig and Microsoft's autodiscover (and also as extension/plugin) +- View MMS messages that are received via email + [#1294](https://github.com/the-djmaze/snappymail/issues/1294) +- Draft code for S/MIME + [#259](https://github.com/the-djmaze/snappymail/issues/259) + +### Changed +- Many OpenPGP improvements + [#89](https://github.com/the-djmaze/snappymail/issues/89) +- Allow CSP connect-src CORS for keys.openpgp.org to directly fetch PGP keys +- Improved handling of visible folders +- KnockoutJS Replace some ko.exportSymbol('*') in favour of ko['*'] +- KnockoutJS use Symbol for isObservableArray() +- Simplify generating folderListVisible +- Drop the bSearchSecretWords param from logger +- Transparent background for text + [#1412](https://github.com/the-djmaze/snappymail/issues/1412) +- Enable OpenPGP.js by default at install +- Added folder edit popup for improved IMAP ACL Support + [#157](https://github.com/the-djmaze/snappymail/issues/157) +- Process all IMAP namespaces +- Update Polish by @tinola +- Update Portuguese by @ner00 + +### Fixed +- Make time_zone a select list due to PEBKAC +- Workaround Outlook generated double spacing + [#1415](https://github.com/the-djmaze/snappymail/issues/1415) +- HTML Parser is not picking up the full Unsubscribe URL in the attached text file + [#1225](https://github.com/the-djmaze/snappymail/issues/1225) +- Contacts - it auto "Select All", after entry delete + [#1411](https://github.com/the-djmaze/snappymail/issues/1411) +- Message header parsing issue + [#1403](https://github.com/the-djmaze/snappymail/issues/1403) +- apple-touch-icon should not be transparent + [#1408](https://github.com/the-djmaze/snappymail/issues/1408) +- Creation of dynamic property is deprecated + [#1409](https://github.com/the-djmaze/snappymail/issues/1409) +- Ask/send readReceipt was broken +- OpenPGP public key can not be removed anymore after importing private key of subkey + [#1384](https://github.com/the-djmaze/snappymail/issues/1384) +- KnockoutJS failed to output text '0' +- JavaScript friendlySize() failed on 0 +- Workaround Dovecot `PREAUTH [CAPABILITY (null)]` issue +- Workaround disabled ACL could cause "Disconnected: Too many invalid IMAP commands" + +### Nextcloud +- Save multiple as .eml + [#1425](https://github.com/the-djmaze/snappymail/issues/1425) +- Disabled support for Nextcloud OpenID Connect + [#1420](https://github.com/the-djmaze/snappymail/issues/1420) + + +## 2.33.0 – 2024-01-22 + +### Added +- Feature to use the SQLite AddressBook per login account instead of global (on by default). +- Return all fetched messages headers in JSON. + +### Changed +- Docker hub use Alpine linux 3.18.5 and PHP 8.2 +- Some InvalidArgumentException to the better suited ValueError +- Removed some unused KnockoutJS code +- KnockoutJS drop unused rateLimit method +- Cleanup some data-bind="" +- Drop the disabled KnockoutJS twoWayBindings +- Drop support for KnockoutJS _ko_property_writers and for two-way binding they must be observables +- Login form use method="POST" to prevent uri exposure when javascript fails +- Merge code to generate MIME PGP parts and MIME Plain parts +- SMTP sendRequestWithCheck for future support of RFC's +- Cleanup mime header handling + +### Fixed +- Sorting not supported since 2.32.0 + [#1373](https://github.com/the-djmaze/snappymail/issues/1373) +- FILE_ON_SAVING_ERROR is not defined + [#1379](https://github.com/the-djmaze/snappymail/issues/1379) +- Saving EML files with same subject result in only saving latest email + [#1381](https://github.com/the-djmaze/snappymail/issues/1381) +- Some Sieve parser issues +- Handling of RainLoop Sieve script +- Sieve rfc5429 RejectCommand and ErejectCommand +- KnockoutJS title:value was removed, use attr:{title:value} +- dataBaseUpgrade() always runs on sqlite and pgsql +- Message was sent but not saved to sent items folder + [#1397](https://github.com/the-djmaze/snappymail/issues/1397) +- DKIM `pass` detection sometimes failed + + +## 2.32.0 – 2023-12-26 + +### Added +- Run full GetUids() in background when message_list_limit is set +- MessageListThreadsMap as background task when message_list_limit is set +- Properly set CACHEDIR.TAG +- Sending group email to all contact addresses + [#1286](https://github.com/the-djmaze/snappymail/pull/1286) by @rezaei92 + +### Changed +- Default IMAP message_list_limit to 10000 +- DoMessageCopy() return toFolder hash/etag +- Improved Squire WYSIWYG +- Sort real attachments and inline attachments for + [#1360](https://github.com/the-djmaze/snappymail/issues/1360) +- Nextcloud Theme fixes and improvements + [#1363](https://github.com/the-djmaze/snappymail/pull/1363) by @hampoelz +- Improve display of attachments + [#1361](https://github.com/the-djmaze/snappymail/issues/1361) +- Rename messageVisibility to messageVisible +- All CSS font-size to % instead of px +- Flip source code view of .eml attachments + [#1332](https://github.com/the-djmaze/snappymail/issues/1332) + +### Fixed +- Folders array_filter(): Argument 1 must be of type array, null given +- At upgrade set `static` and `themes` folder to 0755 +- Preview tooltip shows "null" when PREVIEW capability is disabled + +### Nextcloud +- Improved language handling + [#1362](https://github.com/the-djmaze/snappymail/pull/1362) by @avinash-0007 +- FilterLanguage had wrong parameter order +- Use NextcloudV25+ theme by default + + +## 2.31.0 – 2023-12-08 + +### Added +- PHP Hook `filter.language` to allow remote language selection + +### Changed +- Cleaner language detection +- Get Squire in sync with v2.2.5 and some bugfixes +- Update French by @Cwpute +- Squire: drop support for iPod + +### Fixed +- Call to undefined method FolderMyRights() + [#1344](https://github.com/the-djmaze/snappymail/issues/1344) +- NO Mailbox does not exist, or must be subscribed to") + [#1354](https://github.com/the-djmaze/snappymail/issues/1354) +- Flag indicators are added to wrong message + [#1347](https://github.com/the-djmaze/snappymail/pull/1347) by @SergeyMosin +- Squire: issue when using the enter key in a reply window + [#1296](https://github.com/the-djmaze/snappymail/issues/1296) +- Squire: crash on cut/delete range + +### Nextcloud +- Use language as defined in Nextcloud settings + [#1293](https://github.com/the-djmaze/snappymail/issues/1293) +- Plugin Call to undefined method RainLoop\Model\MainAccount::ImapConnectAndLoginHelper() +- SnappyMail failed due to Nextcloud Symfony polyfill + + +## 2.30.0 – 2023-12-04 + +### Added +- SnappyMail\SensitiveString class to secure passwords +- Allow to disable all IMAP features through Admin -> Domain +- Setting to open mails in a tab or new window + [#951](https://github.com/the-djmaze/snappymail/issues/951) +- Fully support IMAP PREVIEW + [#1338](https://github.com/the-djmaze/snappymail/issues/1338) +- Disable "Mark message as read after", offer manual toggle + [#1289](https://github.com/the-djmaze/snappymail/issues/1289) +- A "Move to" button inside message view as an icon/button and in the drop down menu. + [#1295](https://github.com/the-djmaze/snappymail/issues/1295) +- Support for IMAP WITHIN +- Support \noinferiors to disallow creating subfolders +- A test due to Failed loading libs.min.js + [#358](https://github.com/the-djmaze/snappymail/issues/358), + [#862](https://github.com/the-djmaze/snappymail/issues/862), + [#890](https://github.com/the-djmaze/snappymail/issues/890), + [#895](https://github.com/the-djmaze/snappymail/issues/895), + [#1238](https://github.com/the-djmaze/snappymail/issues/1238), + [#1320](https://github.com/the-djmaze/snappymail/issues/1320) + +### Changed +- Split PHP 8 polyfills from include.php +- Disable snappymail/v/0.0.0/static/.htaccess for now as many servers have issues with it +- Merged all Domain `disable_*` settings into `disabled_capabilities:[]` +- Prioritize LIST-EXTENDED over LSUB (LSUB deprecated in IMAP4rev2) +- Removed unused ImapClient::IsSupported() +- Removed obsolete `$_ENV['SNAPPYMAIL_NEXTCLOUD']` +- Removed unused Plugin->replaceTemplate() +- Removed openDropdownTrigger + +### Fixed +- Move to button does not work + [#1328](https://github.com/the-djmaze/snappymail/issues/1328) +- Mark passwords as sensitive information + [#1343](https://github.com/the-djmaze/snappymail/issues/1343) +- Account sSmtpPassword wrong value +- SCRAM sign-in failed + [#1245](https://github.com/the-djmaze/snappymail/issues/1245) +- Squire generates to many `

` + [#1339](https://github.com/the-djmaze/snappymail/issues/1339) +- Creation of dynamic property SnappyMail\Stream\ZipEntry::$compression is deprecated +- `json.after-*` hooks didn't send $aResponse as recursive array +- Sieve: Move to folder with trailing space does not work + [#1329](https://github.com/the-djmaze/snappymail/issues/1329) +- Squire: cantFocusEmptyTextNodes var is always undefined + [#1337](https://github.com/the-djmaze/snappymail/issues/1337) +- Squire: Remove redundant after replacing styles +- Squire: Handle empty nodes in moveRangeBoundariesDownTree +- Theme "Nextcloud V25+" can't be translated + [#1331](https://github.com/the-djmaze/snappymail/issues/1331) + + +## 2.29.4 – 2023-11-21 + +### Fixed +- Contacts not work + [#1319](https://github.com/the-djmaze/snappymail/issues/1319) + + +## 2.29.3 – 2023-11-21 + +### Added +- Docker Hub image + [#965](https://github.com/the-djmaze/snappymail/pull/965) by @leojonathanoh + +### Changed +- Sabre/VObject 4.5.4 and Sabre/Xml 4.0.4 + [#1311](https://github.com/the-djmaze/snappymail/issues/1311) + +### Fixed +- '#/mailbox/folder/mUID/search' uri/route handling + [#1301](https://github.com/the-djmaze/snappymail/pull/1301) by @SergeyMosin +- "Remember me" doesn't work when browser is closed + [#1313](https://github.com/the-djmaze/snappymail/issues/1313) +- Blank email displayed when "Prefer HTML to plain text" is unchecked and the message is html only + [#1302](https://github.com/the-djmaze/snappymail/issues/1302) +- Parent folder of Sub folder not useable. + [#1008](https://github.com/the-djmaze/snappymail/issues/1008) +- Large detailed header don't display body + [#1284](https://github.com/the-djmaze/snappymail/issues/1284) + +### Nextcloud +- Improvements for Install / update issues #929 + [#929](https://github.com/the-djmaze/snappymail/issues/929) +- Should use language as defined in cloud settings #1293 + [#1293](https://github.com/the-djmaze/snappymail/issues/1293) + + +## 2.29.2 – 2023-11-14 + +### Added +- Show size of folders in folders list #1303 + [#1303](https://github.com/the-djmaze/snappymail/issues/1303) + +### Fixed +- Configuration failed when using special chars in MySQL password #1308 + [#1308](https://github.com/the-djmaze/snappymail/issues/1308) +- With email open, "delete" doesn't delete #1274 + [#1274](https://github.com/the-djmaze/snappymail/issues/1274) +- Fix threading view in Thunderbird (others?) + [#1304](https://github.com/the-djmaze/snappymail/pull/1304) by @tkasch + + +## 2.29.1 – 2023-10-02 + +### Fixed +- Some small messages list bugs + + +## 2.29.0 – 2023-10-02 + +### Added +- Modern UI / Nextcloud Theme + [#629](https://github.com/the-djmaze/snappymail/pull/629) by @hampoelz +- "Add/Edit signature" label to PopupsIdentity.html + [#1248](https://github.com/the-djmaze/snappymail/pull/1248) by @SergeyMosin +- use calendar icon in message list for messages with '.ics' or 'text/calendar' attachments by @SergeyMosin + [#1248](https://github.com/the-djmaze/snappymail/pull/1248) +- Show unseen message count when the message list is threaded + [#1248](https://github.com/the-djmaze/snappymail/pull/1248) by @SergeyMosin +- in mobile mode hide folders(left) panel when a folder is clicked + [#1248](https://github.com/the-djmaze/snappymail/pull/1248) by @SergeyMosin +- spellcheck the subject when 'allowSpellcheck' setting is true + [#1248](https://github.com/the-djmaze/snappymail/pull/1248) by @SergeyMosin +- 'collapse_blockquotes', 'allow_spellcheck' and 'mail_list_grouped' to admin settings ('defaults' section) + [#1248](https://github.com/the-djmaze/snappymail/pull/1248) by @SergeyMosin +- Browser support for autocompleting TOTP code + [#1251](https://github.com/the-djmaze/snappymail/issues/1251) + +### Changed +- URL strip tracking for + [#1225](https://github.com/the-djmaze/snappymail/issues/1225) +- Color picker use color blind palette "Tableau 10" by Maureen Stone by default + [#1199](https://github.com/the-djmaze/snappymail/issues/1199) +- Draft code to improve mobile breakpoints + [#1150](https://github.com/the-djmaze/snappymail/issues/1150) +- address input: space character can trigger '_parseValue' if the email address looks complete + [#1248](https://github.com/the-djmaze/snappymail/pull/1248) by @SergeyMosin +- if applicable set '\\answered' or '$forwarded' flag after a message is sent so the proper icon is shown in the message list view + [#1248](https://github.com/the-djmaze/snappymail/pull/1248) by @SergeyMosin + +### Fixed +- CHARSET is not valid in UTF8 mode + [#1230](https://github.com/the-djmaze/snappymail/issues/1230) +- Spam score is always "acceptable" + [#1228](https://github.com/the-djmaze/snappymail/issues/1228) +- Undefined constant PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT + [#1205](https://github.com/the-djmaze/snappymail/issues/1205) +- Fetch controller.abort(reason) handling + [#1220](https://github.com/the-djmaze/snappymail/issues/1220) +- "Request failed" on message move + [#1220](https://github.com/the-djmaze/snappymail/issues/1220) +- Unwrapped text nodes attached to squire._root + [#1234](https://github.com/the-djmaze/snappymail/pull/1234) by @SergeyMosin +- Extra wrapper div is added in Squire every time a Draft is open (or closed) after save. + [#1208](https://github.com/the-djmaze/snappymail/issues/1208) +- foreach() argument must be of type array|object + [#1237](https://github.com/the-djmaze/snappymail/issues/1237) +- `` tag 'style' is lost in replies + [#1248](https://github.com/the-djmaze/snappymail/pull/1248) by @SergeyMosin +- unseen indicator is not shown in thread view when 'listGrouped' settings is false + [#1248](https://github.com/the-djmaze/snappymail/pull/1248) by @SergeyMosin +- TOTP plugin is dependent on ctype + [#1250](https://github.com/the-djmaze/snappymail/issues/1250) + +### Nextcloud +- iFrame mode: click on unified search result opens inner iFrame + [#1248](https://github.com/the-djmaze/snappymail/pull/1248) by @SergeyMosin +- set 'smremember' cookie if 'sign_me_auto' is set to 'DefaultOn' when using 'snappymail-autologin*', otherwise nextcloud users need to re-login when the browser is re-opened + [#1248](https://github.com/the-djmaze/snappymail/pull/1248) by @SergeyMosin +- Improve UX of "Put in Calendar" option in plugin + [#1259](https://github.com/the-djmaze/snappymail/pull/1259) by @theronakpatel + + +## 2.28.4 – 2023-07-10 + +### Added +- application.ini msg_default_action + [#1204](https://github.com/the-djmaze/snappymail/pull/1204) by @SergeyMosin +- application.ini view_show_next_message + [#1204](https://github.com/the-djmaze/snappymail/pull/1204) by @SergeyMosin +- application.ini view_images + [#1204](https://github.com/the-djmaze/snappymail/pull/1204) by @SergeyMosin +- nextcloud add ability to include custom php file in InstallStep migration + [#1197](https://github.com/the-djmaze/snappymail/pull/1197) by @SergeyMosin +- Support plugin for Squire editor + [#1192](https://github.com/the-djmaze/snappymail/issues/1192) + +### Changed +- only show 'Add "domain.tld" as an application for mailto links?' message after login (firefox shows the message on every reload otherwise). + [#1204](https://github.com/the-djmaze/snappymail/issues/1204) +- Convert getPdoAccessData() : array to a RainLoop\Pdo\Settings object instance +- New bidi buttons to Squire editor + [#1200](https://github.com/the-djmaze/snappymail/pull/1200) by @rezaei92 + +### Fixed +- Undefined constant PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT + [#1205](https://github.com/the-djmaze/snappymail/issues/1205) +- 'reloadTime' function result is passed into 'setInterval' instead of the function + [#1204](https://github.com/the-djmaze/snappymail/pull/1204) by @SergeyMosin +- UNKNOWN-CTE Invalid data in MIME part + [#1186](https://github.com/the-djmaze/snappymail/issues/1186) + + +## 2.28.3 – 2023-06-22 + +### Added +- Attachments in "new window" view + [#1166](https://github.com/the-djmaze/snappymail/issues/1166) + +### Changed +- Update Portuguese by @ner00 +- Update French by @hguilbert + +### Fixed +- Some emails with inline CSS break the UI + [#1187](https://github.com/the-djmaze/snappymail/issues/1187) +- Remote.get() Promise broken by previous change + [#1185](https://github.com/the-djmaze/snappymail/issues/1185) +- Class "MailSo\Base\Exceptions\InvalidArgumentException" not found + [#1182](https://github.com/the-djmaze/snappymail/issues/1182) +- First account not showed in the right list (dropbox) + [#1180](https://github.com/the-djmaze/snappymail/issues/1180) + + +## 2.28.2 – 2023-06-19 + +### Added +- Detailed error for "Cannot access the repository at the moment" + [#1164](https://github.com/the-djmaze/snappymail/issues/1164) +- Bidi in Squire editor + [#1158](https://github.com/the-djmaze/snappymail/issues/1158) +- Translate Squire UI +- Nextcloud 27 compatibility by @LarsBel +- JWT class for handling JSON Web Tokens + +### Changed +- Update German by @cm-schl +- Update French by @hguilbert +- Update Polish by @tinola +- Merge handling of local Account Settings. Found while investigating + [#1170](https://github.com/the-djmaze/snappymail/issues/1170) +- Image max-width now 100% instead of 90vw + +### Fixed +- Cannot modify header information + [#929](https://github.com/the-djmaze/snappymail/issues/929) (comment) +- Admin Panel broken when admin_panel_host is set + [#1169](https://github.com/the-djmaze/snappymail/issues/1169) +- Invalid CSP report-uri +- Prevent MessageList multiple request at the same time + [#1071](https://github.com/the-djmaze/snappymail/issues/1071) +- Error in Addressbook Sync + [#1179](https://github.com/the-djmaze/snappymail/issues/1179) +- base64_decode() second parameter must be true + + +## 2.28.1 – 2023-06-05 + +### Changed +- Optical issue with input fields for mail and folder search + [#1149](https://github.com/the-djmaze/snappymail/issues/1149) +- Update Chinese translation + [#1157](https://github.com/the-djmaze/snappymail/pull/1157) by @mayswind +- Update Polish translation + [#1156](https://github.com/the-djmaze/snappymail/pull/1156) by @tinola + +### Fixed +- Undefined SIG constants + [#1147](https://github.com/the-djmaze/snappymail/issues/1147) + + +## 2.28.0 – 2023-05-30 + +### Added +- Threaded view make number orange when unread sub-messages + [#1028](https://github.com/the-djmaze/snappymail/issues/1028) +- Handle PHP pctnl messages +- addEventListener('rl-view-model') missing for Settings + [#1013](https://github.com/the-djmaze/snappymail/issues/1013) +- CSS `--btn-border-radius` + +### Changed +- Improved RTL languages support + [#1056](https://github.com/the-djmaze/snappymail/issues/1056) +- Composer text/attachments as tabs + [#1119](https://github.com/the-djmaze/snappymail/issues/1119) +- Filter dialog doesn't refer to folder names consistently + [#1111](https://github.com/the-djmaze/snappymail/issues/1111) +- TLS connection for MYSQL contact db + [#1078](https://github.com/the-djmaze/snappymail/issues/1078) +- Allow empty message body when there are attachments + [#1052](https://github.com/the-djmaze/snappymail/issues/1052) +- PHP inherit logger as Trait +- Update Portuguese + [#1124](https://github.com/the-djmaze/snappymail/pull/1124) by @ner00 +- Update Traditional Chinese (Taiwan) + [#1107](https://github.com/the-djmaze/snappymail/pull/1107) by @chiyi4488 +- Update Russian + [#1108](https://github.com/the-djmaze/snappymail/pull/1108) by @konkere +- Update Italian + [#1094](https://github.com/the-djmaze/snappymail/pull/1094) by @cm-schl +- Update French + [#1102](https://github.com/the-djmaze/snappymail/pull/1102) by @hguilbert +- Update German + [#1087](https://github.com/the-djmaze/snappymail/pull/1087) by @cm-schl + +### Fixed +- Show messagelist timeout/abort error for + [#1071](https://github.com/the-djmaze/snappymail/issues/1071) +- DesktopNotifications setting not saved + [#1137](https://github.com/the-djmaze/snappymail/issues/1137) +- PHP Deprecation warning for $_openPipes + [#1141](https://github.com/the-djmaze/snappymail/issues/1141) +- Images size wrong + [#1134](https://github.com/the-djmaze/snappymail/issues/1134) +- Unable to preview body of encrypted mail in mailvelope reply-to + [#1130](https://github.com/the-djmaze/snappymail/issues/1130) +- Replace ` diff --git a/snappymail/v/0.0.0/app/templates/Views/Admin/AdminSettingsPackages.html b/snappymail/v/0.0.0/app/templates/Views/Admin/AdminSettingsPackages.html index 96f289b6a..b52152d44 100644 --- a/snappymail/v/0.0.0/app/templates/Views/Admin/AdminSettingsPackages.html +++ b/snappymail/v/0.0.0/app/templates/Views/Admin/AdminSettingsPackages.html @@ -15,11 +15,14 @@

+ +
+
@@ -28,7 +31,7 @@
-
+
diff --git a/snappymail/v/0.0.0/app/templates/Views/Admin/AdminSettingsPluginProperty.html b/snappymail/v/0.0.0/app/templates/Views/Admin/AdminSettingsPluginProperty.html index 63b96d0a5..130d710dc 100644 --- a/snappymail/v/0.0.0/app/templates/Views/Admin/AdminSettingsPluginProperty.html +++ b/snappymail/v/0.0.0/app/templates/Views/Admin/AdminSettingsPluginProperty.html @@ -1,36 +1,36 @@ - - + + - + - + - + - - + + - +
- + - - + + - - + + diff --git a/snappymail/v/0.0.0/app/templates/Views/Admin/AdminSettingsSecurity.html b/snappymail/v/0.0.0/app/templates/Views/Admin/AdminSettingsSecurity.html index 2e5e27c57..d96bf34bf 100644 --- a/snappymail/v/0.0.0/app/templates/Views/Admin/AdminSettingsSecurity.html +++ b/snappymail/v/0.0.0/app/templates/Views/Admin/AdminSettingsSecurity.html @@ -1,19 +1,38 @@
+
+
+
+
+
+
+
@@ -46,12 +65,14 @@ +

 	
+
diff --git a/snappymail/v/0.0.0/app/templates/Views/Admin/PopupsDomain.html b/snappymail/v/0.0.0/app/templates/Views/Admin/PopupsDomain.html index 086401273..b78891e18 100644 --- a/snappymail/v/0.0.0/app/templates/Views/Admin/PopupsDomain.html +++ b/snappymail/v/0.0.0/app/templates/Views/Admin/PopupsDomain.html @@ -11,8 +11,12 @@
+
-
+
@@ -20,9 +24,10 @@
+
@@ -35,8 +40,8 @@
@@ -58,7 +63,16 @@ value: imapShortLogin } }">
- (user@domain.com → user) + (user@example.com → user) +
+
+ (USER@example.com → user@example.com)

SSL/TLS

-

-
-
-
-
-
+

+ + ⓘ +

+ +
+
+ +
+

@@ -129,15 +123,27 @@ "fast_simple_search": true, "force_select": false, "message_all_headers": false, - "search_filter": null, +
+ + +
--> +
+ + +
+
+ + +
diff --git a/snappymail/v/0.0.0/app/templates/Views/Common/Paginator.html b/snappymail/v/0.0.0/app/templates/Views/Common/Paginator.html index b7ebf668b..5d8177992 100644 --- a/snappymail/v/0.0.0/app/templates/Views/Common/Paginator.html +++ b/snappymail/v/0.0.0/app/templates/Views/Common/Paginator.html @@ -1,3 +1,3 @@ diff --git a/snappymail/v/0.0.0/app/templates/Views/Common/PopupsAsk.html b/snappymail/v/0.0.0/app/templates/Views/Common/PopupsAsk.html index 137c4f95c..8c5e2a30a 100644 --- a/snappymail/v/0.0.0/app/templates/Views/Common/PopupsAsk.html +++ b/snappymail/v/0.0.0/app/templates/Views/Common/PopupsAsk.html @@ -8,6 +8,23 @@
+
+
+
+
diff --git a/snappymail/v/0.0.0/app/templates/Views/Common/PopupsLanguages.html b/snappymail/v/0.0.0/app/templates/Views/Common/PopupsLanguages.html index 0df6a301b..7df69e7f7 100644 --- a/snappymail/v/0.0.0/app/templates/Views/Common/PopupsLanguages.html +++ b/snappymail/v/0.0.0/app/templates/Views/Common/PopupsLanguages.html @@ -4,7 +4,7 @@ diff --git a/snappymail/v/0.0.0/app/templates/Views/Components/Checkbox.html b/snappymail/v/0.0.0/app/templates/Views/Components/Checkbox.html index ca4a720a0..9886a2963 100644 --- a/snappymail/v/0.0.0/app/templates/Views/Components/Checkbox.html +++ b/snappymail/v/0.0.0/app/templates/Views/Components/Checkbox.html @@ -1,8 +1,9 @@ -
-
-
+
+ diff --git a/snappymail/v/0.0.0/app/templates/Views/User/Login.html b/snappymail/v/0.0.0/app/templates/Views/User/Login.html index aed43eaa0..e1dfbbf3d 100644 --- a/snappymail/v/0.0.0/app/templates/Views/User/Login.html +++ b/snappymail/v/0.0.0/app/templates/Views/User/Login.html @@ -7,7 +7,7 @@

-
✉ @@ -25,7 +25,7 @@
-
+
diff --git a/snappymail/v/0.0.0/app/templates/Views/User/MailFolderList.html b/snappymail/v/0.0.0/app/templates/Views/User/MailFolderList.html index aa4958b4c..3103049a1 100644 --- a/snappymail/v/0.0.0/app/templates/Views/User/MailFolderList.html +++ b/snappymail/v/0.0.0/app/templates/Views/User/MailFolderList.html @@ -1,5 +1,5 @@ -
-
+
+ -
- diff --git a/snappymail/v/0.0.0/app/templates/Views/User/MailFolderListItem.html b/snappymail/v/0.0.0/app/templates/Views/User/MailFolderListItem.html index 18e417992..35bb12f22 100644 --- a/snappymail/v/0.0.0/app/templates/Views/User/MailFolderListItem.html +++ b/snappymail/v/0.0.0/app/templates/Views/User/MailFolderListItem.html @@ -1,13 +1,11 @@ -
  • + css: { 'selected': selected() && !isSystemFolder(), 'system': isSystemFolder, 'selectable': canBeSelected, 'unread-sub': hasUnreadInSub, 'anim-action-class': actionBlink }, + attr: { 'data-unread': unreadCount, href: href }"> - -
      + +
      • - diff --git a/snappymail/v/0.0.0/app/templates/Views/User/MailMessageList.html b/snappymail/v/0.0.0/app/templates/Views/User/MailMessageList.html index e3458780b..42521ef43 100644 --- a/snappymail/v/0.0.0/app/templates/Views/User/MailMessageList.html +++ b/snappymail/v/0.0.0/app/templates/Views/User/MailMessageList.html @@ -1,28 +1,27 @@ -
        - - ❮ - +
        + + - - + - -
        + + + 📁 + +
        🗄 - ⚠ + ⚠ 🗑 +
        -