Compare commits
No commits in common. "master" and "v1.12.1" have entirely different histories.
|
|
@ -1,4 +0,0 @@
|
||||||
last 1 version
|
|
||||||
> 30%
|
|
||||||
not IE 11
|
|
||||||
not IE_Mob 11
|
|
||||||
6
.cmds
|
|
@ -6,7 +6,7 @@ yarn upgrade xxx@1.2.3
|
||||||
# transifex
|
# transifex
|
||||||
tx pull -a
|
tx pull -a
|
||||||
|
|
||||||
# dependencies
|
# dependencies
|
||||||
yarn outdated
|
yarn outdated
|
||||||
yarn upgrade-interactive --exact --latest
|
yarn upgrade-interactive --exact --latest
|
||||||
|
|
||||||
|
|
@ -15,5 +15,5 @@ webpack --color --watch
|
||||||
|
|
||||||
#
|
#
|
||||||
gpg --import x
|
gpg --import x
|
||||||
gpg --detach-sign --armor --openpgp -u 87DA4591 --passphrase ?? x
|
gpg --detach-sign --armor --openpgp -u 87DA4591 x
|
||||||
for ff in `ls ./build/dist/releases/**/**/*.zip | xargs`; do gpg --detach-sign --no-tty --yes --armor --openpgp -u 87DA4591 --passphrase ?? $ff; done
|
for ff in `ls *.zip`; do gpg --detach-sign --armor --openpgp -u 87DA4591 $ff; done
|
||||||
|
|
|
||||||
|
|
@ -1,31 +0,0 @@
|
||||||
FROM php:7.4-fpm
|
|
||||||
|
|
||||||
RUN apt-get update
|
|
||||||
|
|
||||||
RUN apt-get install -y \
|
|
||||||
git unzip wget zip curl mlocate \
|
|
||||||
libicu-dev libpcre3-dev libicu-dev \
|
|
||||||
build-essential chrpath libssl-dev \
|
|
||||||
libxft-dev libfreetype6 libfreetype6-dev \
|
|
||||||
libpng-dev libjpeg62-turbo-dev \
|
|
||||||
libfontconfig1 libfontconfig1-dev libzip-dev libldap2-dev
|
|
||||||
|
|
||||||
RUN pecl install xxtea-1.0.11 && \
|
|
||||||
docker-php-ext-enable xxtea
|
|
||||||
|
|
||||||
RUN docker-php-ext-configure intl && \
|
|
||||||
docker-php-ext-configure ldap && \
|
|
||||||
docker-php-ext-configure gd --with-freetype=/usr/include/ --with-jpeg=/usr/include/ && \
|
|
||||||
docker-php-ext-install opcache pdo_mysql zip intl gd ldap
|
|
||||||
|
|
||||||
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
|
|
||||||
|
|
||||||
RUN curl --location --output /usr/local/bin/phpunit https://phar.phpunit.de/phpunit.phar && chmod +x /usr/local/bin/phpunit
|
|
||||||
|
|
||||||
RUN apt-get -y autoremove && apt-get clean
|
|
||||||
|
|
||||||
RUN sed -i '/^;catch_workers_output/ccatch_workers_output = yes' '/usr/local/etc/php-fpm.d/www.conf'
|
|
||||||
|
|
||||||
EXPOSE 9000
|
|
||||||
|
|
||||||
CMD ["php-fpm"]
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
date.timezone = UTC
|
|
||||||
upload_max_filesize = 24M
|
|
||||||
post_max_size = 25M
|
|
||||||
|
|
||||||
# log_errors = On
|
|
||||||
# display_errors = On
|
|
||||||
# error_reporting = E_ALL
|
|
||||||
# error_log = /dev/stderr
|
|
||||||
0
.docker/dev/mail/setup.sh → .docker/mail/setup.sh
Normal file → Executable file
|
|
@ -1,3 +1,4 @@
|
||||||
|
|
||||||
server {
|
server {
|
||||||
listen 80 default;
|
listen 80 default;
|
||||||
listen 443 ssl;
|
listen 443 ssl;
|
||||||
0
.docker/dev/nginx/ssl.sh → .docker/nginx/ssl.sh
Executable file → Normal file
6
.docker/node/Dockerfile
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
FROM node:9.11.2-alpine
|
||||||
|
|
||||||
|
RUN apk add --no-cache git
|
||||||
|
RUN yarn global add gulp@3.9.1
|
||||||
|
|
||||||
|
CMD ["node", "--version"]
|
||||||
27
.docker/php/Dockerfile
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
FROM php:7.1-fpm
|
||||||
|
|
||||||
|
RUN apt-get update
|
||||||
|
|
||||||
|
RUN apt-get install -y \
|
||||||
|
git unzip wget zip curl mlocate \
|
||||||
|
libmcrypt-dev libicu-dev libpcre3-dev libicu-dev \
|
||||||
|
build-essential chrpath libssl-dev \
|
||||||
|
libxft-dev libfreetype6 libfreetype6-dev \
|
||||||
|
libpng-dev libjpeg62-turbo-dev \
|
||||||
|
libfontconfig1 libfontconfig1-dev libzip-dev
|
||||||
|
|
||||||
|
RUN docker-php-ext-configure intl && \
|
||||||
|
docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ && \
|
||||||
|
docker-php-ext-install opcache pdo_mysql mcrypt zip intl gd
|
||||||
|
|
||||||
|
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
|
||||||
|
|
||||||
|
RUN curl --location --output /usr/local/bin/phpunit https://phar.phpunit.de/phpunit.phar && chmod +x /usr/local/bin/phpunit
|
||||||
|
|
||||||
|
RUN apt-get -y autoremove && apt-get clean
|
||||||
|
|
||||||
|
RUN sed -i '/^;catch_workers_output/ccatch_workers_output = yes' '/usr/local/etc/php-fpm.d/www.conf'
|
||||||
|
|
||||||
|
EXPOSE 9000
|
||||||
|
|
||||||
|
CMD ["php-fpm"]
|
||||||
8
.docker/php/rainloop.ini
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
date.timezone = UTC
|
||||||
|
upload_max_filesize = 1G
|
||||||
|
post_max_size = 1G
|
||||||
|
|
||||||
|
# log_errors = On
|
||||||
|
# display_errors = On
|
||||||
|
# error_reporting = E_ALL
|
||||||
|
# error_log = /dev/stderr
|
||||||
|
|
@ -1,192 +0,0 @@
|
||||||
# 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.5-fpm-alpine AS final
|
|
||||||
|
|
||||||
LABEL org.label-schema.description="SnappyMail webmail client image using nginx, php-fpm on Alpine"
|
|
||||||
|
|
||||||
# Install dependencies such as nginx
|
|
||||||
RUN apk add --no-cache ca-certificates nginx supervisor bash
|
|
||||||
|
|
||||||
# Install PHP extensions
|
|
||||||
# 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
|
|
||||||
# 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;
|
|
||||||
|
|
||||||
USER root
|
|
||||||
WORKDIR /snappymail
|
|
||||||
VOLUME /var/lib/snappymail
|
|
||||||
EXPOSE 8888
|
|
||||||
EXPOSE 9000
|
|
||||||
ENTRYPOINT []
|
|
||||||
CMD ["/entrypoint.sh"]
|
|
||||||
|
|
@ -1,86 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
set -eu
|
|
||||||
|
|
||||||
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>/$UPLOAD_MAX_SIZE/g" /usr/local/etc/php-fpm.d/php-fpm.conf /etc/nginx/nginx.conf
|
|
||||||
sed -i "s/<MEMORY_LIMIT>/$MEMORY_LIMIT/g" /usr/local/etc/php-fpm.d/php-fpm.conf
|
|
||||||
|
|
||||||
# Secure cookies
|
|
||||||
if [ "${SECURE_COOKIES}" = 'true' ]; then
|
|
||||||
echo "[INFO] Secure cookies activated"
|
|
||||||
{
|
|
||||||
echo 'session.cookie_httponly = On';
|
|
||||||
echo 'session.cookie_secure = On';
|
|
||||||
echo 'session.use_only_cookies = On';
|
|
||||||
} > /usr/local/etc/php/conf.d/cookies.ini;
|
|
||||||
fi
|
|
||||||
|
|
||||||
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: $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
|
|
||||||
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
|
|
||||||
sed 's/^auth_syslog = .*/auth_syslog = Off/' -i $SNAPPYMAIL_CONFIG_FILE
|
|
||||||
|
|
||||||
(
|
|
||||||
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
|
|
||||||
|
|
||||||
wget -T 1 -qO- 'http://127.0.0.1:8888/' > /dev/null
|
|
||||||
echo "[INFO] Snappymail ready at http://localhost:8888/"
|
|
||||||
) &
|
|
||||||
|
|
||||||
# RUN !
|
|
||||||
exec /usr/bin/supervisord -c /supervisor.conf --pidfile /run/supervisord.pid
|
|
||||||
|
|
@ -1,108 +0,0 @@
|
||||||
worker_processes auto;
|
|
||||||
pid /tmp/nginx.pid;
|
|
||||||
|
|
||||||
events {
|
|
||||||
worker_connections 1024;
|
|
||||||
use epoll;
|
|
||||||
}
|
|
||||||
|
|
||||||
http {
|
|
||||||
include /etc/nginx/mime.types;
|
|
||||||
default_type application/octet-stream;
|
|
||||||
|
|
||||||
access_log off;
|
|
||||||
error_log /dev/stderr error;
|
|
||||||
|
|
||||||
sendfile on;
|
|
||||||
keepalive_timeout 15;
|
|
||||||
keepalive_disable msie6;
|
|
||||||
keepalive_requests 100;
|
|
||||||
tcp_nopush on;
|
|
||||||
tcp_nodelay on;
|
|
||||||
server_tokens off;
|
|
||||||
|
|
||||||
fastcgi_temp_path /tmp/fastcgi 1 2;
|
|
||||||
client_body_temp_path /tmp/client_body 1 2;
|
|
||||||
proxy_temp_path /tmp/proxy 1 2;
|
|
||||||
uwsgi_temp_path /tmp/uwsgi 1 2;
|
|
||||||
scgi_temp_path /tmp/scgi 1 2;
|
|
||||||
|
|
||||||
gzip on;
|
|
||||||
gzip_comp_level 5;
|
|
||||||
gzip_min_length 512;
|
|
||||||
gzip_buffers 4 8k;
|
|
||||||
gzip_proxied any;
|
|
||||||
gzip_vary on;
|
|
||||||
gzip_disable "msie6";
|
|
||||||
gzip_types
|
|
||||||
text/css
|
|
||||||
text/javascript
|
|
||||||
text/xml
|
|
||||||
text/plain
|
|
||||||
text/x-component
|
|
||||||
application/javascript
|
|
||||||
application/x-javascript
|
|
||||||
application/json
|
|
||||||
application/xml
|
|
||||||
application/rss+xml
|
|
||||||
application/vnd.ms-fontobject
|
|
||||||
font/truetype
|
|
||||||
font/opentype
|
|
||||||
image/svg+xml;
|
|
||||||
|
|
||||||
server {
|
|
||||||
listen 8888;
|
|
||||||
listen [::]:8888;
|
|
||||||
#listen [::]:8888 ipv6only=off;
|
|
||||||
root /snappymail;
|
|
||||||
index index.php;
|
|
||||||
charset utf-8;
|
|
||||||
|
|
||||||
client_max_body_size <UPLOAD_MAX_SIZE>;
|
|
||||||
|
|
||||||
location ^~ /data {
|
|
||||||
deny all;
|
|
||||||
}
|
|
||||||
|
|
||||||
location / {
|
|
||||||
try_files $uri $uri/ index.php;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Assets cache control
|
|
||||||
# --------------------------------------
|
|
||||||
location ~* \.(?:html|xml|json)$ {
|
|
||||||
expires -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
location ~* \.(?:css|js)$ {
|
|
||||||
expires 7d;
|
|
||||||
add_header Pragma public;
|
|
||||||
add_header Cache-Control "public";
|
|
||||||
}
|
|
||||||
|
|
||||||
location ~* \.(?:gif|jpe?g|png|ico|otf|eot|svg|ttf|woff|woff2)$ {
|
|
||||||
expires 30d;
|
|
||||||
log_not_found off;
|
|
||||||
add_header Pragma public;
|
|
||||||
add_header Cache-Control "public";
|
|
||||||
}
|
|
||||||
|
|
||||||
# PHP Backend
|
|
||||||
# --------------------------------------
|
|
||||||
location ~* \.php$ {
|
|
||||||
try_files $uri =404;
|
|
||||||
include fastcgi_params;
|
|
||||||
fastcgi_split_path_info ^(.+\.php)(/.*)$;
|
|
||||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
|
||||||
fastcgi_param PATH_INFO $fastcgi_path_info;
|
|
||||||
fastcgi_param HTTP_PROXY "";
|
|
||||||
fastcgi_index index.php;
|
|
||||||
fastcgi_pass 127.0.0.1:9000;
|
|
||||||
fastcgi_intercept_errors on;
|
|
||||||
fastcgi_request_buffering off;
|
|
||||||
fastcgi_param REMOTE_ADDR $http_x_real_ip;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,23 +0,0 @@
|
||||||
<?php
|
|
||||||
$stdIn = STDIN;
|
|
||||||
$stdOut = STDOUT;
|
|
||||||
|
|
||||||
fwrite($stdOut, "READY\n");
|
|
||||||
|
|
||||||
while(true) {
|
|
||||||
if (false == $line = trim(fgets($stdIn))) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$match = null;
|
|
||||||
if (preg_match('/eventname:(.*?) /', $line, $match)) {
|
|
||||||
if (in_array($match[1], ['PROCESS_STATE_EXITED', 'PROCESS_STATE_STOPPED', 'PROCESS_STATE_FATAL'])) {
|
|
||||||
exec('kill -15 '.file_get_contents('/run/supervisord.pid'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fwrite($stdOut, "RESULT 2\nOK");
|
|
||||||
|
|
||||||
sleep(1);
|
|
||||||
fwrite($stdOut, "READY\n");
|
|
||||||
}
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
<?php
|
|
||||||
define('APP_DATA_FOLDER_PATH', '/var/lib/snappymail/');
|
|
||||||
?>
|
|
||||||
|
|
@ -1,40 +0,0 @@
|
||||||
[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=root
|
|
||||||
numprocs=1
|
|
||||||
autostart=true
|
|
||||||
autorestart=false
|
|
||||||
startsecs=0
|
|
||||||
stdout_logfile=/dev/stdout
|
|
||||||
stdout_logfile_maxbytes=0
|
|
||||||
stderr_logfile=/dev/stderr
|
|
||||||
stderr_logfile_maxbytes=0
|
|
||||||
|
|
||||||
[program:php-fpm]
|
|
||||||
command=php-fpm -F
|
|
||||||
process_name=%(program_name)s_%(process_num)02d
|
|
||||||
user=root
|
|
||||||
numprocs=1
|
|
||||||
autostart=true
|
|
||||||
autorestart=false
|
|
||||||
startsecs=0
|
|
||||||
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=root
|
|
||||||
numprocs=1
|
|
||||||
events=PROCESS_STATE_EXITED,PROCESS_STATE_STOPPED,PROCESS_STATE_FATAL
|
|
||||||
autostart=true
|
|
||||||
autorestart=unexpected
|
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
[global]
|
|
||||||
daemonize = no
|
|
||||||
error_log = /dev/stderr
|
|
||||||
log_buffering = no
|
|
||||||
|
|
||||||
[default]
|
|
||||||
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 = /
|
|
||||||
pm.status_path = /status
|
|
||||||
php_admin_value[log_errors] = On
|
|
||||||
php_admin_value[expose_php] = Off
|
|
||||||
php_admin_value[display_errors] = Off
|
|
||||||
php_admin_value[date.timezone] = UTC
|
|
||||||
php_admin_value[post_max_size] = <UPLOAD_MAX_SIZE>
|
|
||||||
php_admin_value[upload_max_filesize] = <UPLOAD_MAX_SIZE>
|
|
||||||
php_admin_value[memory_limit] = <MEMORY_LIMIT>
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
#!/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"
|
|
||||||
|
|
@ -1,29 +0,0 @@
|
||||||
# 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
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
#!/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
|
|
||||||
5
.docker/tx/Dockerfile
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
FROM python:3.6-alpine
|
||||||
|
|
||||||
|
RUN pip install transifex-client
|
||||||
|
|
||||||
|
CMD ["tx", "--version"]
|
||||||
|
|
@ -1,2 +0,0 @@
|
||||||
/.git
|
|
||||||
/node_modules
|
|
||||||
|
|
@ -1,2 +0,0 @@
|
||||||
[*.php]
|
|
||||||
indent_style = tab
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
*.*
|
|
||||||
!/dev/**/*.js
|
|
||||||
!/tasks/**/*.js
|
|
||||||
!/*.js
|
|
||||||
343
.eslintrc.js
|
|
@ -1,64 +1,279 @@
|
||||||
module.exports = {
|
|
||||||
parser: 'babel-eslint',
|
module.exports = {
|
||||||
// extends: ['eslint:recommended', 'plugin:prettier/recommended'],
|
'extends': 'eslint:recommended',
|
||||||
extends: ['eslint:recommended'],
|
"parser": "babel-eslint",
|
||||||
parserOptions: {
|
'parserOptions': {
|
||||||
ecmaVersion: 11,
|
'ecmaVersion': 6,
|
||||||
sourceType: 'module'
|
'sourceType': 'module'
|
||||||
},
|
},
|
||||||
env: {
|
'env': {
|
||||||
node: true,
|
'node': true,
|
||||||
browser: true,
|
'commonjs': true,
|
||||||
es2020: true
|
'es6': true
|
||||||
},
|
},
|
||||||
globals: {
|
// 'plugins': ['compat'],
|
||||||
// SnappyMail
|
'globals': {
|
||||||
'rainloopI18N': "readonly",
|
'RL_COMMUNITY': true,
|
||||||
'rainloopTEMPLATES': "readonly",
|
'RL_ES6': true
|
||||||
'rl': "readonly",
|
},
|
||||||
'shortcuts': "readonly",
|
|
||||||
// '__APP_BOOT': "readonly",
|
// http://eslint.org/docs/rules/
|
||||||
// deb/boot.js
|
'rules': {
|
||||||
'progressJs': "readonly",
|
// plugins
|
||||||
// others
|
// 'compat/compat': 2,
|
||||||
'openpgp': "readonly",
|
|
||||||
'CKEDITOR': "readonly",
|
// errors
|
||||||
'Squire': "readonly",
|
'no-cond-assign': [2, 'always'],
|
||||||
'SquireUI': "readonly",
|
'no-console': 0,
|
||||||
// node_modules/knockout but dev/External/ko.js is used
|
'no-constant-condition': 2,
|
||||||
'ko': "readonly",
|
'no-control-regex': 2,
|
||||||
// vendors/routes/
|
'no-debugger': 2,
|
||||||
'hasher': "readonly",
|
'no-dupe-args': 2,
|
||||||
'Crossroads': "readonly",
|
'no-dupe-keys': 2,
|
||||||
// vendors/jua
|
'no-duplicate-case': 2,
|
||||||
'Jua': "readonly",
|
'no-empty': 2,
|
||||||
// vendors/bootstrap/bootstrap.native.js
|
'no-empty-character-class': 2,
|
||||||
'BSN': "readonly",
|
'no-ex-assign': 2,
|
||||||
// Mailvelope
|
'no-extra-boolean-cast': 2,
|
||||||
'mailvelope': "readonly",
|
// 'no-extra-parens': 2,
|
||||||
// Punycode
|
'no-extra-semi': 2,
|
||||||
'IDN': "readonly",
|
'no-func-assign': 2,
|
||||||
// Turndown
|
'no-inner-declarations': 2,
|
||||||
'TurndownService': "readonly",
|
'no-invalid-regexp': 2,
|
||||||
// Marked
|
'no-irregular-whitespace': 2,
|
||||||
'marked': "readonly"
|
'no-negated-in-lhs': 2,
|
||||||
},
|
'no-obj-calls': 2,
|
||||||
// http://eslint.org/docs/rules/
|
'no-prototype-builtins': 2,
|
||||||
rules: {
|
'no-regex-spaces': 2,
|
||||||
'no-cond-assign': 0,
|
'no-sparse-arrays': 2,
|
||||||
// plugins
|
'no-unexpected-multiline': 2,
|
||||||
'no-mixed-spaces-and-tabs': 'off',
|
'no-unreachable': 2,
|
||||||
'max-len': [
|
'no-unsafe-finally': 2,
|
||||||
'error',
|
'use-isnan': 2,
|
||||||
120,
|
// 'valid-jsdoc': [2, {
|
||||||
2,
|
// 'requireParamDescription': false,
|
||||||
{
|
// 'requireReturnDescription': false
|
||||||
ignoreComments: true,
|
// }],
|
||||||
ignoreUrls: true,
|
'valid-typeof': 2,
|
||||||
ignoreTrailingComments: true,
|
|
||||||
ignorePattern: '(^\\s*(const|let|var)\\s.+=\\s*require\\s*\\(|^import\\s.+\\sfrom\\s.+;$)'
|
// best practices
|
||||||
}
|
'accessor-pairs': 2,
|
||||||
],
|
'array-callback-return': 2,
|
||||||
'no-constant-condition': ["error", { "checkLoops": false }]
|
'block-scoped-var': 2,
|
||||||
}
|
// 'complexity': 2,
|
||||||
};
|
'consistent-return': 2,
|
||||||
|
'curly': 2,
|
||||||
|
'default-case': 2,
|
||||||
|
'dot-location': [2, 'property'],
|
||||||
|
'dot-notation': 2,
|
||||||
|
'eqeqeq': 2,
|
||||||
|
'guard-for-in': 2,
|
||||||
|
'no-alert': 2,
|
||||||
|
'no-caller': 2,
|
||||||
|
'no-case-declarations': 2,
|
||||||
|
'no-div-regex': 2,
|
||||||
|
'no-else-return': 2,
|
||||||
|
'no-empty-function': 2,
|
||||||
|
'no-empty-pattern': 2,
|
||||||
|
'no-eq-null': 2,
|
||||||
|
'no-eval': 2,
|
||||||
|
'no-extend-native': 2,
|
||||||
|
'no-extra-bind': 2,
|
||||||
|
'no-extra-label': 2,
|
||||||
|
'no-fallthrough': 2,
|
||||||
|
'no-floating-decimal': 2,
|
||||||
|
'no-implicit-coercion': [2, {'allow': ['!!', '+']}],
|
||||||
|
'no-implicit-globals': 2,
|
||||||
|
'no-implied-eval': 2,
|
||||||
|
'no-invalid-this': 2,
|
||||||
|
'no-iterator': 2,
|
||||||
|
'no-labels': 2,
|
||||||
|
'no-lone-blocks': 2,
|
||||||
|
'no-loop-func': 2,
|
||||||
|
// 'no-magic-numbers': [2, {
|
||||||
|
// 'ignore': [-1, 0, 1, 2, 10, 100],
|
||||||
|
// 'ignoreArrayIndexes': true
|
||||||
|
// }],
|
||||||
|
'no-multi-spaces': 2,
|
||||||
|
'no-multi-str': 2,
|
||||||
|
'no-native-reassign': 2,
|
||||||
|
'no-new': 2,
|
||||||
|
'no-new-func': 2,
|
||||||
|
'no-new-wrappers': 2,
|
||||||
|
'no-octal': 2,
|
||||||
|
'no-octal-escape': 2,
|
||||||
|
// 'no-param-reassign': 2,
|
||||||
|
'no-proto': 2,
|
||||||
|
'no-redeclare': 2,
|
||||||
|
'no-return-assign': 2,
|
||||||
|
'no-script-url': 2,
|
||||||
|
'no-self-assign': 2,
|
||||||
|
'no-self-compare': 2,
|
||||||
|
'no-sequences': 2,
|
||||||
|
'no-throw-literal': 2,
|
||||||
|
'no-unmodified-loop-condition': 2,
|
||||||
|
'no-unused-expressions': 2,
|
||||||
|
'no-unused-labels': 2,
|
||||||
|
'no-useless-call': 2,
|
||||||
|
'no-useless-concat': 2,
|
||||||
|
'no-useless-escape': 0,
|
||||||
|
'no-void': 2,
|
||||||
|
'no-warning-comments': 2,
|
||||||
|
'no-with': 2,
|
||||||
|
'radix': 2,
|
||||||
|
// 'vars-on-top': 2,
|
||||||
|
'wrap-iife': 2,
|
||||||
|
'yoda': [2, 'always'],
|
||||||
|
|
||||||
|
// strict mode
|
||||||
|
'strict': 2,
|
||||||
|
|
||||||
|
// variables
|
||||||
|
'init-declarations': 2,
|
||||||
|
'no-catch-shadow': 2,
|
||||||
|
'no-delete-var': 2,
|
||||||
|
'no-label-var': 2,
|
||||||
|
'no-restricted-globals': 2,
|
||||||
|
'no-shadow': 2,
|
||||||
|
'no-shadow-restricted-names': 2,
|
||||||
|
'no-undef': 2,
|
||||||
|
'no-undef-init': 2,
|
||||||
|
'no-undefined': 2,
|
||||||
|
'no-unused-vars': 2,
|
||||||
|
'no-use-before-define': 2,
|
||||||
|
|
||||||
|
// node.js and commonjs
|
||||||
|
'callback-return': 2,
|
||||||
|
// 'global-require': 2,
|
||||||
|
'handle-callback-err': 2,
|
||||||
|
// 'no-mixed-requires': 2,
|
||||||
|
'no-new-require': 2,
|
||||||
|
'no-path-concat': 2,
|
||||||
|
'no-process-env': 2,
|
||||||
|
'no-process-exit': 2,
|
||||||
|
'no-restricted-modules': 2,
|
||||||
|
// 'no-sync': 2,
|
||||||
|
|
||||||
|
// stylistic issues
|
||||||
|
'array-bracket-spacing': 2,
|
||||||
|
'block-spacing': [2, 'never'],
|
||||||
|
// 'brace-style': [2, 'allman'],
|
||||||
|
'camelcase': 2,
|
||||||
|
'comma-dangle': [2, 'never'],
|
||||||
|
'comma-spacing': 2,
|
||||||
|
'comma-style': 2,
|
||||||
|
'computed-property-spacing': 2,
|
||||||
|
'consistent-this': [2, 'self'],
|
||||||
|
'eol-last': 2,
|
||||||
|
'func-names': [2, 'never'],
|
||||||
|
// 'func-style': 2,
|
||||||
|
'id-blacklist': [2, 'x'],
|
||||||
|
'id-length': [2, {'min': 1, 'max': 50}],
|
||||||
|
'id-match': 2,
|
||||||
|
'indent': ['error', 'tab', {
|
||||||
|
'SwitchCase': 1,
|
||||||
|
'VariableDeclarator': 1
|
||||||
|
}],
|
||||||
|
'jsx-quotes': 2,
|
||||||
|
'key-spacing': 2,
|
||||||
|
'keyword-spacing': 2,
|
||||||
|
'linebreak-style': [2, 'unix'],
|
||||||
|
// 'lines-around-comment': 2,
|
||||||
|
'max-depth': [2, 10],
|
||||||
|
'max-len': [2, 200],
|
||||||
|
// 'max-lines': 2,
|
||||||
|
'max-nested-callbacks': [2, 5],
|
||||||
|
// 'max-params': 2,
|
||||||
|
// 'max-statements': [2, {'max': 10}, {'ignoreTopLevelFunctions': true}],
|
||||||
|
'max-statements-per-line': 2,
|
||||||
|
'new-cap': 2,
|
||||||
|
'new-parens': 2,
|
||||||
|
// 'newline-after-var': 2,
|
||||||
|
// 'newline-before-return': 2,
|
||||||
|
// 'newline-per-chained-call': 2,
|
||||||
|
'no-array-constructor': 2,
|
||||||
|
'no-bitwise': 2,
|
||||||
|
'no-continue': 2,
|
||||||
|
// 'no-inline-comments': 2,
|
||||||
|
// 'no-lonely-if': 2,
|
||||||
|
// 'no-mixed-operators': 2,
|
||||||
|
'no-mixed-spaces-and-tabs': 2,
|
||||||
|
'no-multiple-empty-lines': [2, {
|
||||||
|
"max": 1,
|
||||||
|
"maxEOF": 1,
|
||||||
|
"maxBOF": 1
|
||||||
|
}],
|
||||||
|
// 'no-negated-condition': 2,
|
||||||
|
// 'no-nested-ternary': 2,
|
||||||
|
'no-new-object': 2,
|
||||||
|
'no-plusplus': [2, {
|
||||||
|
'allowForLoopAfterthoughts': true
|
||||||
|
}],
|
||||||
|
'no-restricted-syntax': 2,
|
||||||
|
'no-spaced-func': 2,
|
||||||
|
'no-ternary': 0,
|
||||||
|
'no-trailing-spaces': 2, // disallow trailing whitespace at the end of lines
|
||||||
|
// 'no-underscore-dangle': 2, // disallow dangling underscores in identifiers
|
||||||
|
'no-unneeded-ternary': 2, // disallow ternary operators when simpler alternatives exist
|
||||||
|
'no-whitespace-before-property': 2,
|
||||||
|
// 'object-curly-newline': 2,
|
||||||
|
'object-curly-spacing': [2, 'never'],
|
||||||
|
'object-property-newline': [2, {'allowMultiplePropertiesPerLine': true}],
|
||||||
|
// 'one-var': [2, {
|
||||||
|
// 'var': 'always',
|
||||||
|
// 'let': 'always',
|
||||||
|
// 'const': 'always'
|
||||||
|
// }],
|
||||||
|
'one-var-declaration-per-line': [2, 'always'],
|
||||||
|
'operator-assignment': 2,
|
||||||
|
'operator-linebreak': [2, 'after'],
|
||||||
|
// 'padded-blocks': [2, 'never'],
|
||||||
|
// 'quote-props': [2, 'as-needed'],
|
||||||
|
'quotes': [2, 'single'],
|
||||||
|
'require-jsdoc': 2,
|
||||||
|
'semi': [2, 'always'],
|
||||||
|
'semi-spacing': 2,
|
||||||
|
// 'sort-vars': 2,
|
||||||
|
'space-before-blocks': 2,
|
||||||
|
'space-before-function-paren': [2, 'never'],
|
||||||
|
'space-in-parens': 2,
|
||||||
|
'space-infix-ops': 2,
|
||||||
|
'space-unary-ops': 2,
|
||||||
|
'spaced-comment': 2,
|
||||||
|
'unicode-bom': [2, 'never'],
|
||||||
|
'wrap-regex': 2,
|
||||||
|
|
||||||
|
// es6
|
||||||
|
'arrow-body-style': [2, 'as-needed'],
|
||||||
|
'arrow-parens': 2,
|
||||||
|
'arrow-spacing': 2,
|
||||||
|
'constructor-super': 2,
|
||||||
|
'generator-star-spacing': 2,
|
||||||
|
'no-class-assign': 2,
|
||||||
|
'no-confusing-arrow': [2, {'allowParens': true}],
|
||||||
|
'no-const-assign': 2,
|
||||||
|
'no-dupe-class-members': 2,
|
||||||
|
'no-duplicate-imports': 2,
|
||||||
|
'no-new-symbol': 2,
|
||||||
|
'no-restricted-imports': 2,
|
||||||
|
'no-this-before-super': 2,
|
||||||
|
'no-useless-computed-key': 2,
|
||||||
|
'no-useless-constructor': 2,
|
||||||
|
'no-useless-rename': 2,
|
||||||
|
'no-var': 2,
|
||||||
|
// 'object-shorthand': 2,
|
||||||
|
'prefer-arrow-callback': 2,
|
||||||
|
'prefer-const': 2,
|
||||||
|
// 'prefer-reflect': 2,
|
||||||
|
|
||||||
|
'prefer-rest-params': 2,
|
||||||
|
'prefer-spread': 2,
|
||||||
|
|
||||||
|
// 'prefer-template': 2,
|
||||||
|
'require-yield': 2,
|
||||||
|
'rest-spread-spacing': 2,
|
||||||
|
'sort-imports': 0, // off
|
||||||
|
'template-curly-spacing': 2,
|
||||||
|
'yield-star-spacing': 2
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
|
||||||
2
.github/FUNDING.yml
vendored
|
|
@ -1,2 +0,0 @@
|
||||||
github: the-djmaze
|
|
||||||
custom: ["https://www.paypal.me/thedjmaze", "https://snappymail.eu"]
|
|
||||||
2
.github/ISSUE_TEMPLATE.md
vendored
|
|
@ -1,5 +1,5 @@
|
||||||
|
|
||||||
**SnappyMail version, browser, browser version:**
|
**RainLoop version, browser, OS:**
|
||||||
|
|
||||||
**Expected behavior and actual behavior:**
|
**Expected behavior and actual behavior:**
|
||||||
|
|
||||||
|
|
|
||||||
38
.github/ISSUE_TEMPLATE/bug_report.md
vendored
|
|
@ -1,38 +0,0 @@
|
||||||
---
|
|
||||||
name: Bug report
|
|
||||||
about: Create a report to help us improve
|
|
||||||
title: ''
|
|
||||||
labels: ''
|
|
||||||
assignees: ''
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Describe the bug**
|
|
||||||
A clear and concise description of what the bug is.
|
|
||||||
|
|
||||||
**To Reproduce**
|
|
||||||
Steps to reproduce the behavior:
|
|
||||||
1. Go to '...'
|
|
||||||
2. Click on '....'
|
|
||||||
3. Scroll down to '....'
|
|
||||||
4. See error
|
|
||||||
|
|
||||||
**Expected behavior**
|
|
||||||
A clear and concise description of what you expected to happen.
|
|
||||||
|
|
||||||
**Screenshots**
|
|
||||||
If applicable, add screenshots to help explain your problem.
|
|
||||||
|
|
||||||
**Please complete the following information:**
|
|
||||||
- Browser: [e.g. chromium 100, firefox 100, safari 14, mobile]
|
|
||||||
- IMAP daemon: [e.g. courier, dovecot]
|
|
||||||
- PHP version:
|
|
||||||
- SnappyMail Version:
|
|
||||||
- Mode: [e.g. standalone, nextcloud, cyberpanel, docker]
|
|
||||||
|
|
||||||
**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.
|
|
||||||
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
|
|
@ -1,20 +0,0 @@
|
||||||
---
|
|
||||||
name: Feature request
|
|
||||||
about: Suggest an idea for this project
|
|
||||||
title: ''
|
|
||||||
labels: ''
|
|
||||||
assignees: ''
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Is your feature request related to a problem? Please describe.**
|
|
||||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
|
||||||
|
|
||||||
**Describe the solution you'd like**
|
|
||||||
A clear and concise description of what you want to happen.
|
|
||||||
|
|
||||||
**Describe alternatives you've considered**
|
|
||||||
A clear and concise description of any alternative solutions or features you've considered.
|
|
||||||
|
|
||||||
**Additional context**
|
|
||||||
Add any other context or screenshots about the feature request here.
|
|
||||||
93
.github/workflows/docker-pr.yml
vendored
|
|
@ -1,93 +0,0 @@
|
||||||
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
|
|
||||||
117
.github/workflows/docker.yml
vendored
|
|
@ -1,117 +0,0 @@
|
||||||
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
|
|
||||||
43
.gitignore
vendored
|
|
@ -1,32 +1,31 @@
|
||||||
*.bak
|
/.idea
|
||||||
*.old
|
/.vscode
|
||||||
/api.php
|
/api.php
|
||||||
/*.log
|
/error.log
|
||||||
/snappymail/v/0.0.0/static/*
|
/nbproject
|
||||||
|
/npm-debug.log
|
||||||
|
/yarn-error.log
|
||||||
|
/rainloop.sublime-project
|
||||||
|
/rainloop.sublime-workspace
|
||||||
|
/rainloop/v/0.0.0/static/*
|
||||||
|
/rainloop/v/0.0.0/app/localization/moment/*
|
||||||
|
!/rainloop/v/0.0.0/app/localization/moment/.gitempty
|
||||||
|
/tests/e2e/configuration.js
|
||||||
|
/tests/e2e/output/*
|
||||||
|
!/tests/e2e/output/.gitempty
|
||||||
|
/vendors/.*
|
||||||
/node_modules
|
/node_modules
|
||||||
/build/local
|
/build/local
|
||||||
/build/dist
|
/build/dist
|
||||||
/build/tmp
|
/build/tmp
|
||||||
/build/docker
|
/build/docker
|
||||||
/.docker/dev/.cache
|
/.docker/.cache
|
||||||
/.docker/dev/mail/config
|
/.docker/mail/config
|
||||||
/.docker/dev/nginx/ssl/*
|
/.docker/nginx/ssl/*
|
||||||
!/.docker/dev/nginx/ssl/.gitempty
|
!/.docker/nginx/ssl/.gitempty
|
||||||
/.docker/release/snappymail-*.zip
|
|
||||||
/dist
|
/dist
|
||||||
/data
|
/data
|
||||||
|
.DS_Store
|
||||||
|
/tests/fix.php
|
||||||
/MULTIPLY
|
/MULTIPLY
|
||||||
/include.php
|
/include.php
|
||||||
/issues
|
|
||||||
.idea/
|
|
||||||
.env
|
|
||||||
/test
|
|
||||||
/public_html
|
|
||||||
/vendors/knockout/spec
|
|
||||||
/vendors/openpgp-5
|
|
||||||
!/vendors/openpgp-5/dist
|
|
||||||
/vendors/squire2
|
|
||||||
!/vendors/squire2/dist
|
|
||||||
/vendors/vanillaqr.js/
|
|
||||||
/integrations/nextcloud/rainloop
|
|
||||||
/integrations/owncloud/rainloop
|
|
||||||
|
|
|
||||||
7
.gitmodules
vendored
|
|
@ -1,7 +0,0 @@
|
||||||
[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
|
|
||||||
51
.htaccess
|
|
@ -1,51 +0,0 @@
|
||||||
<FilesMatch "index\.php">
|
|
||||||
AcceptPathInfo On
|
|
||||||
</FilesMatch>
|
|
||||||
|
|
||||||
<IfModule mod_rewrite.c>
|
|
||||||
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]
|
|
||||||
</IfModule>
|
|
||||||
|
|
||||||
<IfModule mod_expires.c>
|
|
||||||
ExpiresActive On
|
|
||||||
ExpiresByType text/css A15768000
|
|
||||||
ExpiresByType text/html A15768000
|
|
||||||
ExpiresByType application/javascript A15768000
|
|
||||||
ExpiresByType image/gif A15768000
|
|
||||||
ExpiresByType image/jpeg A15768000
|
|
||||||
ExpiresByType image/png A15768000
|
|
||||||
ExpiresByType image/svg+xml A15768000
|
|
||||||
ExpiresByType image/webp A15768000
|
|
||||||
ExpiresByType image/vnd.microsoft.icon A15768000
|
|
||||||
ExpiresByType font/woff A15768000
|
|
||||||
ExpiresByType font/woff2 A15768000
|
|
||||||
</IfModule>
|
|
||||||
|
|
||||||
<IfModule mod_headers.c>
|
|
||||||
# Header set Cache-Control "public, max-age=31536000"
|
|
||||||
# Header set Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; img-src 'self' data:; style-src 'self' 'unsafe-inline'"
|
|
||||||
# Header set Referrer-Policy "no-referrer"
|
|
||||||
# Header set Strict-Transport-Security "max-age=31536000"
|
|
||||||
Header set imagetoolbar "no"
|
|
||||||
# Header set X-Content-Type-Options "nosniff"
|
|
||||||
# Header set X-XSS-Protection "1; mode=block"
|
|
||||||
Header set Service-Worker-Allowed "/"
|
|
||||||
|
|
||||||
# Google FLoC
|
|
||||||
# Header set Permissions-Policy "interest-cohort=()"
|
|
||||||
</IfModule>
|
|
||||||
|
|
||||||
#<IfModule mod_brotli.c>
|
|
||||||
# AddOutputFilterByType BROTLI_COMPRESS text/html text/plain text/xml text/css text/javascript application/javascript
|
|
||||||
#</IfModule>
|
|
||||||
|
|
||||||
<IfModule mod_deflate.c>
|
|
||||||
AddOutputFilterByType DEFLATE text/css text/html text/plain text/xml application/xml text/javascript application/javascript
|
|
||||||
AddOutputFilterByType DEFLATE font/opentype font/otf font/ttf font/woff
|
|
||||||
</IfModule>
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
*.*
|
|
||||||
!/dev/**/*.js
|
|
||||||
!/tasks/**/*.js
|
|
||||||
!/*.js
|
|
||||||
26
.prettierrc
|
|
@ -1,26 +0,0 @@
|
||||||
{
|
|
||||||
"printWidth": 120,
|
|
||||||
"semi": true,
|
|
||||||
"singleQuote": true,
|
|
||||||
"useTabs": true,
|
|
||||||
"bracketSpacing": true,
|
|
||||||
"trailingComma": "none",
|
|
||||||
"arrowParens": "always",
|
|
||||||
"endOfLine": "lf",
|
|
||||||
"quoteProps": "preserve",
|
|
||||||
"overrides": [
|
|
||||||
{
|
|
||||||
"files": "*.js",
|
|
||||||
"options": {
|
|
||||||
"parser": "babel"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"files": "*.jsx",
|
|
||||||
"options": {
|
|
||||||
"parser": "babel"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
13
.travis.yml
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
language: php
|
||||||
|
php:
|
||||||
|
- '5.4'
|
||||||
|
- '5.5'
|
||||||
|
- '5.6'
|
||||||
|
# - '7.0'
|
||||||
|
# - '7.1'
|
||||||
|
#before_script:
|
||||||
|
# - sudo apt-get install -y build-essential libssl-dev
|
||||||
|
# - curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.31.1/install.sh | bash
|
||||||
|
# - nvm install 4.4.5
|
||||||
|
# - nvm use 4.4.5
|
||||||
|
# - npm install -g eslint babel-eslint
|
||||||
15
.tx/config
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
[main]
|
||||||
|
host = https://www.transifex.com
|
||||||
|
minimum_perc = 60
|
||||||
|
type = YAML
|
||||||
|
|
||||||
|
[rainloop-webmail.rainloop-webmail]
|
||||||
|
file_filter = rainloop/v/0.0.0/app/localization/webmail/<lang>.yml
|
||||||
|
source_file = rainloop/v/0.0.0/app/localization/webmail/_source.en.yml
|
||||||
|
source_lang = en
|
||||||
|
|
||||||
|
[rainloop-webmail.rainloop-admin]
|
||||||
|
file_filter = rainloop/v/0.0.0/app/localization/admin/<lang>.yml
|
||||||
|
source_file = rainloop/v/0.0.0/app/localization/admin/_source.en.yml
|
||||||
|
source_lang = en
|
||||||
|
|
||||||
2422
CHANGELOG.md
|
|
@ -1,130 +1,74 @@
|
||||||
|
|
||||||
# Contributor Covenant Code of Conduct
|
# Contributor Covenant Code of Conduct
|
||||||
|
|
||||||
## Our Pledge
|
## Our Pledge
|
||||||
|
|
||||||
We as members, contributors, and leaders pledge to make participation in our
|
In the interest of fostering an open and welcoming environment, we as
|
||||||
community a harassment-free experience for everyone, regardless of age, body
|
contributors and maintainers pledge to making participation in our project and
|
||||||
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
our community a harassment-free experience for everyone, regardless of age, body
|
||||||
identity and expression, level of experience, education, socio-economic status,
|
size, disability, ethnicity, gender identity and expression, level of experience,
|
||||||
nationality, personal appearance, race, religion, or sexual identity
|
nationality, personal appearance, race, religion, or sexual identity and
|
||||||
and orientation.
|
orientation.
|
||||||
|
|
||||||
We pledge to act and interact in ways that contribute to an open, welcoming,
|
|
||||||
diverse, inclusive, and healthy community.
|
|
||||||
|
|
||||||
## Our Standards
|
## Our Standards
|
||||||
|
|
||||||
Examples of behavior that contributes to a positive environment for our
|
Examples of behavior that contributes to creating a positive environment
|
||||||
community include:
|
include:
|
||||||
|
|
||||||
* Demonstrating empathy and kindness toward other people
|
* Using welcoming and inclusive language
|
||||||
* Being respectful of differing opinions, viewpoints, and experiences
|
* Being respectful of differing viewpoints and experiences
|
||||||
* Giving and gracefully accepting constructive feedback
|
* Gracefully accepting constructive criticism
|
||||||
* Accepting responsibility and apologizing to those affected by our mistakes,
|
* Focusing on what is best for the community
|
||||||
and learning from the experience
|
* Showing empathy towards other community members
|
||||||
* Focusing on what is best not just for us as individuals, but for the
|
|
||||||
overall community
|
|
||||||
|
|
||||||
Examples of unacceptable behavior include:
|
Examples of unacceptable behavior by participants include:
|
||||||
|
|
||||||
* The use of sexualized language or imagery, and sexual attention or
|
* The use of sexualized language or imagery and unwelcome sexual attention or
|
||||||
advances of any kind
|
advances
|
||||||
* Trolling, insulting or derogatory comments, and personal or political attacks
|
* Trolling, insulting/derogatory comments, and personal or political attacks
|
||||||
* Public or private harassment
|
* Public or private harassment
|
||||||
* Publishing others' private information, such as a physical or email
|
* Publishing others' private information, such as a physical or electronic
|
||||||
address, without their explicit permission
|
address, without explicit permission
|
||||||
* Other conduct which could reasonably be considered inappropriate in a
|
* Other conduct which could reasonably be considered inappropriate in a
|
||||||
professional setting
|
professional setting
|
||||||
|
|
||||||
## Enforcement Responsibilities
|
## Our Responsibilities
|
||||||
|
|
||||||
Community leaders are responsible for clarifying and enforcing our standards of
|
Project maintainers are responsible for clarifying the standards of acceptable
|
||||||
acceptable behavior and will take appropriate and fair corrective action in
|
behavior and are expected to take appropriate and fair corrective action in
|
||||||
response to any behavior that they deem inappropriate, threatening, offensive,
|
response to any instances of unacceptable behavior.
|
||||||
or harmful.
|
|
||||||
|
|
||||||
Community leaders have the right and responsibility to remove, edit, or reject
|
Project maintainers have the right and responsibility to remove, edit, or
|
||||||
comments, commits, code, wiki edits, issues, and other contributions that are
|
reject comments, commits, code, wiki edits, issues, and other contributions
|
||||||
not aligned to this Code of Conduct, and will communicate reasons for moderation
|
that are not aligned to this Code of Conduct, or to ban temporarily or
|
||||||
decisions when appropriate.
|
permanently any contributor for other behaviors that they deem inappropriate,
|
||||||
|
threatening, offensive, or harmful.
|
||||||
|
|
||||||
## Scope
|
## Scope
|
||||||
|
|
||||||
This Code of Conduct applies within all community spaces, and also applies when
|
This Code of Conduct applies both within project spaces and in public spaces
|
||||||
an individual is officially representing the community in public spaces.
|
when an individual is representing the project or its community. Examples of
|
||||||
Examples of representing our community include using an official e-mail address,
|
representing a project or community include using an official project e-mail
|
||||||
posting via an official social media account, or acting as an appointed
|
address, posting via an official social media account, or acting as an appointed
|
||||||
representative at an online or offline event.
|
representative at an online or offline event. Representation of a project may be
|
||||||
|
further defined and clarified by project maintainers.
|
||||||
|
|
||||||
## Enforcement
|
## Enforcement
|
||||||
|
|
||||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||||
reported to the community leaders responsible for enforcement at
|
reported by contacting the project team at support@rainloop.net. All
|
||||||
[support@snappymail.eu](support@snappymail.eu).
|
complaints will be reviewed and investigated and will result in a response that
|
||||||
All complaints will be reviewed and investigated promptly and fairly.
|
is deemed necessary and appropriate to the circumstances. The project team is
|
||||||
|
obligated to maintain confidentiality with regard to the reporter of an incident.
|
||||||
|
Further details of specific enforcement policies may be posted separately.
|
||||||
|
|
||||||
All community leaders are obligated to respect the privacy and security of the
|
Project maintainers who do not follow or enforce the Code of Conduct in good
|
||||||
reporter of any incident.
|
faith may face temporary or permanent repercussions as determined by other
|
||||||
|
members of the project's leadership.
|
||||||
## Enforcement Guidelines
|
|
||||||
|
|
||||||
Community leaders will follow these Community Impact Guidelines in determining
|
|
||||||
the consequences for any action they deem in violation of this Code of Conduct:
|
|
||||||
|
|
||||||
### 1. Correction
|
|
||||||
|
|
||||||
**Community Impact**: Use of inappropriate language or other behavior deemed
|
|
||||||
unprofessional or unwelcome in the community.
|
|
||||||
|
|
||||||
**Consequence**: A private, written warning from community leaders, providing
|
|
||||||
clarity around the nature of the violation and an explanation of why the
|
|
||||||
behavior was inappropriate. A public apology may be requested.
|
|
||||||
|
|
||||||
### 2. Warning
|
|
||||||
|
|
||||||
**Community Impact**: A violation through a single incident or series
|
|
||||||
of actions.
|
|
||||||
|
|
||||||
**Consequence**: A warning with consequences for continued behavior. No
|
|
||||||
interaction with the people involved, including unsolicited interaction with
|
|
||||||
those enforcing the Code of Conduct, for a specified period of time. This
|
|
||||||
includes avoiding interactions in community spaces as well as external channels
|
|
||||||
like social media. Violating these terms may lead to a temporary or
|
|
||||||
permanent ban.
|
|
||||||
|
|
||||||
### 3. Temporary Ban
|
|
||||||
|
|
||||||
**Community Impact**: A serious violation of community standards, including
|
|
||||||
sustained inappropriate behavior.
|
|
||||||
|
|
||||||
**Consequence**: A temporary ban from any sort of interaction or public
|
|
||||||
communication with the community for a specified period of time. No public or
|
|
||||||
private interaction with the people involved, including unsolicited interaction
|
|
||||||
with those enforcing the Code of Conduct, is allowed during this period.
|
|
||||||
Violating these terms may lead to a permanent ban.
|
|
||||||
|
|
||||||
### 4. Permanent Ban
|
|
||||||
|
|
||||||
**Community Impact**: Demonstrating a pattern of violation of community
|
|
||||||
standards, including sustained inappropriate behavior, harassment of an
|
|
||||||
individual, or aggression toward or disparagement of classes of individuals.
|
|
||||||
|
|
||||||
**Consequence**: A permanent ban from any sort of public interaction within
|
|
||||||
the community.
|
|
||||||
|
|
||||||
## Attribution
|
## Attribution
|
||||||
|
|
||||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
||||||
version 2.0, available at
|
available at [http://contributor-covenant.org/version/1/4][version]
|
||||||
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
|
|
||||||
|
|
||||||
Community Impact Guidelines were inspired by [Mozilla's code of conduct
|
|
||||||
enforcement ladder](https://github.com/mozilla/diversity).
|
|
||||||
|
|
||||||
[homepage]: https://www.contributor-covenant.org
|
|
||||||
|
|
||||||
For answers to common questions about this code of conduct, see the FAQ at
|
|
||||||
https://www.contributor-covenant.org/faq. Translations are available at
|
|
||||||
https://www.contributor-covenant.org/translations.
|
|
||||||
|
|
||||||
|
[homepage]: http://contributor-covenant.org
|
||||||
|
[version]: http://contributor-covenant.org/version/1/4/
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
**Thanks for contributing to SnappyMail Webmail!**
|
**Thanks for contributing to RainLoop Webmail!**
|
||||||
|
|
||||||
1. Fork the repo, do work in a feature branch.
|
1. Fork the repo, do work in a feature branch.
|
||||||
2. Issue a pull request.
|
2. Issue a pull request.
|
||||||
|
|
@ -7,15 +7,14 @@
|
||||||
|
|
||||||
**Getting started**
|
**Getting started**
|
||||||
|
|
||||||
1. Install PHP
|
1. Install node.js - `https://nodejs.org/download/`
|
||||||
2. Install node.js - `https://nodejs.org/download/`
|
2. Install yarn - `https://yarnpkg.com/en/docs/install`
|
||||||
3. Install yarn - `https://yarnpkg.com/en/docs/install`
|
3. Install gulp - `npm install gulp -g`
|
||||||
4. Install gulp - `npm install gulp -g`
|
4. Fork rainloop - `https://github.com/RainLoop/rainloop-webmail/issues/new#fork-destination-box`
|
||||||
5. Fork snappymail from https://github.com/the-djmaze/snappymail
|
5. Clone rainloop - `git clone git@github.com:USERNAME/rainloop-webmail.git rainloop`
|
||||||
6. Clone snappymail - `git clone git@github.com:USERNAME/snappymail.git snappymail`
|
6. `cd rainloop`
|
||||||
7. `cd snappymail`
|
7. Install install all dependencies - `yarn install`
|
||||||
8. Install all dependencies - `yarn install`
|
8. Run gulp - `gulp`
|
||||||
9. Run gulp - `gulp`
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -29,19 +28,8 @@
|
||||||
**Editing HTML Template Files**
|
**Editing HTML Template Files**
|
||||||
|
|
||||||
1. Edit data/\_data_/\_default_/configs/application.ini
|
1. Edit data/\_data_/\_default_/configs/application.ini
|
||||||
2. Set `[cache] system_data` to Off
|
2. Set 'cache_system_data' to Off
|
||||||
|
|
||||||
**Release**
|
|
||||||
|
|
||||||
1. Install gzip
|
|
||||||
2. Install brotli
|
|
||||||
3. php release.php
|
|
||||||
|
|
||||||
Options:
|
|
||||||
* `php release.php --aur` = Build Arch Linux package
|
|
||||||
* `php release.php --docker` = Build Docker instance
|
|
||||||
* `php release.php --plugins` = Build plugins
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
If you have any questions, open an issue or email support@snappymail.eu.
|
If you have any questions, open an issue or email support@rainloop.net.
|
||||||
|
|
|
||||||
2
LICENSE
|
|
@ -658,4 +658,4 @@ specific requirements.
|
||||||
You should also get your employer (if you work as a programmer) or school,
|
You should also get your employer (if you work as a programmer) or school,
|
||||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||||
For more information on this, and how to apply and follow the GNU AGPL, see
|
For more information on this, and how to apply and follow the GNU AGPL, see
|
||||||
<http://www.gnu.org/licenses/>.
|
<http://www.gnu.org/licenses/>.
|
||||||
60
Makefile
|
|
@ -1,76 +1,64 @@
|
||||||
#!make
|
#!make
|
||||||
|
|
||||||
rebuild: _down
|
rebuild: _down
|
||||||
docker compose build --no-cache
|
docker-compose build --no-cache
|
||||||
|
|
||||||
up: _up status
|
up: _up status
|
||||||
_up:
|
_up:
|
||||||
docker compose up -d
|
docker-compose up -d
|
||||||
|
|
||||||
stop: _stop status
|
stop: _stop status
|
||||||
_stop:
|
_stop:
|
||||||
docker compose stop
|
docker-compose stop
|
||||||
|
|
||||||
down: _down status
|
down: _down status
|
||||||
_down:
|
_down:
|
||||||
docker compose down
|
docker-compose down
|
||||||
|
|
||||||
restart: _stop _up status
|
restart: _stop _up status
|
||||||
|
|
||||||
status:
|
status:
|
||||||
@docker compose ps
|
@docker-compose ps
|
||||||
|
|
||||||
tx:
|
tx:
|
||||||
@docker compose run --no-deps --rm tx tx pull -a -s -f -d
|
@docker-compose run --no-deps --rm tx tx pull -a -s -f -d
|
||||||
|
|
||||||
console-node:
|
console-node:
|
||||||
@docker compose run --no-deps --rm node sh
|
@docker-compose run --no-deps --rm node sh
|
||||||
console-tx:
|
console-tx:
|
||||||
@docker compose run --no-deps --rm tx sh
|
@docker-compose run --no-deps --rm tx sh
|
||||||
console-php:
|
console-php:
|
||||||
@docker compose exec php sh
|
@docker-compose exec php sh
|
||||||
console: console-node
|
console: console-node
|
||||||
|
|
||||||
logs:
|
logs:
|
||||||
@docker compose logs --tail=100 -f
|
@docker-compose logs --tail=100 -f
|
||||||
logs-db:
|
logs-db:
|
||||||
@docker compose logs --tail=100 -f db
|
@docker-compose logs --tail=100 -f db
|
||||||
logs-php:
|
logs-php:
|
||||||
@docker compose logs --tail=100 -f php
|
@docker-compose logs --tail=100 -f php
|
||||||
logs-node:
|
logs-node:
|
||||||
@docker compose logs --tail=100 -f node
|
@docker-compose logs --tail=100 -f node
|
||||||
logs-nginx:
|
logs-nginx:
|
||||||
@docker compose logs --tail=100 -f nginx
|
@docker-compose logs --tail=100 -f nginx
|
||||||
logs-mail:
|
logs-mail:
|
||||||
@docker compose logs --tail=100 -f mail
|
@docker-compose logs --tail=100 -f mail
|
||||||
logs-tx:
|
logs-tx:
|
||||||
@docker compose logs --tail=100 -f tx
|
@docker-compose logs --tail=100 -f tx
|
||||||
|
|
||||||
rl-lint:
|
rl-lint:
|
||||||
@docker compose run --no-deps --rm node gulp lint
|
@docker-compose run --no-deps --rm node gulp lint
|
||||||
rl-dev:
|
rl-dev:
|
||||||
@docker compose run --no-deps --rm node npm run watch-js
|
@docker-compose run --no-deps --rm node gulp
|
||||||
rl-compile:
|
rl-watch:
|
||||||
@docker compose run --no-deps --rm node gulp build
|
@docker-compose run --no-deps --rm node gulp watch
|
||||||
rl-compile-with-source:
|
|
||||||
@docker compose run --no-deps --rm node gulp build --source
|
|
||||||
rl-watch-css:
|
|
||||||
@docker compose run --no-deps --rm node npm run watch-css
|
|
||||||
rl-watch-js:
|
|
||||||
@docker compose run --no-deps --rm node npm run watch-js
|
|
||||||
|
|
||||||
rl-build:
|
rl-build:
|
||||||
@docker compose run --no-deps --rm node gulp all
|
@docker-compose run --no-deps --rm node gulp all
|
||||||
|
rl-build-pro:
|
||||||
yarn-install:
|
@docker-compose run --no-deps --rm node gulp all --pro
|
||||||
@docker compose run --no-deps --rm node yarn install
|
|
||||||
yarn-outdated:
|
|
||||||
@docker compose run --no-deps --rm node yarn outdated
|
|
||||||
yarn-upgrade:
|
|
||||||
@docker compose run --no-deps --rm node yarn upgrade-interactive --exact --latest
|
|
||||||
|
|
||||||
gpg:
|
gpg:
|
||||||
docker run -it --rm -w=/var/www \
|
docker run -it --rm -w=/var/www \
|
||||||
-v $(shell pwd)/.docker/.cache/.gnupg:/root/.gnupg \
|
-v $(shell pwd)/.docker/.cache/.gnupg:/root/.gnupg \
|
||||||
-v $(shell pwd):/var/www \
|
-v $(shell pwd):/var/www \
|
||||||
ubuntu:16.04 bash
|
ubuntu:latest bash
|
||||||
|
|
|
||||||
217
README.md
|
|
@ -1,226 +1,29 @@
|
||||||
<div align="center">
|
<div align="center">
|
||||||
<a href="https://github.com/the-djmaze/snappymail">
|
<a href="https://github.com/RainLoop/rainloop-webmail">
|
||||||
<img src="https://snappymail.eu/static/img/logo-256x256-white.png">
|
<img width="200" heigth="200" src="https://www.rainloop.net/static/img/logo-256x256-tiny.png">
|
||||||
</a>
|
</a>
|
||||||
<br>
|
<br>
|
||||||
<h1>SnappyMail</h1>
|
<h1>RainLoop Webmail</h1>
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
[](https://github.com/the-djmaze/snappymail/actions/workflows/docker.yml)
|
|
||||||
[](https://hub.docker.com/r/djmaze/snappymail/tags)
|
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Simple, modern, lightweight & fast web-based email client.
|
Simple, modern & fast web-based email client.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
The drastically upgraded & secured fork of <a href="https://github.com/RainLoop/rainloop-webmail">RainLoop Webmail Community edition</a>.
|
Modest system requirements, decent performance, simple installation and upgrade, no database required
|
||||||
</p>
|
- all these make RainLoop Webmail a perfect choice for your email solution.
|
||||||
<p>
|
|
||||||
We thank the RainLoop Team for making a great PHP 5 product that was good in the past.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
Up to date system requirements, snappy performance, simple installation and upgrade, no database required
|
|
||||||
- all these make SnappyMail a good choice.
|
|
||||||
</p>
|
</p>
|
||||||
<h2></h2>
|
<h2></h2>
|
||||||
<br>
|
<br>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
For more information about the product, check [snappymail.eu](https://snappymail.eu/).
|
For more information about the product, check [rainloop.net](http://www.rainloop.net/).
|
||||||
|
|
||||||
Information about installing the product, check the [wiki page](https://github.com/the-djmaze/snappymail/wiki/Installation-instructions).
|
Information about installing the product, check the [documentation page](http://www.rainloop.net/docs/installation/).
|
||||||
|
|
||||||
And don't forget to read the whole [Wiki](https://github.com/the-djmaze/snappymail/wiki).
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
**SnappyMail** is released under
|
**RainLoop Webmail (Community edition)** is released under
|
||||||
**GNU AFFERO GENERAL PUBLIC LICENSE Version 3 (AGPL)**.
|
**GNU AFFERO GENERAL PUBLIC LICENSE Version 3 (AGPL)**.
|
||||||
http://www.gnu.org/licenses/agpl-3.0.html
|
http://www.gnu.org/licenses/agpl-3.0.html
|
||||||
|
|
||||||
Copyright (c) 2020 - 2024 SnappyMail
|
Copyright (c) 2018 Rainloop Team
|
||||||
Copyright (c) 2013 - 2022 RainLoop
|
|
||||||
|
|
||||||
## Modifications
|
|
||||||
|
|
||||||
This fork of RainLoop has the following changes:
|
|
||||||
|
|
||||||
* Privacy/GDPR friendly (no: Social, Gravatar, Facebook, Google, Twitter, DropBox, X-Mailer)
|
|
||||||
* Admin uses password_hash/password_verify
|
|
||||||
* Auth failed attempts written to syslog
|
|
||||||
* Added Fail2ban instructions
|
|
||||||
* ES2020
|
|
||||||
* PHP 7.4+ required
|
|
||||||
* PHP mbstring extension required
|
|
||||||
* PHP replaced pclZip with PharData and ZipArchive
|
|
||||||
* Dark mode
|
|
||||||
* Added option to remove background/font colors from messages for real "dark mode"
|
|
||||||
* Removed BackwardCapability (class \RainLoop\Account)
|
|
||||||
* Removed ChangePassword (re-implemented as plugin)
|
|
||||||
* Removed POP3 support
|
|
||||||
* Removed background video support
|
|
||||||
* Removed Sentry (Application Monitoring and Error Tracking Software)
|
|
||||||
* Removed Spyc yaml
|
|
||||||
* Removed OwnCloud
|
|
||||||
* Replaced gulp-uglify with gulp-terser
|
|
||||||
* CRLF => LF line endings
|
|
||||||
* Embed boot.js and boot.css into index.html
|
|
||||||
* Removal of old JavaScript code (things are native these days)
|
|
||||||
* Added modified [Squire](https://github.com/the-djmaze/Squire/tree/snappymail) HTML editor as replacement for CKEditor
|
|
||||||
* Updated [Sabre/VObject](https://github.com/sabre-io/vobject)
|
|
||||||
* Split Admin specific JavaScript code from User code
|
|
||||||
* Split Sieve specific JavaScript code from User code
|
|
||||||
* JSON reviver
|
|
||||||
* Better memory garbage collection management
|
|
||||||
* Added serviceworker for Notifications
|
|
||||||
* Added advanced Sieve scripts editor
|
|
||||||
* Slimmed down language files
|
|
||||||
* Replaced webpack with rollup
|
|
||||||
* No user-agent detection (use device width)
|
|
||||||
* Added support to load plugins as .phar
|
|
||||||
* Replaced old Sabre library
|
|
||||||
* AddressBook Contacts support MySQL/MariaDB utf8mb4
|
|
||||||
* Added [Fetch Metadata Request Headers](https://www.w3.org/TR/fetch-metadata/) checks
|
|
||||||
* Reduced excessive DOM size
|
|
||||||
* Support [Kolab groupware](https://kolab.org/)
|
|
||||||
* Support many more [IMAP RFC's](https://snappymail.eu/comparison#IMAP)
|
|
||||||
* Support Sodium and OpenSSL for encryption
|
|
||||||
* Much better PGP support
|
|
||||||
|
|
||||||
|
|
||||||
### Supported browsers
|
|
||||||
|
|
||||||
This fork uses downsized/simplified versions of scripts and has no support for Internet Explorer nor Edge Legacy.
|
|
||||||
Supported are:
|
|
||||||
|
|
||||||
* Chrome 80+
|
|
||||||
* Edge 80+
|
|
||||||
* Firefox 78+
|
|
||||||
* Opera 67+
|
|
||||||
* Safari 13.1+
|
|
||||||
|
|
||||||
|
|
||||||
### Removal of old JavaScript
|
|
||||||
|
|
||||||
The result is faster and smaller download code (good for mobile networks).
|
|
||||||
|
|
||||||
* Added dev/prototype.js for some additional features
|
|
||||||
* Modified Jua.js to be without jQuery
|
|
||||||
* Replaced Autolinker with simple https/email detection
|
|
||||||
* Replaced momentToNode with proper HTML5 `<time>`
|
|
||||||
* Replaced resize listeners with ResizeObserver
|
|
||||||
* Replaced bootstrap.js with native drop-in replacement
|
|
||||||
* Replaced dev/Common/ClientStorageDriver/* with Web Storage Objects polyfill
|
|
||||||
* Replaced *Ajax with *Fetch classes because we use the Fetch API, not jQuery.ajax
|
|
||||||
* Replaced [knockoutjs](https://github.com/knockout/knockout) 3.4 with a modified 3.5.1
|
|
||||||
* Replaced knockout-sortable with native HTML5 drag&drop
|
|
||||||
* Replaced simplestatemanager with CSS @media
|
|
||||||
* Replaced inputosaurus with own code
|
|
||||||
* Replaced keymaster with own shortcuts handler
|
|
||||||
* Replaced OpenPGP.js v2 with OpenPGP.js v5
|
|
||||||
* Removed ifvisible.js
|
|
||||||
* Removed pikaday
|
|
||||||
* Removed underscore
|
|
||||||
* Removed polyfills
|
|
||||||
* Removed Modernizr
|
|
||||||
* Removed nanoscroll
|
|
||||||
* Removed lightgallery
|
|
||||||
* Removed jQuery
|
|
||||||
* Removed jquery-ui
|
|
||||||
* Removed jquery-scrollstop
|
|
||||||
* Removed jquery-mousewheel
|
|
||||||
* Removed matchmedia-polyfill
|
|
||||||
* Removed momentjs (use Intl)
|
|
||||||
* Removed opentip (use CSS)
|
|
||||||
* Removed non-community (aka Prem/Premium/License) code
|
|
||||||
* Removed ProgressJS
|
|
||||||
|
|
||||||
|
|
||||||
RainLoop 1.17 vs SnappyMail
|
|
||||||
|
|
||||||
|js/* |RainLoop |Snappy |
|
|
||||||
|--------------- |--------: |--------: |
|
|
||||||
|admin.js |2.170.153 | 84.925 |
|
|
||||||
|app.js |4.207.787 | 447.263 |
|
|
||||||
|boot.js | 868.735 | 4.343 |
|
|
||||||
|libs.js | 658.812 | 233.728 |
|
|
||||||
|sieve.js | 0 | 91.418 |
|
|
||||||
|polyfills.js | 334.608 | 0 |
|
|
||||||
|serviceworker.js | 0 | 285 |
|
|
||||||
|TOTAL |8.240.095 | 861.962 |
|
|
||||||
|
|
||||||
|js/min/* |RainLoop |Snappy |RL gzip |SM gzip |RL brotli |SM brotli |
|
|
||||||
|--------------- |--------: |--------: |------: |------: |--------: |--------: |
|
|
||||||
|admin.min.js | 256.831 | 41.719 | 73.606 | 14.022 | 60.877 | 12.567 |
|
|
||||||
|app.min.js | 515.367 | 202.101 |139.456 | 68.505 |110.485 | 58.481 |
|
|
||||||
|boot.min.js | 84.659 | 2.231 | 26.998 | 1.271 | 23.643 | 1.067 |
|
|
||||||
|libs.min.js | 584.772 | 110.646 |180.901 | 39.518 |155.182 | 35.207 |
|
|
||||||
|sieve.min.js | 0 | 45.504 | 0 | 11.131 | 0 | 9.917 |
|
|
||||||
|polyfills.min.js | 32.837 | 0 | 11.406 | 0 | 10.175 | 0 |
|
|
||||||
|TOTAL user |1.217.635 | 314.978 |358.761 |109.294 |299.485 | 94.755 |
|
|
||||||
|TOTAL user+sieve |1.217.635 | 360.482 |358.761 |120.425 |299.485 |104.672 |
|
|
||||||
|TOTAL admin | 959.099 | 154.596 |292.911 | 54.811 |249.877 | 48.841 |
|
|
||||||
|
|
||||||
For a user it is around 66% smaller and faster than traditional RainLoop.
|
|
||||||
|
|
||||||
### CSS changes
|
|
||||||
|
|
||||||
* Solve jQuery removed "features" with native css code
|
|
||||||
* Themes work in mobile mode
|
|
||||||
* Bugfix invalid/conflicting css rules
|
|
||||||
* Use flexbox
|
|
||||||
* Use border-box
|
|
||||||
* Split app.css to have separate admin.css
|
|
||||||
* Remove oldschool 'float'
|
|
||||||
* Remove unused css
|
|
||||||
* Removed html.no-css
|
|
||||||
* Removed dev/Styles/Cmd.less
|
|
||||||
* Removed dev/Styles/Scroll.less
|
|
||||||
* Removed Internet Explorer from normalize.css
|
|
||||||
* Removed node_modules/opentip/css/opentip.css
|
|
||||||
* Removed node_modules/pikaday/css/pikaday.css
|
|
||||||
* Removed unused vendors/bootstrap/less/*
|
|
||||||
* Removed vendors/jquery-nanoscroller/nanoscroller.css
|
|
||||||
* Removed vendors/jquery-letterfx/jquery-letterfx.min.css
|
|
||||||
* Removed vendors/Progress.js/minified/progressjs.min.css
|
|
||||||
* Removed gulp-autoprefixer
|
|
||||||
|
|
||||||
|
|
||||||
|css/* |RainLoop |Snappy |RL gzip |SM gzip |SM brotli |
|
|
||||||
|------------ |-------: |------: |------: |------: |--------: |
|
|
||||||
|app.css | 340.331 | 85.073 | 46.946 | 17.792 | 15.210 |
|
|
||||||
|app.min.css | 274.947 | 68.272 | 39.647 | 15.615 | 13.636 |
|
|
||||||
|boot.css | | 1.326 | | 664 | 545 |
|
|
||||||
|boot.min.css | | 1.071 | | 590 | 474 |
|
|
||||||
|admin.css | | 30.880 | | 7.045 | 6.127 |
|
|
||||||
|admin.min.css | | 24.959 | | 6.368 | 5.615 |
|
|
||||||
|
|
||||||
### PGP
|
|
||||||
RainLoop uses the old OpenPGP.js v2
|
|
||||||
SnappyMail v2.12 uses OpenPGP.js v5, GnuPG and Mailvelope.
|
|
||||||
SnappyMail is able to use and generate ECDSA and EDDSA keys, where RainLoop does not.
|
|
||||||
|
|
||||||
Since SnappyMail tries to achieve the best mobile experience, it forked OpenPGP.js to strip it down.
|
|
||||||
* remove all unused Node.js
|
|
||||||
* remove all old browsers support
|
|
||||||
See https://github.com/the-djmaze/openpgpjs for development
|
|
||||||
|
|
||||||
|OpenPGP |RainLoop |Snappy |RL gzip |SM gzip |RL brotli |SM brotli |
|
|
||||||
|--------------- |--------: |--------: |------: |-------: |--------: |--------: |
|
|
||||||
|openpgp.min.js | 330.742 | 546.165 |102.388 | 169.207 | 84.241 | 138.688 |
|
|
||||||
|openpgp.worker | 1.499 | | 824 | | 695 | |
|
|
||||||
|
|
||||||
|
|
||||||
### Squire vs CKEditor
|
|
||||||
The [Squire](https://github.com/neilj/Squire) implementation is not 100% compatible yet, but it shows the massive overhead of CKEditor.
|
|
||||||
|
|
||||||
Still TODO:
|
|
||||||
|
|
||||||
* support for tables (really needed?!?)
|
|
||||||
|
|
||||||
| | normal | min | gzip | min gzip |
|
|
||||||
|-------- |-------: |-------: |------: |--------: |
|
|
||||||
|squire | 122.321 | 41.906 | 31.867 | 14.330 |
|
|
||||||
|ckeditor | ? | 520.035 | ? | 155.916 |
|
|
||||||
|
|
||||||
CKEditor including the 7 asset requests (css,language,plugins,icons) is 633.46 KB / 180.47 KB (gzip).
|
|
||||||
|
|
|
||||||
40
SECURITY.md
|
|
@ -1,40 +0,0 @@
|
||||||
# Security Policy
|
|
||||||
|
|
||||||
## Supported Versions
|
|
||||||
|
|
||||||
Currently due to the fast development only the latest version receives security updates.
|
|
||||||
|
|
||||||
| Version | Supported |
|
|
||||||
| -------- | --------- |
|
|
||||||
| 2.34.x | ✔ |
|
|
||||||
| < 2.34.0 | ❌ |
|
|
||||||
|
|
||||||
## Reporting a Vulnerability
|
|
||||||
|
|
||||||
Please report security issues or vulnerabilities as an encrypted email to [security@snappymail.eu](mailto:security@snappymail.eu).
|
|
||||||
Your report should be detailed enough with clear steps to reproduce and classify the found vulnerability.
|
|
||||||
|
|
||||||
You can find the PGP public key below and on the major public keyservers like [keys.openpgp.org](https://keys.openpgp.org).
|
|
||||||
```
|
|
||||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
|
||||||
Comment: Type: 255-bit EdDSA
|
|
||||||
Comment: Fingerprint: 445D265124E6072671E64D0733F868A7E35E8277
|
|
||||||
|
|
||||||
mDMEYiE2QRYJKwYBBAHaRw8BAQdAqMrQUm6DddWcQNo0VEjNIu3Q6CfP3nokVv2Y
|
|
||||||
rNQ1avq0LFNuYXBweU1haWwgU2VjdXJpdHkgPHNlY3VyaXR5QHNuYXBweW1haWwu
|
|
||||||
ZXU+iJQEExYKADwWIQREXSZRJOYHJnHmTQcz+Gin416CdwUCYiE2QQIbAwULCQgH
|
|
||||||
AgMiAgEGFQoJCAsCBBYCAwECHgcCF4AACgkQM/hop+NegnfSGgD9GEHpOrvWpBGY
|
|
||||||
dYfvVd/+Lv5d+dFBcPyki9zu9zHfhwkBAL343EF6ZR0XwMlOQu9wu0hT9KBz4g55
|
|
||||||
6D41i0PrEaoBuDgEYiE2QRIKKwYBBAGXVQEFAQEHQMMr9gcVcJ3aiup/tpl8ZXxy
|
|
||||||
aJiJRGkPyNwGI5vxHMpZAwEIB4h4BBgWCgAgFiEERF0mUSTmByZx5k0HM/hop+Ne
|
|
||||||
gncFAmIhNkECGwwACgkQM/hop+NegndVhgD/SVGSKbF4G2W024VpW2tm3zCT+ue+
|
|
||||||
YMXQVq4SJt7UpWABAORudfJxsBqCRKtPlZMgGTJLjcOkyFJ9C2Fx7DeN0J4I
|
|
||||||
=nSOi
|
|
||||||
-----END PGP PUBLIC KEY BLOCK-----
|
|
||||||
```
|
|
||||||
|
|
||||||
## Publishing and Credits
|
|
||||||
|
|
||||||
I will analyze and fix the reported issue as fast as possible.
|
|
||||||
Together with the reporter, I plan the disclosure of the found and fixed vulnerability.
|
|
||||||
Credits to the reporter are granted and can be included in all public communication if desired.
|
|
||||||
1
_MULTIPLY
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
Name this file as "MULTIPLY" to enable multiple domain installation.
|
||||||
52
_include.php
|
|
@ -1,31 +1,21 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
// Name this file as "include.php" to enable it.
|
// Name this file as "include.php" to enable it.
|
||||||
|
|
||||||
//header('Strict-Transport-Security: max-age=31536000');
|
/**
|
||||||
|
* @return string
|
||||||
/**
|
*/
|
||||||
* Uncomment to enable multiple domain installation.
|
function __get_custom_data_full_path()
|
||||||
*/
|
{
|
||||||
//define('MULTIDOMAIN', 1);
|
return '';
|
||||||
|
return '/var/external-rainloop-data-folder/'; // custom data folder path
|
||||||
/**
|
}
|
||||||
* Uncomment to disable APCU.
|
|
||||||
*/
|
/**
|
||||||
//define('APP_USE_APCU_CACHE', false);
|
* @return string
|
||||||
|
*/
|
||||||
/**
|
function __get_additional_configuration_name()
|
||||||
* Custom 'data' folder path
|
{
|
||||||
*/
|
return '';
|
||||||
//define('APP_DATA_FOLDER_PATH', dirname(__DIR__) . '/snappymail-data/');
|
return defined('APP_SITE') && 0 < strlen(APP_SITE) ? APP_SITE.'.ini' : ''; // additional configuration file name
|
||||||
//define('APP_DATA_FOLDER_PATH', '/var/external-snappymail-data-folder/');
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Additional configuration file name
|
|
||||||
*/
|
|
||||||
//define('APP_CONFIGURATION_NAME', $_SERVER['HTTP_HOST'].'.ini');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Also update extensions on upgrade
|
|
||||||
*/
|
|
||||||
//define('SNAPPYMAIL_UPDATE_PLUGINS', 1);
|
|
||||||
|
|
|
||||||
BIN
assets/android-icon.png
Normal file
|
After Width: | Height: | Size: 5.4 KiB |
BIN
assets/apple-touch-icon.png
Normal file
|
After Width: | Height: | Size: 832 B |
BIN
assets/browsers/chrome.gif
Normal file
|
After Width: | Height: | Size: 3.7 KiB |
BIN
assets/browsers/firefox.gif
Normal file
|
After Width: | Height: | Size: 4.1 KiB |
BIN
assets/browsers/opera.gif
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
assets/browsers/safari.gif
Normal file
|
After Width: | Height: | Size: 4.8 KiB |
BIN
assets/css/default-skin.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
38
assets/css/default-skin.svg
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg width="264px" height="88px" viewBox="0 0 264 88" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
|
||||||
|
<!-- Generator: Sketch 3.0 (7574) - http://www.bohemiancoding.com/sketch -->
|
||||||
|
<title>default-skin 2</title>
|
||||||
|
<description>Created with Sketch.</description>
|
||||||
|
<defs></defs>
|
||||||
|
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
|
||||||
|
<g id="default-skin" sketch:type="MSLayerGroup">
|
||||||
|
<path d="M67.0018835,59.5 L67.0018835,63.268331 C60.6953142,64.1065038 57.8175182,69.0186795 57,73 C59.2189781,70.171167 62.5639273,67.9024591 67.0018835,67.9024591 L67.0018835,71.5 L73,65.5853951 L67.0018835,59.5 Z" id="Shape" fill="#FFFFFF" sketch:type="MSShapeGroup"></path>
|
||||||
|
<g id="Group" transform="translate(13.000000, 15.000000)" fill="#FFFFFF" sketch:type="MSShapeGroup">
|
||||||
|
<path d="M0,14 L0,9 L2,9 L2,12 L5,12 L5,14 L0,14 Z" id="Shape"></path>
|
||||||
|
<path d="M0,0 L5,0 L5,2 L2,2 L2,5 L0,5 L0,0 Z" id="Shape"></path>
|
||||||
|
<path d="M18,0 L18,5 L16,5 L16,2 L15.2629743,2 L13,2 L13,0 L18,0 Z" id="Shape"></path>
|
||||||
|
<path d="M18,14 L13,14 L13,12 L16,12 L16,9 L18,9 L18,14 Z" id="Shape"></path>
|
||||||
|
</g>
|
||||||
|
<g id="Group-4" transform="translate(57.000000, 15.000000)" fill="#FFFFFF" sketch:type="MSShapeGroup">
|
||||||
|
<path d="M0,14 L0,9 L2,9 L2,12 L5,12 L5,14 L0,14 Z" id="Shape" transform="translate(2.500000, 11.500000) rotate(-180.000000) translate(-2.500000, -11.500000) "></path>
|
||||||
|
<path d="M0,0 L5,0 L5,2 L2,2 L2,5 L0,5 L0,0 Z" id="Shape" transform="translate(2.500000, 2.500000) rotate(-180.000000) translate(-2.500000, -2.500000) "></path>
|
||||||
|
<path d="M18,0 L18,5 L16,5 L16,2 L15.2629743,2 L13,2 L13,0 L18,0 Z" id="Shape" transform="translate(15.500000, 2.500000) rotate(-180.000000) translate(-15.500000, -2.500000) "></path>
|
||||||
|
<path d="M18,14 L13,14 L13,12 L16,12 L16,9 L18,9 L18,14 Z" id="Shape" transform="translate(15.500000, 11.500000) rotate(-180.000000) translate(-15.500000, -11.500000) "></path>
|
||||||
|
</g>
|
||||||
|
<path d="M21,65 L21,57 L23,57 L23,65 L31,65 L31,67 L23,67 L23,75 L21,75 L21,67 L13,67 L13,65 L21,65 Z" id="Rectangle-13" fill="#FFFFFF" sketch:type="MSShapeGroup" transform="translate(22.000000, 66.000000) rotate(-45.000000) translate(-22.000000, -66.000000) "></path>
|
||||||
|
<path d="M111.784738,65.0291574 L110,63.5 L113,60 L103,60 L103,58 L113,58 L110,54.5 L111.784738,53.0320871 L117,59 L111.784738,65.0291574 Z" id="Shape-3" fill="#FFFFFF" sketch:type="MSShapeGroup"></path>
|
||||||
|
<path d="M155.784738,65.0291574 L154,63.5 L157,60 L147,60 L147,58 L157,58 L154,54.5 L155.784738,53.0320871 L161,59 L155.784738,65.0291574 Z" id="Shape-4" fill="#FFFFFF" sketch:type="MSShapeGroup" transform="translate(154.000000, 59.000000) scale(-1, 1) translate(-154.000000, -59.000000) "></path>
|
||||||
|
<g id="Group-2" transform="translate(147.000000, 16.000000)" sketch:type="MSShapeGroup">
|
||||||
|
<rect id="Rectangle-11" fill="#FFFFFF" transform="translate(11.767767, 11.767767) scale(-1, 1) rotate(-45.000000) translate(-11.767767, -11.767767) " x="9.67157286" y="10.767767" width="4.59619409" height="2"></rect>
|
||||||
|
<path d="M5.5,11 C8.53756612,11 11,8.53756612 11,5.5 C11,2.46243388 8.53756612,0 5.5,0 C2.46243388,0 0,2.46243388 0,5.5 C0,8.53756612 2.46243388,11 5.5,11 Z" id="Oval-1" stroke="#FFFFFF" stroke-width="1.5"></path>
|
||||||
|
<rect id="Rectangle-12" fill="#FFFFFF" x="3" y="5" width="5" height="1"></rect>
|
||||||
|
</g>
|
||||||
|
<g id="Group-3" transform="translate(103.000000, 16.000000)" sketch:type="MSShapeGroup">
|
||||||
|
<path d="M13.9571068,12.5428932 L12.5428932,13.9571068 L9.29289322,10.7071068 L10.7071068,9.29289322 L13.9571068,12.5428932 Z" id="Rectangle-11" fill="#FFFFFF"></path>
|
||||||
|
<path d="M5.5,11 C8.53756612,11 11,8.53756612 11,5.5 C11,2.46243388 8.53756612,0 5.5,0 C2.46243388,0 0,2.46243388 0,5.5 C0,8.53756612 2.46243388,11 5.5,11 Z" id="Oval-1" stroke="#FFFFFF" stroke-width="1.5"></path>
|
||||||
|
<rect id="Rectangle-17" fill="#FFFFFF" x="3" y="5" width="5" height="1"></rect>
|
||||||
|
<rect id="Rectangle-16" fill="#FFFFFF" transform="translate(5.500000, 5.500000) rotate(-269.000000) translate(-5.500000, -5.500000) " x="3" y="5" width="5" height="1"></rect>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 4.5 KiB |
BIN
assets/css/flags.png
Normal file
|
After Width: | Height: | Size: 77 KiB |
BIN
assets/css/images/editor.png
Normal file
|
After Width: | Height: | Size: 8.2 KiB |
BIN
assets/css/images/empty-contact.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
BIN
assets/css/images/grey.png
Normal file
|
After Width: | Height: | Size: 109 B |
BIN
assets/css/images/icom-message-notification.png
Normal file
|
After Width: | Height: | Size: 832 B |
BIN
assets/css/images/loading.gif
Normal file
|
After Width: | Height: | Size: 869 B |
BIN
assets/css/images/rainloop-logo.png
Normal file
|
After Width: | Height: | Size: 4.6 KiB |
BIN
assets/css/images/sync.gif
Normal file
|
After Width: | Height: | Size: 847 B |
BIN
assets/css/images/sync.png
Normal file
|
After Width: | Height: | Size: 356 B |
BIN
assets/css/images/white.png
Normal file
|
After Width: | Height: | Size: 110 B |
BIN
assets/css/img/loading.gif
Normal file
|
After Width: | Height: | Size: 869 B |
BIN
assets/css/loading.gif
Normal file
|
After Width: | Height: | Size: 869 B |
BIN
assets/css/preloader.gif
Normal file
|
After Width: | Height: | Size: 869 B |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 866 B After Width: | Height: | Size: 866 B |
BIN
assets/favicon.ico
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
assets/favicon.png
Normal file
|
After Width: | Height: | Size: 832 B |
16
assets/manifest.json
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
{
|
||||||
|
"name": "RainLoop Webmail",
|
||||||
|
"short_name": "RainLoop",
|
||||||
|
"description": "Simple, modern & fast web-based email client",
|
||||||
|
"display": "standalone",
|
||||||
|
"icons": [{
|
||||||
|
"src": "apple-touch-icon.png",
|
||||||
|
"sizes": "64x64",
|
||||||
|
"type": "image/png"
|
||||||
|
}, {
|
||||||
|
"src": "android-icon.png",
|
||||||
|
"sizes": "192x192",
|
||||||
|
"type": "image/png"
|
||||||
|
}],
|
||||||
|
"start_url": "../../../../"
|
||||||
|
}
|
||||||
BIN
assets/sounds/new-mail.mp3
Normal file
BIN
assets/sounds/new-mail.ogg
Normal file
|
|
@ -1,9 +0,0 @@
|
||||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
|
||||||
|
|
||||||
mDMEYg0atBYJKwYBBAHaRw8BAQdA2S2tvGavChACjtBastsKRThD3rsBW1LUZLmN
|
|
||||||
Zbs4uaG0I1NuYXBweU1haWwgPHJlbGVhc2VzQHNuYXBweW1haWwuZXU+iJQEExYK
|
|
||||||
ADwWIQQQFuRweRRVQvi6EzVIIIuhMpDz6wUCYg0atAIbAwULCQgHAgMiAgEGFQoJ
|
|
||||||
CAsCBBYCAwECHgcCF4AACgkQSCCLoTKQ8+u9SAD/Q/IoAwjUkKDJBPq0RGwCFnl6
|
|
||||||
FG/VHB97CvBSpGOxtIsBAMCwMhWlsaBHAEqbzxiN+cdlMYwV23+SWLUJ/XMFgukE
|
|
||||||
=5ZwF
|
|
||||||
-----END PGP PUBLIC KEY BLOCK-----
|
|
||||||
|
|
@ -1,57 +0,0 @@
|
||||||
# Maintainer: George Rawlinson <george@rawlinson.net.nz>
|
|
||||||
|
|
||||||
pkgname=snappymail
|
|
||||||
pkgver=2.7.2
|
|
||||||
pkgrel=1
|
|
||||||
pkgdesc="modern PHP webmail client"
|
|
||||||
arch=('any')
|
|
||||||
license=('AGPL3')
|
|
||||||
url="https://github.com/the-djmaze/snappymail"
|
|
||||||
depends=('php-fpm')
|
|
||||||
makedepends=('php', 'nodejs' 'yarn' 'gulp', 'rollup')
|
|
||||||
optdepends=('mariadb: storage backend for contacts'
|
|
||||||
'php-pgsql: storage backend for contacts'
|
|
||||||
'php-sqlite: storage backend for contacts')
|
|
||||||
source=("$pkgname-$pkgver.tar.gz::$url/archive/v$pkgver.tar.gz"
|
|
||||||
"$pkgname.sysusers"
|
|
||||||
"$pkgname.tmpfiles")
|
|
||||||
b2sums=('a877041eaa74ca9824323b0ba80b3515205628825ed76fccff1511b2547c27419bae4733d24f8f36e6860c671cb609c4c5f31fa19529a92c628cb714570ff8ae'
|
|
||||||
'e020b2d4bc694ca056f5c15b148c69553ab610b5e1789f52543aa65e098f8097a41709b5b0fc22a6a01088a9d3f14d623b1b6e9ae2570acd4f380f429301c003'
|
|
||||||
'2536e11622895322cc752c6b651811b2122d3ae60099fe609609d7b45ba1ed00ea729c23f344405078698d161dbf9bcaffabf8eff14b740acdce3c681c513318')
|
|
||||||
|
|
||||||
prepare() {
|
|
||||||
sed -i "s/\$sCustomDataPath = '';/\$sCustomDataPath = '\/var\/lib\/$pkgname';/" "$pkgname-$pkgver/$pkgname/v/0.0.0/include.php"
|
|
||||||
|
|
||||||
# create folder for build output
|
|
||||||
mkdir -p build
|
|
||||||
}
|
|
||||||
|
|
||||||
build() {
|
|
||||||
cd "$pkgname-$pkgver"
|
|
||||||
yarn install
|
|
||||||
|
|
||||||
# build snappymail
|
|
||||||
php release.php --aur
|
|
||||||
bsdtar -x \
|
|
||||||
-C "$srcdir/build" \
|
|
||||||
-f "build/dist/releases/webmail/$pkgver/$pkgname-$pkgver.zip"
|
|
||||||
find . -type d -exec chmod 755 {} \;
|
|
||||||
find . -type f -exec chmod 644 {} \;
|
|
||||||
}
|
|
||||||
|
|
||||||
package() {
|
|
||||||
# directories
|
|
||||||
install -dm755 "$pkgdir/usr/share/snappymail" \
|
|
||||||
"$pkgdir/var/lib/snappymail"
|
|
||||||
|
|
||||||
# application files
|
|
||||||
cp -r "$srcdir/build/snappymail" "$pkgdir/usr/share/snappymail"
|
|
||||||
install -Dm644 -t "$pkgdir/usr/share/snappymail" "$srcdir/build/index.php"
|
|
||||||
|
|
||||||
# data files
|
|
||||||
cp -r "$srcdir/build/data" "$pkgdir/var/lib/snappymail"
|
|
||||||
|
|
||||||
# sysusers
|
|
||||||
install -Dm644 "$srcdir/$pkgname.sysusers" "$pkgdir/usr/lib/sysusers.d/$pkgname.conf"
|
|
||||||
install -Dm644 "$srcdir/$pkgname.tmpfiles" "$pkgdir/usr/lib/tmpfiles.d/$pkgname.conf"
|
|
||||||
}
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
u snappymail - "Snappymail User" /var/lib/snappymail
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Z /var/lib/snappymail - snappymail snappymail
|
|
||||||
|
|
@ -1,38 +0,0 @@
|
||||||
<?php
|
|
||||||
echo "\x1b[33;1m === cPanel === \x1b[0m\n";
|
|
||||||
|
|
||||||
$cpanel_destination = "{$destPath}snappymail-{$package->version}-cpanel.tar";
|
|
||||||
|
|
||||||
@unlink($cpanel_destination);
|
|
||||||
@unlink("{$cpanel_destination}.gz");
|
|
||||||
|
|
||||||
$cpanel_tar = new PharData($cpanel_destination);
|
|
||||||
|
|
||||||
$cpanel_tar->buildFromDirectory('./integrations/cpanel', "@integrations/cpanel/@");
|
|
||||||
|
|
||||||
$cpanel_path = '/usr/local/cpanel/base/3rdparty/snappymail/';
|
|
||||||
|
|
||||||
$files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator('snappymail/v'), RecursiveIteratorIterator::SELF_FIRST);
|
|
||||||
foreach ($files as $file) {
|
|
||||||
if (is_file($file)) {
|
|
||||||
$newFile = str_replace('\\', '/', $file);
|
|
||||||
$cpanel_tar->addFile($file, "{$cpanel_path}{$newFile}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$cpanel_tar->addFile('.htaccess', "{$cpanel_path}.htaccess");
|
|
||||||
$cpanel_tar->addFile('README.md', "{$cpanel_path}README.md");
|
|
||||||
$cpanel_tar->addFromString("{$cpanel_path}VERSION", $package->version);
|
|
||||||
|
|
||||||
$index = file_get_contents('index.php');
|
|
||||||
$index = str_replace('0.0.0', $package->version, $index);
|
|
||||||
$cpanel_tar->addFromString("{$cpanel_path}index.php", $index);
|
|
||||||
|
|
||||||
$data = file_get_contents('dev/serviceworker.js');
|
|
||||||
$cpanel_tar->addFromString("{$cpanel_path}serviceworker.js", $data);
|
|
||||||
|
|
||||||
$cpanel_tar->compress(Phar::GZ);
|
|
||||||
unlink($cpanel_destination);
|
|
||||||
$cpanel_destination .= '.gz';
|
|
||||||
|
|
||||||
echo "{$cpanel_destination} created\n";
|
|
||||||
|
|
@ -1,83 +0,0 @@
|
||||||
<?php
|
|
||||||
echo "\x1b[33;1m === Debian === \x1b[0m\n";
|
|
||||||
|
|
||||||
// Debian Repository
|
|
||||||
define('DEB_SOURCE_DIR', __DIR__ . '/deb');
|
|
||||||
define('DEB_DEST_DIR', DEB_SOURCE_DIR . "/snappymail_{$package->version}-1_all");
|
|
||||||
is_dir(DEB_DEST_DIR) && passthru('rm -dfr '.escapeshellarg(DEB_DEST_DIR));
|
|
||||||
|
|
||||||
$dir = DEB_DEST_DIR . '/DEBIAN';
|
|
||||||
$data = file_get_contents(DEB_SOURCE_DIR . '/DEBIAN/control');
|
|
||||||
$data = str_replace('0.0.0', $package->version, $data);
|
|
||||||
mkdir($dir, 0755, true);
|
|
||||||
file_put_contents("{$dir}/control", $data);
|
|
||||||
copy(DEB_SOURCE_DIR . '/DEBIAN/postinst', $dir . '/postinst');
|
|
||||||
chmod($dir . '/postinst', 0755);
|
|
||||||
|
|
||||||
$dir = DEB_DEST_DIR . '/var/lib/snappymail';
|
|
||||||
mkdir($dir, 0755, true);
|
|
||||||
file_put_contents($dir . '/VERSION', $package->version);
|
|
||||||
copy('data/README.md', "{$dir}/README.md");
|
|
||||||
|
|
||||||
$dir = DEB_DEST_DIR . '/usr/share/doc/snappymail';
|
|
||||||
mkdir($dir, 0755, true);
|
|
||||||
copy('CODE_OF_CONDUCT.md', "{$dir}/CODE_OF_CONDUCT.md");
|
|
||||||
copy('CONTRIBUTING.md', "{$dir}/CONTRIBUTING.md");
|
|
||||||
copy('README.md', "{$dir}/README.md");
|
|
||||||
//copy('CODE_OF_CONDUCT.md', "{$dir}/CODE_OF_CONDUCT.md");
|
|
||||||
//usr/share/doc/snappymail/README.Debian
|
|
||||||
//usr/share/doc/snappymail/changelog.Debian.gz
|
|
||||||
//usr/share/doc/snappymail/copyright
|
|
||||||
|
|
||||||
// Move files into package directory
|
|
||||||
$dir = DEB_DEST_DIR . '/usr/share/snappymail';
|
|
||||||
mkdir($dir, 0755, true);
|
|
||||||
passthru('cp -r "' . dirname(__DIR__) . '/snappymail" "' . $dir . '"');
|
|
||||||
|
|
||||||
rename("{$dir}/snappymail/v/0.0.0", "{$dir}/snappymail/v/{$package->version}");
|
|
||||||
|
|
||||||
$data = file_get_contents('index.php');
|
|
||||||
file_put_contents("{$dir}/index.php", str_replace('0.0.0', $package->version, $data));
|
|
||||||
|
|
||||||
$data = file_get_contents('_include.php');
|
|
||||||
file_put_contents("{$dir}/include.php", preg_replace('@(external-snappymail-data-folder/\'\);)@', "\$1\ndefine('APP_DATA_FOLDER_PATH', '/var/lib/snappymail/');", $data));
|
|
||||||
|
|
||||||
passthru('dpkg --build ' . escapeshellarg(DEB_DEST_DIR));
|
|
||||||
|
|
||||||
$TARGET_DIR = __DIR__ . "/dist/releases/webmail/{$package->version}/";
|
|
||||||
|
|
||||||
passthru('mv '
|
|
||||||
. escapeshellarg(DEB_DEST_DIR.'.deb') . ' '
|
|
||||||
. escapeshellarg($TARGET_DIR . basename(DEB_DEST_DIR.'.deb'))
|
|
||||||
);
|
|
||||||
|
|
||||||
passthru('rm -dfr '.escapeshellarg(DEB_DEST_DIR));
|
|
||||||
|
|
||||||
// https://github.com/the-djmaze/snappymail/issues/185#issuecomment-1059420588
|
|
||||||
$cwd = getcwd();
|
|
||||||
chdir($TARGET_DIR);
|
|
||||||
passthru('dpkg-scanpackages . /dev/null > '.escapeshellarg($TARGET_DIR . 'Packages'));
|
|
||||||
passthru('dpkg-scanpackages . /dev/null | gzip -9c > '.escapeshellarg($TARGET_DIR . 'Packages.gz'));
|
|
||||||
$size = filesize($TARGET_DIR . 'Packages');
|
|
||||||
$gz_size = filesize($TARGET_DIR . 'Packages.gz');
|
|
||||||
$Release = 'Origin: SnappyMail Repository
|
|
||||||
Label: SnappyMail
|
|
||||||
Suite: stable
|
|
||||||
Codename: stable
|
|
||||||
Version: 1.0
|
|
||||||
Architectures: all
|
|
||||||
Components: main
|
|
||||||
Description: SnappyMail repository
|
|
||||||
Date: ' . gmdate('r') . '
|
|
||||||
MD5Sum:
|
|
||||||
' . hash_file('md5', $TARGET_DIR . 'Packages') . ' ' . $size . ' Packages
|
|
||||||
' . hash_file('md5', $TARGET_DIR . 'Packages.gz') . ' ' . $gz_size . ' Packages.gz
|
|
||||||
SHA1:
|
|
||||||
' . hash_file('sha1', $TARGET_DIR . 'Packages') . ' ' . $size . ' Packages
|
|
||||||
' . hash_file('sha1', $TARGET_DIR . 'Packages.gz') . ' ' . $gz_size . ' Packages.gz
|
|
||||||
SHA256:
|
|
||||||
' . hash_file('sha256', $TARGET_DIR . 'Packages') . ' ' . $size . ' Packages
|
|
||||||
' . hash_file('sha256', $TARGET_DIR . 'Packages.gz') . ' ' . $gz_size . ' Packages.gz
|
|
||||||
';
|
|
||||||
file_put_contents($TARGET_DIR . 'Release', $Release);
|
|
||||||
chdir($cwd);
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
Package: snappymail
|
|
||||||
Version: 0.0.0
|
|
||||||
Maintainer: SnappyMail <debian@snappymail.eu>
|
|
||||||
Depends: nginx | apache2 | httpd, php-fpm | libapache2-mod-php, php-json, php-mbstring
|
|
||||||
Recommends: php-intl, php-sodium, php-uuid
|
|
||||||
Suggests: php-sqlite3 | php-mysql | php-pgsql, php-curl, php-exif, php-gnupg, php-gd | php-gmagick | php-imagick, php-openssl, php-zip
|
|
||||||
Architecture: all
|
|
||||||
Homepage: https://snappymail.eu
|
|
||||||
Vcs-Browser: https://github.com/the-djmaze/snappymail
|
|
||||||
Vcs-Git: https://github.com/the-djmaze/snappymail.git
|
|
||||||
Description: SnappyMail is a PHP-based simple, modern, lightweight & fast web-based email client with no database requirements.
|
|
||||||
It supports IMAP, SMTP and Sieve protocols, multiple accounts and identities, an admin panel for configuration.
|
|
||||||
Plugins can be installed to further extend functionality.
|
|
||||||
Emails are not stored locally, but are accessed through IMAP.
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
chown -R www-data:www-data /var/lib/snappymail
|
|
||||||
chown -R root:root /usr/share/snappymail/
|
|
||||||
|
|
@ -1,92 +0,0 @@
|
||||||
<?php
|
|
||||||
echo "\x1b[33;1m === Nextcloud === \x1b[0m\n";
|
|
||||||
|
|
||||||
$cert_dir = $_SERVER['HOME'].'/.nextcloud/certificates';
|
|
||||||
|
|
||||||
$nc_destination = "{$destPath}snappymail-{$package->version}-nextcloud.tar";
|
|
||||||
|
|
||||||
@unlink($nc_destination);
|
|
||||||
@unlink("{$nc_destination}.gz");
|
|
||||||
|
|
||||||
$nc_tar = new PharData($nc_destination);
|
|
||||||
$hashes = [];
|
|
||||||
|
|
||||||
file_put_contents(ROOT_DIR . '/integrations/nextcloud/snappymail/VERSION', $package->version);
|
|
||||||
$file = ROOT_DIR . '/integrations/nextcloud/snappymail/appinfo/info.xml';
|
|
||||||
file_put_contents($file, preg_replace('/<version>[^<]*</', "<version>{$package->version}<", file_get_contents($file)));
|
|
||||||
|
|
||||||
$nc_tar->buildFromDirectory('./integrations/nextcloud', "@integrations/nextcloud/snappymail/@");
|
|
||||||
$files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator('integrations/nextcloud/snappymail'));
|
|
||||||
foreach ($files as $file) {
|
|
||||||
if (is_file($file)) {
|
|
||||||
$name = str_replace('\\', '/', $file);
|
|
||||||
$name = str_replace('integrations/nextcloud/snappymail/', '', $name);
|
|
||||||
$hashes[$name] = hash_file('sha512', $file);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator('snappymail/v'), RecursiveIteratorIterator::SELF_FIRST);
|
|
||||||
foreach ($files as $file) {
|
|
||||||
if (is_file($file)) {
|
|
||||||
$newFile = str_replace('\\', '/', $file);
|
|
||||||
$newName = str_replace('/.htaccess', '/_htaccess', $newFile);
|
|
||||||
$nc_tar->addFile($file, "snappymail/app/{$newName}");
|
|
||||||
$hashes["app/{$newFile}"] = hash_file('sha512', $file);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
$nc_tar->addFile('data/.htaccess');
|
|
||||||
$nc_tar->addFromString('data/VERSION', $package->version);
|
|
||||||
$nc_tar->addFile('data/README.md');
|
|
||||||
$nc_tar->addFile('_include.php', 'snappymail/app/_include.php');
|
|
||||||
*/
|
|
||||||
$nc_tar->addFile('.htaccess', 'snappymail/app/_htaccess');
|
|
||||||
$hashes['app/.htaccess'] = hash_file('sha512', '.htaccess');
|
|
||||||
|
|
||||||
$index = file_get_contents('index.php');
|
|
||||||
$index = str_replace('0.0.0', $package->version, $index);
|
|
||||||
//$index = str_replace('snappymail/v/', '', $index);
|
|
||||||
$nc_tar->addFromString('snappymail/app/index.php', $index);
|
|
||||||
$hashes['app/index.php'] = hash('sha512', $index);
|
|
||||||
|
|
||||||
$nc_tar->addFile('README.md', 'snappymail/app/README.md');
|
|
||||||
$hashes['app/README.md'] = hash_file('sha512', 'README.md');
|
|
||||||
|
|
||||||
$nc_tar->addFile('CHANGELOG.md', 'snappymail/CHANGELOG.md');
|
|
||||||
$hashes['CHANGELOG.md'] = hash_file('sha512', 'CHANGELOG.md');
|
|
||||||
|
|
||||||
$data = file_get_contents('dev/serviceworker.js');
|
|
||||||
$nc_tar->addFromString('snappymail/app/serviceworker.js', $data);
|
|
||||||
$hashes['app/serviceworker.js'] = hash('sha512', $data);
|
|
||||||
|
|
||||||
spl_autoload_register(function($name){
|
|
||||||
$file = __DIR__ . '/' . str_replace('\\', '/', $name) . '.php';
|
|
||||||
require $file;
|
|
||||||
});
|
|
||||||
|
|
||||||
ksort($hashes);
|
|
||||||
$cert = file_get_contents($cert_dir.'/snappymail.crt');
|
|
||||||
$rsa = new \phpseclib\Crypt\RSA();
|
|
||||||
$rsa->loadKey(file_get_contents($cert_dir.'/snappymail.key'));
|
|
||||||
$x509 = new \phpseclib\File\X509();
|
|
||||||
$x509->loadX509($cert);
|
|
||||||
$x509->setPrivateKey($rsa);
|
|
||||||
$rsa->setSignatureMode(\phpseclib\Crypt\RSA::SIGNATURE_PSS);
|
|
||||||
$rsa->setMGFHash('sha512');
|
|
||||||
$rsa->setSaltLength(0);
|
|
||||||
$signature = $rsa->sign(json_encode($hashes));
|
|
||||||
$nc_tar->addFromString('snappymail/appinfo/signature.json', json_encode([
|
|
||||||
'hashes' => $hashes,
|
|
||||||
'signature' => base64_encode($signature),
|
|
||||||
'certificate' => $cert
|
|
||||||
], JSON_PRETTY_PRINT));
|
|
||||||
|
|
||||||
$nc_tar->compress(Phar::GZ);
|
|
||||||
unlink($nc_destination);
|
|
||||||
$nc_destination .= '.gz';
|
|
||||||
|
|
||||||
$signature = shell_exec("openssl dgst -sha512 -sign {$cert_dir}/snappymail.key {$nc_destination} | openssl base64");
|
|
||||||
file_put_contents($nc_destination.'.sig', $signature);
|
|
||||||
|
|
||||||
echo "{$nc_destination} created\n";
|
|
||||||
|
|
@ -1,100 +0,0 @@
|
||||||
<?php
|
|
||||||
echo "\x1b[33;1m === ownCloud === \x1b[0m\n";
|
|
||||||
|
|
||||||
$cert_dir = false; // $_SERVER['HOME'].'/.owncloud/certificates';
|
|
||||||
|
|
||||||
$nc_destination = "{$destPath}snappymail-{$package->version}-owncloud.tar";
|
|
||||||
|
|
||||||
@unlink($nc_destination);
|
|
||||||
@unlink("{$nc_destination}.gz");
|
|
||||||
|
|
||||||
$nc_tar = new PharData($nc_destination);
|
|
||||||
$hashes = [];
|
|
||||||
|
|
||||||
file_put_contents(ROOT_DIR . '/integrations/owncloud/snappymail/VERSION', $package->version);
|
|
||||||
$file = ROOT_DIR . '/integrations/owncloud/snappymail/appinfo/info.xml';
|
|
||||||
file_put_contents($file, preg_replace('/<version>[^<]*</', "<version>{$package->version}<", file_get_contents($file)));
|
|
||||||
|
|
||||||
$nc_tar->buildFromDirectory('./integrations/owncloud', "@integrations/owncloud/snappymail/@");
|
|
||||||
$files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator('integrations/owncloud/snappymail'));
|
|
||||||
foreach ($files as $file) {
|
|
||||||
if (is_file($file)) {
|
|
||||||
$name = str_replace('\\', '/', $file);
|
|
||||||
$name = str_replace('integrations/owncloud/snappymail/', '', $name);
|
|
||||||
$hashes[$name] = hash_file('sha512', $file);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator('snappymail/v'), RecursiveIteratorIterator::SELF_FIRST);
|
|
||||||
foreach ($files as $file) {
|
|
||||||
if (is_file($file)) {
|
|
||||||
$newFile = str_replace('\\', '/', $file);
|
|
||||||
// $newFile = str_replace("'snappymail/v/'.", '', $newFile);
|
|
||||||
$nc_tar->addFile($file, "snappymail/app/{$newFile}");
|
|
||||||
$hashes["app/{$newFile}"] = hash_file('sha512', $file);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$nc_tar->delete("snappymail/app/snappymail/v/{$package->version}/app/.htaccess");
|
|
||||||
$nc_tar->addFile("snappymail/v/{$package->version}/app/.htaccess", "snappymail/app/snappymail/v/{$package->version}/app/_htaccess");
|
|
||||||
$nc_tar->delete("snappymail/app/snappymail/v/{$package->version}/static/.htaccess");
|
|
||||||
$nc_tar->addFile("snappymail/v/{$package->version}/static/.htaccess", "snappymail/app/snappymail/v/{$package->version}/static/_htaccess");
|
|
||||||
|
|
||||||
/*
|
|
||||||
$nc_tar->addFile('data/.htaccess');
|
|
||||||
$nc_tar->addFromString('data/VERSION', $package->version);
|
|
||||||
$nc_tar->addFile('data/README.md');
|
|
||||||
$nc_tar->addFile('_include.php', 'snappymail/app/_include.php');
|
|
||||||
*/
|
|
||||||
$nc_tar->addFile('.htaccess', 'snappymail/app/_htaccess');
|
|
||||||
$hashes['app/.htaccess'] = hash_file('sha512', '.htaccess');
|
|
||||||
|
|
||||||
$index = file_get_contents('index.php');
|
|
||||||
$index = str_replace('0.0.0', $package->version, $index);
|
|
||||||
//$index = str_replace('snappymail/v/', '', $index);
|
|
||||||
$nc_tar->addFromString('snappymail/app/index.php', $index);
|
|
||||||
$hashes['app/index.php'] = hash('sha512', $index);
|
|
||||||
|
|
||||||
$nc_tar->addFile('README.md', 'snappymail/app/README.md');
|
|
||||||
$hashes['app/README.md'] = hash_file('sha512', 'README.md');
|
|
||||||
|
|
||||||
$nc_tar->addFile('CHANGELOG.md', 'snappymail/CHANGELOG.md');
|
|
||||||
$hashes['CHANGELOG.md'] = hash_file('sha512', 'CHANGELOG.md');
|
|
||||||
|
|
||||||
$data = file_get_contents('dev/serviceworker.js');
|
|
||||||
$nc_tar->addFromString('snappymail/app/serviceworker.js', $data);
|
|
||||||
$hashes['app/serviceworker.js'] = hash('sha512', $data);
|
|
||||||
|
|
||||||
if ($cert_dir) {
|
|
||||||
spl_autoload_register(function($name){
|
|
||||||
$file = __DIR__ . '/' . str_replace('\\', '/', $name) . '.php';
|
|
||||||
require $file;
|
|
||||||
});
|
|
||||||
|
|
||||||
ksort($hashes);
|
|
||||||
$cert = file_get_contents($cert_dir.'/snappymail.crt');
|
|
||||||
$rsa = new \phpseclib\Crypt\RSA();
|
|
||||||
$rsa->loadKey(file_get_contents($cert_dir.'/snappymail.key'));
|
|
||||||
$x509 = new \phpseclib\File\X509();
|
|
||||||
$x509->loadX509($cert);
|
|
||||||
$x509->setPrivateKey($rsa);
|
|
||||||
$rsa->setSignatureMode(\phpseclib\Crypt\RSA::SIGNATURE_PSS);
|
|
||||||
$rsa->setMGFHash('sha512');
|
|
||||||
$rsa->setSaltLength(0);
|
|
||||||
$signature = $rsa->sign(json_encode($hashes));
|
|
||||||
$nc_tar->addFromString('snappymail/appinfo/signature.json', json_encode([
|
|
||||||
'hashes' => $hashes,
|
|
||||||
'signature' => base64_encode($signature),
|
|
||||||
'certificate' => $cert
|
|
||||||
], JSON_PRETTY_PRINT));
|
|
||||||
}
|
|
||||||
|
|
||||||
$nc_tar->compress(Phar::GZ);
|
|
||||||
unlink($nc_destination);
|
|
||||||
$nc_destination .= '.gz';
|
|
||||||
|
|
||||||
if ($cert_dir) {
|
|
||||||
$signature = shell_exec("openssl dgst -sha512 -sign {$cert_dir}/snappymail.key {$nc_destination} | openssl base64");
|
|
||||||
file_put_contents($nc_destination.'.sig', $signature);
|
|
||||||
}
|
|
||||||
|
|
||||||
echo "{$nc_destination} created\n";
|
|
||||||
28
build/owncloud/rainloop-app/INSTALL
Executable file
|
|
@ -0,0 +1,28 @@
|
||||||
|
************************************************************************
|
||||||
|
*
|
||||||
|
* ownCloud/Nextcloud - RainLoop Webmail package
|
||||||
|
*
|
||||||
|
* @author RainLoop Team
|
||||||
|
* @copyright 2018 RainLoop Team
|
||||||
|
*
|
||||||
|
* https://github.com/RainLoop/rainloop-webmail/tree/master/build/owncloud
|
||||||
|
*
|
||||||
|
************************************************************************
|
||||||
|
|
||||||
|
REQUIREMENTS:
|
||||||
|
- ownCloud version 6 or higher
|
||||||
|
or
|
||||||
|
- Nextcloud version 10 or higher
|
||||||
|
|
||||||
|
|
||||||
|
INSTALL:
|
||||||
|
- Unpack the RainLoop Webmail application package in the apps directory of your ownCloud or Nextcloud instance
|
||||||
|
- Make sure the rights are appropriately set
|
||||||
|
|
||||||
|
CONFIGURATION:
|
||||||
|
- ownCloud:
|
||||||
|
1) In the Apps > Enable 'RainLoop' plugin
|
||||||
|
2) In the Settings > Personal > Type your email server login and password
|
||||||
|
- Nextcloud:
|
||||||
|
1) In the Apps > Enable 'RainLoop' plugin after checking 'Enable experimental apps'
|
||||||
|
2) In the Settings > Personal > Type your email server login and password
|
||||||
1
build/owncloud/rainloop-app/VERSION
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
0.0
|
||||||
18
build/owncloud/rainloop-app/admin.php
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ownCloud - RainLoop mail plugin
|
||||||
|
*
|
||||||
|
* @author RainLoop Team
|
||||||
|
*
|
||||||
|
* https://github.com/RainLoop/rainloop-webmail/tree/master/build/owncloud
|
||||||
|
*/
|
||||||
|
|
||||||
|
OCP\User::checkAdminUser();
|
||||||
|
|
||||||
|
OCP\Util::addScript('rainloop', 'admin');
|
||||||
|
|
||||||
|
$oTemplate = new OCP\Template('rainloop', 'admin-local');
|
||||||
|
$oTemplate->assign('rainloop-admin-panel-link', OC_RainLoop_Helper::getAppUrl().'?admin');
|
||||||
|
$oTemplate->assign('rainloop-autologin', OCP\Config::getAppValue('rainloop', 'rainloop-autologin', false));
|
||||||
|
return $oTemplate->fetchPage();
|
||||||
35
build/owncloud/rainloop-app/ajax/admin.php
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ownCloud - RainLoop mail plugin
|
||||||
|
*
|
||||||
|
* @author RainLoop Team
|
||||||
|
*
|
||||||
|
* https://github.com/RainLoop/rainloop-webmail/tree/master/build/owncloud
|
||||||
|
*/
|
||||||
|
|
||||||
|
OCP\JSON::checkAdminUser();
|
||||||
|
OCP\JSON::checkAppEnabled('rainloop');
|
||||||
|
OCP\JSON::callCheck();
|
||||||
|
|
||||||
|
$sUrl = '';
|
||||||
|
$sPath = '';
|
||||||
|
$bAutologin = false;
|
||||||
|
|
||||||
|
if (isset($_POST['appname']) && 'rainloop' === $_POST['appname'])
|
||||||
|
{
|
||||||
|
OCP\Config::setAppValue('rainloop', 'rainloop-autologin', isset($_POST['rainloop-autologin']) ?
|
||||||
|
'1' === $_POST['rainloop-autologin'] : false);
|
||||||
|
|
||||||
|
$bAutologin = OCP\Config::getAppValue('rainloop', 'rainloop-autologin', false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sleep(1);
|
||||||
|
OC_JSON::error(array('Message' => 'Invalid Argument(s)'));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
sleep(1);
|
||||||
|
OCP\JSON::success(array('Message' => 'Saved successfully'));
|
||||||
|
return true;
|
||||||
46
build/owncloud/rainloop-app/ajax/personal.php
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ownCloud - RainLoop mail plugin
|
||||||
|
*
|
||||||
|
* @author RainLoop Team
|
||||||
|
*
|
||||||
|
* https://github.com/RainLoop/rainloop-webmail/tree/master/build/owncloud
|
||||||
|
*/
|
||||||
|
|
||||||
|
OCP\JSON::checkLoggedIn();
|
||||||
|
OCP\JSON::checkAppEnabled('rainloop');
|
||||||
|
OCP\JSON::callCheck();
|
||||||
|
|
||||||
|
$sEmail = '';
|
||||||
|
$sLogin = '';
|
||||||
|
|
||||||
|
if (isset($_POST['appname'], $_POST['rainloop-password'], $_POST['rainloop-email']) && 'rainloop' === $_POST['appname'])
|
||||||
|
{
|
||||||
|
$sUser = OCP\User::getUser();
|
||||||
|
|
||||||
|
$sPostEmail = $_POST['rainloop-email'];
|
||||||
|
|
||||||
|
OCP\Config::setUserValue($sUser, 'rainloop', 'rainloop-email', $sPostEmail);
|
||||||
|
|
||||||
|
$sPass = $_POST['rainloop-password'];
|
||||||
|
if ('******' !== $sPass && '' !== $sPass)
|
||||||
|
{
|
||||||
|
include_once OC_App::getAppPath('rainloop').'/lib/RainLoopHelper.php';
|
||||||
|
|
||||||
|
OCP\Config::setUserValue($sUser, 'rainloop', 'rainloop-password',
|
||||||
|
OC_RainLoop_Helper::encodePassword($sPass, md5($sPostEmail)));
|
||||||
|
}
|
||||||
|
|
||||||
|
$sEmail = OCP\Config::getUserValue($sUser, 'rainloop', 'rainloop-email', '');
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sleep(1);
|
||||||
|
OC_JSON::error(array('Message' => 'Invalid argument(s)', 'Email' => $sEmail));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
sleep(1);
|
||||||
|
OCP\JSON::success(array('Message' => 'Saved successfully', 'Email' => $sEmail));
|
||||||
|
return true;
|
||||||
36
build/owncloud/rainloop-app/app.php
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
OCP\User::checkLoggedIn();
|
||||||
|
|
||||||
|
if (@file_exists(__DIR__.'/app/index.php'))
|
||||||
|
{
|
||||||
|
include_once OC_App::getAppPath('rainloop').'/lib/RainLoopHelper.php';
|
||||||
|
|
||||||
|
OC_RainLoop_Helper::regRainLoopDataFunction();
|
||||||
|
|
||||||
|
if (isset($_GET['OwnCloudAuth']))
|
||||||
|
{
|
||||||
|
$sEmail = '';
|
||||||
|
$sEncodedPassword = '';
|
||||||
|
|
||||||
|
$sUser = OCP\User::getUser();
|
||||||
|
|
||||||
|
if (OCP\Config::getAppValue('rainloop', 'rainloop-autologin', false))
|
||||||
|
{
|
||||||
|
$sEmail = $sUser;
|
||||||
|
$sEncodedPassword = OCP\Config::getUserValue($sUser, 'rainloop', 'rainloop-autologin-password', '');
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$sEmail = OCP\Config::getUserValue($sUser, 'rainloop', 'rainloop-email', '');
|
||||||
|
$sEncodedPassword = OCP\Config::getUserValue($sUser, 'rainloop', 'rainloop-password', '');
|
||||||
|
}
|
||||||
|
|
||||||
|
$sDecodedPassword = OC_RainLoop_Helper::decodePassword($sEncodedPassword, md5($sEmail));
|
||||||
|
|
||||||
|
$_ENV['___rainloop_owncloud_email'] = $sEmail;
|
||||||
|
$_ENV['___rainloop_owncloud_password'] = $sDecodedPassword;
|
||||||
|
}
|
||||||
|
|
||||||
|
include __DIR__.'/app/index.php';
|
||||||
|
}
|
||||||
33
build/owncloud/rainloop-app/appinfo/app.php
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ownCloud - RainLoop mail plugin
|
||||||
|
*
|
||||||
|
* @author RainLoop Team
|
||||||
|
*
|
||||||
|
* https://github.com/RainLoop/owncloud
|
||||||
|
*/
|
||||||
|
|
||||||
|
OC::$CLASSPATH['OC_RainLoop_Helper'] = OC_App::getAppPath('rainloop') . '/lib/RainLoopHelper.php';
|
||||||
|
|
||||||
|
OCP\App::registerAdmin('rainloop', 'admin');
|
||||||
|
OCP\App::registerPersonal('rainloop', 'personal');
|
||||||
|
|
||||||
|
if (OCP\Config::getAppValue('rainloop', 'rainloop-autologin', false))
|
||||||
|
{
|
||||||
|
OCP\Util::connectHook('OC_User', 'post_login', 'OC_RainLoop_Helper', 'login');
|
||||||
|
OCP\Util::connectHook('OC_User', 'post_setPassword', 'OC_RainLoop_Helper', 'changePassword');
|
||||||
|
}
|
||||||
|
|
||||||
|
OCP\Util::connectHook('OC_User', 'logout', 'OC_RainLoop_Helper', 'logout');
|
||||||
|
|
||||||
|
OCP\Util::addScript('rainloop', 'rainloop');
|
||||||
|
|
||||||
|
OCP\App::addNavigationEntry(array(
|
||||||
|
'id' => 'rainloop_index',
|
||||||
|
'order' => 10,
|
||||||
|
'href' => OCP\Util::linkToRoute('rainloop_index'),
|
||||||
|
'icon' => OCP\Util::imagePath('rainloop', 'mail.png'),
|
||||||
|
'name' => 'Email'
|
||||||
|
));
|
||||||
|
|
||||||
20
build/owncloud/rainloop-app/appinfo/info.xml
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<info xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://apps.nextcloud.com/schema/apps/info.xsd">
|
||||||
|
<id>rainloop</id>
|
||||||
|
<name>RainLoop</name>
|
||||||
|
<summary>RainLoop Webmail</summary>
|
||||||
|
<description>Simple, modern and fast web-based email client.</description>
|
||||||
|
<version>0.0</version>
|
||||||
|
<licence></licence>
|
||||||
|
<author>RainLoop Team</author>
|
||||||
|
<require>6.0</require>
|
||||||
|
<ocsid>165254</ocsid>
|
||||||
|
<dependencies>
|
||||||
|
<php min-version="5.4" />
|
||||||
|
<owncloud min-version="6" max-version="9.2" />
|
||||||
|
<nextcloud min-version="8" max-version="11" />
|
||||||
|
</dependencies>
|
||||||
|
<category>tools</category>
|
||||||
|
<website>https://www.rainloop.net/</website>
|
||||||
|
<bugs>https://github.com/RainLoop/rainloop-webmail/issues</bugs>
|
||||||
|
</info>
|
||||||
13
build/owncloud/rainloop-app/appinfo/routes.php
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
$this->create('rainloop_index', '/')
|
||||||
|
->actionInclude('rainloop/index.php');
|
||||||
|
|
||||||
|
$this->create('rainloop_app', '/app/')
|
||||||
|
->actionInclude('rainloop/app.php');
|
||||||
|
|
||||||
|
$this->create('rainloop_ajax_personal', 'ajax/personal.php')
|
||||||
|
->actionInclude('rainloop/ajax/personal.php');
|
||||||
|
|
||||||
|
$this->create('rainloop_ajax_admin', 'ajax/admin.php')
|
||||||
|
->actionInclude('rainloop/ajax/admin.php');
|
||||||
6
build/owncloud/rainloop-app/css/style.css
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
/*
|
||||||
|
Empty style sheet!
|
||||||
|
Only needed to give you the opportunity to theme the owncloud part
|
||||||
|
of the rainloop app with the theming system integrated in ownCoud
|
||||||
|
if the rainloop app is activated.
|
||||||
|
*/
|
||||||
BIN
build/owncloud/rainloop-app/img/logo-64x64.png
Executable file
|
After Width: | Height: | Size: 832 B |
BIN
build/owncloud/rainloop-app/img/mail.png
Executable file
|
After Width: | Height: | Size: 478 B |
26
build/owncloud/rainloop-app/index.php
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ownCloud - RainLoop mail plugin
|
||||||
|
*
|
||||||
|
* @author RainLoop Team
|
||||||
|
*
|
||||||
|
* https://github.com/RainLoop/rainloop-webmail/tree/master/build/owncloud
|
||||||
|
*/
|
||||||
|
|
||||||
|
OCP\User::checkLoggedIn();
|
||||||
|
OCP\App::checkAppEnabled('rainloop');
|
||||||
|
OCP\App::setActiveNavigationEntry('rainloop_index');
|
||||||
|
|
||||||
|
// Load the empty file ../css/style.css, that's needed to allow theming of
|
||||||
|
// the ownCloud header and navigation if rainloop is the active app.
|
||||||
|
OCP\Util::addStyle('rainloop', 'style');
|
||||||
|
|
||||||
|
include_once OC_App::getAppPath('rainloop').'/lib/RainLoopHelper.php';
|
||||||
|
|
||||||
|
$sUrl = OC_RainLoop_Helper::normalizeUrl(OC_RainLoop_Helper::getAppUrl());
|
||||||
|
|
||||||
|
$oTemplate = new OCP\Template('rainloop', 'index', 'user');
|
||||||
|
$oTemplate->assign('rainloop-iframe-url', OC_RainLoop_Helper::normalizeUrl($sUrl).'?OwnCloudAuth');
|
||||||
|
|
||||||
|
$oTemplate->printpage();
|
||||||
12
build/owncloud/rainloop-app/js/admin.js
Executable file
|
|
@ -0,0 +1,12 @@
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ownCloud - RainLoop mail plugin
|
||||||
|
*
|
||||||
|
* @author RainLoop Team
|
||||||
|
*
|
||||||
|
* https://github.com/RainLoop/rainloop-webmail/tree/master/build/owncloud
|
||||||
|
*/
|
||||||
|
|
||||||
|
$(function() {
|
||||||
|
RainLoopFormHelper('#mail-rainloop-admin-form', 'admin.php');
|
||||||
|
});
|
||||||