2
0
Эх сурвалжийг харах

Merge pull request #4882 from mailcow/staging

2022-11 Update
Niklas Meyer 2 жил өмнө
parent
commit
6d8c978d17

+ 1 - 1
.github/workflows/pr_to_nightly.yml

@@ -12,7 +12,7 @@ jobs:
         with:
           fetch-depth: 0
       - name: Run the Action
-        uses: devops-infra/action-pull-request@v0.5.1
+        uses: devops-infra/action-pull-request@v0.5.3
         with:
           github_token: ${{ secrets.PRTONIGHTLY_ACTION_PAT }}
           title: Automatic PR to nightly from ${{ github.event.repository.updated_at}}

+ 34 - 0
.github/workflows/rebuild_backup_image.yml

@@ -0,0 +1,34 @@
+name: Build mailcow backup image
+
+on:
+  schedule:
+    # At 00:00 on Sunday
+    - cron: "0 0 * * 0"
+  workflow_dispatch: # Allow to run workflow manually
+
+jobs:
+  docker_image_build:
+    runs-on: ubuntu-latest
+    steps:
+      - name: Checkout
+        uses: actions/checkout@v3
+
+      - name: Set up QEMU
+        uses: docker/setup-qemu-action@v2
+
+      - name: Set up Docker Buildx
+        uses: docker/setup-buildx-action@v2
+
+      - name: Login to Docker Hub
+        uses: docker/login-action@v2
+        with:
+          username: ${{ secrets.BACKUPIMAGEBUILD_ACTION_DOCKERHUB_USERNAME }}
+          password: ${{ secrets.BACKUPIMAGEBUILD_ACTION_DOCKERHUB_TOKEN }}
+
+      - name: Build and push
+        uses: docker/build-push-action@v3
+        with:
+          context: .
+          file: data/Dockerfiles/backup/Dockerfile
+          push: true
+          tags: mailcow/backup:latest

+ 25 - 11
data/Dockerfiles/phpfpm/Dockerfile

@@ -1,12 +1,12 @@
-FROM php:8.0-fpm-alpine3.16
+FROM php:8.1-fpm-alpine3.16
 LABEL maintainer "Andre Peters <andre.peters@servercow.de>"
 
-ENV APCU_PECL 5.1.21
+ENV APCU_PECL 5.1.22
 ENV IMAGICK_PECL 3.7.0
-# Mailparse is pulled from master branch
-#ENV MAILPARSE_PECL 3.0.2
+ENV MAILPARSE_PECL 3.1.4
 ENV MEMCACHED_PECL 3.2.0
 ENV REDIS_PECL 5.3.7
+ENV COMPOSER 2.4.4
 
 RUN apk add -U --no-cache autoconf \
   aspell-dev \
@@ -18,6 +18,7 @@ RUN apk add -U --no-cache autoconf \
   freetype-dev \
   g++ \
   git \
+  gettext \
   gettext-dev \
   gmp-dev \
   gnupg \
@@ -27,8 +28,11 @@ RUN apk add -U --no-cache autoconf \
   imagemagick-dev \
   imap-dev \
   jq \
+  libavif \
+  libavif-dev \
   libjpeg-turbo \
   libjpeg-turbo-dev \
+  libmemcached \
   libmemcached-dev \
   libpng \
   libpng-dev \
@@ -38,7 +42,9 @@ RUN apk add -U --no-cache autoconf \
   libtool \
   libwebp-dev \
   libxml2-dev \
+  libxpm \
   libxpm-dev \
+  libzip \
   libzip-dev \
   make \
   mysql-client \
@@ -49,22 +55,24 @@ RUN apk add -U --no-cache autoconf \
   samba-client \
   zlib-dev \
   tzdata \
-  && git clone https://github.com/php/pecl-mail-mailparse \
-  && cd pecl-mail-mailparse \
-  && pecl install package.xml \
-  && cd .. \
-  && rm -r pecl-mail-mailparse \
-  && pecl install redis-${REDIS_PECL} memcached-${MEMCACHED_PECL} APCu-${APCU_PECL} imagick-${IMAGICK_PECL} \
+  && pecl install mailparse-${MAILPARSE_PECL} \
+  && pecl install redis-${REDIS_PECL} \
+  && pecl install memcached-${MEMCACHED_PECL} \
+  && pecl install APCu-${APCU_PECL} \
+  && pecl install imagick-${IMAGICK_PECL} \
   && docker-php-ext-enable apcu imagick memcached mailparse redis \
   && pecl clear-cache \
   && docker-php-ext-configure intl \
   && docker-php-ext-configure exif \
   && docker-php-ext-configure gd --with-freetype=/usr/include/ \  
     --with-jpeg=/usr/include/ \
+    --with-webp \
+    --with-xpm \
+    --with-avif \
   && docker-php-ext-install -j 4 exif gd gettext intl ldap opcache pcntl pdo pdo_mysql pspell soap sockets zip bcmath gmp \
   && docker-php-ext-configure imap --with-imap --with-imap-ssl \
   && docker-php-ext-install -j 4 imap \
-  && curl --silent --show-error https://getcomposer.org/installer | php \
+  && curl --silent --show-error https://getcomposer.org/installer | php -- --version=${COMPOSER} \
   && mv composer.phar /usr/local/bin/composer \
   && chmod +x /usr/local/bin/composer \
   && apk del --purge autoconf \
@@ -72,15 +80,21 @@ RUN apk add -U --no-cache autoconf \
     cyrus-sasl-dev \
     freetype-dev \
     g++ \
+    gettext-dev \
     icu-dev \
     imagemagick-dev \
     imap-dev \
+    libavif-dev \
     libjpeg-turbo-dev \
+    libmemcached-dev \
     libpng-dev \
     libressl-dev \
     libwebp-dev \
     libxml2-dev \
+    libxpm-dev \
+    libzip-dev \
     make \
+    openldap-dev \
     pcre-dev \
     zlib-dev
 

+ 1 - 2
data/conf/rspamd/local.d/metadata_exporter.conf

@@ -16,8 +16,7 @@ rules {
     backend = "http";
     url = "http://nginx:9081/pushover.php";
     selector = "mailcow_rcpt";
-    # Only return msgid, do not parse the full message
-    formatter = "msgid";
+    formatter = "json";
     meta_headers = true;
   }
 }

+ 24 - 2
data/conf/rspamd/meta_exporter/pushover.php

@@ -47,6 +47,7 @@ if (!function_exists('getallheaders'))  {
 }
 
 $headers = getallheaders();
+$json_body = json_decode(file_get_contents('php://input'));
 
 $qid      = $headers['X-Rspamd-Qid'];
 $rcpts    = $headers['X-Rspamd-Rcpt'];
@@ -65,6 +66,20 @@ if (is_array($symbols_array)) {
   }
 }
 
+$sender_address = $json_body->header_from[0];
+$sender_name = '-';
+if (preg_match('/(?<name>.*?)<(?<address>.*?)>/i', $sender_address, $matches)) {
+	$sender_address = $matches['address'];
+  $sender_name =  trim($matches['name'], '"\' ');
+}
+
+$to_address = $json_body->header_to[0];
+$to_name = '-';
+if (preg_match('/(?<name>.*?)<(?<address>.*?)>/i', $to_address, $matches)) {
+	$to_address = $matches['address'];
+  $to_name =  trim($matches['name'], '"\' ');
+}
+
 $rcpt_final_mailboxes = array();
 
 // Loop through all rcpts
@@ -229,9 +244,16 @@ foreach ($rcpt_final_mailboxes as $rcpt_final) {
     $post_fields = array(
       "token" => $api_data['token'],
       "user" => $api_data['key'],
-      "title" => sprintf("%s", str_replace(array('{SUBJECT}', '{SENDER}'), array($subject, $sender), $title)),
+      "title" => sprintf("%s", str_replace(
+        array('{SUBJECT}', '{SENDER}', '{SENDER_NAME}', '{SENDER_ADDRESS}', '{TO_NAME}', '{TO_ADDRESS}'), 
+        array($subject, $sender, $sender_name, $sender_address, $to_name, $to_address), $title)
+      ),
       "priority" => $priority,
-      "message" => sprintf("%s", str_replace(array('{SUBJECT}', '{SENDER}'), array($subject, $sender), $text))
+      "message" => sprintf("%s", str_replace(
+        array('{SUBJECT}', '{SENDER}', '{SENDER_NAME}', '{SENDER_ADDRESS}', '{TO_NAME}', '{TO_ADDRESS}', '\n'),
+        array($subject, $sender, $sender_name, $sender_address, $to_name, $to_address, PHP_EOL), $text)
+      ),
+      "sound" => $attributes['sound'] ?? "pushover"
     );
     if ($attributes['evaluate_x_prio'] == "1" && $priority == 1) {
       $post_fields['expire'] = 600;

+ 59 - 0
data/web/api/openapi.yaml

@@ -3349,6 +3349,7 @@ paths:
                           evaluate_x_prio: "0"
                           key: 21e8918e1jksdjcpis712
                           only_x_prio: "0"
+                          sound: "pushover"
                           senders: ""
                           senders_regex: ""
                           text: ""
@@ -3392,6 +3393,7 @@ paths:
                   evaluate_x_prio: "0"
                   key: 21e8918e1jksdjcpis712
                   only_x_prio: "0"
+                  sound: "pushover"
                   senders: ""
                   senders_regex: ""
                   text: ""
@@ -3413,6 +3415,9 @@ paths:
                     only_x_prio:
                       description: Only send push for prio mails
                       type: number
+                    sound:
+                      description: Set notification sound
+                      type: string
                     senders:
                       description: Only send push for emails from these senders
                       type: string
@@ -5501,6 +5506,60 @@ paths:
                   attr:
                     spam_score: "8,15"
       summary: Edit mailbox spam filter score
+  "/api/v1/get/mailbox/all/{domain}":
+    get:
+      parameters:
+        - description: name of domain
+          in: path
+          name: domain
+          required: false
+          schema:
+            type: string
+        - description: e.g. api-key-string
+          example: api-key-string
+          in: header
+          name: X-API-Key
+          required: false
+          schema:
+            type: string
+      responses:
+        "401":
+          $ref: "#/components/responses/Unauthorized"
+        "200":
+          content:
+            application/json:
+              examples:
+                response:
+                  value:
+                    - active: "1"
+                      attributes:
+                        force_pw_update: "0"
+                        mailbox_format: "maildir:"
+                        quarantine_notification: never
+                        sogo_access: "1"
+                        tls_enforce_in: "0"
+                        tls_enforce_out: "0"
+                      domain: domain3.tld
+                      is_relayed: 0
+                      local_part: info
+                      max_new_quota: 10737418240
+                      messages: 0
+                      name: Full name
+                      percent_class: success
+                      percent_in_use: 0
+                      quota: 3221225472
+                      quota_used: 0
+                      rl: false
+                      spam_aliases: 0
+                      username: info@domain3.tld
+                      tags: ["tag1", "tag2"]
+          description: OK
+          headers: {}
+      tags:
+        - Mailboxes
+      description: You can list all mailboxes existing in system for a specific domain.
+      operationId: Get mailboxes of a domain
+      summary: Get mailboxes of a domain
 
 tags:
   - name: Domains

+ 3 - 1
data/web/inc/functions.pushover.inc.php

@@ -51,6 +51,7 @@ function pushover($_action, $_data = null) {
           $active = (isset($_data['active'])) ? intval($_data['active']) : $is_now['active'];
           $evaluate_x_prio = (isset($_data['evaluate_x_prio'])) ? intval($_data['evaluate_x_prio']) : $is_now['evaluate_x_prio'];
           $only_x_prio = (isset($_data['only_x_prio'])) ? intval($_data['only_x_prio']) : $is_now['only_x_prio'];
+          $sound = (isset($_data['sound'])) ? $_data['sound'] : $is_now['sound'];
         }
         else {
           $_SESSION['return'][] = array(
@@ -101,7 +102,8 @@ function pushover($_action, $_data = null) {
         $po_attributes = json_encode(
           array(
             'evaluate_x_prio' => strval(intval($evaluate_x_prio)),
-            'only_x_prio' => strval(intval($only_x_prio))
+            'only_x_prio' => strval(intval($only_x_prio)),
+            'sound' => strval($sound)
           )
         );
         $stmt = $pdo->prepare("REPLACE INTO `pushover` (`username`, `key`, `attributes`, `senders_regex`, `senders`, `token`, `title`, `text`, `active`)

+ 2 - 1
data/web/inc/init_db.inc.php

@@ -3,7 +3,7 @@ function init_db_schema() {
   try {
     global $pdo;
 
-    $db_version = "25072022_2300";
+    $db_version = "17112022_2115";
 
     $stmt = $pdo->query("SHOW TABLES LIKE 'versions'");
     $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
@@ -1264,6 +1264,7 @@ function init_db_schema() {
     $pdo->query("UPDATE `pushover` SET `attributes` = '{}' WHERE `attributes` = '' OR `attributes` IS NULL;");
     $pdo->query("UPDATE `pushover` SET `attributes` =  JSON_SET(`attributes`, '$.evaluate_x_prio', \"0\") WHERE JSON_VALUE(`attributes`, '$.evaluate_x_prio') IS NULL;");
     $pdo->query("UPDATE `pushover` SET `attributes` =  JSON_SET(`attributes`, '$.only_x_prio', \"0\") WHERE JSON_VALUE(`attributes`, '$.only_x_prio') IS NULL;");
+    $pdo->query("UPDATE `pushover` SET `attributes` =  JSON_SET(`attributes`, '$.sound', \"pushover\") WHERE JSON_VALUE(`attributes`, '$.sound') IS NULL;");
     // mailbox
     $pdo->query("UPDATE `mailbox` SET `attributes` = '{}' WHERE `attributes` = '' OR `attributes` IS NULL;");
     $pdo->query("UPDATE `mailbox` SET `attributes` =  JSON_SET(`attributes`, '$.passwd_update', \"0\") WHERE JSON_VALUE(`attributes`, '$.passwd_update') IS NULL;");

+ 2 - 0
data/web/lang/lang.en-gb.json

@@ -574,6 +574,7 @@
         "pushover_sender_regex": "Consider the following sender regex",
         "pushover_text": "Notification text",
         "pushover_title": "Notification title",
+        "pushover_sound": "Sound",
         "pushover_vars": "When no sender filter is defined, all mails will be considered.<br>Regex filters as well as exact sender checks can be defined individually and will be considered sequentially. They do not depend on each other.<br>Useable variables for text and title (please take note of data protection policies)",
         "pushover_verify": "Verify credentials",
         "quota_mb": "Quota (MiB)",
@@ -1097,6 +1098,7 @@
         "pushover_sender_regex": "Match senders by the following regex",
         "pushover_text": "Notification text",
         "pushover_title": "Notification title",
+        "pushover_sound": "Sound",
         "pushover_vars": "When no sender filter is defined, all mails will be considered.<br>Regex filters as well as exact sender checks can be defined individually and will be considered sequentially. They do not depend on each other.<br>Useable variables for text and title (please take note of data protection policies)",
         "pushover_verify": "Verify credentials",
         "q_add_header": "Junk folder",

+ 2 - 0
data/web/lang/lang.nl-nl.json

@@ -536,6 +536,7 @@
         "pushover_sender_regex": "Uitsluitend een afzender met de volgende regex",
         "pushover_text": "Meldingstekst ({SUBJECT} zal worden vervangen door het onderwerp)",
         "pushover_title": "Meldingstitel",
+        "pushover_sound": "Geluid",
         "pushover_vars": "Wanneer er geen afzenders zijn uitgesloten zullen alle mails doorkomen.<br>Regex-filters en afzendercontroles kunnen individueel worden ingesteld en zullen in volgorde worden verwerkt. Ze zijn niet afhankelijk van elkaar.<br>Bruikbare variabelen voor tekst en titel (neem het gegevensbeschermingsbeleid in acht)",
         "pushover_verify": "Verifieer aanmeldingsgegevens",
         "quota_mb": "Quota (MiB)",
@@ -1002,6 +1003,7 @@
         "pushover_sender_regex": "Uitsluitend een afzender met de volgende regex",
         "pushover_text": "Meldingstekst ({SUBJECT} zal worden vervangen door het onderwerp)",
         "pushover_title": "Meldingstitel",
+        "pushover_sound": "Geluid",
         "pushover_vars": "Wanneer er geen afzenders zijn uitgesloten zullen alle mails doorkomen.<br>Regex-filters en afzendercontroles kunnen individueel worden ingesteld en zullen in volgorde worden verwerkt. Ze zijn niet afhankelijk van elkaar.<br>Bruikbare variabelen voor tekst en titel (let op het gegevensbeschermingsbeleid)",
         "pushover_verify": "Verifieer aanmeldingsgegevens",
         "q_add_header": "Spamfolder",

+ 1 - 1
data/web/lang/lang.sk-sk.json

@@ -106,7 +106,7 @@
         "username": "Používateľské meno",
         "validate": "Overiť",
         "validation_success": "Úspešne overené",
-        "app_passwd_protocols": "Povolené protokoly"
+        "app_passwd_protocols": "Povolené protokoly k heslu aplikácie"
     },
     "admin": {
         "access": "Prístup",

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 385 - 293
data/web/lang/lang.zh-cn.json


+ 31 - 1
data/web/templates/edit/mailbox.twig

@@ -275,7 +275,7 @@
         </div>
         <div class="col-sm-10">
           <p class="help-block">{{ lang.user.pushover_info|format(mailbox)|raw }}</p>
-          <p class="help-block">{{ lang.edit.pushover_vars|raw }}: <code>{SUBJECT}</code>, <code>{SENDER}</code></p>
+          <p class="help-block">{{ lang.edit.pushover_vars|raw }}: <code>{SUBJECT}</code>, <code>{SENDER}</code>, <code>{SENDER_ADDRESS}</code>, <code>{SENDER_NAME}</code>, <code>{TO_NAME}</code>, <code>{TO_ADDRESS}</code></p>
           <div class="form-group">
             <div class="row">
               <div class="col-sm-6">
@@ -308,6 +308,36 @@
                   <input type="text" class="form-control" name="senders" value="{{ pushover_data.senders }}" placeholder="sender1@example.com, sender2@example.com">
                 </div>
               </div>
+              <div class="col-sm-12">
+                <div class="form-group">
+                  <label for="sound">{{ lang.edit.pushover_sound }}</label><br>
+                  <select name="sound" class="form-control">
+                    <option value="pushover"{% if pushover_data.attributes.sound == 'pushover' %} selected{% endif %}>Pushover (default)</option>
+                    <option value="bike"{% if pushover_data.attributes.sound == 'bike' %} selected{% endif %}>Bike</option>
+                    <option value="bugle"{% if pushover_data.attributes.sound == 'bugle' %} selected{% endif %}>Bugle</option>
+                    <option value="cashregister"{% if pushover_data.attributes.sound == 'cashregister' %} selected{% endif %}>Cash Register</option>
+                    <option value="classical"{% if pushover_data.attributes.sound == 'classical' %} selected{% endif %}>Classical</option>
+                    <option value="cosmic"{% if pushover_data.attributes.sound == 'cosmic' %} selected{% endif %}>Cosmic</option>
+                    <option value="falling"{% if pushover_data.attributes.sound == 'falling' %} selected{% endif %}>Falling</option>
+                    <option value="gamelan"{% if pushover_data.attributes.sound == 'gamelan' %} selected{% endif %}>Gamelan</option>
+                    <option value="incoming"{% if pushover_data.attributes.sound == 'incoming' %} selected{% endif %}>Incoming</option>
+                    <option value="intermission"{% if pushover_data.attributes.sound == 'intermission' %} selected{% endif %}>Intermission</option>
+                    <option value="magic"{% if pushover_data.attributes.sound == 'magic' %} selected{% endif %}>Magic</option>
+                    <option value="mechanical"{% if pushover_data.attributes.sound == 'mechanical' %} selected{% endif %}>Mechanical</option>
+                    <option value="pianobar"{% if pushover_data.attributes.sound == 'pianobar' %} selected{% endif %}>Piano Bar</option>
+                    <option value="siren"{% if pushover_data.attributes.sound == 'siren' %} selected{% endif %}>Siren</option>
+                    <option value="spacealarm"{% if pushover_data.attributes.sound == 'spacealarm' %} selected{% endif %}>Space Alarm</option>
+                    <option value="tugboat"{% if pushover_data.attributes.sound == 'tugboat' %} selected{% endif %}>Tug Boat</option>
+                    <option value="alien"{% if pushover_data.attributes.sound == 'alien' %} selected{% endif %}>Alien Alarm (long)</option>
+                    <option value="climb"{% if pushover_data.attributes.sound == 'climb' %} selected{% endif %}>Climb (long)</option>
+                    <option value="persistent"{% if pushover_data.attributes.sound == 'persistent' %} selected{% endif %}>Persistent (long)</option>
+                    <option value="echo"{% if pushover_data.attributes.sound == 'echo' %} selected{% endif %}>Pushover Echo (long)</option>
+                    <option value="updown"{% if pushover_data.attributes.sound == 'updown' %} selected{% endif %}>Up Down (long)</option>
+                    <option value="vibrate"{% if pushover_data.attributes.sound == 'vibrate' %} selected{% endif %}>Vibrate Only</option>
+                    <option value="none"{% if pushover_data.attributes.sound == 'none' %} selected{% endif %}> None (silent) </option>
+                  </select>
+                </div>
+              </div>
               <div class="col-sm-12">
                 <div class="checkbox">
                   <label><input type="checkbox" value="1" name="active"{% if pushover_data.active == '1' %} checked{% endif %}> {{ lang.edit.active }}</label>

+ 31 - 1
data/web/templates/user/Pushover.twig

@@ -9,7 +9,7 @@
       </div>
       <div class="col-sm-10">
         <p class="help-block">{{ lang.user.pushover_info|format(mailcow_cc_username)|raw }}</p>
-        <p class="help-block">{{ lang.user.pushover_vars|raw }}: <code>{SUBJECT}</code>, <code>{SENDER}</code></p>
+        <p class="help-block">{{ lang.edit.pushover_vars|raw }}: <code>{SUBJECT}</code>, <code>{SENDER}</code>, <code>{SENDER_ADDRESS}</code>, <code>{SENDER_NAME}</code>, <code>{TO_NAME}</code>, <code>{TO_ADDRESS}</code></p>
         <div class="form-group">
           <div class="row">
             <div class="col-sm-6">
@@ -42,6 +42,36 @@
                 <input type="text" class="form-control" name="senders" value="{{ pushover_data.senders }}" placeholder="sender1@example.com, sender2@example.com">
               </div>
             </div>
+            <div class="col-sm-12">
+              <div class="form-group">
+                <label for="sound">{{ lang.edit.pushover_sound }}</label><br>
+                <select name="sound" class="form-control">
+                  <option value="pushover"{% if pushover_data.attributes.sound == 'pushover' %} selected{% endif %}>Pushover (default)</option>
+                  <option value="bike"{% if pushover_data.attributes.sound == 'bike' %} selected{% endif %}>Bike</option>
+                  <option value="bugle"{% if pushover_data.attributes.sound == 'bugle' %} selected{% endif %}>Bugle</option>
+                  <option value="cashregister"{% if pushover_data.attributes.sound == 'cashregister' %} selected{% endif %}>Cash Register</option>
+                  <option value="classical"{% if pushover_data.attributes.sound == 'classical' %} selected{% endif %}>Classical</option>
+                  <option value="cosmic"{% if pushover_data.attributes.sound == 'cosmic' %} selected{% endif %}>Cosmic</option>
+                  <option value="falling"{% if pushover_data.attributes.sound == 'falling' %} selected{% endif %}>Falling</option>
+                  <option value="gamelan"{% if pushover_data.attributes.sound == 'gamelan' %} selected{% endif %}>Gamelan</option>
+                  <option value="incoming"{% if pushover_data.attributes.sound == 'incoming' %} selected{% endif %}>Incoming</option>
+                  <option value="intermission"{% if pushover_data.attributes.sound == 'intermission' %} selected{% endif %}>Intermission</option>
+                  <option value="magic"{% if pushover_data.attributes.sound == 'magic' %} selected{% endif %}>Magic</option>
+                  <option value="mechanical"{% if pushover_data.attributes.sound == 'mechanical' %} selected{% endif %}>Mechanical</option>
+                  <option value="pianobar"{% if pushover_data.attributes.sound == 'pianobar' %} selected{% endif %}>Piano Bar</option>
+                  <option value="siren"{% if pushover_data.attributes.sound == 'siren' %} selected{% endif %}>Siren</option>
+                  <option value="spacealarm"{% if pushover_data.attributes.sound == 'spacealarm' %} selected{% endif %}>Space Alarm</option>
+                  <option value="tugboat"{% if pushover_data.attributes.sound == 'tugboat' %} selected{% endif %}>Tug Boat</option>
+                  <option value="alien"{% if pushover_data.attributes.sound == 'alien' %} selected{% endif %}>Alien Alarm (long)</option>
+                  <option value="climb"{% if pushover_data.attributes.sound == 'climb' %} selected{% endif %}>Climb (long)</option>
+                  <option value="persistent"{% if pushover_data.attributes.sound == 'persistent' %} selected{% endif %}>Persistent (long)</option>
+                  <option value="echo"{% if pushover_data.attributes.sound == 'echo' %} selected{% endif %}>Pushover Echo (long)</option>
+                  <option value="updown"{% if pushover_data.attributes.sound == 'updown' %} selected{% endif %}>Up Down (long)</option>
+                  <option value="vibrate"{% if pushover_data.attributes.sound == 'vibrate' %} selected{% endif %}>Vibrate Only</option>
+                  <option value="none"{% if pushover_data.attributes.sound == 'none' %} selected{% endif %}> None (silent) </option>
+                </select>
+              </div>
+            </div>
             <div class="col-sm-12">
               <div class="checkbox">
                 <label><input type="checkbox" value="1" name="active"{% if pushover_data.active == '1' %} checked{% endif %}> {{ lang.user.active }}</label>

+ 3 - 3
docker-compose.yml

@@ -76,7 +76,7 @@ services:
             - clamd
 
     rspamd-mailcow:
-      image: mailcow/rspamd:1.90
+      image: mailcow/rspamd:1.91
       stop_grace_period: 30s
       depends_on:
         - dovecot-mailcow
@@ -106,7 +106,7 @@ services:
             - rspamd
 
     php-fpm-mailcow:
-      image: mailcow/phpfpm:1.79
+      image: mailcow/phpfpm:1.80
       command: "php-fpm -d date.timezone=${TZ} -d expose_php=0"
       depends_on:
         - redis-mailcow
@@ -168,7 +168,7 @@ services:
             - phpfpm
 
     sogo-mailcow:
-      image: mailcow/sogo:1.111
+      image: mailcow/sogo:1.112
       environment:
         - DBNAME=${DBNAME}
         - DBUSER=${DBUSER}

+ 4 - 4
helper-scripts/backup_and_restore.sh

@@ -1,6 +1,6 @@
 #!/usr/bin/env bash
 
-DEBIAN_DOCKER_IMAGE="mailcow/backup:1.0"
+DEBIAN_DOCKER_IMAGE="mailcow/backup:latest"
 
 if [[ ! -z ${MAILCOW_BACKUP_LOCATION} ]]; then
   BACKUP_LOCATION="${MAILCOW_BACKUP_LOCATION}"
@@ -58,7 +58,7 @@ if ! [[ "${THREADS}" =~ ^[1-9]+$ ]] ; then
   echo "Thread input is not a number!"
   exit 1
 elif [[ "${THREADS}" =~ ^[1-9]+$ ]] ; then
-  echo "Using ${THREADS} Thread(s) for this run." 
+  echo "Using ${THREADS} Thread(s) for this run."
   echo "Notice: You can set the Thread count with the THREADS Variable before you run this script."
 fi
 
@@ -181,7 +181,7 @@ function restore() {
 
   elif [ "${DOCKER_COMPOSE_VERSION}" == "standalone" ]; then
     COMPOSE_COMMAND="docker-compose"
-  
+
   else
     echo -e "\e[31mCan not read DOCKER_COMPOSE_VERSION variable from mailcow.conf! Is your mailcow up to date? Exiting...\e[0m"
     exit 1
@@ -380,4 +380,4 @@ elif [[ ${1} == "restore" ]]; then
   done
   echo "Restoring ${FILE_SELECTION[${input_sel}]} from ${RESTORE_POINT}..."
   restore "${RESTORE_POINT}" ${FILE_SELECTION[${input_sel}]}
-fi
+fi

+ 1 - 1
helper-scripts/docker-compose.override.yml.d/HAPROXY/docker-compose.override.yml

@@ -1,6 +1,6 @@
 ##
 ## Set haproxy_trusted_networks in Dovecots extra.conf!
-#ä
+##
 
 version: '2.1'
 services:

+ 1 - 1
helper-scripts/update_compose.sh

@@ -50,7 +50,7 @@ echo -e "\e[32mTrying to determine GLIBC version...\e[0m"
             exit 0
         else
             echo -e "\e[33mWARNING: $COMPOSE_PATH is not writable, but new version $LATEST_COMPOSE is available (installed: $COMPOSE_VERSION)\e[0m"
-            return 1
+            exit 1
         fi
         fi
     else

+ 3 - 3
update.sh

@@ -3,9 +3,9 @@
 ############## Begin Function Section ##############
 
 check_online_status() {
-  CHECK_ONLINE_IPS=(1.1.1.1 9.9.9.9 8.8.8.8)
-  for ip in "${CHECK_ONLINE_IPS[@]}"; do
-    if timeout 3 ping -c 1 ${ip} > /dev/null; then
+  CHECK_ONLINE_DOMAINS=('https://github.com' 'https://hub.docker.com')
+  for domain in "${CHECK_ONLINE_DOMAINS[@]}"; do
+    if timeout 3 curl --head --silent --output /dev/null ${domain}; then
       return 0
     fi
   done

Энэ ялгаанд хэт олон файл өөрчлөгдсөн тул зарим файлыг харуулаагүй болно