git subrepo clone https://github.com/mailcow/mailcow-dockerized.git mailcow/src/mailcow-dockerized
subrepo: subdir: "mailcow/src/mailcow-dockerized"
merged: "a832becb"
upstream: origin: "https://github.com/mailcow/mailcow-dockerized.git"
branch: "master"
commit: "a832becb"
git-subrepo: version: "0.4.3"
origin: "???"
commit: "???"
Change-Id: If5be2d621a211e164c9b6577adaa7884449f16b5
diff --git a/mailcow/src/mailcow-dockerized/data/conf/clamav/clamd.conf b/mailcow/src/mailcow-dockerized/data/conf/clamav/clamd.conf
new file mode 100644
index 0000000..df1aa1e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/clamav/clamd.conf
@@ -0,0 +1,47 @@
+#Debug true
+#LogFile /dev/null
+LogTime yes
+LogClean yes
+ExtendedDetectionInfo yes
+PidFile /run/clamav/clamd.pid
+OfficialDatabaseOnly no
+LocalSocket /run/clamav/clamd.sock
+TCPSocket 3310
+StreamMaxLength 25M
+MaxThreads 10
+ReadTimeout 10
+CommandReadTimeout 3
+SendBufTimeout 200
+MaxQueue 80
+IdleTimeout 20
+SelfCheck 3600
+User clamav
+Foreground yes
+DetectPUA yes
+# See https://github.com/vrtadmin/clamav-faq/blob/master/faq/faq-pua.md
+#ExcludePUA NetTool
+#ExcludePUA PWTool
+#IncludePUA Spy
+#IncludePUA Scanner
+#IncludePUA RAT
+HeuristicAlerts yes
+ScanOLE2 yes
+AlertOLE2Macros no
+ScanPDF yes
+ScanSWF yes
+ScanXMLDOCS yes
+ScanHWP3 yes
+ScanMail yes
+PhishingSignatures no
+PhishingScanURLs no
+HeuristicScanPrecedence yes
+ScanHTML yes
+ScanArchive yes
+MaxScanSize 50M
+MaxFileSize 25M
+MaxRecursion 5
+MaxFiles 200
+Bytecode yes
+BytecodeSecurity TrustSigned
+BytecodeTimeout 1000
+ConcurrentDatabaseReload no
diff --git a/mailcow/src/mailcow-dockerized/data/conf/clamav/freshclam.conf b/mailcow/src/mailcow-dockerized/data/conf/clamav/freshclam.conf
new file mode 100644
index 0000000..cfb497e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/clamav/freshclam.conf
@@ -0,0 +1,19 @@
+#UpdateLogFile /dev/console
+LogTime yes
+PidFile /run/clamav/freshclam.pid
+DatabaseOwner clamav
+DNSDatabaseInfo current.cvd.clamav.net
+DatabaseMirror db.uk.clamav.net
+DatabaseMirror db.nl.clamav.net
+DatabaseMirror db.fr.clamav.net
+DatabaseMirror db.ch.clamav.net
+MaxAttempts 4
+ScriptedUpdates yes
+Checks 6
+NotifyClamd /etc/clamav/clamd.conf
+Foreground yes
+ConnectTimeout 20
+ReceiveTimeout 20
+TestDatabases yes
+Bytecode yes
+
diff --git a/mailcow/src/mailcow-dockerized/data/conf/dovecot/dovecot.conf b/mailcow/src/mailcow-dockerized/data/conf/dovecot/dovecot.conf
new file mode 100644
index 0000000..cef7de8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/dovecot/dovecot.conf
@@ -0,0 +1,535 @@
+# --------------------------------------------------------------------------
+# Please create a file "extra.conf" for persistent overrides to dovecot.conf
+# --------------------------------------------------------------------------
+# LDAP example:
+#passdb {
+# args = /etc/dovecot/ldap/passdb.conf
+# driver = ldap
+#}
+
+auth_mechanisms = plain login
+#mail_debug = yes
+#auth_debug = yes
+log_path = syslog
+disable_plaintext_auth = yes
+# Uncomment on NFS share
+#mmap_disable = yes
+#mail_fsync = always
+#mail_nfs_index = yes
+#mail_nfs_storage = yes
+login_log_format_elements = "user=<%u> method=%m rip=%r lip=%l mpid=%e %c %k"
+mail_home = /var/vmail/%d/%n
+mail_location = maildir:~/
+mail_plugins = </etc/dovecot/mail_plugins
+mail_attachment_fs = crypt:set_prefix=mail_crypt_global:posix:
+mail_attachment_dir = /var/attachments
+mail_attachment_min_size = 128k
+
+# Dovecot 2.2
+#ssl_protocols = !SSLv3
+# Dovecot 2.3
+ssl_min_protocol = TLSv1.2
+
+ssl_prefer_server_ciphers = yes
+ssl_cipher_list = ALL:!ADH:!LOW:!SSLv2:!SSLv3:!EXP:!aNULL:!eNULL:!3DES:!MD5:!PSK:!DSS:!RC4:!SEED:!IDEA:+HIGH:+MEDIUM
+
+# Default in Dovecot 2.3
+ssl_options = no_compression no_ticket
+
+# New in Dovecot 2.3
+ssl_dh = </etc/ssl/mail/dhparams.pem
+# Dovecot 2.2
+#ssl_dh_parameters_length = 2048
+log_timestamp = "%Y-%m-%d %H:%M:%S "
+recipient_delimiter = +
+auth_master_user_separator = *
+mail_shared_explicit_inbox = yes
+mail_prefetch_count = 30
+# try a master passwd
+passdb {
+ driver = passwd-file
+ args = /etc/dovecot/dovecot-master.passwd
+ master = yes
+ pass = yes
+ result_failure = continue
+ result_internalfail = continue
+}
+# try an app passwd
+passdb {
+ driver = lua
+ args = file=/etc/dovecot/lua/app-passdb.lua blocking=yes
+ pass = yes
+ result_failure = continue
+ result_internalfail = continue
+}
+# check for regular password - if empty (e.g. force-passwd-reset), previous pass=yes passdbs also fail
+# a return of the following passdb is mandatory
+passdb {
+ args = /etc/dovecot/sql/dovecot-dict-sql-passdb.conf
+ driver = sql
+ result_success = return-ok
+ result_failure = continue
+ result_internalfail = continue
+}
+passdb {
+ driver = passwd-file
+ args = /etc/dovecot/dovecot-master.passwd
+ skip = authenticated
+}
+# Set doveadm_password=your-secret-password in data/conf/dovecot/extra.conf (create if missing)
+service doveadm {
+ inet_listener {
+ port = 12345
+ }
+ vsz_limit=2048 MB
+}
+namespace inbox {
+ inbox = yes
+ location =
+ separator = /
+ mailbox "Trash" {
+ auto = subscribe
+ special_use = \Trash
+ }
+ mailbox "Deleted Messages" {
+ special_use = \Trash
+ }
+ mailbox "Deleted Items" {
+ special_use = \Trash
+ }
+ mailbox "Rubbish" {
+ special_use = \Trash
+ }
+ mailbox "Gelöschte Objekte" {
+ special_use = \Trash
+ }
+ mailbox "Gelöschte Elemente" {
+ special_use = \Trash
+ }
+ mailbox "Papierkorb" {
+ special_use = \Trash
+ }
+ mailbox "Itens Excluidos" {
+ special_use = \Trash
+ }
+ mailbox "Itens Excluídos" {
+ special_use = \Trash
+ }
+ mailbox "Lixeira" {
+ special_use = \Trash
+ }
+ mailbox "Prullenbak" {
+ special_use = \Trash
+ }
+ mailbox "Odstránené položky" {
+ special_use = \Trash
+ }
+ mailbox "Koš" {
+ special_use = \Trash
+ }
+ mailbox "Verwijderde items" {
+ special_use = \Trash
+ }
+ mailbox "废件箱" {
+ special_use = \Trash
+ }
+ mailbox "已删除消息" {
+ special_use = \Trash
+ }
+ mailbox "已删除邮件" {
+ special_use = \Trash
+ }
+ mailbox "Archive" {
+ auto = subscribe
+ special_use = \Archive
+ }
+ mailbox "Archiv" {
+ special_use = \Archive
+ }
+ mailbox "Archives" {
+ special_use = \Archive
+ }
+ mailbox "Arquivo" {
+ special_use = \Archive
+ }
+ mailbox "Arquivos" {
+ special_use = \Archive
+ }
+ mailbox "Archief" {
+ special_use = \Archive
+ }
+ mailbox "Archív" {
+ special_use = \Archive
+ }
+ mailbox "Archivovať" {
+ special_use = \Archive
+ }
+ mailbox "归档" {
+ special_use = \Archive
+ }
+ mailbox "Sent" {
+ auto = subscribe
+ special_use = \Sent
+ }
+ mailbox "Sent Messages" {
+ special_use = \Sent
+ }
+ mailbox "Sent Items" {
+ special_use = \Sent
+ }
+ mailbox "已发送" {
+ special_use = \Sent
+ }
+ mailbox "已发送消息" {
+ special_use = \Sent
+ }
+ mailbox "已发送邮件" {
+ special_use = \Sent
+ }
+ mailbox "Gesendet" {
+ special_use = \Sent
+ }
+ mailbox "Gesendete Objekte" {
+ special_use = \Sent
+ }
+ mailbox "Gesendete Elemente" {
+ special_use = \Sent
+ }
+ mailbox "Itens Enviados" {
+ special_use = \Sent
+ }
+ mailbox "Enviados" {
+ special_use = \Sent
+ }
+ mailbox "Verzonden items" {
+ special_use = \Sent
+ }
+ mailbox "Verzonden" {
+ special_use = \Sent
+ }
+ mailbox "Odoslaná pošta" {
+ special_use = \Sent
+ }
+ mailbox "Odoslané" {
+ special_use = \Sent
+ }
+ mailbox "Drafts" {
+ auto = subscribe
+ special_use = \Drafts
+ }
+ mailbox "Entwürfe" {
+ special_use = \Drafts
+ }
+ mailbox "Rascunhos" {
+ special_use = \Drafts
+ }
+ mailbox "Concepten" {
+ special_use = \Drafts
+ }
+ mailbox "Koncepty" {
+ special_use = \Drafts
+ }
+ mailbox "草稿" {
+ special_use = \Drafts
+ }
+ mailbox "草稿箱" {
+ special_use = \Drafts
+ }
+ mailbox "Junk" {
+ auto = subscribe
+ special_use = \Junk
+ }
+ mailbox "Junk-E-Mail" {
+ special_use = \Junk
+ }
+ mailbox "Junk E-Mail" {
+ special_use = \Junk
+ }
+ mailbox "Spam" {
+ special_use = \Junk
+ }
+ mailbox "Lixo Eletrônico" {
+ special_use = \Junk
+ }
+ mailbox "Nevyžiadaná pošta" {
+ special_use = \Junk
+ }
+ mailbox "Infikované položky" {
+ special_use = \Junk
+ }
+ mailbox "Ongewenste e-mail" {
+ special_use = \Junk
+ }
+ mailbox "垃圾" {
+ special_use = \Junk
+ }
+ mailbox "垃圾箱" {
+ special_use = \Junk
+ }
+ mailbox "Koncepty" {
+ special_use = \Drafts
+ }
+ mailbox "Nevyžádaná pošta" {
+ special_use = \Junk
+ }
+ mailbox "Odstraněná pošta" {
+ special_use = \Trash
+ }
+ mailbox "Odeslaná pošta" {
+ special_use = \Sent
+ }
+ mailbox "Skräp" {
+ special_use = \Trash
+ }
+ mailbox "Borttagna Meddelanden" {
+ special_use = \Trash
+ }
+ mailbox "Arkiv" {
+ special_use = \Archive
+ }
+ mailbox "Arkeverat" {
+ special_use = \Archive
+ }
+ mailbox "Skickat" {
+ special_use = \Sent
+ }
+ mailbox "Skickade Meddelanden" {
+ special_use = \Sent
+ }
+ mailbox "Utkast" {
+ special_use = \Drafts
+ }
+ prefix =
+}
+protocols = imap sieve lmtp pop3
+service dict {
+ unix_listener dict {
+ mode = 0660
+ user = vmail
+ group = vmail
+ }
+}
+service log {
+ user = dovenull
+}
+service config {
+ unix_listener config {
+ user = root
+ group = vmail
+ mode = 0660
+ }
+}
+service auth {
+ inet_listener auth-inet {
+ port = 10001
+ }
+ unix_listener auth-master {
+ mode = 0600
+ user = vmail
+ }
+ unix_listener auth-userdb {
+ mode = 0600
+ user = vmail
+ }
+}
+service managesieve-login {
+ inet_listener sieve {
+ port = 4190
+ }
+ inet_listener sieve_haproxy {
+ port = 14190
+ haproxy = yes
+ }
+ service_count = 1
+ process_min_avail = 2
+ vsz_limit = 1G
+}
+service imap-login {
+ service_count = 1
+ process_limit = 10000
+ vsz_limit = 1G
+ user = dovenull
+ inet_listener imap_haproxy {
+ port = 10143
+ haproxy = yes
+ }
+ inet_listener imaps_haproxy {
+ port = 10993
+ ssl = yes
+ haproxy = yes
+ }
+}
+service pop3-login {
+ service_count = 1
+ vsz_limit = 1G
+ inet_listener pop3_haproxy {
+ port = 10110
+ haproxy = yes
+ }
+ inet_listener pop3s_haproxy {
+ port = 10995
+ ssl = yes
+ haproxy = yes
+ }
+}
+service imap {
+ executable = imap imap-postlogin
+ user = vmail
+ vsz_limit = 1G
+}
+service managesieve {
+ process_limit = 256
+}
+service lmtp {
+ inet_listener lmtp-inet {
+ port = 24
+ }
+ user = vmail
+}
+listen = *,[::]
+ssl_cert = </etc/ssl/mail/cert.pem
+ssl_key = </etc/ssl/mail/key.pem
+!include_try /etc/dovecot/sni.conf
+!include_try /etc/dovecot/sogo_trusted_ip.conf
+userdb {
+ driver = passwd-file
+ args = /etc/dovecot/dovecot-master.userdb
+}
+userdb {
+ args = /etc/dovecot/sql/dovecot-dict-sql-userdb.conf
+ driver = sql
+ skip = found
+}
+protocol imap {
+ mail_plugins = </etc/dovecot/mail_plugins_imap
+ imap_metadata = yes
+}
+mail_attribute_dict = file:%h/dovecot-attributes
+protocol lmtp {
+ mail_plugins = </etc/dovecot/mail_plugins_lmtp
+ auth_socket_path = /var/run/dovecot/auth-master
+}
+protocol sieve {
+ managesieve_logout_format = bytes=%i/%o
+}
+plugin {
+ # Allow "any" or "authenticated" to be used in ACLs
+ acl_anyone = </etc/dovecot/acl_anyone
+ acl_shared_dict = file:/var/vmail/shared-mailboxes.db
+ acl = vfile
+ last_login_dict = </etc/dovecot/last_login
+ last_login_key = last-login/%s/%u
+ fts = solr
+ fts_autoindex = yes
+ fts_solr = url=http://solr:8983/solr/dovecot-fts/
+ quota = dict:Userquota::proxy::sqlquota
+ quota_rule2 = Trash:storage=+100%%
+ sieve = /var/vmail/sieve/%u.sieve
+ sieve_plugins = sieve_imapsieve sieve_extprograms
+ sieve_vacation_send_from_recipient = yes
+ sieve_redirect_envelope_from = recipient
+ # From elsewhere to Spam folder
+ imapsieve_mailbox1_name = Junk
+ imapsieve_mailbox1_causes = COPY
+ imapsieve_mailbox1_before = file:/usr/lib/dovecot/sieve/report-spam.sieve
+ # END
+ # From Spam folder to elsewhere
+ imapsieve_mailbox2_name = *
+ imapsieve_mailbox2_from = Junk
+ imapsieve_mailbox2_causes = COPY
+ imapsieve_mailbox2_before = file:/usr/lib/dovecot/sieve/report-ham.sieve
+ # END
+ quota_warning = storage=95%% quota-warning 95 %u
+ quota_warning2 = storage=80%% quota-warning 80 %u
+ sieve_pipe_bin_dir = /usr/lib/dovecot/sieve
+ sieve_global_extensions = +vnd.dovecot.pipe +vnd.dovecot.execute
+ sieve_extensions = +notify +imapflags +vacation-seconds +editheader
+ sieve_max_script_size = 1M
+ sieve_max_redirects = 100
+ sieve_max_actions = 101
+ sieve_quota_max_scripts = 0
+ sieve_quota_max_storage = 0
+ listescape_char = "\\"
+ sieve_vacation_min_period = 5s
+ sieve_vacation_max_period = 0
+ sieve_vacation_default_period = 60s
+ sieve_before = /var/vmail/sieve/global_sieve_before.sieve
+ sieve_before2 = dict:proxy::sieve_before;name=active;bindir=/var/vmail/sieve_before_bindir
+ sieve_after = dict:proxy::sieve_after;name=active;bindir=/var/vmail/sieve_after_bindir
+ sieve_after2 = /var/vmail/sieve/global_sieve_after.sieve
+ sieve_duplicate_default_period = 1m
+ sieve_duplicate_max_period = 7d
+ sieve_vacation_dont_check_recipient = yes
+
+ # -- Global keys
+ mail_crypt_global_private_key = </mail_crypt/ecprivkey.pem
+ mail_crypt_global_public_key = </mail_crypt/ecpubkey.pem
+ mail_crypt_save_version = 2
+
+ # Enable compression while saving, lz4 Dovecot v2.2.11+
+ zlib_save = lz4
+
+ mail_log_events = delete undelete expunge copy mailbox_delete mailbox_rename
+ mail_log_fields = uid box msgid size
+ mail_log_cached_only = yes
+}
+service quota-warning {
+ executable = script /usr/local/bin/quota_notify.py
+ # use some unprivileged user for executing the quota warnings
+ user = vmail
+ unix_listener quota-warning {
+ user = vmail
+ }
+}
+dict {
+ sqlquota = mysql:/etc/dovecot/sql/dovecot-dict-sql-quota.conf
+ sieve_after = mysql:/etc/dovecot/sql/dovecot-dict-sql-sieve_after.conf
+ sieve_before = mysql:/etc/dovecot/sql/dovecot-dict-sql-sieve_before.conf
+}
+remote 127.0.0.1 {
+ disable_plaintext_auth = no
+}
+submission_host = postfix:588
+mail_max_userip_connections = 500
+service imap-postlogin {
+ executable = script-login /usr/local/bin/postlogin.sh
+ unix_listener imap-postlogin {
+ user = vmail
+ mode = 0660
+ }
+}
+service stats {
+ unix_listener stats-writer {
+ mode = 0660
+ user = vmail
+ }
+}
+imap_max_line_length = 2 M
+#auth_cache_verify_password_with_worker = yes
+#auth_cache_negative_ttl = 0
+#auth_cache_ttl = 30 s
+#auth_cache_size = 2 M
+service replicator {
+ process_min_avail = 1
+}
+service aggregator {
+ fifo_listener replication-notify-fifo {
+ user = vmail
+ }
+ unix_listener replication-notify {
+ user = vmail
+ }
+}
+service replicator {
+ unix_listener replicator-doveadm {
+ mode = 0666
+ }
+}
+replication_max_conns = 10
+doveadm_port = 12345
+replication_dsync_parameters = -d -l 30 -U -n INBOX
+!include_try /etc/dovecot/extra.conf
+!include_try /etc/dovecot/sogo-sso.conf
+!include_try /etc/dovecot/shared_namespace.conf
+default_client_limit = 10400
+default_vsz_limit = 1024 M
diff --git a/mailcow/src/mailcow-dockerized/data/conf/dovecot/global_sieve_after b/mailcow/src/mailcow-dockerized/data/conf/dovecot/global_sieve_after
new file mode 100644
index 0000000..cf12543
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/dovecot/global_sieve_after
@@ -0,0 +1,30 @@
+# global_sieve_after script
+# global_sieve_before -> user sieve_before (mailcow UI) -> user sieve_after (mailcow UI) -> global_sieve_after
+
+require "fileinto";
+require "mailbox";
+require "variables";
+require "subaddress";
+require "envelope";
+require "duplicate";
+
+if header :contains "X-Spam-Flag" "YES" {
+ fileinto "Junk";
+}
+
+if allof (
+ envelope :detail :matches "to" "*",
+ header :contains "X-Moo-Tag" "YES"
+ ) {
+ set :lower :upperfirst "tag" "${1}";
+ if mailboxexists "INBOX/${1}" {
+ fileinto "INBOX/${1}";
+ } else {
+ fileinto :create "INBOX/${tag}";
+ }
+}
+
+if duplicate {
+ discard;
+ stop;
+}
\ No newline at end of file
diff --git a/mailcow/src/mailcow-dockerized/data/conf/dovecot/global_sieve_before b/mailcow/src/mailcow-dockerized/data/conf/dovecot/global_sieve_before
new file mode 100644
index 0000000..e6a523d
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/dovecot/global_sieve_before
@@ -0,0 +1,2 @@
+# global_sieve_before script
+# global_sieve_before -> user sieve_before (mailcow UI) -> user sieve_after (mailcow UI) -> global_sieve_after
diff --git a/mailcow/src/mailcow-dockerized/data/conf/dovecot/ldap/passdb.conf b/mailcow/src/mailcow-dockerized/data/conf/dovecot/ldap/passdb.conf
new file mode 100644
index 0000000..12fc3c0
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/dovecot/ldap/passdb.conf
@@ -0,0 +1,9 @@
+#hosts = 1.2.3.4
+#dn = cn=admin,dc=example,dc=local
+#dnpass = password
+#ldap_version = 3
+#base = ou=People,dc=example,dc=local
+#auth_bind = no
+#pass_filter = (&(objectClass=posixAccount)(mail=%u))
+#pass_attrs = mail=user,userPassword=password
+#default_pass_scheme = SSHA
diff --git a/mailcow/src/mailcow-dockerized/data/conf/mysql/my.cnf b/mailcow/src/mailcow-dockerized/data/conf/mysql/my.cnf
new file mode 100644
index 0000000..9f52068
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/mysql/my.cnf
@@ -0,0 +1,33 @@
+[mysqld]
+character-set-client-handshake = FALSE
+character-set-server = utf8mb4
+collation-server = utf8mb4_unicode_ci
+#innodb_file_per_table = TRUE
+#innodb_file_format = barracuda
+#innodb_large_prefix = TRUE
+#sql_mode=IGNORE_SPACE,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
+max_allowed_packet = 192M
+max-connections = 350
+key_buffer_size = 0
+read_buffer_size = 192K
+sort_buffer_size = 2M
+innodb_buffer_pool_size = 24M
+read_rnd_buffer_size = 256K
+tmp_table_size = 24M
+performance_schema = 0
+innodb-strict-mode = 0
+thread_cache_size = 8
+query_cache_type = 0
+query_cache_size = 0
+max_heap_table_size = 48M
+thread_stack = 128K
+skip-host-cache
+skip-name-resolve
+log-warnings = 0
+event_scheduler = 1
+
+[client]
+default-character-set = utf8mb4
+
+[mysql]
+default-character-set = utf8mb4
diff --git a/mailcow/src/mailcow-dockerized/data/conf/nginx/000-map-size.conf b/mailcow/src/mailcow-dockerized/data/conf/nginx/000-map-size.conf
new file mode 100644
index 0000000..a834306
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/nginx/000-map-size.conf
@@ -0,0 +1,3 @@
+map_hash_max_size 256;
+map_hash_bucket_size 256;
+
diff --git a/mailcow/src/mailcow-dockerized/data/conf/nginx/dynmaps.conf b/mailcow/src/mailcow-dockerized/data/conf/nginx/dynmaps.conf
new file mode 100644
index 0000000..99c0c6a
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/nginx/dynmaps.conf
@@ -0,0 +1,19 @@
+server {
+ listen 8081;
+ listen [::]:8081;
+ index index.php index.html;
+ server_name _;
+ error_log /var/log/nginx/error.log;
+ access_log /var/log/nginx/access.log;
+ root /dynmaps;
+
+ location ~ \.php$ {
+ try_files $uri =404;
+ fastcgi_split_path_info ^(.+\.php)(/.+)$;
+ fastcgi_pass phpfpm:9001;
+ fastcgi_index index.php;
+ include fastcgi_params;
+ fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
+ fastcgi_param PATH_INFO $fastcgi_path_info;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/conf/nginx/includes/site-defaults.conf b/mailcow/src/mailcow-dockerized/data/conf/nginx/includes/site-defaults.conf
new file mode 100644
index 0000000..c4c06b2
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/nginx/includes/site-defaults.conf
@@ -0,0 +1,216 @@
+
+ include /etc/nginx/mime.types;
+ charset utf-8;
+ override_charset on;
+
+ ssl_protocols TLSv1.2 TLSv1.3;
+ ssl_prefer_server_ciphers on;
+ ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305;
+ ssl_ecdh_curve X25519:X448:secp384r1:secp256k1;
+ ssl_session_cache shared:SSL:50m;
+ ssl_session_timeout 1d;
+ ssl_session_tickets off;
+
+ add_header Strict-Transport-Security "max-age=15768000;";
+ add_header X-Content-Type-Options nosniff;
+ add_header X-XSS-Protection "1; mode=block";
+ add_header X-Robots-Tag none;
+ add_header X-Download-Options noopen;
+ add_header X-Frame-Options "SAMEORIGIN" always;
+ add_header X-Permitted-Cross-Domain-Policies none;
+ add_header Referrer-Policy strict-origin;
+
+ index index.php index.html;
+
+ client_max_body_size 0;
+
+ gzip on;
+ gzip_disable "msie6";
+
+ gzip_vary on;
+ gzip_proxied off;
+ gzip_comp_level 6;
+ gzip_buffers 16 8k;
+ gzip_http_version 1.1;
+ gzip_min_length 256;
+ gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript application/vnd.ms-fontobject application/x-font-ttf font/opentype image/svg+xml image/x-icon;
+
+ location ~ ^/(fonts|js|css|img)/ {
+ expires max;
+ add_header Cache-Control public;
+ }
+
+ error_log /var/log/nginx/error.log;
+ access_log /var/log/nginx/access.log;
+ fastcgi_hide_header X-Powered-By;
+ absolute_redirect off;
+ root /web;
+
+ location / {
+ try_files $uri $uri/ @strip-ext;
+ }
+
+ location /qhandler {
+ rewrite ^/qhandler/(.*)/(.*) /qhandler.php?action=$1&hash=$2;
+ }
+
+ location /edit {
+ rewrite ^/edit/(.*)/(.*) /edit.php?$1=$2;
+ }
+
+ location @strip-ext {
+ rewrite ^(.*)$ $1.php last;
+ }
+
+ location ~ ^/api/v1/(.*)$ {
+ try_files $uri $uri/ /json_api.php?query=$1;
+ }
+
+ location ^~ /.well-known/acme-challenge/ {
+ allow all;
+ default_type "text/plain";
+ }
+
+ # If behind reverse proxy, forwards the correct IP
+ set_real_ip_from 10.0.0.0/8;
+ set_real_ip_from 172.16.0.0/12;
+ set_real_ip_from 192.168.0.0/16;
+ set_real_ip_from fc00::/7;
+ real_ip_header X-Forwarded-For;
+ real_ip_recursive on;
+
+ rewrite ^/.well-known/caldav$ /SOGo/dav/ permanent;
+ rewrite ^/.well-known/carddav$ /SOGo/dav/ permanent;
+
+ location ^~ /principals {
+ return 301 /SOGo/dav;
+ }
+
+ location ~ \.php$ {
+ try_files $uri =404;
+ fastcgi_split_path_info ^(.+\.php)(/.+)$;
+ fastcgi_pass phpfpm:9002;
+ fastcgi_index index.php;
+ include /etc/nginx/fastcgi_params;
+ fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
+ fastcgi_param PATH_INFO $fastcgi_path_info;
+ fastcgi_read_timeout 3600;
+ fastcgi_send_timeout 3600;
+ }
+
+ location /rspamd/ {
+ location /rspamd/auth {
+ # proxy_pass is not inherited
+ proxy_pass http://rspamd:11334/auth;
+ proxy_intercept_errors on;
+ proxy_set_header Host $http_host;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_redirect off;
+ error_page 403 /_rspamderror.php;
+ }
+ proxy_pass http://rspamd:11334/;
+ proxy_set_header Host $http_host;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_redirect off;
+ }
+
+ location ~* ^/Autodiscover/Autodiscover.xml {
+ fastcgi_split_path_info ^(.+\.php)(/.+)$;
+ fastcgi_pass phpfpm:9002;
+ include /etc/nginx/fastcgi_params;
+ fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
+ try_files /autodiscover.php =404;
+ }
+
+ location ~* ^/Autodiscover/Autodiscover.json {
+ fastcgi_split_path_info ^(.+\.php)(/.+)$;
+ fastcgi_pass phpfpm:9002;
+ include /etc/nginx/fastcgi_params;
+ fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
+ try_files /autodiscover-json.php =404;
+ }
+
+ location ~ /(?:m|M)ail/(?:c|C)onfig-v1.1.xml {
+ fastcgi_split_path_info ^(.+\.php)(/.+)$;
+ fastcgi_pass phpfpm:9002;
+ include /etc/nginx/fastcgi_params;
+ fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
+ try_files /autoconfig.php =404;
+ }
+
+ # auth_request endpoint if ALLOW_ADMIN_EMAIL_LOGIN is set
+ location /sogo-auth-verify {
+ internal;
+ proxy_set_header X-Original-URI $request_uri;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header Host $http_host;
+ proxy_set_header Content-Length "";
+ proxy_pass http://127.0.0.1:65510/sogo-auth;
+ proxy_pass_request_body off;
+ }
+
+ location ^~ /Microsoft-Server-ActiveSync {
+ include /etc/nginx/conf.d/sogo_proxy_auth.active;
+ include /etc/nginx/conf.d/sogo_eas.active;
+ proxy_connect_timeout 75;
+ proxy_send_timeout 3600;
+ proxy_read_timeout 3600;
+ proxy_buffers 64 256k;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header Host $http_host;
+ client_body_buffer_size 512k;
+ client_max_body_size 0;
+ }
+
+ location ^~ /SOGo {
+ include /etc/nginx/conf.d/sogo_proxy_auth.active;
+ include /etc/nginx/conf.d/sogo.active;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header Host $http_host;
+ proxy_set_header x-webobjects-server-protocol HTTP/1.0;
+ proxy_set_header x-webobjects-remote-host $remote_addr;
+ proxy_set_header x-webobjects-server-name $server_name;
+ proxy_set_header x-webobjects-server-url $client_req_scheme://$http_host;
+ proxy_set_header x-webobjects-server-port $server_port;
+ proxy_send_timeout 3600;
+ proxy_read_timeout 3600;
+ client_body_buffer_size 128k;
+ client_max_body_size 0;
+ break;
+ }
+
+ location ~* /sogo$ {
+ return 301 $client_req_scheme://$http_host/SOGo;
+ }
+
+ location /SOGo.woa/WebServerResources/ {
+ alias /usr/lib/GNUstep/SOGo/WebServerResources/;
+ }
+
+ location /.woa/WebServerResources/ {
+ alias /usr/lib/GNUstep/SOGo/WebServerResources/;
+ }
+
+ location /SOGo/WebServerResources/ {
+ alias /usr/lib/GNUstep/SOGo/WebServerResources/;
+ }
+
+ location (^/SOGo/so/ControlPanel/Products/[^/]*UI/Resources/.*\.(jpg|png|gif|css|js)$) {
+ alias /usr/lib/GNUstep/SOGo/$1.SOGo/Resources/$2;
+ }
+
+ include /etc/nginx/conf.d/site.*.custom;
+
+ error_page 502 @awaitingupstream;
+
+ location @awaitingupstream {
+ rewrite ^(.*)$ /_status.502.html break;
+ }
+
+ location ~ ^/cache/(.*)$ {
+ try_files $uri $uri/ /resource.php?file=$1;
+ }
diff --git a/mailcow/src/mailcow-dockerized/data/conf/nginx/meta_exporter.conf b/mailcow/src/mailcow-dockerized/data/conf/nginx/meta_exporter.conf
new file mode 100644
index 0000000..74291b1
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/nginx/meta_exporter.conf
@@ -0,0 +1,19 @@
+server {
+ listen 9081;
+ index index.php index.html;
+ server_name _;
+ error_log /var/log/nginx/error.log;
+ access_log /var/log/nginx/access.log;
+ root /meta_exporter;
+ client_max_body_size 10M;
+ location ~ \.php$ {
+ client_max_body_size 10M;
+ try_files $uri =404;
+ fastcgi_split_path_info ^(.+\.php)(/.+)$;
+ fastcgi_pass phpfpm:9001;
+ fastcgi_index pipe.php;
+ include fastcgi_params;
+ fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
+ fastcgi_param PATH_INFO $fastcgi_path_info;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/conf/nginx/site.conf b/mailcow/src/mailcow-dockerized/data/conf/nginx/site.conf
new file mode 100644
index 0000000..d6e6b13
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/nginx/site.conf
@@ -0,0 +1,10 @@
+server_tokens off;
+proxy_cache_path /tmp levels=1:2 keys_zone=sogo:10m inactive=24h max_size=1g;
+server_names_hash_bucket_size 64;
+
+map $http_x_forwarded_proto $client_req_scheme {
+ default $scheme;
+ https https;
+}
+
+include /etc/nginx/conf.d/sites.active;
diff --git a/mailcow/src/mailcow-dockerized/data/conf/nginx/templates/listen_plain.template b/mailcow/src/mailcow-dockerized/data/conf/nginx/templates/listen_plain.template
new file mode 100644
index 0000000..a044b22
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/nginx/templates/listen_plain.template
@@ -0,0 +1,2 @@
+listen ${HTTP_PORT};
+listen [::]:${HTTP_PORT};
diff --git a/mailcow/src/mailcow-dockerized/data/conf/nginx/templates/listen_ssl.template b/mailcow/src/mailcow-dockerized/data/conf/nginx/templates/listen_ssl.template
new file mode 100644
index 0000000..93ec80c
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/nginx/templates/listen_ssl.template
@@ -0,0 +1,2 @@
+listen ${HTTPS_PORT} ssl http2;
+listen [::]:${HTTPS_PORT} ssl http2;
diff --git a/mailcow/src/mailcow-dockerized/data/conf/nginx/templates/server_name.template b/mailcow/src/mailcow-dockerized/data/conf/nginx/templates/server_name.template
new file mode 100644
index 0000000..261a1ec
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/nginx/templates/server_name.template
@@ -0,0 +1 @@
+server_name ${MAILCOW_HOSTNAME} autodiscover.* autoconfig.*;
diff --git a/mailcow/src/mailcow-dockerized/data/conf/nginx/templates/sites.template.sh b/mailcow/src/mailcow-dockerized/data/conf/nginx/templates/sites.template.sh
new file mode 100644
index 0000000..782c814
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/nginx/templates/sites.template.sh
@@ -0,0 +1,38 @@
+echo '
+server {
+ listen 127.0.0.1:65510;
+ include /etc/nginx/conf.d/listen_plain.active;
+ include /etc/nginx/conf.d/listen_ssl.active;
+
+ ssl_certificate /etc/ssl/mail/cert.pem;
+ ssl_certificate_key /etc/ssl/mail/key.pem;
+
+ include /etc/nginx/conf.d/server_name.active;
+
+ include /etc/nginx/conf.d/includes/site-defaults.conf;
+}
+';
+for cert_dir in /etc/ssl/mail/*/ ; do
+ if [[ ! -f ${cert_dir}domains ]] || [[ ! -f ${cert_dir}cert.pem ]] || [[ ! -f ${cert_dir}key.pem ]]; then
+ continue
+ fi
+ # do not create vhost for default-certificate. the cert is already in the default server listen
+ domains="$(cat ${cert_dir}domains | sed -e 's/^[[:space:]]*//')"
+ case "${domains}" in
+ "") continue;;
+ "${MAILCOW_HOSTNAME}"*) continue;;
+ esac
+ echo -n '
+server {
+ include /etc/nginx/conf.d/listen_ssl.active;
+
+ ssl_certificate '${cert_dir}'cert.pem;
+ ssl_certificate_key '${cert_dir}'key.pem;
+';
+ echo -n '
+ server_name '${domains}';
+
+ include /etc/nginx/conf.d/includes/site-defaults.conf;
+}
+';
+done
diff --git a/mailcow/src/mailcow-dockerized/data/conf/nginx/templates/sogo.auth_request.template.sh b/mailcow/src/mailcow-dockerized/data/conf/nginx/templates/sogo.auth_request.template.sh
new file mode 100644
index 0000000..f6d2d98
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/nginx/templates/sogo.auth_request.template.sh
@@ -0,0 +1,10 @@
+if printf "%s\n" "${ALLOW_ADMIN_EMAIL_LOGIN}" | grep -E '^([yY][eE][sS]|[yY])+$' >/dev/null; then
+ echo 'auth_request /sogo-auth-verify;
+auth_request_set $user $upstream_http_x_user;
+auth_request_set $auth $upstream_http_x_auth;
+auth_request_set $auth_type $upstream_http_x_auth_type;
+proxy_set_header x-webobjects-remote-user "$user";
+proxy_set_header Authorization "$auth";
+proxy_set_header x-webobjects-auth-type "$auth_type";
+'
+fi
diff --git a/mailcow/src/mailcow-dockerized/data/conf/nginx/templates/sogo.template b/mailcow/src/mailcow-dockerized/data/conf/nginx/templates/sogo.template
new file mode 100644
index 0000000..2c08438
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/nginx/templates/sogo.template
@@ -0,0 +1 @@
+proxy_pass http://${IPV4_NETWORK}.248:20000;
diff --git a/mailcow/src/mailcow-dockerized/data/conf/nginx/templates/sogo_eas.template.sh b/mailcow/src/mailcow-dockerized/data/conf/nginx/templates/sogo_eas.template.sh
new file mode 100644
index 0000000..b241ef0
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/nginx/templates/sogo_eas.template.sh
@@ -0,0 +1,5 @@
+if printf "%s\n" "${SKIP_SOGO}" | grep -E '^([yY][eE][sS]|[yY])+$' >/dev/null; then
+ echo "return 410;"
+else
+ echo "proxy_pass http://${IPV4_NETWORK}.248:20000/SOGo/Microsoft-Server-ActiveSync;"
+fi
diff --git a/mailcow/src/mailcow-dockerized/data/conf/phpfpm/php-conf.d/opcache-recommended.ini b/mailcow/src/mailcow-dockerized/data/conf/phpfpm/php-conf.d/opcache-recommended.ini
new file mode 100644
index 0000000..104f242
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/phpfpm/php-conf.d/opcache-recommended.ini
@@ -0,0 +1,7 @@
+opcache.enable=1
+opcache.enable_cli=1
+opcache.interned_strings_buffer=8
+opcache.max_accelerated_files=10000
+opcache.memory_consumption=128
+opcache.save_comments=1
+opcache.revalidate_freq=1
diff --git a/mailcow/src/mailcow-dockerized/data/conf/phpfpm/php-conf.d/other.ini b/mailcow/src/mailcow-dockerized/data/conf/phpfpm/php-conf.d/other.ini
new file mode 100644
index 0000000..379be75
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/phpfpm/php-conf.d/other.ini
@@ -0,0 +1,2 @@
+max_execution_time = 3600
+max_input_time = 3600
diff --git a/mailcow/src/mailcow-dockerized/data/conf/phpfpm/php-conf.d/upload.ini b/mailcow/src/mailcow-dockerized/data/conf/phpfpm/php-conf.d/upload.ini
new file mode 100644
index 0000000..5cb28f1
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/phpfpm/php-conf.d/upload.ini
@@ -0,0 +1,3 @@
+file_uploads = On
+upload_max_filesize = 64M
+post_max_size = 64M
diff --git a/mailcow/src/mailcow-dockerized/data/conf/phpfpm/php-fpm.d/pools.conf b/mailcow/src/mailcow-dockerized/data/conf/phpfpm/php-fpm.d/pools.conf
new file mode 100644
index 0000000..605e686
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/phpfpm/php-fpm.d/pools.conf
@@ -0,0 +1,29 @@
+[system-worker]
+user = www-data
+group = www-data
+pm = dynamic
+pm.max_children = 15
+pm.start_servers = 2
+pm.min_spare_servers = 2
+pm.max_spare_servers = 4
+listen = [::]:9001
+access.log = /proc/self/fd/2
+clear_env = no
+catch_workers_output = yes
+php_admin_value[memory_limit] = 256M
+php_admin_value[disable_functions] = show_source, highlight_file, apache_child_terminate, apache_get_modules, apache_note, apache_setenv, virtual, dl, disk_total_space, posix_getpwnam, posix_getpwuid, posix_mkfifo, posix_mknod, posix_setpgid, posix_setsid, posix_setuid, posix_uname, proc_nice, openlog, syslog, pfsockopen, system, shell_exec, passthru, popen, proc_open, exec, ini_alter, pcntl_exec, proc_close, proc_get_status, proc_terminate, symlink
+
+[web-worker]
+user = www-data
+group = www-data
+pm = dynamic
+pm.max_children = 50
+pm.start_servers = 10
+pm.min_spare_servers = 10
+pm.max_spare_servers = 15
+listen = [::]:9002
+access.log = /proc/self/fd/2
+clear_env = no
+catch_workers_output = yes
+php_admin_value[memory_limit] = 512M
+php_admin_value[disable_functions] = show_source, highlight_file, apache_child_terminate, apache_get_modules, apache_note, apache_setenv, virtual, dl, disk_total_space, posix_getpwnam, posix_getpwuid, posix_mkfifo, posix_mknod, posix_setpgid, posix_setsid, posix_setuid, posix_uname, proc_nice, openlog, syslog, pfsockopen, system, shell_exec, passthru, popen, proc_open, exec, ini_alter, pcntl_exec, proc_close, proc_get_status, proc_terminate, symlink
diff --git a/mailcow/src/mailcow-dockerized/data/conf/phpfpm/sogo-sso/.gitkeep b/mailcow/src/mailcow-dockerized/data/conf/phpfpm/sogo-sso/.gitkeep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/phpfpm/sogo-sso/.gitkeep
diff --git a/mailcow/src/mailcow-dockerized/data/conf/postfix/allow_mailcow_local.regexp b/mailcow/src/mailcow-dockerized/data/conf/postfix/allow_mailcow_local.regexp
new file mode 100644
index 0000000..0da4593
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/postfix/allow_mailcow_local.regexp
@@ -0,0 +1 @@
+/^(.+)@mailcow.local/ OK
diff --git a/mailcow/src/mailcow-dockerized/data/conf/postfix/anonymize_headers.pcre b/mailcow/src/mailcow-dockerized/data/conf/postfix/anonymize_headers.pcre
new file mode 100644
index 0000000..739237b
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/postfix/anonymize_headers.pcre
@@ -0,0 +1,19 @@
+if /^\s*Received:.*Authenticated sender.*\(Postcow\)/
+#/^Received: from .*? \([\w-.]* \[.*?\]\)\s+\(Authenticated sender: (.+)\)\s+by.+\(Postcow\) with (E?SMTPS?A?) id ([A-F0-9]+).+;.*?/
+/^Received: from .*? \([\w-.]* \[.*?\]\)(.*|\n.*)\(Authenticated sender: (.+)\)\s+by.+\(Postcow\) with (.*)/
+ REPLACE Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with $3
+endif
+if /^\s*Received: from.* \(.*dovecot-mailcow.*mailcow-network.*\).*\(Postcow\)/
+/^Received: from.* (.*|\n.*)\((.+) (.+)\)\s+by (.+) \(Postcow\) with (.*)/
+ REPLACE Received: from sieve (sieve $3) by $4 (Postcow) with $5
+endif
+if /^\s*Received: from.* \(.*rspamd-mailcow.*mailcow-network.*\).*\(Postcow\)/
+/^Received: from.* (.*|\n.*)\((.+) (.+)\)\s+by (.+) \(Postcow\) with (.*)/
+ REPLACE Received: from rspamd (rspamd $3) by $4 (Postcow) with $5
+endif
+/^\s*X-Enigmail/ IGNORE
+/^\s*X-Mailer/ IGNORE
+/^\s*X-Originating-IP/ IGNORE
+/^\s*X-Forward/ IGNORE
+# Not removing UA by default, might be signed
+#/^\s*User-Agent/ IGNORE
diff --git a/mailcow/src/mailcow-dockerized/data/conf/postfix/local_transport b/mailcow/src/mailcow-dockerized/data/conf/postfix/local_transport
new file mode 100644
index 0000000..6dd2101
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/postfix/local_transport
@@ -0,0 +1,2 @@
+/watchdog@localhost$/ watchdog_discard:
+/localhost$/ local:
diff --git a/mailcow/src/mailcow-dockerized/data/conf/postfix/main.cf b/mailcow/src/mailcow-dockerized/data/conf/postfix/main.cf
new file mode 100644
index 0000000..e8da794
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/postfix/main.cf
@@ -0,0 +1,201 @@
+# --------------------------------------------------------------------------
+# Please create a file "extra.cf" for persistent overrides to main.cf
+# --------------------------------------------------------------------------
+biff = no
+append_dot_mydomain = no
+smtpd_tls_cert_file = /etc/ssl/mail/cert.pem
+smtpd_tls_key_file = /etc/ssl/mail/key.pem
+tls_server_sni_maps = hash:/opt/postfix/conf/sni.map
+smtpd_tls_received_header = yes
+smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
+smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
+smtpd_relay_restrictions = permit_mynetworks,
+ permit_sasl_authenticated,
+ defer_unauth_destination
+# alias maps are auto-generated in postfix.sh on startup
+alias_maps = hash:/etc/aliases
+alias_database = hash:/etc/aliases
+relayhost =
+mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16 [fe80::]/10 [fc00::]/7
+mailbox_size_limit = 0
+recipient_delimiter = +
+inet_interfaces = all
+inet_protocols = all
+bounce_queue_lifetime = 1d
+broken_sasl_auth_clients = yes
+disable_vrfy_command = yes
+maximal_backoff_time = 1800s
+maximal_queue_lifetime = 5d
+delay_warning_time = 4h
+message_size_limit = 104857600
+milter_default_action = accept
+milter_protocol = 6
+minimal_backoff_time = 300s
+plaintext_reject_code = 550
+postscreen_access_list = permit_mynetworks,
+ cidr:/opt/postfix/conf/custom_postscreen_whitelist.cidr,
+ cidr:/opt/postfix/conf/postscreen_access.cidr,
+ tcp:127.0.0.1:10027
+postscreen_bare_newline_enable = no
+postscreen_blacklist_action = drop
+postscreen_cache_cleanup_interval = 24h
+postscreen_cache_map = proxy:btree:$data_directory/postscreen_cache
+postscreen_dnsbl_action = enforce
+postscreen_dnsbl_sites = wl.mailspike.net=127.0.0.[18;19;20]*-2
+ hostkarma.junkemailfilter.com=127.0.0.1*-2
+ list.dnswl.org=127.0.[0..255].0*-2
+ list.dnswl.org=127.0.[0..255].1*-4
+ list.dnswl.org=127.0.[0..255].2*-6
+ list.dnswl.org=127.0.[0..255].3*-8
+ ix.dnsbl.manitu.net*2
+ bl.spamcop.net*2
+ bl.suomispam.net*2
+ hostkarma.junkemailfilter.com=127.0.0.2*3
+ hostkarma.junkemailfilter.com=127.0.0.4*2
+ hostkarma.junkemailfilter.com=127.0.1.2*1
+ backscatter.spameatingmonkey.net*2
+ bl.ipv6.spameatingmonkey.net*2
+ bl.spameatingmonkey.net*2
+ b.barracudacentral.org=127.0.0.2*7
+ bl.mailspike.net=127.0.0.2*5
+ bl.mailspike.net=127.0.0.[10;11;12]*4
+ dnsbl.sorbs.net=127.0.0.10*8
+ dnsbl.sorbs.net=127.0.0.5*6
+ dnsbl.sorbs.net=127.0.0.7*3
+ dnsbl.sorbs.net=127.0.0.8*2
+ dnsbl.sorbs.net=127.0.0.6*2
+ dnsbl.sorbs.net=127.0.0.9*2
+ zen.spamhaus.org=127.0.0.[10;11]*8
+ zen.spamhaus.org=127.0.0.[4..7]*6
+ zen.spamhaus.org=127.0.0.3*4
+ zen.spamhaus.org=127.0.0.2*3
+postscreen_dnsbl_threshold = 6
+postscreen_dnsbl_ttl = 5m
+postscreen_greet_action = enforce
+postscreen_greet_banner = $smtpd_banner
+postscreen_greet_ttl = 2d
+postscreen_greet_wait = 3s
+postscreen_non_smtp_command_enable = no
+postscreen_pipelining_enable = no
+proxy_read_maps = proxy:mysql:/opt/postfix/conf/sql/mysql_sasl_passwd_maps_transport_maps.cf,
+ proxy:mysql:/opt/postfix/conf/sql/mysql_sasl_access_maps.cf,
+ proxy:mysql:/opt/postfix/conf/sql/mysql_tls_enforce_in_policy.cf,
+ $sender_dependent_default_transport_maps,
+ $smtp_tls_policy_maps,
+ $local_recipient_maps,
+ $mydestination,
+ $virtual_alias_maps,
+ $virtual_alias_domains,
+ $virtual_mailbox_maps,
+ $virtual_mailbox_domains,
+ $relay_recipient_maps,
+ $relay_domains,
+ $canonical_maps,
+ $sender_canonical_maps,
+ $sender_bcc_maps,
+ $recipient_bcc_maps,
+ $recipient_canonical_maps,
+ $relocated_maps,
+ $transport_maps,
+ $mynetworks,
+ $smtpd_sender_login_maps,
+ $smtp_sasl_password_maps
+queue_run_delay = 300s
+relay_domains = proxy:mysql:/opt/postfix/conf/sql/mysql_virtual_relay_domain_maps.cf
+relay_recipient_maps = proxy:mysql:/opt/postfix/conf/sql/mysql_relay_recipient_maps.cf
+sender_dependent_default_transport_maps = proxy:mysql:/opt/postfix/conf/sql/mysql_sender_dependent_default_transport_maps.cf
+smtp_tls_CAfile = /etc/ssl/certs/ca-certificates.crt
+smtp_tls_cert_file = /etc/ssl/mail/cert.pem
+smtp_tls_key_file = /etc/ssl/mail/key.pem
+smtp_tls_loglevel = 1
+smtp_dns_support_level = dnssec
+smtp_tls_security_level = dane
+smtpd_data_restrictions = reject_unauth_pipelining, permit
+smtpd_delay_reject = yes
+smtpd_error_sleep_time = 10s
+smtpd_hard_error_limit = ${stress?1}${stress:5}
+smtpd_helo_required = yes
+smtpd_proxy_timeout = 600s
+smtpd_recipient_restrictions = check_sasl_access proxy:mysql:/opt/postfix/conf/sql/mysql_sasl_access_maps.cf,
+ permit_sasl_authenticated,
+ permit_mynetworks,
+ check_recipient_access proxy:mysql:/opt/postfix/conf/sql/mysql_tls_enforce_in_policy.cf,
+ reject_invalid_helo_hostname,
+ reject_unauth_destination
+smtpd_sasl_auth_enable = yes
+smtpd_sasl_authenticated_header = yes
+smtpd_sasl_path = inet:dovecot:10001
+smtpd_sasl_type = dovecot
+smtpd_sender_login_maps = proxy:mysql:/opt/postfix/conf/sql/mysql_virtual_sender_acl.cf
+smtpd_sender_restrictions = reject_authenticated_sender_login_mismatch,
+ permit_mynetworks,
+ permit_sasl_authenticated,
+ reject_unlisted_sender,
+ reject_unknown_sender_domain
+smtpd_soft_error_limit = 3
+smtpd_tls_auth_only = yes
+smtpd_tls_dh1024_param_file = /etc/ssl/mail/dhparams.pem
+smtpd_tls_eecdh_grade = auto
+smtpd_tls_exclude_ciphers = ECDHE-RSA-RC4-SHA, RC4, aNULL, DES-CBC3-SHA, ECDHE-RSA-DES-CBC3-SHA, EDH-RSA-DES-CBC3-SHA
+smtpd_tls_loglevel = 1
+
+# Mandatory protocols and ciphers are used when a connections is enforced to use TLS
+# Does _not_ apply to enforced incoming TLS settings per mailbox
+smtp_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
+lmtp_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
+smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
+smtpd_tls_mandatory_ciphers = high
+
+smtp_tls_protocols = !SSLv2, !SSLv3
+lmtp_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
+smtpd_tls_protocols = !SSLv2, !SSLv3
+
+smtpd_tls_security_level = may
+tls_preempt_cipherlist = yes
+tls_ssl_options = NO_COMPRESSION, NO_RENEGOTIATION
+virtual_alias_maps = proxy:mysql:/opt/postfix/conf/sql/mysql_virtual_alias_maps.cf,
+ proxy:mysql:/opt/postfix/conf/sql/mysql_virtual_resource_maps.cf,
+ proxy:mysql:/opt/postfix/conf/sql/mysql_virtual_spamalias_maps.cf,
+ proxy:mysql:/opt/postfix/conf/sql/mysql_virtual_alias_domain_maps.cf
+virtual_gid_maps = static:5000
+virtual_mailbox_base = /var/vmail/
+virtual_mailbox_domains = proxy:mysql:/opt/postfix/conf/sql/mysql_virtual_domains_maps.cf
+recipient_bcc_maps = proxy:mysql:/opt/postfix/conf/sql/mysql_recipient_bcc_maps.cf
+sender_bcc_maps = proxy:mysql:/opt/postfix/conf/sql/mysql_sender_bcc_maps.cf
+recipient_canonical_maps = proxy:mysql:/opt/postfix/conf/sql/mysql_recipient_canonical_maps.cf
+recipient_canonical_classes = envelope_recipient
+virtual_mailbox_maps = proxy:mysql:/opt/postfix/conf/sql/mysql_virtual_mailbox_maps.cf
+virtual_minimum_uid = 104
+virtual_transport = lmtp:inet:dovecot:24
+virtual_uid_maps = static:5000
+smtpd_milters = inet:rspamd:9900
+non_smtpd_milters = inet:rspamd:9900
+milter_mail_macros = i {mail_addr} {client_addr} {client_name} {auth_authen}
+mydestination = localhost.localdomain, localhost
+smtp_address_preference = any
+smtp_sender_dependent_authentication = yes
+smtp_sasl_auth_enable = yes
+smtp_sasl_password_maps = proxy:mysql:/opt/postfix/conf/sql/mysql_sasl_passwd_maps_sender_dependent.cf
+smtp_sasl_security_options =
+smtp_sasl_mechanism_filter = plain, login
+smtp_tls_policy_maps = proxy:mysql:/opt/postfix/conf/sql/mysql_tls_policy_override_maps.cf
+smtp_header_checks = pcre:/opt/postfix/conf/anonymize_headers.pcre
+mail_name = Postcow
+# local_transport map catches local destinations and prevents routing local dests when the next map would route "*"
+# Use custom_transport.pcre for custom transports
+transport_maps = pcre:/opt/postfix/conf/custom_transport.pcre,
+ pcre:/opt/postfix/conf/local_transport,
+ proxy:mysql:/opt/postfix/conf/sql/mysql_relay_ne.cf,
+ proxy:mysql:/opt/postfix/conf/sql/mysql_transport_maps.cf
+smtp_sasl_auth_soft_bounce = no
+postscreen_discard_ehlo_keywords = silent-discard, dsn
+compatibility_level = 2
+smtputf8_enable = no
+smtpd_last_auth = check_policy_service inet:127.0.0.1:10028
+# Define protocols for SMTPS and submission service
+submission_smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
+smtps_smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
+
+# DO NOT EDIT ANYTHING BELOW #
+# User overrides #
+
diff --git a/mailcow/src/mailcow-dockerized/data/conf/postfix/master.cf b/mailcow/src/mailcow-dockerized/data/conf/postfix/master.cf
new file mode 100644
index 0000000..ffd1ac4
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/postfix/master.cf
@@ -0,0 +1,145 @@
+# inter-mx with postscreen on 25/tcp
+smtp inet n - n - 1 postscreen
+10025 inet n - n - 1 postscreen
+ -o postscreen_upstream_proxy_protocol=haproxy
+ -o syslog_name=haproxy
+smtpd pass - - n - - smtpd
+ -o smtpd_helo_restrictions=permit_mynetworks,reject_non_fqdn_helo_hostname
+ -o smtpd_sasl_auth_enable=no
+ -o smtpd_sender_restrictions=permit_mynetworks,reject_unlisted_sender,reject_unknown_sender_domain
+
+# smtpd tls-wrapped (smtps) on 465/tcp
+# TLS protocol can be modified by setting smtps_smtpd_tls_mandatory_protocols in extra.cf
+smtps inet n - n - - smtpd
+ -o smtpd_tls_wrappermode=yes
+ -o smtpd_client_restrictions=permit_mynetworks,permit_sasl_authenticated,reject
+ -o smtpd_tls_mandatory_protocols=$smtps_smtpd_tls_mandatory_protocols
+ -o tls_preempt_cipherlist=yes
+ -o cleanup_service_name=smtp_sender_cleanup
+ -o syslog_name=postfix/smtps
+ -o smtpd_end_of_data_restrictions=$smtpd_last_auth
+10465 inet n - n - - smtpd
+ -o smtpd_upstream_proxy_protocol=haproxy
+ -o smtpd_tls_wrappermode=yes
+ -o smtpd_client_restrictions=permit_mynetworks,permit_sasl_authenticated,reject
+ -o smtpd_tls_mandatory_protocols=$smtps_smtpd_tls_mandatory_protocols
+ -o tls_preempt_cipherlist=yes
+ -o cleanup_service_name=smtp_sender_cleanup
+ -o syslog_name=postfix/smtps-haproxy
+ -o smtpd_end_of_data_restrictions=$smtpd_last_auth
+
+# smtpd with starttls on 587/tcp
+# TLS protocol can be modified by setting submission_smtpd_tls_mandatory_protocols in extra.cf
+submission inet n - n - - smtpd
+ -o smtpd_client_restrictions=permit_mynetworks,permit_sasl_authenticated,reject
+ -o smtpd_enforce_tls=yes
+ -o smtpd_tls_security_level=encrypt
+ -o smtpd_tls_mandatory_protocols=$submission_smtpd_tls_mandatory_protocols
+ -o tls_preempt_cipherlist=yes
+ -o cleanup_service_name=smtp_sender_cleanup
+ -o syslog_name=postfix/submission
+ -o smtpd_end_of_data_restrictions=$smtpd_last_auth
+10587 inet n - n - - smtpd
+ -o smtpd_upstream_proxy_protocol=haproxy
+ -o smtpd_client_restrictions=permit_mynetworks,permit_sasl_authenticated,reject
+ -o smtpd_enforce_tls=yes
+ -o smtpd_tls_security_level=encrypt
+ -o smtpd_tls_mandatory_protocols=$submission_smtpd_tls_mandatory_protocols
+ -o tls_preempt_cipherlist=yes
+ -o cleanup_service_name=smtp_sender_cleanup
+ -o syslog_name=postfix/submission-haproxy
+ -o smtpd_end_of_data_restrictions=$smtpd_last_auth
+
+# used by SOGo
+# smtpd_sender_restrictions should match main.cf, but with check_sasl_access prepended for login-as-mailbox-user function
+588 inet n - n - - smtpd
+ -o smtpd_client_restrictions=permit_mynetworks,permit_sasl_authenticated,reject
+ -o smtpd_tls_auth_only=no
+ -o smtpd_sender_restrictions=check_sasl_access,regexp:/opt/postfix/conf/allow_mailcow_local.regexp,reject_authenticated_sender_login_mismatch,permit_mynetworks,permit_sasl_authenticated,reject_unlisted_sender,reject_unknown_sender_domain
+ -o cleanup_service_name=smtp_sender_cleanup
+ -o syslog_name=postfix/sogo
+ -o smtpd_end_of_data_restrictions=$smtpd_last_auth
+
+# used to reinject quarantine mails
+590 inet n - n - - smtpd
+ -o smtpd_helo_restrictions=
+ -o smtpd_client_restrictions=permit_mynetworks,reject
+ -o smtpd_tls_auth_only=no
+ -o smtpd_milters=
+ -o non_smtpd_milters=
+ -o syslog_name=postfix/quarantine
+ -o smtpd_end_of_data_restrictions=$smtpd_last_auth
+
+# enforced smtp connector
+smtp_enforced_tls unix - - n - - smtp
+ -o smtp_tls_security_level=encrypt
+ -o syslog_name=enforced-tls-smtp
+ -o smtp_delivery_status_filter=pcre:/opt/postfix/conf/smtp_dsn_filter
+
+# smtp connector used, when a transport map matched
+# this helps to have different sasl maps than we have with sender dependent transport maps
+smtp_via_transport_maps unix - - n - - smtp
+ -o smtp_sasl_password_maps=proxy:mysql:/opt/postfix/conf/sql/mysql_sasl_passwd_maps_transport_maps.cf
+
+tlsproxy unix - - n - 0 tlsproxy
+dnsblog unix - - n - 0 dnsblog
+pickup fifo n - n 60 1 pickup
+cleanup unix n - n - 0 cleanup
+qmgr fifo n - n 300 1 qmgr
+tlsmgr unix - - n 1000? 1 tlsmgr
+rewrite unix - - n - - trivial-rewrite
+bounce unix - - n - 0 bounce
+defer unix - - n - 0 bounce
+trace unix - - n - 0 bounce
+verify unix - - n - 1 verify
+flush unix n - n 1000? 0 flush
+proxymap unix - - n - - proxymap
+proxywrite unix - - n - 1 proxymap
+smtp unix - - n - - smtp
+relay unix - - n - - smtp
+showq unix n - n - - showq
+error unix - - n - - error
+retry unix - - n - - error
+discard unix - - n - - discard
+local unix - n n - - local
+virtual unix - n n - - virtual
+lmtp unix - - n - - lmtp
+anvil unix - - n - 1 anvil
+scache unix - - n - 1 scache
+maildrop unix - n n - - pipe flags=DRhu
+ user=vmail argv=/usr/bin/maildrop -d ${recipient}
+
+# used to anonymize sender IP
+smtp_sender_cleanup unix n - y - 0 cleanup
+ -o header_checks=$smtp_header_checks
+
+# start whitelist_fwd
+127.0.0.1:10027 inet n n n - 0 spawn user=nobody argv=/usr/local/bin/whitelist_forwardinghosts.sh
+127.0.0.1:10028 inet n n n - 0 spawn user=nobody argv=/usr/local/bin/smtpd_last_login.sh
+# end whitelist_fwd
+
+# start watchdog-specific
+# logs to local7 (hidden)
+589 inet n - n - - smtpd
+ -o smtpd_client_restrictions=permit_mynetworks,reject
+ -o syslog_name=watchdog
+ -o syslog_facility=local7
+ -o smtpd_milters=
+ -o cleanup_service_name=watchdog_cleanup
+ -o non_smtpd_milters=
+watchdog_cleanup unix n - n - 0 cleanup
+ -o syslog_name=watchdog
+ -o syslog_facility=local7
+ -o queue_service_name=watchdog_qmgr
+watchdog_qmgr fifo n - n 300 1 qmgr
+ -o syslog_facility=local7
+ -o syslog_name=watchdog
+ -o rewrite_service_name=watchdog_rewrite
+watchdog_rewrite unix - - n - - trivial-rewrite
+ -o syslog_facility=local7
+ -o syslog_name=watchdog
+ -o local_transport=watchdog_discard
+watchdog_discard unix - - n - - discard
+ -o syslog_facility=local7
+ -o syslog_name=watchdog
+# end watchdog-specific
diff --git a/mailcow/src/mailcow-dockerized/data/conf/postfix/postscreen_access.cidr b/mailcow/src/mailcow-dockerized/data/conf/postfix/postscreen_access.cidr
new file mode 100644
index 0000000..63c7342
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/postfix/postscreen_access.cidr
@@ -0,0 +1,1932 @@
+# Whitelist generated by Postwhite v3.4 on Sun Dec 15 21:16:19 CET 2019
+# https://github.com/stevejenkins/postwhite/
+# 1928 total rules
+2a00:1450:4000::/36 permit
+2a01:111:f400::/48 permit
+2a01:111:f403::/48 permit
+2a02:a60:0:5::/64 permit
+2c0f:fb50:4000::/36 permit
+3.93.157.0/24 permit
+8.20.114.31 permit
+8.25.194.0/23 permit
+8.25.196.0/23 permit
+8.39.54.0/23 permit
+8.40.222.0/23 permit
+8.45.169.0/24 permit
+12.130.86.238 permit
+13.77.161.179 permit
+13.111.0.0/16 permit
+13.111.0.0/22 permit
+13.111.52.0/22 permit
+13.111.63.0/24 permit
+13.111.68.0/24 permit
+13.111.72.0/22 permit
+13.111.92.0/24 permit
+13.111.111.0/24 permit
+17.36.0.0/16 permit
+17.41.0.0/16 permit
+17.58.0.0/16 permit
+17.110.0.0/15 permit
+17.111.110.0/23 permit
+17.120.0.0/16 permit
+17.133.0.0/16 permit
+17.139.0.0/16 permit
+17.142.0.0/15 permit
+17.151.1.0/24 permit
+17.158.0.0/15 permit
+17.162.0.0/15 permit
+17.164.0.0/16 permit
+17.171.37.0/24 permit
+17.172.0.0/16 permit
+17.179.168.0/23 permit
+18.194.95.56 permit
+18.208.124.128/25 permit
+20.185.214.0/27 permit
+20.185.214.2 permit
+20.185.214.32/27 permit
+20.185.214.64/27 permit
+23.23.237.213 permit
+23.103.131.7 permit
+23.103.224.0/19 permit
+23.253.182.0/23 permit
+23.253.182.103 permit
+23.253.183.145 permit
+23.253.183.146 permit
+23.253.183.147 permit
+23.253.183.148 permit
+23.253.183.150 permit
+27.123.204.128/30 permit
+27.123.204.132/31 permit
+27.123.204.148/30 permit
+27.123.204.152 permit
+27.123.204.168/30 permit
+27.123.204.172 permit
+27.123.204.188/30 permit
+27.123.204.192 permit
+27.123.206.0/24 permit
+27.123.206.50/31 permit
+27.123.206.56/29 permit
+27.123.206.76/30 permit
+27.123.206.80/28 permit
+27.126.146.0/24 permit
+34.200.123.20 permit
+34.212.163.75 permit
+34.213.104.127 permit
+34.225.212.172 permit
+35.176.132.251 permit
+35.190.247.0/24 permit
+35.191.0.0/16 permit
+37.188.97.188 permit
+37.218.248.47 permit
+37.218.249.47 permit
+37.218.251.62 permit
+40.76.4.15 permit
+40.92.0.0/15 permit
+40.97.116.82 permit
+40.97.128.194 permit
+40.97.148.226 permit
+40.97.153.146 permit
+40.97.156.114 permit
+40.97.160.2 permit
+40.97.161.50 permit
+40.97.164.146 permit
+40.107.0.0/16 permit
+40.112.72.205 permit
+40.113.200.201 permit
+41.74.192.0/22 permit
+41.74.196.0/22 permit
+41.74.200.0/23 permit
+41.74.201.0/24 permit
+41.74.204.0/23 permit
+41.74.205.0/24 permit
+42.159.163.81 permit
+42.159.163.82 permit
+42.159.163.83 permit
+46.19.168.0/23 permit
+46.226.48.0/21 permit
+46.228.36.37 permit
+46.228.36.38/31 permit
+46.228.36.212/30 permit
+46.228.36.216/31 permit
+46.228.37.1 permit
+46.228.37.2 permit
+46.228.37.3 permit
+46.228.37.4 permit
+46.228.37.5 permit
+46.228.37.6/31 permit
+46.228.37.8/31 permit
+46.228.37.10/31 permit
+46.228.37.12/30 permit
+46.228.37.16/30 permit
+46.228.37.20/30 permit
+46.228.37.24/30 permit
+46.228.37.28/31 permit
+46.228.37.30/31 permit
+46.228.37.32/29 permit
+46.228.37.40/29 permit
+46.228.37.48/31 permit
+46.228.37.50/31 permit
+46.228.37.52/30 permit
+46.228.37.56/31 permit
+46.228.38.33 permit
+46.228.38.34/31 permit
+46.228.38.36/31 permit
+46.228.38.38 permit
+46.228.38.53 permit
+46.228.38.54/31 permit
+46.228.38.56/31 permit
+46.228.38.58 permit
+46.228.38.101 permit
+46.228.38.102/31 permit
+46.228.38.128/28 permit
+46.228.38.144/29 permit
+46.228.38.152/31 permit
+46.228.38.154 permit
+46.228.39.0/24 permit
+46.228.39.64/27 permit
+46.228.39.96/30 permit
+46.228.39.100/30 permit
+46.228.39.104/29 permit
+46.228.39.112/31 permit
+46.243.88.174 permit
+46.243.88.175 permit
+46.243.88.176 permit
+46.243.88.177 permit
+50.18.45.249 permit
+50.18.121.236 permit
+50.18.121.248 permit
+50.18.123.221 permit
+50.18.124.70 permit
+50.18.125.97 permit
+50.18.125.237 permit
+50.18.126.162 permit
+50.23.218.192/27 permit
+50.31.32.0/19 permit
+50.31.36.197 permit
+50.31.36.199 permit
+50.31.36.205 permit
+50.31.36.208 permit
+50.31.36.213 permit
+50.31.44.111 permit
+50.31.57.54/31 permit
+50.31.57.60 permit
+50.31.57.61 permit
+50.31.57.62 permit
+50.31.60.1 permit
+50.31.156.96/27 permit
+50.31.205.0/24 permit
+50.207.218.237 permit
+51.4.71.62 permit
+51.163.158.0/24 permit
+51.163.159.0/24 permit
+52.0.20.102 permit
+52.5.230.59 permit
+52.27.5.72 permit
+52.27.28.47 permit
+52.33.191.91 permit
+52.36.138.31 permit
+52.37.142.146 permit
+52.38.191.253 permit
+52.41.64.145 permit
+52.60.41.5 permit
+52.60.115.116 permit
+52.95.48.152/29 permit
+52.95.49.88/29 permit
+52.100.0.0/14 permit
+52.128.40.0/21 permit
+52.200.59.0/24 permit
+52.205.61.79 permit
+52.207.191.216 permit
+52.222.62.51 permit
+52.222.73.83 permit
+52.222.73.120 permit
+52.222.75.85 permit
+54.90.148.255 permit
+54.156.255.69 permit
+54.172.97.247 permit
+54.173.229.38 permit
+54.174.52.0/24 permit
+54.174.53.128/30 permit
+54.174.57.0/24 permit
+54.174.59.0/24 permit
+54.174.60.0/23 permit
+54.174.63.0/24 permit
+54.186.193.102 permit
+54.214.39.184 permit
+54.240.0.0/18 permit
+54.240.40.0/25 permit
+54.240.56.128/26 permit
+54.240.63.0/25 permit
+54.241.16.209 permit
+54.243.205.80 permit
+54.244.54.130 permit
+54.244.242.0/24 permit
+62.13.128.0/24 permit
+62.13.129.128/25 permit
+62.13.136.0/22 permit
+62.13.140.0/22 permit
+62.13.144.0/22 permit
+62.13.148.0/23 permit
+62.13.150.0/23 permit
+62.13.152.0/23 permit
+62.17.146.128/26 permit
+62.140.7.0/24 permit
+62.140.10.0/24 permit
+63.80.14.0/23 permit
+63.111.28.137 permit
+63.128.21.0/24 permit
+63.143.57.128/25 permit
+63.143.59.128/25 permit
+64.18.0.0/20 permit
+64.20.241.45 permit
+64.34.47.128/27 permit
+64.34.57.192/26 permit
+64.79.155.0/24 permit
+64.79.155.192 permit
+64.89.45.192/30 permit
+64.89.45.196 permit
+64.95.144.196 permit
+64.127.115.252 permit
+64.132.88.0/23 permit
+64.132.92.0/24 permit
+64.135.77.0/24 permit
+64.135.83.0/24 permit
+64.147.123.17 permit
+64.147.123.18 permit
+64.147.123.19 permit
+64.147.123.20 permit
+64.147.123.21 permit
+64.147.123.24 permit
+64.147.123.25 permit
+64.147.123.26 permit
+64.147.123.27 permit
+64.147.123.28 permit
+64.147.123.29 permit
+64.207.219.7 permit
+64.207.219.8 permit
+64.207.219.9 permit
+64.207.219.10 permit
+64.207.219.11 permit
+64.207.219.12 permit
+64.207.219.71 permit
+64.207.219.72 permit
+64.207.219.73 permit
+64.207.219.74 permit
+64.207.219.75 permit
+64.207.219.76 permit
+64.207.219.135 permit
+64.207.219.136 permit
+64.207.219.137 permit
+64.207.219.138 permit
+64.207.219.139 permit
+64.207.219.140 permit
+64.233.160.0/19 permit
+65.38.115.76 permit
+65.38.115.84 permit
+65.39.215.0/24 permit
+65.52.80.137 permit
+65.54.51.64/26 permit
+65.54.61.64/26 permit
+65.54.121.120/29 permit
+65.54.121.124/31 permit
+65.54.190.0/24 permit
+65.54.241.0/24 permit
+65.55.29.77 permit
+65.55.33.64/28 permit
+65.55.34.0/24 permit
+65.55.42.224/28 permit
+65.55.52.224/27 permit
+65.55.78.128/25 permit
+65.55.81.48/28 permit
+65.55.81.54/31 permit
+65.55.90.0/24 permit
+65.55.94.0/25 permit
+65.55.111.0/24 permit
+65.55.113.64/26 permit
+65.55.116.0/25 permit
+65.55.126.0/25 permit
+65.55.174.0/25 permit
+65.55.178.128/27 permit
+65.55.234.192/26 permit
+65.110.161.77 permit
+65.123.29.213 permit
+65.123.29.220 permit
+65.154.166.0/24 permit
+65.212.180.36 permit
+66.102.0.0/20 permit
+66.111.4.25 permit
+66.111.4.26 permit
+66.111.4.27 permit
+66.111.4.28 permit
+66.111.4.29 permit
+66.111.4.221 permit
+66.111.4.222 permit
+66.111.4.224 permit
+66.111.4.225 permit
+66.111.4.229 permit
+66.111.4.230 permit
+66.135.202.0/27 permit
+66.135.215.0/24 permit
+66.135.222.1 permit
+66.162.193.226/31 permit
+66.163.184.0/21 permit
+66.163.184.0/24 permit
+66.163.185.0/24 permit
+66.163.186.0/24 permit
+66.163.187.0/24 permit
+66.163.188.0/24 permit
+66.163.189.0/24 permit
+66.163.190.0/24 permit
+66.163.191.0/24 permit
+66.170.126.97 permit
+66.196.80.112/28 permit
+66.196.80.144/29 permit
+66.196.80.193 permit
+66.196.81.0/24 permit
+66.196.81.104/29 permit
+66.196.81.112/29 permit
+66.196.81.120 permit
+66.196.81.125 permit
+66.196.81.126/31 permit
+66.196.81.128/28 permit
+66.196.81.144/29 permit
+66.196.81.152/31 permit
+66.196.81.154 permit
+66.196.81.225 permit
+66.196.81.226/31 permit
+66.196.81.228/30 permit
+66.196.81.232/31 permit
+66.196.81.234 permit
+66.211.168.230/31 permit
+66.211.184.0/23 permit
+66.218.74.64/30 permit
+66.218.74.68/31 permit
+66.218.75.112/30 permit
+66.218.75.116/31 permit
+66.218.75.144/31 permit
+66.218.75.146 permit
+66.218.75.152 permit
+66.218.75.192/30 permit
+66.218.75.196/31 permit
+66.218.75.203 permit
+66.218.75.212/30 permit
+66.218.75.216/31 permit
+66.218.75.223 permit
+66.218.75.232/30 permit
+66.218.75.236/31 permit
+66.218.75.243 permit
+66.218.75.252/31 permit
+66.218.75.254 permit
+66.220.144.128/25 permit
+66.220.155.0/24 permit
+66.220.157.0/25 permit
+66.231.80.0/20 permit
+66.240.227.0/24 permit
+66.249.80.0/20 permit
+67.23.31.6 permit
+67.72.99.26 permit
+67.195.22.0/24 permit
+67.195.22.113 permit
+67.195.22.116/30 permit
+67.195.23.144/30 permit
+67.195.23.148 permit
+67.195.60.0/24 permit
+67.195.60.45 permit
+67.195.60.46/31 permit
+67.195.60.48/31 permit
+67.195.60.50 permit
+67.195.60.146 permit
+67.195.60.155 permit
+67.195.60.156 permit
+67.195.87.0/24 permit
+67.195.87.64 permit
+67.195.87.81 permit
+67.195.87.82/31 permit
+67.195.87.84/31 permit
+67.195.87.86 permit
+67.195.87.128 permit
+67.195.87.145 permit
+67.195.87.146/31 permit
+67.195.87.192 permit
+67.195.87.209 permit
+67.195.87.210/31 permit
+67.195.124.137 permit
+67.195.124.139 permit
+67.195.124.141 permit
+67.195.124.143 permit
+67.195.124.145 permit
+67.195.124.147 permit
+67.219.240.0/20 permit
+67.221.168.65 permit
+67.228.2.24/30 permit
+67.228.21.184/29 permit
+67.228.34.32/27 permit
+67.228.37.4/30 permit
+67.228.50.54/31 permit
+67.231.145.42 permit
+67.231.153.30 permit
+68.142.230.0/24 permit
+68.142.230.64/31 permit
+68.142.230.69 permit
+68.142.230.70/31 permit
+68.142.230.72/30 permit
+68.142.230.76/31 permit
+68.142.230.78 permit
+68.232.131.164 permit
+68.232.131.172 permit
+68.232.131.183 permit
+68.232.131.185 permit
+68.232.143.44 permit
+68.232.145.216 permit
+68.232.148.56 permit
+68.232.148.128 permit
+68.232.148.138 permit
+68.232.157.60 permit
+68.232.157.143 permit
+68.232.192.0/20 permit
+69.63.178.128/25 permit
+69.63.181.0/24 permit
+69.63.184.0/25 permit
+69.65.42.195 permit
+69.65.49.192/29 permit
+69.72.32.0/20 permit
+69.147.84.227 permit
+69.162.98.0/24 permit
+69.169.224.0/20 permit
+69.171.232.0/24 permit
+69.171.244.0/23 permit
+70.37.151.128/25 permit
+70.42.149.35 permit
+72.3.185.0/24 permit
+72.3.237.64/28 permit
+72.14.192.0/18 permit
+72.21.192.0/19 permit
+72.21.217.142 permit
+72.30.234.152/29 permit
+72.30.236.160/30 permit
+72.30.236.164/31 permit
+72.30.236.180/30 permit
+72.30.236.184/31 permit
+72.30.236.208/30 permit
+72.30.236.212/31 permit
+72.30.236.224/30 permit
+72.30.236.228/31 permit
+72.30.236.244/30 permit
+72.30.236.248/31 permit
+72.30.237.32/30 permit
+72.30.237.36/31 permit
+72.30.237.52/30 permit
+72.30.237.56/31 permit
+72.30.237.80/31 permit
+72.30.237.96/30 permit
+72.30.237.100/31 permit
+72.30.237.116/30 permit
+72.30.237.120/31 permit
+72.30.237.144/30 permit
+72.30.237.148/31 permit
+72.30.237.160/30 permit
+72.30.237.164/31 permit
+72.30.237.180/30 permit
+72.30.237.184/31 permit
+72.30.237.204/30 permit
+72.30.238.0/23 permit
+72.30.238.116/30 permit
+72.30.238.120/31 permit
+72.30.238.128 permit
+72.30.238.133 permit
+72.30.238.168/30 permit
+72.30.238.172/31 permit
+72.30.238.188/30 permit
+72.30.238.192 permit
+72.30.238.197 permit
+72.30.238.224/31 permit
+72.30.238.240/30 permit
+72.30.238.244/31 permit
+72.30.239.5 permit
+72.30.239.37 permit
+72.30.239.38/31 permit
+72.30.239.40/31 permit
+72.30.239.42 permit
+72.30.239.57 permit
+72.30.239.64 permit
+72.30.239.69 permit
+72.30.239.89 permit
+72.30.239.90/31 permit
+72.30.239.92/31 permit
+72.30.239.94 permit
+72.30.239.128 permit
+72.30.239.198 permit
+72.30.239.224/30 permit
+72.30.239.228/31 permit
+72.30.239.244/30 permit
+72.30.239.248/31 permit
+72.32.154.0/24 permit
+72.32.217.0/24 permit
+72.32.243.0/24 permit
+72.34.168.75 permit
+72.34.168.76 permit
+72.52.72.32/28 permit
+72.52.72.36 permit
+74.6.128.0/21 permit
+74.6.128.0/24 permit
+74.6.129.0/24 permit
+74.6.130.0/24 permit
+74.6.131.0/24 permit
+74.6.132.0/24 permit
+74.6.133.0/24 permit
+74.6.134.0/24 permit
+74.6.135.0/24 permit
+74.63.63.115 permit
+74.63.63.121 permit
+74.63.194.126 permit
+74.63.212.0/24 permit
+74.63.234.75 permit
+74.63.236.0/24 permit
+74.86.113.28/30 permit
+74.86.129.240/30 permit
+74.86.131.208/30 permit
+74.86.132.208/30 permit
+74.86.160.160/30 permit
+74.86.164.188/30 permit
+74.86.171.192/30 permit
+74.86.195.28/30 permit
+74.86.207.36/30 permit
+74.86.226.216/30 permit
+74.86.236.240/30 permit
+74.86.241.250/31 permit
+74.112.67.243 permit
+74.125.0.0/16 permit
+74.202.227.40 permit
+74.208.4.192/26 permit
+74.208.5.64/26 permit
+74.208.122.0/26 permit
+74.209.250.0/24 permit
+74.209.250.12 permit
+75.126.253.48 permit
+76.223.176.0/24 permit
+76.223.180.0/23 permit
+76.223.188.0/24 permit
+76.223.189.0/24 permit
+76.223.190.0/24 permit
+77.238.176.0/22 permit
+77.238.176.0/24 permit
+77.238.177.0/24 permit
+77.238.178.0/24 permit
+77.238.179.0/24 permit
+77.238.189.21 permit
+77.238.189.23 permit
+77.238.189.35 permit
+77.238.189.39 permit
+77.238.189.58/31 permit
+77.238.189.60/30 permit
+77.238.189.64/29 permit
+77.238.189.76/31 permit
+77.238.189.128/30 permit
+77.238.189.132/31 permit
+77.238.189.137 permit
+77.238.189.138/31 permit
+77.238.189.140/31 permit
+77.238.189.142 permit
+77.238.189.146/31 permit
+77.238.189.148/30 permit
+81.223.46.0/27 permit
+82.165.159.0/24 permit
+82.165.159.0/26 permit
+82.165.229.130 permit
+82.165.230.22 permit
+84.16.77.1 permit
+85.158.136.0/21 permit
+86.61.88.25 permit
+87.238.80.0/21 permit
+87.248.103.12 permit
+87.248.103.21 permit
+87.248.103.23 permit
+87.248.103.27 permit
+87.248.103.29 permit
+87.248.103.36 permit
+87.248.103.42/31 permit
+87.248.103.44 permit
+87.248.103.64 permit
+87.248.103.76 permit
+87.248.103.83 permit
+87.248.103.92/31 permit
+87.248.103.94 permit
+87.248.103.107 permit
+87.248.103.113 permit
+87.248.103.122 permit
+87.248.110.0/24 permit
+87.248.117.30 permit
+87.248.117.65 permit
+87.248.117.67 permit
+87.248.117.70 permit
+87.248.117.73 permit
+87.248.117.74 permit
+87.248.117.86 permit
+87.248.117.97 permit
+87.248.117.98 permit
+87.248.117.104 permit
+87.248.117.119 permit
+87.248.117.124 permit
+87.248.117.185 permit
+87.248.117.196 permit
+87.248.117.198 permit
+87.248.117.201 permit
+87.248.117.202 permit
+87.248.117.205 permit
+87.253.232.0/21 permit
+89.22.108.0/24 permit
+91.194.248.0/23 permit
+91.211.240.0/22 permit
+91.211.243.0/24 permit
+91.220.42.0/24 permit
+94.236.119.0/26 permit
+94.245.112.0/27 permit
+94.245.112.10/31 permit
+95.131.104.0/21 permit
+96.43.144.0/20 permit
+96.43.144.64/28 permit
+96.43.144.64/31 permit
+96.43.148.64/28 permit
+96.43.148.64/31 permit
+96.43.151.64/28 permit
+96.46.150.192/27 permit
+98.136.44.181 permit
+98.136.44.182/31 permit
+98.136.44.184 permit
+98.136.164.0/24 permit
+98.136.164.36/31 permit
+98.136.164.64/29 permit
+98.136.164.72/30 permit
+98.136.164.76/31 permit
+98.136.164.78 permit
+98.136.172.32/30 permit
+98.136.172.36/31 permit
+98.136.185.0/24 permit
+98.136.185.29 permit
+98.136.185.42/31 permit
+98.136.185.46 permit
+98.136.185.115 permit
+98.136.214.28/30 permit
+98.136.214.97 permit
+98.136.214.98/31 permit
+98.136.214.100 permit
+98.136.214.116/30 permit
+98.136.214.120/31 permit
+98.136.214.157 permit
+98.136.214.158/31 permit
+98.136.214.160/31 permit
+98.136.214.162 permit
+98.136.214.190/31 permit
+98.136.214.192/30 permit
+98.136.214.238/31 permit
+98.136.214.255 permit
+98.136.215.0/31 permit
+98.136.215.2 permit
+98.136.215.3 permit
+98.136.215.4/31 permit
+98.136.215.6 permit
+98.136.215.114/31 permit
+98.136.215.116/31 permit
+98.136.215.118 permit
+98.136.215.136/30 permit
+98.136.215.148/30 permit
+98.136.215.152/31 permit
+98.136.215.179 permit
+98.136.215.180/30 permit
+98.136.215.184 permit
+98.136.215.208/30 permit
+98.136.215.212/31 permit
+98.136.217.0/24 permit
+98.136.217.1 permit
+98.136.217.2 permit
+98.136.217.3 permit
+98.136.217.4/30 permit
+98.136.217.8/31 permit
+98.136.217.10/31 permit
+98.136.217.12/30 permit
+98.136.217.16/30 permit
+98.136.217.20/30 permit
+98.136.218.0/24 permit
+98.136.218.39 permit
+98.136.218.40/29 permit
+98.136.218.48/28 permit
+98.136.218.67 permit
+98.136.218.68/30 permit
+98.136.218.72/30 permit
+98.137.12.0/24 permit
+98.137.12.48/30 permit
+98.137.12.52/31 permit
+98.137.12.54 permit
+98.137.12.177 permit
+98.137.12.178/31 permit
+98.137.12.180/31 permit
+98.137.12.182 permit
+98.137.12.192/27 permit
+98.137.12.224/28 permit
+98.137.12.240/29 permit
+98.137.12.248/30 permit
+98.137.12.252/31 permit
+98.137.12.254 permit
+98.137.13.81 permit
+98.137.13.82 permit
+98.137.13.87 permit
+98.137.13.88 permit
+98.137.13.91 permit
+98.137.13.92 permit
+98.137.13.97 permit
+98.137.13.98 permit
+98.137.13.101 permit
+98.137.13.102 permit
+98.137.13.107 permit
+98.137.13.108 permit
+98.137.13.111 permit
+98.137.13.112 permit
+98.137.13.117 permit
+98.137.13.118 permit
+98.137.13.121 permit
+98.137.13.122 permit
+98.137.13.127 permit
+98.137.13.128 permit
+98.137.13.131 permit
+98.137.13.132 permit
+98.137.13.137 permit
+98.137.13.138 permit
+98.137.64.0/21 permit
+98.137.64.0/24 permit
+98.137.65.0/24 permit
+98.137.66.0/24 permit
+98.137.67.0/24 permit
+98.137.68.0/24 permit
+98.137.69.0/24 permit
+98.137.70.0/24 permit
+98.137.71.0/24 permit
+98.137.176.58/31 permit
+98.137.177.247 permit
+98.138.31.128/30 permit
+98.138.31.132/31 permit
+98.138.31.192/30 permit
+98.138.31.196/31 permit
+98.138.31.202/31 permit
+98.138.31.204/30 permit
+98.138.31.232/30 permit
+98.138.31.236/31 permit
+98.138.82.208/30 permit
+98.138.82.212/31 permit
+98.138.83.176/31 permit
+98.138.83.179 permit
+98.138.83.180/31 permit
+98.138.84.0/22 permit
+98.138.84.37 permit
+98.138.84.38/31 permit
+98.138.84.40/29 permit
+98.138.85.128/30 permit
+98.138.85.132/31 permit
+98.138.85.148/30 permit
+98.138.85.152/31 permit
+98.138.85.168/30 permit
+98.138.85.172/31 permit
+98.138.85.188/30 permit
+98.138.85.192/31 permit
+98.138.85.208/30 permit
+98.138.85.212/31 permit
+98.138.85.228/30 permit
+98.138.85.232/31 permit
+98.138.85.248/30 permit
+98.138.85.252/31 permit
+98.138.86.69 permit
+98.138.86.156/31 permit
+98.138.86.192/30 permit
+98.138.86.196/31 permit
+98.138.87.1 permit
+98.138.87.2/31 permit
+98.138.87.4/31 permit
+98.138.87.6 permit
+98.138.87.7 permit
+98.138.87.8/31 permit
+98.138.87.10/31 permit
+98.138.87.12 permit
+98.138.87.16/30 permit
+98.138.87.64/30 permit
+98.138.87.68/31 permit
+98.138.87.73 permit
+98.138.87.74/31 permit
+98.138.87.76/31 permit
+98.138.87.78 permit
+98.138.87.144/30 permit
+98.138.87.148/31 permit
+98.138.87.192/30 permit
+98.138.87.196/31 permit
+98.138.88.0/22 permit
+98.138.88.105 permit
+98.138.88.106 permit
+98.138.88.128/30 permit
+98.138.88.132/31 permit
+98.138.88.148/30 permit
+98.138.88.152/31 permit
+98.138.88.232/29 permit
+98.138.89.160/28 permit
+98.138.89.192/29 permit
+98.138.89.232/31 permit
+98.138.89.234 permit
+98.138.89.240 permit
+98.138.89.244/31 permit
+98.138.89.246 permit
+98.138.89.248/30 permit
+98.138.89.252/31 permit
+98.138.89.254 permit
+98.138.90.64/28 permit
+98.138.90.80/29 permit
+98.138.90.88/30 permit
+98.138.90.92/31 permit
+98.138.90.95 permit
+98.138.90.96/30 permit
+98.138.90.100 permit
+98.138.90.104/30 permit
+98.138.90.108/31 permit
+98.138.90.113 permit
+98.138.90.114/31 permit
+98.138.90.116/31 permit
+98.138.90.118 permit
+98.138.90.122/31 permit
+98.138.90.124/30 permit
+98.138.90.131 permit
+98.138.90.132/30 permit
+98.138.90.136 permit
+98.138.91.1 permit
+98.138.91.2/31 permit
+98.138.91.4/31 permit
+98.138.91.6 permit
+98.138.100.0/23 permit
+98.138.100.220/30 permit
+98.138.100.224/30 permit
+98.138.100.228/31 permit
+98.138.101.160/28 permit
+98.138.101.176/29 permit
+98.138.104.96/30 permit
+98.138.104.100 permit
+98.138.104.112/30 permit
+98.138.104.116 permit
+98.138.120.0/24 permit
+98.138.120.36/30 permit
+98.138.120.48/28 permit
+98.138.197.46/31 permit
+98.138.197.48/30 permit
+98.138.197.169 permit
+98.138.197.176 permit
+98.138.197.180 permit
+98.138.198.52/31 permit
+98.138.198.54 permit
+98.138.198.56 permit
+98.138.198.61 permit
+98.138.198.190/31 permit
+98.138.198.239 permit
+98.138.199.6 permit
+98.138.199.9 permit
+98.138.199.48 permit
+98.138.199.83 permit
+98.138.199.84 permit
+98.138.199.86/31 permit
+98.138.199.94 permit
+98.138.199.116 permit
+98.138.199.208/30 permit
+98.138.199.212/31 permit
+98.138.199.218/31 permit
+98.138.199.220/30 permit
+98.138.199.236 permit
+98.138.206.67 permit
+98.138.206.73 permit
+98.138.206.143 permit
+98.138.206.167 permit
+98.138.206.169 permit
+98.138.206.173 permit
+98.138.207.9 permit
+98.138.207.10/31 permit
+98.138.207.12/31 permit
+98.138.207.14 permit
+98.138.210.39 permit
+98.138.210.64/30 permit
+98.138.210.68/31 permit
+98.138.210.74/31 permit
+98.138.210.76/30 permit
+98.138.210.84 permit
+98.138.210.86 permit
+98.138.210.89 permit
+98.138.210.93 permit
+98.138.210.94 permit
+98.138.210.96 permit
+98.138.210.98 permit
+98.138.210.101 permit
+98.138.210.111 permit
+98.138.210.115 permit
+98.138.210.122 permit
+98.138.210.136 permit
+98.138.210.146 permit
+98.138.210.148 permit
+98.138.210.155 permit
+98.138.210.158/31 permit
+98.138.210.166 permit
+98.138.210.169 permit
+98.138.210.175 permit
+98.138.210.177 permit
+98.138.210.181 permit
+98.138.210.182/31 permit
+98.138.210.187 permit
+98.138.210.189 permit
+98.138.210.201 permit
+98.138.210.203 permit
+98.138.210.210 permit
+98.138.210.240/30 permit
+98.138.210.244/31 permit
+98.138.211.122/31 permit
+98.138.211.124/30 permit
+98.138.211.128/30 permit
+98.138.211.132/31 permit
+98.138.211.148/30 permit
+98.138.211.152/31 permit
+98.138.211.216/30 permit
+98.138.211.220/31 permit
+98.138.213.128/30 permit
+98.138.213.132/31 permit
+98.138.213.138/31 permit
+98.138.213.140/30 permit
+98.138.213.148/30 permit
+98.138.213.152/31 permit
+98.138.213.158/31 permit
+98.138.213.160/30 permit
+98.138.213.168/30 permit
+98.138.213.172/31 permit
+98.138.213.237 permit
+98.138.213.238/31 permit
+98.138.213.240/31 permit
+98.138.213.242 permit
+98.138.215.0/24 permit
+98.138.215.12/30 permit
+98.138.215.16/28 permit
+98.138.217.216/30 permit
+98.138.217.220/31 permit
+98.138.226.0/24 permit
+98.138.226.30/31 permit
+98.138.226.56/29 permit
+98.138.226.64/30 permit
+98.138.226.68/31 permit
+98.138.226.74/31 permit
+98.138.226.76/30 permit
+98.138.226.84/30 permit
+98.138.226.88/31 permit
+98.138.226.124/30 permit
+98.138.226.128/30 permit
+98.138.226.132/31 permit
+98.138.226.160/29 permit
+98.138.226.168/31 permit
+98.138.226.240/30 permit
+98.138.226.244 permit
+98.138.227.32/30 permit
+98.138.227.36/31 permit
+98.138.227.56/30 permit
+98.138.227.60/31 permit
+98.138.227.80/30 permit
+98.138.227.84/31 permit
+98.138.227.104/30 permit
+98.138.227.108/31 permit
+98.138.227.128/30 permit
+98.138.227.132/31 permit
+98.138.229.0/24 permit
+98.138.229.24/29 permit
+98.138.229.32/31 permit
+98.138.229.122/31 permit
+98.138.229.138/31 permit
+98.138.229.154/31 permit
+98.138.229.170/31 permit
+98.139.164.0/24 permit
+98.139.164.96/30 permit
+98.139.164.100/30 permit
+98.139.164.104/29 permit
+98.139.164.112/30 permit
+98.139.172.112/30 permit
+98.139.172.116/31 permit
+98.139.175.0/24 permit
+98.139.175.65 permit
+98.139.175.66/31 permit
+98.139.175.68/30 permit
+98.139.175.72/29 permit
+98.139.175.80/29 permit
+98.139.175.88/30 permit
+98.139.175.92/31 permit
+98.139.175.94 permit
+98.139.210.112/30 permit
+98.139.210.128/30 permit
+98.139.210.132/31 permit
+98.139.210.138/31 permit
+98.139.210.140/30 permit
+98.139.210.148/30 permit
+98.139.210.152/31 permit
+98.139.210.170/31 permit
+98.139.210.172/30 permit
+98.139.210.180/30 permit
+98.139.210.184/31 permit
+98.139.210.190/31 permit
+98.139.210.192/30 permit
+98.139.210.196/31 permit
+98.139.210.202/31 permit
+98.139.210.204/30 permit
+98.139.211.0/24 permit
+98.139.211.160/30 permit
+98.139.211.192/28 permit
+98.139.212.0/23 permit
+98.139.212.160/28 permit
+98.139.212.176/29 permit
+98.139.212.184/30 permit
+98.139.212.188/31 permit
+98.139.212.192/27 permit
+98.139.212.224/28 permit
+98.139.212.240/29 permit
+98.139.212.248/30 permit
+98.139.213.8/31 permit
+98.139.213.10/31 permit
+98.139.213.12/30 permit
+98.139.214.155 permit
+98.139.214.156/30 permit
+98.139.214.221 permit
+98.139.215.0/24 permit
+98.139.215.228/31 permit
+98.139.215.230 permit
+98.139.215.248/30 permit
+98.139.215.252/31 permit
+98.139.215.254 permit
+98.139.218.53 permit
+98.139.218.61 permit
+98.139.218.63 permit
+98.139.219.128 permit
+98.139.219.138 permit
+98.139.219.159 permit
+98.139.219.177 permit
+98.139.219.184 permit
+98.139.219.193 permit
+98.139.219.194 permit
+98.139.219.196 permit
+98.139.219.203 permit
+98.139.219.209 permit
+98.139.219.215 permit
+98.139.219.216/31 permit
+98.139.219.231 permit
+98.139.220.43 permit
+98.139.220.50 permit
+98.139.220.57 permit
+98.139.220.63 permit
+98.139.220.71 permit
+98.139.220.73 permit
+98.139.220.85 permit
+98.139.220.96 permit
+98.139.220.100 permit
+98.139.220.103 permit
+98.139.220.104 permit
+98.139.220.106/31 permit
+98.139.220.110/31 permit
+98.139.220.112/31 permit
+98.139.220.144 permit
+98.139.220.152 permit
+98.139.220.157 permit
+98.139.220.158 permit
+98.139.220.163 permit
+98.139.220.164 permit
+98.139.220.170 permit
+98.139.220.182 permit
+98.139.220.187 permit
+98.139.220.189 permit
+98.139.220.193 permit
+98.139.220.198 permit
+98.139.220.203 permit
+98.139.220.208/31 permit
+98.139.220.212 permit
+98.139.220.214/31 permit
+98.139.220.219 permit
+98.139.220.223 permit
+98.139.220.232 permit
+98.139.220.238 permit
+98.139.220.243 permit
+98.139.220.245 permit
+98.139.220.253 permit
+98.139.221.0/24 permit
+98.139.221.43 permit
+98.139.221.60/30 permit
+98.139.221.156/30 permit
+98.139.221.232/30 permit
+98.139.221.236/31 permit
+98.139.221.250 permit
+98.139.244.0/24 permit
+98.139.244.47 permit
+98.139.244.49 permit
+98.139.244.50/31 permit
+98.139.244.52/30 permit
+98.139.244.57 permit
+98.139.244.58/31 permit
+98.139.244.60/31 permit
+98.139.244.62 permit
+98.139.244.132 permit
+98.139.244.141 permit
+98.139.244.142/31 permit
+98.139.244.144/31 permit
+98.139.244.146 permit
+98.139.244.152 permit
+98.139.244.161 permit
+98.139.244.162/31 permit
+98.139.244.164/31 permit
+98.139.244.166 permit
+98.139.244.172 permit
+98.139.244.181 permit
+98.139.244.182/31 permit
+98.139.244.184/31 permit
+98.139.244.186 permit
+98.139.244.192 permit
+98.139.244.201 permit
+98.139.244.202/31 permit
+98.139.244.204/31 permit
+98.139.244.206 permit
+98.139.244.212 permit
+98.139.244.221 permit
+98.139.244.222/31 permit
+98.139.244.224/31 permit
+98.139.244.226 permit
+98.139.244.232 permit
+98.139.245.176/30 permit
+98.139.245.180/31 permit
+98.139.245.208/30 permit
+98.139.245.212/31 permit
+103.9.8.121 permit
+103.9.8.122 permit
+103.9.8.123 permit
+103.9.96.0/22 permit
+103.13.69.0/24 permit
+103.28.42.0/24 permit
+103.96.20.0/24 permit
+103.96.22.0/24 permit
+103.237.104.0/22 permit
+104.43.243.237 permit
+104.47.0.0/17 permit
+104.130.96.0/28 permit
+104.130.122.0/23 permit
+104.215.148.63 permit
+104.245.209.192/26 permit
+106.10.144.64/27 permit
+106.10.144.100/31 permit
+106.10.144.103 permit
+106.10.144.112/28 permit
+106.10.144.128 permit
+106.10.144.133 permit
+106.10.144.138 permit
+106.10.144.143 permit
+106.10.144.148 permit
+106.10.144.153 permit
+106.10.144.158 permit
+106.10.144.163 permit
+106.10.144.168 permit
+106.10.145.33 permit
+106.10.145.34/31 permit
+106.10.145.160/31 permit
+106.10.145.162 permit
+106.10.145.192/30 permit
+106.10.145.196/31 permit
+106.10.145.224/30 permit
+106.10.145.228/31 permit
+106.10.146.48/30 permit
+106.10.146.52/31 permit
+106.10.146.224/30 permit
+106.10.146.228/31 permit
+106.10.148.0/24 permit
+106.10.148.48/30 permit
+106.10.148.52/31 permit
+106.10.148.68/30 permit
+106.10.148.80/28 permit
+106.10.148.100/30 permit
+106.10.148.124/31 permit
+106.10.148.252/31 permit
+106.10.148.254 permit
+106.10.149.28/31 permit
+106.10.149.30 permit
+106.10.149.160/30 permit
+106.10.149.164/31 permit
+106.10.150.0/23 permit
+106.10.150.23 permit
+106.10.150.24/30 permit
+106.10.150.28/31 permit
+106.10.150.32/30 permit
+106.10.150.36/31 permit
+106.10.150.52/30 permit
+106.10.150.56/31 permit
+106.10.150.72/30 permit
+106.10.150.76/31 permit
+106.10.150.92/30 permit
+106.10.150.96/31 permit
+106.10.150.112/30 permit
+106.10.150.116/31 permit
+106.10.150.132/30 permit
+106.10.150.136/31 permit
+106.10.150.172/30 permit
+106.10.151.15 permit
+106.10.151.16/31 permit
+106.10.151.18 permit
+106.10.151.19 permit
+106.10.151.20 permit
+106.10.151.21 permit
+106.10.151.22/31 permit
+106.10.151.24/31 permit
+106.10.151.26/31 permit
+106.10.151.28/30 permit
+106.10.151.122/31 permit
+106.10.151.138/31 permit
+106.10.151.154/31 permit
+106.10.151.170/31 permit
+106.10.151.186/31 permit
+106.10.151.202/31 permit
+106.10.151.218/31 permit
+106.10.151.234/31 permit
+106.10.151.239 permit
+106.10.151.250/31 permit
+106.10.151.252/31 permit
+106.10.151.254 permit
+106.10.167.0/24 permit
+106.10.167.72 permit
+106.10.167.128/27 permit
+106.10.167.160/28 permit
+106.10.167.176/31 permit
+106.10.167.244/31 permit
+106.10.167.246 permit
+106.10.169.16/30 permit
+106.10.169.20 permit
+106.10.169.21 permit
+106.10.169.208/31 permit
+106.10.169.210/31 permit
+106.10.169.233 permit
+106.10.169.234/31 permit
+106.10.169.236/31 permit
+106.10.169.238 permit
+106.10.169.253 permit
+106.10.169.254 permit
+106.10.174.118/31 permit
+106.10.174.120/30 permit
+106.10.174.154/31 permit
+106.10.174.156/30 permit
+106.10.176.0/24 permit
+106.10.176.32/29 permit
+106.10.176.48 permit
+106.10.176.112 permit
+106.10.176.128/29 permit
+106.10.176.136 permit
+106.10.176.255 permit
+106.10.177.0 permit
+106.10.177.108/30 permit
+106.10.177.128/30 permit
+106.10.177.184/30 permit
+106.10.177.188/31 permit
+106.10.177.217 permit
+106.10.177.218/31 permit
+106.10.177.220/31 permit
+106.10.177.222 permit
+106.10.196.43 permit
+106.10.196.44/30 permit
+106.10.196.48 permit
+106.10.240.0/22 permit
+106.10.240.0/24 permit
+106.10.241.0/24 permit
+106.10.242.0/24 permit
+106.10.243.0/24 permit
+106.10.244.0/24 permit
+106.50.16.0/28 permit
+108.174.0.0/24 permit
+108.174.0.215 permit
+108.174.3.0/24 permit
+108.174.3.215 permit
+108.174.6.0/24 permit
+108.174.6.215 permit
+108.175.18.45 permit
+108.175.30.45 permit
+108.177.8.0/21 permit
+108.177.96.0/19 permit
+108.178.6.0/24 permit
+109.237.142.0/24 permit
+111.221.23.128/25 permit
+111.221.26.0/27 permit
+111.221.66.0/25 permit
+111.221.69.128/25 permit
+111.221.112.0/21 permit
+116.214.12.0/24 permit
+116.214.12.47 permit
+116.214.12.48/31 permit
+116.214.12.56/31 permit
+116.214.12.58 permit
+116.214.12.73 permit
+116.214.12.74/31 permit
+116.214.12.76/31 permit
+116.214.12.78 permit
+116.214.12.93 permit
+116.214.12.94/31 permit
+116.214.12.96/31 permit
+116.214.12.98 permit
+117.120.16.0/21 permit
+119.42.242.52/31 permit
+119.42.242.156 permit
+124.47.150.0/24 permit
+124.47.189.0/24 permit
+124.108.96.0/24 permit
+124.108.96.24/31 permit
+124.108.96.28/31 permit
+124.108.96.70/31 permit
+124.108.96.72/31 permit
+128.127.70.0/26 permit
+129.41.77.70 permit
+129.41.169.249 permit
+130.61.9.72 permit
+130.61.68.235 permit
+130.211.0.0/22 permit
+130.248.172.0/24 permit
+130.248.173.0/24 permit
+131.107.0.0/16 permit
+131.253.30.0/24 permit
+131.253.121.0/26 permit
+131.253.121.20 permit
+131.253.121.52 permit
+132.145.11.129 permit
+132.145.13.209 permit
+134.170.27.8 permit
+134.170.113.0/26 permit
+134.170.141.64/26 permit
+134.170.143.0/24 permit
+134.170.174.0/24 permit
+135.84.80.192/26 permit
+135.84.82.0/24 permit
+135.84.216.0/22 permit
+136.143.182.0/23 permit
+136.143.188.0/23 permit
+136.147.128.0/20 permit
+136.147.135.0/24 permit
+136.147.176.0/20 permit
+136.147.176.0/24 permit
+136.147.182.0/24 permit
+139.60.152.0/22 permit
+139.178.64.159 permit
+139.178.64.195 permit
+139.180.17.0/24 permit
+141.193.32.0/23 permit
+146.20.112.0/26 permit
+146.20.113.0/24 permit
+146.20.191.0/24 permit
+146.88.28.0/24 permit
+146.101.78.0/24 permit
+147.75.65.173 permit
+147.75.65.174 permit
+147.75.98.190 permit
+147.160.158.0/24 permit
+147.243.1.47 permit
+147.243.1.48 permit
+147.243.1.153 permit
+147.243.128.24 permit
+147.243.128.26 permit
+148.105.0.14 permit
+148.105.8.0/21 permit
+149.72.0.0/16 permit
+151.101.1.140 permit
+151.101.65.140 permit
+151.101.129.140 permit
+151.101.193.140 permit
+157.55.0.192/26 permit
+157.55.1.128/26 permit
+157.55.2.0/25 permit
+157.55.9.128/25 permit
+157.55.11.0/25 permit
+157.55.49.0/25 permit
+157.55.61.0/24 permit
+157.55.157.128/25 permit
+157.55.225.0/25 permit
+157.56.24.0/25 permit
+157.56.120.128/26 permit
+157.56.232.0/21 permit
+157.56.240.0/20 permit
+157.56.248.0/21 permit
+157.58.196.96/29 permit
+157.58.249.3 permit
+157.151.208.65 permit
+158.247.16.0/20 permit
+159.135.224.0/20 permit
+161.38.192.0/22 permit
+161.38.196.0/22 permit
+161.71.32.0/21 permit
+162.208.119.181 permit
+162.247.216.0/22 permit
+162.248.184.121 permit
+162.248.184.122 permit
+162.248.185.121 permit
+162.248.185.122 permit
+162.248.186.121 permit
+162.248.186.122 permit
+163.47.180.0/22 permit
+163.114.130.16 permit
+166.78.68.0/22 permit
+166.78.68.221 permit
+166.78.69.146 permit
+166.78.69.169 permit
+166.78.69.170 permit
+166.78.71.131 permit
+167.89.0.0/17 permit
+167.89.2.4 permit
+167.89.22.44 permit
+167.89.25.84 permit
+167.89.31.192/29 permit
+167.89.32.5 permit
+167.89.32.50 permit
+167.89.46.159 permit
+167.89.46.185 permit
+167.89.60.95 permit
+167.89.62.118 permit
+167.89.64.9 permit
+167.89.65.0 permit
+167.89.65.53 permit
+167.89.65.100 permit
+167.89.74.233 permit
+167.89.75.33 permit
+167.89.75.126 permit
+167.89.75.136 permit
+167.89.75.164 permit
+167.89.101.2 permit
+167.89.101.192/28 permit
+167.89.107.125 permit
+167.89.107.127 permit
+167.89.107.129 permit
+167.89.107.136 permit
+167.216.129.170 permit
+167.216.129.182/31 permit
+167.216.129.184/29 permit
+167.216.129.192/29 permit
+167.216.129.200 permit
+167.216.129.205 permit
+167.216.129.206/31 permit
+167.216.129.208/31 permit
+167.216.129.210 permit
+167.220.67.232/29 permit
+167.220.67.238 permit
+168.245.0.0/17 permit
+172.217.0.0/19 permit
+172.217.32.0/20 permit
+172.217.128.0/19 permit
+172.217.160.0/20 permit
+172.217.192.0/19 permit
+172.253.56.0/21 permit
+172.253.112.0/20 permit
+173.0.84.224/27 permit
+173.0.94.244/30 permit
+173.193.132.134/31 permit
+173.193.210.32/27 permit
+173.194.0.0/16 permit
+173.203.79.182 permit
+173.203.81.39 permit
+173.224.160.128/25 permit
+173.224.160.188 permit
+173.224.161.128/25 permit
+173.228.155.0/24 permit
+173.236.20.0/24 permit
+174.36.84.8/29 permit
+174.36.84.16/29 permit
+174.36.84.32/29 permit
+174.36.84.144/29 permit
+174.36.84.240/29 permit
+174.36.85.248/30 permit
+174.36.114.128/30 permit
+174.36.114.140/30 permit
+174.36.114.148/30 permit
+174.36.114.152/29 permit
+174.37.67.28/30 permit
+174.37.226.64/27 permit
+174.129.194.241 permit
+174.129.203.189 permit
+174.137.46.0/24 permit
+176.32.105.0/24 permit
+176.32.127.0/24 permit
+178.236.10.128/26 permit
+180.189.28.0/24 permit
+182.50.76.0/22 permit
+182.50.78.64/28 permit
+184.173.105.0/24 permit
+184.173.153.0/24 permit
+185.4.120.0/24 permit
+185.4.122.0/24 permit
+185.12.80.0/22 permit
+185.28.196.0/22 permit
+185.58.84.0/24 permit
+185.58.87.0/24 permit
+185.72.128.75 permit
+185.72.128.76 permit
+185.80.93.204 permit
+185.80.93.227 permit
+185.80.95.31 permit
+185.90.20.0/22 permit
+185.189.236.0/22 permit
+185.211.120.0/22 permit
+185.250.236.0/22 permit
+188.125.68.132 permit
+188.125.68.152/31 permit
+188.125.68.156 permit
+188.125.68.163 permit
+188.125.68.172/31 permit
+188.125.68.176 permit
+188.125.68.179 permit
+188.125.68.184 permit
+188.125.68.186 permit
+188.125.68.192 permit
+188.125.69.0/24 permit
+188.125.69.105 permit
+188.125.69.110 permit
+188.125.69.112 permit
+188.125.69.120 permit
+188.125.69.126 permit
+188.125.69.131 permit
+188.125.69.132/31 permit
+188.125.69.137 permit
+188.125.69.139 permit
+188.125.69.144/30 permit
+188.125.69.148/31 permit
+188.125.83.88/30 permit
+188.125.83.92/31 permit
+188.125.83.96/30 permit
+188.125.83.100/31 permit
+188.125.83.116/30 permit
+188.125.83.120/31 permit
+188.125.83.140/30 permit
+188.125.83.144/31 permit
+188.125.83.160/30 permit
+188.125.83.164/31 permit
+188.125.84.32/30 permit
+188.125.84.36 permit
+188.125.84.122/31 permit
+188.125.84.124/30 permit
+188.125.84.244/30 permit
+188.125.84.248/31 permit
+188.125.85.116/30 permit
+188.125.85.120/31 permit
+188.125.85.130/31 permit
+188.125.85.132/30 permit
+188.125.85.202/31 permit
+188.125.85.204/31 permit
+188.125.85.206 permit
+188.125.85.233 permit
+188.125.85.234/31 permit
+188.125.85.236/31 permit
+188.125.85.238 permit
+188.172.128.0/20 permit
+192.0.64.0/18 permit
+192.28.128.0/18 permit
+192.30.252.0/22 permit
+192.64.236.0/24 permit
+192.64.237.0/24 permit
+192.64.238.0/24 permit
+192.92.97.0/24 permit
+192.161.144.0/20 permit
+192.162.87.0/24 permit
+192.237.158.0/23 permit
+192.237.159.42 permit
+192.237.159.43 permit
+192.254.112.0/20 permit
+192.254.112.60 permit
+192.254.112.98/31 permit
+192.254.113.10 permit
+192.254.113.101 permit
+192.254.114.176 permit
+192.254.115.72 permit
+192.254.118.63 permit
+192.254.127.96/27 permit
+193.109.254.0/23 permit
+194.64.234.128/27 permit
+194.64.234.129 permit
+194.106.220.0/23 permit
+194.113.24.0/22 permit
+194.154.193.192/27 permit
+195.54.172.0/23 permit
+195.130.217.0/24 permit
+195.245.230.0/23 permit
+198.2.128.0/18 permit
+198.2.128.0/24 permit
+198.2.132.0/22 permit
+198.2.136.0/23 permit
+198.2.177.0/24 permit
+198.2.178.0/24 permit
+198.2.179.0/24 permit
+198.2.180.0/24 permit
+198.2.186.0/23 permit
+198.21.0.0/21 permit
+198.21.3.166 permit
+198.21.4.224 permit
+198.37.144.0/20 permit
+198.37.145.250 permit
+198.37.146.118/31 permit
+198.37.149.128 permit
+198.37.151.26 permit
+198.61.254.0/23 permit
+198.61.254.231 permit
+198.178.234.57 permit
+198.245.80.0/20 permit
+198.245.81.0/24 permit
+199.15.176.173 permit
+199.15.212.0/22 permit
+199.15.213.187 permit
+199.15.226.37 permit
+199.16.156.0/22 permit
+199.33.145.1 permit
+199.33.145.32 permit
+199.59.148.0/22 permit
+199.101.161.130 permit
+199.101.162.0/25 permit
+199.122.120.0/21 permit
+199.122.123.0/24 permit
+199.127.232.0/22 permit
+199.201.64.23 permit
+199.201.65.23 permit
+199.255.192.0/22 permit
+202.129.242.0/23 permit
+202.165.102.47 permit
+202.177.148.100 permit
+202.177.148.110 permit
+203.32.4.25 permit
+203.55.21.0/24 permit
+203.81.17.0/24 permit
+203.122.32.250 permit
+203.145.57.160/27 permit
+203.188.194.32 permit
+203.188.194.151 permit
+203.188.194.203 permit
+203.188.194.204 permit
+203.188.194.213 permit
+203.188.194.251 permit
+203.188.195.240/30 permit
+203.188.195.244/31 permit
+203.188.197.0/24 permit
+203.188.197.193 permit
+203.188.197.194/31 permit
+203.188.197.196/30 permit
+203.188.197.209 permit
+203.188.197.210/31 permit
+203.188.197.212/30 permit
+203.188.197.216/29 permit
+203.188.197.232/29 permit
+203.188.197.240/29 permit
+203.188.200.0/24 permit
+203.188.200.56/31 permit
+203.188.200.58 permit
+203.188.200.60/30 permit
+203.188.200.83 permit
+203.188.200.100/31 permit
+203.188.200.102 permit
+203.188.200.108/31 permit
+203.188.200.160/31 permit
+203.188.200.208/30 permit
+203.188.200.212/31 permit
+203.188.201.12/30 permit
+203.209.230.75 permit
+203.209.230.76/31 permit
+204.2.193.0/29 permit
+204.11.168.0/21 permit
+204.13.11.48/29 permit
+204.13.11.48/30 permit
+204.14.232.0/21 permit
+204.14.232.64/28 permit
+204.14.234.64/28 permit
+204.29.186.0/23 permit
+204.75.142.0/24 permit
+204.79.197.212 permit
+204.92.114.187 permit
+204.92.114.203 permit
+204.92.114.204/31 permit
+204.141.32.0/23 permit
+204.141.42.0/23 permit
+204.153.120.0/23 permit
+205.139.110.0/24 permit
+205.139.111.0/24 permit
+205.201.128.0/20 permit
+205.201.131.128/25 permit
+205.201.134.128/25 permit
+205.201.136.0/23 permit
+205.201.137.229 permit
+205.201.139.0/24 permit
+205.207.104.0/22 permit
+205.207.104.108 permit
+205.251.233.32 permit
+205.251.233.36 permit
+206.25.247.143 permit
+206.25.247.155 permit
+206.165.246.80/29 permit
+206.191.224.0/19 permit
+206.246.157.1 permit
+207.46.4.128/25 permit
+207.46.22.35 permit
+207.46.50.72 permit
+207.46.50.82 permit
+207.46.50.192/26 permit
+207.46.50.224 permit
+207.46.52.71 permit
+207.46.52.79 permit
+207.46.58.128/25 permit
+207.46.116.128/29 permit
+207.46.117.0/24 permit
+207.46.132.128/27 permit
+207.46.198.0/25 permit
+207.46.200.0/27 permit
+207.67.38.0/24 permit
+207.67.98.192/27 permit
+207.68.176.0/26 permit
+207.68.176.96/27 permit
+207.82.80.0/24 permit
+207.126.144.0/20 permit
+207.171.160.0/19 permit
+207.211.30.0/24 permit
+207.211.31.0/25 permit
+207.211.41.113 permit
+207.218.90.0/24 permit
+207.250.68.0/24 permit
+208.40.232.70 permit
+208.43.21.28/30 permit
+208.43.21.64/29 permit
+208.43.21.72/30 permit
+208.43.239.136/30 permit
+208.46.212.208/31 permit
+208.46.212.210 permit
+208.64.132.0/22 permit
+208.71.40.0/24 permit
+208.71.40.63 permit
+208.71.40.64/31 permit
+208.71.40.174/31 permit
+208.71.40.185 permit
+208.71.40.186/31 permit
+208.71.40.202/31 permit
+208.71.40.204/31 permit
+208.71.40.219 permit
+208.71.41.21 permit
+208.71.41.22/31 permit
+208.71.41.24/31 permit
+208.71.41.42/31 permit
+208.71.41.64/30 permit
+208.71.41.68/31 permit
+208.71.41.171 permit
+208.71.41.172/31 permit
+208.71.41.188/30 permit
+208.71.41.192/31 permit
+208.71.42.0/24 permit
+208.71.42.190/31 permit
+208.71.42.192/28 permit
+208.71.42.208/30 permit
+208.71.42.212/31 permit
+208.71.42.214 permit
+208.72.249.240/29 permit
+208.74.204.0/22 permit
+208.74.204.9 permit
+208.75.120.0/22 permit
+208.75.122.246 permit
+208.82.236.96/28 permit
+208.82.237.96/28 permit
+208.82.238.96/28 permit
+208.85.50.137 permit
+208.117.48.0/20 permit
+208.185.229.45 permit
+208.201.241.163 permit
+209.43.22.0/28 permit
+209.46.117.168 permit
+209.46.117.179 permit
+209.61.151.0/24 permit
+209.67.98.46 permit
+209.67.98.59 permit
+209.85.128.0/17 permit
+212.4.136.0/26 permit
+212.25.240.75 permit
+212.25.240.76 permit
+212.25.240.83 permit
+212.25.240.84 permit
+212.82.96.0/24 permit
+212.82.96.32/27 permit
+212.82.96.64/29 permit
+212.82.98.0/24 permit
+212.82.98.32/29 permit
+212.82.98.64/27 permit
+212.82.98.96/30 permit
+212.82.98.100/30 permit
+212.82.98.104/29 permit
+212.82.98.112/29 permit
+212.82.98.120/30 permit
+212.82.98.144/28 permit
+212.82.105.240/30 permit
+212.82.108.112/29 permit
+212.82.108.120/30 permit
+212.82.108.124/31 permit
+212.82.108.126 permit
+212.82.108.132/30 permit
+212.82.108.136/30 permit
+212.82.108.208/30 permit
+212.82.108.212/31 permit
+212.82.108.224/30 permit
+212.82.108.232/29 permit
+212.82.108.240/29 permit
+212.82.108.248/30 permit
+212.82.108.252/31 permit
+212.82.108.254 permit
+212.82.109.128/31 permit
+212.82.109.132 permit
+212.82.111.131 permit
+212.82.111.133 permit
+212.82.111.135 permit
+212.82.111.137 permit
+212.82.111.139 permit
+212.82.111.141 permit
+212.82.111.225 permit
+212.82.111.226/31 permit
+212.82.111.228/31 permit
+212.82.111.230 permit
+212.123.28.40 permit
+212.227.15.0/24 permit
+212.227.15.0/25 permit
+212.227.17.0/27 permit
+212.227.126.128/25 permit
+213.165.64.0/23 permit
+213.167.75.0/24 permit
+213.167.81.0/24 permit
+213.199.128.139 permit
+213.199.128.145 permit
+213.199.138.181 permit
+213.199.138.191 permit
+213.199.161.128/27 permit
+213.199.177.0/26 permit
+216.17.150.242 permit
+216.17.150.251 permit
+216.24.224.0/20 permit
+216.39.60.0/23 permit
+216.39.60.154/31 permit
+216.39.60.156/30 permit
+216.39.60.160/30 permit
+216.39.60.164 permit
+216.39.60.192/28 permit
+216.39.60.208/29 permit
+216.39.60.216 permit
+216.39.60.218 permit
+216.39.60.230/31 permit
+216.39.60.232/29 permit
+216.39.60.240/29 permit
+216.39.60.248/30 permit
+216.39.60.252/31 permit
+216.39.60.254 permit
+216.39.61.170 permit
+216.39.61.175 permit
+216.39.61.238/31 permit
+216.39.62.0/24 permit
+216.39.62.32/28 permit
+216.39.62.48/29 permit
+216.39.62.56/30 permit
+216.39.62.60/31 permit
+216.39.62.136/29 permit
+216.39.62.144/31 permit
+216.46.168.197 permit
+216.46.168.222 permit
+216.52.185.88/29 permit
+216.58.192.0/19 permit
+216.66.217.240/29 permit
+216.71.96.0/22 permit
+216.71.152.175 permit
+216.71.152.207 permit
+216.71.154.29 permit
+216.71.155.88 permit
+216.71.155.89 permit
+216.74.162.13 permit
+216.74.162.14 permit
+216.82.240.0/20 permit
+216.98.158.0/24 permit
+216.99.5.67 permit
+216.99.5.68 permit
+216.109.114.0/24 permit
+216.109.114.32/27 permit
+216.109.114.64/29 permit
+216.113.160.0/24 permit
+216.113.172.0/25 permit
+216.113.175.0/24 permit
+216.128.126.97 permit
+216.136.162.65 permit
+216.136.162.120/29 permit
+216.136.168.80/28 permit
+216.198.0.0/18 permit
+216.203.30.55 permit
+216.203.33.178/31 permit
+216.205.24.0/24 permit
+216.239.32.0/19 permit
+217.72.192.64/26 permit
+217.72.192.248/29 permit
+217.72.207.0/27 permit
+217.77.141.52 permit
+217.77.141.59 permit
+217.175.193.0/24 permit
+217.175.194.0/23 permit
+217.175.196.0/24 permit
+2001:4860:4000::/36 permit
+2404:6800:4000::/36 permit
+2607:f8b0:4000::/36 permit
+2620:109:c003:104::215 permit
+2620:109:c003:104::/64 permit
+2620:109:c006:104::215 permit
+2620:109:c006:104::/64 permit
+2620:109:c00d:104::/64 permit
+2620:10d:c091:450::16 permit
+2620:119:50c0:207::215 permit
+2620:119:50c0:207::/64 permit
+2800:3f0:4000::/36 permit
+194.25.134.0/24 permit # t-online.de
diff --git a/mailcow/src/mailcow-dockerized/data/conf/postfix/smtp_dsn_filter b/mailcow/src/mailcow-dockerized/data/conf/postfix/smtp_dsn_filter
new file mode 100644
index 0000000..2fb5101
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/postfix/smtp_dsn_filter
@@ -0,0 +1,6 @@
+/^4(\.\d+\.\d+ TLS is required, but host \S+ refused to start TLS: .+)/
+ 5$1
+/^4(\.\d+\.\d+ TLS is required, but was not offered by host .+)/
+ 5$1
+/^4.7.5(.*)/
+ 5.7.5$1
diff --git a/mailcow/src/mailcow-dockerized/data/conf/rspamd/custom/bad_asn.map b/mailcow/src/mailcow-dockerized/data/conf/rspamd/custom/bad_asn.map
new file mode 100644
index 0000000..fb42628
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/rspamd/custom/bad_asn.map
@@ -0,0 +1,30 @@
+# High spam networks, disabled by default
+# ASN SCORE DESC
+# Remove comment to enable score
+#201942 5 #Soltia Consulting SL - ipinfo.io
+#16276 2 #OVH
+#12876 2 #ONLINE S.A.S
+#31034 5 #ARUBA-ASN, IT
+#12874 5 #FASTWEB, IT
+#30823 3 #PKV spam
+#42831 5 #UK Dedicated Servers Ltd
+#29119 5 #Aire Networks del Mediterraneo S.L.U.
+#13335 5 #Cloudflare
+#28753 5 #Leaseweb
+#61272 5 #Informacines sistemos ir technologijos
+#53755 5 #Input Output Flood LLC
+#29422 5 #FICIX Helsinki
+#62255 4 #Asmunda New Media Ltd
+#14061 4 #Digitalocean
+#55293 4 #A2 Hosting
+#63018 4 #US Dedicated
+#197518 2 #RACKMARKT
+#44493 2
+#46606 2
+#49505 2
+#21100 2
+#197695 2
+#198068 2
+#43146 2
+#49100 4
+#39364 4
diff --git a/mailcow/src/mailcow-dockerized/data/conf/rspamd/custom/bad_languages.map b/mailcow/src/mailcow-dockerized/data/conf/rspamd/custom/bad_languages.map
new file mode 100644
index 0000000..cf9ce3e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/rspamd/custom/bad_languages.map
@@ -0,0 +1 @@
+# Regex! /de/ will also match /de_at/ etc.
diff --git a/mailcow/src/mailcow-dockerized/data/conf/rspamd/custom/bad_words.map b/mailcow/src/mailcow-dockerized/data/conf/rspamd/custom/bad_words.map
new file mode 100644
index 0000000..0d9af8b
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/rspamd/custom/bad_words.map
@@ -0,0 +1,29 @@
+/\serotic\s/i
+/\serection\s/i
+/\ssexy\s/i
+/\sass\s/i
+/\sviagra\s/i
+/\stits\s/i
+/\stitty\s/i
+/\stitties\s/i
+/\scum\s/i
+/\ssperm\s/i
+/\sslut\s/i
+/\sporn\s/i
+/\scock\s/i
+/\spharma\s/i
+/\spharmacy\s/i
+/\sseo\s/i
+/\sjackpot\s/i
+/\slottery\s/i
+/bitcoin/i
+/trojaner/i
+/malware/i
+/\sscooter\s/i
+/testost/i
+/web\sdevelopment/i
+/\slottery\s/i
+/\ssex\s/i
+/\svagina\s/i
+/\spenis\s/i
+/\smarketing\s/i
\ No newline at end of file
diff --git a/mailcow/src/mailcow-dockerized/data/conf/rspamd/custom/bad_words_de.map b/mailcow/src/mailcow-dockerized/data/conf/rspamd/custom/bad_words_de.map
new file mode 100644
index 0000000..ccdd586
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/rspamd/custom/bad_words_de.map
@@ -0,0 +1,17 @@
+/\slotto\s/i
+/pillenversand/i
+/\skredithilfe\s/i
+/\skapital\s/i
+/\skrankenversicherung\s/i
+/pädophil/i
+/paedophil/i
+/freiberufler/i
+/unternehmer/i
+/masturbieren/i
+/\sescooter\s/i
+/\se-scooter\s/i
+/testost/i
+/\spotenz\s/i
+/potenzmittel/i
+/rezeptfrei/i
+/apotheke/i
\ No newline at end of file
diff --git a/mailcow/src/mailcow-dockerized/data/conf/rspamd/custom/bulk_header.map b/mailcow/src/mailcow-dockerized/data/conf/rspamd/custom/bulk_header.map
new file mode 100644
index 0000000..303954e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/rspamd/custom/bulk_header.map
@@ -0,0 +1,18 @@
+/X-EMV-Platform; .*/i
+/.*nur-1-click*/i
+/.*episerver.*/i
+/.*supergewinne.*/i
+/List-Unsubscribe.*nbps\.eu/i
+/X-Mailer: AWeber.*/i
+/.*regiofinder.*/i
+/.*EmailSocket.*/i
+/List-Unsubscribe:.*respread.*/i
+/.*greenflamingo.*/i
+/.*senderemailglobal.*/i
+/.*promio\.net.*/i
+/.*promio\.de.*/i
+/.*mailer-service\.com.*/i
+/.*mailer-service\.de.*/i
+/.*dynamic-lht.*/i
+/.*light-house-traffic.*/i
+/.*newsletterplus.*/i
diff --git a/mailcow/src/mailcow-dockerized/data/conf/rspamd/custom/fishy_tlds.map b/mailcow/src/mailcow-dockerized/data/conf/rspamd/custom/fishy_tlds.map
new file mode 100644
index 0000000..1b8b2b0
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/rspamd/custom/fishy_tlds.map
@@ -0,0 +1,65 @@
+/.+\.accountant$/i
+/.+\.art$/i
+/.+\.asia$/i
+/.+\.bid$/i
+/.+\.biz$/i
+/.+\.care$/i
+/.+\.cf$/i
+/.+\.click$/i
+/.+\.cloud$/i
+/.+\.co$/i
+/.+\.construction$/i
+/.+\.country$/i
+/.+\.cricket$/i
+/.+\.date$/i
+/.+\.desi$/i
+/.+\.download$/i
+/.+\.estate$/i
+/.+\.faith$/i
+/.+\.fit$/i
+/.+\.flights$/i
+/.+\.ga$/i
+/.+\.gdn$/i
+/.+\.gq$/i
+/.+\.guru$/i
+/.+\.icu$/i
+/.+\.id$/i
+/.+\.info$/i
+/.+\.in.net$/i
+/.+\.ir$/i
+/.+\.jetzt$/i
+/.+\.kim$/i
+/.+\.life$/i
+/.+\.link$/i
+/.+\.loan$/i
+/.+\.mk$/i
+/.+\.ml$/i
+/.+\.ninja$/i
+/.+\.online$/i
+/.+\.ooo$/i
+/.+\.party$/i
+/.+\.pro$/i
+/.+\.ps$/i
+/.+\.pw$/i
+/.+\.racing$/i
+/.+\.review$/i
+/.+\.rocks$/i
+/.+\.ryukyu$/i
+/.+\.science$/i
+/.+\.site$/i
+/.+\.space$/i
+/.+\.stream$/i
+/.+\.sucks$/i
+/.+\.tk$/i
+/.+\.top$/i
+/.+\.topica\.com$/i
+/.+\.town$/i
+/.+\.trade$/i
+/.+\.uno$/i
+/.+\.vip$/i
+/.+\.webcam$/i
+/.+\.website$/i
+/.+\.win$/i
+/.+\.work$/i
+/.+\.world$/i
+/.+\.xyz$/i
diff --git a/mailcow/src/mailcow-dockerized/data/conf/rspamd/custom/global_mime_from_blacklist.map b/mailcow/src/mailcow-dockerized/data/conf/rspamd/custom/global_mime_from_blacklist.map
new file mode 100644
index 0000000..3c87288
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/rspamd/custom/global_mime_from_blacklist.map
@@ -0,0 +1 @@
+# /.+example\.com/i
diff --git a/mailcow/src/mailcow-dockerized/data/conf/rspamd/custom/global_mime_from_whitelist.map b/mailcow/src/mailcow-dockerized/data/conf/rspamd/custom/global_mime_from_whitelist.map
new file mode 100644
index 0000000..3c87288
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/rspamd/custom/global_mime_from_whitelist.map
@@ -0,0 +1 @@
+# /.+example\.com/i
diff --git a/mailcow/src/mailcow-dockerized/data/conf/rspamd/custom/global_rcpt_blacklist.map b/mailcow/src/mailcow-dockerized/data/conf/rspamd/custom/global_rcpt_blacklist.map
new file mode 100644
index 0000000..3c87288
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/rspamd/custom/global_rcpt_blacklist.map
@@ -0,0 +1 @@
+# /.+example\.com/i
diff --git a/mailcow/src/mailcow-dockerized/data/conf/rspamd/custom/global_rcpt_whitelist.map b/mailcow/src/mailcow-dockerized/data/conf/rspamd/custom/global_rcpt_whitelist.map
new file mode 100644
index 0000000..3c87288
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/rspamd/custom/global_rcpt_whitelist.map
@@ -0,0 +1 @@
+# /.+example\.com/i
diff --git a/mailcow/src/mailcow-dockerized/data/conf/rspamd/custom/global_smtp_from_blacklist.map b/mailcow/src/mailcow-dockerized/data/conf/rspamd/custom/global_smtp_from_blacklist.map
new file mode 100644
index 0000000..3c87288
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/rspamd/custom/global_smtp_from_blacklist.map
@@ -0,0 +1 @@
+# /.+example\.com/i
diff --git a/mailcow/src/mailcow-dockerized/data/conf/rspamd/custom/global_smtp_from_whitelist.map b/mailcow/src/mailcow-dockerized/data/conf/rspamd/custom/global_smtp_from_whitelist.map
new file mode 100644
index 0000000..3c87288
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/rspamd/custom/global_smtp_from_whitelist.map
@@ -0,0 +1 @@
+# /.+example\.com/i
diff --git a/mailcow/src/mailcow-dockerized/data/conf/rspamd/custom/ip_wl.map b/mailcow/src/mailcow-dockerized/data/conf/rspamd/custom/ip_wl.map
new file mode 100644
index 0000000..c8bb552
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/rspamd/custom/ip_wl.map
@@ -0,0 +1,4 @@
+# IP whitelist
+# 127.0.0.1
+# 1.2.3.4
+# ...
diff --git a/mailcow/src/mailcow-dockerized/data/conf/rspamd/custom/monitoring_nolog.map b/mailcow/src/mailcow-dockerized/data/conf/rspamd/custom/monitoring_nolog.map
new file mode 100644
index 0000000..0e00de7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/rspamd/custom/monitoring_nolog.map
@@ -0,0 +1,7 @@
+# Skip logging for these addresses
+/monitoring-system@everycloudtech\.us/i
+/monitor@tools\.mailflowmonitoring\.com/i
+/watchdog@localhost/i
+/supertool@mxtoolbox\.com/i
+/test@mxtoolboxsmtpdiag\.com/i
+/open-relay-check@mailcow\.email/i
diff --git a/mailcow/src/mailcow-dockerized/data/conf/rspamd/dynmaps/aliasexp.php b/mailcow/src/mailcow-dockerized/data/conf/rspamd/dynmaps/aliasexp.php
new file mode 100644
index 0000000..947a024
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/rspamd/dynmaps/aliasexp.php
@@ -0,0 +1,174 @@
+<?php
+// File size is limited by Nginx site to 10M
+// To speed things up, we do not include prerequisites
+header('Content-Type: text/plain');
+require_once "vars.inc.php";
+// Do not show errors, we log to using error_log
+ini_set('error_reporting', 0);
+// Init database
+//$dsn = $database_type . ':host=' . $database_host . ';dbname=' . $database_name;
+$dsn = $database_type . ":unix_socket=" . $database_sock . ";dbname=" . $database_name;
+$opt = [
+ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
+ PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
+ PDO::ATTR_EMULATE_PREPARES => false,
+];
+try {
+ $pdo = new PDO($dsn, $database_user, $database_pass, $opt);
+}
+catch (PDOException $e) {
+ error_log("ALIASEXP: " . $e . PHP_EOL);
+ http_response_code(501);
+ exit;
+}
+
+// Init Redis
+$redis = new Redis();
+$redis->connect('redis-mailcow', 6379);
+
+function parse_email($email) {
+ if(!filter_var($email, FILTER_VALIDATE_EMAIL)) return false;
+ $a = strrpos($email, '@');
+ return array('local' => substr($email, 0, $a), 'domain' => substr(substr($email, $a), 1));
+}
+if (!function_exists('getallheaders')) {
+ function getallheaders() {
+ if (!is_array($_SERVER)) {
+ return array();
+ }
+ $headers = array();
+ foreach ($_SERVER as $name => $value) {
+ if (substr($name, 0, 5) == 'HTTP_') {
+ $headers[str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5)))))] = $value;
+ }
+ }
+ return $headers;
+ }
+}
+
+// Read headers
+$headers = getallheaders();
+// Get rcpt
+$rcpt = $headers['Rcpt'];
+// Remove tag
+$rcpt = preg_replace('/^(.*?)\+.*(@.*)$/', '$1$2', $rcpt);
+// Parse email address
+$parsed_rcpt = parse_email($rcpt);
+// Create array of final mailboxes
+$rcpt_final_mailboxes = array();
+
+// Skip if not a mailcow handled domain
+try {
+ if (!$redis->hGet('DOMAIN_MAP', $parsed_rcpt['domain'])) {
+ exit;
+ }
+}
+catch (RedisException $e) {
+ error_log("ALIASEXP: " . $e . PHP_EOL);
+ http_response_code(504);
+ exit;
+}
+
+// Always assume rcpt is not a final mailbox but an alias for a mailbox or further aliases
+//
+// rcpt
+// |
+// mailbox <-- goto ---> alias1, alias2, mailbox2
+// | |
+// mailbox3 |
+// |
+// alias3 ---> mailbox4
+//
+try {
+ $stmt = $pdo->prepare("SELECT `goto` FROM `alias` WHERE `address` = :rcpt AND `active` = '1'");
+ $stmt->execute(array(
+ ':rcpt' => $rcpt
+ ));
+ $gotos = $stmt->fetch(PDO::FETCH_ASSOC)['goto'];
+ if (empty($gotos)) {
+ $stmt = $pdo->prepare("SELECT `goto` FROM `alias` WHERE `address` = :rcpt AND `active` = '1'");
+ $stmt->execute(array(
+ ':rcpt' => '@' . $parsed_rcpt['domain']
+ ));
+ $gotos = $stmt->fetch(PDO::FETCH_ASSOC)['goto'];
+ }
+ if (empty($gotos)) {
+ $stmt = $pdo->prepare("SELECT `target_domain` FROM `alias_domain` WHERE `alias_domain` = :rcpt AND `active` = '1'");
+ $stmt->execute(array(':rcpt' => $parsed_rcpt['domain']));
+ $goto_branch = $stmt->fetch(PDO::FETCH_ASSOC)['target_domain'];
+ if ($goto_branch) {
+ $gotos = $parsed_rcpt['local'] . '@' . $goto_branch;
+ }
+ }
+ $gotos_array = explode(',', $gotos);
+
+ $loop_c = 0;
+
+ while (count($gotos_array) != 0 && $loop_c <= 20) {
+
+ // Loop through all found gotos
+ foreach ($gotos_array as $index => &$goto) {
+ error_log("ALIAS EXPANDER: http pipe: query " . $goto . " as username from mailbox" . PHP_EOL);
+ $stmt = $pdo->prepare("SELECT `username` FROM `mailbox` WHERE `username` = :goto AND (`active`= '1' OR `active`= '2');");
+ $stmt->execute(array(':goto' => $goto));
+ $username = $stmt->fetch(PDO::FETCH_ASSOC)['username'];
+ if (!empty($username)) {
+ error_log("ALIAS EXPANDER: http pipe: mailbox found: " . $username . PHP_EOL);
+ // Current goto is a mailbox, save to rcpt_final_mailboxes if not a duplicate
+ if (!in_array($username, $rcpt_final_mailboxes)) {
+ $rcpt_final_mailboxes[] = $username;
+ }
+ }
+ else {
+ $parsed_goto = parse_email($goto);
+ if (!$redis->hGet('DOMAIN_MAP', $parsed_goto['domain'])) {
+ error_log("ALIAS EXPANDER:" . $goto . " is not a mailcow handled mailbox or alias address" . PHP_EOL);
+ }
+ else {
+ $stmt = $pdo->prepare("SELECT `goto` FROM `alias` WHERE `address` = :goto AND `active` = '1'");
+ $stmt->execute(array(':goto' => $goto));
+ $goto_branch = $stmt->fetch(PDO::FETCH_ASSOC)['goto'];
+ if ($goto_branch) {
+ error_log("ALIAS EXPANDER: http pipe: goto address " . $goto . " is an alias branch for " . $goto_branch . PHP_EOL);
+ $goto_branch_array = explode(',', $goto_branch);
+ } else {
+ $stmt = $pdo->prepare("SELECT `target_domain` FROM `alias_domain` WHERE `alias_domain` = :domain AND `active` AND '1'");
+ $stmt->execute(array(':domain' => $parsed_goto['domain']));
+ $goto_branch = $stmt->fetch(PDO::FETCH_ASSOC)['target_domain'];
+ if ($goto_branch) {
+ error_log("ALIAS EXPANDER: http pipe: goto domain " . $parsed_goto['domain'] . " is a domain alias branch for " . $goto_branch . PHP_EOL);
+ $goto_branch_array = array($parsed_goto['local'] . '@' . $goto_branch);
+ }
+ }
+ }
+ }
+ // goto item was processed, unset
+ unset($gotos_array[$index]);
+ }
+
+ // Merge goto branch array derived from previous loop (if any), filter duplicates and unset goto branch array
+ if (!empty($goto_branch_array)) {
+ $gotos_array = array_unique(array_merge($gotos_array, $goto_branch_array));
+ unset($goto_branch_array);
+ }
+
+ // Reindex array
+ $gotos_array = array_values($gotos_array);
+
+ // Force exit if loop cannot be solved
+ // Postfix does not allow for alias loops, so this should never happen.
+ $loop_c++;
+ error_log("ALIAS EXPANDER: http pipe: goto array count on loop #". $loop_c . " is " . count($gotos_array) . PHP_EOL);
+ }
+}
+catch (PDOException $e) {
+ error_log("ALIAS EXPANDER: " . $e->getMessage() . PHP_EOL);
+ http_response_code(502);
+ exit;
+}
+
+// Does also return the mailbox name if question == answer (query == mailbox)
+if (count($rcpt_final_mailboxes) == 1) {
+ error_log("ALIASEXP: direct alias " . $rcpt . " expanded to " . $rcpt_final_mailboxes[0] . PHP_EOL);
+ echo trim($rcpt_final_mailboxes[0]);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/conf/rspamd/dynmaps/forwardinghosts.php b/mailcow/src/mailcow-dockerized/data/conf/rspamd/dynmaps/forwardinghosts.php
new file mode 100644
index 0000000..10285b7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/rspamd/dynmaps/forwardinghosts.php
@@ -0,0 +1,57 @@
+<?php
+header('Content-Type: text/plain');
+ini_set('error_reporting', 0);
+
+$redis = new Redis();
+$redis->connect('redis-mailcow', 6379);
+
+function in_net($addr, $net) {
+ $net = explode('/', $net);
+ if (count($net) > 1) {
+ $mask = $net[1];
+ }
+ $net = inet_pton($net[0]);
+ $addr = inet_pton($addr);
+ $length = strlen($net); // 4 for IPv4, 16 for IPv6
+ if (strlen($net) != strlen($addr)) {
+ return false;
+ }
+ if (!isset($mask)) {
+ $mask = $length * 8;
+ }
+ $addr_bin = '';
+ $net_bin = '';
+ for ($i = 0; $i < $length; ++$i) {
+ $addr_bin .= str_pad(decbin(ord(substr($addr, $i, $i+1))), 8, '0', STR_PAD_LEFT);
+ $net_bin .= str_pad(decbin(ord(substr($net, $i, $i+1))), 8, '0', STR_PAD_LEFT);
+ }
+ return substr($addr_bin, 0, $mask) == substr($net_bin, 0, $mask);
+}
+
+if (isset($_GET['host'])) {
+ try {
+ foreach ($redis->hGetAll('WHITELISTED_FWD_HOST') as $host => $source) {
+ if (in_net($_GET['host'], $host)) {
+ echo '200 PERMIT';
+ exit;
+ }
+ }
+ echo '200 DUNNO';
+ }
+ catch (RedisException $e) {
+ echo '200 DUNNO';
+ exit;
+ }
+} else {
+ try {
+ echo '240.240.240.240' . PHP_EOL;
+ foreach ($redis->hGetAll('WHITELISTED_FWD_HOST') as $host => $source) {
+ echo $host . PHP_EOL;
+ }
+ }
+ catch (RedisException $e) {
+ echo '240.240.240.240' . PHP_EOL;
+ exit;
+ }
+}
+?>
diff --git a/mailcow/src/mailcow-dockerized/data/conf/rspamd/dynmaps/index.html b/mailcow/src/mailcow-dockerized/data/conf/rspamd/dynmaps/index.html
new file mode 100644
index 0000000..90531a4
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/rspamd/dynmaps/index.html
@@ -0,0 +1,2 @@
+<html>
+</html>
diff --git a/mailcow/src/mailcow-dockerized/data/conf/rspamd/dynmaps/settings.php b/mailcow/src/mailcow-dockerized/data/conf/rspamd/dynmaps/settings.php
new file mode 100644
index 0000000..0569db9
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/rspamd/dynmaps/settings.php
@@ -0,0 +1,449 @@
+<?php
+/*
+The match section performs AND operation on different matches: for example, if you have from and rcpt in the same rule,
+then the rule matches only when from AND rcpt match. For similar matches, the OR rule applies: if you have multiple rcpt matches,
+then any of these will trigger the rule. If a rule is triggered then no more rules are matched.
+*/
+header('Content-Type: text/plain');
+require_once "vars.inc.php";
+// Getting headers sent by the client.
+ini_set('error_reporting', 0);
+
+//$dsn = $database_type . ':host=' . $database_host . ';dbname=' . $database_name;
+$dsn = $database_type . ":unix_socket=" . $database_sock . ";dbname=" . $database_name;
+$opt = [
+ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
+ PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
+ PDO::ATTR_EMULATE_PREPARES => false,
+];
+try {
+ $pdo = new PDO($dsn, $database_user, $database_pass, $opt);
+ $stmt = $pdo->query("SELECT '1' FROM `filterconf`");
+}
+catch (PDOException $e) {
+ echo 'settings { }';
+ exit;
+}
+
+// Check if db changed and return header
+/*
+$stmt = $pdo->prepare("SELECT MAX(UNIX_TIMESTAMP(UPDATE_TIME)) AS `db_update_time` FROM information_schema.tables
+ WHERE (`TABLE_NAME` = 'filterconf' OR `TABLE_NAME` = 'settingsmap')
+ AND TABLE_SCHEMA = :dbname;");
+$stmt->execute(array(
+ ':dbname' => $database_name
+));
+$db_update_time = $stmt->fetch(PDO::FETCH_ASSOC)['db_update_time'];
+if (empty($db_update_time)) {
+ $db_update_time = 1572048000;
+}
+if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && (strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) == $db_update_time)) {
+ header('Last-Modified: '.gmdate('D, d M Y H:i:s', $db_update_time).' GMT', true, 304);
+ exit;
+} else {
+ header('Last-Modified: '.gmdate('D, d M Y H:i:s', $db_update_time).' GMT', true, 200);
+}
+*/
+
+function parse_email($email) {
+ if (!filter_var($email, FILTER_VALIDATE_EMAIL)) return false;
+ $a = strrpos($email, '@');
+ return array('local' => substr($email, 0, $a), 'domain' => substr($email, $a));
+}
+
+function wl_by_sogo() {
+ global $pdo;
+ $rcpt = array();
+ $stmt = $pdo->query("SELECT DISTINCT(`sogo_folder_info`.`c_path2`) AS `user`, GROUP_CONCAT(`sogo_quick_contact`.`c_mail`) AS `contacts` FROM `sogo_folder_info`
+ INNER JOIN `sogo_quick_contact` ON `sogo_quick_contact`.`c_folder_id` = `sogo_folder_info`.`c_folder_id`
+ GROUP BY `c_path2`");
+ $sogo_contacts = $stmt->fetchAll(PDO::FETCH_ASSOC);
+ while ($row = array_shift($sogo_contacts)) {
+ foreach (explode(',', $row['contacts']) as $contact) {
+ if (!filter_var($contact, FILTER_VALIDATE_EMAIL)) {
+ continue;
+ }
+ // Explicit from, no mime_from, no regex - envelope must match
+ // mailcow white and blacklists also cover mime_from
+ $rcpt[$row['user']][] = str_replace('/', '\/', $contact);
+ }
+ }
+ return $rcpt;
+}
+
+function ucl_rcpts($object, $type) {
+ global $pdo;
+ $rcpt = array();
+ if ($type == 'mailbox') {
+ // Standard aliases
+ $stmt = $pdo->prepare("SELECT `address` FROM `alias`
+ WHERE `goto` = :object_goto
+ AND `address` NOT LIKE '@%'");
+ $stmt->execute(array(
+ ':object_goto' => $object
+ ));
+ $standard_aliases = $stmt->fetchAll(PDO::FETCH_ASSOC);
+ while ($row = array_shift($standard_aliases)) {
+ $local = parse_email($row['address'])['local'];
+ $domain = parse_email($row['address'])['domain'];
+ if (!empty($local) && !empty($domain)) {
+ $rcpt[] = '/^' . str_replace('/', '\/', $local) . '[+].*' . str_replace('/', '\/', $domain) . '$/i';
+ }
+ $rcpt[] = str_replace('/', '\/', $row['address']);
+ }
+ // Aliases by alias domains
+ $stmt = $pdo->prepare("SELECT CONCAT(`local_part`, '@', `alias_domain`.`alias_domain`) AS `alias` FROM `mailbox`
+ LEFT OUTER JOIN `alias_domain` ON `mailbox`.`domain` = `alias_domain`.`target_domain`
+ WHERE `mailbox`.`username` = :object");
+ $stmt->execute(array(
+ ':object' => $object
+ ));
+ $by_domain_aliases = $stmt->fetchAll(PDO::FETCH_ASSOC);
+ array_filter($by_domain_aliases);
+ while ($row = array_shift($by_domain_aliases)) {
+ if (!empty($row['alias'])) {
+ $local = parse_email($row['alias'])['local'];
+ $domain = parse_email($row['alias'])['domain'];
+ if (!empty($local) && !empty($domain)) {
+ $rcpt[] = '/^' . str_replace('/', '\/', $local) . '[+].*' . str_replace('/', '\/', $domain) . '$/i';
+ }
+ $rcpt[] = str_replace('/', '\/', $row['alias']);
+ }
+ }
+ }
+ elseif ($type == 'domain') {
+ // Domain self
+ $rcpt[] = '/.*@' . $object . '/i';
+ $stmt = $pdo->prepare("SELECT `alias_domain` FROM `alias_domain`
+ WHERE `target_domain` = :object");
+ $stmt->execute(array(':object' => $object));
+ $alias_domains = $stmt->fetchAll(PDO::FETCH_ASSOC);
+ array_filter($alias_domains);
+ while ($row = array_shift($alias_domains)) {
+ $rcpt[] = '/.*@' . $row['alias_domain'] . '/i';
+ }
+ }
+ return $rcpt;
+}
+?>
+settings {
+ watchdog {
+ priority = 10;
+ rcpt_mime = "/null@localhost/i";
+ from_mime = "/watchdog@localhost/i";
+ apply "default" {
+ symbols_disabled = ["HISTORY_SAVE", "ARC", "ARC_SIGNED", "DKIM", "DKIM_SIGNED", "CLAM_VIRUS"];
+ want_spam = yes;
+ actions {
+ reject = 9999.0;
+ greylist = 9998.0;
+ "add header" = 9997.0;
+ }
+
+ }
+ }
+<?php
+
+/*
+// Start custom scores for users
+*/
+
+$stmt = $pdo->query("SELECT DISTINCT `object` FROM `filterconf` WHERE `option` = 'highspamlevel' OR `option` = 'lowspamlevel'");
+$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
+
+while ($row = array_shift($rows)) {
+ $username_sane = preg_replace("/[^a-zA-Z0-9]+/", "", $row['object']);
+?>
+ score_<?=$username_sane;?> {
+ priority = 4;
+<?php
+ foreach (ucl_rcpts($row['object'], strpos($row['object'], '@') === FALSE ? 'domain' : 'mailbox') as $rcpt) {
+?>
+ rcpt = <?=json_encode($rcpt, JSON_UNESCAPED_SLASHES);?>;
+<?php
+ }
+ $stmt = $pdo->prepare("SELECT `option`, `value` FROM `filterconf`
+ WHERE (`option` = 'highspamlevel' OR `option` = 'lowspamlevel')
+ AND `object`= :object");
+ $stmt->execute(array(':object' => $row['object']));
+ $spamscore = $stmt->fetchAll(PDO::FETCH_COLUMN|PDO::FETCH_GROUP);
+?>
+ apply "default" {
+ actions {
+ reject = <?=$spamscore['highspamlevel'][0];?>;
+ greylist = <?=$spamscore['lowspamlevel'][0] - 1;?>;
+ "add header" = <?=$spamscore['lowspamlevel'][0];?>;
+ }
+ }
+ }
+<?php
+}
+
+/*
+// Start SOGo contacts whitelist
+// Priority 4, lower than a domain whitelist (5) and lower than a mailbox whitelist (6)
+*/
+
+foreach (wl_by_sogo() as $user => $contacts) {
+ $username_sane = preg_replace("/[^a-zA-Z0-9]+/", "", $user);
+?>
+ whitelist_sogo_<?=$username_sane;?> {
+<?php
+ foreach ($contacts as $contact) {
+?>
+ from = <?=json_encode($contact, JSON_UNESCAPED_SLASHES);?>;
+<?php
+ }
+?>
+ priority = 4;
+<?php
+ foreach (ucl_rcpts($user, 'mailbox') as $rcpt) {
+?>
+ rcpt = <?=json_encode($rcpt, JSON_UNESCAPED_SLASHES);?>;
+<?php
+ }
+?>
+ apply "default" {
+ SOGO_CONTACT = -99.0;
+ }
+ symbols [
+ "SOGO_CONTACT"
+ ]
+ }
+<?php
+}
+
+/*
+// Start whitelist
+*/
+
+$stmt = $pdo->query("SELECT DISTINCT `object` FROM `filterconf` WHERE `option` = 'whitelist_from'");
+$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
+while ($row = array_shift($rows)) {
+ $username_sane = preg_replace("/[^a-zA-Z0-9]+/", "", $row['object']);
+?>
+ whitelist_<?=$username_sane;?> {
+<?php
+ $list_items = array();
+ $stmt = $pdo->prepare("SELECT `value` FROM `filterconf`
+ WHERE `object`= :object
+ AND `option` = 'whitelist_from'");
+ $stmt->execute(array(':object' => $row['object']));
+ $list_items = $stmt->fetchAll(PDO::FETCH_ASSOC);
+ foreach ($list_items as $item) {
+?>
+ from = "/<?='^' . str_replace('\*', '.*', preg_quote($item['value'], '/')) . '$' ;?>/i";
+<?php
+ }
+ if (!filter_var(trim($row['object']), FILTER_VALIDATE_EMAIL)) {
+?>
+ priority = 5;
+<?php
+ foreach (ucl_rcpts($row['object'], strpos($row['object'], '@') === FALSE ? 'domain' : 'mailbox') as $rcpt) {
+?>
+ rcpt = <?=json_encode($rcpt, JSON_UNESCAPED_SLASHES);?>;
+<?php
+ }
+ }
+ else {
+?>
+ priority = 6;
+<?php
+ foreach (ucl_rcpts($row['object'], strpos($row['object'], '@') === FALSE ? 'domain' : 'mailbox') as $rcpt) {
+?>
+ rcpt = <?=json_encode($rcpt, JSON_UNESCAPED_SLASHES);?>;
+<?php
+ }
+ }
+?>
+ apply "default" {
+ MAILCOW_WHITE = -999.0;
+ }
+ symbols [
+ "MAILCOW_WHITE"
+ ]
+ }
+ whitelist_mime_<?=$username_sane;?> {
+<?php
+ foreach ($list_items as $item) {
+?>
+ from_mime = "/<?='^' . str_replace('\*', '.*', preg_quote($item['value'], '/')) . '$' ;?>/i";
+<?php
+ }
+ if (!filter_var(trim($row['object']), FILTER_VALIDATE_EMAIL)) {
+?>
+ priority = 5;
+<?php
+ foreach (ucl_rcpts($row['object'], strpos($row['object'], '@') === FALSE ? 'domain' : 'mailbox') as $rcpt) {
+?>
+ rcpt = <?=json_encode($rcpt, JSON_UNESCAPED_SLASHES);?>;
+<?php
+ }
+ }
+ else {
+?>
+ priority = 6;
+<?php
+ foreach (ucl_rcpts($row['object'], strpos($row['object'], '@') === FALSE ? 'domain' : 'mailbox') as $rcpt) {
+?>
+ rcpt = <?=json_encode($rcpt, JSON_UNESCAPED_SLASHES);?>;
+<?php
+ }
+ }
+?>
+ apply "default" {
+ MAILCOW_WHITE = -999.0;
+ }
+ symbols [
+ "MAILCOW_WHITE"
+ ]
+ }
+<?php
+}
+
+/*
+// Start blacklist
+*/
+
+$stmt = $pdo->query("SELECT DISTINCT `object` FROM `filterconf` WHERE `option` = 'blacklist_from'");
+$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
+while ($row = array_shift($rows)) {
+ $username_sane = preg_replace("/[^a-zA-Z0-9]+/", "", $row['object']);
+?>
+ blacklist_<?=$username_sane;?> {
+<?php
+ $list_items = array();
+ $stmt = $pdo->prepare("SELECT `value` FROM `filterconf`
+ WHERE `object`= :object
+ AND `option` = 'blacklist_from'");
+ $stmt->execute(array(':object' => $row['object']));
+ $list_items = $stmt->fetchAll(PDO::FETCH_ASSOC);
+ foreach ($list_items as $item) {
+?>
+ from = "/<?='^' . str_replace('\*', '.*', preg_quote($item['value'], '/')) . '$' ;?>/i";
+<?php
+ }
+ if (!filter_var(trim($row['object']), FILTER_VALIDATE_EMAIL)) {
+?>
+ priority = 5;
+<?php
+ foreach (ucl_rcpts($row['object'], strpos($row['object'], '@') === FALSE ? 'domain' : 'mailbox') as $rcpt) {
+?>
+ rcpt = <?=json_encode($rcpt, JSON_UNESCAPED_SLASHES);?>;
+<?php
+ }
+ }
+ else {
+?>
+ priority = 6;
+<?php
+ foreach (ucl_rcpts($row['object'], strpos($row['object'], '@') === FALSE ? 'domain' : 'mailbox') as $rcpt) {
+?>
+ rcpt = <?=json_encode($rcpt, JSON_UNESCAPED_SLASHES);?>;
+<?php
+ }
+ }
+?>
+ apply "default" {
+ MAILCOW_BLACK = 999.0;
+ }
+ symbols [
+ "MAILCOW_BLACK"
+ ]
+ }
+ blacklist_header_<?=$username_sane;?> {
+<?php
+ foreach ($list_items as $item) {
+?>
+ from_mime = "/<?='^' . str_replace('\*', '.*', preg_quote($item['value'], '/')) . '$' ;?>/i";
+<?php
+ }
+ if (!filter_var(trim($row['object']), FILTER_VALIDATE_EMAIL)) {
+?>
+ priority = 5;
+<?php
+ foreach (ucl_rcpts($row['object'], strpos($row['object'], '@') === FALSE ? 'domain' : 'mailbox') as $rcpt) {
+?>
+ rcpt = <?=json_encode($rcpt, JSON_UNESCAPED_SLASHES);?>;
+<?php
+ }
+ }
+ else {
+?>
+ priority = 6;
+<?php
+ foreach (ucl_rcpts($row['object'], strpos($row['object'], '@') === FALSE ? 'domain' : 'mailbox') as $rcpt) {
+?>
+ rcpt = <?=json_encode($rcpt, JSON_UNESCAPED_SLASHES);?>;
+<?php
+ }
+ }
+?>
+ apply "default" {
+ MAILCOW_BLACK = 999.0;
+ }
+ symbols [
+ "MAILCOW_BLACK"
+ ]
+ }
+<?php
+}
+
+/*
+// Start traps
+*/
+
+?>
+ ham_trap {
+<?php
+ foreach (ucl_rcpts('ham@localhost', 'mailbox') as $rcpt) {
+?>
+ rcpt = <?=json_encode($rcpt, JSON_UNESCAPED_SLASHES);?>;
+<?php
+ }
+?>
+ priority = 9;
+ apply "default" {
+ symbols_enabled = ["HISTORY_SAVE"];
+ }
+ symbols [
+ "HAM_TRAP"
+ ]
+ }
+
+ spam_trap {
+<?php
+ foreach (ucl_rcpts('spam@localhost', 'mailbox') as $rcpt) {
+?>
+ rcpt = <?=json_encode($rcpt, JSON_UNESCAPED_SLASHES);?>;
+<?php
+ }
+?>
+ priority = 9;
+ apply "default" {
+ symbols_enabled = ["HISTORY_SAVE"];
+ }
+ symbols [
+ "SPAM_TRAP"
+ ]
+ }
+<?php
+// Start additional content
+
+$stmt = $pdo->query("SELECT `id`, `content` FROM `settingsmap` WHERE `active` = '1'");
+$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
+while ($row = array_shift($rows)) {
+ $username_sane = preg_replace("/[^a-zA-Z0-9]+/", "", $row['id']);
+?>
+ additional_settings_<?=intval($row['id']);?> {
+<?php
+ $content = preg_split('/\r\n|\r|\n/', $row['content']);
+ foreach ($content as $line) {
+ echo ' ' . $line . PHP_EOL;
+ }
+?>
+ }
+<?php
+}
+?>
+}
diff --git a/mailcow/src/mailcow-dockerized/data/conf/rspamd/dynmaps/vars.inc.php b/mailcow/src/mailcow-dockerized/data/conf/rspamd/dynmaps/vars.inc.php
new file mode 100644
index 0000000..79566b0
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/rspamd/dynmaps/vars.inc.php
@@ -0,0 +1,6 @@
+<?php
+require_once('../../../web/inc/vars.inc.php');
+if (file_exists('../../../web/inc/vars.local.inc.php')) {
+ include_once('../../../web/inc/vars.local.inc.php');
+}
+?>
diff --git a/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/actions.conf b/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/actions.conf
new file mode 100644
index 0000000..3de63a5
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/actions.conf
@@ -0,0 +1,3 @@
+reject = 15;
+add_header = 8;
+greylist = 7;
diff --git a/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/antivirus.conf b/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/antivirus.conf
new file mode 100644
index 0000000..c8d31d1
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/antivirus.conf
@@ -0,0 +1,11 @@
+clamav {
+ # Scan whole message
+ scan_mime_parts = false;
+ #scan_text_mime = true;
+ #scan_image_mime = true;
+ symbol = "CLAM_VIRUS";
+ type = "clamav";
+ log_clean = true;
+ servers = "clamd:3310";
+ max_size = 20971520;
+}
diff --git a/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/arc.conf b/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/arc.conf
new file mode 100644
index 0000000..a857fc4
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/arc.conf
@@ -0,0 +1,32 @@
+# If false, messages with empty envelope from are not signed
+allow_envfrom_empty = true;
+# If true, envelope/header domain mismatch is ignored
+allow_hdrfrom_mismatch = true;
+# If true, multiple from headers are allowed (but only first is used)
+allow_hdrfrom_multiple = false;
+# If true, username does not need to contain matching domain
+allow_username_mismatch = false;
+# If false, messages from authenticated users are not selected for signing
+sign_authenticated = false;
+# Default path to key, can include '$domain' and '$selector' variables
+path = "/data/dkim/keys/$domain.dkim";
+# Default selector to use
+selector = "dkim";
+# If false, messages from local networks are not selected for signing
+sign_local = false;
+# Symbol to add when message is signed
+symbol = "ARC_SIGNED";
+# Whether to fallback to global config
+try_fallback = true;
+# Domain to use for DKIM signing: can be "header" or "envelope"
+use_domain = "recipient";
+# Whether to normalise domains to eSLD
+use_esld = false;
+# Whether to get keys from Redis
+use_redis = true;
+# Hash for DKIM keys in Redis
+key_prefix = "DKIM_PRIV_KEYS";
+# Selector map
+selector_prefix = "DKIM_SELECTORS";
+sign_inbound = true;
+use_domain_sign_inbound = "recipient";
diff --git a/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/asn.conf b/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/asn.conf
new file mode 100644
index 0000000..42b6780
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/asn.conf
@@ -0,0 +1,6 @@
+provider_type = "rspamd";
+provider_info {
+ ip4 = "asn.rspamd.com";
+ ip6 = "asn6.rspamd.com";
+}
+symbol = "ASN";
diff --git a/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/composites.conf b/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/composites.conf
new file mode 100644
index 0000000..13c977c
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/composites.conf
@@ -0,0 +1,51 @@
+MX_IMPLICIT {
+ expression = "MX_GOOD & MX_MISSING";
+ score = -0.01;
+}
+VIRUS_FOUND {
+ expression = "CLAM_VIRUS & !MAILCOW_WHITE";
+ score = 2000.0;
+}
+# Bad policy from free mail providers
+FREEMAIL_POLICY_FAILURE {
+ expression = "-g+:policies & !DMARC_POLICY_ALLOW & !MAILLIST & ( FREEMAIL_ENVFROM | FREEMAIL_FROM ) & !WHITELISTED_FWD_HOST";
+ score = 16.0;
+}
+# Bad policy from non-whitelisted senders
+# Remove SOGO_CONTACT symbol for fwd hosts and senders with broken policy
+SOGO_CONTACT_EXCLUDE {
+ expression = "(-WHITELISTED_FWD_HOST | -g+:policies) & ^SOGO_CONTACT & !DMARC_POLICY_ALLOW";
+}
+# Spoofed header from and broken policy (excluding sieve host, rspamd host, whitelisted senders, authenticated senders and forward hosts)
+SPOOFED_UNAUTH {
+ expression = "!MAILCOW_AUTH & !MAILCOW_WHITE & !RSPAMD_HOST & !SIEVE_HOST & MAILCOW_DOMAIN_HEADER_FROM & !WHITELISTED_FWD_HOST & -g+:policies";
+ score = 50.0;
+}
+# Only apply to inbound unauthed and not whitelisted
+OLEFY_MACRO {
+ expression = "!MAILCOW_AUTH & !MAILCOW_WHITE & OLETOOLS";
+ score = 20.0;
+ policy = "remove_weight";
+}
+# Applies to a content filter map
+BAD_WORD_BAD_TLD {
+ expression = "FISHY_TLD & ( BAD_WORDS | BAD_WORDS_DE )"
+ score = 10.0;
+}
+# Forged with bad policies and not fwd host, keep bad policy symbols
+FORGED_W_BAD_POLICY {
+ expression = "( -g+:policies | -R_SPF_NA) & ( ~FROM_NEQ_ENVFROM | ~FORGED_SENDER ) & !WHITELISTED_FWD_HOST & !DMARC_POLICY_ALLOW"
+ score = 3.0;
+}
+# Keep negative (good) scores for rbl, policies and hfilter, disable neural group
+WL_FWD_HOST {
+ expression = "-WHITELISTED_FWD_HOST & (^g+:rbl | ^g+:policies | ^g+:hfilter | ^g:neural)"
+}
+# Exclude X-Spam like flags from scoring from fwd and sieve hosts
+UPSTREAM_CHECKS_EXCLUDE_FWD_HOST {
+ expression = "(-SIEVE_HOST | -WHITELISTED_FWD_HOST) & (^UNITEDINTERNET_SPAM | ^SPAM_FLAG | ^KLMS_SPAM | ^AOL_SPAM | ^MICROSOFT_SPAM)"
+}
+# Remove fuzzy group from bounces
+BOUNCE_FUZZY {
+ expression = "-BOUNCE & ^g+:fuzzy";
+}
diff --git a/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/dkim_signing.conf b/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/dkim_signing.conf
new file mode 100644
index 0000000..13eb094
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/dkim_signing.conf
@@ -0,0 +1,35 @@
+# If false, messages with empty envelope from are not signed
+allow_envfrom_empty = true;
+# If true, envelope/header domain mismatch is ignored
+allow_hdrfrom_mismatch = true;
+# If true, multiple from headers are allowed (but only first is used)
+allow_hdrfrom_multiple = true;
+# If true, username does not need to contain matching domain
+allow_username_mismatch = true;
+# If false, messages from authenticated users are not selected for signing
+sign_authenticated = true;
+# Default path to key, can include '$domain' and '$selector' variables
+path = "/data/dkim/keys/$domain.dkim";
+# Default selector to use
+selector = "dkim";
+# If false, messages from local networks are not selected for signing
+sign_local = true;
+# Symbol to add when message is signed
+symbol = "DKIM_SIGNED";
+# Whether to fallback to global config
+try_fallback = true;
+# Domain to use for DKIM signing: can be "header" or "envelope"
+use_domain = "envelope";
+# Whether to normalise domains to eSLD
+use_esld = false;
+# Whether to get keys from Redis
+use_redis = true;
+# Hash for DKIM keys in Redis
+key_prefix = "DKIM_PRIV_KEYS";
+# Selector map
+selector_prefix = "DKIM_SELECTORS";
+# Sieve is in sign_networks only
+# forwards are arc signed, rejects are dkim signed
+sign_networks = "/etc/rspamd/custom/dovecot_trusted.map";
+use_domain_sign_networks = "header";
+sign_headers = "from:sender:reply-to:subject:date:message-id:to:cc:mime-version:content-type:content-transfer-encoding:resent-to:resent-cc:resent-from:resent-sender:resent-message-id:in-reply-to:references:list-id:list-help:list-owner:list-unsubscribe:list-subscribe:list-post:openpgp:autocrypt";
diff --git a/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/external_services.conf b/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/external_services.conf
new file mode 100644
index 0000000..f05314b
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/external_services.conf
@@ -0,0 +1,9 @@
+oletools {
+ # default olefy settings
+ servers = "olefy:10055";
+ # needs to be set explicitly for Rspamd < 1.9.5
+ scan_mime_parts = true;
+ # mime-part regex matching in content-type or filename
+ # block all macros
+ extended = true;
+}
diff --git a/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/force_actions.conf b/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/force_actions.conf
new file mode 100644
index 0000000..a1b9899
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/force_actions.conf
@@ -0,0 +1,12 @@
+rules {
+ WHITELIST_FORWARDING_HOST_NO_REJECT {
+ action = "add header";
+ expression = "WHITELISTED_FWD_HOST";
+ require_action = ["reject"];
+ }
+ WHITELIST_FORWARDING_HOST_NO_GREYLIST {
+ action = "no action";
+ expression = "WHITELISTED_FWD_HOST";
+ require_action = ["greylist", "soft reject"];
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/fuzzy_check.conf b/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/fuzzy_check.conf
new file mode 100644
index 0000000..855e8d0
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/fuzzy_check.conf
@@ -0,0 +1,54 @@
+rule "local" {
+ # Fuzzy storage server list
+ servers = "localhost:11445";
+ # Default symbol for unknown flags
+ symbol = "LOCAL_FUZZY_UNKNOWN";
+ # Additional mime types to store/check
+ mime_types = ["application/*"];
+ # Hash weight threshold for all maps
+ max_score = 100.0;
+ # Whether we can learn this storage
+ read_only = no;
+ # Ignore unknown flags
+ skip_unknown = yes;
+ # Hash generation algorithm
+ algorithm = "mumhash";
+
+ # Map flags to symbols
+ fuzzy_map = {
+ LOCAL_FUZZY_DENIED {
+ max_score = 10.0;
+ flag = 11;
+ }
+ LOCAL_FUZZY_WHITE {
+ max_score = 5.0;
+ flag = 13;
+ }
+ }
+}
+
+rule "mailcow" {
+ # Fuzzy storage server list
+ servers = "fuzzy.mailcow.email:11445";
+ # Default symbol for unknown flags
+ symbol = "MAILCOW_FUZZY_UNKNOWN";
+ # Additional mime types to store/check
+ mime_types = ["application/*"];
+ # Hash weight threshold for all maps
+ max_score = 100.0;
+ # Whether we can learn this storage
+ read_only = yes;
+ # Ignore unknown flags
+ skip_unknown = yes;
+ # Hash generation algorithm
+ algorithm = "mumhash";
+ # Encrypt connection
+ encryption_key = "oa7xjgdr9u7w3hq1xbttas6brgau8qc17yi7ur5huaeq6paq8h4y";
+ # Map flags to symbols
+ fuzzy_map = {
+ MAILCOW_FUZZY_DENIED {
+ max_score = 10.0;
+ flag = 11;
+ }
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/fuzzy_group.conf b/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/fuzzy_group.conf
new file mode 100644
index 0000000..561ac4e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/fuzzy_group.conf
@@ -0,0 +1,17 @@
+symbols = {
+ "LOCAL_FUZZY_UNKNOWN" {
+ weight = 0.1;
+ }
+ "LOCAL_FUZZY_DENIED" {
+ weight = 15.0;
+ }
+ "MAILCOW_FUZZY_UNKNOWN" {
+ weight = 0.1;
+ }
+ "MAILCOW_FUZZY_DENIED" {
+ weight = 7.0;
+ }
+ "LOCAL_FUZZY_WHITE" {
+ weight = -10.0;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/greylist.conf b/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/greylist.conf
new file mode 100644
index 0000000..c43c907
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/greylist.conf
@@ -0,0 +1,4 @@
+whitelisted_ip = "http://nginx:8081/forwardinghosts.php";
+ipv4_mask = 24;
+ipv6_mask = 64;
+message = "Greylisted, please try again later";
diff --git a/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/groups.conf b/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/groups.conf
new file mode 100644
index 0000000..ef599ef
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/groups.conf
@@ -0,0 +1,50 @@
+symbols {
+ "MAILCOW_AUTH" {
+ description = "mailcow authenticated";
+ score = -20.0;
+ }
+ "CTYPE_MIXED_BOGUS" {
+ score = 0.0;
+ }
+ "BAD_REP_POLICIES" {
+ score = 2.0;
+ }
+ "BULK_HEADER" {
+ score = 4.0;
+ }
+}
+
+group "MX" {
+ "MX_INVALID" {
+ score = 0.5;
+ description = "No connectable MX";
+ one_shot = true;
+ }
+ "MX_MISSING" {
+ score = 2.0;
+ description = "No MX record";
+ one_shot = true;
+ }
+ "MX_GOOD" {
+ score = -0.01;
+ description = "MX was ok";
+ one_shot = true;
+ }
+}
+
+group "reputation" {
+ symbols = {
+ "IP_REPUTATION_HAM" {
+ weight = 1.0;
+ }
+ "IP_REPUTATION_SPAM" {
+ weight = 4.0;
+ }
+ "SENDER_REP_HAM" {
+ weight = 1.0;
+ }
+ "SENDER_REP_SPAM" {
+ weight = 2.0;
+ }
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/headers_group.conf b/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/headers_group.conf
new file mode 100644
index 0000000..1df92b5
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/headers_group.conf
@@ -0,0 +1,7 @@
+symbols = {
+ "R_MIXED_CHARSET" {
+ weight = 1.0;
+ description = "Mixed characters in a message";
+ one_shot = true;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/hfilter_group.conf b/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/hfilter_group.conf
new file mode 100644
index 0000000..3c908c5
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/hfilter_group.conf
@@ -0,0 +1,5 @@
+symbols = {
+ "HFILTER_HOSTNAME_UNKNOWN" {
+ score = 8.5;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/history_redis.conf b/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/history_redis.conf
new file mode 100644
index 0000000..68a59b0
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/history_redis.conf
@@ -0,0 +1 @@
+nrows = 1000;
diff --git a/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/metadata_exporter.conf b/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/metadata_exporter.conf
new file mode 100644
index 0000000..f29f480
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/metadata_exporter.conf
@@ -0,0 +1,72 @@
+rules {
+ QUARANTINE {
+ backend = "http";
+ url = "http://nginx:9081/pipe.php";
+ selector = "reject_no_global_bl";
+ formatter = "default";
+ meta_headers = true;
+ }
+ RLINFO {
+ backend = "http";
+ url = "http://nginx:9081/pipe_rl.php";
+ selector = "ratelimited";
+ formatter = "json";
+ }
+ PUSHOVERMAIL {
+ backend = "http";
+ url = "http://nginx:9081/pushover.php";
+ selector = "mailcow_rcpt";
+ # Only return msgid, do not parse the full message
+ formatter = "msgid";
+ meta_headers = true;
+ }
+}
+
+custom_select {
+ mailcow_rcpt = <<EOD
+return function(task)
+ local action = task:get_metric_action('default')
+ if task:has_symbol('NO_LOG_STAT') or (action == 'reject' or action == 'add header' or action == 'rewrite subject') then
+ return false
+ else
+ if task:get_symbol("RCPT_MAILCOW_DOMAIN") then
+ return true
+ end
+ return false
+ end
+end
+EOD;
+ ratelimited = <<EOD
+return function(task)
+ local ratelimited = task:get_symbol("RATELIMITED")
+ if ratelimited then
+ return true
+ end
+ return false
+end
+EOD;
+ reject_no_global_bl = <<EOD
+return function(task)
+ if not task:has_symbol('GLOBAL_SMTP_FROM_BL')
+ and not task:has_symbol('GLOBAL_MIME_FROM_BL')
+ and not task:has_symbol('LOCAL_BL_ASN')
+ and not task:has_symbol('GLOBAL_RCPT_BL')
+ and not task:has_symbol('MAILCOW_BLACK') then
+ local action = task:get_metric_action('default')
+ if action == 'reject' or action == 'add header' or action == 'rewrite subject' then
+ return true
+ end
+ end
+ return false
+end
+EOD;
+}
+
+custom_format {
+ msgid = <<EOD
+return function(task)
+ return task:get_message_id()
+end
+EOD;
+}
+
diff --git a/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/milter_headers.conf b/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/milter_headers.conf
new file mode 100644
index 0000000..f61c3b9
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/milter_headers.conf
@@ -0,0 +1,43 @@
+use = ["spam-header", "x-spamd-result", "x-rspamd-queue-id", "authentication-results", "fuzzy-hashes"];
+skip_local = false;
+skip_authenticated = true;
+routines {
+ spam-header {
+ header = "X-Spam-Flag";
+ value = "YES";
+ remove = 1;
+ }
+ fuzzy-hashes {
+ header = "X-Rspamd-Fuzzy";
+ }
+ authentication-results {
+ header = "Authentication-Results";
+ add_smtp_user = false;
+ remove = 1;
+ spf_symbols {
+ pass = "R_SPF_ALLOW";
+ fail = "R_SPF_FAIL";
+ softfail = "R_SPF_SOFTFAIL";
+ neutral = "R_SPF_NEUTRAL";
+ temperror = "R_SPF_DNSFAIL";
+ none = "R_SPF_NA";
+ permerror = "R_SPF_PERMFAIL";
+ }
+ dkim_symbols {
+ pass = "R_DKIM_ALLOW";
+ fail = "R_DKIM_REJECT";
+ temperror = "R_DKIM_TEMPFAIL";
+ none = "R_DKIM_NA";
+ permerror = "R_DKIM_PERMFAIL";
+ }
+ dmarc_symbols {
+ pass = "DMARC_POLICY_ALLOW";
+ permerror = "DMARC_BAD_POLICY";
+ temperror = "DMARC_DNSFAIL";
+ none = "DMARC_NA";
+ reject = "DMARC_POLICY_REJECT";
+ softfail = "DMARC_POLICY_SOFTFAIL";
+ quarantine = "DMARC_POLICY_QUARANTINE";
+ }
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/mime_types.conf b/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/mime_types.conf
new file mode 100644
index 0000000..5d82982
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/mime_types.conf
@@ -0,0 +1,47 @@
+# Extensions that are treated as 'bad'
+# Number is score multiply factor
+bad_extensions = {
+ scr = 20,
+ lnk = 20,
+ exe = 20,
+ msi = 1,
+ msp = 1,
+ msu = 1,
+ jar = 2,
+ com = 20,
+ bat = 4,
+ cmd = 4,
+ ps1 = 4,
+ ace = 4,
+ arj = 4,
+ cab = 3,
+ vbs = 20,
+ hta = 4,
+ shs = 4,
+ wsc = 4,
+ wsf = 4,
+ iso = 8,
+ img = 8
+};
+
+# Extensions that are particularly penalized for archives
+bad_archive_extensions = {
+ pptx = 0.5,
+ docx = 0.5,
+ xlsx = 0.5,
+ pdf = 1.0,
+ jar = 3,
+ js = 0.5,
+ vbs = 20,
+ exe = 20
+};
+
+# Used to detect another archive in archive
+archive_extensions = {
+ zip = 1,
+ arj = 1,
+ rar = 1,
+ ace = 1,
+ 7z = 1,
+ cab = 1
+};
diff --git a/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/mime_types_group.conf b/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/mime_types_group.conf
new file mode 100644
index 0000000..b8dae7d
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/mime_types_group.conf
@@ -0,0 +1,7 @@
+symbols = {
+ "MIME_DOUBLE_BAD_EXTENSION" {
+ weight = 0; # This rule has dynamic weight up to 4.0
+ description = "Bad extension cloaking";
+ one_shot = true;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/multimap.conf b/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/multimap.conf
new file mode 100644
index 0000000..0f05bb5
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/multimap.conf
@@ -0,0 +1,157 @@
+RCPT_MAILCOW_DOMAIN {
+ type = "rcpt";
+ filter = "email:domain";
+ map = "redis://DOMAIN_MAP";
+ symbols_set = ["RCPT_MAILCOW_DOMAIN"];
+}
+
+WHITELISTED_FWD_HOST {
+ type = "ip";
+ map = "redis://WHITELISTED_FWD_HOST";
+ symbols_set = ["WHITELISTED_FWD_HOST"];
+}
+
+BULK_HEADER {
+ type = "content";
+ map = "${LOCAL_CONFDIR}/custom/bulk_header.map";
+ filter = "headers"
+ regexp = true;
+ symbols_set = ["BULK_HEADER"];
+}
+
+LOCAL_BL_ASN {
+ require_symbols = "!MAILCOW_WHITE";
+ type = "asn";
+ map = "${LOCAL_CONFDIR}/custom/bad_asn.map";
+ score = 5;
+ description = "Sender's ASN is on the local blacklist";
+ symbols_set = ["LOCAL_BL_ASN"];
+}
+
+GLOBAL_SMTP_FROM_WL {
+ type = "from";
+ map = "${LOCAL_CONFDIR}/custom/global_smtp_from_whitelist.map";
+ regexp = true;
+ score = -2050;
+}
+
+GLOBAL_SMTP_FROM_BL {
+ type = "from";
+ map = "${LOCAL_CONFDIR}/custom/global_smtp_from_blacklist.map";
+ regexp = true;
+ score = 2050;
+}
+
+GLOBAL_MIME_FROM_WL {
+ type = "header";
+ header = "from";
+ filter = "email:addr";
+ map = "${LOCAL_CONFDIR}/custom/global_mime_from_whitelist.map";
+ regexp = true;
+ score = -2050;
+}
+
+GLOBAL_MIME_FROM_BL {
+ type = "header";
+ header = "from";
+ filter = "email:addr";
+ map = "${LOCAL_CONFDIR}/custom/global_mime_from_blacklist.map";
+ regexp = true;
+ score = 2050;
+}
+
+GLOBAL_RCPT_WL {
+ type = "rcpt";
+ map = "${LOCAL_CONFDIR}/custom/global_rcpt_whitelist.map";
+ regexp = true;
+ prefilter = true;
+ action = "accept";
+}
+
+GLOBAL_RCPT_BL {
+ type = "rcpt";
+ map = "${LOCAL_CONFDIR}/custom/global_rcpt_blacklist.map";
+ regexp = true;
+ prefilter = true;
+ action = "reject";
+}
+
+SIEVE_HOST {
+ type = "ip";
+ map = "${LOCAL_CONFDIR}/custom/dovecot_trusted.map";
+ symbols_set = ["SIEVE_HOST"];
+ score = -15;
+}
+
+RSPAMD_HOST {
+ type = "ip";
+ map = "${LOCAL_CONFDIR}/custom/rspamd_trusted.map";
+ symbols_set = ["RSPAMD_HOST"];
+}
+
+MAILCOW_DOMAIN_HEADER_FROM {
+ type = "header";
+ header = "from";
+ filter = "email:domain";
+ map = "redis://DOMAIN_MAP";
+}
+
+IP_WHITELIST {
+ type = "ip";
+ map = "${LOCAL_CONFDIR}/custom/ip_wl.map";
+ symbols_set = ["IP_WHITELIST"];
+ score = -2050;
+}
+
+FISHY_TLD {
+ type = "from";
+ filter = "email:domain";
+ map = "${LOCAL_CONFDIR}/custom/fishy_tlds.map";
+ regexp = true;
+ score = 0.1;
+}
+
+BAD_WORDS {
+ type = "content";
+ filter = "text";
+ map = "${LOCAL_CONFDIR}/custom/bad_words.map";
+ regexp = true;
+ score = 0.1;
+}
+
+BAD_WORDS_DE {
+ type = "content";
+ filter = "text";
+ map = "${LOCAL_CONFDIR}/custom/bad_words_de.map";
+ regexp = true;
+ score = 0.1;
+}
+
+BAD_LANG {
+ type = 'selector';
+ selector = 'languages';
+ map = "${LOCAL_CONFDIR}/custom/bad_languages.map";
+ symbols_set = ["LANG_FILTER"];
+ regexp = true;
+ score = 5.0;
+}
+
+BAZAR_ABUSE_CH {
+ type = "selector";
+ selector = "attachments(hex,md5)";
+ map = "https://bazaar.abuse.ch/export/txt/md5/recent/";
+ score = 10.0;
+}
+
+URLHAUS_ABUSE_CH {
+ type = "url";
+ filter = "full";
+ map = "https://urlhaus.abuse.ch/downloads/text_online/";
+ score = 10.0;
+}
+
+SMTP_LIMITED_ACCESS {
+ type = "user";
+ map = "redis://SMTP_LIMITED_ACCESS";
+ symbols_set = ["SMTP_LIMITED_ACCESS"];
+}
diff --git a/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/mx_check.conf b/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/mx_check.conf
new file mode 100644
index 0000000..22fcedf
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/mx_check.conf
@@ -0,0 +1,7 @@
+timeout = 8.0;
+symbol_bad_mx = "MX_INVALID";
+symbol_no_mx = "MX_MISSING";
+symbol_good_mx = "MX_GOOD";
+expire = 86400;
+key_prefix = "rmx";
+enabled = true;
diff --git a/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/neural.conf b/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/neural.conf
new file mode 100644
index 0000000..f4658db
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/neural.conf
@@ -0,0 +1,24 @@
+rules {
+ "LONG" {
+ train {
+ max_trains = 200;
+ max_usages = 20;
+ max_iterations = 25;
+ learning_rate = 0.01,
+ }
+ symbol_spam = "NEURAL_SPAM_LONG";
+ symbol_ham = "NEURAL_HAM_LONG";
+ ann_expire = 45d;
+ }
+ "SHORT" {
+ train {
+ max_trains = 100;
+ max_usages = 10;
+ max_iterations = 15;
+ learning_rate = 0.01,
+ }
+ symbol_spam = "NEURAL_SPAM_SHORT";
+ symbol_ham = "NEURAL_HAM_SHORT";
+ ann_expire = 7d;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/neural_group.conf b/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/neural_group.conf
new file mode 100644
index 0000000..fca5cec
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/neural_group.conf
@@ -0,0 +1,18 @@
+symbols = {
+ "NEURAL_SPAM_LONG" {
+ weight = 3.7; # sample weight
+ description = "Neural network spam (long)";
+ }
+ "NEURAL_HAM_LONG" {
+ weight = -4.0; # sample weight
+ description = "Neural network ham (long)";
+ }
+ "NEURAL_SPAM_SHORT" {
+ weight = 2.5; # sample weight
+ description = "Neural network spam (short)";
+ }
+ "NEURAL_HAM_SHORT" {
+ weight = -2.0; # sample weight
+ description = "Neural network ham (short)";
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/options.inc b/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/options.inc
new file mode 100644
index 0000000..4fbdfba
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/options.inc
@@ -0,0 +1,9 @@
+dns {
+ enable_dnssec = true;
+}
+map_watch_interval = 30s;
+dns {
+ timeout = 4s;
+ retransmits = 2;
+}
+disable_monitoring = true;
diff --git a/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/phishing.conf b/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/phishing.conf
new file mode 100644
index 0000000..69be164
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/phishing.conf
@@ -0,0 +1 @@
+phishtank_enabled = false;
diff --git a/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/policies_group.conf b/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/policies_group.conf
new file mode 100644
index 0000000..8799db1
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/policies_group.conf
@@ -0,0 +1,23 @@
+symbols = {
+ "ARC_REJECT" {
+ score = 0.01;
+ }
+ "R_SPF_FAIL" {
+ score = 8.0;
+ }
+ "R_SPF_PERMFAIL" {
+ score = 8.0;
+ }
+ "R_DKIM_REJECT" {
+ score = 8.0;
+ }
+ "DMARC_POLICY_REJECT" {
+ weight = 16.0;
+ }
+ "DMARC_POLICY_QUARANTINE" {
+ weight = 8.0;
+ }
+ "DMARC_POLICY_SOFTFAIL" {
+ weight = 0.0;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/rbl.conf b/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/rbl.conf
new file mode 100644
index 0000000..c44b9ef
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/rbl.conf
@@ -0,0 +1,46 @@
+rbls {
+ uceprotect1 {
+ symbol = "RBL_UCEPROTECT_LEVEL1";
+ rbl = "dnsbl-1.uceprotect.net";
+ }
+ uceprotect2 {
+ symbol = "RBL_UCEPROTECT_LEVEL2";
+ rbl = "dnsbl-2.uceprotect.net";
+ }
+ sorbs {
+ symbol = "RBL_SORBS";
+ rbl = "dnsbl.sorbs.net";
+ returncodes {
+ # http:// www.sorbs.net/general/using.shtml
+ RBL_SORBS_HTTP = "127.0.0.2";
+ RBL_SORBS_SOCKS = "127.0.0.3";
+ RBL_SORBS_MISC = "127.0.0.4";
+ RBL_SORBS_SMTP = "127.0.0.5";
+ RBL_SORBS_RECENT = "127.0.0.6";
+ RBL_SORBS_WEB = "127.0.0.7";
+ RBL_SORBS_DUL = "127.0.0.10";
+ RBL_SORBS_BLOCK = "127.0.0.8";
+ RBL_SORBS_ZOMBIE = "127.0.0.9";
+ }
+ }
+ interserver_ip {
+ symbol = "RBL_INTERSERVER_IP";
+ rbl = "rbl.interserver.net";
+ ipv6 = false;
+ returncodes {
+ RBL_INTERSERVER_BAD_IP = "127.0.0.2";
+ }
+ }
+ interserver_uri {
+ symbol = "RBL_INTERSERVER_URI";
+ rbl = "rbluri.interserver.net";
+ ignore_defaults = true;
+ no_ip = true;
+ dkim = true;
+ emails = true;
+ urls = true;
+ returncodes = {
+ RBL_INTERSERVER_BAD_URI = "127.0.0.2";
+ }
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/rbl_group.conf b/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/rbl_group.conf
new file mode 100644
index 0000000..4e3dce7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/rbl_group.conf
@@ -0,0 +1,60 @@
+symbols = {
+ "RBL_UCEPROTECT_LEVEL1" {
+ score = 3.5;
+ }
+ "RBL_UCEPROTECT_LEVEL2" {
+ score = 1.5;
+ }
+ "RBL_SORBS" {
+ score = 0.0;
+ description = "Unrecognised result from SORBS RBL";
+ }
+ "RBL_SORBS_HTTP" {
+ score = 2.5;
+ description = "List of Open HTTP Proxy Servers.";
+ }
+ "RBL_SORBS_SOCKS" {
+ score = 2.5;
+ description = "List of Open SOCKS Proxy Servers.";
+ }
+ "RBL_SORBS_MISC" {
+ score = 1.0;
+ description = "List of open Proxy Servers not listed in the SOCKS or HTTP lists.";
+ }
+ "RBL_SORBS_SMTP" {
+ score = 4.0;
+ description = "List of Open SMTP relay servers.";
+ }
+ "RBL_SORBS_RECENT" {
+ score = 2.0;
+ description = "List of hosts that have been noted as sending spam/UCE/UBE to the admins of SORBS within the last 28 days (includes new.spam.dnsbl.sorbs.net).";
+ }
+ "RBL_SORBS_WEB" {
+ score = 2.0;
+ description = "List of web (WWW) servers which have spammer abusable vulnerabilities (e.g. FormMail scripts)";
+ }
+ "RBL_SORBS_DUL" {
+ score = 2.0;
+ description = "Dynamic IP Address ranges (NOT a Dial Up list!)";
+ }
+ "RBL_SORBS_BLOCK" {
+ score = 0.5;
+ description = "List of hosts demanding that they never be tested by SORBS.";
+ }
+ "RBL_SORBS_ZOMBIE" {
+ score = 2.0;
+ description = "List of networks hijacked from their original owners, some of which have already used for spamming.";
+ }
+ "RECEIVED_SPAMHAUS_XBL" {
+ weight = 0.0;
+ description = "Received address is listed in ZEN XBL";
+ }
+ "RBL_INTERSERVER_BAD_URI" {
+ score = 4.0;
+ description = "Listed on Interserver RBL";
+ }
+ "RBL_INTERSERVER_BAD_IP" {
+ score = 4.0;
+ description = "Listed on Interserver RBL";
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/redis.conf b/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/redis.conf
new file mode 100644
index 0000000..5ee0ac1
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/redis.conf
@@ -0,0 +1,2 @@
+servers = "redis:6379";
+timeout = 10;
diff --git a/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/reputation.conf b/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/reputation.conf
new file mode 100644
index 0000000..0e3d03e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/reputation.conf
@@ -0,0 +1,10 @@
+rules {
+ ip_reputation = {
+ selector "ip" {
+ }
+ backend "redis" {
+ servers = "redis";
+ }
+ symbol = "IP_REPUTATION";
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/spamassassin.conf b/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/spamassassin.conf
new file mode 100644
index 0000000..d091af6
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/spamassassin.conf
@@ -0,0 +1 @@
+ruleset = "/etc/rspamd/custom/sa-rules";
diff --git a/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/statistic.conf b/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/statistic.conf
new file mode 100644
index 0000000..1ca3e08
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/statistic.conf
@@ -0,0 +1,24 @@
+classifier "bayes" {
+ tokenizer {
+ name = "osb";
+ }
+ backend = "redis";
+ min_tokens = 11;
+ min_learns = 5;
+ new_schema = true;
+ expire = 2592000;
+ statfile {
+ symbol = "BAYES_HAM";
+ spam = false;
+ }
+ statfile {
+ symbol = "BAYES_SPAM";
+ spam = true;
+ }
+ autolearn {
+ spam_threshold = 12.0;
+ ham_threshold = -4.5;
+ check_balance = true;
+ min_balance = 0.9;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/statistics_group.conf b/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/statistics_group.conf
new file mode 100644
index 0000000..7ed35b1
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/rspamd/local.d/statistics_group.conf
@@ -0,0 +1,10 @@
+symbols = {
+ "BAYES_SPAM" {
+ weight = 2.5;
+ description = "Message probably spam, probability: ";
+ }
+ "BAYES_HAM" {
+ weight = -5.5;
+ description = "Message probably ham, probability: ";
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/conf/rspamd/lua/ivm-sg.lua b/mailcow/src/mailcow-dockerized/data/conf/rspamd/lua/ivm-sg.lua
new file mode 100644
index 0000000..6642fe4
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/rspamd/lua/ivm-sg.lua
@@ -0,0 +1,61 @@
+-- Thanks to https://raw.githubusercontent.com/fatalbanana
+
+local lua_maps = require 'lua_maps'
+local rspamd_regexp = require 'rspamd_regexp'
+local rspamd_util = require 'rspamd_util'
+
+local ivm_sendgrid_ids = lua_maps.map_add_from_ucl(
+ 'https://www.invaluement.com/spdata/sendgrid-id-dnsbl.txt',
+ 'set',
+ 'Invaluement Service Provider DNSBL: Sendgrid IDs'
+)
+
+local ivm_sendgrid_envfromdomains = lua_maps.map_add_from_ucl(
+ 'https://www.invaluement.com/spdata/sendgrid-envelopefromdomain-dnsbl.txt',
+ 'set',
+ 'Invaluement Service Provider DNSBL: Sendgrid envelope domains'
+)
+
+local cb_id = rspamd_config:register_symbol({
+ name = 'IVM_SENDGRID',
+ callback = function(task)
+ -- Is it Sendgrid?
+ local sg_hdr = task:get_header('X-SG-EID')
+ if not sg_hdr then return end
+
+ -- Get original envelope from
+ local env_from = task:get_from{'smtp', 'orig'}
+ if not env_from then return end
+
+ -- Check normalised domain in domains list
+ if ivm_sendgrid_envfromdomains and ivm_sendgrid_envfromdomains:get_key(rspamd_util.get_tld(env_from[1].domain)) then
+ task:insert_result('IVM_SENDGRID_DOMAIN', 1.0)
+ end
+
+ -- Check ID in ID list
+ local lp_re = rspamd_regexp.create_cached([[^bounces\+(\d+)-]])
+ local res = lp_re:search(env_from[1].user, true, true)
+ if not res then return end
+ if ivm_sendgrid_ids and ivm_sendgrid_ids:get_key(res[1][2]) then
+ task:insert_result('IVM_SENDGRID_ID', 1.0)
+ end
+ end,
+ description = 'Invaluement Service Provider DNSBL: Sendgrid',
+ type = 'callback',
+})
+
+rspamd_config:register_symbol({
+ name = 'IVM_SENDGRID_DOMAIN',
+ parent = cb_id,
+ group = 'ivmspdnsbl',
+ score = 8.0,
+ type = 'virtual',
+})
+
+rspamd_config:register_symbol({
+ name = 'IVM_SENDGRID_ID',
+ parent = cb_id,
+ group = 'ivmspdnsbl',
+ score = 8.0,
+ type = 'virtual',
+})
diff --git a/mailcow/src/mailcow-dockerized/data/conf/rspamd/lua/ratelimit.lua b/mailcow/src/mailcow-dockerized/data/conf/rspamd/lua/ratelimit.lua
new file mode 100644
index 0000000..635fe3e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/rspamd/lua/ratelimit.lua
@@ -0,0 +1,16 @@
+local custom_keywords = {}
+
+custom_keywords.mailcow = function(task)
+ local rspamd_logger = require "rspamd_logger"
+ local dyn_rl_symbol = task:get_symbol("DYN_RL")
+ if dyn_rl_symbol then
+ local rl_value = dyn_rl_symbol[1].options[1]
+ local rl_object = dyn_rl_symbol[1].options[2]
+ if rl_value and rl_object then
+ rspamd_logger.infox(rspamd_config, "DYN_RL symbol has value %s for object %s, returning %s...", rl_value, rl_object, "rs_dynrl_" .. rl_object)
+ return "rs_dynrl_" .. rl_object, rl_value
+ end
+ end
+end
+
+return custom_keywords
diff --git a/mailcow/src/mailcow-dockerized/data/conf/rspamd/lua/rspamd.local.lua b/mailcow/src/mailcow-dockerized/data/conf/rspamd/lua/rspamd.local.lua
new file mode 100644
index 0000000..3f4c326
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/rspamd/lua/rspamd.local.lua
@@ -0,0 +1,398 @@
+-- Load sendgrid ID validator, thanks to https://github.com/fatalbanana
+local rspamd_util = require 'rspamd_util'
+local f = '/etc/rspamd/lua/ivm-sg.lua'
+if rspamd_util.file_exists(f) then
+ dofile(f)
+end
+
+rspamd_config.MAILCOW_AUTH = {
+ callback = function(task)
+ local uname = task:get_user()
+ if uname then
+ return 1
+ end
+ end
+}
+
+local monitoring_hosts = rspamd_config:add_map{
+ url = "/etc/rspamd/custom/monitoring_nolog.map",
+ description = "Monitoring hosts",
+ type = "regexp"
+}
+
+rspamd_config:register_symbol({
+ name = 'SMTP_ACCESS',
+ type = 'postfilter',
+ callback = function(task)
+ local util = require("rspamd_util")
+ local rspamd_logger = require "rspamd_logger"
+ local rspamd_ip = require 'rspamd_ip'
+ local uname = task:get_user()
+ local limited_access = task:get_symbol("SMTP_LIMITED_ACCESS")
+
+ if not uname then
+ return false
+ end
+
+ if not limited_access then
+ return false
+ end
+
+ local hash_key = 'SMTP_ALLOW_NETS_' .. uname
+
+ local redis_params = rspamd_parse_redis_server('smtp_access')
+ local ip = task:get_from_ip()
+
+ if ip == nil or not ip:is_valid() then
+ return false
+ end
+
+ local from_ip_string = tostring(ip)
+ smtp_access_table = {from_ip_string}
+
+ local maxbits = 128
+ local minbits = 32
+ if ip:get_version() == 4 then
+ maxbits = 32
+ minbits = 8
+ end
+ for i=maxbits,minbits,-1 do
+ local nip = ip:apply_mask(i):to_string() .. "/" .. i
+ table.insert(smtp_access_table, nip)
+ end
+ local function smtp_access_cb(err, data)
+ if err then
+ rspamd_logger.infox(rspamd_config, "smtp_access query request for ip %s returned invalid or empty data (\"%s\") or error (\"%s\")", ip, data, err)
+ return false
+ else
+ rspamd_logger.infox(rspamd_config, "checking ip %s for smtp_access in %s", from_ip_string, hash_key)
+ for k,v in pairs(data) do
+ if (v and v ~= userdata and v == '1') then
+ rspamd_logger.infox(rspamd_config, "found ip in smtp_access map")
+ task:insert_result(true, 'SMTP_ACCESS', 0.0, from_ip_string)
+ return true
+ end
+ end
+ rspamd_logger.infox(rspamd_config, "couldnt find ip in smtp_access map")
+ task:insert_result(true, 'SMTP_ACCESS', 999.0, from_ip_string)
+ return true
+ end
+ end
+ table.insert(smtp_access_table, 1, hash_key)
+ local redis_ret_user = rspamd_redis_make_request(task,
+ redis_params, -- connect params
+ hash_key, -- hash key
+ false, -- is write
+ smtp_access_cb, --callback
+ 'HMGET', -- command
+ smtp_access_table -- arguments
+ )
+ if not redis_ret_user then
+ rspamd_logger.infox(rspamd_config, "cannot check smtp_access redis map")
+ end
+ end,
+ priority = 10
+})
+
+rspamd_config:register_symbol({
+ name = 'POSTMASTER_HANDLER',
+ type = 'prefilter',
+ callback = function(task)
+ local rcpts = task:get_recipients('smtp')
+ local rspamd_logger = require "rspamd_logger"
+ local lua_util = require "lua_util"
+ local from = task:get_from(1)
+
+ -- not applying to mails with more than one rcpt to avoid bypassing filters by addressing postmaster
+ if rcpts and #rcpts == 1 then
+ for _,rcpt in ipairs(rcpts) do
+ local rcpt_split = rspamd_str_split(rcpt['addr'], '@')
+ if #rcpt_split == 2 then
+ if rcpt_split[1] == 'postmaster' then
+ task:set_pre_result('accept', 'whitelisting postmaster smtp rcpt')
+ return
+ end
+ end
+ end
+ end
+
+ if from then
+ for _,fr in ipairs(from) do
+ local fr_split = rspamd_str_split(fr['addr'], '@')
+ if #fr_split == 2 then
+ if fr_split[1] == 'postmaster' and task:get_user() then
+ -- no whitelist, keep signatures
+ task:insert_result(true, 'POSTMASTER_FROM', -2500.0)
+ return
+ end
+ end
+ end
+ end
+
+ end,
+ priority = 10
+})
+
+rspamd_config:register_symbol({
+ name = 'KEEP_SPAM',
+ type = 'prefilter',
+ callback = function(task)
+ local util = require("rspamd_util")
+ local rspamd_logger = require "rspamd_logger"
+ local rspamd_ip = require 'rspamd_ip'
+ local uname = task:get_user()
+
+ if uname then
+ return false
+ end
+
+ local redis_params = rspamd_parse_redis_server('keep_spam')
+ local ip = task:get_from_ip()
+
+ if ip == nil or not ip:is_valid() then
+ return false
+ end
+
+ local from_ip_string = tostring(ip)
+ ip_check_table = {from_ip_string}
+
+ local maxbits = 128
+ local minbits = 32
+ if ip:get_version() == 4 then
+ maxbits = 32
+ minbits = 8
+ end
+ for i=maxbits,minbits,-1 do
+ local nip = ip:apply_mask(i):to_string() .. "/" .. i
+ table.insert(ip_check_table, nip)
+ end
+ local function keep_spam_cb(err, data)
+ if err then
+ rspamd_logger.infox(rspamd_config, "keep_spam query request for ip %s returned invalid or empty data (\"%s\") or error (\"%s\")", ip, data, err)
+ return false
+ else
+ for k,v in pairs(data) do
+ if (v and v ~= userdata and v == '1') then
+ rspamd_logger.infox(rspamd_config, "found ip in keep_spam map, setting pre-result")
+ task:set_pre_result('accept', 'ip matched with forward hosts')
+ end
+ end
+ end
+ end
+ table.insert(ip_check_table, 1, 'KEEP_SPAM')
+ local redis_ret_user = rspamd_redis_make_request(task,
+ redis_params, -- connect params
+ 'KEEP_SPAM', -- hash key
+ false, -- is write
+ keep_spam_cb, --callback
+ 'HMGET', -- command
+ ip_check_table -- arguments
+ )
+ if not redis_ret_user then
+ rspamd_logger.infox(rspamd_config, "cannot check keep_spam redis map")
+ end
+ end,
+ priority = 19
+})
+
+rspamd_config:register_symbol({
+ name = 'TLS_HEADER',
+ type = 'postfilter',
+ callback = function(task)
+ local rspamd_logger = require "rspamd_logger"
+ local tls_tag = task:get_request_header('TLS-Version')
+ if type(tls_tag) == 'nil' then
+ task:set_milter_reply({
+ add_headers = {['X-Last-TLS-Session-Version'] = 'None'}
+ })
+ else
+ task:set_milter_reply({
+ add_headers = {['X-Last-TLS-Session-Version'] = tostring(tls_tag)}
+ })
+ end
+ end,
+ priority = 12
+})
+
+rspamd_config:register_symbol({
+ name = 'TAG_MOO',
+ type = 'postfilter',
+ callback = function(task)
+ local util = require("rspamd_util")
+ local rspamd_logger = require "rspamd_logger"
+ local redis_params = rspamd_parse_redis_server('taghandler')
+ local rspamd_http = require "rspamd_http"
+ local rcpts = task:get_recipients('smtp')
+ local lua_util = require "lua_util"
+
+ local tagged_rcpt = task:get_symbol("TAGGED_RCPT")
+ local mailcow_domain = task:get_symbol("RCPT_MAILCOW_DOMAIN")
+
+ if tagged_rcpt and tagged_rcpt[1].options and mailcow_domain then
+ local tag = tagged_rcpt[1].options[1]
+ rspamd_logger.infox("found tag: %s", tag)
+ local action = task:get_metric_action('default')
+ rspamd_logger.infox("metric action now: %s", action)
+
+ if action ~= 'no action' and action ~= 'greylist' then
+ rspamd_logger.infox("skipping tag handler for action: %s", action)
+ return true
+ end
+
+ local function http_callback(err_message, code, body, headers)
+ if body ~= nil and body ~= "" then
+ rspamd_logger.infox(rspamd_config, "expanding rcpt to \"%s\"", body)
+
+ local function tag_callback_subject(err, data)
+ if err or type(data) ~= 'string' then
+ rspamd_logger.infox(rspamd_config, "subject tag handler rcpt %s returned invalid or empty data (\"%s\") or error (\"%s\") - trying subfolder tag handler...", body, data, err)
+
+ local function tag_callback_subfolder(err, data)
+ if err or type(data) ~= 'string' then
+ rspamd_logger.infox(rspamd_config, "subfolder tag handler for rcpt %s returned invalid or empty data (\"%s\") or error (\"%s\")", body, data, err)
+ else
+ rspamd_logger.infox("Add X-Moo-Tag header")
+ task:set_milter_reply({
+ add_headers = {['X-Moo-Tag'] = 'YES'}
+ })
+ end
+ end
+
+ local redis_ret_subfolder = rspamd_redis_make_request(task,
+ redis_params, -- connect params
+ body, -- hash key
+ false, -- is write
+ tag_callback_subfolder, --callback
+ 'HGET', -- command
+ {'RCPT_WANTS_SUBFOLDER_TAG', body} -- arguments
+ )
+ if not redis_ret_subfolder then
+ rspamd_logger.infox(rspamd_config, "cannot make request to load tag handler for rcpt")
+ end
+
+ else
+ rspamd_logger.infox("user wants subject modified for tagged mail")
+ local sbj = task:get_header('Subject')
+ new_sbj = '=?UTF-8?B?' .. tostring(util.encode_base64('[' .. tag .. '] ' .. sbj)) .. '?='
+ task:set_milter_reply({
+ remove_headers = {['Subject'] = 1},
+ add_headers = {['Subject'] = new_sbj}
+ })
+ end
+ end
+
+ local redis_ret_subject = rspamd_redis_make_request(task,
+ redis_params, -- connect params
+ body, -- hash key
+ false, -- is write
+ tag_callback_subject, --callback
+ 'HGET', -- command
+ {'RCPT_WANTS_SUBJECT_TAG', body} -- arguments
+ )
+ if not redis_ret_subject then
+ rspamd_logger.infox(rspamd_config, "cannot make request to load tag handler for rcpt")
+ end
+
+ end
+ end
+
+ if rcpts and #rcpts == 1 then
+ for _,rcpt in ipairs(rcpts) do
+ local rcpt_split = rspamd_str_split(rcpt['addr'], '@')
+ if #rcpt_split == 2 then
+ if rcpt_split[1] == 'postmaster' then
+ rspamd_logger.infox(rspamd_config, "not expanding postmaster alias")
+ else
+ rspamd_http.request({
+ task=task,
+ url='http://nginx:8081/aliasexp.php',
+ body='',
+ callback=http_callback,
+ headers={Rcpt=rcpt['addr']},
+ })
+ end
+ end
+ end
+ end
+
+ end
+ end,
+ priority = 19
+})
+
+rspamd_config:register_symbol({
+ name = 'DYN_RL_CHECK',
+ type = 'prefilter',
+ callback = function(task)
+ local util = require("rspamd_util")
+ local redis_params = rspamd_parse_redis_server('dyn_rl')
+ local rspamd_logger = require "rspamd_logger"
+ local envfrom = task:get_from(1)
+ local uname = task:get_user()
+ if not envfrom or not uname then
+ return false
+ end
+ local uname = uname:lower()
+
+ local env_from_domain = envfrom[1].domain:lower() -- get smtp from domain in lower case
+
+ local function redis_cb_user(err, data)
+
+ if err or type(data) ~= 'string' then
+ rspamd_logger.infox(rspamd_config, "dynamic ratelimit request for user %s returned invalid or empty data (\"%s\") or error (\"%s\") - trying dynamic ratelimit for domain...", uname, data, err)
+
+ local function redis_key_cb_domain(err, data)
+ if err or type(data) ~= 'string' then
+ rspamd_logger.infox(rspamd_config, "dynamic ratelimit request for domain %s returned invalid or empty data (\"%s\") or error (\"%s\")", env_from_domain, data, err)
+ else
+ rspamd_logger.infox(rspamd_config, "found dynamic ratelimit in redis for domain %s with value %s", env_from_domain, data)
+ task:insert_result('DYN_RL', 0.0, data, env_from_domain)
+ end
+ end
+
+ local redis_ret_domain = rspamd_redis_make_request(task,
+ redis_params, -- connect params
+ env_from_domain, -- hash key
+ false, -- is write
+ redis_key_cb_domain, --callback
+ 'HGET', -- command
+ {'RL_VALUE', env_from_domain} -- arguments
+ )
+ if not redis_ret_domain then
+ rspamd_logger.infox(rspamd_config, "cannot make request to load ratelimit for domain")
+ end
+ else
+ rspamd_logger.infox(rspamd_config, "found dynamic ratelimit in redis for user %s with value %s", uname, data)
+ task:insert_result('DYN_RL', 0.0, data, uname)
+ end
+
+ end
+
+ local redis_ret_user = rspamd_redis_make_request(task,
+ redis_params, -- connect params
+ uname, -- hash key
+ false, -- is write
+ redis_cb_user, --callback
+ 'HGET', -- command
+ {'RL_VALUE', uname} -- arguments
+ )
+ if not redis_ret_user then
+ rspamd_logger.infox(rspamd_config, "cannot make request to load ratelimit for user")
+ end
+ return true
+ end,
+ flags = 'empty',
+ priority = 20
+})
+
+rspamd_config:register_symbol({
+ name = 'NO_LOG_STAT',
+ type = 'postfilter',
+ callback = function(task)
+ local from = task:get_header('From')
+ if from and monitoring_hosts:get_key(from) then
+ task:set_flag('no_log')
+ task:set_flag('no_stat')
+ end
+ end
+})
diff --git a/mailcow/src/mailcow-dockerized/data/conf/rspamd/meta_exporter/pipe.php b/mailcow/src/mailcow-dockerized/data/conf/rspamd/meta_exporter/pipe.php
new file mode 100644
index 0000000..88e66e8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/rspamd/meta_exporter/pipe.php
@@ -0,0 +1,260 @@
+<?php
+// File size is limited by Nginx site to 10M
+// To speed things up, we do not include prerequisites
+header('Content-Type: text/plain');
+require_once "vars.inc.php";
+// Do not show errors, we log to using error_log
+ini_set('error_reporting', 0);
+// Init database
+//$dsn = $database_type . ':host=' . $database_host . ';dbname=' . $database_name;
+$dsn = $database_type . ":unix_socket=" . $database_sock . ";dbname=" . $database_name;
+$opt = [
+ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
+ PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
+ PDO::ATTR_EMULATE_PREPARES => false,
+];
+try {
+ $pdo = new PDO($dsn, $database_user, $database_pass, $opt);
+}
+catch (PDOException $e) {
+ error_log("QUARANTINE: " . $e . PHP_EOL);
+ http_response_code(501);
+ exit;
+}
+// Init Redis
+$redis = new Redis();
+$redis->connect('redis-mailcow', 6379);
+
+// Functions
+function parse_email($email) {
+ if(!filter_var($email, FILTER_VALIDATE_EMAIL)) return false;
+ $a = strrpos($email, '@');
+ return array('local' => substr($email, 0, $a), 'domain' => substr(substr($email, $a), 1));
+}
+if (!function_exists('getallheaders')) {
+ function getallheaders() {
+ if (!is_array($_SERVER)) {
+ return array();
+ }
+ $headers = array();
+ foreach ($_SERVER as $name => $value) {
+ if (substr($name, 0, 5) == 'HTTP_') {
+ $headers[str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5)))))] = $value;
+ }
+ }
+ return $headers;
+ }
+}
+
+$raw_data_content = file_get_contents('php://input');
+$raw_data = mb_convert_encoding($raw_data_content, 'HTML-ENTITIES', "UTF-8");
+$headers = getallheaders();
+
+$qid = $headers['X-Rspamd-Qid'];
+$fuzzy = $headers['X-Rspamd-Fuzzy'];
+$subject = $headers['X-Rspamd-Subject'];
+$score = $headers['X-Rspamd-Score'];
+$rcpts = $headers['X-Rspamd-Rcpt'];
+$user = $headers['X-Rspamd-User'];
+$ip = $headers['X-Rspamd-Ip'];
+$action = $headers['X-Rspamd-Action'];
+$sender = $headers['X-Rspamd-From'];
+$symbols = $headers['X-Rspamd-Symbols'];
+
+$raw_size = (int)$_SERVER['CONTENT_LENGTH'];
+
+if (empty($sender)) {
+ error_log("QUARANTINE: Unknown sender, assuming empty-env-from@localhost" . PHP_EOL);
+ $sender = 'empty-env-from@localhost';
+}
+
+if ($fuzzy == 'unknown') {
+ $fuzzy = '[]';
+}
+
+try {
+ $max_size = (int)$redis->Get('Q_MAX_SIZE');
+ if (($max_size * 1048576) < $raw_size) {
+ error_log(sprintf("QUARANTINE: Message too large: %d b exceeds %d b", $raw_size, ($max_size * 1048576)) . PHP_EOL);
+ http_response_code(505);
+ exit;
+ }
+ if ($exclude_domains = $redis->Get('Q_EXCLUDE_DOMAINS')) {
+ $exclude_domains = json_decode($exclude_domains, true);
+ }
+ $retention_size = (int)$redis->Get('Q_RETENTION_SIZE');
+}
+catch (RedisException $e) {
+ error_log("QUARANTINE: " . $e . PHP_EOL);
+ http_response_code(504);
+ exit;
+}
+
+$rcpt_final_mailboxes = array();
+
+// Loop through all rcpts
+foreach (json_decode($rcpts, true) as $rcpt) {
+ // Remove tag
+ $rcpt = preg_replace('/^(.*?)\+.*(@.*)$/', '$1$2', $rcpt);
+
+ // Break rcpt into local part and domain part
+ $parsed_rcpt = parse_email($rcpt);
+
+ // Skip if not a mailcow handled domain
+ try {
+ if (!$redis->hGet('DOMAIN_MAP', $parsed_rcpt['domain'])) {
+ continue;
+ }
+ }
+ catch (RedisException $e) {
+ error_log("QUARANTINE: " . $e . PHP_EOL);
+ http_response_code(504);
+ exit;
+ }
+
+ // Skip if domain is excluded
+ if (in_array($parsed_rcpt['domain'], $exclude_domains)) {
+ error_log(sprintf("QUARANTINE: Skipped domain %s", $parsed_rcpt['domain']) . PHP_EOL);
+ continue;
+ }
+
+ // Always assume rcpt is not a final mailbox but an alias for a mailbox or further aliases
+ //
+ // rcpt
+ // |
+ // mailbox <-- goto ---> alias1, alias2, mailbox2
+ // | |
+ // mailbox3 |
+ // |
+ // alias3 ---> mailbox4
+ //
+ try {
+ $stmt = $pdo->prepare("SELECT `goto` FROM `alias` WHERE `address` = :rcpt AND `active` = '1'");
+ $stmt->execute(array(
+ ':rcpt' => $rcpt
+ ));
+ $gotos = $stmt->fetch(PDO::FETCH_ASSOC)['goto'];
+ if (empty($gotos)) {
+ $stmt = $pdo->prepare("SELECT `goto` FROM `alias` WHERE `address` = :rcpt AND `active` = '1'");
+ $stmt->execute(array(
+ ':rcpt' => '@' . $parsed_rcpt['domain']
+ ));
+ $gotos = $stmt->fetch(PDO::FETCH_ASSOC)['goto'];
+ }
+ if (empty($gotos)) {
+ $stmt = $pdo->prepare("SELECT `target_domain` FROM `alias_domain` WHERE `alias_domain` = :rcpt AND `active` = '1'");
+ $stmt->execute(array(':rcpt' => $parsed_rcpt['domain']));
+ $goto_branch = $stmt->fetch(PDO::FETCH_ASSOC)['target_domain'];
+ if ($goto_branch) {
+ $gotos = $parsed_rcpt['local'] . '@' . $goto_branch;
+ }
+ }
+ $gotos_array = explode(',', $gotos);
+
+ $loop_c = 0;
+
+ while (count($gotos_array) != 0 && $loop_c <= 20) {
+
+ // Loop through all found gotos
+ foreach ($gotos_array as $index => &$goto) {
+ error_log("RCPT RESOVLER: http pipe: query " . $goto . " as username from mailbox" . PHP_EOL);
+ $stmt = $pdo->prepare("SELECT `username` FROM `mailbox` WHERE `username` = :goto AND (`active`= '1' OR `active`= '2');");
+ $stmt->execute(array(':goto' => $goto));
+ $username = $stmt->fetch(PDO::FETCH_ASSOC)['username'];
+ if (!empty($username)) {
+ error_log("RCPT RESOVLER: http pipe: mailbox found: " . $username . PHP_EOL);
+ // Current goto is a mailbox, save to rcpt_final_mailboxes if not a duplicate
+ if (!in_array($username, $rcpt_final_mailboxes)) {
+ $rcpt_final_mailboxes[] = $username;
+ }
+ }
+ else {
+ $parsed_goto = parse_email($goto);
+ if (!$redis->hGet('DOMAIN_MAP', $parsed_goto['domain'])) {
+ error_log("RCPT RESOVLER:" . $goto . " is not a mailcow handled mailbox or alias address" . PHP_EOL);
+ }
+ else {
+ $stmt = $pdo->prepare("SELECT `goto` FROM `alias` WHERE `address` = :goto AND `active` = '1'");
+ $stmt->execute(array(':goto' => $goto));
+ $goto_branch = $stmt->fetch(PDO::FETCH_ASSOC)['goto'];
+ if ($goto_branch) {
+ error_log("RCPT RESOVLER: http pipe: goto address " . $goto . " is an alias branch for " . $goto_branch . PHP_EOL);
+ $goto_branch_array = explode(',', $goto_branch);
+ } else {
+ $stmt = $pdo->prepare("SELECT `target_domain` FROM `alias_domain` WHERE `alias_domain` = :domain AND `active` AND '1'");
+ $stmt->execute(array(':domain' => $parsed_goto['domain']));
+ $goto_branch = $stmt->fetch(PDO::FETCH_ASSOC)['target_domain'];
+ if ($goto_branch) {
+ error_log("RCPT RESOVLER: http pipe: goto domain " . $parsed_goto['domain'] . " is a domain alias branch for " . $goto_branch . PHP_EOL);
+ $goto_branch_array = array($parsed_goto['local'] . '@' . $goto_branch);
+ }
+ }
+ }
+ }
+ // goto item was processed, unset
+ unset($gotos_array[$index]);
+ }
+
+ // Merge goto branch array derived from previous loop (if any), filter duplicates and unset goto branch array
+ if (!empty($goto_branch_array)) {
+ $gotos_array = array_unique(array_merge($gotos_array, $goto_branch_array));
+ unset($goto_branch_array);
+ }
+
+ // Reindex array
+ $gotos_array = array_values($gotos_array);
+
+ // Force exit if loop cannot be solved
+ // Postfix does not allow for alias loops, so this should never happen.
+ $loop_c++;
+ error_log("RCPT RESOVLER: http pipe: goto array count on loop #". $loop_c . " is " . count($gotos_array) . PHP_EOL);
+ }
+ }
+ catch (PDOException $e) {
+ error_log("RCPT RESOVLER: " . $e->getMessage() . PHP_EOL);
+ http_response_code(502);
+ exit;
+ }
+}
+
+foreach ($rcpt_final_mailboxes as $rcpt_final) {
+ error_log("QUARANTINE: quarantine pipe: processing quarantine message for rcpt " . $rcpt_final . PHP_EOL);
+ try {
+ $stmt = $pdo->prepare("INSERT INTO `quarantine` (`qid`, `subject`, `score`, `sender`, `rcpt`, `symbols`, `user`, `ip`, `msg`, `action`, `fuzzy_hashes`)
+ VALUES (:qid, :subject, :score, :sender, :rcpt, :symbols, :user, :ip, :msg, :action, :fuzzy_hashes)");
+ $stmt->execute(array(
+ ':qid' => $qid,
+ ':subject' => $subject,
+ ':score' => $score,
+ ':sender' => $sender,
+ ':rcpt' => $rcpt_final,
+ ':symbols' => $symbols,
+ ':user' => $user,
+ ':ip' => $ip,
+ ':msg' => $raw_data,
+ ':action' => $action,
+ ':fuzzy_hashes' => $fuzzy
+ ));
+ $stmt = $pdo->prepare('DELETE FROM `quarantine` WHERE `rcpt` = :rcpt AND `id` NOT IN (
+ SELECT `id`
+ FROM (
+ SELECT `id`
+ FROM `quarantine`
+ WHERE `rcpt` = :rcpt2
+ ORDER BY id DESC
+ LIMIT :retention_size
+ ) x
+ );');
+ $stmt->execute(array(
+ ':rcpt' => $rcpt_final,
+ ':rcpt2' => $rcpt_final,
+ ':retention_size' => $retention_size
+ ));
+ }
+ catch (PDOException $e) {
+ error_log("QUARANTINE: " . $e->getMessage() . PHP_EOL);
+ http_response_code(503);
+ exit;
+ }
+}
+
diff --git a/mailcow/src/mailcow-dockerized/data/conf/rspamd/meta_exporter/pipe_rl.php b/mailcow/src/mailcow-dockerized/data/conf/rspamd/meta_exporter/pipe_rl.php
new file mode 100644
index 0000000..5f7fd42
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/rspamd/meta_exporter/pipe_rl.php
@@ -0,0 +1,48 @@
+<?php
+// File size is limited by Nginx site to 10M
+// To speed things up, we do not include prerequisites
+header('Content-Type: text/plain');
+require_once "vars.inc.php";
+// Do not show errors, we log to using error_log
+ini_set('error_reporting', 0);
+// Init Redis
+$redis = new Redis();
+try {
+ if (!empty(getenv('REDIS_SLAVEOF_IP'))) {
+ $redis->connect(getenv('REDIS_SLAVEOF_IP'), getenv('REDIS_SLAVEOF_PORT'));
+ }
+ else {
+ $redis->connect('redis-mailcow', 6379);
+ }
+}
+catch (Exception $e) {
+ exit;
+}
+
+$raw_data_content = file_get_contents('php://input');
+$raw_data_decoded = json_decode($raw_data_content, true);
+
+$data['time'] = time();
+$data['rcpt'] = implode(', ', $raw_data_decoded['rcpt']);
+$data['from'] = $raw_data_decoded['from'];
+$data['user'] = $raw_data_decoded['user'];
+$symbol_rl_key = array_search('RATELIMITED', array_column($raw_data_decoded['symbols'], 'name'));
+$data['rl_info'] = implode($raw_data_decoded['symbols'][$symbol_rl_key]['options']);
+preg_match('/(.+)\((.+)\)/i', $data['rl_info'], $rl_matches);
+if (!empty($rl_matches[1]) && !empty($rl_matches[2])) {
+ $data['rl_name'] = $rl_matches[1];
+ $data['rl_hash'] = $rl_matches[2];
+}
+else {
+ $data['rl_name'] = 'err';
+ $data['rl_hash'] = 'err';
+}
+$data['qid'] = $raw_data_decoded['qid'];
+$data['ip'] = $raw_data_decoded['ip'];
+$data['message_id'] = $raw_data_decoded['message_id'];
+$data['header_subject'] = implode(' ', $raw_data_decoded['header_subject']);
+$data['header_from'] = implode(', ', $raw_data_decoded['header_from']);
+
+$redis->lpush('RL_LOG', json_encode($data));
+exit;
+
diff --git a/mailcow/src/mailcow-dockerized/data/conf/rspamd/meta_exporter/pushover.php b/mailcow/src/mailcow-dockerized/data/conf/rspamd/meta_exporter/pushover.php
new file mode 100644
index 0000000..a5e8334
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/rspamd/meta_exporter/pushover.php
@@ -0,0 +1,252 @@
+<?php
+// File size is limited by Nginx site to 10M
+// To speed things up, we do not include prerequisites
+header('Content-Type: text/plain');
+require_once "vars.inc.php";
+// Do not show errors, we log to using error_log
+ini_set('error_reporting', 0);
+// Init database
+//$dsn = $database_type . ':host=' . $database_host . ';dbname=' . $database_name;
+$dsn = $database_type . ":unix_socket=" . $database_sock . ";dbname=" . $database_name;
+$opt = [
+ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
+ PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
+ PDO::ATTR_EMULATE_PREPARES => false,
+];
+try {
+ $pdo = new PDO($dsn, $database_user, $database_pass, $opt);
+}
+catch (PDOException $e) {
+ error_log("NOTIFY: " . $e . PHP_EOL);
+ http_response_code(501);
+ exit;
+}
+// Init Redis
+$redis = new Redis();
+$redis->connect('redis-mailcow', 6379);
+
+// Functions
+function parse_email($email) {
+ if(!filter_var($email, FILTER_VALIDATE_EMAIL)) return false;
+ $a = strrpos($email, '@');
+ return array('local' => substr($email, 0, $a), 'domain' => substr(substr($email, $a), 1));
+}
+if (!function_exists('getallheaders')) {
+ function getallheaders() {
+ if (!is_array($_SERVER)) {
+ return array();
+ }
+ $headers = array();
+ foreach ($_SERVER as $name => $value) {
+ if (substr($name, 0, 5) == 'HTTP_') {
+ $headers[str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5)))))] = $value;
+ }
+ }
+ return $headers;
+ }
+}
+
+$headers = getallheaders();
+
+$qid = $headers['X-Rspamd-Qid'];
+$rcpts = $headers['X-Rspamd-Rcpt'];
+$sender = $headers['X-Rspamd-From'];
+$ip = $headers['X-Rspamd-Ip'];
+$subject = $headers['X-Rspamd-Subject'];
+$priority = 0;
+
+$symbols_array = json_decode($headers['X-Rspamd-Symbols'], true);
+if (is_array($symbols_array)) {
+ foreach ($symbols_array as $symbol) {
+ if ($symbol['name'] == 'HAS_X_PRIO_ONE') {
+ $priority = 1;
+ break;
+ }
+ }
+}
+
+$rcpt_final_mailboxes = array();
+
+// Loop through all rcpts
+foreach (json_decode($rcpts, true) as $rcpt) {
+ // Remove tag
+ $rcpt = preg_replace('/^(.*?)\+.*(@.*)$/', '$1$2', $rcpt);
+
+ // Break rcpt into local part and domain part
+ $parsed_rcpt = parse_email($rcpt);
+
+ // Skip if not a mailcow handled domain
+ try {
+ if (!$redis->hGet('DOMAIN_MAP', $parsed_rcpt['domain'])) {
+ continue;
+ }
+ }
+ catch (RedisException $e) {
+ error_log("NOTIFY: " . $e . PHP_EOL);
+ http_response_code(504);
+ exit;
+ }
+
+ // Always assume rcpt is not a final mailbox but an alias for a mailbox or further aliases
+ //
+ // rcpt
+ // |
+ // mailbox <-- goto ---> alias1, alias2, mailbox2
+ // | |
+ // mailbox3 |
+ // |
+ // alias3 ---> mailbox4
+ //
+ try {
+ $stmt = $pdo->prepare("SELECT `goto` FROM `alias` WHERE `address` = :rcpt AND `active` = '1'");
+ $stmt->execute(array(
+ ':rcpt' => $rcpt
+ ));
+ $gotos = $stmt->fetch(PDO::FETCH_ASSOC)['goto'];
+ if (empty($gotos)) {
+ $stmt = $pdo->prepare("SELECT `goto` FROM `alias` WHERE `address` = :rcpt AND `active` = '1'");
+ $stmt->execute(array(
+ ':rcpt' => '@' . $parsed_rcpt['domain']
+ ));
+ $gotos = $stmt->fetch(PDO::FETCH_ASSOC)['goto'];
+ }
+ if (empty($gotos)) {
+ $stmt = $pdo->prepare("SELECT `target_domain` FROM `alias_domain` WHERE `alias_domain` = :rcpt AND `active` = '1'");
+ $stmt->execute(array(':rcpt' => $parsed_rcpt['domain']));
+ $goto_branch = $stmt->fetch(PDO::FETCH_ASSOC)['target_domain'];
+ if ($goto_branch) {
+ $gotos = $parsed_rcpt['local'] . '@' . $goto_branch;
+ }
+ }
+ $gotos_array = explode(',', $gotos);
+
+ $loop_c = 0;
+
+ while (count($gotos_array) != 0 && $loop_c <= 20) {
+
+ // Loop through all found gotos
+ foreach ($gotos_array as $index => &$goto) {
+ error_log("RCPT RESOVLER: http pipe: query " . $goto . " as username from mailbox" . PHP_EOL);
+ $stmt = $pdo->prepare("SELECT `username` FROM `mailbox` WHERE `username` = :goto AND (`active`= '1' OR `active`= '2');");
+ $stmt->execute(array(':goto' => $goto));
+ $username = $stmt->fetch(PDO::FETCH_ASSOC)['username'];
+ if (!empty($username)) {
+ error_log("RCPT RESOVLER: http pipe: mailbox found: " . $username . PHP_EOL);
+ // Current goto is a mailbox, save to rcpt_final_mailboxes if not a duplicate
+ if (!in_array($username, $rcpt_final_mailboxes)) {
+ $rcpt_final_mailboxes[] = $username;
+ }
+ }
+ else {
+ $parsed_goto = parse_email($goto);
+ if (!$redis->hGet('DOMAIN_MAP', $parsed_goto['domain'])) {
+ error_log("RCPT RESOVLER:" . $goto . " is not a mailcow handled mailbox or alias address" . PHP_EOL);
+ }
+ else {
+ $stmt = $pdo->prepare("SELECT `goto` FROM `alias` WHERE `address` = :goto AND `active` = '1'");
+ $stmt->execute(array(':goto' => $goto));
+ $goto_branch = $stmt->fetch(PDO::FETCH_ASSOC)['goto'];
+ if ($goto_branch) {
+ error_log("RCPT RESOVLER: http pipe: goto address " . $goto . " is an alias branch for " . $goto_branch . PHP_EOL);
+ $goto_branch_array = explode(',', $goto_branch);
+ } else {
+ $stmt = $pdo->prepare("SELECT `target_domain` FROM `alias_domain` WHERE `alias_domain` = :domain AND `active` AND '1'");
+ $stmt->execute(array(':domain' => $parsed_goto['domain']));
+ $goto_branch = $stmt->fetch(PDO::FETCH_ASSOC)['target_domain'];
+ if ($goto_branch) {
+ error_log("RCPT RESOVLER: http pipe: goto domain " . $parsed_goto['domain'] . " is a domain alias branch for " . $goto_branch . PHP_EOL);
+ $goto_branch_array = array($parsed_goto['local'] . '@' . $goto_branch);
+ }
+ }
+ }
+ }
+ // goto item was processed, unset
+ unset($gotos_array[$index]);
+ }
+
+ // Merge goto branch array derived from previous loop (if any), filter duplicates and unset goto branch array
+ if (!empty($goto_branch_array)) {
+ $gotos_array = array_unique(array_merge($gotos_array, $goto_branch_array));
+ unset($goto_branch_array);
+ }
+
+ // Reindex array
+ $gotos_array = array_values($gotos_array);
+
+ // Force exit if loop cannot be solved
+ // Postfix does not allow for alias loops, so this should never happen.
+ $loop_c++;
+ error_log("RCPT RESOVLER: http pipe: goto array count on loop #". $loop_c . " is " . count($gotos_array) . PHP_EOL);
+ }
+ }
+ catch (PDOException $e) {
+ error_log("RCPT RESOVLER: " . $e->getMessage() . PHP_EOL);
+ http_response_code(502);
+ exit;
+ }
+}
+
+
+foreach ($rcpt_final_mailboxes as $rcpt_final) {
+ error_log("NOTIFY: pushover pipe: processing pushover message for rcpt " . $rcpt_final . PHP_EOL);
+ $stmt = $pdo->prepare("SELECT * FROM `pushover`
+ WHERE `username` = :username AND `active` = '1'");
+ $stmt->execute(array(
+ ':username' => $rcpt_final
+ ));
+ $api_data = $stmt->fetch(PDO::FETCH_ASSOC);
+ if (isset($api_data['key']) && isset($api_data['token'])) {
+ $title = (!empty($api_data['title'])) ? $api_data['title'] : 'Mail';
+ $text = (!empty($api_data['text'])) ? $api_data['text'] : 'You\'ve got mail 📧';
+ $attributes = json_decode($api_data['attributes'], true);
+ $senders = explode(',', $api_data['senders']);
+ $senders = array_filter($senders);
+ $senders_regex = $api_data['senders_regex'];
+ $sender_validated = false;
+ if (empty($senders) && empty($senders_regex)) {
+ $sender_validated = true;
+ }
+ else {
+ if (!empty($senders)) {
+ if (in_array($sender, $senders)) {
+ $sender_validated = true;
+ }
+ }
+ if (!empty($senders_regex) && $sender_validated !== true) {
+ if (preg_match($senders_regex, $sender)) {
+ $sender_validated = true;
+ }
+ }
+ }
+ if ($sender_validated === false) {
+ error_log("NOTIFY: pushover pipe: skipping unwanted sender " . $sender);
+ continue;
+ }
+ if ($attributes['only_x_prio'] == "1" && $priority == 0) {
+ error_log("NOTIFY: pushover pipe: mail has no X-Priority: 1 header, skipping");
+ continue;
+ }
+ $post_fields = array(
+ "token" => $api_data['token'],
+ "user" => $api_data['key'],
+ "title" => sprintf("%s", str_replace(array('{SUBJECT}', '{SENDER}'), array($subject, $sender), $title)),
+ "priority" => $priority,
+ "message" => sprintf("%s", str_replace(array('{SUBJECT}', '{SENDER}'), array($subject, $sender), $text))
+ );
+ if ($attributes['evaluate_x_prio'] == "1" && $priority == 1) {
+ $post_fields['expire'] = 600;
+ $post_fields['retry'] = 120;
+ $post_fields['priority'] = 2;
+ }
+ curl_setopt_array($ch = curl_init(), array(
+ CURLOPT_URL => "https://api.pushover.net/1/messages.json",
+ CURLOPT_POSTFIELDS => $post_fields,
+ CURLOPT_SAFE_UPLOAD => true,
+ CURLOPT_RETURNTRANSFER => true,
+ ));
+ $result = curl_exec($ch);
+ $httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
+ curl_close($ch);
+ error_log("NOTIFY: result: " . $httpcode . PHP_EOL);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/conf/rspamd/meta_exporter/vars.inc.php b/mailcow/src/mailcow-dockerized/data/conf/rspamd/meta_exporter/vars.inc.php
new file mode 100644
index 0000000..79566b0
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/rspamd/meta_exporter/vars.inc.php
@@ -0,0 +1,6 @@
+<?php
+require_once('../../../web/inc/vars.inc.php');
+if (file_exists('../../../web/inc/vars.local.inc.php')) {
+ include_once('../../../web/inc/vars.local.inc.php');
+}
+?>
diff --git a/mailcow/src/mailcow-dockerized/data/conf/rspamd/override.d/logging.inc b/mailcow/src/mailcow-dockerized/data/conf/rspamd/override.d/logging.inc
new file mode 100644
index 0000000..64d4064
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/rspamd/override.d/logging.inc
@@ -0,0 +1,5 @@
+level = "silent";
+type = "console";
+systemd = false;
+.include "$CONFDIR/logging.inc"
+.include(try=true; priority=20) "$CONFDIR/override.d/logging.custom.inc"
diff --git a/mailcow/src/mailcow-dockerized/data/conf/rspamd/override.d/ratelimit.conf b/mailcow/src/mailcow-dockerized/data/conf/rspamd/override.d/ratelimit.conf
new file mode 100644
index 0000000..aec1c78
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/rspamd/override.d/ratelimit.conf
@@ -0,0 +1,12 @@
+rates {
+ # Format: "1 / 1h" or "20 / 1m" etc. - global ratelimits are disabled by default
+ to = "100 / 1s";
+ to_ip = "100 / 1s";
+ to_ip_from = "100 / 1s";
+ bounce_to = "100 / 1h";
+ bounce_to_ip = "7 / 1m";
+}
+whitelisted_rcpts = "postmaster,mailer-daemon";
+max_rcpt = 25;
+custom_keywords = "/etc/rspamd/lua/ratelimit.lua";
+info_symbol = "RATELIMITED";
diff --git a/mailcow/src/mailcow-dockerized/data/conf/rspamd/override.d/worker-controller.inc b/mailcow/src/mailcow-dockerized/data/conf/rspamd/override.d/worker-controller.inc
new file mode 100644
index 0000000..8c929b1
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/rspamd/override.d/worker-controller.inc
@@ -0,0 +1,7 @@
+bind_socket = "*:11334";
+count = 1;
+secure_ip = "127.0.0.1";
+secure_ip = "::1";
+bind_socket = "/var/lib/rspamd/rspamd.sock mode=0666 owner=nobody";
+.include(try=true; priority=10) "$CONFDIR/override.d/worker-controller-password.inc"
+.include(try=true; priority=30) "$CONFDIR/override.d/worker-controller.custom.inc"
diff --git a/mailcow/src/mailcow-dockerized/data/conf/rspamd/override.d/worker-fuzzy.inc b/mailcow/src/mailcow-dockerized/data/conf/rspamd/override.d/worker-fuzzy.inc
new file mode 100644
index 0000000..291e615
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/rspamd/override.d/worker-fuzzy.inc
@@ -0,0 +1,12 @@
+# Socket to listen on (UDP and TCP from rspamd 1.3)
+bind_socket = "*:11445";
+allow_update = ["127.0.0.1", "::1"];
+# Number of processes to serve this storage (useful for read scaling)
+count = 1;
+# Backend ("sqlite" or "redis" - default "sqlite")
+backend = "redis";
+# Hashes storage time (3 months)
+expire = 90d;
+# Synchronize updates to the storage each minute
+sync = 1min;
+
diff --git a/mailcow/src/mailcow-dockerized/data/conf/rspamd/override.d/worker-normal.inc b/mailcow/src/mailcow-dockerized/data/conf/rspamd/override.d/worker-normal.inc
new file mode 100644
index 0000000..c0f1fb1
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/rspamd/override.d/worker-normal.inc
@@ -0,0 +1,4 @@
+bind_socket = "*:11333";
+task_timeout = 12s;
+count = 1;
+.include(try=true; priority=30) "$CONFDIR/override.d/worker-normal.custom.inc"
diff --git a/mailcow/src/mailcow-dockerized/data/conf/rspamd/override.d/worker-proxy.inc b/mailcow/src/mailcow-dockerized/data/conf/rspamd/override.d/worker-proxy.inc
new file mode 100644
index 0000000..9eb4775
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/rspamd/override.d/worker-proxy.inc
@@ -0,0 +1,9 @@
+bind_socket = "rspamd:9900";
+milter = true;
+upstream "local" {
+ name = "localhost";
+ default = true;
+ hosts = "rspamd:11333"
+}
+reject_message = "This message does not meet our delivery requirements";
+.include(try=true; priority=30) "$CONFDIR/override.d/worker-proxy.custom.inc"
diff --git a/mailcow/src/mailcow-dockerized/data/conf/rspamd/plugins.d/README.md b/mailcow/src/mailcow-dockerized/data/conf/rspamd/plugins.d/README.md
new file mode 100644
index 0000000..1516cf2
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/rspamd/plugins.d/README.md
@@ -0,0 +1 @@
+This is where you should copy any rspamd custom module
diff --git a/mailcow/src/mailcow-dockerized/data/conf/rspamd/rspamd.conf.local b/mailcow/src/mailcow-dockerized/data/conf/rspamd/rspamd.conf.local
new file mode 100644
index 0000000..9f2f8f1
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/rspamd/rspamd.conf.local
@@ -0,0 +1 @@
+# rspamd.conf.local
diff --git a/mailcow/src/mailcow-dockerized/data/conf/rspamd/rspamd.conf.override b/mailcow/src/mailcow-dockerized/data/conf/rspamd/rspamd.conf.override
new file mode 100644
index 0000000..d033e8e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/rspamd/rspamd.conf.override
@@ -0,0 +1,2 @@
+# rspamd.conf.override
+
diff --git a/mailcow/src/mailcow-dockerized/data/conf/sogo/custom-sogo.js b/mailcow/src/mailcow-dockerized/data/conf/sogo/custom-sogo.js
new file mode 100644
index 0000000..9ee6dab
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/sogo/custom-sogo.js
@@ -0,0 +1,7 @@
+// Custom SOGo JS
+
+// Change the visible font-size in the editor, this does not change the font of a html message by default
+CKEDITOR.addCss("body {font-size: 16px !important}");
+
+// Enable scayt by default
+//CKEDITOR.config.scayt_autoStartup = true;
diff --git a/mailcow/src/mailcow-dockerized/data/conf/sogo/plist_ldap b/mailcow/src/mailcow-dockerized/data/conf/sogo/plist_ldap
new file mode 100644
index 0000000..d585a49
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/sogo/plist_ldap
@@ -0,0 +1,28 @@
+ <!--
+ <example>
+ <key>canAuthenticate</key>
+ <string>YES</string>
+ <key>id</key>
+ <string>${line}_ldap</string>
+ <key>isAddressBook</key>
+ <string>NO</string>
+ <key>IDFieldName</key>
+ <string>mail</string>
+ <key>UIDFieldName</key>
+ <string>uid</string>
+ <key>bindFields</key>
+ <array>
+ <string>mail</string>
+ </array>
+ <key>type</key>
+ <string>ldap</string>
+ <key>bindDN</key>
+ <string>cn=admin,dc=example,dc=local</string>
+ <key>bindPassword</key>
+ <string>password</string>
+ <key>baseDN</key>
+ <string>ou=People,dc=example,dc=local</string>
+ <key>hostname</key>
+ <string>ldap://1.2.3.4:389</string>
+ </example>
+ -->
diff --git a/mailcow/src/mailcow-dockerized/data/conf/sogo/sogo-full.svg b/mailcow/src/mailcow-dockerized/data/conf/sogo/sogo-full.svg
new file mode 100644
index 0000000..98ff2fc
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/sogo/sogo-full.svg
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
+ <!ENTITY st0 "fill:#50BD37;">
+]>
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="640px" height="350px" viewBox="78.712 58.488 640 350" style="enable-background:new 78.712 58.488 640 350;"
+ xml:space="preserve">
+<path style="&st0;" d="M648.541,145.679c-9.947,0-17.009-7.278-17.009-17.048c0-9.777,7.062-17.057,17.009-17.057
+ c10.024,0,17.086,7.279,17.086,17.057C665.627,138.401,658.565,145.679,648.541,145.679z M648.511,94.893
+ c-19.693,0-33.679,14.4-33.679,33.738c0,19.33,13.985,33.729,33.679,33.729c19.822,0,33.808-14.4,33.808-33.729
+ C682.318,109.293,668.333,94.893,648.511,94.893z M648.482,179.843c-29.889,0-51.123-21.868-51.123-51.212
+ c0-29.353,21.234-51.209,51.123-51.209c30.082,0,51.307,21.856,51.307,51.209C699.789,157.975,678.564,179.843,648.482,179.843z
+ M648.442,58.488c-40.929,0-69.995,29.946-69.995,70.143c0,40.189,29.066,70.125,69.995,70.125c41.194,0,70.27-29.937,70.27-70.125
+ C718.712,88.434,689.637,58.488,648.442,58.488z M158.166,183.902l-21.018-5.008c-19.131-4.396-28.849-9.413-28.849-23.21
+ c0-15.684,15.99-21.965,30.419-21.965c14.667,0,25.382,7.329,31.693,18.737c0.02,0.048,0.051,0.097,0.09,0.157
+ c0.127,0.247,0.276,0.484,0.403,0.731l0.03-0.02c1.985,3.002,5.323,5.008,8.919,5.008c6.122,0,10.558-4.425,10.558-10.547
+ c0-2.341-0.504-4.82-1.601-6.688c-10.764-18.302-28.513-26.192-48.838-26.192c-27.594,0-54.262,13.797-54.262,44.218
+ c0,27.921,27.605,36.079,37.64,38.578l20.069,4.71c15.368,3.763,27.912,8.791,27.912,23.517c0,16.938-17.561,23.943-34.499,23.943
+ c-17.245,0-30.015-9.37-38.814-22.37h-0.01c-1.956-3-4.988-4.328-8.702-4.328c-5.984,0-10.805,5.185-10.587,11.162
+ c0.098,2.438,0.909,4.637,2.153,6.405c13.787,20.633,33.728,28.41,55.96,28.41c28.543,0,57.085-13.143,57.085-45.132
+ C193.918,203.325,178.551,188.613,158.166,183.902z M298.479,250.312c-33.866,0-55.199-25.403-55.199-58.331
+ c0-32.939,21.333-58.343,55.199-58.343c34.192,0,55.516,25.403,55.516,58.343C353.996,224.91,332.672,250.312,298.479,250.312z
+ M298.479,114.823c-45.471,0-77.777,32.93-77.777,77.158c0,44.217,32.306,77.146,77.777,77.146
+ c45.786,0,78.093-32.929,78.093-77.146C376.572,147.753,344.266,114.823,298.479,114.823z M518.715,234.312
+ c-0.771,0.74-1.549,1.472-2.399,2.175c-1.106,1.014-2.391,2.112-3.854,3.208c-8.829,6.391-19.979,10.094-33.017,10.094
+ c-33.876,0-55.198-25.402-55.198-58.332c0-32.939,21.322-58.342,55.198-58.342c34.183,0,55.506,25.403,55.506,58.342
+ C534.951,208.653,529.135,223.774,518.715,234.312z M468.097,317.938c2.528,0,5.146-0.168,7.863-0.504
+ c5.018-0.631,9.588-0.909,13.729-0.909c19.24,0.109,29.036,5.7,34.943,12.158c5.895,6.499,8.168,15.311,8.158,22.796
+ c0.01,3.586-0.555,6.795-1.177,8.721c-2.944,8.93-8.888,15.002-17.996,19.576c-9.035,4.484-21.095,6.777-33.707,6.757
+ c-4.514,0-9.105-0.288-13.639-0.831c-8.573-0.987-19.911-4.671-28.13-11.093c-4.138-3.199-6.458-6.991-8.858-11.485
+ c-2.379-4.514-2.783-9.748-2.783-16.442v-0.742c0-12.346,4.84-20.544,11.051-26.5c3.07-2.904,5.69-5.064,7.99-6.438
+ c0.366-0.218,0.438-0.416,0.755-0.593C452.39,316.014,459.684,317.968,468.097,317.938z M479.445,114.301
+ c-45.471,0-77.786,32.929-77.786,77.157c0,29.887,14.765,54.598,38.378,67.489c-0.314,0.314-0.621,0.641-0.916,0.966
+ c-6.104,6.687-9.226,15.25-9.236,23.913c-0.008,3.821,0.624,7.741,1.977,11.494c-3.062,1.956-6.717,4.634-10.46,8.147
+ c-9.026,8.408-18.734,22.541-19.021,42.097c-0.01,0.454-0.01,0.829-0.01,1.118c-0.01,10.071,2.379,19.157,6.459,26.774
+ c6.133,11.466,15.683,19.445,25.539,24.77c9.917,5.334,20.257,8.166,29.273,9.274c5.373,0.643,10.826,0.988,16.268,0.988
+ c15.151-0.02,30.261-2.578,43.409-9.019c13.085-6.34,24.333-17.253,29.192-32.562c1.443-4.553,2.212-9.719,2.231-15.428
+ c-0.02-11.595-3.349-25.759-13.767-37.452c-10.421-11.734-27.654-19.566-51.288-19.459c-5.138,0-10.606,0.356-16.426,1.078
+ c-1.877,0.227-3.596,0.334-5.166,0.334c-7.239-0.048-10.872-2.053-13.036-4.098c-2.133-2.084-3.2-4.839-3.229-8.058
+ c-0.01-3.28,1.284-6.727,3.467-9.078c2.231-2.332,5.008-3.91,9.846-3.97c0.436,0,0.9,0.01,1.374,0.05
+ c3.101,0.216,6.112,0.325,9.037,0.325c24.188,0.047,42.38-7.448,54.756-17.759c12.415-10.312,18.971-22.854,22.071-32.76l-0.04-0.01
+ c3.37-8.899,5.197-18.715,5.197-29.166C557.539,147.229,525.234,114.301,479.445,114.301z"/>
+</svg>
diff --git a/mailcow/src/mailcow-dockerized/data/conf/sogo/sogo.conf b/mailcow/src/mailcow-dockerized/data/conf/sogo/sogo.conf
new file mode 100644
index 0000000..78791d5
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/sogo/sogo.conf
@@ -0,0 +1,86 @@
+{
+ SOGoCalendarDefaultRoles = (
+ PublicViewer,
+ ConfidentialDAndTViewer,
+ PrivateDAndTViewer
+ );
+
+ WOWorkersCount = "20";
+ SOGoACLsSendEMailNotifications = YES;
+ SOGoAppointmentSendEMailNotifications = YES;
+ SOGoDraftsFolderName = "Drafts";
+ SOGoJunkFolderName= "Junk";
+ SOGoMailDomain = "sogo.local";
+ SOGoEnableEMailAlarms = YES;
+ SOGoFoldersSendEMailNotifications = YES;
+ SOGoForwardEnabled = YES;
+ SOGoUIAdditionalJSFiles = (js/custom-sogo.js);
+ SOGoEnablePublicAccess = YES;
+
+ // Multi-domain setup
+ // Domains are isolated, you can define visibility options here.
+ // Example:
+
+ // SOGoDomainsVisibility = (
+ // (domain1.tld, domain5.tld),
+ // (domain3.tld, domain2.tld)
+ // );
+
+ // self-signed is not trusted anymore
+ SOGoSieveServer = "sieve://dovecot:4190/?TLS=YES&tlsVerifyMode=none";
+ SOGoSMTPServer = "smtp://postfix:588/?TLS=YES&tlsVerifyMode=none";
+ WOPort = "0.0.0.0:20000";
+ SOGoMemcachedHost = "memcached";
+
+ SOGoLanguage = English;
+ SOGoMailAuxiliaryUserAccountsEnabled = YES;
+ SOGoMailCustomFromEnabled = YES;
+ SOGoMailingMechanism = smtp;
+ SOGoSMTPAuthenticationType = plain;
+
+ SxVMemLimit = 384;
+
+ SOGoMaximumPingInterval = 3540;
+
+ SOGoInternalSyncInterval = 45;
+ SOGoMaximumSyncInterval = 3540;
+
+ // 100 seems to break some Android clients
+ //SOGoMaximumSyncWindowSize = 99;
+ // This should do the trick for Outlook 2016
+ SOGoMaximumSyncResponseSize = 512;
+
+ WOWatchDogRequestTimeout = 30;
+ WOListenQueueSize = 16;
+ WONoDetach = YES;
+
+ SOGoIMAPAclConformsToIMAPExt = Yes;
+ SOGoPageTitle = "SOGo Groupware";
+ SOGoFirstDayOfWeek = "1";
+
+ SOGoSieveFolderEncoding = "UTF-8";
+ SOGoPasswordChangeEnabled = YES;
+ SOGoSentFolderName = "Sent";
+ SOGoMailShowSubscribedFoldersOnly = NO;
+ NGImap4ConnectionStringSeparator = "/";
+ SOGoSieveScriptsEnabled = YES;
+ SOGoTrashFolderName = "Trash";
+ SOGoVacationEnabled = YES;
+
+ SOGoCacheCleanupInterval = 900;
+ SOGoMaximumFailedLoginCount = 10;
+ SOGoMaximumFailedLoginInterval = 900;
+ SOGoFailedLoginBlockInterval = 900;
+
+ MySQL4Encoding = "utf8mb4";
+ //SOGoDebugRequests = YES;
+ //SoDebugBaseURL = YES;
+ //ImapDebugEnabled = YES;
+ //SOGoEASDebugEnabled = YES;
+ //LDAPDebugEnabled = YES;
+ //PGDebugEnabled = YES;
+ //MySQL4DebugEnabled = YES;
+ //SOGoUIxDebugEnabled = YES;
+ //WODontZipResponse = YES;
+ WOLogFile = "/dev/sogo_log";
+}
diff --git a/mailcow/src/mailcow-dockerized/data/conf/unbound/unbound.conf b/mailcow/src/mailcow-dockerized/data/conf/unbound/unbound.conf
new file mode 100644
index 0000000..27110c0
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/conf/unbound/unbound.conf
@@ -0,0 +1,45 @@
+server:
+ verbosity: 1
+ interface: 0.0.0.0
+ interface: ::0
+ logfile: /dev/console
+ do-ip4: yes
+ do-ip6: yes
+ do-udp: yes
+ do-tcp: yes
+ do-daemonize: no
+ #access-control: 0.0.0.0/0 allow
+ access-control: 10.0.0.0/8 allow
+ access-control: 172.16.0.0/12 allow
+ access-control: 192.168.0.0/16 allow
+ access-control: fc00::/7 allow
+ access-control: fe80::/10 allow
+ #access-control: ::0/0 allow
+ directory: "/etc/unbound"
+ username: unbound
+ auto-trust-anchor-file: trusted-key.key
+ #private-address: 10.0.0.0/8
+ #private-address: 172.16.0.0/12
+ #private-address: 192.168.0.0/16
+ #private-address: 169.254.0.0/16
+ #private-address: fc00::/7
+ #private-address: fe80::/10
+ # cache-min-ttl needs to be less or equal to cache-max-negative-ttl
+ cache-min-ttl: 5
+ cache-max-negative-ttl: 60
+ root-hints: "/etc/unbound/root.hints"
+ hide-identity: yes
+ hide-version: yes
+ max-udp-size: 4096
+ msg-buffer-size: 65552
+ unwanted-reply-threshold: 10000
+ ipsecmod-enabled: no
+
+remote-control:
+ control-enable: yes
+ control-interface: 127.0.0.1
+ control-port: 8953
+ server-key-file: "/etc/unbound/unbound_server.key"
+ server-cert-file: "/etc/unbound/unbound_server.pem"
+ control-key-file: "/etc/unbound/unbound_control.key"
+ control-cert-file: "/etc/unbound/unbound_control.pem"