2035: updated roundcube to 1.5.1 and carddav to 4.3.0 r=mergify[bot] a=ghostwheel42

## What type of PR?

enhancement

## What does this PR do?

updated roundcube to 1.5 and carddav to 4.2.2
also runs cleanup cronjob _once_ at startup

### Related issue(s)

- closes #2031 
- runs cleanup job mentioned in #1702 at startup

## Prerequisites
Before we can consider review and merge, please make sure the following list is done and checked.
If an entry in not applicable, you can check it or remove it from the list.

- [X] In case of feature or enhancement: documentation updated accordingly
- [X] Unless it's docs or a minor change: add [changelog](https://mailu.io/master/contributors/workflow.html#changelog) entry file.


Co-authored-by: Alexander Graf <ghostwheel42@users.noreply.github.com>
master
bors[bot] 2 years ago committed by GitHub
commit c5966b29db
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -100,6 +100,7 @@ services:
env_file: .env
volumes:
- "$ROOT/webmail:/data"
- "$ROOT/overrides/$WEBMAIL:/overrides:ro"
depends_on:
- imap

@ -128,6 +128,7 @@ services:
env_file: .env
volumes:
- "$ROOT/webmail:/data"
- "$ROOT/overrides/$WEBMAIL:/overrides:ro"
depends_on:
- imap

@ -263,6 +263,50 @@ The roundcube service stores configurations in a database.
- ``ROUNDCUBE_DB_USER``: the database user for roundcube service. (when not ``sqlite``)
- ``ROUNDCUBE_DB_NAME``: the database name for roundcube service. (when not ``sqlite``)
Webmail settings
----------------
When using roundcube it is possible to select the plugins to be enabled by setting ``ROUNDCUBE_PLUGINS`` to
a comma separated list of plugin-names. Included plugins are:
- acl (needs configuration)
- additional_message_headers (needs configuration)
- archive
- attachment_reminder
- carddav
- database_attachmentsi
- debug_logger
- emoticons
- enigma
- help
- hide_blockquote
- identicon
- identity_select
- jqueryui
- mailu
- managesieve
- markasjunk
- new_user_dialog
- newmail_notifier
- reconnect
- show_additional_headers (needs configuration)
- subscriptions_option
- vcard_attachments
- zipdownload
If ``ROUNDCUBE_PLUGINS`` is not set the following plugins are enabled by default:
- archive
- carddav
- enigma
- mailu
- managesieve
- markasjunk
- zipdownload
To disable all plugins just set ``ROUNDCUBE_PLUGINS`` to ``mailu``.
To configure a plugin add php files named ``*.inc`` to roundcube's :ref:`override section <override-label>`.
Mail log settings
-----------------

@ -147,6 +147,7 @@ services:
env_file: {{ env }}
volumes:
- "{{ root }}/webmail:/data"
- "{{ root }}/overrides/{{ webmail_type }}:/overrides:ro"
depends_on:
- imap
{% endif %}

@ -123,6 +123,7 @@ services:
env_file: {{ env }}
volumes:
- "{{ root }}/webmail:/data"
- "{{ root }}/overrides/{{ webmail_type }}:/overrides:ro"
deploy:
replicas: 1
healthcheck:

@ -0,0 +1 @@
updated roundcube to 1.5 and carddav to 4.2.2 using php8

@ -1,10 +1,10 @@
# NOTE: only add file if building for arm
# NOTE: only add qemu-arm-static if building for arm
ARG ARCH=""
ARG QEMU=other
FROM ${ARCH}php:7.4-apache as build_arm
FROM ${ARCH}php:8.0-apache as build_arm
ONBUILD COPY --from=balenalib/rpi-alpine:3.14 /usr/bin/qemu-arm-static /usr/bin/qemu-arm-static
FROM ${ARCH}php:8.0-apache as build_other
FROM ${ARCH}php:7.4-apache as build_other
FROM build_${QEMU}
ARG VERSION
@ -12,25 +12,37 @@ ENV TZ Etc/UTC
LABEL version=$VERSION
#Shared layer between rainloop and roundcube
RUN apt-get update && apt-get install -y \
python3 curl python3-pip git python3-multidict tzdata \
&& rm -rf /var/lib/apt/lists \
&& echo "ServerSignature Off\nServerName roundcube" >> /etc/apache2/apache2.conf \
&& sed -i 's,CustomLog.*combined$,\0 "'"expr=!(%{HTTP_USER_AGENT}=='health'\&\&(-R '127.0.0.1/8' || -R '::1'))"'",' /etc/apache2/sites-available/000-default.conf
RUN set -eu \
&& apt update \
&& echo 'debconf debconf/frontend select Noninteractive' | debconf-set-selections \
&& apt install -y --no-install-recommends \
python3 curl python3-pip git python3-multidict \
python3-jinja2 gpg tzdata \
&& pip3 install socrate \
&& echo date.timezone=UTC > /usr/local/etc/php/conf.d/timezone.ini \
&& echo "ServerSignature Off\nServerName roundcube" >> /etc/apache2/apache2.conf \
&& sed -i 's,CustomLog.*combined$,\0 "'"expr=!(%{HTTP_USER_AGENT}=='health'\&\&(-R '127.0.0.1/8' || -R '::1'))"'",' /etc/apache2/sites-available/000-default.conf \
\
&& mark="$(apt-mark showmanual)" \
&& apt install -y --no-install-recommends \
libfreetype6-dev libicu-dev libjpeg62-turbo-dev libldap2-dev libmagickwand-dev \
libpng-dev libpq-dev libsqlite3-dev libzip-dev libpspell-dev libonig-dev \
&& ln -s php.ini-production /usr/local/etc/php/php.ini \
&& docker-php-ext-configure gd --with-jpeg --with-freetype \
&& docker-php-ext-install exif gd intl zip pspell pdo_mysql pdo_pgsql pdo_sqlite \
&& pecl install imagick \
&& docker-php-ext-enable imagick opcache \
&& apt-mark auto '.*' >/dev/null \
&& apt-mark manual ${mark} >/dev/null \
&& ldd "$(php -r 'echo ini_get("extension_dir");')"/*.so | awk '/=>/ { print $3 }' | sort -u | \
xargs -r dpkg-query -S | cut -d: -f1 | sort -u | xargs -r apt-mark manual >/dev/null \
&& apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \
&& rm -rf /var/lib/apt/lists
# Shared layer between nginx, dovecot, postfix, postgresql, rspamd, unbound, rainloop, roundcube
RUN pip3 install socrate
ENV ROUNDCUBE_URL https://github.com/roundcube/roundcubemail/releases/download/1.5.1/roundcubemail-1.5.1-complete.tar.gz
ENV CARDDAV_URL https://github.com/mstilkerich/rcmcarddav/releases/download/v4.3.0/carddav-v4.3.0.tar.gz
ENV ROUNDCUBE_URL https://github.com/roundcube/roundcubemail/releases/download/1.4.11/roundcubemail-1.4.11-complete.tar.gz
ENV CARDDAV_URL https://github.com/mstilkerich/rcmcarddav/releases/download/v4.1.2/carddav-v4.1.2.tar.gz
RUN apt-get update && apt-get install -y \
zlib1g-dev libzip4 libzip-dev libpq-dev \
python3-jinja2 \
gpg \
&& docker-php-ext-install zip pdo_mysql pdo_pgsql \
RUN set -eu \
&& rm -rf /var/www/html/ \
&& cd /var/www \
&& curl -sL ${ROUNDCUBE_URL} | tar xz \
@ -38,27 +50,29 @@ RUN apt-get update && apt-get install -y \
&& mv roundcubemail-* html \
&& mv carddav html/plugins/ \
&& cd html \
&& rm -rf CHANGELOG INSTALL LICENSE README.md UPGRADING composer.json-dist installer composer.* \
&& sed -i 's,mod_php5.c,mod_php7.c,g' .htaccess \
&& sed -i 's,^php_value.*post_max_size,#&,g' .htaccess \
&& sed -i 's,^php_value.*upload_max_filesize,#&,g' .htaccess \
&& rm -rf CHANGELOG.md SECURITY.md INSTALL LICENSE README.md UPGRADING composer.json-dist installer composer.* \
&& ln -sf index.php /var/www/html/sso.php \
&& ln -sf /dev/stderr /var/www/html/logs/errors.log \
&& chown -R root:root . \
&& chown www-data:www-data logs temp \
&& chmod -R a+rX . \
&& rm -rf /var/lib/apt/lists \
&& a2enmod rewrite deflate expires headers
&& a2enmod rewrite deflate expires headers \
&& echo date.timezone=${TZ} > /usr/local/etc/php/conf.d/timezone.ini \
&& rm -rf plugins/{autologon,example_addressbook,http_authentication,krb_authentication,new_user_identity,password,redundant_attachments,squirrelmail_usercopy,userinfo,virtuser_file,virtuser_query}
# enable database_attachments (and memcache?)
COPY php.ini /php.ini
COPY config.inc.php /var/www/html/config/
COPY mailu.php /var/www/html/plugins/mailu/mailu.php
COPY start.py /start.py
COPY php.ini /
COPY config.inc.php /
COPY start.py /
EXPOSE 80/tcp
VOLUME ["/data"]
VOLUME /data
VOLUME /overrides
CMD /start.py
HEALTHCHECK CMD curl -f -L -H 'User-Agent: health' http://localhost/ || exit 1
RUN echo $VERSION >> /version
RUN echo $VERSION >> /version

@ -3,46 +3,29 @@
$config = array();
// Generals
$config['db_dsnw'] = getenv('DB_DSNW');;
$config['db_dsnw'] = '{{ DB_DSNW }}';
$config['temp_dir'] = '/tmp/';
$config['des_key'] = getenv('SECRET_KEY') ? getenv('SECRET_KEY') : trim(file_get_contents(getenv('SECRET_KEY_FILE')));
$config['des_key'] = '{{ SECRET_KEY }}';
$config['cipher_method'] = 'AES-256-CBC';
$config['identities_level'] = 0;
$config['reply_all_mode'] = 1;
// List of active plugins (in plugins/ directory)
$config['plugins'] = array(
'archive',
'zipdownload',
'markasjunk',
'managesieve',
'enigma',
'carddav'
);
$front = getenv('FRONT_ADDRESS') ? getenv('FRONT_ADDRESS') : 'front';
$imap = getenv('IMAP_ADDRESS') ? getenv('IMAP_ADDRESS') : 'imap';
$config['log_driver'] = 'stdout';
$config['zipdownload_selection'] = true;
$config['enable_spellcheck'] = true;
$config['spellcheck_engine'] = 'pspell';
// Mail servers
$config['default_host'] = $front;
$config['default_host'] = '{{ FRONT_ADDRESS or "front" }}';
$config['default_port'] = 10143;
$config['smtp_server'] = $front;
$config['smtp_server'] = '{{ FRONT_ADDRESS or "front" }}';
$config['smtp_port'] = 10025;
$config['smtp_user'] = '%u';
$config['smtp_pass'] = '%p';
// Sieve script management
$config['managesieve_host'] = $imap;
$config['managesieve_host'] = '{{ IMAP_ADDRESS or "imap" }}';
$config['managesieve_usetls'] = false;
// Customization settings
if (filter_var(getenv('ADMIN'), FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE)) {
$config['support_url'] = getenv('WEB_ADMIN') ? '../..' . getenv('WEB_ADMIN') : '';
}
$config['product_name'] = 'Mailu Webmail';
array_push($config['plugins'], 'mailu');
$config['sso_logout_url'] = '/sso/logout';
// We access the IMAP and SMTP servers locally with internal names, SSL
// will obviously fail but this sounds better than allowing insecure login
// from the outter world
@ -56,11 +39,27 @@ $config['imap_conn_options'] = $ssl_no_check;
$config['smtp_conn_options'] = $ssl_no_check;
$config['managesieve_conn_options'] = $ssl_no_check;
// roundcube customization
$config['product_name'] = 'Mailu Webmail';
{%- if ADMIN and WEB_ADMIN %}
$config['support_url'] = '../..{{ WEB_ADMIN }}';
{%- endif %}
$config['plugins'] = array({{ PLUGINS }});
// skin name: folder from skins/
$config['skin'] = 'elastic';
// Enigma gpg plugin
// configure mailu sso plugin
$config['sso_logout_url'] = '/sso/logout';
// configure enigma gpg plugin
$config['enigma_pgp_homedir'] = '/data/gpg';
// Set From header for DKIM signed message delivery reports
// set From header for DKIM signed message delivery reports
$config['mdn_use_from'] = true;
// includes
{%- for inc in INCLUDES %}
include('{{ inc }}');
{%- endfor %}

@ -0,0 +1,2 @@
#!/bin/sh
SCRIPT_NAME=/ping SCRIPT_FILENAME=/ping REQUEST_METHOD=GET cgi-fcgi -bind -connect 127.0.0.1:9000 2>/dev/null | grep -qFx pong

@ -15,7 +15,14 @@ class mailu extends rcube_plugin
function startup($args)
{
if (empty($_SESSION['user_id'])) {
$args['action'] = 'login';
$args['action'] = 'login';
}
$ua = $_SERVER['HTTP_USER_AGENT'];
$ra = $_SERVER['REMOTE_ADDR'];
if ($ua == 'health' and ($ra == '127.0.0.1' or $ra == '::1')) {
print('OK');
exit();
}
return $args;
@ -23,10 +30,16 @@ class mailu extends rcube_plugin
function authenticate($args)
{
if (!in_array('HTTP_X_REMOTE_USER', $_SERVER) || !in_array('HTTP_X_REMOTE_USER_TOKEN', $_SERVER)) {
if (!array_key_exists('HTTP_X_REMOTE_USER', $_SERVER) or !array_key_exists('HTTP_X_REMOTE_USER_TOKEN', $_SERVER)) {
if ($_SERVER['PHP_SELF'] == '/sso.php') {
header('HTTP/1.0 403 Forbidden');
die();
print('mailu sso failure');
} else {
header('Location: sso.php');
}
exit();
}
$args['user'] = $_SERVER['HTTP_X_REMOTE_USER'];
$args['pass'] = $_SERVER['HTTP_X_REMOTE_USER_TOKEN'];
@ -36,30 +49,25 @@ class mailu extends rcube_plugin
return $args;
}
function logout($args) {
// Redirect to global SSO logout path.
// Redirect to global SSO logout path.
function logout($args)
{
$this->load_config();
$sso_logout_url = rcmail::get_instance()->config->get('sso_logout_url');
header("Location: " . $sso_logout_url, true);
exit;
header('Location: ' . $sso_logout_url, true);
exit();
}
function login($args)
{
header('Location: index.php');
exit();
header('Location: index.php');
exit();
}
function login_failed($args)
{
$ua = $_SERVER['HTTP_USER_AGENT'];
$ra = $_SERVER['REMOTE_ADDR'];
if ($ua == 'health' and ($ra == '127.0.0.1' or $ra == '::1')) {
echo "OK";
exit;
}
header('Location: sso.php');
exit();
header('Location: sso.php');
exit();
}
}

@ -1,61 +1,105 @@
#!/usr/bin/python3
import os
import logging as log
import logging
import sys
from socrate import conf
import subprocess
import hmac
log.basicConfig(stream=sys.stderr, level=os.environ.get("LOG_LEVEL", "WARNING"))
env = os.environ
os.environ["MAX_FILESIZE"] = str(int(int(os.environ.get("MESSAGE_SIZE_LIMIT")) * 0.66 / 1048576))
logging.basicConfig(stream=sys.stderr, level=env.get("LOG_LEVEL", "WARNING"))
db_flavor = os.environ.get("ROUNDCUBE_DB_FLAVOR", "sqlite")
# jinja context
context = {}
context.update(env)
context["MAX_FILESIZE"] = str(int(int(env.get("MESSAGE_SIZE_LIMIT", "50000000")) * 0.66 / 1048576))
db_flavor = env.get("ROUNDCUBE_DB_FLAVOR", "sqlite")
if db_flavor == "sqlite":
os.environ["DB_DSNW"] = "sqlite:////data/roundcube.db"
context["DB_DSNW"] = "sqlite:////data/roundcube.db"
elif db_flavor == "mysql":
os.environ["DB_DSNW"] = "mysql://%s:%s@%s/%s" % (
os.environ.get("ROUNDCUBE_DB_USER", "roundcube"),
os.environ.get("ROUNDCUBE_DB_PW"),
os.environ.get("ROUNDCUBE_DB_HOST", "database"),
os.environ.get("ROUNDCUBE_DB_NAME", "roundcube")
context["DB_DSNW"] = "mysql://%s:%s@%s/%s" % (
env.get("ROUNDCUBE_DB_USER", "roundcube"),
env.get("ROUNDCUBE_DB_PW"),
env.get("ROUNDCUBE_DB_HOST", "database"),
env.get("ROUNDCUBE_DB_NAME", "roundcube")
)
elif db_flavor == "postgresql":
os.environ["DB_DSNW"] = "pgsql://%s:%s@%s/%s" % (
os.environ.get("ROUNDCUBE_DB_USER", "roundcube"),
os.environ.get("ROUNDCUBE_DB_PW"),
os.environ.get("ROUNDCUBE_DB_HOST", "database"),
os.environ.get("ROUNDCUBE_DB_NAME", "roundcube")
context["DB_DSNW"] = "pgsql://%s:%s@%s/%s" % (
env.get("ROUNDCUBE_DB_USER", "roundcube"),
env.get("ROUNDCUBE_DB_PW"),
env.get("ROUNDCUBE_DB_HOST", "database"),
env.get("ROUNDCUBE_DB_NAME", "roundcube")
)
else:
print("Unknown ROUNDCUBE_DB_FLAVOR: %s", db_flavor)
print(f"Unknown ROUNDCUBE_DB_FLAVOR: {db_flavor}", file=sys.stderr)
exit(1)
conf.jinja("/php.ini", os.environ, "/usr/local/etc/php/conf.d/roundcube.ini")
# derive roundcube secret key
secret_key = env.get("SECRET_KEY")
if not secret_key:
try:
secret_key = open(env.get("SECRET_KEY_FILE"), "r").read().strip()
except Exception as exc:
print(f"Can't read SECRET_KEY from file: {exc}", file=sys.stderr)
exit(2)
# Create dirs, setup permissions
context['SECRET_KEY'] = hmac.new(bytearray(secret_key, 'utf-8'), bytearray('ROUNDCUBE_KEY', 'utf-8'), 'sha256').hexdigest()
# roundcube plugins
# (using "dict" because it is ordered and "set" is not)
plugins = dict((p, None) for p in env.get("ROUNDCUBE_PLUGINS", "").replace(" ", "").split(",") if p and os.path.isdir(os.path.join("/var/www/plugins", p)))
if plugins:
plugins["mailu"] = None
else:
plugins = dict((k, None) for k in ["archive", "zipdownload", "markasjunk", "managesieve", "enigma", "carddav", "mailu"])
context["PLUGINS"] = ",".join(f"'{p}'" for p in plugins)
# add overrides
context["INCLUDES"] = sorted(inc for inc in os.listdir("/overrides") if inc.endswith(".inc")) if os.path.isdir("/overrides") else []
# create config files
conf.jinja("/php.ini", context, "/usr/local/etc/php/conf.d/roundcube.ini")
conf.jinja("/config.inc.php", context, "/var/www/html/config/config.inc.php")
# create dirs
os.system("mkdir -p /data/gpg")
print("Initializing database")
try:
print("Initializing database")
result = subprocess.check_output(["/var/www/html/bin/initdb.sh", "--dir", "/var/www/html/SQL"],
stderr=subprocess.STDOUT)
print(result.decode())
except subprocess.CalledProcessError as e:
if "already exists" in e.stdout.decode():
except subprocess.CalledProcessError as exc:
err = exc.stdout.decode()
if "already exists" in err:
print("Already initialzed")
else:
print(e.stdout.decode())
quit(1)
print(err)
exit(3)
print("Upgrading database")
try:
print("Upgrading database")
subprocess.check_call(["/var/www/html/bin/update.sh", "--version=?", "-y"], stderr=subprocess.STDOUT)
except subprocess.CalledProcessError as e:
quit(1)
except subprocess.CalledProcessError as exc:
exit(4)
else:
print("Cleaning database")
try:
subprocess.check_call(["/var/www/html/bin/cleandb.sh"], stderr=subprocess.STDOUT)
except subprocess.CalledProcessError as exc:
exit(5)
# Setup database permissions
# setup permissions
os.system("chown -R www-data:www-data /data")
# Run apache
os.execv("/usr/local/bin/apache2-foreground", ["apache2-foreground"])
# clean env
[env.pop(key, None) for key in env.keys() if key == "SECRET_KEY" or key.startswith("ROUNDCUBE_")]
# run apache
os.execve("/usr/local/bin/apache2-foreground", ["apache2-foreground"], env)

Loading…
Cancel
Save